@carto/ps-react-ui 4.5.1 → 4.6.1
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/{download-config-DemuQ3Jm.js → download-config-C3I0jWIL.js} +2 -2
- package/dist/{download-config-DemuQ3Jm.js.map → download-config-C3I0jWIL.js.map} +1 -1
- package/dist/{row-D4VOhcNI.js → row-DZSP99LW.js} +2 -2
- package/dist/{row-D4VOhcNI.js.map → row-DZSP99LW.js.map} +1 -1
- package/dist/{series-Bola3CmD.js → series-DLNHDWs0.js} +3 -3
- package/dist/{series-Bola3CmD.js.map → series-DLNHDWs0.js.map} +1 -1
- package/dist/types/hooks/index.d.ts +0 -1
- package/dist/types/widgets/actions/brush-toggle/brush-toggle.d.ts +3 -0
- package/dist/types/widgets/actions/index.d.ts +4 -4
- package/dist/types/widgets/actions/lock-selection/types.d.ts +2 -0
- package/dist/types/widgets/actions/relative-data/relative-data.d.ts +7 -2
- package/dist/types/widgets/actions/relative-data/types.d.ts +2 -0
- package/dist/types/widgets/actions/zoom-toggle/zoom-toggle.d.ts +4 -0
- package/dist/types/widgets/category/index.d.ts +10 -2
- package/dist/types/widgets/no-data/no-data.d.ts +3 -2
- package/dist/types/widgets/no-data/types.d.ts +5 -1
- package/dist/types/widgets/stores/index.d.ts +1 -1
- package/dist/types/widgets/stores/types.d.ts +10 -10
- package/dist/types/widgets/stores/widget-store.d.ts +2 -3
- package/dist/types/widgets/table/index.d.ts +6 -2
- package/dist/{use-widget-ref-BFazQvJK.js → use-widget-ref-Ddr_SlJJ.js} +2 -2
- package/dist/{use-widget-ref-BFazQvJK.js.map → use-widget-ref-Ddr_SlJJ.js.map} +1 -1
- package/dist/{use-widget-selector-DqRmWQ1K.js → use-widget-selector-DFl2hW0R.js} +2 -2
- package/dist/{use-widget-selector-DqRmWQ1K.js.map → use-widget-selector-DFl2hW0R.js.map} +1 -1
- package/dist/{widget-store-CIrb9RKP.js → widget-store-Bw5zRUGg.js} +93 -95
- package/dist/widget-store-Bw5zRUGg.js.map +1 -0
- package/dist/widgets/actions.js +770 -755
- package/dist/widgets/actions.js.map +1 -1
- package/dist/widgets/bar.js +2 -2
- package/dist/widgets/category.js +3 -3
- package/dist/widgets/category.js.map +1 -1
- package/dist/widgets/echart.js +2 -2
- package/dist/widgets/error.js +37 -2
- package/dist/widgets/error.js.map +1 -1
- package/dist/widgets/formula.js +5 -5
- package/dist/widgets/histogram.js +1 -1
- package/dist/widgets/loader.js +1 -1
- package/dist/widgets/markdown.js +2 -2
- package/dist/widgets/no-data.js +58 -2
- package/dist/widgets/no-data.js.map +1 -1
- package/dist/widgets/note.js +121 -2
- package/dist/widgets/note.js.map +1 -1
- package/dist/widgets/pie.js +2 -2
- package/dist/widgets/range.js +3 -3
- package/dist/widgets/scatterplot.js +2 -2
- package/dist/widgets/skeleton-loader.js +1 -1
- package/dist/widgets/spread.js +5 -5
- package/dist/widgets/stores.js +2 -2
- package/dist/widgets/table.js +3 -3
- package/dist/widgets/timeseries.js +2 -2
- package/dist/widgets/utils.js +1 -1
- package/dist/widgets/wrapper.js +2 -2
- package/package.json +2 -6
- package/src/hooks/index.ts +0 -1
- package/src/widgets/actions/brush-toggle/brush-toggle.tsx +18 -22
- package/src/widgets/actions/change-column/change-column.test.tsx +1 -1
- package/src/widgets/actions/download/download.test.tsx +1 -1
- package/src/widgets/actions/index.ts +11 -2
- package/src/widgets/actions/lock-selection/lock-selection.test.tsx +14 -0
- package/src/widgets/actions/lock-selection/lock-selection.tsx +18 -11
- package/src/widgets/actions/lock-selection/types.ts +2 -0
- package/src/widgets/actions/relative-data/relative-data.test.tsx +211 -20
- package/src/widgets/actions/relative-data/relative-data.tsx +65 -34
- package/src/widgets/actions/relative-data/types.ts +2 -0
- package/src/widgets/actions/searcher/searcher.tsx +28 -30
- package/src/widgets/actions/stack-toggle/stack-toggle.tsx +11 -2
- package/src/widgets/actions/zoom-toggle/zoom-toggle.tsx +53 -45
- package/src/widgets/category/category-ui.tsx +4 -6
- package/src/widgets/category/index.ts +13 -14
- package/src/widgets/no-data/no-data.test.tsx +90 -40
- package/src/widgets/no-data/no-data.tsx +7 -5
- package/src/widgets/no-data/types.ts +5 -1
- package/src/widgets/stores/index.ts +2 -0
- package/src/widgets/stores/types.ts +10 -18
- package/src/widgets/stores/widget-store.test.ts +132 -13
- package/src/widgets/stores/widget-store.ts +29 -35
- package/src/widgets/table/index.ts +6 -4
- package/dist/error-Cj8eUMrl.js +0 -40
- package/dist/error-Cj8eUMrl.js.map +0 -1
- package/dist/no-data-DkIt7Qt1.js +0 -61
- package/dist/no-data-DkIt7Qt1.js.map +0 -1
- package/dist/note-t51drNe0.js +0 -124
- package/dist/note-t51drNe0.js.map +0 -1
- package/dist/types/hooks/use-debounce.d.ts +0 -19
- package/dist/types/widgets/category/components/index.d.ts +0 -10
- package/dist/types/widgets/index.d.ts +0 -9
- package/dist/types/widgets/table/hooks/index.d.ts +0 -6
- package/dist/widget-store-CIrb9RKP.js.map +0 -1
- package/dist/widgets.js +0 -13
- package/dist/widgets.js.map +0 -1
- package/src/hooks/use-debounce.ts +0 -55
- package/src/widgets/category/components/index.ts +0 -14
- package/src/widgets/index.ts +0 -25
- package/src/widgets/table/hooks/index.ts +0 -7
|
@@ -10,12 +10,12 @@ describe('WidgetNoData', () => {
|
|
|
10
10
|
useWidgetStore.getState().clearWidgets()
|
|
11
11
|
})
|
|
12
12
|
|
|
13
|
-
describe('when
|
|
13
|
+
describe('when sourceData is empty', () => {
|
|
14
14
|
test('renders NoData UI with empty array', () => {
|
|
15
15
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
16
16
|
isLoading: false,
|
|
17
17
|
isFetching: false,
|
|
18
|
-
|
|
18
|
+
sourceData: [],
|
|
19
19
|
})
|
|
20
20
|
|
|
21
21
|
render(
|
|
@@ -31,11 +31,11 @@ describe('WidgetNoData', () => {
|
|
|
31
31
|
expect(screen.queryByText('Widget Content')).toBeNull()
|
|
32
32
|
})
|
|
33
33
|
|
|
34
|
-
test('renders NoData UI with null
|
|
34
|
+
test('renders NoData UI with null sourceData', () => {
|
|
35
35
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
36
36
|
isLoading: false,
|
|
37
37
|
isFetching: false,
|
|
38
|
-
|
|
38
|
+
sourceData: null,
|
|
39
39
|
})
|
|
40
40
|
|
|
41
41
|
render(
|
|
@@ -48,11 +48,11 @@ describe('WidgetNoData', () => {
|
|
|
48
48
|
expect(screen.queryByText('Widget Content')).toBeNull()
|
|
49
49
|
})
|
|
50
50
|
|
|
51
|
-
test('renders NoData UI with undefined
|
|
51
|
+
test('renders NoData UI with undefined sourceData', () => {
|
|
52
52
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
53
53
|
isLoading: false,
|
|
54
54
|
isFetching: false,
|
|
55
|
-
|
|
55
|
+
sourceData: undefined,
|
|
56
56
|
})
|
|
57
57
|
|
|
58
58
|
render(
|
|
@@ -69,7 +69,7 @@ describe('WidgetNoData', () => {
|
|
|
69
69
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
70
70
|
isLoading: false,
|
|
71
71
|
isFetching: false,
|
|
72
|
-
|
|
72
|
+
sourceData: [[], []],
|
|
73
73
|
})
|
|
74
74
|
|
|
75
75
|
render(
|
|
@@ -86,7 +86,7 @@ describe('WidgetNoData', () => {
|
|
|
86
86
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
87
87
|
isLoading: false,
|
|
88
88
|
isFetching: false,
|
|
89
|
-
|
|
89
|
+
sourceData: {},
|
|
90
90
|
})
|
|
91
91
|
|
|
92
92
|
render(
|
|
@@ -100,12 +100,12 @@ describe('WidgetNoData', () => {
|
|
|
100
100
|
})
|
|
101
101
|
})
|
|
102
102
|
|
|
103
|
-
describe('when
|
|
104
|
-
test('renders children with array
|
|
103
|
+
describe('when sourceData exists', () => {
|
|
104
|
+
test('renders children with array sourceData', () => {
|
|
105
105
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
106
106
|
isLoading: false,
|
|
107
107
|
isFetching: false,
|
|
108
|
-
|
|
108
|
+
sourceData: [{ value: 1 }],
|
|
109
109
|
})
|
|
110
110
|
|
|
111
111
|
render(
|
|
@@ -118,11 +118,11 @@ describe('WidgetNoData', () => {
|
|
|
118
118
|
expect(screen.queryByText('No data available')).toBeNull()
|
|
119
119
|
})
|
|
120
120
|
|
|
121
|
-
test('renders children with object
|
|
121
|
+
test('renders children with object sourceData', () => {
|
|
122
122
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
123
123
|
isLoading: false,
|
|
124
124
|
isFetching: false,
|
|
125
|
-
|
|
125
|
+
sourceData: { content: 'Hello' },
|
|
126
126
|
})
|
|
127
127
|
|
|
128
128
|
render(
|
|
@@ -135,11 +135,11 @@ describe('WidgetNoData', () => {
|
|
|
135
135
|
expect(screen.queryByText('No data available')).toBeNull()
|
|
136
136
|
})
|
|
137
137
|
|
|
138
|
-
test('renders children with nested array
|
|
138
|
+
test('renders children with nested array sourceData', () => {
|
|
139
139
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
140
140
|
isLoading: false,
|
|
141
141
|
isFetching: false,
|
|
142
|
-
|
|
142
|
+
sourceData: [[{ name: 'A', value: 1 }]],
|
|
143
143
|
})
|
|
144
144
|
|
|
145
145
|
render(
|
|
@@ -152,11 +152,11 @@ describe('WidgetNoData', () => {
|
|
|
152
152
|
expect(screen.queryByText('No data available')).toBeNull()
|
|
153
153
|
})
|
|
154
154
|
|
|
155
|
-
test('renders children with primitive
|
|
155
|
+
test('renders children with primitive sourceData (number)', () => {
|
|
156
156
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
157
157
|
isLoading: false,
|
|
158
158
|
isFetching: false,
|
|
159
|
-
|
|
159
|
+
sourceData: 0,
|
|
160
160
|
})
|
|
161
161
|
|
|
162
162
|
render(
|
|
@@ -169,11 +169,11 @@ describe('WidgetNoData', () => {
|
|
|
169
169
|
expect(screen.queryByText('No data available')).toBeNull()
|
|
170
170
|
})
|
|
171
171
|
|
|
172
|
-
test('renders children with primitive
|
|
172
|
+
test('renders children with primitive sourceData (string)', () => {
|
|
173
173
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
174
174
|
isLoading: false,
|
|
175
175
|
isFetching: false,
|
|
176
|
-
|
|
176
|
+
sourceData: 'test',
|
|
177
177
|
})
|
|
178
178
|
|
|
179
179
|
render(
|
|
@@ -186,11 +186,11 @@ describe('WidgetNoData', () => {
|
|
|
186
186
|
expect(screen.queryByText('No data available')).toBeNull()
|
|
187
187
|
})
|
|
188
188
|
|
|
189
|
-
test('renders children with primitive
|
|
189
|
+
test('renders children with primitive sourceData (boolean)', () => {
|
|
190
190
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
191
191
|
isLoading: false,
|
|
192
192
|
isFetching: false,
|
|
193
|
-
|
|
193
|
+
sourceData: false,
|
|
194
194
|
})
|
|
195
195
|
|
|
196
196
|
render(
|
|
@@ -205,11 +205,10 @@ describe('WidgetNoData', () => {
|
|
|
205
205
|
})
|
|
206
206
|
|
|
207
207
|
describe('when loading or fetching', () => {
|
|
208
|
-
test('renders children when isLoading=true even if
|
|
208
|
+
test('renders children when isLoading=true even if sourceData is empty', () => {
|
|
209
209
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
210
210
|
isLoading: true,
|
|
211
211
|
isFetching: false,
|
|
212
|
-
data: [],
|
|
213
212
|
})
|
|
214
213
|
|
|
215
214
|
render(
|
|
@@ -222,11 +221,10 @@ describe('WidgetNoData', () => {
|
|
|
222
221
|
expect(screen.queryByText('No data available')).toBeNull()
|
|
223
222
|
})
|
|
224
223
|
|
|
225
|
-
test('renders children when isFetching=true even if
|
|
224
|
+
test('renders children when isFetching=true even if sourceData is empty', () => {
|
|
226
225
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
227
226
|
isLoading: false,
|
|
228
227
|
isFetching: true,
|
|
229
|
-
data: [],
|
|
230
228
|
})
|
|
231
229
|
|
|
232
230
|
render(
|
|
@@ -243,7 +241,6 @@ describe('WidgetNoData', () => {
|
|
|
243
241
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
244
242
|
isLoading: true,
|
|
245
243
|
isFetching: true,
|
|
246
|
-
data: [],
|
|
247
244
|
})
|
|
248
245
|
|
|
249
246
|
render(
|
|
@@ -262,7 +259,7 @@ describe('WidgetNoData', () => {
|
|
|
262
259
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
263
260
|
isLoading: false,
|
|
264
261
|
isFetching: false,
|
|
265
|
-
|
|
262
|
+
sourceData: [],
|
|
266
263
|
})
|
|
267
264
|
|
|
268
265
|
render(
|
|
@@ -279,7 +276,7 @@ describe('WidgetNoData', () => {
|
|
|
279
276
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
280
277
|
isLoading: false,
|
|
281
278
|
isFetching: false,
|
|
282
|
-
|
|
279
|
+
sourceData: [],
|
|
283
280
|
})
|
|
284
281
|
|
|
285
282
|
render(
|
|
@@ -298,10 +295,10 @@ describe('WidgetNoData', () => {
|
|
|
298
295
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
299
296
|
isLoading: false,
|
|
300
297
|
isFetching: false,
|
|
301
|
-
|
|
298
|
+
sourceData: { customField: 'value' },
|
|
302
299
|
})
|
|
303
300
|
|
|
304
|
-
// Custom isEmpty that treats this
|
|
301
|
+
// Custom isEmpty that treats this sourceData as empty
|
|
305
302
|
const customIsEmpty = (data: unknown) => {
|
|
306
303
|
const d = data as { customField: string }
|
|
307
304
|
return d?.customField === 'value'
|
|
@@ -321,7 +318,7 @@ describe('WidgetNoData', () => {
|
|
|
321
318
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
322
319
|
isLoading: false,
|
|
323
320
|
isFetching: false,
|
|
324
|
-
|
|
321
|
+
sourceData: [],
|
|
325
322
|
})
|
|
326
323
|
|
|
327
324
|
// Custom isEmpty that treats empty array as having data
|
|
@@ -352,12 +349,66 @@ describe('WidgetNoData', () => {
|
|
|
352
349
|
})
|
|
353
350
|
})
|
|
354
351
|
|
|
352
|
+
describe('sourceData vs pipeline-transformed data', () => {
|
|
353
|
+
test('renders children when sourceData has data but pipeline data is empty', () => {
|
|
354
|
+
useWidgetStore.getState().setWidget(widgetId, {
|
|
355
|
+
isLoading: false,
|
|
356
|
+
isFetching: false,
|
|
357
|
+
sourceData: [{ value: 1 }, { value: 2 }],
|
|
358
|
+
data: [], // pipeline filtered everything out
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
render(
|
|
362
|
+
<WidgetNoData id={widgetId}>
|
|
363
|
+
<div>Widget Content</div>
|
|
364
|
+
</WidgetNoData>,
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
// Should show children because sourceData is not empty
|
|
368
|
+
expect(screen.getByText('Widget Content')).toBeTruthy()
|
|
369
|
+
expect(screen.queryByText('No data available')).toBeNull()
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
test('renders NoData when both sourceData and data are empty', () => {
|
|
373
|
+
useWidgetStore.getState().setWidget(widgetId, {
|
|
374
|
+
isLoading: false,
|
|
375
|
+
isFetching: false,
|
|
376
|
+
sourceData: [],
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
render(
|
|
380
|
+
<WidgetNoData id={widgetId}>
|
|
381
|
+
<div>Widget Content</div>
|
|
382
|
+
</WidgetNoData>,
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
expect(screen.getByText('No data available')).toBeTruthy()
|
|
386
|
+
expect(screen.queryByText('Widget Content')).toBeNull()
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
test('renders NoData when sourceData is null (API returned nothing)', () => {
|
|
390
|
+
useWidgetStore.getState().setWidget(widgetId, {
|
|
391
|
+
isLoading: false,
|
|
392
|
+
isFetching: false,
|
|
393
|
+
sourceData: null,
|
|
394
|
+
})
|
|
395
|
+
|
|
396
|
+
render(
|
|
397
|
+
<WidgetNoData id={widgetId}>
|
|
398
|
+
<div>Widget Content</div>
|
|
399
|
+
</WidgetNoData>,
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
expect(screen.getByText('No data available')).toBeTruthy()
|
|
403
|
+
expect(screen.queryByText('Widget Content')).toBeNull()
|
|
404
|
+
})
|
|
405
|
+
})
|
|
406
|
+
|
|
355
407
|
describe('reactivity to store changes', () => {
|
|
356
|
-
test('updates from NoData to content when
|
|
408
|
+
test('updates from NoData to content when sourceData arrives', () => {
|
|
357
409
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
358
410
|
isLoading: false,
|
|
359
411
|
isFetching: false,
|
|
360
|
-
data: [],
|
|
361
412
|
})
|
|
362
413
|
|
|
363
414
|
const { rerender } = render(
|
|
@@ -369,9 +420,9 @@ describe('WidgetNoData', () => {
|
|
|
369
420
|
expect(screen.getByText('No data available')).toBeTruthy()
|
|
370
421
|
expect(screen.queryByText('Widget Content')).toBeNull()
|
|
371
422
|
|
|
372
|
-
// Update with
|
|
423
|
+
// Update with sourceData
|
|
373
424
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
374
|
-
|
|
425
|
+
sourceData: [{ value: 1 }],
|
|
375
426
|
})
|
|
376
427
|
|
|
377
428
|
// Force rerender to pick up store changes
|
|
@@ -385,11 +436,11 @@ describe('WidgetNoData', () => {
|
|
|
385
436
|
expect(screen.queryByText('No data available')).toBeNull()
|
|
386
437
|
})
|
|
387
438
|
|
|
388
|
-
test('updates from content to NoData when
|
|
439
|
+
test('updates from content to NoData when sourceData becomes empty', () => {
|
|
389
440
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
390
441
|
isLoading: false,
|
|
391
442
|
isFetching: false,
|
|
392
|
-
|
|
443
|
+
sourceData: [{ value: 1 }],
|
|
393
444
|
})
|
|
394
445
|
|
|
395
446
|
const { rerender } = render(
|
|
@@ -401,8 +452,8 @@ describe('WidgetNoData', () => {
|
|
|
401
452
|
expect(screen.getByText('Widget Content')).toBeTruthy()
|
|
402
453
|
expect(screen.queryByText('No data available')).toBeNull()
|
|
403
454
|
|
|
404
|
-
// Clear
|
|
405
|
-
useWidgetStore.getState().setWidget(widgetId, {
|
|
455
|
+
// Clear sourceData
|
|
456
|
+
useWidgetStore.getState().setWidget(widgetId, { sourceData: [] })
|
|
406
457
|
|
|
407
458
|
// Force rerender to pick up store changes
|
|
408
459
|
rerender(
|
|
@@ -419,7 +470,6 @@ describe('WidgetNoData', () => {
|
|
|
419
470
|
useWidgetStore.getState().setWidget(widgetId, {
|
|
420
471
|
isLoading: false,
|
|
421
472
|
isFetching: false,
|
|
422
|
-
data: [],
|
|
423
473
|
})
|
|
424
474
|
|
|
425
475
|
const { rerender } = render(
|
|
@@ -6,8 +6,9 @@ import { styles } from './style'
|
|
|
6
6
|
/**
|
|
7
7
|
* NoData wrapper component that displays empty state UI when widget has no data
|
|
8
8
|
*
|
|
9
|
-
* Integrates with widget store to check loading/fetching state and data availability.
|
|
10
|
-
*
|
|
9
|
+
* Integrates with widget store to check loading/fetching state and source data availability.
|
|
10
|
+
* Uses `sourceData` (pre-pipeline data) instead of `data` (post-pipeline) to distinguish
|
|
11
|
+
* "API returned nothing" from "pipeline tools filtered everything out".
|
|
11
12
|
*
|
|
12
13
|
* @example Basic usage
|
|
13
14
|
* ```tsx
|
|
@@ -44,10 +45,11 @@ export function WidgetNoData({
|
|
|
44
45
|
isEmpty = defaultIsEmpty,
|
|
45
46
|
}: WidgetNoDataProps) {
|
|
46
47
|
// Single consolidated subscription instead of 3 separate ones.
|
|
47
|
-
|
|
48
|
+
// Reads sourceData (pre-pipeline) to check emptiness, not data (post-pipeline).
|
|
49
|
+
const { isLoading, isFetching, sourceData } = useWidgetSelector(id, (w) => ({
|
|
48
50
|
isLoading: w?.isLoading,
|
|
49
51
|
isFetching: w?.isFetching,
|
|
50
|
-
|
|
52
|
+
sourceData: w?.sourceData,
|
|
51
53
|
}))
|
|
52
54
|
|
|
53
55
|
// If loading or fetching, show children
|
|
@@ -57,7 +59,7 @@ export function WidgetNoData({
|
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
// Check if data is empty
|
|
60
|
-
if (isEmpty(
|
|
62
|
+
if (isEmpty(sourceData)) {
|
|
61
63
|
return (
|
|
62
64
|
<Box sx={styles.root}>
|
|
63
65
|
<Typography variant='body2' color='text.primary'>
|
|
@@ -59,7 +59,11 @@ export interface WidgetNoDataProps {
|
|
|
59
59
|
description?: string
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
|
-
* Optional custom function to determine if data is empty
|
|
62
|
+
* Optional custom function to determine if source data is empty.
|
|
63
|
+
* Receives `sourceData` (pre-pipeline data from the API), not `data`
|
|
64
|
+
* (post-pipeline). This allows distinguishing "API returned nothing"
|
|
65
|
+
* from "pipeline tools filtered everything out".
|
|
66
|
+
*
|
|
63
67
|
* If not provided, uses default isEmpty logic that handles:
|
|
64
68
|
* - null/undefined → empty
|
|
65
69
|
* - [] (empty array) → empty
|
|
@@ -14,6 +14,10 @@ export interface WidgetsStoreProps {
|
|
|
14
14
|
type: string
|
|
15
15
|
/** Widget data - flexible to accommodate different widget types */
|
|
16
16
|
data: unknown
|
|
17
|
+
/** Original pre-pipeline data. Used by NoData to distinguish
|
|
18
|
+
* "no data from API" from "pipeline tools filtered everything out".
|
|
19
|
+
* Set automatically by executeToolPipeline — not a component prop. */
|
|
20
|
+
sourceData?: unknown
|
|
17
21
|
/** Loading state */
|
|
18
22
|
isLoading: boolean
|
|
19
23
|
/** Fetching state (e.g., for async data) */
|
|
@@ -41,11 +45,7 @@ export interface WidgetsStoreProps {
|
|
|
41
45
|
* Tool transformation function type
|
|
42
46
|
* Can be synchronous or asynchronous to support remote operations
|
|
43
47
|
*/
|
|
44
|
-
export type ToolTransformFunction = (
|
|
45
|
-
data: unknown,
|
|
46
|
-
config?: Record<string, unknown>,
|
|
47
|
-
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
|
48
|
-
) => Promise<unknown> | unknown
|
|
48
|
+
export type ToolTransformFunction = (data: unknown) => unknown
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* Tool registration for widget pipeline
|
|
@@ -88,8 +88,6 @@ export interface ToolRegistration {
|
|
|
88
88
|
enabled: boolean
|
|
89
89
|
/** 'data' (default) transforms data, 'config' transforms widget config/option */
|
|
90
90
|
type?: ToolType
|
|
91
|
-
/** Tool-specific configuration */
|
|
92
|
-
config?: Record<string, unknown>
|
|
93
91
|
/**
|
|
94
92
|
* Array of tool IDs to disable when this tool is active.
|
|
95
93
|
* During pipeline execution, if this tool is enabled, any tools listed
|
|
@@ -169,24 +167,18 @@ export interface WidgetStoreActions {
|
|
|
169
167
|
unregisterTool: (widgetId: string, toolId: string) => void
|
|
170
168
|
|
|
171
169
|
/**
|
|
172
|
-
*
|
|
170
|
+
* Set tool enabled state
|
|
173
171
|
* @param widgetId - Widget ID
|
|
174
172
|
* @param toolId - Tool ID
|
|
175
|
-
* @param
|
|
173
|
+
* @param enabled - Whether tool should be enabled
|
|
176
174
|
*/
|
|
177
|
-
|
|
178
|
-
widgetId: string,
|
|
179
|
-
toolId: string,
|
|
180
|
-
config: Record<string, unknown>,
|
|
181
|
-
) => void
|
|
175
|
+
setToolEnabled: (widgetId: string, toolId: string, enabled: boolean) => void
|
|
182
176
|
|
|
183
177
|
/**
|
|
184
|
-
*
|
|
178
|
+
* Trigger pipeline re-execution by bumping the registeredTools reference.
|
|
185
179
|
* @param widgetId - Widget ID
|
|
186
|
-
* @param toolId - Tool ID
|
|
187
|
-
* @param enabled - Whether tool should be enabled
|
|
188
180
|
*/
|
|
189
|
-
|
|
181
|
+
triggerToolPipeline: (widgetId: string) => void
|
|
190
182
|
|
|
191
183
|
/**
|
|
192
184
|
* Execute the tool transformation pipeline
|