@thoughtspot/ts-chart-sdk 0.0.1-alpha.8 → 0.0.2-alpha.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.
Files changed (131) hide show
  1. package/lib/main/custom-chart-context.d.ts +17 -3
  2. package/lib/main/custom-chart-context.d.ts.map +1 -1
  3. package/lib/main/custom-chart-context.js +138 -33
  4. package/lib/main/custom-chart-context.js.map +1 -1
  5. package/lib/main/custom-chart-context.spec.js +259 -164
  6. package/lib/main/custom-chart-context.spec.js.map +1 -1
  7. package/lib/main/post-message-event-bridge.d.ts +3 -3
  8. package/lib/main/post-message-event-bridge.d.ts.map +1 -1
  9. package/lib/main/post-message-event-bridge.js +24 -36
  10. package/lib/main/post-message-event-bridge.js.map +1 -1
  11. package/lib/main/post-message-event-bridge.spec.js +0 -2
  12. package/lib/main/post-message-event-bridge.spec.js.map +1 -1
  13. package/lib/main/util.d.ts +2 -0
  14. package/lib/main/util.d.ts.map +1 -0
  15. package/lib/main/util.js +9 -0
  16. package/lib/main/util.js.map +1 -0
  17. package/lib/react/use-custom-chart-context.spec.js +74 -119
  18. package/lib/react/use-custom-chart-context.spec.js.map +1 -1
  19. package/lib/types/chart-to-ts-event.types.d.ts +7 -1
  20. package/lib/types/chart-to-ts-event.types.d.ts.map +1 -1
  21. package/lib/types/chart-to-ts-event.types.js.map +1 -1
  22. package/lib/types/common.types.d.ts +2 -0
  23. package/lib/types/common.types.d.ts.map +1 -1
  24. package/lib/types/ts-to-chart-event.types.d.ts +26 -1
  25. package/lib/types/ts-to-chart-event.types.d.ts.map +1 -1
  26. package/lib/types/ts-to-chart-event.types.js +2 -0
  27. package/lib/types/ts-to-chart-event.types.js.map +1 -1
  28. package/package.json +5 -4
  29. package/src/main/custom-chart-context.spec.ts +330 -173
  30. package/src/main/custom-chart-context.ts +276 -39
  31. package/src/main/post-message-event-bridge.spec.ts +0 -3
  32. package/src/main/post-message-event-bridge.ts +36 -62
  33. package/src/main/util.ts +11 -0
  34. package/src/react/use-custom-chart-context.spec.tsx +84 -120
  35. package/src/types/chart-to-ts-event.types.ts +21 -1
  36. package/src/types/common.types.ts +15 -1
  37. package/src/types/ts-to-chart-event.types.ts +84 -0
  38. package/cjs/index.d.ts +0 -9
  39. package/cjs/index.d.ts.map +0 -1
  40. package/cjs/index.js +0 -25
  41. package/cjs/index.js.map +0 -1
  42. package/cjs/main/custom-chart-context.d.ts +0 -40
  43. package/cjs/main/custom-chart-context.d.ts.map +0 -1
  44. package/cjs/main/custom-chart-context.js +0 -218
  45. package/cjs/main/custom-chart-context.js.map +0 -1
  46. package/cjs/main/custom-chart-context.spec.d.ts +0 -2
  47. package/cjs/main/custom-chart-context.spec.d.ts.map +0 -1
  48. package/cjs/main/custom-chart-context.spec.js +0 -448
  49. package/cjs/main/custom-chart-context.spec.js.map +0 -1
  50. package/cjs/main/post-message-event-bridge.d.ts +0 -6
  51. package/cjs/main/post-message-event-bridge.d.ts.map +0 -1
  52. package/cjs/main/post-message-event-bridge.js +0 -46
  53. package/cjs/main/post-message-event-bridge.js.map +0 -1
  54. package/cjs/main/post-message-event-bridge.spec.d.ts +0 -2
  55. package/cjs/main/post-message-event-bridge.spec.d.ts.map +0 -1
  56. package/cjs/main/post-message-event-bridge.spec.js +0 -124
  57. package/cjs/main/post-message-event-bridge.spec.js.map +0 -1
  58. package/cjs/react/custom-chart-context-service.d.ts +0 -33
  59. package/cjs/react/custom-chart-context-service.d.ts.map +0 -1
  60. package/cjs/react/custom-chart-context-service.js +0 -118
  61. package/cjs/react/custom-chart-context-service.js.map +0 -1
  62. package/cjs/react/custom-chart.context.d.ts +0 -26
  63. package/cjs/react/custom-chart.context.d.ts.map +0 -1
  64. package/cjs/react/custom-chart.context.js +0 -105
  65. package/cjs/react/custom-chart.context.js.map +0 -1
  66. package/cjs/react/custom-chart.spec.d.ts +0 -2
  67. package/cjs/react/custom-chart.spec.d.ts.map +0 -1
  68. package/cjs/react/custom-chart.spec.js +0 -72
  69. package/cjs/react/custom-chart.spec.js.map +0 -1
  70. package/cjs/react/mocks/custom-chart-context-mock.d.ts +0 -3
  71. package/cjs/react/mocks/custom-chart-context-mock.d.ts.map +0 -1
  72. package/cjs/react/mocks/custom-chart-context-mock.js +0 -100
  73. package/cjs/react/mocks/custom-chart-context-mock.js.map +0 -1
  74. package/cjs/react/use-custom-chart-context.d.ts +0 -4
  75. package/cjs/react/use-custom-chart-context.d.ts.map +0 -1
  76. package/cjs/react/use-custom-chart-context.js +0 -95
  77. package/cjs/react/use-custom-chart-context.js.map +0 -1
  78. package/cjs/react/use-custom-chart-context.spec.d.ts +0 -2
  79. package/cjs/react/use-custom-chart-context.spec.d.ts.map +0 -1
  80. package/cjs/react/use-custom-chart-context.spec.js +0 -391
  81. package/cjs/react/use-custom-chart-context.spec.js.map +0 -1
  82. package/cjs/react/use-custom-chart-context.util.d.ts +0 -6
  83. package/cjs/react/use-custom-chart-context.util.d.ts.map +0 -1
  84. package/cjs/react/use-custom-chart-context.util.js +0 -60
  85. package/cjs/react/use-custom-chart-context.util.js.map +0 -1
  86. package/cjs/react/use-custom-chart-types.d.ts +0 -23
  87. package/cjs/react/use-custom-chart-types.d.ts.map +0 -1
  88. package/cjs/react/use-custom-chart-types.js +0 -3
  89. package/cjs/react/use-custom-chart-types.js.map +0 -1
  90. package/cjs/test/test-utils.d.ts +0 -7
  91. package/cjs/test/test-utils.d.ts.map +0 -1
  92. package/cjs/test/test-utils.js +0 -14
  93. package/cjs/test/test-utils.js.map +0 -1
  94. package/cjs/types/answer-column.types.d.ts +0 -69
  95. package/cjs/types/answer-column.types.d.ts.map +0 -1
  96. package/cjs/types/answer-column.types.js +0 -59
  97. package/cjs/types/answer-column.types.js.map +0 -1
  98. package/cjs/types/chart-to-ts-event.types.d.ts +0 -92
  99. package/cjs/types/chart-to-ts-event.types.d.ts.map +0 -1
  100. package/cjs/types/chart-to-ts-event.types.js +0 -32
  101. package/cjs/types/chart-to-ts-event.types.js.map +0 -1
  102. package/cjs/types/common.types.d.ts +0 -50
  103. package/cjs/types/common.types.d.ts.map +0 -1
  104. package/cjs/types/common.types.js +0 -3
  105. package/cjs/types/common.types.js.map +0 -1
  106. package/cjs/types/configurator.types.d.ts +0 -15
  107. package/cjs/types/configurator.types.d.ts.map +0 -1
  108. package/cjs/types/configurator.types.js +0 -3
  109. package/cjs/types/configurator.types.js.map +0 -1
  110. package/cjs/types/ts-to-chart-event.types.d.ts +0 -69
  111. package/cjs/types/ts-to-chart-event.types.d.ts.map +0 -1
  112. package/cjs/types/ts-to-chart-event.types.js +0 -16
  113. package/cjs/types/ts-to-chart-event.types.js.map +0 -1
  114. package/cjs/types/visual-prop.types.d.ts +0 -73
  115. package/cjs/types/visual-prop.types.d.ts.map +0 -1
  116. package/cjs/types/visual-prop.types.js +0 -3
  117. package/cjs/types/visual-prop.types.js.map +0 -1
  118. package/dist/ts-chart-sdk.d.ts +0 -312
  119. package/lib/dist/ts-chart-sdk.d.ts +0 -312
  120. package/lib/react/custom-chart-context-service.d.ts +0 -33
  121. package/lib/react/custom-chart-context-service.d.ts.map +0 -1
  122. package/lib/react/custom-chart-context-service.js +0 -91
  123. package/lib/react/custom-chart-context-service.js.map +0 -1
  124. package/lib/react/custom-chart.context.d.ts +0 -26
  125. package/lib/react/custom-chart.context.d.ts.map +0 -1
  126. package/lib/react/custom-chart.context.js +0 -78
  127. package/lib/react/custom-chart.context.js.map +0 -1
  128. package/lib/react/custom-chart.spec.d.ts +0 -2
  129. package/lib/react/custom-chart.spec.d.ts.map +0 -1
  130. package/lib/react/custom-chart.spec.js +0 -67
  131. package/lib/react/custom-chart.spec.js.map +0 -1
@@ -5,13 +5,20 @@
5
5
  *
6
6
  * Copyright: ThoughtSpot Inc. 2023
7
7
  */
8
+
8
9
  import _ from 'lodash';
9
10
  import {
11
+ AxisMenuActionHandler,
10
12
  ChartToTSEvent,
11
13
  ChartToTSEventsPayloadMap,
14
+ ContextMenuActionHandler,
15
+ CustomAction,
12
16
  ErrorType,
17
+ OpenAxisMenuEventPayload,
18
+ OpenContextMenuEventPayload,
13
19
  } from '../types/chart-to-ts-event.types';
14
20
  import {
21
+ AppConfig,
15
22
  ChartConfig,
16
23
  ChartModel,
17
24
  ValidationResponse,
@@ -19,8 +26,10 @@ import {
19
26
  } from '../types/common.types';
20
27
  import { ChartConfigEditorDefinition } from '../types/configurator.types';
21
28
  import {
29
+ AxisMenuCustomActionPayload,
22
30
  ChartConfigValidateEventPayload,
23
31
  ChartModelUpdateEventPayload,
32
+ ContextMenuCustomActionPayload,
24
33
  DataUpdateEventPayload,
25
34
  GetDataQueryPayload,
26
35
  GetDataQueryResponsePayload,
@@ -34,9 +43,16 @@ import {
34
43
  VisualPropsValidateEventPayload,
35
44
  } from '../types/ts-to-chart-event.types';
36
45
  import { VisualPropEditorDefinition } from '../types/visual-prop.types';
37
- import * as PostMessageEventBridge from './post-message-event-bridge';
38
-
39
- let isInitialized = false;
46
+ import {
47
+ globalThis,
48
+ initMessageListener,
49
+ postMessageToHostApp,
50
+ } from './post-message-event-bridge';
51
+
52
+ export type AllowedConfigurations = {
53
+ allowColumnNumberFormatting: boolean;
54
+ allowColumnConditionalFormatting: boolean;
55
+ };
40
56
 
41
57
  export type CustomChartContextProps = {
42
58
  /**
@@ -54,7 +70,10 @@ export type CustomChartContextProps = {
54
70
  * @returns {@link Array<Query>}
55
71
  * @version SDK: 0.1 | ThoughtSpot:
56
72
  */
57
- getQueriesFromChartConfig: (chartConfig: ChartConfig[]) => Query[];
73
+ getQueriesFromChartConfig: (
74
+ chartConfig: ChartConfig[],
75
+ chartModel: ChartModel,
76
+ ) => Query[];
58
77
  /**
59
78
  * Main Render function that will render the chart based on the chart context provided
60
79
  *
@@ -109,6 +128,9 @@ export type CustomChartContextProps = {
109
128
  * @version SDK: 0.1 | ThoughtSpot:
110
129
  */
111
130
  visualPropEditorDefinition?: VisualPropEditorDefinition;
131
+
132
+ // Whether user wants thoughtspot default number and conditional formatting
133
+ allowedConfigurations?: AllowedConfigurations;
112
134
  };
113
135
 
114
136
  /**
@@ -118,6 +140,10 @@ const DEFAULT_CHART_CONTEXT_PROPS: Partial<CustomChartContextProps> = {
118
140
  validateConfig: () => ({ isValid: true }),
119
141
  validateVisualProps: () => ({ isValid: true }),
120
142
  chartConfigEditorDefinition: undefined,
143
+ allowedConfigurations: {
144
+ allowColumnNumberFormatting: false,
145
+ allowColumnConditionalFormatting: false,
146
+ },
121
147
  };
122
148
 
123
149
  export class CustomChartContext {
@@ -132,6 +158,8 @@ export class CustomChartContext {
132
158
  */
133
159
  private componentId = '';
134
160
 
161
+ private removeListener: () => void = _.noop;
162
+
135
163
  /**
136
164
  * host app url
137
165
  *
@@ -149,6 +177,13 @@ export class CustomChartContext {
149
177
  */
150
178
  private chartModel: ChartModel = {} as any;
151
179
 
180
+ /**
181
+ * App Config object. This contains the app state like locale and timezones.
182
+ *
183
+ * @version SDK: 0.1 | ThoughtSpot:
184
+ */
185
+ private appConfig: AppConfig = {};
186
+
152
187
  /**
153
188
  * Chart Props Object to define the workflow of the application
154
189
  *
@@ -185,6 +220,24 @@ export class CustomChartContext {
185
220
  */
186
221
  private triggerInitResolve: () => void = _.noop;
187
222
 
223
+ /**
224
+ * Stores the callbacks of context menu custom action based on custom action id
225
+ *
226
+ * @returns {@link ContextMenuActionHandler}
227
+ * @version SDK: 0.1 | ThoughtSpot:
228
+ */
229
+ private contextMenuActionHandler: ContextMenuActionHandler = {};
230
+
231
+ /**
232
+ * Stores the callbacks of axis menu custom action based on custom action id
233
+ *
234
+ * @returns {@link AxisMenuActionHandler}
235
+ * @version SDK: 0.1 | ThoughtSpot:
236
+ */
237
+ private axisMenuActionHandler: AxisMenuActionHandler = {};
238
+
239
+ public containerEl: HTMLElement | null = null;
240
+
188
241
  /**
189
242
  * Constructor to only accept context props as payload
190
243
  *
@@ -273,8 +326,8 @@ export class CustomChartContext {
273
326
  * @version SDK: 0.1 | ThoughtSpot:
274
327
  */
275
328
  public destroy() {
276
- PostMessageEventBridge.destroyMessageListener(this.eventProcessor);
277
- isInitialized = false;
329
+ this.removeListener();
330
+ globalThis.isInitialized = false;
278
331
  }
279
332
 
280
333
  /**
@@ -284,6 +337,107 @@ export class CustomChartContext {
284
337
  */
285
338
  public getChartModel = (): ChartModel => this.chartModel;
286
339
 
340
+ /**
341
+ * Getter for the chart model object
342
+ *
343
+ * @version SDK: 0.1 | ThoughtSpot:
344
+ */
345
+ public getAppConfig = (): AppConfig => this.appConfig;
346
+
347
+ /**
348
+ * Function to store the context menu custom action callback mapped with action id
349
+ * @param {[OpenContextMenuEventPayload]} eventPayload Event payload bound
350
+ * to the type of the event
351
+ * @returns payload
352
+ */
353
+ public contextMenuCustomActionPreProcessor(
354
+ eventPayload: [OpenContextMenuEventPayload],
355
+ ): [OpenContextMenuEventPayload] {
356
+ // clear out the stored custom events callback for context menu
357
+ this.contextMenuActionHandler = {};
358
+ if (_.isEmpty(eventPayload?.[0]?.customActions)) {
359
+ return eventPayload;
360
+ }
361
+ eventPayload?.[0]?.customActions?.forEach((action: CustomAction) => {
362
+ this.contextMenuActionHandler[action.id] = action.onClick;
363
+ });
364
+ const processedCustomActions = eventPayload[0]?.customActions?.map(
365
+ (action: CustomAction) => {
366
+ return {
367
+ id: action.id,
368
+ label: action.label,
369
+ icon: action.icon,
370
+ };
371
+ },
372
+ );
373
+ const processedPayload: [OpenContextMenuEventPayload] = [
374
+ {
375
+ ...eventPayload[0],
376
+ customActions: processedCustomActions as CustomAction[],
377
+ },
378
+ ];
379
+ return processedPayload;
380
+ }
381
+
382
+ /**
383
+ * Function to store the axis menu custom action callback mapped with action id
384
+ * @param {[OpenAxisMenuEventPayload]} eventPayload Event payload bound
385
+ * to the type of the event
386
+ * @returns payload
387
+ */
388
+ public axisMenuCustomActionPreProcessor(
389
+ eventPayload: [OpenAxisMenuEventPayload],
390
+ ): [OpenAxisMenuEventPayload] {
391
+ // clear out the stored custom events callback for axis menu
392
+ this.axisMenuActionHandler = {};
393
+ if (_.isEmpty(eventPayload?.[0]?.customActions)) {
394
+ return eventPayload;
395
+ }
396
+ eventPayload[0].customActions?.forEach((action: CustomAction) => {
397
+ this.axisMenuActionHandler[action.id] = action.onClick;
398
+ });
399
+ const processedCustomActions = eventPayload?.[0].customActions?.map(
400
+ (action: CustomAction) => {
401
+ return {
402
+ id: action.id,
403
+ label: action.label,
404
+ icon: action.icon,
405
+ };
406
+ },
407
+ );
408
+ const processedPayload: [OpenAxisMenuEventPayload] = [
409
+ {
410
+ ...eventPayload[0],
411
+ customActions: processedCustomActions as CustomAction[],
412
+ },
413
+ ];
414
+ return processedPayload;
415
+ }
416
+
417
+ /**
418
+ * Function to process the event payload based on event type
419
+ * @param {ChartToTSEventsPayloadMap[T]} eventPayload Event payload bound
420
+ * to the type of the event
421
+ * @returns payload
422
+ */
423
+ private eventPayloadPreProcessor<T extends keyof ChartToTSEventsPayloadMap>(
424
+ eventType: T,
425
+ eventPayload: ChartToTSEventsPayloadMap[T],
426
+ ): ChartToTSEventsPayloadMap[T] {
427
+ switch (eventType) {
428
+ case ChartToTSEvent.OpenContextMenu:
429
+ return this.contextMenuCustomActionPreProcessor(
430
+ eventPayload as [OpenContextMenuEventPayload],
431
+ ) as ChartToTSEventsPayloadMap[T];
432
+ case ChartToTSEvent.OpenAxisMenu:
433
+ return this.axisMenuCustomActionPreProcessor(
434
+ eventPayload as [OpenAxisMenuEventPayload],
435
+ ) as ChartToTSEventsPayloadMap[T];
436
+ default:
437
+ return eventPayload;
438
+ }
439
+ }
440
+
287
441
  /**
288
442
  * Function to emit Chart to TS Events to the TS application.
289
443
 
@@ -296,16 +450,20 @@ export class CustomChartContext {
296
450
  eventType: T,
297
451
  ...eventPayload: ChartToTSEventsPayloadMap[T]
298
452
  ): Promise<any> {
299
- if (!isInitialized) {
453
+ if (!globalThis.isInitialized) {
300
454
  console.log(
301
455
  'Chart Context: not initialized the context, something went wrong',
302
456
  );
303
457
  return Promise.reject(new Error('Context not initialized'));
304
458
  }
305
- return PostMessageEventBridge.postMessageToHostApp(
459
+ const processedPayload = this.eventPayloadPreProcessor(
460
+ eventType,
461
+ eventPayload,
462
+ );
463
+ return postMessageToHostApp(
306
464
  this.componentId,
307
465
  this.hostUrl,
308
- eventPayload?.[0] ?? null,
466
+ processedPayload?.[0] ?? null,
309
467
  eventType,
310
468
  );
311
469
  }
@@ -315,13 +473,13 @@ export class CustomChartContext {
315
473
  * Process all the functions via the eventProcess callback
316
474
  */
317
475
  private registerEventProcessor = () => {
318
- if (isInitialized) {
476
+ if (globalThis.isInitialized) {
319
477
  console.error(
320
478
  'The context is already initialized. you cannot have multiple contexts',
321
479
  );
322
480
  throw new Error(ErrorType.MultipleContextsNotSupported);
323
481
  }
324
- PostMessageEventBridge.initMessageListener(this.eventProcessor);
482
+ this.removeListener = initMessageListener(this.eventProcessor);
325
483
 
326
484
  this.registerEvents();
327
485
  };
@@ -331,29 +489,13 @@ export class CustomChartContext {
331
489
  *
332
490
  * @param event : Message Event Object
333
491
  */
334
- private eventProcessor = (event: MessageEvent) => {
335
- if (event.data.source !== 'ts-host-app') {
336
- return;
337
- }
338
-
339
- console.log(
340
- 'Chart Context: message received:',
341
- event.data.eventType,
342
- event.data,
343
- );
492
+ private eventProcessor = (data: any) => {
493
+ console.log('Chart Context: message received:', data.eventType, data);
344
494
 
345
- const messageResponse = this.executeEventListenerCBs(event);
495
+ const messageResponse = this.executeEventListenerCBs(data);
346
496
 
347
497
  // respond back to parent to confirm/ack the receipt
348
- if (!_.isNil(event.ports[0])) {
349
- if (!_.isNil(messageResponse)) {
350
- event.ports[0].postMessage({
351
- ...(messageResponse as any),
352
- });
353
- } else {
354
- event.ports[0].postMessage({});
355
- }
356
- }
498
+ return messageResponse;
357
499
  };
358
500
 
359
501
  /**
@@ -433,6 +575,7 @@ export class CustomChartContext {
433
575
  const queries =
434
576
  this.chartContextProps.getQueriesFromChartConfig(
435
577
  payload.config,
578
+ this.chartModel,
436
579
  );
437
580
  return {
438
581
  queries,
@@ -447,6 +590,94 @@ export class CustomChartContext {
447
590
  this.chartContextProps.renderChart(this);
448
591
  });
449
592
 
593
+ /**
594
+ * This event is triggered when the custom context action is triggered from TS app
595
+ */
596
+ this.onInternal(
597
+ TSToChartEvent.ContextMenuActionClick,
598
+ (
599
+ payload: ContextMenuCustomActionPayload,
600
+ ): {
601
+ isValid: boolean;
602
+ error?: unknown;
603
+ } => {
604
+ try {
605
+ const {
606
+ id: customActionCallback,
607
+ clickedPoint,
608
+ selectedPoints,
609
+ event,
610
+ } = payload.customAction;
611
+ const customActionCallbackArgs = {
612
+ id: customActionCallback,
613
+ clickedPoint,
614
+ selectedPoints,
615
+ event,
616
+ };
617
+ this.contextMenuActionHandler[customActionCallback](
618
+ customActionCallbackArgs,
619
+ );
620
+ return {
621
+ isValid: true,
622
+ };
623
+ } catch (error: unknown) {
624
+ console.log(
625
+ 'ContextMenuCustomAction: payload recieved:',
626
+ payload,
627
+ 'CustomActionCallbackStore:',
628
+ this.axisMenuActionHandler,
629
+ );
630
+ return {
631
+ isValid: false,
632
+ error,
633
+ };
634
+ }
635
+ },
636
+ );
637
+
638
+ /**
639
+ * This event is triggered when the custom axis action is triggered from TS app
640
+ */
641
+ this.onInternal(
642
+ TSToChartEvent.AxisMenuActionClick,
643
+ (
644
+ payload: AxisMenuCustomActionPayload,
645
+ ): {
646
+ isValid: boolean;
647
+ error?: unknown;
648
+ } => {
649
+ try {
650
+ const {
651
+ id: customActionCallback,
652
+ columnIds,
653
+ event,
654
+ } = payload.customAction;
655
+ const customActionCallbackArgs = {
656
+ id: customActionCallback,
657
+ columnIds,
658
+ event,
659
+ };
660
+ this.axisMenuActionHandler[customActionCallback](
661
+ customActionCallbackArgs,
662
+ );
663
+ return {
664
+ isValid: true,
665
+ };
666
+ } catch (error: unknown) {
667
+ console.log(
668
+ 'AxisMenuCustomAction: payload recieved:',
669
+ payload,
670
+ 'CustomActionCallbackStore:',
671
+ this.axisMenuActionHandler,
672
+ );
673
+ return {
674
+ isValid: false,
675
+ error,
676
+ };
677
+ }
678
+ },
679
+ );
680
+
450
681
  // Register External Events
451
682
  // These events are readable by the developer
452
683
 
@@ -517,13 +748,17 @@ export class CustomChartContext {
517
748
  this.componentId = payload.componentId;
518
749
  this.hostUrl = payload.hostUrl;
519
750
  this.chartModel = payload.chartModel;
751
+ this.appConfig = payload.appConfig ?? {};
752
+ this.containerEl = payload.containerElSelector
753
+ ? document.querySelector(payload.containerElSelector)
754
+ : null;
520
755
 
521
756
  return this.publishChartContextPropsToHost();
522
757
  };
523
758
 
524
759
  private initializationComplete = (): void => {
525
760
  // context is now initialized
526
- isInitialized = true;
761
+ globalThis.isInitialized = true;
527
762
 
528
763
  // TODO: following can be done behind a promise
529
764
  this.triggerInitResolve();
@@ -557,6 +792,8 @@ export class CustomChartContext {
557
792
  this.chartContextProps.chartConfigEditorDefinition,
558
793
  visualPropEditorDefinition:
559
794
  this.chartContextProps.visualPropEditorDefinition,
795
+ allowedConfigurations:
796
+ this.chartContextProps.allowedConfigurations,
560
797
  };
561
798
  };
562
799
 
@@ -566,12 +803,12 @@ export class CustomChartContext {
566
803
  * @param event : Message Event Object
567
804
  * @returns response to be sent back to the message sender (host)
568
805
  */
569
- private executeEventListenerCBs = (event: MessageEvent): any => {
806
+ private executeEventListenerCBs = (data: any): any => {
570
807
  // do basic sanity
571
- const payload = event.data.payload;
808
+ const payload = data.payload;
572
809
  let response;
573
- if (_.isArray(this.eventListeners[event.data.eventType])) {
574
- this.eventListeners[event.data.eventType].forEach((callback) => {
810
+ if (_.isArray(this.eventListeners[data.eventType])) {
811
+ this.eventListeners[data.eventType].forEach((callback) => {
575
812
  // this is a problem today if we have multiple callbacks
576
813
  // registered. only the last response will be sent back to the
577
814
  // server
@@ -580,15 +817,15 @@ export class CustomChartContext {
580
817
  } else {
581
818
  response = {
582
819
  hasError: true,
583
- error: `Event type not recognised or processed: ${event.data.eventType}`,
820
+ error: `Event type not recognised or processed: ${data.eventType}`,
584
821
  };
585
822
  }
586
823
 
587
824
  console.log(
588
825
  'ChartContext: Response:',
589
- event.data.eventType,
826
+ data.eventType,
590
827
  response,
591
- this.eventListeners[event.data.eventType]?.length,
828
+ this.eventListeners[data.eventType]?.length,
592
829
  );
593
830
  return response;
594
831
  };
@@ -66,7 +66,6 @@ describe('postMessageToHostApp', () => {
66
66
  );
67
67
 
68
68
  // Verify that the MessageChannel was used correctly
69
- expect(channel.port1.close).toHaveBeenCalled();
70
69
  expect(messageChannelMock.MessageChannel).toHaveBeenCalled();
71
70
  });
72
71
 
@@ -121,8 +120,6 @@ describe('postMessageToHostApp', () => {
121
120
  [channel.port2],
122
121
  );
123
122
 
124
- // Verify that the MessageChannel was used correctly
125
- expect(channel.port1.close).toHaveBeenCalled();
126
123
  expect(messageChannelMock.MessageChannel).toHaveBeenCalled();
127
124
  });
128
125
 
@@ -1,23 +1,23 @@
1
+ import { onMessage, sendMessage } from 'promise-postmessage';
1
2
  import { ChartToTSEvent } from '../types/chart-to-ts-event.types';
3
+ import { timeout } from './util';
2
4
 
3
5
  const TIMEOUT_THRESHOLD = 30000; // 30sec
4
6
 
5
- /**
6
- * method to listen to messages using postMessage from the parent.
7
- *
8
- * @param {any} handleMessageEvent
9
- */
10
- const init = (handleMessageEvent: any) => {
11
- window.addEventListener('message', handleMessageEvent);
12
- };
7
+ const elSelector = new URL(import.meta.url).searchParams.get('elSelector');
8
+ const target =
9
+ (elSelector && (document.querySelector(elSelector) as HTMLElement)) ||
10
+ window.parent;
11
+
12
+ const globalThis = (target instanceof Window ? window : target) as any;
13
13
 
14
14
  /**
15
- * stop listening to the messages
15
+ * method to listen to messages using postMessage from the parent.
16
16
  *
17
17
  * @param {any} handleMessageEvent
18
18
  */
19
- const destroy = (handleMessageEvent: any) => {
20
- window.removeEventListener('message', handleMessageEvent);
19
+ const init = (handleMessageEvent: (data: any) => Promise<any> | any) => {
20
+ return onMessage(handleMessageEvent, target, 'child');
21
21
  };
22
22
 
23
23
  /**
@@ -28,61 +28,35 @@ const destroy = (handleMessageEvent: any) => {
28
28
  * @param {ChartToTSEvent} eventType type of the event
29
29
  * @returns Promise
30
30
  */
31
- const postMessageToHostApp = (
31
+ const postMessageToHostApp = async (
32
32
  componentId: string,
33
33
  hostUrl: string,
34
34
  eventPayload: any,
35
35
  eventType: ChartToTSEvent,
36
- ): Promise<any> =>
37
- new Promise((resolve, reject) => {
38
- const channel = new MessageChannel();
39
- channel.port1.onmessage = (res: any) => {
40
- channel.port1.close();
41
- const { hasError, error } = res.data;
42
- if (hasError) {
43
- console.log('ChartContext: message failure:', res.data);
44
- reject(error);
45
- } else {
46
- console.log('ChartContext: message success:', res.data);
47
- resolve(res.data);
48
- }
49
- };
50
-
51
- setTimeout(() => {
52
- reject(
53
- new Error(
54
- `ChartContext: postMessage operation timed out. ${eventType}`,
55
- eventPayload,
56
- ),
57
- );
58
- }, TIMEOUT_THRESHOLD);
59
-
60
- try {
61
- window.parent.window.postMessage(
62
- {
63
- componentId,
64
- payload: {
65
- ...eventPayload,
66
- },
67
- eventType,
68
- source: 'ts-chart-sdk',
36
+ ): Promise<any> => {
37
+ const resp = await timeout(
38
+ sendMessage(
39
+ target,
40
+ {
41
+ componentId,
42
+ payload: {
43
+ ...eventPayload,
69
44
  },
70
- hostUrl,
71
- [channel.port2],
72
- );
73
- } catch (err) {
74
- console.error(
75
- 'ChartContext: error in emitting event:',
76
- err,
77
45
  eventType,
78
- eventPayload,
79
- );
80
- reject(err);
81
- }
82
- });
83
-
84
- export {
85
- init as initMessageListener,
86
- destroy as destroyMessageListener,
87
- postMessageToHostApp,
46
+ source: 'ts-chart-sdk',
47
+ },
48
+ {
49
+ origin: hostUrl,
50
+ endpoint: 'child',
51
+ },
52
+ ),
53
+ TIMEOUT_THRESHOLD,
54
+ 'ChartContext: postMessage operation timed out.',
55
+ );
56
+ if (resp.hasError) {
57
+ throw new Error(resp.error);
58
+ }
59
+ return resp;
88
60
  };
61
+
62
+ export { init as initMessageListener, postMessageToHostApp, globalThis };
@@ -0,0 +1,11 @@
1
+ export function timeout(promise: Promise<any>, ms: number, message?: string) {
2
+ return Promise.race([
3
+ promise,
4
+ new Promise((resolve, reject) => {
5
+ setTimeout(
6
+ () => reject(new Error(message || 'Operation timed out.')),
7
+ ms,
8
+ );
9
+ }),
10
+ ]);
11
+ }