@joystick.js/ui-canary 0.0.0-canary.25 → 0.0.0-canary.250

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 (231) hide show
  1. package/build.js +15 -0
  2. package/dist/index.js +20 -20
  3. package/increment_version.js +3 -0
  4. package/index.html +7 -0
  5. package/package.json +9 -13
  6. package/src/accounts/authenticated.js +8 -0
  7. package/src/accounts/index.js +21 -0
  8. package/src/accounts/login.js +7 -0
  9. package/src/accounts/logout.js +8 -0
  10. package/src/accounts/recover_password.js +7 -0
  11. package/src/accounts/request.js +70 -0
  12. package/src/accounts/reset_password.js +7 -0
  13. package/src/accounts/signup.js +7 -0
  14. package/src/accounts/user.js +8 -0
  15. package/src/api/get.js +73 -0
  16. package/src/api/index.js +10 -0
  17. package/src/api/set.js +83 -0
  18. package/src/attach_joystick_to_window.js +31 -0
  19. package/src/cache/class.js +98 -0
  20. package/src/cache/index.js +5 -0
  21. package/src/component/class.js +360 -0
  22. package/src/component/css/compile.js +108 -0
  23. package/src/component/data/compile.js +44 -0
  24. package/src/component/data/fetch.js +12 -0
  25. package/src/component/data/load_data_from_window.js +13 -0
  26. package/src/component/dom/is_valid_attribute_name.js +11 -0
  27. package/src/component/events/attach_event_listener_for_element.js +32 -0
  28. package/src/component/events/serialize.js +12 -0
  29. package/src/component/index.js +17 -0
  30. package/src/component/methods/compile.js +28 -0
  31. package/src/component/props/compile.js +21 -0
  32. package/src/component/props/compile_default.js +21 -0
  33. package/src/component/register_component_options.js +44 -0
  34. package/src/component/render_methods/component.js +53 -0
  35. package/src/component/render_methods/component_ssr.js +22 -0
  36. package/src/component/render_methods/each.js +19 -0
  37. package/src/component/render_methods/i18n.js +50 -0
  38. package/src/component/render_methods/index.js +19 -0
  39. package/src/component/render_methods/when.js +20 -0
  40. package/src/component/state/compile.js +21 -0
  41. package/src/component/url/compile.js +39 -0
  42. package/src/component/validate_component_options/has_required_options.js +9 -0
  43. package/src/component/validate_component_options/index.js +16 -0
  44. package/src/component/validate_component_options/required_options.js +5 -0
  45. package/src/component/virtual_dom/diff.js +64 -0
  46. package/src/component/virtual_dom/diff_attributes.js +37 -0
  47. package/src/component/virtual_dom/diff_children.js +74 -0
  48. package/src/component/virtual_dom/element_patch_functions.js +31 -0
  49. package/src/component/virtual_dom/map_patch_functions_to_nodes.js +14 -0
  50. package/src/component/virtual_dom/render_virtual_dom_to_dom.js +37 -0
  51. package/src/external/get.js +9 -0
  52. package/src/external/track.js +10 -0
  53. package/src/forms/validate.js +306 -0
  54. package/src/forms/validators/credit_card.js +19 -0
  55. package/src/forms/validators/custom.js +5 -0
  56. package/src/forms/validators/email.js +12 -0
  57. package/src/forms/validators/equals.js +5 -0
  58. package/src/forms/validators/index.js +43 -0
  59. package/src/forms/validators/matches.js +5 -0
  60. package/src/forms/validators/max_length.js +5 -0
  61. package/src/forms/validators/min_length.js +5 -0
  62. package/src/forms/validators/phone.js +14 -0
  63. package/src/forms/validators/postal_code.js +204 -0
  64. package/src/forms/validators/regex.js +5 -0
  65. package/src/forms/validators/required.js +13 -0
  66. package/src/forms/validators/semver.js +14 -0
  67. package/src/forms/validators/slug.js +12 -0
  68. package/src/forms/validators/strong_password.js +12 -0
  69. package/src/forms/validators/url.js +12 -0
  70. package/src/forms/validators/vat.js +54 -0
  71. package/src/index.js +55 -0
  72. package/src/lib/constants.js +13 -0
  73. package/src/lib/debounce.js +9 -0
  74. package/src/lib/generate_cookie_header.js +7 -0
  75. package/src/lib/generate_id.js +15 -0
  76. package/src/lib/get_joystick_environment.js +13 -0
  77. package/src/lib/log_request_errors.js +15 -0
  78. package/src/lib/nested_object_diff.js +164 -0
  79. package/src/lib/parse_json.js +12 -0
  80. package/src/lib/throw_framework_error.js +5 -0
  81. package/src/lib/types.js +59 -0
  82. package/src/mount/index.js +45 -0
  83. package/src/test/create_file.js +10 -0
  84. package/src/test/index.js +13 -0
  85. package/src/test/track_function_call.js +16 -0
  86. package/src/tree/add_node_to_tree.js +6 -0
  87. package/src/tree/clean_up.js +11 -0
  88. package/src/tree/get_child_instance_ids.js +7 -0
  89. package/src/tree/get_children_from_tree.js +25 -0
  90. package/src/tree/get_css_from_tree.js +43 -0
  91. package/src/tree/get_event_listeners_for_nodes.js +15 -0
  92. package/src/tree/get_node_from_tree.js +7 -0
  93. package/src/tree/get_parent_from_tree.js +8 -0
  94. package/src/tree/jobs/index.js +196 -0
  95. package/src/tree/jobs/run.js +11 -0
  96. package/src/tree/replace_child_in_vdom.js +18 -0
  97. package/src/upload/index.js +72 -0
  98. package/src/websockets/client.js +125 -0
  99. package/src/websockets/register_on_component.js +27 -0
  100. package/test.js +145 -0
  101. package/README.md +0 -8
  102. package/_package.json +0 -26
  103. package/canary.js +0 -12
  104. package/dist/accounts/authenticated.js +0 -1
  105. package/dist/accounts/index.js +0 -1
  106. package/dist/accounts/login.js +0 -1
  107. package/dist/accounts/logout.js +0 -1
  108. package/dist/accounts/recoverPassword.js +0 -1
  109. package/dist/accounts/request.js +0 -1
  110. package/dist/accounts/resetPassword.js +0 -1
  111. package/dist/accounts/signup.js +0 -1
  112. package/dist/accounts/user.js +0 -1
  113. package/dist/api/get.js +0 -1
  114. package/dist/api/index.js +0 -1
  115. package/dist/api/set.js +0 -1
  116. package/dist/attachJoystickToWindow.js +0 -1
  117. package/dist/cache/class.js +0 -1
  118. package/dist/cache/index.js +0 -1
  119. package/dist/component/class/css/compile.js +0 -21
  120. package/dist/component/class/css/prefix.js +0 -1
  121. package/dist/component/class/data/compile.js +0 -1
  122. package/dist/component/class/data/fetch.js +0 -1
  123. package/dist/component/class/data/findComponentDataFromSSR.js +0 -1
  124. package/dist/component/class/data/loadDataFromWindow.js +0 -1
  125. package/dist/component/class/events/_registerListeners.js +0 -1
  126. package/dist/component/class/events/_unregisterListeners.js +0 -1
  127. package/dist/component/class/events/registerListeners.js +0 -1
  128. package/dist/component/class/events/serialize.js +0 -1
  129. package/dist/component/class/events/unregisterListeners.js +0 -1
  130. package/dist/component/class/index.js +0 -21
  131. package/dist/component/class/lifecycle/compile.js +0 -1
  132. package/dist/component/class/methods/compile.js +0 -1
  133. package/dist/component/class/options/allowedComponentOptions.js +0 -1
  134. package/dist/component/class/options/allowedDOMEvents.js +0 -1
  135. package/dist/component/class/options/allowedLifecycleMethods.js +0 -1
  136. package/dist/component/class/options/defaultLifecycleMethods.js +0 -1
  137. package/dist/component/class/options/hasAllRequiredOptions.js +0 -1
  138. package/dist/component/class/options/registerOptions.js +0 -21
  139. package/dist/component/class/options/requiredOptions.js +0 -1
  140. package/dist/component/class/options/validateOptions.js +0 -1
  141. package/dist/component/class/options/validators/css.js +0 -1
  142. package/dist/component/class/options/validators/events.js +0 -1
  143. package/dist/component/class/options/validators/index.js +0 -1
  144. package/dist/component/class/options/validators/lifecycle.js +0 -1
  145. package/dist/component/class/options/validators/methods.js +0 -1
  146. package/dist/component/class/options/validators/name.js +0 -1
  147. package/dist/component/class/options/validators/render.js +0 -1
  148. package/dist/component/class/options/validators/websockets.js +0 -1
  149. package/dist/component/class/options/validators/wrapper.js +0 -1
  150. package/dist/component/class/props/compile.js +0 -1
  151. package/dist/component/class/props/compileDefault.js +0 -1
  152. package/dist/component/class/render/clearTimersOnChildren.js +0 -1
  153. package/dist/component/class/render/forMount.js +0 -1
  154. package/dist/component/class/render/getExistingPropsMap.js +0 -1
  155. package/dist/component/class/render/getExistingStateMap.js +0 -1
  156. package/dist/component/class/render/getUpdatedDOM.js +0 -1
  157. package/dist/component/class/render/sanitizeHTML.js +0 -1
  158. package/dist/component/class/render/toHTML.js +0 -1
  159. package/dist/component/class/render/wrapHTML.js +0 -1
  160. package/dist/component/class/renderMethods/compile.js +0 -1
  161. package/dist/component/class/renderMethods/component.js +0 -1
  162. package/dist/component/class/renderMethods/dragDrop/attachEventListeners.js +0 -1
  163. package/dist/component/class/renderMethods/dragDrop/concept.js +0 -0
  164. package/dist/component/class/renderMethods/dragDrop/draggable.js +0 -1
  165. package/dist/component/class/renderMethods/dragDrop/droppable.js +0 -1
  166. package/dist/component/class/renderMethods/dragDrop/index.js +0 -1
  167. package/dist/component/class/renderMethods/dragDrop/isBefore.js +0 -1
  168. package/dist/component/class/renderMethods/each.js +0 -1
  169. package/dist/component/class/renderMethods/i18n.js +0 -1
  170. package/dist/component/class/renderMethods/index.js +0 -1
  171. package/dist/component/class/renderMethods/when.js +0 -1
  172. package/dist/component/class/state/compile.js +0 -1
  173. package/dist/component/class/url/compile.js +0 -1
  174. package/dist/component/class/virtualDOM/build.js +0 -1
  175. package/dist/component/class/virtualDOM/buildTree.js +0 -1
  176. package/dist/component/class/virtualDOM/diff/attributes.js +0 -1
  177. package/dist/component/class/virtualDOM/diff/children.js +0 -1
  178. package/dist/component/class/virtualDOM/diff/elementPatchFunctions.js +0 -1
  179. package/dist/component/class/virtualDOM/diff/index.js +0 -1
  180. package/dist/component/class/virtualDOM/diff/mapPatchFunctionsToNodes.js +0 -1
  181. package/dist/component/class/virtualDOM/renderTreeToDOM.js +0 -1
  182. package/dist/component/index.js +0 -21
  183. package/dist/component/renderComponentToHTML.js +0 -1
  184. package/dist/component/tree/addChildToParent.js +0 -1
  185. package/dist/component/tree/clearChildrenOnParent.js +0 -1
  186. package/dist/component/tree/findComponentInTreeByField.js +0 -1
  187. package/dist/component/tree/replaceChildInVDOMTree.js +0 -1
  188. package/dist/component/tree/updateParentInstanceInTree.js +0 -1
  189. package/dist/css/getCSSFromTree.js +0 -21
  190. package/dist/css/update.js +0 -21
  191. package/dist/forms/validate.js +0 -1
  192. package/dist/forms/validators/creditCard.js +0 -1
  193. package/dist/forms/validators/email.js +0 -1
  194. package/dist/forms/validators/equals.js +0 -1
  195. package/dist/forms/validators/index.js +0 -1
  196. package/dist/forms/validators/matches.js +0 -1
  197. package/dist/forms/validators/maxLength.js +0 -1
  198. package/dist/forms/validators/minLength.js +0 -1
  199. package/dist/forms/validators/phone.js +0 -1
  200. package/dist/forms/validators/postalCode.js +0 -1
  201. package/dist/forms/validators/required.js +0 -1
  202. package/dist/forms/validators/semVer.js +0 -1
  203. package/dist/forms/validators/slug.js +0 -1
  204. package/dist/forms/validators/strongPassword.js +0 -1
  205. package/dist/forms/validators/types.js +0 -1
  206. package/dist/forms/validators/url.js +0 -1
  207. package/dist/forms/validators/vat.js +0 -1
  208. package/dist/html/index.js +0 -1
  209. package/dist/lib/addToQueue.js +0 -1
  210. package/dist/lib/assignOptionsToInstance.js +0 -1
  211. package/dist/lib/constants.js +0 -1
  212. package/dist/lib/debounce.js +0 -1
  213. package/dist/lib/generateId.js +0 -1
  214. package/dist/lib/isNode.js +0 -1
  215. package/dist/lib/isValidAttributeName.js +0 -1
  216. package/dist/lib/logRequestErrors.js +0 -1
  217. package/dist/lib/parseJSON.js +0 -1
  218. package/dist/lib/processQueue.js +0 -1
  219. package/dist/lib/queueArray.js +0 -1
  220. package/dist/lib/serializeEvents.js +0 -1
  221. package/dist/lib/stringContainsHTML.js +0 -1
  222. package/dist/lib/throttle.js +0 -1
  223. package/dist/lib/throwFrameworkError.js +0 -1
  224. package/dist/lib/types.js +0 -1
  225. package/dist/lib/windowIsUndefined.js +0 -1
  226. package/dist/mount/appendToTarget.js +0 -1
  227. package/dist/mount/index.js +0 -1
  228. package/dist/mount/initializeJoystickComponentTree.js +0 -1
  229. package/dist/overrideTimers.js +0 -1
  230. package/dist/upload/index.js +0 -1
  231. package/dist/websockets/client.js +0 -1
@@ -0,0 +1,59 @@
1
+ const is_any = (value) => {
2
+ return !!value;
3
+ };
4
+
5
+ const is_array = (value) => {
6
+ return !!Array.isArray(value);
7
+ };
8
+
9
+ const is_boolean = (value) => {
10
+ return (value === true || value === false);
11
+ };
12
+
13
+ const is_float = (value) => {
14
+ return Number(value) === value && value % 1 !== 0;
15
+ };
16
+
17
+ const is_function = (value) => {
18
+ return typeof value === 'function';
19
+ };
20
+
21
+ const is_integer = (value) => {
22
+ return Number(value) === value && value % 1 === 0;
23
+ };
24
+
25
+ const is_null = (value) => {
26
+ return value === null;
27
+ };
28
+
29
+ const is_number = (value) => {
30
+ return Number(value) === value;
31
+ };
32
+
33
+ const is_object = (value) => {
34
+ return !!(value && typeof value === "object" && !Array.isArray(value));
35
+ };
36
+
37
+ const is_string = (value) => {
38
+ return typeof value === "string";
39
+ };
40
+
41
+ const is_undefined = (value) => {
42
+ return typeof value === 'undefined';
43
+ };
44
+
45
+ const types = {
46
+ is_any,
47
+ is_array,
48
+ is_boolean,
49
+ is_float,
50
+ is_function,
51
+ is_integer,
52
+ is_null,
53
+ is_number,
54
+ is_object,
55
+ is_string,
56
+ is_undefined,
57
+ };
58
+
59
+ export default types;
@@ -0,0 +1,45 @@
1
+ import add_node_to_tree from "../tree/add_node_to_tree.js";
2
+ import run_tree_job from '../tree/jobs/run.js';
3
+ import track_function_call from "../test/track_function_call.js";
4
+
5
+ const mount_to_target = (dom_node = {}, target = {}) => {
6
+ target.replaceChildren();
7
+ target.appendChild(dom_node);
8
+ };
9
+
10
+ const mount = (Component, props = {}, target = {}) => {
11
+ track_function_call(`ui.mount`, [
12
+ Component,
13
+ props,
14
+ target,
15
+ ]);
16
+
17
+ // NOTE: Dump the component tree on mount to account for remounting via HMR. This ensures we
18
+ // don't keep old node references in the tree which can trip up renders matching on the
19
+ // wrong/old element.
20
+ run_tree_job('reset_tree_for_hmr');
21
+
22
+ const component_instance = Component({ props });
23
+ const dom = component_instance.render_for_mount();
24
+
25
+ add_node_to_tree(component_instance);
26
+
27
+ run_tree_job('lifecycle.onBeforeMount', { root_instance_id: component_instance?.instance_id });
28
+ run_tree_job('lifecycle.onBeforeRender', { root_instance_id: component_instance?.instance_id });
29
+ run_tree_job('css', { is_mount: true });
30
+
31
+ mount_to_target(dom, target);
32
+
33
+ run_tree_job('attach_event_listeners', { root_instance_id: component_instance?.instance_id });
34
+
35
+ run_tree_job('lifecycle.onMount', { root_instance_id: component_instance?.instance_id });
36
+ run_tree_job('lifecycle.onRender', { root_instance_id: component_instance?.instance_id });
37
+
38
+ window.addEventListener('beforeunload', () => {
39
+ run_tree_job('lifecycle.onBeforeUnmount', { root_instance_id: component_instance?.instance_id });
40
+ });
41
+
42
+ return component_instance;
43
+ };
44
+
45
+ export default mount;
@@ -0,0 +1,10 @@
1
+ const create_file = (bytes = 128, file_name = 'test.txt', mime_type = 'text/plain') => {
2
+ const is_blob = bytes instanceof Blob;
3
+ return new File(
4
+ is_blob ? bytes : new Blob(new Uint8Array(bytes || 128), { type: mime_type }),
5
+ file_name,
6
+ { type: mime_type }
7
+ );
8
+ };
9
+
10
+ export default create_file;
@@ -0,0 +1,13 @@
1
+ import create_file from "./create_file.js";
2
+ import track_function_call from "./track_function_call.js";
3
+
4
+ const test = {
5
+ utils: {
6
+ createFile: create_file,
7
+ create_file,
8
+ trackFunctionCall: track_function_call,
9
+ track_function_call,
10
+ },
11
+ };
12
+
13
+ export default test;
@@ -0,0 +1,16 @@
1
+ const track_function_call = (path = '', args = []) => {
2
+ if (typeof window !== 'undefined' && !!window.__joystick_test__) {
3
+ window.test = {
4
+ ...(window.test || {}),
5
+ function_calls: {
6
+ ...(window?.test?.function_calls || {}),
7
+ [path]: [
8
+ ...((window?.test?.function_calls && window?.test?.function_calls[path]) || []),
9
+ { called_at: new Date().toISOString(), args },
10
+ ]
11
+ }
12
+ };
13
+ }
14
+ };
15
+
16
+ export default track_function_call;
@@ -0,0 +1,6 @@
1
+ const add_node_to_tree = (node = {}, ssr_tree = null) => {
2
+ const tree_on_window = typeof window !== 'undefined' ? window.joystick._internal.tree : [];
3
+ (ssr_tree || tree_on_window).push(node);
4
+ };
5
+
6
+ export default add_node_to_tree;
@@ -0,0 +1,11 @@
1
+ import get_child_instance_ids from "./get_child_instance_ids.js";
2
+
3
+ const clean_up = (existing_children = {}) => {
4
+ const existing_children_instance_ids = get_child_instance_ids(existing_children);
5
+
6
+ joystick._internal.tree = joystick?._internal?.tree?.filter((node) => {
7
+ return !existing_children_instance_ids?.includes(node?.instance_id);
8
+ });
9
+ };
10
+
11
+ export default clean_up;
@@ -0,0 +1,7 @@
1
+ const get_child_instance_ids = (children = {}) => {
2
+ return Object.values(children)?.flatMap((child_instance_ids = []) => {
3
+ return child_instance_ids;
4
+ });
5
+ };
6
+
7
+ export default get_child_instance_ids;
@@ -0,0 +1,25 @@
1
+ import get_child_instance_ids from "./get_child_instance_ids.js";
2
+
3
+ const get_children_from_tree = (child_instance_ids = [], existing_child_nodes = []) => {
4
+ const child_nodes = existing_child_nodes || [];
5
+
6
+ const child_nodes_matching_instance_ids = window?.joystick?._internal?.tree?.filter((node) => {
7
+ return child_instance_ids?.includes(node?.instance_id);
8
+ });
9
+
10
+ for (let i = 0; i < child_nodes_matching_instance_ids?.length; i += 1) {
11
+ const child_node = child_nodes_matching_instance_ids[i];
12
+
13
+ child_nodes.push(child_node);
14
+
15
+ const child_node_children_instance_ids = get_child_instance_ids(child_node.children);
16
+
17
+ if (child_node_children_instance_ids?.length > 0) {
18
+ get_children_from_tree(child_node_children_instance_ids, child_nodes);
19
+ }
20
+ }
21
+
22
+ return child_nodes;
23
+ };
24
+
25
+ export default get_children_from_tree;
@@ -0,0 +1,43 @@
1
+ import compile_css from "../component/css/compile.js";
2
+ import constants from "../lib/constants.js";
3
+
4
+ const handle_prefix_css = (component_id, css_string) => {
5
+ return (css_string || "")
6
+ .replace(constants.CSS_COMMENT_REGEX, () => {
7
+ return "";
8
+ })
9
+ .replace(constants.CSS_SELECTOR_REGEX, (match) => {
10
+ if (["@", ": "].some((skip) => match?.includes(skip))) {
11
+ return match;
12
+ }
13
+
14
+ return `[js-c="${component_id}"] ${match.trim()}`;
15
+ })
16
+ // NOTE: Use @wrapper as a placeholder target for assigning styles
17
+ // to the Joystick component's root wrapper element.
18
+ .replace(/@wrapper/g, `[js-c="${component_id}"]`)
19
+ ?.trim();
20
+ };
21
+
22
+ const get_css_from_tree = (tree = [], css = [], is_email = false) => {
23
+ for (let i = 0; i < tree?.length; i += 1) {
24
+ const node = tree[i];
25
+
26
+ if (node?.css) {
27
+ const component_id = node?.id;
28
+ const raw_css = node.options.css;
29
+ const compiled_css = compile_css(raw_css, node);
30
+ const prefixed_css = !is_email ? handle_prefix_css(component_id, compiled_css) : null;
31
+
32
+ if (is_email) {
33
+ css.push(compiled_css);
34
+ } else {
35
+ css.push(prefixed_css);
36
+ }
37
+ }
38
+ }
39
+
40
+ return css;
41
+ };
42
+
43
+ export default get_css_from_tree;
@@ -0,0 +1,15 @@
1
+ import serialize_events from "../component/events/serialize.js";
2
+
3
+ const get_event_listeners_for_nodes = (nodes = []) => {
4
+ return nodes?.flatMap((node) => {
5
+ const events_for_node = serialize_events(node?.events);
6
+ return events_for_node?.flatMap((event_for_node) => {
7
+ return {
8
+ instance: node,
9
+ ...event_for_node,
10
+ };
11
+ });
12
+ });
13
+ };
14
+
15
+ export default get_event_listeners_for_nodes;
@@ -0,0 +1,7 @@
1
+ const get_node_from_tree = (instance_id = '') => {
2
+ return window?.joystick?._internal?.tree?.find((node) => {
3
+ return node?.instance_id === instance_id;
4
+ });
5
+ };
6
+
7
+ export default get_node_from_tree;
@@ -0,0 +1,8 @@
1
+ const get_parent_from_tree = (child_component_id = '', child_instance_id = '') => {
2
+ return joystick?._internal?.tree?.find((node) => {
3
+ const children_of_component_id = node?.children[child_component_id];
4
+ return children_of_component_id && children_of_component_id?.includes(child_instance_id);
5
+ });
6
+ };
7
+
8
+ export default get_parent_from_tree;
@@ -0,0 +1,196 @@
1
+ import attach_event_listener_for_element from "../../component/events/attach_event_listener_for_element.js";
2
+ import get_child_instance_ids from "../get_child_instance_ids.js";
3
+ import get_children_from_tree from "../get_children_from_tree.js";
4
+ import get_css_from_tree from "../get_css_from_tree.js";
5
+ import get_event_listeners_for_nodes from "../get_event_listeners_for_nodes.js";
6
+ import get_node_from_tree from "../get_node_from_tree.js";
7
+ import generate_id from "../../lib/generate_id.js";
8
+ import track_function_call from "../../test/track_function_call.js";
9
+ import types from "../../lib/types.js";
10
+
11
+ const get_nodes_for_job = (root_instance_id = '') => {
12
+ const node = get_node_from_tree(root_instance_id);
13
+ const child_instance_ids = get_child_instance_ids(node?.children);
14
+ const child_nodes = get_children_from_tree(child_instance_ids);
15
+
16
+ return [
17
+ node,
18
+ ...(child_nodes || []),
19
+ ];
20
+ };
21
+
22
+ const clear_timers = (root_instance_id = null, existing_tree = null) => {
23
+ // NOTE: If we call this as part of reset_tree_for_hmr, we want to wipe out ALL timers
24
+ // on the tree (the original root instance gets delete on remount).
25
+ const nodes = root_instance_id && !existing_tree ? get_nodes_for_job(root_instance_id) : (existing_tree || []);
26
+ const timers = nodes?.flatMap((node) => {
27
+ return node?.timers ? Object.values(node?.timers) : [];
28
+ });
29
+
30
+ for (let i = 0; i < timers?.length; i += 1) {
31
+ const timer_id = timers[i];
32
+ // NOTE: Modern browsers should support both of these the same,
33
+ // but to guarantee timers get cleared, run both on the timer_id.
34
+ clearTimeout(timer_id);
35
+ clearInterval(timer_id);
36
+ }
37
+ };
38
+
39
+ const clear_websockets = () => {
40
+ // NOTE: If we call this as part of reset_tree_for_hmr, we want to wipe out ALL timers
41
+ // on the tree (the original root instance gets delete on remount).
42
+ const websockets = window.__joystick_hmr_previous_websockets__;
43
+ for (let i = 0; i < websockets?.length; i += 1) {
44
+ const websocket = websockets[i];
45
+ if (websocket?.client?.close && types.is_function(websocket?.client?.close)) {
46
+ websocket.client.close(1000);
47
+ }
48
+ }
49
+ };
50
+
51
+ const jobs = {
52
+ 'attach_event_listeners': ({ root_instance_id }) => {
53
+ const nodes = window?.joystick?._internal?.tree;
54
+ const event_listeners = get_event_listeners_for_nodes(nodes);
55
+
56
+ for (let i = 0; i < event_listeners?.length; i += 1) {
57
+ const event_listener = event_listeners[i];
58
+ const elements = document.querySelectorAll(`[js-i="${event_listener?.instance?.instance_id}"] ${event_listener?.selector}`);
59
+ const render_methods = event_listener?.instance?.compile_render_methods();
60
+
61
+ for (let i = 0; i < elements?.length; i += 1) {
62
+ const element = elements[i];
63
+ attach_event_listener_for_element(event_listener, element, render_methods);
64
+ }
65
+ }
66
+
67
+ return event_listeners;
68
+ },
69
+ 'clear_timers': ({ root_instance_id = null }) => {
70
+ clear_timers(root_instance_id);
71
+ },
72
+ 'clear_websockets': ({ root_instance_id = null }) => {
73
+ clear_websockets();
74
+ },
75
+ 'css': ({ is_mount = false, is_email = false, ssr_tree = null }) => {
76
+ const existing_style_tag = typeof window !== 'undefined' ? document.head.querySelector(`style[js-css]`) : null;
77
+ const css_from_tree = get_css_from_tree(ssr_tree || window.joystick?._internal?.tree, [], is_email);
78
+ const css = is_mount ? css_from_tree?.reverse().join("").trim() : css_from_tree?.join("").trim();
79
+
80
+ if (typeof window !== 'undefined' && existing_style_tag?.innerText === css) {
81
+ // NOTE: No changes, do not update CSS in DOM.
82
+ return;
83
+ }
84
+
85
+ if (typeof window !== 'undefined' && existing_style_tag) {
86
+ existing_style_tag.innerHTML = css;
87
+ }
88
+
89
+ if (typeof window !== 'undefined' && !existing_style_tag) {
90
+ const style = document.createElement("style");
91
+ style.setAttribute("js-styles", "");
92
+ style.innerHTML = css;
93
+ document.head.appendChild(style);
94
+ }
95
+
96
+ return css;
97
+ },
98
+ 'detach_event_listeners': ({ root_instance_id }) => {
99
+ const nodes = window?.joystick?._internal?.tree;
100
+ const event_listeners = nodes?.filter((node) => {
101
+ return !!node?._event_listeners;
102
+ }).flatMap((node) => {
103
+ return node?._event_listeners;
104
+ });
105
+
106
+ for (let i = 0; i < event_listeners?.length; i += 1) {
107
+ const event_listener = event_listeners[i];
108
+ event_listener.element.removeEventListener(event_listener?.type, event_listener?.handler);
109
+ }
110
+ },
111
+ 'lifecycle.onBeforeMount': ({ root_instance_id }) => {
112
+ const nodes = get_nodes_for_job(root_instance_id);
113
+
114
+ for (let i = 0; i < nodes?.length; i += 1) {
115
+ const node = nodes[i];
116
+ if (types.is_function(node?.lifecycle?.onBeforeMount) || types.is_function(node?.lifecycle?.on_before_mount)) {
117
+ (node.lifecycle.onBeforeMount || node.lifecycle.on_before_mount)(node);
118
+ track_function_call(`ui.${node?.options?.test?.name || generate_id()}.lifecycle.on_before_mount`, [node]);
119
+ }
120
+ }
121
+ },
122
+ 'lifecycle.onMount': ({ root_instance_id }) => {
123
+ const nodes = get_nodes_for_job(root_instance_id);
124
+
125
+ for (let i = 0; i < nodes?.length; i += 1) {
126
+ const node = nodes[i];
127
+ if (types.is_function(node?.lifecycle?.onMount) || types.is_function(node?.lifecycle?.on_mount)) {
128
+ (node.lifecycle.onMount || node.lifecycle.on_mount)(node);
129
+ track_function_call(`ui.${node?.options?.test?.name || generate_id()}.lifecycle.on_mount`, [node]);
130
+ }
131
+ }
132
+ },
133
+ 'lifecycle.onBeforeRender': ({ root_instance_id }) => {
134
+ const nodes = get_nodes_for_job(root_instance_id);
135
+
136
+ for (let i = 0; i < nodes?.length; i += 1) {
137
+ const node = nodes[i];
138
+ if (types.is_function(node?.lifecycle?.onBeforeRender) || types.is_function(node?.lifecycle?.on_before_render)) {
139
+ (node.lifecycle.onBeforeRender || node.lifecycle.on_before_render)(node);
140
+ track_function_call(`ui.${node?.options?.test?.name || generate_id()}.lifecycle.on_before_render`, [node]);
141
+ }
142
+ }
143
+ },
144
+ 'lifecycle.onRender': ({ root_instance_id }) => {
145
+ const nodes = get_nodes_for_job(root_instance_id);
146
+
147
+ for (let i = 0; i < nodes?.length; i += 1) {
148
+ const node = nodes[i];
149
+ if (types.is_function(node?.lifecycle?.onRender) || types.is_function(node?.lifecycle?.on_render)) {
150
+ (node.lifecycle.onRender || node.lifecycle.on_render)(node);
151
+ track_function_call(`ui.${node?.options?.test?.name || generate_id()}.lifecycle.on_render`, [node]);
152
+ }
153
+ }
154
+ },
155
+ 'lifecycle.onUpdateProps': ({ root_instance_id }) => {
156
+ const nodes = get_nodes_for_job(root_instance_id);
157
+
158
+ for (let i = 0; i < nodes?.length; i += 1) {
159
+ const node = nodes[i];
160
+ if (types.is_function(node?.lifecycle?.onUpdateProps) || types.is_function(node?.lifecycle?.on_update_props)) {
161
+ (node.lifecycle.onUpdateProps || node.lifecycle.on_update_props)(node);
162
+ track_function_call(`ui.${node?.options?.test?.name || generate_id()}.lifecycle.on_update_props`, [node]);
163
+ }
164
+ }
165
+ },
166
+ 'lifecycle.onRefetchData': ({ root_instance_id }) => {
167
+ const nodes = get_nodes_for_job(root_instance_id);
168
+
169
+ for (let i = 0; i < nodes?.length; i += 1) {
170
+ const node = nodes[i];
171
+ if (types.is_function(node?.lifecycle?.onRefetchData) || types.is_function(node?.lifecycle?.on_refetch_data)) {
172
+ (node.lifecycle.onRefetchData || node.lifecycle.on_refetch_data)(node);
173
+ track_function_call(`ui.${node?.options?.test?.name || generate_id()}.lifecycle.on_refetch_data`, [node]);
174
+ }
175
+ }
176
+ },
177
+ 'lifecycle.onBeforeUnmount': ({ root_instance_id }) => {
178
+ const nodes = get_nodes_for_job(root_instance_id);
179
+
180
+ for (let i = 0; i < nodes?.length; i += 1) {
181
+ const node = nodes[i];
182
+ if (types.is_function(node?.lifecycle?.onBeforeUnmount) || types.is_function(node?.lifecycle?.on_before_unmount)) {
183
+ (node.lifecycle.onBeforeUnmount || node.lifecycle.on_before_unmount)(node);
184
+ track_function_call(`ui.${node?.options?.test?.name || generate_id()}.lifecycle.on_before_unmount`, [node]);
185
+ }
186
+ }
187
+ },
188
+ 'reset_tree_for_hmr': () => {
189
+ clear_timers(null, window.__joystick_hmr_previous_tree__);
190
+ clear_websockets();
191
+ window.__joystick_hmr_previous_tree__ = [];
192
+ window.__joystick_hmr_previous_websockets__ = [];
193
+ },
194
+ };
195
+
196
+ export default jobs;
@@ -0,0 +1,11 @@
1
+ import jobs from './index.js';
2
+
3
+ const run_tree_job = (job_name = '', options = {}) => {
4
+ const job_to_run = jobs[job_name];
5
+
6
+ if (typeof job_to_run === 'function') {
7
+ return job_to_run(options);
8
+ }
9
+ };
10
+
11
+ export default run_tree_job;
@@ -0,0 +1,18 @@
1
+ import types from "../lib/types.js";
2
+
3
+ const replace_child_in_vdom = (virtual_dom = {}, child_instance_id = '', updated_vdom_node = {}) => {
4
+ for (let i = 0; i < virtual_dom?.children?.length; i += 1) {
5
+ const child = virtual_dom?.children[i];
6
+
7
+ if (types.is_object(child) && child.attributes && child.attributes['js-i'] && child.attributes['js-i'] === child_instance_id) {
8
+ virtual_dom.children[i] = updated_vdom_node;
9
+ break;
10
+ }
11
+
12
+ if (types.is_object(child)) {
13
+ replace_child_in_vdom(child, child_instance_id, updated_vdom_node);
14
+ }
15
+ }
16
+ };
17
+
18
+ export default replace_child_in_vdom;
@@ -0,0 +1,72 @@
1
+ import generate_id from "../lib/generate_id.js";
2
+ import log_request_errors from "../lib/log_request_errors.js";
3
+ import track_function_call from "../test/track_function_call.js";
4
+ import websocket_client from "../websockets/client.js";
5
+
6
+ export default (uploader_name = '', uploader_options = {}) => {
7
+ if (window?.__joystick_test__) {
8
+ // NOTE: In a test, do not try to upload anything, just track the call and return.
9
+ track_function_call(`ui.upload.${uploader_name}`, [
10
+ uploader_name,
11
+ uploader_options,
12
+ ]);
13
+
14
+ return;
15
+ }
16
+
17
+ return new Promise((resolve, reject) => {
18
+ const upload_id = generate_id(16);
19
+ let last_progress = 0;
20
+
21
+ websocket_client({
22
+ url: `${window?.process?.env.NODE_ENV === 'development' ? 'ws' : 'wss'}://${location.host}/api/_websockets/uploaders`,
23
+ options: {
24
+ logging: process.env.NODE_ENV === 'development',
25
+ autoReconnect: true,
26
+ reconnectAttempts: 12,
27
+ reconnectDelayInSeconds: 5,
28
+ },
29
+ query: {
30
+ id: upload_id,
31
+ },
32
+ events: {
33
+ on_message: (message = {}) => {
34
+ if (message?.type === 'PROGRESS' && (uploader_options?.onProgress || uploader_options?.on_progress) && last_progress < 100 && last_progress !== message?.progress) {
35
+ last_progress = message?.progress;
36
+ (uploader_options.onProgress || uploader_options?.on_progress)(message?.progress, message?.provider);
37
+ }
38
+ },
39
+ },
40
+ }, () => {
41
+ let formData;
42
+
43
+ if (uploader_options?.files?.length > 0) {
44
+ formData = new FormData();
45
+ const files = Array.from(uploader_options?.files);
46
+
47
+ for (let i = 0; i < files?.length; i += 1) {
48
+ const file = files[i];
49
+ formData.append('files', file, file.name);
50
+ }
51
+ }
52
+
53
+ fetch(`${window.location.origin}/api/_uploaders/${uploader_name}`, {
54
+ method: 'POST',
55
+ headers: {
56
+ 'x-joystick-upload-id': upload_id,
57
+ 'x-joystick-upload-input': JSON.stringify(uploader_options?.input || {}),
58
+ },
59
+ body: formData,
60
+ }).then(async (data) => {
61
+ const response = await data.json();
62
+
63
+ if (response && response.errors) {
64
+ log_request_errors('upload', response.errors);
65
+ reject({ errors: response.errors });
66
+ } else {
67
+ resolve(response?.uploads);
68
+ }
69
+ });
70
+ });
71
+ });
72
+ };