@mochabug/adapt-web 1.0.0-rc21 → 1.0.0-rc23

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 (162) hide show
  1. package/README.md +225 -0
  2. package/dist/esm/index.js +961 -159
  3. package/dist/esm/index.js.map +1 -1
  4. package/dist/esm/types.js +2 -0
  5. package/dist/esm/types.js.map +1 -0
  6. package/dist/types/index.d.ts +67 -27
  7. package/dist/types/types.d.ts +254 -0
  8. package/dist/umd/adapt-web.js +5038 -0
  9. package/dist/umd/adapt-web.min.js +271 -0
  10. package/package.json +19 -41
  11. package/dist/cjs/genproto/buf/validate/validate_pb.js +0 -355
  12. package/dist/cjs/genproto/buf/validate/validate_pb.js.map +0 -1
  13. package/dist/cjs/genproto/google/api/annotations_pb.js +0 -30
  14. package/dist/cjs/genproto/google/api/annotations_pb.js.map +0 -1
  15. package/dist/cjs/genproto/google/api/client_pb.js +0 -290
  16. package/dist/cjs/genproto/google/api/client_pb.js.map +0 -1
  17. package/dist/cjs/genproto/google/api/http_pb.js +0 -37
  18. package/dist/cjs/genproto/google/api/http_pb.js.map +0 -1
  19. package/dist/cjs/genproto/google/api/launch_stage_pb.js +0 -104
  20. package/dist/cjs/genproto/google/api/launch_stage_pb.js.map +0 -1
  21. package/dist/cjs/genproto/mochabugapis/adapt/automations/v1/automations_pb.js +0 -179
  22. package/dist/cjs/genproto/mochabugapis/adapt/automations/v1/automations_pb.js.map +0 -1
  23. package/dist/cjs/genproto/mochabugapis/adapt/graph/exchange_pb.js +0 -29
  24. package/dist/cjs/genproto/mochabugapis/adapt/graph/exchange_pb.js.map +0 -1
  25. package/dist/cjs/genproto/mochabugapis/adapt/graph/jtd_schema_pb.js +0 -29
  26. package/dist/cjs/genproto/mochabugapis/adapt/graph/jtd_schema_pb.js.map +0 -1
  27. package/dist/cjs/genproto/mochabugapis/adapt/graph/receiver_pb.js +0 -29
  28. package/dist/cjs/genproto/mochabugapis/adapt/graph/receiver_pb.js.map +0 -1
  29. package/dist/cjs/genproto/mochabugapis/adapt/graph/signal_binding_pb.js +0 -88
  30. package/dist/cjs/genproto/mochabugapis/adapt/graph/signal_binding_pb.js.map +0 -1
  31. package/dist/cjs/genproto/mochabugapis/adapt/graph/signal_data_pb.js +0 -28
  32. package/dist/cjs/genproto/mochabugapis/adapt/graph/signal_data_pb.js.map +0 -1
  33. package/dist/cjs/genproto/mochabugapis/adapt/graph/signal_descriptor_pb.js +0 -29
  34. package/dist/cjs/genproto/mochabugapis/adapt/graph/signal_descriptor_pb.js.map +0 -1
  35. package/dist/cjs/genproto/mochabugapis/adapt/graph/signal_format_pb.js +0 -29
  36. package/dist/cjs/genproto/mochabugapis/adapt/graph/signal_format_pb.js.map +0 -1
  37. package/dist/cjs/genproto/mochabugapis/adapt/graph/transceiver_pb.js +0 -29
  38. package/dist/cjs/genproto/mochabugapis/adapt/graph/transceiver_pb.js.map +0 -1
  39. package/dist/cjs/genproto/mochabugapis/adapt/graph/transmitter_pb.js +0 -65
  40. package/dist/cjs/genproto/mochabugapis/adapt/graph/transmitter_pb.js.map +0 -1
  41. package/dist/cjs/genproto/mochabugapis/adapt/graph/vertex_metadata_pb.js +0 -31
  42. package/dist/cjs/genproto/mochabugapis/adapt/graph/vertex_metadata_pb.js.map +0 -1
  43. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/compound_services_pb.js +0 -33
  44. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/compound_services_pb.js.map +0 -1
  45. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/file_pb.js +0 -28
  46. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/file_pb.js.map +0 -1
  47. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/http_proxy_service_pb.js +0 -105
  48. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/http_proxy_service_pb.js.map +0 -1
  49. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/manifest_pb.js +0 -30
  50. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/manifest_pb.js.map +0 -1
  51. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/oauth2_service_pb.js +0 -187
  52. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/oauth2_service_pb.js.map +0 -1
  53. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/plugins_pb.js +0 -48
  54. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/plugins_pb.js.map +0 -1
  55. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/service_definition_pb.js +0 -32
  56. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/service_definition_pb.js.map +0 -1
  57. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/service_settings_pb.js +0 -40
  58. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/service_settings_pb.js.map +0 -1
  59. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/variable_service_pb.js +0 -30
  60. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/variable_service_pb.js.map +0 -1
  61. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/vertex_pb.js +0 -79
  62. package/dist/cjs/genproto/mochabugapis/adapt/plugins/v1/vertex_pb.js.map +0 -1
  63. package/dist/cjs/genproto/mochabugapis/adapt/runtime/v1/incoming_pb.js +0 -74
  64. package/dist/cjs/genproto/mochabugapis/adapt/runtime/v1/incoming_pb.js.map +0 -1
  65. package/dist/cjs/genproto/mochabugapis/adapt/runtime/v1/runtime_pb.js +0 -442
  66. package/dist/cjs/genproto/mochabugapis/adapt/runtime/v1/runtime_pb.js.map +0 -1
  67. package/dist/cjs/genproto/mochabugapis/adapt/runtime/v1/store_pb.js +0 -94
  68. package/dist/cjs/genproto/mochabugapis/adapt/runtime/v1/store_pb.js.map +0 -1
  69. package/dist/cjs/index.js +0 -191
  70. package/dist/cjs/index.js.map +0 -1
  71. package/dist/cjs/pubsub-client.js +0 -566
  72. package/dist/cjs/pubsub-client.js.map +0 -1
  73. package/dist/esm/genproto/buf/validate/validate_pb.js +0 -352
  74. package/dist/esm/genproto/buf/validate/validate_pb.js.map +0 -1
  75. package/dist/esm/genproto/google/api/annotations_pb.js +0 -27
  76. package/dist/esm/genproto/google/api/annotations_pb.js.map +0 -1
  77. package/dist/esm/genproto/google/api/client_pb.js +0 -287
  78. package/dist/esm/genproto/google/api/client_pb.js.map +0 -1
  79. package/dist/esm/genproto/google/api/http_pb.js +0 -34
  80. package/dist/esm/genproto/google/api/http_pb.js.map +0 -1
  81. package/dist/esm/genproto/google/api/launch_stage_pb.js +0 -101
  82. package/dist/esm/genproto/google/api/launch_stage_pb.js.map +0 -1
  83. package/dist/esm/genproto/mochabugapis/adapt/automations/v1/automations_pb.js +0 -176
  84. package/dist/esm/genproto/mochabugapis/adapt/automations/v1/automations_pb.js.map +0 -1
  85. package/dist/esm/genproto/mochabugapis/adapt/graph/exchange_pb.js +0 -26
  86. package/dist/esm/genproto/mochabugapis/adapt/graph/exchange_pb.js.map +0 -1
  87. package/dist/esm/genproto/mochabugapis/adapt/graph/jtd_schema_pb.js +0 -26
  88. package/dist/esm/genproto/mochabugapis/adapt/graph/jtd_schema_pb.js.map +0 -1
  89. package/dist/esm/genproto/mochabugapis/adapt/graph/receiver_pb.js +0 -26
  90. package/dist/esm/genproto/mochabugapis/adapt/graph/receiver_pb.js.map +0 -1
  91. package/dist/esm/genproto/mochabugapis/adapt/graph/signal_binding_pb.js +0 -85
  92. package/dist/esm/genproto/mochabugapis/adapt/graph/signal_binding_pb.js.map +0 -1
  93. package/dist/esm/genproto/mochabugapis/adapt/graph/signal_data_pb.js +0 -25
  94. package/dist/esm/genproto/mochabugapis/adapt/graph/signal_data_pb.js.map +0 -1
  95. package/dist/esm/genproto/mochabugapis/adapt/graph/signal_descriptor_pb.js +0 -26
  96. package/dist/esm/genproto/mochabugapis/adapt/graph/signal_descriptor_pb.js.map +0 -1
  97. package/dist/esm/genproto/mochabugapis/adapt/graph/signal_format_pb.js +0 -26
  98. package/dist/esm/genproto/mochabugapis/adapt/graph/signal_format_pb.js.map +0 -1
  99. package/dist/esm/genproto/mochabugapis/adapt/graph/transceiver_pb.js +0 -26
  100. package/dist/esm/genproto/mochabugapis/adapt/graph/transceiver_pb.js.map +0 -1
  101. package/dist/esm/genproto/mochabugapis/adapt/graph/transmitter_pb.js +0 -62
  102. package/dist/esm/genproto/mochabugapis/adapt/graph/transmitter_pb.js.map +0 -1
  103. package/dist/esm/genproto/mochabugapis/adapt/graph/vertex_metadata_pb.js +0 -28
  104. package/dist/esm/genproto/mochabugapis/adapt/graph/vertex_metadata_pb.js.map +0 -1
  105. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/compound_services_pb.js +0 -30
  106. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/compound_services_pb.js.map +0 -1
  107. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/file_pb.js +0 -25
  108. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/file_pb.js.map +0 -1
  109. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/http_proxy_service_pb.js +0 -102
  110. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/http_proxy_service_pb.js.map +0 -1
  111. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/manifest_pb.js +0 -27
  112. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/manifest_pb.js.map +0 -1
  113. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/oauth2_service_pb.js +0 -184
  114. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/oauth2_service_pb.js.map +0 -1
  115. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/plugins_pb.js +0 -45
  116. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/plugins_pb.js.map +0 -1
  117. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/service_definition_pb.js +0 -29
  118. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/service_definition_pb.js.map +0 -1
  119. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/service_settings_pb.js +0 -37
  120. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/service_settings_pb.js.map +0 -1
  121. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/variable_service_pb.js +0 -27
  122. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/variable_service_pb.js.map +0 -1
  123. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/vertex_pb.js +0 -76
  124. package/dist/esm/genproto/mochabugapis/adapt/plugins/v1/vertex_pb.js.map +0 -1
  125. package/dist/esm/genproto/mochabugapis/adapt/runtime/v1/incoming_pb.js +0 -71
  126. package/dist/esm/genproto/mochabugapis/adapt/runtime/v1/incoming_pb.js.map +0 -1
  127. package/dist/esm/genproto/mochabugapis/adapt/runtime/v1/runtime_pb.js +0 -438
  128. package/dist/esm/genproto/mochabugapis/adapt/runtime/v1/runtime_pb.js.map +0 -1
  129. package/dist/esm/genproto/mochabugapis/adapt/runtime/v1/store_pb.js +0 -91
  130. package/dist/esm/genproto/mochabugapis/adapt/runtime/v1/store_pb.js.map +0 -1
  131. package/dist/esm/pubsub-client.js +0 -559
  132. package/dist/esm/pubsub-client.js.map +0 -1
  133. package/dist/types/genproto/buf/validate/validate_pb.d.ts +0 -8490
  134. package/dist/types/genproto/google/api/annotations_pb.d.ts +0 -13
  135. package/dist/types/genproto/google/api/client_pb.d.ts +0 -1431
  136. package/dist/types/genproto/google/api/http_pb.d.ts +0 -842
  137. package/dist/types/genproto/google/api/launch_stage_pb.d.ts +0 -93
  138. package/dist/types/genproto/mochabugapis/adapt/automations/v1/automations_pb.d.ts +0 -1043
  139. package/dist/types/genproto/mochabugapis/adapt/graph/exchange_pb.d.ts +0 -76
  140. package/dist/types/genproto/mochabugapis/adapt/graph/jtd_schema_pb.d.ts +0 -400
  141. package/dist/types/genproto/mochabugapis/adapt/graph/receiver_pb.d.ts +0 -68
  142. package/dist/types/genproto/mochabugapis/adapt/graph/signal_binding_pb.d.ts +0 -429
  143. package/dist/types/genproto/mochabugapis/adapt/graph/signal_data_pb.d.ts +0 -197
  144. package/dist/types/genproto/mochabugapis/adapt/graph/signal_descriptor_pb.d.ts +0 -160
  145. package/dist/types/genproto/mochabugapis/adapt/graph/signal_format_pb.d.ts +0 -304
  146. package/dist/types/genproto/mochabugapis/adapt/graph/transceiver_pb.d.ts +0 -76
  147. package/dist/types/genproto/mochabugapis/adapt/graph/transmitter_pb.d.ts +0 -119
  148. package/dist/types/genproto/mochabugapis/adapt/graph/vertex_metadata_pb.d.ts +0 -98
  149. package/dist/types/genproto/mochabugapis/adapt/plugins/v1/compound_services_pb.d.ts +0 -346
  150. package/dist/types/genproto/mochabugapis/adapt/plugins/v1/file_pb.d.ts +0 -63
  151. package/dist/types/genproto/mochabugapis/adapt/plugins/v1/http_proxy_service_pb.d.ts +0 -1281
  152. package/dist/types/genproto/mochabugapis/adapt/plugins/v1/manifest_pb.d.ts +0 -387
  153. package/dist/types/genproto/mochabugapis/adapt/plugins/v1/oauth2_service_pb.d.ts +0 -804
  154. package/dist/types/genproto/mochabugapis/adapt/plugins/v1/plugins_pb.d.ts +0 -237
  155. package/dist/types/genproto/mochabugapis/adapt/plugins/v1/service_definition_pb.d.ts +0 -240
  156. package/dist/types/genproto/mochabugapis/adapt/plugins/v1/service_settings_pb.d.ts +0 -538
  157. package/dist/types/genproto/mochabugapis/adapt/plugins/v1/variable_service_pb.d.ts +0 -189
  158. package/dist/types/genproto/mochabugapis/adapt/plugins/v1/vertex_pb.d.ts +0 -268
  159. package/dist/types/genproto/mochabugapis/adapt/runtime/v1/incoming_pb.d.ts +0 -338
  160. package/dist/types/genproto/mochabugapis/adapt/runtime/v1/runtime_pb.d.ts +0 -2720
  161. package/dist/types/genproto/mochabugapis/adapt/runtime/v1/store_pb.d.ts +0 -871
  162. package/dist/types/pubsub-client.d.ts +0 -59
package/dist/esm/index.js CHANGED
@@ -1,164 +1,966 @@
1
- // Re-export from the new PubsubClient module
2
- export * from "./pubsub-client.js";
3
- // Default configuration
4
- const defaultConfig = {
5
- baseUrl: "https://adapt-dev.mochabugapis.com/v1/automations",
6
- wsBaseUrl: "wss://adapt-dev.mochabugapis.com/v1/automations",
7
- };
8
- // Global configuration
9
- let globalConfig = { ...defaultConfig };
10
- // Configure the Adapt client
11
- export function configure(config) {
12
- globalConfig = { ...globalConfig, ...config };
13
- }
14
- // Get current configuration
15
- export function getConfig() {
16
- return { ...globalConfig };
17
- }
18
- // Reset to default configuration
19
- export function resetConfig() {
20
- globalConfig = { ...defaultConfig };
21
- }
22
- // Retry configuration
23
- const RETRY_CONFIG = {
24
- maxAttempts: 5,
25
- initialDelay: 50, // 50ms
26
- maxDelay: 5000, // 5 seconds
27
- retryableStatusCodes: [429, 502, 503, 504], // Too Many Requests, Bad Gateway, Service Unavailable, Gateway Timeout
28
- };
29
- // Sleep helper
30
- function sleep(ms) {
31
- return new Promise((resolve) => setTimeout(resolve, ms));
32
- }
33
- // Retry wrapper with exponential backoff
34
- async function fetchWithRetry(url, options) {
35
- let lastError;
36
- for (let attempt = 1; attempt <= RETRY_CONFIG.maxAttempts; attempt++) {
37
- try {
38
- const response = await fetch(url, options);
39
- if (response.ok) {
40
- return response;
41
- }
42
- if (RETRY_CONFIG.retryableStatusCodes.includes(response.status)) {
43
- lastError = new RestClientError(response);
44
- if (attempt < RETRY_CONFIG.maxAttempts) {
45
- const delay = Math.min(RETRY_CONFIG.initialDelay * Math.pow(2, attempt - 1), RETRY_CONFIG.maxDelay);
46
- console.warn(`Request failed with ${response.status}, retrying in ${delay}ms (attempt ${attempt}/${RETRY_CONFIG.maxAttempts})`);
47
- await sleep(delay);
48
- continue;
1
+ import { inheritSession, PubsubClient, startSession, stopSession, } from "@mochabug/adapt-core";
2
+ /**
3
+ * Default CSS styles with CSS Custom Properties for theming.
4
+ */
5
+ const DEFAULT_STYLES = `
6
+ .mb-adapt {
7
+ width: 100%;
8
+ height: 100%;
9
+ --mb-adapt-border-radius: 8px;
10
+ --mb-adapt-backdrop-color: rgba(0, 0, 0, 0.5);
11
+ --mb-adapt-dialog-bg: transparent;
12
+ --mb-adapt-backdrop-z: 999;
13
+ --mb-adapt-dialog-z: 1000;
14
+ --mb-adapt-dialog-width: 80%;
15
+ --mb-adapt-dialog-height: 80%;
16
+ --mb-adapt-drag-handle-width: 6px;
17
+ --mb-adapt-drag-handle-color: #d1d5db;
18
+ --mb-adapt-drag-handle-hover: #6b7280;
19
+ --mb-adapt-banner-height: 40px;
20
+ --mb-adapt-banner-bg: #f9fafb;
21
+ --mb-adapt-banner-border: #e5e7eb;
22
+ --mb-adapt-button-color: #374151;
23
+ --mb-adapt-button-hover-bg: #e5e7eb;
24
+ }
25
+
26
+ .mb-adapt__wrapper {
27
+ position: relative;
28
+ display: flex;
29
+ width: 100%;
30
+ height: 100%;
31
+ }
32
+
33
+ .mb-adapt__frame {
34
+ position: relative;
35
+ min-width: 0;
36
+ overflow: hidden;
37
+ transition: width 0.15s ease-out;
38
+ }
39
+
40
+ .mb-adapt__iframe {
41
+ width: 100%;
42
+ height: 100%;
43
+ border: 0;
44
+ display: block;
45
+ border-radius: var(--mb-adapt-border-radius);
46
+ pointer-events: auto;
47
+ }
48
+
49
+ .mb-adapt__drag-handle {
50
+ position: absolute;
51
+ top: 0;
52
+ bottom: 0;
53
+ width: var(--mb-adapt-drag-handle-width);
54
+ background-color: var(--mb-adapt-drag-handle-color);
55
+ cursor: ew-resize;
56
+ z-index: 10;
57
+ transition: background-color 0.2s, left 0.15s ease-out;
58
+ }
59
+
60
+ .mb-adapt__drag-handle:hover {
61
+ background-color: var(--mb-adapt-drag-handle-hover);
62
+ }
63
+
64
+ .mb-adapt__drag-overlay {
65
+ position: absolute;
66
+ inset: 0;
67
+ z-index: 9999;
68
+ cursor: ew-resize;
69
+ }
70
+
71
+ .mb-adapt__iframe-overlay {
72
+ position: absolute;
73
+ inset: 0;
74
+ z-index: 5;
75
+ }
76
+
77
+ .mb-adapt__dialog-backdrop {
78
+ position: fixed;
79
+ inset: 0;
80
+ background-color: var(--mb-adapt-backdrop-color);
81
+ z-index: var(--mb-adapt-backdrop-z);
82
+ display: none;
83
+ }
84
+
85
+ .mb-adapt__dialog-backdrop--visible {
86
+ display: block;
87
+ }
88
+
89
+ .mb-adapt__dialog {
90
+ position: fixed;
91
+ top: 50%;
92
+ left: 50%;
93
+ transform: translate(-50%, -50%);
94
+ width: var(--mb-adapt-dialog-width);
95
+ height: var(--mb-adapt-dialog-height);
96
+ background-color: var(--mb-adapt-dialog-bg);
97
+ border-radius: var(--mb-adapt-border-radius);
98
+ z-index: var(--mb-adapt-dialog-z);
99
+ overflow: hidden;
100
+ flex-direction: column;
101
+ display: none;
102
+ }
103
+
104
+ .mb-adapt__dialog--visible {
105
+ display: flex;
106
+ }
107
+
108
+ .mb-adapt__dialog-banner {
109
+ height: var(--mb-adapt-banner-height);
110
+ background-color: var(--mb-adapt-banner-bg);
111
+ border-bottom: 1px solid var(--mb-adapt-banner-border);
112
+ display: flex;
113
+ align-items: center;
114
+ justify-content: flex-end;
115
+ padding: 0 8px;
116
+ flex-shrink: 0;
117
+ }
118
+
119
+ .mb-adapt__dialog-close {
120
+ background: none;
121
+ border: none;
122
+ color: var(--mb-adapt-button-color);
123
+ cursor: pointer;
124
+ font-size: 20px;
125
+ width: 32px;
126
+ height: 32px;
127
+ display: flex;
128
+ align-items: center;
129
+ justify-content: center;
130
+ border-radius: 4px;
131
+ transition: background-color 0.2s;
132
+ }
133
+
134
+ .mb-adapt__dialog-close:hover {
135
+ background-color: var(--mb-adapt-button-hover-bg);
136
+ }
137
+
138
+ .mb-adapt__expand-button {
139
+ position: absolute;
140
+ top: 50%;
141
+ transform: translateY(-50%);
142
+ background: linear-gradient(180deg, rgba(255,255,255,0.98) 0%, rgba(248,250,252,0.98) 100%);
143
+ border: none;
144
+ color: #64748b;
145
+ cursor: pointer;
146
+ width: 14px;
147
+ height: 48px;
148
+ display: none;
149
+ align-items: center;
150
+ justify-content: center;
151
+ z-index: 100;
152
+ transition: all 0.2s ease-out;
153
+ font-size: 14px;
154
+ line-height: 1;
155
+ padding: 0;
156
+ box-shadow:
157
+ 0 2px 8px rgba(0, 0, 0, 0.12),
158
+ 0 1px 3px rgba(0, 0, 0, 0.08),
159
+ inset 0 1px 0 rgba(255, 255, 255, 0.8);
160
+ border-radius: 4px;
161
+ backdrop-filter: blur(8px);
162
+ -webkit-backdrop-filter: blur(8px);
163
+ }
164
+
165
+ .mb-adapt__expand-button:hover {
166
+ background: linear-gradient(180deg, rgba(255,255,255,1) 0%, rgba(241,245,249,1) 100%);
167
+ color: #475569;
168
+ transform: translateY(-50%) scale(1.02);
169
+ box-shadow:
170
+ 0 4px 12px rgba(0, 0, 0, 0.15),
171
+ 0 2px 4px rgba(0, 0, 0, 0.1),
172
+ inset 0 1px 0 rgba(255, 255, 255, 1);
173
+ }
174
+
175
+ .mb-adapt__expand-button:active {
176
+ transform: translateY(-50%) scale(0.98);
177
+ box-shadow:
178
+ 0 1px 4px rgba(0, 0, 0, 0.1),
179
+ 0 1px 2px rgba(0, 0, 0, 0.06);
180
+ }
181
+
182
+ .mb-adapt__expand-button--visible {
183
+ display: flex !important;
184
+ }
185
+
186
+ .mb-adapt__expand-button--left {
187
+ left: 0;
188
+ border-top-left-radius: 0;
189
+ border-bottom-left-radius: 0;
190
+ box-shadow:
191
+ 2px 2px 8px rgba(0, 0, 0, 0.12),
192
+ 1px 1px 3px rgba(0, 0, 0, 0.08),
193
+ inset 0 1px 0 rgba(255, 255, 255, 0.8);
194
+ }
195
+
196
+ .mb-adapt__expand-button--left:hover {
197
+ box-shadow:
198
+ 3px 4px 12px rgba(0, 0, 0, 0.15),
199
+ 2px 2px 4px rgba(0, 0, 0, 0.1),
200
+ inset 0 1px 0 rgba(255, 255, 255, 1);
201
+ }
202
+
203
+ .mb-adapt__expand-button--right {
204
+ right: 0;
205
+ border-top-right-radius: 0;
206
+ border-bottom-right-radius: 0;
207
+ box-shadow:
208
+ -2px 2px 8px rgba(0, 0, 0, 0.12),
209
+ -1px 1px 3px rgba(0, 0, 0, 0.08),
210
+ inset 0 1px 0 rgba(255, 255, 255, 0.8);
211
+ }
212
+
213
+ .mb-adapt__expand-button--right:hover {
214
+ box-shadow:
215
+ -3px 4px 12px rgba(0, 0, 0, 0.15),
216
+ -2px 2px 4px rgba(0, 0, 0, 0.1),
217
+ inset 0 1px 0 rgba(255, 255, 255, 1);
218
+ }
219
+
220
+ .mb-adapt__expand-button--dialog {
221
+ left: 50%;
222
+ top: 0;
223
+ transform: translateX(-50%);
224
+ width: 56px;
225
+ height: 20px;
226
+ font-size: 16px;
227
+ line-height: 20px;
228
+ vertical-align: middle;
229
+ text-align: center;
230
+ border-radius: 6px;
231
+ border-top-left-radius: 0;
232
+ border-top-right-radius: 0;
233
+ box-shadow:
234
+ 0 3px 8px rgba(0, 0, 0, 0.12),
235
+ 0 1px 3px rgba(0, 0, 0, 0.08),
236
+ inset 0 1px 0 rgba(255, 255, 255, 0.8);
237
+ }
238
+
239
+ .mb-adapt__expand-button--dialog:hover {
240
+ transform: translateX(-50%) scale(1.02);
241
+ box-shadow:
242
+ 0 5px 12px rgba(0, 0, 0, 0.15),
243
+ 0 2px 4px rgba(0, 0, 0, 0.1),
244
+ inset 0 1px 0 rgba(255, 255, 255, 1);
245
+ }
246
+
247
+ .mb-adapt__expand-button--dialog:active {
248
+ transform: translateX(-50%) scale(0.98);
249
+ }
250
+
251
+ .mb-adapt__drag-handle--disabled {
252
+ pointer-events: none;
253
+ opacity: 0.3;
254
+ }
255
+
256
+ .mb-adapt__main-container {
257
+ position: relative;
258
+ width: 100%;
259
+ height: 100%;
260
+ overflow: visible;
261
+ }
262
+
263
+ /* Responsive dialog - full screen on small viewports */
264
+ @media (max-width: 600px) {
265
+ .mb-adapt__dialog {
266
+ width: 100%;
267
+ height: 100%;
268
+ border-radius: 0;
269
+ top: 0;
270
+ left: 0;
271
+ transform: none;
272
+ }
273
+ }
274
+ `;
275
+ /**
276
+ * Browser client for rendering Adapt automation sessions in iframes.
277
+ *
278
+ * Architecture:
279
+ * - Keeps all iframes mounted, just toggles visibility
280
+ * - Uses visibility toggling instead of DOM destruction
281
+ * - Immediate snap when reaching collapse threshold during drag
282
+ */
283
+ export class AdaptWebClient {
284
+ constructor(options) {
285
+ this.rootElement = null;
286
+ this.mainUrl = null;
287
+ this.forkQueue = [];
288
+ this.currentFork = null;
289
+ this.sessionToken = null;
290
+ this.isDragging = false;
291
+ // Persistent DOM elements - created once, reused always
292
+ this.wrapperElement = null;
293
+ this.mainFrameElement = null;
294
+ this.forkFrameElement = null;
295
+ this.mainIframe = null;
296
+ this.forkIframe = null;
297
+ this.dragHandleElement = null;
298
+ this.mainExpandButton = null;
299
+ this.forkExpandButton = null;
300
+ // Dialog elements
301
+ this.mainContainer = null;
302
+ this.dialogBackdrop = null;
303
+ this.dialogElement = null;
304
+ this.dialogExpandButton = null;
305
+ // Event listener references for cleanup
306
+ this.mouseMoveHandler = null;
307
+ this.mouseUpHandler = null;
308
+ this.resizeObserver = null;
309
+ this.destroyed = false;
310
+ this.options = {
311
+ ...options,
312
+ forkDisplayMode: options.forkDisplayMode ?? "side-by-side",
313
+ };
314
+ this.splitPercentage = options.sideBySideSplit ?? 50;
315
+ const container = document.getElementById(options.container);
316
+ if (!container) {
317
+ throw new Error(`Container with id '${options.container}' not found`);
318
+ }
319
+ this.container = container;
320
+ this.pubsub = new PubsubClient(false);
321
+ this.injectDefaultStyles();
322
+ this.createRootElement();
323
+ this.setupDragListeners();
324
+ this.setupResizeObserver();
325
+ this.init();
326
+ }
327
+ setupResizeObserver() {
328
+ if (!this.rootElement)
329
+ return;
330
+ this.resizeObserver = new ResizeObserver(() => {
331
+ if (this.options.forkDisplayMode === "side-by-side" && this.currentFork) {
332
+ this.updateSideBySideVisibility();
333
+ }
334
+ });
335
+ this.resizeObserver.observe(this.rootElement);
336
+ }
337
+ setupDragListeners() {
338
+ let unclampedSplit = this.splitPercentage;
339
+ let wasCollapsed = false;
340
+ const handleMouseMove = (e) => {
341
+ if (!this.isDragging || !this.rootElement)
342
+ return;
343
+ const rect = this.rootElement.getBoundingClientRect();
344
+ if (rect.width === 0)
345
+ return; // Prevent division by zero
346
+ const offsetX = e.clientX - rect.left;
347
+ unclampedSplit = (offsetX / rect.width) * 100;
348
+ // Check if we should snap to collapsed state
349
+ const mainWidth = unclampedSplit;
350
+ const forkWidth = 100 - unclampedSplit;
351
+ if (mainWidth < AdaptWebClient.COLLAPSE_THRESHOLD) {
352
+ // Snap to collapsed left
353
+ if (!wasCollapsed) {
354
+ wasCollapsed = true;
355
+ this.splitPercentage = 0;
356
+ this.updateSideBySideVisibility();
357
+ }
358
+ }
359
+ else if (forkWidth < AdaptWebClient.COLLAPSE_THRESHOLD) {
360
+ // Snap to collapsed right
361
+ if (!wasCollapsed) {
362
+ wasCollapsed = true;
363
+ this.splitPercentage = 100;
364
+ this.updateSideBySideVisibility();
49
365
  }
50
366
  }
51
- throw new RestClientError(response);
52
- }
53
- catch (error) {
54
- if (error instanceof RestClientError) {
55
- throw error;
56
- }
57
- if (attempt < RETRY_CONFIG.maxAttempts) {
58
- const delay = Math.min(RETRY_CONFIG.initialDelay * Math.pow(2, attempt - 1), RETRY_CONFIG.maxDelay);
59
- console.warn(`Network error, retrying in ${delay}ms (attempt ${attempt}/${RETRY_CONFIG.maxAttempts})`, error);
60
- await sleep(delay);
61
- continue;
62
- }
63
- throw error;
64
- }
65
- }
66
- throw lastError || new Error("All retry attempts failed");
67
- }
68
- // REST API functions
69
- export async function startSession(req, token) {
70
- const headers = new Headers({
71
- "Content-Type": "application/json",
72
- "Response-Type": "application/json",
73
- });
74
- if (token) {
75
- headers.set("Authorization", `Bearer ${token}`);
76
- }
77
- const response = await fetchWithRetry(`${globalConfig.baseUrl}/${req.id}/session/start`, {
78
- method: "POST",
79
- body: JSON.stringify(req),
80
- headers,
81
- });
82
- return await response.json();
83
- }
84
- export async function inheritSession(id, sessionToken) {
85
- const response = await fetchWithRetry(`${globalConfig.baseUrl}/${id}/session/inherit`, {
86
- method: "POST",
87
- body: JSON.stringify({ id }),
88
- headers: {
89
- "Content-Type": "application/json",
90
- "Response-Type": "application/json",
91
- Authorization: `Bearer ${sessionToken}`,
92
- },
93
- });
94
- return await response.json();
95
- }
96
- export async function getSession(id, sessionToken) {
97
- const response = await fetchWithRetry(`${globalConfig.baseUrl}/${id}/session`, {
98
- method: "GET",
99
- headers: {
100
- "Response-Type": "application/json",
101
- Authorization: `Bearer ${sessionToken}`,
102
- },
103
- });
104
- return await response.json();
105
- }
106
- export async function readOutput(id, sessionToken, options) {
107
- const params = new URLSearchParams();
108
- if (options?.pageSize !== undefined) {
109
- params.set("page_size", options.pageSize.toString());
110
- }
111
- if (options?.vertex) {
112
- params.set("vertex", options.vertex);
113
- }
114
- if (options?.newerThan) {
115
- params.set("newer_than", options.newerThan);
116
- }
117
- const queryString = params.toString();
118
- const url = `${globalConfig.baseUrl}/${id}/session/output${queryString ? `?${queryString}` : ""}`;
119
- const response = await fetchWithRetry(url, {
120
- method: "GET",
121
- headers: {
122
- "Response-Type": "application/json",
123
- Authorization: `Bearer ${sessionToken}`,
124
- },
125
- });
126
- return await response.json();
127
- }
128
- export async function readUrls(id, sessionToken, options) {
129
- const params = new URLSearchParams();
130
- if (options?.pageSize !== undefined) {
131
- params.set("page_size", options.pageSize.toString());
132
- }
133
- if (options?.newerThan) {
134
- params.set("newer_than", options.newerThan);
135
- }
136
- const queryString = params.toString();
137
- const url = `${globalConfig.baseUrl}/${id}/session/urls${queryString ? `?${queryString}` : ""}`;
138
- const response = await fetchWithRetry(url, {
139
- method: "GET",
140
- headers: {
141
- "Response-Type": "application/json",
142
- Authorization: `Bearer ${sessionToken}`,
143
- },
144
- });
145
- return await response.json();
146
- }
147
- export async function stopSession(id, sessionToken) {
148
- await fetchWithRetry(`${globalConfig.baseUrl}/${id}/session`, {
149
- method: "DELETE",
150
- headers: {
151
- Authorization: `Bearer ${sessionToken}`,
152
- },
153
- });
154
- }
155
- export class RestClientError extends Error {
156
- constructor(response) {
157
- super(`HTTP Error: ${response.status} ${response.statusText}`);
158
- this.name = "RestClientError";
159
- this.status = response.status;
160
- this.statusText = response.statusText;
161
- this.response = response;
367
+ else {
368
+ // Normal drag - clamp to prevent collapse
369
+ wasCollapsed = false;
370
+ this.splitPercentage = Math.max(AdaptWebClient.COLLAPSE_THRESHOLD, Math.min(100 - AdaptWebClient.COLLAPSE_THRESHOLD, unclampedSplit));
371
+ this.updateSideBySideWidths();
372
+ }
373
+ };
374
+ const handleMouseUp = () => {
375
+ if (!this.isDragging)
376
+ return;
377
+ this.isDragging = false;
378
+ wasCollapsed = false;
379
+ document.getElementById("mb-adapt-drag-overlay")?.remove();
380
+ this.rootElement
381
+ ?.querySelectorAll(".mb-adapt__iframe-overlay")
382
+ .forEach((el) => el.remove());
383
+ // Re-enable transitions after drag
384
+ if (this.mainFrameElement)
385
+ this.mainFrameElement.style.transition = "";
386
+ if (this.forkFrameElement)
387
+ this.forkFrameElement.style.transition = "";
388
+ if (this.dragHandleElement)
389
+ this.dragHandleElement.style.transition = "";
390
+ // Finalize position - use unclamped value if not collapsed
391
+ if (this.splitPercentage !== 0 &&
392
+ this.splitPercentage !== 100 &&
393
+ unclampedSplit >= AdaptWebClient.COLLAPSE_THRESHOLD &&
394
+ 100 - unclampedSplit >= AdaptWebClient.COLLAPSE_THRESHOLD) {
395
+ this.splitPercentage = unclampedSplit;
396
+ }
397
+ // Reset for next drag
398
+ unclampedSplit = this.splitPercentage;
399
+ };
400
+ this.mouseMoveHandler = handleMouseMove;
401
+ this.mouseUpHandler = handleMouseUp;
402
+ document.addEventListener("mousemove", this.mouseMoveHandler);
403
+ document.addEventListener("mouseup", this.mouseUpHandler);
404
+ }
405
+ injectDefaultStyles() {
406
+ if (document.getElementById("mb-adapt-styles"))
407
+ return;
408
+ const style = document.createElement("style");
409
+ style.id = "mb-adapt-styles";
410
+ style.textContent = DEFAULT_STYLES;
411
+ document.head.appendChild(style);
412
+ }
413
+ createRootElement() {
414
+ this.rootElement = document.createElement("div");
415
+ this.rootElement.className = this.options.classNames?.root || "mb-adapt";
416
+ if (this.options.styles) {
417
+ Object.assign(this.rootElement.style, this.options.styles);
418
+ }
419
+ this.container.appendChild(this.rootElement);
420
+ }
421
+ parseInheritToken() {
422
+ const inheritFrom = this.options.inheritFrom;
423
+ if (!inheritFrom)
424
+ return null;
425
+ if ("hash" in inheritFrom) {
426
+ return this.parseFromHash(inheritFrom.hash);
427
+ }
428
+ else {
429
+ return this.parseFromParam(inheritFrom.param);
430
+ }
431
+ }
432
+ parseFromHash(key) {
433
+ const hash = window.location.hash.slice(1); // Remove leading #
434
+ if (!hash)
435
+ return null;
436
+ const params = new URLSearchParams(hash);
437
+ const token = params.get(key);
438
+ if (!token)
439
+ return null;
440
+ // Remove the key from hash and clean URL
441
+ params.delete(key);
442
+ const newHash = params.toString();
443
+ const newUrl = window.location.pathname +
444
+ window.location.search +
445
+ (newHash ? "#" + newHash : "");
446
+ history.replaceState(null, "", newUrl);
447
+ return decodeURIComponent(token);
448
+ }
449
+ parseFromParam(key) {
450
+ const params = new URLSearchParams(window.location.search);
451
+ const token = params.get(key);
452
+ if (!token)
453
+ return null;
454
+ // Remove the key from params and clean URL
455
+ params.delete(key);
456
+ const newSearch = params.toString();
457
+ const newUrl = window.location.pathname +
458
+ (newSearch ? "?" + newSearch : "") +
459
+ window.location.hash;
460
+ history.replaceState(null, "", newUrl);
461
+ return decodeURIComponent(token);
462
+ }
463
+ async init() {
464
+ // Priority: sessionToken > inheritToken/inheritFrom > authToken
465
+ if (this.options.sessionToken) {
466
+ // Use pre-created session token directly (server-side scenario)
467
+ this.sessionToken = this.options.sessionToken;
468
+ }
469
+ else {
470
+ // Determine inherit token: URL-parsed takes precedence over option
471
+ const urlToken = this.parseInheritToken();
472
+ const inheritToken = urlToken || this.options.inheritToken;
473
+ // If inheritFrom was specified but no token found in URL, error out
474
+ if (this.options.inheritFrom && !urlToken) {
475
+ const source = "hash" in this.options.inheritFrom
476
+ ? `hash key '${this.options.inheritFrom.hash}'`
477
+ : `param '${this.options.inheritFrom.param}'`;
478
+ console.error(`[AdaptWebClient] No inherit token found in URL ${source}`);
479
+ return;
480
+ }
481
+ // Either inherit existing session or start new one
482
+ let result;
483
+ if (inheritToken) {
484
+ result = await inheritSession(this.options.id, inheritToken);
485
+ }
486
+ else {
487
+ const req = {
488
+ id: this.options.id,
489
+ };
490
+ if (this.options.transmitter) {
491
+ req.transmitter = this.options.transmitter;
492
+ }
493
+ if (this.options.signals) {
494
+ req.signals = this.options.signals;
495
+ }
496
+ result = await startSession(req, this.options.authToken);
497
+ }
498
+ this.sessionToken = result.token;
499
+ }
500
+ const subscribeOptions = {
501
+ id: this.options.id,
502
+ sessionToken: this.sessionToken,
503
+ onUrl: (msg) => this.onUrl(msg),
504
+ onSession: (sessionJson) => {
505
+ // Handle session completion - minimize all forks, show only main
506
+ if (sessionJson.status === "STATUS_COMPLETED" && !sessionJson.fork) {
507
+ this.handleSessionComplete();
508
+ }
509
+ if (this.options.onSession) {
510
+ this.options.onSession(sessionJson.status || "STATUS_UNSPECIFIED", sessionJson.fork);
511
+ }
512
+ },
513
+ };
514
+ if (this.options.onOutput) {
515
+ subscribeOptions.onOutput = this.options.onOutput;
516
+ }
517
+ await this.pubsub.subscribe(subscribeOptions);
518
+ }
519
+ async destroy() {
520
+ this.destroyed = true;
521
+ // We stop best-effort. Sometimes you will get perm denied etc...
522
+ if (this.sessionToken) {
523
+ stopSession(this.options.id, this.sessionToken);
524
+ }
525
+ await this.pubsub.unsubscribe();
526
+ // Remove event listeners to prevent memory leaks
527
+ if (this.mouseMoveHandler) {
528
+ document.removeEventListener("mousemove", this.mouseMoveHandler);
529
+ }
530
+ if (this.mouseUpHandler) {
531
+ document.removeEventListener("mouseup", this.mouseUpHandler);
532
+ }
533
+ if (this.resizeObserver) {
534
+ this.resizeObserver.disconnect();
535
+ }
536
+ this.rootElement?.parentNode?.removeChild(this.rootElement);
537
+ // Don't remove shared styles - they're reused across instances
538
+ // Clear internal state
539
+ this.mainUrl = null;
540
+ this.mainToken = undefined;
541
+ this.forkQueue = [];
542
+ this.currentFork = null;
543
+ this.sessionToken = null;
544
+ this.rootElement = null;
545
+ this.wrapperElement = null;
546
+ this.mainFrameElement = null;
547
+ this.forkFrameElement = null;
548
+ this.mainIframe = null;
549
+ this.forkIframe = null;
550
+ this.dragHandleElement = null;
551
+ this.mainExpandButton = null;
552
+ this.forkExpandButton = null;
553
+ this.mainContainer = null;
554
+ this.dialogBackdrop = null;
555
+ this.dialogElement = null;
556
+ this.dialogExpandButton = null;
557
+ this.mouseMoveHandler = null;
558
+ this.mouseUpHandler = null;
559
+ this.resizeObserver = null;
560
+ }
561
+ onUrl(msg) {
562
+ if (this.destroyed)
563
+ return;
564
+ const fork = msg.fork || "";
565
+ if (msg.done) {
566
+ this.handleDoneMessage(fork);
567
+ return;
568
+ }
569
+ if (!msg.url)
570
+ return;
571
+ if (!fork) {
572
+ // Main URL update - never affects dialog open/close state
573
+ this.handleMainUrl(msg.url, msg.token);
574
+ }
575
+ else {
576
+ // Fork URL - should open dialog
577
+ this.handleForkUrl(msg.url, msg.token, fork);
578
+ }
579
+ }
580
+ handleSessionComplete() {
581
+ // Clear all forks and minimize to show only main frame
582
+ this.currentFork = null;
583
+ this.forkQueue = [];
584
+ if (this.options.forkDisplayMode === "side-by-side") {
585
+ this.updateSideBySideVisibility();
586
+ }
587
+ else if (this.options.forkDisplayMode === "dialog") {
588
+ this.updateDialogVisibility();
589
+ }
590
+ }
591
+ handleDoneMessage(fork) {
592
+ if (!fork) {
593
+ return;
594
+ }
595
+ // Remove from queue
596
+ this.forkQueue = this.forkQueue.filter((item) => item.fork !== fork);
597
+ // If current fork is done, clear tracking but keep iframe mounted
598
+ // Then check if there's another fork waiting
599
+ if (this.currentFork?.fork === fork) {
600
+ this.currentFork = null;
601
+ // Check if there's another fork in queue to display
602
+ if (this.forkQueue.length > 0) {
603
+ this.activateNextFork();
604
+ }
605
+ // If no more forks, iframe stays mounted but we don't close dialog
606
+ // Dialog will close when user clicks close or backdrop
607
+ }
608
+ }
609
+ handleMainUrl(url, token) {
610
+ this.mainUrl = url;
611
+ this.mainToken = token;
612
+ // Update main iframe only - never touch dialog state
613
+ this.updateMainIframe();
614
+ }
615
+ handleForkUrl(url, token, fork) {
616
+ const depth = (fork.match(/\//g) || []).length;
617
+ const forkItem = {
618
+ url,
619
+ token,
620
+ fork,
621
+ depth,
622
+ time: Date.now(),
623
+ };
624
+ // If no main URL yet, use fork as main temporarily
625
+ if (!this.mainUrl) {
626
+ this.mainUrl = url;
627
+ this.mainToken = token;
628
+ this.updateMainIframe();
629
+ }
630
+ // Add to queue and activate if no current fork
631
+ this.forkQueue.push(forkItem);
632
+ if (!this.currentFork) {
633
+ this.activateNextFork();
634
+ }
635
+ }
636
+ activateNextFork() {
637
+ if (this.forkQueue.length === 0)
638
+ return;
639
+ // Sort: deepest first, then newest
640
+ this.forkQueue.sort((a, b) => {
641
+ if (a.depth !== b.depth)
642
+ return b.depth - a.depth;
643
+ return b.time - a.time;
644
+ });
645
+ this.currentFork = this.forkQueue.shift();
646
+ // Update fork iframe and show dialog
647
+ this.updateForkIframe();
648
+ if (this.options.forkDisplayMode === "dialog") {
649
+ this.updateDialogVisibility();
650
+ }
651
+ else {
652
+ this.updateSideBySideVisibility();
653
+ }
654
+ }
655
+ updateMainIframe() {
656
+ if (!this.rootElement || !this.mainUrl)
657
+ return;
658
+ // Ensure structure exists
659
+ if (this.options.forkDisplayMode === "dialog") {
660
+ if (!this.mainContainer) {
661
+ this.createDialogStructure();
662
+ }
663
+ // Update main iframe if URL changed
664
+ const newSrc = this.getIframeSrc(this.mainUrl, this.mainToken);
665
+ if (!this.mainIframe || this.mainIframe.src !== newSrc) {
666
+ this.mainIframe = this.createIframe(this.mainUrl, this.mainToken);
667
+ const oldIframe = this.mainContainer.querySelector(".mb-adapt__iframe");
668
+ if (oldIframe)
669
+ oldIframe.remove();
670
+ this.mainContainer.insertBefore(this.mainIframe, this.mainContainer.firstChild);
671
+ }
672
+ }
673
+ else {
674
+ // Side-by-side
675
+ if (!this.wrapperElement) {
676
+ this.createSideBySideStructure();
677
+ }
678
+ const newSrc = this.getIframeSrc(this.mainUrl, this.mainToken);
679
+ if (!this.mainIframe || this.mainIframe.src !== newSrc) {
680
+ this.mainIframe = this.createIframe(this.mainUrl, this.mainToken);
681
+ this.mainFrameElement.innerHTML = "";
682
+ this.mainFrameElement.appendChild(this.mainIframe);
683
+ }
684
+ this.updateSideBySideVisibility();
685
+ }
686
+ }
687
+ updateForkIframe() {
688
+ if (!this.currentFork)
689
+ return;
690
+ const newSrc = this.getIframeSrc(this.currentFork.url, this.currentFork.token);
691
+ if (this.options.forkDisplayMode === "dialog") {
692
+ if (!this.mainContainer) {
693
+ this.createDialogStructure();
694
+ }
695
+ if (!this.forkIframe || this.forkIframe.src !== newSrc) {
696
+ this.forkIframe = this.createIframe(this.currentFork.url, this.currentFork.token);
697
+ this.forkIframe.style.borderRadius = "0";
698
+ const iframeContainer = this.dialogElement.children[1];
699
+ iframeContainer.innerHTML = "";
700
+ iframeContainer.appendChild(this.forkIframe);
701
+ }
702
+ }
703
+ else {
704
+ // Side-by-side
705
+ if (!this.wrapperElement) {
706
+ this.createSideBySideStructure();
707
+ }
708
+ if (!this.forkIframe || this.forkIframe.src !== newSrc) {
709
+ this.forkIframe = this.createIframe(this.currentFork.url, this.currentFork.token);
710
+ this.forkFrameElement.innerHTML = "";
711
+ this.forkFrameElement.appendChild(this.forkIframe);
712
+ }
713
+ }
714
+ }
715
+ createSideBySideStructure() {
716
+ if (this.wrapperElement)
717
+ return;
718
+ this.rootElement.innerHTML = "";
719
+ this.wrapperElement = document.createElement("div");
720
+ this.wrapperElement.className =
721
+ this.options.classNames?.wrapper || "mb-adapt__wrapper";
722
+ // Main frame
723
+ this.mainFrameElement = document.createElement("div");
724
+ this.mainFrameElement.className =
725
+ this.options.classNames?.frameMain ||
726
+ `${this.options.classNames?.frame || "mb-adapt__frame"} mb-adapt__frame--main`;
727
+ // Fork frame
728
+ this.forkFrameElement = document.createElement("div");
729
+ this.forkFrameElement.className =
730
+ this.options.classNames?.frameFork ||
731
+ `${this.options.classNames?.frame || "mb-adapt__frame"} mb-adapt__frame--fork`;
732
+ // Drag handle
733
+ this.dragHandleElement = document.createElement("div");
734
+ this.dragHandleElement.className =
735
+ this.options.classNames?.dragHandle || "mb-adapt__drag-handle";
736
+ this.dragHandleElement.style.transform = "translateX(-50%)";
737
+ this.dragHandleElement.addEventListener("mousedown", (e) => {
738
+ e.preventDefault();
739
+ this.isDragging = true;
740
+ // Disable transitions during drag for smooth performance
741
+ if (this.mainFrameElement)
742
+ this.mainFrameElement.style.transition = "none";
743
+ if (this.forkFrameElement)
744
+ this.forkFrameElement.style.transition = "none";
745
+ if (this.dragHandleElement)
746
+ this.dragHandleElement.style.transition = "none";
747
+ const overlay = document.createElement("div");
748
+ overlay.className = "mb-adapt__drag-overlay";
749
+ overlay.id = "mb-adapt-drag-overlay";
750
+ this.rootElement.appendChild(overlay);
751
+ [this.mainFrameElement, this.forkFrameElement].forEach((frame) => {
752
+ if (frame) {
753
+ const iframeOverlay = document.createElement("div");
754
+ iframeOverlay.className = "mb-adapt__iframe-overlay";
755
+ frame.appendChild(iframeOverlay);
756
+ }
757
+ });
758
+ });
759
+ // Main expand button - shows on LEFT when main collapsed, arrow points RIGHT
760
+ this.mainExpandButton = document.createElement("button");
761
+ this.mainExpandButton.className =
762
+ this.options.classNames?.expandButton || "mb-adapt__expand-button";
763
+ this.mainExpandButton.classList.add("mb-adapt__expand-button--left");
764
+ this.mainExpandButton.innerHTML = "›"; // Arrow points RIGHT (where main will expand)
765
+ this.mainExpandButton.setAttribute("aria-label", "Expand main frame");
766
+ this.mainExpandButton.setAttribute("title", "Expand main frame");
767
+ this.mainExpandButton.addEventListener("click", () => {
768
+ this.splitPercentage = 50;
769
+ this.updateSideBySideVisibility();
770
+ });
771
+ // Fork expand button - shows on RIGHT when fork collapsed, arrow points LEFT
772
+ this.forkExpandButton = document.createElement("button");
773
+ this.forkExpandButton.className =
774
+ this.options.classNames?.expandButton || "mb-adapt__expand-button";
775
+ this.forkExpandButton.classList.add("mb-adapt__expand-button--right");
776
+ this.forkExpandButton.innerHTML = "‹"; // Arrow points LEFT (where fork will expand)
777
+ this.forkExpandButton.setAttribute("aria-label", "Expand fork frame");
778
+ this.forkExpandButton.setAttribute("title", "Expand fork frame");
779
+ this.forkExpandButton.addEventListener("click", () => {
780
+ this.splitPercentage = 50;
781
+ this.updateSideBySideVisibility();
782
+ });
783
+ this.wrapperElement.appendChild(this.mainFrameElement);
784
+ this.wrapperElement.appendChild(this.forkFrameElement);
785
+ this.wrapperElement.appendChild(this.dragHandleElement);
786
+ this.wrapperElement.appendChild(this.mainExpandButton);
787
+ this.wrapperElement.appendChild(this.forkExpandButton);
788
+ this.rootElement.appendChild(this.wrapperElement);
789
+ }
790
+ isResponsiveMode() {
791
+ if (!this.rootElement)
792
+ return false;
793
+ return this.rootElement.offsetWidth < AdaptWebClient.RESPONSIVE_BREAKPOINT;
794
+ }
795
+ updateSideBySideVisibility() {
796
+ if (!this.mainFrameElement ||
797
+ !this.forkFrameElement ||
798
+ !this.dragHandleElement)
799
+ return;
800
+ // No current fork - show only main at 100%
801
+ if (!this.currentFork) {
802
+ this.mainFrameElement.style.width = "100%";
803
+ this.mainFrameElement.style.display = "block";
804
+ this.forkFrameElement.style.display = "none";
805
+ this.dragHandleElement.style.display = "none";
806
+ this.mainExpandButton.classList.remove("mb-adapt__expand-button--visible");
807
+ this.forkExpandButton.classList.remove("mb-adapt__expand-button--visible");
808
+ return;
809
+ }
810
+ // Responsive mode: show only fork when container is narrow
811
+ if (this.isResponsiveMode()) {
812
+ this.mainFrameElement.style.width = "0%";
813
+ this.mainFrameElement.style.display = "none";
814
+ this.forkFrameElement.style.width = "100%";
815
+ this.forkFrameElement.style.display = "block";
816
+ this.dragHandleElement.style.display = "none";
817
+ this.mainExpandButton.classList.add("mb-adapt__expand-button--visible");
818
+ this.forkExpandButton.classList.remove("mb-adapt__expand-button--visible");
819
+ return;
820
+ }
821
+ // Normal side-by-side mode
822
+ const mainWidth = this.splitPercentage;
823
+ const forkWidth = 100 - this.splitPercentage;
824
+ const mainCollapsed = mainWidth < AdaptWebClient.COLLAPSE_THRESHOLD;
825
+ const forkCollapsed = forkWidth < AdaptWebClient.COLLAPSE_THRESHOLD;
826
+ // Update main frame
827
+ this.mainFrameElement.style.width = mainCollapsed ? "0%" : `${mainWidth}%`;
828
+ this.mainFrameElement.style.display = mainCollapsed ? "none" : "block";
829
+ // Update fork frame
830
+ this.forkFrameElement.style.width = forkCollapsed ? "0%" : `${forkWidth}%`;
831
+ this.forkFrameElement.style.display = forkCollapsed ? "none" : "block";
832
+ // Update drag handle
833
+ this.dragHandleElement.style.left = `${this.splitPercentage}%`;
834
+ this.dragHandleElement.style.display = "block";
835
+ if (mainCollapsed || forkCollapsed) {
836
+ this.dragHandleElement.classList.add("mb-adapt__drag-handle--disabled");
837
+ }
838
+ else {
839
+ this.dragHandleElement.classList.remove("mb-adapt__drag-handle--disabled");
840
+ }
841
+ // Update expand buttons
842
+ if (mainCollapsed) {
843
+ this.mainExpandButton.classList.add("mb-adapt__expand-button--visible");
844
+ }
845
+ else {
846
+ this.mainExpandButton.classList.remove("mb-adapt__expand-button--visible");
847
+ }
848
+ if (forkCollapsed) {
849
+ this.forkExpandButton.classList.add("mb-adapt__expand-button--visible");
850
+ }
851
+ else {
852
+ this.forkExpandButton.classList.remove("mb-adapt__expand-button--visible");
853
+ }
854
+ }
855
+ updateSideBySideWidths() {
856
+ if (!this.mainFrameElement ||
857
+ !this.forkFrameElement ||
858
+ !this.dragHandleElement)
859
+ return;
860
+ const mainWidth = this.splitPercentage;
861
+ const forkWidth = 100 - this.splitPercentage;
862
+ this.mainFrameElement.style.width = `${mainWidth}%`;
863
+ this.forkFrameElement.style.width = `${forkWidth}%`;
864
+ this.dragHandleElement.style.left = `${this.splitPercentage}%`;
865
+ }
866
+ createDialogStructure() {
867
+ if (this.mainContainer)
868
+ return;
869
+ this.rootElement.innerHTML = "";
870
+ // Main container
871
+ this.mainContainer = document.createElement("div");
872
+ this.mainContainer.className = "mb-adapt__main-container";
873
+ // Dialog expand button
874
+ this.dialogExpandButton = document.createElement("button");
875
+ this.dialogExpandButton.className =
876
+ this.options.classNames?.expandButton || "mb-adapt__expand-button";
877
+ this.dialogExpandButton.classList.add("mb-adapt__expand-button--dialog");
878
+ this.dialogExpandButton.innerHTML = "⌄";
879
+ this.dialogExpandButton.setAttribute("aria-label", "Open fork dialog");
880
+ this.dialogExpandButton.setAttribute("title", "Open fork dialog");
881
+ this.dialogExpandButton.addEventListener("click", () => {
882
+ this.activateNextFork();
883
+ });
884
+ // Backdrop
885
+ this.dialogBackdrop = document.createElement("div");
886
+ this.dialogBackdrop.className =
887
+ this.options.classNames?.dialogBackdrop || "mb-adapt__dialog-backdrop";
888
+ if (this.options.dialogBackdropClose) {
889
+ this.dialogBackdrop.addEventListener("click", () => {
890
+ // Put current fork back in queue before closing
891
+ if (this.currentFork) {
892
+ this.forkQueue.unshift(this.currentFork);
893
+ }
894
+ this.currentFork = null;
895
+ this.updateDialogVisibility();
896
+ });
897
+ }
898
+ // Dialog
899
+ this.dialogElement = document.createElement("div");
900
+ this.dialogElement.className =
901
+ this.options.classNames?.dialog || "mb-adapt__dialog";
902
+ const banner = document.createElement("div");
903
+ banner.className =
904
+ this.options.classNames?.dialogBanner || "mb-adapt__dialog-banner";
905
+ const closeBtn = document.createElement("button");
906
+ closeBtn.className =
907
+ this.options.classNames?.dialogClose || "mb-adapt__dialog-close";
908
+ closeBtn.innerHTML = "×";
909
+ closeBtn.setAttribute("aria-label", "Close dialog");
910
+ closeBtn.setAttribute("title", "Close dialog");
911
+ closeBtn.addEventListener("click", () => {
912
+ // Put current fork back in queue before closing
913
+ if (this.currentFork) {
914
+ this.forkQueue.unshift(this.currentFork);
915
+ }
916
+ this.currentFork = null;
917
+ this.updateDialogVisibility();
918
+ });
919
+ banner.appendChild(closeBtn);
920
+ this.dialogElement.appendChild(banner);
921
+ const iframeContainer = document.createElement("div");
922
+ iframeContainer.style.flex = "1";
923
+ iframeContainer.style.overflow = "hidden";
924
+ this.dialogElement.appendChild(iframeContainer);
925
+ this.mainContainer.appendChild(this.dialogExpandButton);
926
+ this.rootElement.appendChild(this.mainContainer);
927
+ this.rootElement.appendChild(this.dialogBackdrop);
928
+ this.rootElement.appendChild(this.dialogElement);
929
+ }
930
+ updateDialogVisibility() {
931
+ if (!this.dialogExpandButton || !this.dialogBackdrop || !this.dialogElement)
932
+ return;
933
+ const hasForkAvailable = this.forkQueue.length > 0;
934
+ const hasForkShowing = this.currentFork !== null;
935
+ // Show expand button if fork available but not showing
936
+ if (!hasForkShowing && hasForkAvailable) {
937
+ this.dialogExpandButton.classList.add("mb-adapt__expand-button--visible");
938
+ }
939
+ else {
940
+ this.dialogExpandButton.classList.remove("mb-adapt__expand-button--visible");
941
+ }
942
+ // Show/hide dialog
943
+ if (hasForkShowing) {
944
+ this.dialogBackdrop.classList.add("mb-adapt__dialog-backdrop--visible");
945
+ this.dialogElement.classList.add("mb-adapt__dialog--visible");
946
+ }
947
+ else {
948
+ this.dialogBackdrop.classList.remove("mb-adapt__dialog-backdrop--visible");
949
+ this.dialogElement.classList.remove("mb-adapt__dialog--visible");
950
+ }
951
+ }
952
+ getIframeSrc(url, token) {
953
+ return `${url}${token ? "#" + token : ""}`;
954
+ }
955
+ createIframe(url, token) {
956
+ const iframe = document.createElement("iframe");
957
+ iframe.className = this.options.classNames?.iframe || "mb-adapt__iframe";
958
+ iframe.src = this.getIframeSrc(url, token);
959
+ iframe.setAttribute("sandbox", "allow-downloads allow-same-origin allow-scripts allow-popups allow-forms allow-modals");
960
+ iframe.setAttribute("allow", "geolocation; accelerometer; midi; microphone; camera; magnetometer; gyroscope; fullscreen; payment;");
961
+ return iframe;
162
962
  }
163
963
  }
964
+ AdaptWebClient.COLLAPSE_THRESHOLD = 15;
965
+ AdaptWebClient.RESPONSIVE_BREAKPOINT = 600; // px - below this, auto-collapse to single view
164
966
  //# sourceMappingURL=index.js.map