@zoho_apptics/apptics-js-sdk 2.0.0-beta → 2.0.0-beta.2

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 (236) hide show
  1. package/CHANGELOG.md +191 -21
  2. package/README.md +519 -333
  3. package/dist/apptics.esm.min.js +2 -2
  4. package/dist/apptics.esm.min.js.map +1 -1
  5. package/dist/apptics.min.js +2 -2
  6. package/dist/apptics.min.js.map +1 -1
  7. package/dist/chunks/lifecycle-C6m1W7jo.min.js +3 -0
  8. package/dist/chunks/lifecycle-C6m1W7jo.min.js.map +1 -0
  9. package/dist/chunks/send-CgUO82ne.min.js +3 -0
  10. package/dist/chunks/send-CgUO82ne.min.js.map +1 -0
  11. package/dist/cjs/core/attempts.js +1 -1
  12. package/dist/cjs/core/batch.js +2 -2
  13. package/dist/cjs/core/consent.d.ts +18 -4
  14. package/dist/cjs/core/consent.js +31 -15
  15. package/dist/cjs/core/constants.d.ts +57 -27
  16. package/dist/cjs/core/constants.js +52 -33
  17. package/dist/cjs/core/db.d.ts +12 -4
  18. package/dist/cjs/core/db.js +167 -34
  19. package/dist/cjs/core/debug.js +1 -1
  20. package/dist/cjs/core/env.d.ts +0 -3
  21. package/dist/cjs/core/env.js +1 -9
  22. package/dist/cjs/core/framework-id.d.ts +1 -1
  23. package/dist/cjs/core/framework-id.js +3 -3
  24. package/dist/cjs/core/guard.d.ts +9 -0
  25. package/dist/cjs/core/guard.js +27 -13
  26. package/dist/cjs/core/hooks.d.ts +7 -4
  27. package/dist/cjs/core/hooks.js +3 -3
  28. package/dist/cjs/core/locks.d.ts +9 -0
  29. package/dist/cjs/core/locks.js +22 -0
  30. package/dist/cjs/core/logger.d.ts +3 -4
  31. package/dist/cjs/core/logger.js +4 -40
  32. package/dist/cjs/core/state.d.ts +9 -6
  33. package/dist/cjs/core/state.js +3 -5
  34. package/dist/cjs/core/storage.d.ts +20 -5
  35. package/dist/cjs/core/storage.js +115 -20
  36. package/dist/cjs/core/stylesheet.d.ts +8 -0
  37. package/dist/cjs/core/stylesheet.js +29 -0
  38. package/dist/cjs/core/transport.d.ts +2 -0
  39. package/dist/cjs/core/transport.js +30 -18
  40. package/dist/cjs/core/utils.js +1 -1
  41. package/dist/cjs/core/validate.js +2 -2
  42. package/dist/cjs/device/appversion.d.ts +10 -6
  43. package/dist/cjs/device/appversion.js +38 -3
  44. package/dist/cjs/device/index.d.ts +28 -2
  45. package/dist/cjs/device/index.js +312 -44
  46. package/dist/cjs/engagement/api-rules.d.ts +32 -67
  47. package/dist/cjs/engagement/api-rules.js +144 -157
  48. package/dist/cjs/engagement/auto-api.js +2 -2
  49. package/dist/cjs/engagement/auto-screen.d.ts +2 -0
  50. package/dist/cjs/engagement/auto-screen.js +67 -3
  51. package/dist/cjs/engagement/defined-events.js +1 -1
  52. package/dist/cjs/engagement/send.js +12 -3
  53. package/dist/cjs/engagement/session.d.ts +29 -3
  54. package/dist/cjs/engagement/session.js +253 -26
  55. package/dist/cjs/engagement/track.d.ts +4 -4
  56. package/dist/cjs/engagement/track.js +58 -30
  57. package/dist/cjs/errors/send.js +2 -2
  58. package/dist/cjs/errors/track.d.ts +2 -1
  59. package/dist/cjs/errors/track.js +49 -7
  60. package/dist/cjs/feedback/controls.d.ts +12 -0
  61. package/dist/cjs/feedback/controls.js +104 -25
  62. package/dist/cjs/feedback/index.d.ts +8 -7
  63. package/dist/cjs/feedback/index.js +32 -13
  64. package/dist/cjs/feedback/logs.d.ts +13 -11
  65. package/dist/cjs/feedback/logs.js +57 -28
  66. package/dist/cjs/feedback/quartz.d.ts +18 -0
  67. package/dist/cjs/feedback/quartz.js +105 -0
  68. package/dist/cjs/feedback/send.d.ts +5 -2
  69. package/dist/cjs/feedback/send.js +30 -28
  70. package/dist/cjs/feedback/styles.d.ts +10 -0
  71. package/dist/cjs/feedback/styles.js +8 -0
  72. package/dist/cjs/feedback/template.d.ts +1 -1
  73. package/dist/cjs/feedback/template.js +20 -12
  74. package/dist/cjs/feedback/ui.d.ts +21 -6
  75. package/dist/cjs/feedback/ui.js +283 -70
  76. package/dist/cjs/heatmap/send.d.ts +2 -0
  77. package/dist/cjs/heatmap/send.js +3 -5
  78. package/dist/cjs/heatmap/track.d.ts +1 -1
  79. package/dist/cjs/heatmap/track.js +87 -16
  80. package/dist/cjs/index.d.ts +16 -63
  81. package/dist/cjs/index.js +144 -95
  82. package/dist/cjs/lifecycle.d.ts +21 -3
  83. package/dist/cjs/lifecycle.js +353 -89
  84. package/dist/cjs/remoteconfig/country.d.ts +4 -0
  85. package/dist/cjs/remoteconfig/country.js +73 -0
  86. package/dist/cjs/remoteconfig/custom.d.ts +7 -7
  87. package/dist/cjs/remoteconfig/custom.js +31 -51
  88. package/dist/cjs/remoteconfig/evaluate.d.ts +3 -3
  89. package/dist/cjs/remoteconfig/evaluate.js +56 -43
  90. package/dist/cjs/remoteconfig/fetch.d.ts +16 -9
  91. package/dist/cjs/remoteconfig/fetch.js +120 -39
  92. package/dist/cjs/remoteconfig/index.d.ts +19 -8
  93. package/dist/cjs/remoteconfig/index.js +81 -39
  94. package/dist/cjs/remoteconfig/store.d.ts +15 -7
  95. package/dist/cjs/remoteconfig/store.js +68 -35
  96. package/dist/cjs/remoteconfig/tz-countries.d.ts +8 -0
  97. package/dist/cjs/remoteconfig/tz-countries.js +13 -0
  98. package/dist/{esm/core → cjs/remotelog}/callsite.d.ts +11 -4
  99. package/dist/cjs/{core → remotelog}/callsite.js +30 -7
  100. package/dist/cjs/remotelog/gate.d.ts +2 -11
  101. package/dist/cjs/remotelog/gate.js +9 -35
  102. package/dist/cjs/remotelog/index.d.ts +4 -21
  103. package/dist/cjs/remotelog/logger.d.ts +11 -17
  104. package/dist/cjs/remotelog/logger.js +31 -59
  105. package/dist/cjs/remotelog/send.js +11 -11
  106. package/dist/cjs/remotelogger/index.d.ts +12 -0
  107. package/dist/cjs/remotelogger/index.js +18 -0
  108. package/dist/cjs/scheduler.d.ts +3 -1
  109. package/dist/cjs/scheduler.js +25 -22
  110. package/dist/cjs/types.d.ts +208 -90
  111. package/dist/cjs/user/index.js +16 -7
  112. package/dist/esm/core/attempts.js +1 -1
  113. package/dist/esm/core/batch.js +2 -2
  114. package/dist/esm/core/consent.d.ts +18 -4
  115. package/dist/esm/core/consent.js +32 -17
  116. package/dist/esm/core/constants.d.ts +57 -27
  117. package/dist/esm/core/constants.js +51 -33
  118. package/dist/esm/core/db.d.ts +12 -4
  119. package/dist/esm/core/db.js +164 -35
  120. package/dist/esm/core/debug.js +1 -1
  121. package/dist/esm/core/env.d.ts +0 -3
  122. package/dist/esm/core/env.js +2 -9
  123. package/dist/esm/core/framework-id.d.ts +1 -1
  124. package/dist/esm/core/framework-id.js +3 -3
  125. package/dist/esm/core/guard.d.ts +9 -0
  126. package/dist/esm/core/guard.js +27 -14
  127. package/dist/esm/core/hooks.d.ts +7 -4
  128. package/dist/esm/core/hooks.js +3 -3
  129. package/dist/esm/core/locks.d.ts +9 -0
  130. package/dist/esm/core/locks.js +20 -0
  131. package/dist/esm/core/logger.d.ts +3 -4
  132. package/dist/esm/core/logger.js +4 -40
  133. package/dist/esm/core/state.d.ts +9 -6
  134. package/dist/esm/core/state.js +3 -5
  135. package/dist/esm/core/storage.d.ts +20 -5
  136. package/dist/esm/core/storage.js +113 -21
  137. package/dist/esm/core/stylesheet.d.ts +8 -0
  138. package/dist/esm/core/stylesheet.js +27 -0
  139. package/dist/esm/core/transport.d.ts +2 -0
  140. package/dist/esm/core/transport.js +30 -19
  141. package/dist/esm/core/utils.js +1 -1
  142. package/dist/esm/core/validate.js +2 -2
  143. package/dist/esm/device/appversion.d.ts +10 -6
  144. package/dist/esm/device/appversion.js +37 -4
  145. package/dist/esm/device/index.d.ts +28 -2
  146. package/dist/esm/device/index.js +313 -49
  147. package/dist/esm/engagement/api-rules.d.ts +32 -67
  148. package/dist/esm/engagement/api-rules.js +143 -155
  149. package/dist/esm/engagement/auto-api.js +3 -3
  150. package/dist/esm/engagement/auto-screen.d.ts +2 -0
  151. package/dist/esm/engagement/auto-screen.js +67 -4
  152. package/dist/esm/engagement/defined-events.js +1 -1
  153. package/dist/esm/engagement/send.js +12 -3
  154. package/dist/esm/engagement/session.d.ts +29 -3
  155. package/dist/esm/engagement/session.js +251 -30
  156. package/dist/esm/engagement/track.d.ts +4 -4
  157. package/dist/esm/engagement/track.js +65 -37
  158. package/dist/esm/errors/send.js +2 -2
  159. package/dist/esm/errors/track.d.ts +2 -1
  160. package/dist/esm/errors/track.js +49 -7
  161. package/dist/esm/feedback/controls.d.ts +12 -0
  162. package/dist/esm/feedback/controls.js +103 -26
  163. package/dist/esm/feedback/index.d.ts +8 -7
  164. package/dist/esm/feedback/index.js +34 -13
  165. package/dist/esm/feedback/logs.d.ts +13 -11
  166. package/dist/esm/feedback/logs.js +59 -30
  167. package/dist/esm/feedback/quartz.d.ts +18 -0
  168. package/dist/esm/feedback/quartz.js +99 -0
  169. package/dist/esm/feedback/send.d.ts +5 -2
  170. package/dist/esm/feedback/send.js +31 -31
  171. package/dist/esm/feedback/styles.d.ts +10 -0
  172. package/dist/esm/feedback/styles.js +4 -0
  173. package/dist/esm/feedback/template.d.ts +1 -1
  174. package/dist/esm/feedback/template.js +20 -12
  175. package/dist/esm/feedback/ui.d.ts +21 -6
  176. package/dist/esm/feedback/ui.js +283 -71
  177. package/dist/esm/heatmap/send.d.ts +2 -0
  178. package/dist/esm/heatmap/send.js +3 -5
  179. package/dist/esm/heatmap/track.d.ts +1 -1
  180. package/dist/esm/heatmap/track.js +87 -16
  181. package/dist/esm/index.d.ts +16 -63
  182. package/dist/esm/index.js +148 -83
  183. package/dist/esm/lifecycle.d.ts +21 -3
  184. package/dist/esm/lifecycle.js +359 -98
  185. package/dist/esm/remoteconfig/country.d.ts +4 -0
  186. package/dist/esm/remoteconfig/country.js +70 -0
  187. package/dist/esm/remoteconfig/custom.d.ts +7 -7
  188. package/dist/esm/remoteconfig/custom.js +32 -52
  189. package/dist/esm/remoteconfig/evaluate.d.ts +3 -3
  190. package/dist/esm/remoteconfig/evaluate.js +57 -44
  191. package/dist/esm/remoteconfig/fetch.d.ts +16 -9
  192. package/dist/esm/remoteconfig/fetch.js +120 -39
  193. package/dist/esm/remoteconfig/index.d.ts +19 -8
  194. package/dist/esm/remoteconfig/index.js +82 -40
  195. package/dist/esm/remoteconfig/store.d.ts +15 -7
  196. package/dist/esm/remoteconfig/store.js +68 -36
  197. package/dist/esm/remoteconfig/tz-countries.d.ts +8 -0
  198. package/dist/esm/remoteconfig/tz-countries.js +11 -0
  199. package/dist/{cjs/core → esm/remotelog}/callsite.d.ts +11 -4
  200. package/dist/esm/{core → remotelog}/callsite.js +30 -8
  201. package/dist/esm/remotelog/gate.d.ts +2 -11
  202. package/dist/esm/remotelog/gate.js +10 -32
  203. package/dist/esm/remotelog/index.d.ts +4 -21
  204. package/dist/esm/remotelog/logger.d.ts +11 -17
  205. package/dist/esm/remotelog/logger.js +33 -61
  206. package/dist/esm/remotelog/send.js +13 -13
  207. package/dist/esm/remotelogger/index.d.ts +12 -0
  208. package/dist/esm/remotelogger/index.js +13 -0
  209. package/dist/esm/scheduler.d.ts +3 -1
  210. package/dist/esm/scheduler.js +26 -24
  211. package/dist/esm/types.d.ts +208 -90
  212. package/dist/esm/user/index.js +18 -8
  213. package/dist/feedback.esm.min.js +2 -2
  214. package/dist/feedback.esm.min.js.map +1 -1
  215. package/dist/remoteconfig.esm.min.js +3 -0
  216. package/dist/remoteconfig.esm.min.js.map +1 -0
  217. package/dist/remotelogger.esm.min.js +3 -0
  218. package/dist/remotelogger.esm.min.js.map +1 -0
  219. package/package.json +16 -17
  220. package/dist/chunks/batch-BU_mTpm1.min.js +0 -3
  221. package/dist/chunks/batch-BU_mTpm1.min.js.map +0 -1
  222. package/dist/chunks/logs-Bea5zUW_.min.js +0 -3
  223. package/dist/chunks/logs-Bea5zUW_.min.js.map +0 -1
  224. package/dist/cjs/auto-init.d.ts +0 -8
  225. package/dist/cjs/auto-init.js +0 -32
  226. package/dist/cjs/heatmap/index.d.ts +0 -16
  227. package/dist/cjs/heatmap/index.js +0 -22
  228. package/dist/cjs/remotelog/index.js +0 -55
  229. package/dist/esm/auto-init.d.ts +0 -8
  230. package/dist/esm/auto-init.js +0 -29
  231. package/dist/esm/heatmap/index.d.ts +0 -16
  232. package/dist/esm/heatmap/index.js +0 -17
  233. package/dist/esm/remotelog/index.js +0 -51
  234. package/dist/heatmap.esm.min.js +0 -3
  235. package/dist/heatmap.esm.min.js.map +0 -1
  236. package/dist/style.css +0 -1
@@ -1,4 +1,5 @@
1
1
  import type { Properties } from '../types.js';
2
2
  export declare function trackError(errorEvent: any, jsonObj?: Properties): void;
3
- export declare function enableGlobalErrorHandler(status?: boolean): void;
3
+ /** AppticsError.setErrorTracking: uncaught errors on or off, as the `track_error` config sets it. */
4
+ export declare function setErrorTracking(status?: boolean): void;
4
5
  export declare function extractMethodNameFromStackTrace(stackTrace: string): string;
@@ -1,4 +1,4 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.2 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  import { AP_CONSTANTS } from '../core/constants.js';
3
3
  import { _ZAP } from '../core/state.js';
4
4
  import { Console } from '../core/logger.js';
@@ -36,19 +36,59 @@ function stackOf(errorEvent) {
36
36
  }
37
37
  /** Said in place of a stack when there is none, so `message` is never sent empty. */
38
38
  const NO_STACK = 'no stack available'; // no i18n
39
+ /** The element an event came from, as `<script src="…">`, so a failed load says what failed. */
40
+ function describeTarget(target) {
41
+ var el = target;
42
+ if (!el || typeof el.tagName !== 'string') { // no i18n
43
+ return ''; // no i18n
44
+ }
45
+ var tag = el.tagName.toLowerCase();
46
+ var url = el.currentSrc || el.src || el.href || ''; // no i18n
47
+ return ' on <' + tag + (url ? (el.href && !el.src ? ' href="' : ' src="') + url + '"' : '') + '>'; // no i18n
48
+ }
49
+ /**
50
+ * What was thrown or rejected, as text an issue can be named by. An Error reads as itself. A
51
+ * promise rejected with an Event - what a failed script or image load hands over - used to be
52
+ * recorded as "[object Event]"; it is named by its type and where it came from instead. Anything
53
+ * else that is an object is shown as its JSON, cut short.
54
+ */
55
+ function describeThrown(thrown) {
56
+ if (thrown === null || thrown === undefined) {
57
+ return ''; // no i18n
58
+ }
59
+ if (typeof thrown !== 'object') { // no i18n
60
+ return String(thrown);
61
+ }
62
+ if (thrown instanceof Error || typeof thrown.message === 'string' && typeof thrown.name === 'string') { // no i18n
63
+ return String(thrown);
64
+ }
65
+ if (typeof Event !== 'undefined' && thrown instanceof Event) { // no i18n
66
+ return 'Event "' + thrown.type + '"' + describeTarget(thrown.target); // no i18n
67
+ }
68
+ var text = String(thrown);
69
+ if (text !== '[object Object]') { // no i18n
70
+ return text;
71
+ }
72
+ try {
73
+ return JSON.stringify(thrown).slice(0, 300);
74
+ }
75
+ catch (err) {
76
+ return text;
77
+ }
78
+ }
39
79
  function trackError(errorEvent, jsonObj) {
40
80
  if (!canTrackErrors('trackError')) { // no i18n
41
81
  return;
42
82
  }
43
83
  if (isEmpty(errorEvent)) {
44
- Console.warn('AppticsTrackError: Invalid error'); // no i18n
84
+ Console.warn('AppticsError.trackError: Invalid error'); // no i18n
45
85
  return;
46
86
  }
47
87
  var _jsonObj = validateJSON(jsonObj);
48
88
  var stack = stackOf(errorEvent);
49
89
  var methodName = extractMethodNameFromStackTrace(stack) || "";
50
90
  var issuetype = errorEvent.type || "";
51
- var thrown = errorEvent.reason || errorEvent.error || errorEvent.message || "";
91
+ var thrown = describeThrown(errorEvent.reason || errorEvent.error || errorEvent.message || "");
52
92
  // "Error: x at handler", or just "Error: x" when the stack names no method. issuename is
53
93
  // required too, so something that carried no message at all is still named rather than blank
54
94
  var described = !isEmpty(String(thrown)) ? String(thrown) : (!isEmpty(issuetype) ? String(issuetype) : 'Unknown error'); // no i18n
@@ -74,11 +114,13 @@ function trackError(errorEvent, jsonObj) {
74
114
  commitPendingSession();
75
115
  noteDebugActivity();
76
116
  error_transactions.add(errorData);
77
- Console.log('AppticsTrackError(\'' + issuetype + '\',\'' + message + '\',' + JSON.stringify(_jsonObj || {}) + ')'); // no i18n
117
+ Console.log('AppticsError.trackError(\'' + issuetype + '\',\'' + message + '\',' + JSON.stringify(_jsonObj || {}) + ')'); // no i18n
78
118
  Console.dir(errorData);
79
119
  }
80
- function enableGlobalErrorHandler(status) {
81
- _ZAP._isGlobalErrorTracking = typeof status === "boolean" ? status : true; // no i18n
120
+ /** AppticsError.setErrorTracking: uncaught errors on or off, as the `track_error` config sets it. */
121
+ function setErrorTracking(status) {
122
+ _ZAP._config.track_error = typeof status === "boolean" ? status : true; // no i18n
123
+ Console.log('automatic error tracking: ' + (_ZAP._config.track_error ? 'on' : 'off')); // no i18n
82
124
  }
83
125
  function extractMethodNameFromStackTrace(stackTrace) {
84
126
  let methodName = ''; // no i18n
@@ -120,4 +162,4 @@ function extractMethodNameFromStackTrace(stackTrace) {
120
162
  return methodName;
121
163
  }
122
164
 
123
- export { enableGlobalErrorHandler, extractMethodNameFromStackTrace, trackError };
165
+ export { extractMethodNameFromStackTrace, setErrorTracking, trackError };
@@ -12,6 +12,12 @@ export declare const logChoice: {
12
12
  includeLog?: boolean;
13
13
  includeDyninfo?: boolean;
14
14
  };
15
+ /**
16
+ * Who a sendFeedback() report, made without the form, is attributed to: nobody when `anonymous`,
17
+ * else the user AppticsUser.setUser set (or the active registered one, status 1). Returns a function
18
+ * that puts back the choice that was there, so a form left open keeps its own.
19
+ */
20
+ export declare function chooseUserForSend(anonymous: boolean): () => void;
15
21
  /**
16
22
  * The "User" dropdown above the description. It lists Anonymous plus every registered user, and
17
23
  * starts on the active one (status 1) unless the caller asked for anonymous.
@@ -29,3 +35,9 @@ export declare function wireLogControls(modal: HTMLElement, opts: Dict): void;
29
35
  * kept inside the viewport.
30
36
  */
31
37
  export declare function wireDrag(box: HTMLElement): void;
38
+ /**
39
+ * Lets the recording timer be dragged anywhere on the page. A press that moves it is a drag, and
40
+ * does not also stop the recording, as a plain click on it does. Call before the click listener
41
+ * is added, so a drag's click is stopped ahead of it.
42
+ */
43
+ export declare function wireTimerDrag(timer: HTMLElement): void;
@@ -1,8 +1,9 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.2 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  import { Console } from '../core/logger.js';
3
3
  import { hooks } from '../core/hooks.js';
4
4
  import { user_defaults } from '../core/storage.js';
5
5
  import { isEmpty } from '../core/utils.js';
6
+ import { _ZAP } from '../core/state.js';
6
7
  import { hasLogLines, hasDiagnostics, logText, diagnosticsText } from './logs.js';
7
8
 
8
9
  /**
@@ -23,6 +24,34 @@ function resetUserChoice() {
23
24
  userChoice.userid = ''; // no i18n
24
25
  userChoice.groupid = ''; // no i18n
25
26
  }
27
+ /**
28
+ * Who a sendFeedback() report, made without the form, is attributed to: nobody when `anonymous`,
29
+ * else the user AppticsUser.setUser set (or the active registered one, status 1). Returns a function
30
+ * that puts back the choice that was there, so a form left open keeps its own.
31
+ */
32
+ function chooseUserForSend(anonymous) {
33
+ var before = { anonymous: userChoice.anonymous, userid: userChoice.userid, groupid: userChoice.groupid };
34
+ resetUserChoice();
35
+ if (!anonymous) {
36
+ // the user setUser set on this page, else the active one of those registered before
37
+ var active = !isEmpty(_ZAP._user_info.userid) ? _ZAP._user_info : null;
38
+ storedUsers().forEach(function (user) {
39
+ if (!active && user && user.status == 1 && !isEmpty(user.userid)) {
40
+ active = user;
41
+ }
42
+ });
43
+ if (active) {
44
+ userChoice.anonymous = false;
45
+ userChoice.userid = String(active.userid);
46
+ userChoice.groupid = String(active.groupid || ''); // no i18n
47
+ }
48
+ }
49
+ return function restore() {
50
+ userChoice.anonymous = before.anonymous;
51
+ userChoice.userid = before.userid;
52
+ userChoice.groupid = before.groupid;
53
+ };
54
+ }
26
55
  /** Every distinct registered user, by the address the picker shows. */
27
56
  function storedUsers() {
28
57
  var users = user_defaults.item('users'); // no i18n
@@ -236,45 +265,93 @@ function wireDrag(box) {
236
265
  if (!header) {
237
266
  return;
238
267
  }
239
- var startX = 0, startY = 0, boxLeft = 0, boxTop = 0, dragging = false;
240
- header.addEventListener('mousedown', function (event) {
241
- if (event.target.closest('.zasdk-close')) { // no i18n
242
- return; // the close button is not a drag handle
243
- }
244
- if (!box.style.left || box.style.left === 'auto') { // no i18n
245
- var rect = box.getBoundingClientRect();
246
- box.style.right = 'auto'; // no i18n
247
- box.style.bottom = 'auto'; // no i18n
248
- box.style.left = rect.left + 'px'; // no i18n
249
- box.style.top = rect.top + 'px'; // no i18n
268
+ makeDraggable(box, header, function (target) {
269
+ // the close button is not a drag handle
270
+ return !!target.closest('.zasdk-close'); // no i18n
271
+ });
272
+ }
273
+ /** Where the recording timer was last dragged to, so the next recording's timer starts there. */
274
+ var timerSpot = null;
275
+ /**
276
+ * Lets the recording timer be dragged anywhere on the page. A press that moves it is a drag, and
277
+ * does not also stop the recording, as a plain click on it does. Call before the click listener
278
+ * is added, so a drag's click is stopped ahead of it.
279
+ */
280
+ function wireTimerDrag(timer) {
281
+ if (timerSpot) {
282
+ placeAt(timer, timerSpot.left, timerSpot.top);
283
+ }
284
+ makeDraggable(timer, timer, undefined, function (left, top) {
285
+ timerSpot = { left: left, top: top };
286
+ });
287
+ }
288
+ /** Puts a fixed box at left/top, inside the viewport. */
289
+ function placeAt(box, left, top) {
290
+ box.style.right = 'auto'; // no i18n
291
+ box.style.bottom = 'auto'; // no i18n
292
+ box.style.left = Math.max(0, Math.min(left, window.innerWidth - box.offsetWidth)) + 'px'; // no i18n
293
+ box.style.top = Math.max(0, Math.min(top, window.innerHeight - box.offsetHeight)) + 'px'; // no i18n
294
+ }
295
+ /**
296
+ * Moves `box` with the mouse or a finger pressed on `handle`. `skip` says which presses are not a
297
+ * drag; `moved` hears where the box ended up. A click that ends a drag goes no further.
298
+ */
299
+ function makeDraggable(box, handle, skip, moved) {
300
+ var startX = 0, startY = 0, boxLeft = 0, boxTop = 0, dragging = false, dragged = false;
301
+ handle.addEventListener('pointerdown', function (event) {
302
+ if (event.button !== 0 || (skip && skip(event.target))) {
303
+ return;
250
304
  }
305
+ var rect = box.getBoundingClientRect();
251
306
  dragging = true;
307
+ dragged = false;
252
308
  startX = event.clientX;
253
309
  startY = event.clientY;
254
- boxLeft = parseInt(box.style.left, 10);
255
- boxTop = parseInt(box.style.top, 10);
256
- header.style.cursor = 'grabbing'; // no i18n
310
+ boxLeft = rect.left;
311
+ boxTop = rect.top;
312
+ handle.style.cursor = 'move'; // no i18n
313
+ // the moves and the release come to the handle however far the pointer goes, so nothing
314
+ // is left listening on the document once the box is gone
315
+ try {
316
+ handle.setPointerCapture(event.pointerId);
317
+ }
318
+ catch (err) { /* a pointer already released */ }
257
319
  event.preventDefault();
258
320
  });
259
- document.addEventListener('mousemove', function (event) {
321
+ handle.addEventListener('pointermove', function (event) {
260
322
  if (!dragging) {
261
323
  return;
262
324
  }
263
- var left = boxLeft + (event.clientX - startX);
264
- var top = boxTop + (event.clientY - startY);
265
- box.style.left = Math.max(0, Math.min(left, window.innerWidth - box.offsetWidth)) + 'px'; // no i18n
266
- box.style.top = Math.max(0, Math.min(top, window.innerHeight - box.offsetHeight)) + 'px'; // no i18n
267
- });
268
- document.addEventListener('mouseup', function () {
269
- if (dragging) {
270
- dragging = false;
271
- header.style.cursor = 'grab'; // no i18n
325
+ var dx = event.clientX - startX, dy = event.clientY - startY;
326
+ if (!dragged && Math.abs(dx) < 4 && Math.abs(dy) < 4) {
327
+ return; // a press that wobbles is still a click
272
328
  }
329
+ dragged = true;
330
+ placeAt(box, boxLeft + dx, boxTop + dy);
273
331
  });
332
+ function stop() {
333
+ if (!dragging) {
334
+ return;
335
+ }
336
+ dragging = false;
337
+ handle.style.cursor = ''; // no i18n
338
+ if (dragged && moved) {
339
+ moved(parseInt(box.style.left, 10), parseInt(box.style.top, 10));
340
+ }
341
+ }
342
+ handle.addEventListener('pointerup', stop); // no i18n
343
+ handle.addEventListener('pointercancel', stop); // no i18n
344
+ box.addEventListener('click', function (event) {
345
+ if (dragged) {
346
+ dragged = false;
347
+ event.stopImmediatePropagation();
348
+ event.preventDefault();
349
+ }
350
+ }, true);
274
351
  }
275
352
  // core/transport asks for the picked user when it builds the feedback request's parameters
276
353
  hooks.feedbackUser = function () {
277
354
  return userChoice.anonymous || isEmpty(userChoice.userid) ? null : userChoice;
278
355
  };
279
356
 
280
- export { logChoice, userChoice, wireDrag, wireLogControls, wireUserPicker };
357
+ export { chooseUserForSend, logChoice, userChoice, wireDrag, wireLogControls, wireTimerDrag, wireUserPicker };
@@ -1,8 +1,9 @@
1
- import { feedbackClose as feedbackCloseImpl } from './ui.js';
2
1
  import type { AppticsFeedbackApi } from '../types.js';
3
- export declare const feedbackOpen: AppticsFeedbackApi["feedbackOpen"];
4
- export declare const feedbackClose: typeof feedbackCloseImpl;
5
- /** Resolves once the feedback is sent; rejects when it wasn't (SDK not started, offline, refused). */
6
- export declare const sendFeedback: AppticsFeedbackApi["sendFeedback"];
7
- declare const feedback: AppticsFeedbackApi;
8
- export default feedback;
2
+ export type { FeedbackOpenOptions, SendFeedbackOptions } from '../types.js';
3
+ /**
4
+ * Android's AppticsFeedback: the form, sending feedback without it, and the context recorded for
5
+ * the next one. Every feedback call, addFeedbackLog and addDiagnosticsInfo included, is here and
6
+ * only here: the main entry has no AppticsFeedback.
7
+ */
8
+ export declare const AppticsFeedback: AppticsFeedbackApi;
9
+ export default AppticsFeedback;
@@ -1,30 +1,51 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
2
- import { guard } from '../core/guard.js';
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.2 | (c) Zoho Corporation Private Limited | see LICENSE */
2
+ import { forward, guard } from '../core/guard.js';
3
+ import { AP_FEEDBACK_TYPE } from '../core/constants.js';
3
4
  import { Console } from '../core/logger.js';
4
5
  import { ready } from '../lifecycle.js';
5
- import { sendFeedback as sendFeedback$1, feedbackClose as feedbackClose$1, feedbackOpen as feedbackOpen$1 } from './ui.js';
6
+ import { setFeedbackTheme, sendFeedback, feedbackFormClose, feedbackFormOpen } from './ui.js';
7
+ import { addDiagnosticsInfo, addFeedbackLog } from './logs.js';
6
8
 
7
9
  /**
8
10
  * Optional feedback modal, shipped as its own entry point:
9
- * import { feedbackOpen } from '@zoho_apptics/apptics-js-sdk/feedback';
10
- * import '@zoho_apptics/apptics-js-sdk/style.css';
11
+ * import { AppticsFeedback } from '@zoho_apptics/apptics-js-sdk/feedback';
12
+ * AppticsFeedback.feedbackFormOpen();
11
13
  * Apps that never import it don't pay for the modal or its markup.
12
14
  * The <script> build includes it, so snippet users are unaffected.
13
15
  */
14
- const feedbackOpen = guard('feedbackOpen', feedbackOpen$1); // no i18n
15
- const feedbackClose = guard('feedbackClose', feedbackClose$1); // no i18n
16
+ const feedbackFormOpenGuarded = guard('AppticsFeedback.feedbackFormOpen', feedbackFormOpen); // no i18n
17
+ const feedbackFormCloseGuarded = guard('AppticsFeedback.feedbackFormClose', feedbackFormClose); // no i18n
18
+ const addFeedbackLogGuarded = guard('AppticsFeedback.addFeedbackLog', addFeedbackLog); // no i18n
19
+ const addDiagnosticsInfoGuarded = guard('AppticsFeedback.addDiagnosticsInfo', addDiagnosticsInfo); // no i18n
20
+ const setFeedbackThemeGuarded = guard('AppticsFeedback.setFeedbackTheme', setFeedbackTheme); // no i18n
16
21
  /** Resolves once the feedback is sent; rejects when it wasn't (SDK not started, offline, refused). */
17
- const sendFeedback = guard('sendFeedback', function (...args) {
22
+ const sendFeedbackGuarded = guard('AppticsFeedback.sendFeedback', function (...args) {
18
23
  return ready().then(function (started) {
19
24
  if (!started) {
20
- throw new Error('apptics.sendFeedback: not sent, the SDK has not started; call init() first'); // no i18n
25
+ throw new Error('AppticsFeedback.sendFeedback: not sent, the SDK has not started; call Apptics.init() first'); // no i18n
21
26
  }
22
- return sendFeedback$1(...args);
27
+ return sendFeedback(...args);
23
28
  }).catch(function (err) {
24
- Console.error('apptics.sendFeedback failed:', err); // no i18n
29
+ Console.error('AppticsFeedback.sendFeedback failed:', err); // no i18n
25
30
  throw err;
26
31
  });
27
32
  });
28
- const feedback = { feedbackOpen, feedbackClose, sendFeedback };
33
+ /* each call a function of its own, with the parameter names the console shows (see forward) */
34
+ /**
35
+ * Android's AppticsFeedback: the form, sending feedback without it, and the context recorded for
36
+ * the next one. Every feedback call, addFeedbackLog and addDiagnosticsInfo included, is here and
37
+ * only here: the main entry has no AppticsFeedback.
38
+ */
39
+ const AppticsFeedback = {
40
+ /** The feedback types: BUG, FEEDBACK, HELP, REPORT. */
41
+ AP_FEEDBACK_TYPE: AP_FEEDBACK_TYPE,
42
+ feedbackFormOpen: function feedbackFormOpen(options) { return forward(feedbackFormOpenGuarded, arguments); },
43
+ feedbackFormClose: function feedbackFormClose() { return forward(feedbackFormCloseGuarded, arguments); },
44
+ sendFeedback: function sendFeedback(options) { return forward(sendFeedbackGuarded, arguments); },
45
+ addFeedbackLog: function addFeedbackLog(message) { return forward(addFeedbackLogGuarded, arguments); },
46
+ addDiagnosticsInfo: function addDiagnosticsInfo(heading, key, value) { return forward(addDiagnosticsInfoGuarded, arguments); },
47
+ /** The form's theme from now on, and of a form open now: 'light', 'dark' or 'auto'. */
48
+ setFeedbackTheme: function setFeedbackTheme(theme) { return forward(setFeedbackThemeGuarded, arguments); },
49
+ };
29
50
 
30
- export { feedback as default, feedbackClose, feedbackOpen, sendFeedback };
51
+ export { AppticsFeedback, AppticsFeedback as default };
@@ -15,26 +15,28 @@ export declare function trimStoredLogs(): Promise<void>;
15
15
  */
16
16
  export declare function addFeedbackLog(message: string): void;
17
17
  /**
18
- * Records a diagnostics key/value under a heading, sent inside dyninfo.txt.
19
- * Entries sharing a heading are grouped together in the file.
18
+ * Records a diagnostics entry, `value` under `key` in the `heading` block of dyninfo.txt. All three
19
+ * are required: an entry without a value says nothing, so it is refused and the console says why.
20
+ * A value of 0 or false is a value.
20
21
  */
21
- export declare function addDiagnosticsInfo(heading: string, key: string, value?: unknown): void;
22
+ export declare function addDiagnosticsInfo(heading: string, key: string, value: unknown): void;
22
23
  /** Removes every stored entry. */
23
24
  export declare function clearFeedbackLogs(): Promise<void>;
24
25
  /** Removes the entries a submission carried, by the ids the rendered files reported. */
25
- export declare function log_transactions_remove(sentIds: string[]): Promise<void>;
26
+ export declare function feedbacklog_transactions_remove(sentIds: string[]): Promise<void>;
26
27
  /** feedbacklog.txt from the stored log lines, or null when there are none. */
27
28
  export declare function toLogFile(): Promise<RenderedFile | null>;
28
- /** The log lines as the file would carry them, for showing in the modal before sending. */
29
+ /**
30
+ * The log lines for showing in the modal before sending, each time in the visitor's local zone.
31
+ * The file that is sent (toLogFile) keeps the ISO 8601 UTC stamps, so the server and anything
32
+ * that parses it are unaffected.
33
+ */
29
34
  export declare function logText(): Promise<string>;
30
- /** The diagnostics entries as dyninfo.txt would carry them, without the device info block. */
35
+ /** The diagnostics entries as dyninfo.txt carries them. */
31
36
  export declare function diagnosticsText(): Promise<string>;
32
37
  /** True when any log line is waiting, so the modal knows whether to offer the toggle. */
33
38
  export declare function hasLogLines(): Promise<boolean>;
34
- /**
35
- * dyninfo.txt: the stored diagnostics entries followed by a [Device Info] block holding
36
- * `deviceInfo`. Returns null only when there is nothing at all to put in it.
37
- */
38
- export declare function toDyninfoFile(deviceInfo: string | null): Promise<RenderedFile | null>;
39
+ /** dyninfo.txt: the stored diagnostics entries. Returns null when there are none. */
40
+ export declare function toDyninfoFile(): Promise<RenderedFile | null>;
39
41
  /** True when any diagnostics entry is waiting, so a submission knows to send dyninfo unasked. */
40
42
  export declare function hasDiagnostics(): Promise<boolean>;
@@ -1,6 +1,7 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
2
- import { Console } from '../core/logger.js';
3
- import { log_transactions } from '../core/storage.js';
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.2 | (c) Zoho Corporation Private Limited | see LICENSE */
2
+ import { warnAlways, Console } from '../core/logger.js';
3
+ import { FEEDBACK_LOG, FEEDBACK_DIAGNOSTICS } from '../core/db.js';
4
+ import { feedbacklog_transactions } from '../core/storage.js';
4
5
  import { isExpired } from '../core/state.js';
5
6
  import { nowMs } from '../core/utils.js';
6
7
 
@@ -24,18 +25,19 @@ const MAX_LOG_FILE_SIZE = 2 * 1024 * 1024;
24
25
  const TRIM_DELAY_MS = 2000;
25
26
  const LOG_FILE_NAME = 'feedbacklog.txt'; // no i18n
26
27
  const DYNINFO_FILE_NAME = 'dyninfo.txt'; // no i18n
27
- const LOG = 'log'; // no i18n
28
- const DIAGNOSTICS = 'diagnostics'; // no i18n
28
+ // the types the entries are stored under (2.0.0-beta and 1.x said log and diagnostics)
29
+ const LOG = FEEDBACK_LOG;
30
+ const DIAGNOSTICS = FEEDBACK_DIAGNOSTICS;
29
31
  let trimScheduled = false;
30
32
  /** Drops the oldest entries once the store is over MAX_ENTRIES. */
31
33
  function trimStoredLogs() {
32
- return log_transactions.all().then(function (items) {
34
+ return feedbacklog_transactions.all().then(function (items) {
33
35
  const excess = items.length - MAX_ENTRIES;
34
36
  if (excess <= 0) {
35
37
  return undefined;
36
38
  }
37
39
  Console.warn('apptics: dropping ' + excess + ' oldest feedback log entries (cap is ' + MAX_ENTRIES + ')'); // no i18n
38
- return log_transactions.remove(items.slice(0, excess));
40
+ return feedbacklog_transactions.remove(items.slice(0, excess));
39
41
  });
40
42
  }
41
43
  /** One trim per burst of adds, so a chatty app pays for one pass over the store, not one per line. */
@@ -50,7 +52,7 @@ function scheduleTrim() {
50
52
  }, TRIM_DELAY_MS);
51
53
  }
52
54
  function store(item) {
53
- log_transactions.add(item);
55
+ feedbacklog_transactions.add(item);
54
56
  scheduleTrim();
55
57
  }
56
58
  function truncate(text) {
@@ -70,11 +72,30 @@ function addFeedbackLog(message) {
70
72
  * Records a diagnostics key/value under a heading, sent inside dyninfo.txt.
71
73
  * Entries sharing a heading are grouped together in the file.
72
74
  */
75
+ /** Messages already printed, so a call repeated in a loop says so once. */
76
+ const refusedSaid = {};
77
+ function refuse(message) {
78
+ if (!refusedSaid[message]) {
79
+ refusedSaid[message] = true;
80
+ warnAlways('AppticsFeedback.addDiagnosticsInfo: ' + message + ', so the entry is not recorded'); // no i18n
81
+ }
82
+ }
83
+ /**
84
+ * Records a diagnostics entry, `value` under `key` in the `heading` block of dyninfo.txt. All three
85
+ * are required: an entry without a value says nothing, so it is refused and the console says why.
86
+ * A value of 0 or false is a value.
87
+ */
73
88
  function addDiagnosticsInfo(heading, key, value) {
74
89
  if (typeof heading !== 'string' || heading.length === 0) { // no i18n
90
+ refuse('a heading is required');
75
91
  return;
76
92
  }
77
93
  if (typeof key !== 'string' || key.length === 0) { // no i18n
94
+ refuse('a key is required');
95
+ return;
96
+ }
97
+ if (value === undefined || value === null || value === '') { // no i18n
98
+ refuse('a value is required for "' + heading + '" / "' + key + '"');
78
99
  return;
79
100
  }
80
101
  store({
@@ -82,16 +103,16 @@ function addDiagnosticsInfo(heading, key, value) {
82
103
  happenedat: nowMs(),
83
104
  heading: heading,
84
105
  key: key,
85
- value: truncate(String(value === undefined ? '' : value)), // no i18n
106
+ value: truncate(String(value)),
86
107
  });
87
108
  }
88
109
  /** Removes the entries a submission carried, by the ids the rendered files reported. */
89
- function log_transactions_remove(sentIds) {
90
- return log_transactions.remove(sentIds.map(function (id) { return { id: id }; }));
110
+ function feedbacklog_transactions_remove(sentIds) {
111
+ return feedbacklog_transactions.remove(sentIds.map(function (id) { return { id: id }; }));
91
112
  }
92
113
  /** Entries of one type, oldest first, skipping any that have passed batch_request_timeout. */
93
114
  function entriesOfType(type) {
94
- return log_transactions.all().then(function (items) {
115
+ return feedbacklog_transactions.all().then(function (items) {
95
116
  return items.filter(function (item) {
96
117
  return item.type === type && !isExpired(item.happenedat);
97
118
  });
@@ -145,11 +166,29 @@ function toLogFile() {
145
166
  return asFile(LOG_FILE_NAME, renderLogLines(items), items);
146
167
  });
147
168
  }
148
- /** The log lines as the file would carry them, for showing in the modal before sending. */
169
+ /** `16 Oct 2026, 11:53:48 PM`: a log line's time in the visitor's own zone, for the viewer. */
170
+ function readableStamp(item) {
171
+ var iso = stamp(item);
172
+ var d = new Date(iso);
173
+ if (isNaN(d.getTime())) {
174
+ return iso;
175
+ }
176
+ return d.toLocaleDateString(undefined, { day: '2-digit', month: 'short', year: 'numeric' }) + ', ' + // no i18n
177
+ d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit', second: '2-digit' }); // no i18n
178
+ }
179
+ /**
180
+ * The log lines for showing in the modal before sending, each time in the visitor's local zone.
181
+ * The file that is sent (toLogFile) keeps the ISO 8601 UTC stamps, so the server and anything
182
+ * that parses it are unaffected.
183
+ */
149
184
  function logText() {
150
- return entriesOfType(LOG).then(renderLogLines);
185
+ return entriesOfType(LOG).then(function (items) {
186
+ return items.map(function (item) {
187
+ return '[' + readableStamp(item) + '] ' + item.message; // no i18n
188
+ }).join('\n'); // no i18n
189
+ });
151
190
  }
152
- /** The diagnostics entries as dyninfo.txt would carry them, without the device info block. */
191
+ /** The diagnostics entries as dyninfo.txt carries them. */
153
192
  function diagnosticsText() {
154
193
  return entriesOfType(DIAGNOSTICS).then(groupDiagnostics);
155
194
  }
@@ -159,23 +198,13 @@ function hasLogLines() {
159
198
  return items.length > 0;
160
199
  });
161
200
  }
162
- /**
163
- * dyninfo.txt: the stored diagnostics entries followed by a [Device Info] block holding
164
- * `deviceInfo`. Returns null only when there is nothing at all to put in it.
165
- */
166
- function toDyninfoFile(deviceInfo) {
201
+ /** dyninfo.txt: the stored diagnostics entries. Returns null when there are none. */
202
+ function toDyninfoFile() {
167
203
  return entriesOfType(DIAGNOSTICS).then(function (items) {
168
- const blocks = [];
169
- if (items.length > 0) {
170
- blocks.push(groupDiagnostics(items));
171
- }
172
- if (deviceInfo) {
173
- blocks.push('[Device Info]\n' + deviceInfo); // no i18n
174
- }
175
- if (blocks.length === 0) {
204
+ if (items.length === 0) {
176
205
  return null;
177
206
  }
178
- return asFile(DYNINFO_FILE_NAME, blocks.join('\n\n'), items); // no i18n
207
+ return asFile(DYNINFO_FILE_NAME, groupDiagnostics(items), items);
179
208
  });
180
209
  }
181
210
  /** True when any diagnostics entry is waiting, so a submission knows to send dyninfo unasked. */
@@ -185,4 +214,4 @@ function hasDiagnostics() {
185
214
  });
186
215
  }
187
216
 
188
- export { DYNINFO_FILE_NAME, LOG_FILE_NAME, MAX_LOG_FILE_SIZE, addDiagnosticsInfo, addFeedbackLog, diagnosticsText, hasDiagnostics, hasLogLines, logText, log_transactions_remove, toDyninfoFile, toLogFile, trimStoredLogs };
217
+ export { DYNINFO_FILE_NAME, LOG_FILE_NAME, MAX_LOG_FILE_SIZE, addDiagnosticsInfo, addFeedbackLog, diagnosticsText, feedbacklog_transactions_remove, hasDiagnostics, hasLogLines, logText, toDyninfoFile, toLogFile, trimStoredLogs };
@@ -0,0 +1,18 @@
1
+ /** quartz_domain as a recording host: zoho.com → https://quartz.zoho.com. '' when it isn't a domain. */
2
+ export declare function recordingDomain(domain: string): string;
3
+ /**
4
+ * The Quartz script for an app whose getsdkconfig answer carries no quartz_cdn_url, chosen by
5
+ * the serviceUrl: a localzoho server's apps load it from Zoho's local CDN, every other app from
6
+ * the public one.
7
+ */
8
+ export declare function defaultQuartzScriptUrl(serviceUrl: string): string;
9
+ /** The script to load: quartz_cdn_url when getsdkconfig gave one, else the CDN the serviceUrl points to. */
10
+ export declare function quartzScriptSource(cdnUrl: string, serviceUrl: string): string;
11
+ /** The url to load, or '' when it isn't an https url on a Zoho host. */
12
+ export declare function quartzScriptUrl(url: string): string;
13
+ /**
14
+ * Makes Quartz available: resolves true once it is on the page, false when it can't be (no url,
15
+ * a url that isn't allowed, or a script that failed to load). Adds the script once; every caller
16
+ * waits on the same load, and a failed one may be tried again on the next open.
17
+ */
18
+ export declare function loadQuartz(url: string): Promise<boolean>;