@ea-lab/reactive-json 0.0.20 → 0.0.21

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 (124) hide show
  1. package/README.md +1 -1
  2. package/dist/esm/types/component/action/HashChangeListener.d.ts +9 -0
  3. package/{lib/component/action/Hide.jsx → dist/esm/types/component/action/Hide.d.ts} +2 -6
  4. package/dist/esm/types/component/action/MessageListener.d.ts +9 -0
  5. package/dist/esm/types/component/action/Popover.d.ts +5 -0
  6. package/dist/esm/types/component/action/ReactOnEvent.d.ts +26 -0
  7. package/dist/esm/types/component/action/Redirect.d.ts +9 -0
  8. package/dist/esm/types/component/action/Tooltip.d.ts +5 -0
  9. package/{lib/component/action/VisuallyHide.jsx → dist/esm/types/component/action/VisuallyHide.d.ts} +1 -4
  10. package/dist/esm/types/component/element/form/CheckBoxField.d.ts +7 -0
  11. package/dist/esm/types/component/element/form/DateField.d.ts +2 -0
  12. package/dist/esm/types/component/element/form/NumberField.d.ts +7 -0
  13. package/dist/esm/types/component/element/form/SelectField.d.ts +7 -0
  14. package/dist/esm/types/component/element/form/TextAreaField.d.ts +6 -0
  15. package/dist/esm/types/component/element/form/TextField.d.ts +6 -0
  16. package/dist/esm/types/component/element/form/formElementsCommon.d.ts +23 -0
  17. package/dist/esm/types/component/element/html/AccordionItem.d.ts +16 -0
  18. package/dist/esm/types/component/element/html/FolderSortableTree.d.ts +6 -0
  19. package/dist/esm/types/component/element/html/FormatNumeral.d.ts +7 -0
  20. package/dist/esm/types/component/element/html/Html.d.ts +8 -0
  21. package/dist/esm/types/component/element/html/LabelFromValue.d.ts +22 -0
  22. package/dist/esm/types/component/element/html/Modal.d.ts +6 -0
  23. package/dist/esm/types/component/element/html/ModalForm.d.ts +9 -0
  24. package/dist/esm/types/component/element/html/Paragraph.d.ts +5 -0
  25. package/dist/esm/types/component/element/html/PreformattedMarkup.d.ts +7 -0
  26. package/dist/esm/types/component/element/html/SortableTreeItemCollapseButton.d.ts +9 -0
  27. package/dist/esm/types/component/element/html/Tabs.d.ts +18 -0
  28. package/dist/esm/types/component/element/special/BootstrapElement.d.ts +10 -0
  29. package/dist/esm/types/component/element/special/Count.d.ts +13 -0
  30. package/dist/esm/types/component/element/special/DataFilter.d.ts +11 -0
  31. package/dist/esm/types/component/element/special/DelayedActions.d.ts +25 -0
  32. package/dist/esm/types/component/element/special/PageControls.d.ts +9 -0
  33. package/dist/esm/types/component/element/special/Phantom.d.ts +17 -0
  34. package/dist/esm/types/component/element/special/Switch.d.ts +6 -0
  35. package/dist/esm/types/component/hook/usePagination.d.ts +30 -0
  36. package/dist/esm/types/component/index.d.ts +5 -0
  37. package/dist/esm/types/component/reaction/addData.d.ts +6 -0
  38. package/dist/esm/types/component/reaction/fetchData.d.ts +8 -0
  39. package/dist/esm/types/component/reaction/moveData.d.ts +6 -0
  40. package/dist/esm/types/component/reaction/postMessage.d.ts +6 -0
  41. package/dist/esm/types/component/reaction/redirectNow.d.ts +6 -0
  42. package/dist/esm/types/component/reaction/removeData.d.ts +6 -0
  43. package/dist/esm/types/component/reaction/setClipboardData.d.ts +6 -0
  44. package/dist/esm/types/component/reaction/setData.d.ts +6 -0
  45. package/dist/esm/types/component/reaction/submitData.d.ts +8 -0
  46. package/dist/esm/types/component/reaction/triggerEvent.d.ts +6 -0
  47. package/dist/esm/types/component/utility/formatString.d.ts +17 -0
  48. package/dist/esm/types/engine/Actions.d.ts +19 -0
  49. package/dist/esm/types/engine/ComponentCollector.d.ts +12 -0
  50. package/{lib/engine/EventDispatcherContext.jsx → dist/esm/types/engine/EventDispatcherContext.d.ts} +4 -7
  51. package/dist/esm/types/engine/EventDispatcherProvider.d.ts +16 -0
  52. package/{lib/engine/GlobalDataContext.jsx → dist/esm/types/engine/GlobalDataContext.d.ts} +1 -4
  53. package/dist/esm/types/engine/GlobalDataContextProvider.d.ts +11 -0
  54. package/{lib/engine/PaginationContext.jsx → dist/esm/types/engine/PaginationContext.d.ts} +3 -4
  55. package/dist/esm/types/engine/PaginationProvider.d.ts +12 -0
  56. package/dist/esm/types/engine/ReactiveJsonRoot.d.ts +28 -0
  57. package/{lib/engine/TemplateContext.jsx → dist/esm/types/engine/TemplateContext.d.ts} +1 -4
  58. package/dist/esm/types/engine/TemplateSystem.d.ts +89 -0
  59. package/dist/esm/types/engine/View.d.ts +7 -0
  60. package/dist/esm/types/index.d.ts +6 -0
  61. package/dist/esm/types/main.d.ts +10 -0
  62. package/dist/index.cjs.js +9201 -0
  63. package/dist/index.cjs.js.map +1 -0
  64. package/dist/index.d.ts +44 -0
  65. package/dist/index.esm.js +9180 -0
  66. package/dist/index.esm.js.map +1 -0
  67. package/package.json +26 -15
  68. package/dist/reactive-json.css +0 -5
  69. package/dist/reactive-json.js +0 -47707
  70. package/dist/reactive-json.js.map +0 -1
  71. package/dist/reactive-json.umd.cjs +0 -366
  72. package/dist/reactive-json.umd.cjs.map +0 -1
  73. package/lib/component/action/HashChangeListener.jsx +0 -66
  74. package/lib/component/action/MessageListener.jsx +0 -62
  75. package/lib/component/action/Popover.jsx +0 -53
  76. package/lib/component/action/ReactOnEvent.jsx +0 -118
  77. package/lib/component/action/Redirect.jsx +0 -26
  78. package/lib/component/action/Tooltip.jsx +0 -27
  79. package/lib/component/element/form/CheckBoxField.jsx +0 -215
  80. package/lib/component/element/form/DateField.jsx +0 -42
  81. package/lib/component/element/form/NumberField.jsx +0 -29
  82. package/lib/component/element/form/SelectField.jsx +0 -130
  83. package/lib/component/element/form/TextAreaField.jsx +0 -48
  84. package/lib/component/element/form/TextField.jsx +0 -65
  85. package/lib/component/element/form/formElementsCommon.jsx +0 -54
  86. package/lib/component/element/html/AccordionItem.jsx +0 -42
  87. package/lib/component/element/html/FolderSortableTree.jsx +0 -307
  88. package/lib/component/element/html/FormatNumeral.jsx +0 -118
  89. package/lib/component/element/html/Html.jsx +0 -107
  90. package/lib/component/element/html/LabelFromValue.jsx +0 -89
  91. package/lib/component/element/html/Modal.jsx +0 -77
  92. package/lib/component/element/html/ModalForm.jsx +0 -30
  93. package/lib/component/element/html/Paragraph.jsx +0 -10
  94. package/lib/component/element/html/PreformattedMarkup.jsx +0 -54
  95. package/lib/component/element/html/SortableTreeItemCollapseButton.jsx +0 -20
  96. package/lib/component/element/html/Tabs.jsx +0 -55
  97. package/lib/component/element/special/BootstrapElement.jsx +0 -32
  98. package/lib/component/element/special/Count.jsx +0 -46
  99. package/lib/component/element/special/DataFilter.jsx +0 -156
  100. package/lib/component/element/special/DelayedActions.jsx +0 -119
  101. package/lib/component/element/special/PageControls.jsx +0 -19
  102. package/lib/component/element/special/Phantom.jsx +0 -25
  103. package/lib/component/element/special/Switch.jsx +0 -131
  104. package/lib/component/hook/usePagination.jsx +0 -184
  105. package/lib/component/reaction/addData.jsx +0 -23
  106. package/lib/component/reaction/fetchData.jsx +0 -83
  107. package/lib/component/reaction/moveData.jsx +0 -52
  108. package/lib/component/reaction/postMessage.jsx +0 -43
  109. package/lib/component/reaction/redirectNow.jsx +0 -17
  110. package/lib/component/reaction/removeData.jsx +0 -48
  111. package/lib/component/reaction/setClipboardData.jsx +0 -20
  112. package/lib/component/reaction/setData.jsx +0 -23
  113. package/lib/component/reaction/submitData.jsx +0 -136
  114. package/lib/component/reaction/triggerEvent.jsx +0 -62
  115. package/lib/component/utility/formatString.jsx +0 -59
  116. package/lib/engine/Actions.jsx +0 -392
  117. package/lib/engine/ComponentCollector.js +0 -28
  118. package/lib/engine/EventDispatcherProvider.jsx +0 -80
  119. package/lib/engine/GlobalDataContextProvider.jsx +0 -33
  120. package/lib/engine/PaginationProvider.jsx +0 -61
  121. package/lib/engine/ReactiveJsonRoot.jsx +0 -318
  122. package/lib/engine/TemplateSystem.jsx +0 -302
  123. package/lib/engine/View.jsx +0 -248
  124. package/lib/main.jsx +0 -52
@@ -1,83 +0,0 @@
1
- import axios from "axios";
2
- import {evaluateTemplateValue} from "../../engine/TemplateSystem";
3
-
4
- /**
5
- * Fetches data. Similar to submitData, but for GET requests.
6
- *
7
- * Will reload the app content if refreshAppOnResponse is true.
8
- *
9
- * @param {{args: {refreshAppOnResponse, url}, event, globalDataContext, templateContext}} props Reaction function props.
10
- */
11
- export const fetchData = (props) => {
12
- // Prevent multiple submits / fetches.
13
- const reactionEvent = props?.event;
14
-
15
- // Check in realtime if we are already submitting.
16
- // With this system, only 1 submit can be made concurrently for all roots.
17
- const body = document.body;
18
-
19
- if (body.dataset.htmlBuilderIsSubmitting === "true") {
20
- return;
21
- }
22
-
23
- // This will block any attempts to resubmit until receiving the response.
24
- body.dataset.htmlBuilderIsSubmitting = "true";
25
-
26
- const currentTarget = reactionEvent.currentTarget;
27
-
28
- if (currentTarget?.dataset) {
29
- // Useful for styling.
30
- currentTarget.dataset.isSubmitting = "true";
31
- }
32
-
33
- const {globalDataContext: _globalDataContext, templateContext} = props;
34
-
35
- // Use the root context when submitting data,
36
- // not the maybe-filtered one that the DataFilter component may have edited.
37
- // This could be made configurable if ever needed.
38
- const globalDataContext = _globalDataContext.getRootContext ? _globalDataContext.getRootContext() : _globalDataContext;
39
-
40
- /**
41
- * Tells if the response content will replace the current app content.
42
- *
43
- * @type {boolean}
44
- */
45
- const refreshAppOnResponse = props?.args?.refreshAppOnResponse ?? true;
46
-
47
- const url = evaluateTemplateValue({
48
- valueToEvaluate: props?.args?.url, globalDataContext, templateContext
49
- });
50
-
51
- if (!url) {
52
- return;
53
- }
54
-
55
- const headers = globalDataContext.headersForData ?? {};
56
-
57
- const {setRawAppData} = globalDataContext;
58
-
59
- axios
60
- .get(
61
- url,
62
- {
63
- headers
64
- })
65
- .then((value) => {
66
- if (!refreshAppOnResponse) {
67
- return;
68
- }
69
-
70
- // This will trigger a complete re-render.
71
- setRawAppData(value.data);
72
- })
73
- .catch((reason) => {
74
- console.log("reactionFunction:fetchData : Could not fetch. Reason: " + reason.message);
75
- })
76
- .finally(() => {
77
- delete body.dataset.htmlBuilderIsSubmitting;
78
-
79
- if (currentTarget?.dataset) {
80
- delete currentTarget.dataset.isSubmitting;
81
- }
82
- });
83
- };
@@ -1,52 +0,0 @@
1
- import {dataLocationToPath} from "../../engine/TemplateSystem";
2
-
3
- /**
4
- * Moves data at the specified path.
5
- *
6
- * @param {{}} props
7
- */
8
- export const moveData = (props) => {
9
- const {globalDataContext, templateContext} = props;
10
- const {path, target} = props.args;
11
-
12
- if (path === undefined && target !== "currentTemplateData") {
13
- return;
14
- }
15
-
16
- let dataAbsolutePath;
17
-
18
- if (path) {
19
- dataAbsolutePath = dataLocationToPath({
20
- currentPath: templateContext.templatePath,
21
- dataLocation: path,
22
- globalDataContext,
23
- templateContext
24
- });
25
- } else {
26
- // Target mode.
27
- dataAbsolutePath = templateContext.templatePath;
28
-
29
- // Dev note: could this be interesting for the other mode?
30
- let parentLevel = props.args.parentLevel ?? 0;
31
-
32
- while (parentLevel > 0) {
33
- --parentLevel;
34
-
35
- // Remove a level from the path.
36
- const lastIndex = dataAbsolutePath.lastIndexOf('.');
37
-
38
- if (lastIndex < 1) {
39
- // No valid path to remove. Is there a valid use case where we should remove everything?
40
- return;
41
- }
42
-
43
- dataAbsolutePath = dataAbsolutePath.substring(0, lastIndex);
44
- }
45
- }
46
-
47
- const {increment} = props.args;
48
-
49
- globalDataContext?.updateData({
50
- increment,
51
- }, dataAbsolutePath, "move");
52
- };
@@ -1,43 +0,0 @@
1
- import {evaluateTemplateValueCollection} from "../../engine/TemplateSystem";
2
-
3
- /**
4
- * Posts a message to the specified target.
5
- *
6
- * @param {{args: {includeChangedValue, message, messageTarget, on, targetOrigin}, event, globalDataContext, templateContext}} props
7
- */
8
- export const postMessage = (props) => {
9
- const messageTargets = {
10
- parent: window.parent,
11
- self: window,
12
- };
13
-
14
- const messageTarget = messageTargets[props?.args?.messageTarget ?? "parent"] ?? window;
15
-
16
- // The targetOrigin must match the schema and domain where the message will be sent.
17
- // Otherwise, the message will be discarded for security reasons.
18
- // When not set, the target will be the current location's origin by default.
19
- const messageTargetOrigin = props?.args?.targetOrigin ?? window.location.origin;
20
-
21
- const message_evaluated = evaluateTemplateValueCollection({
22
- globalDataContext: props.globalDataContext,
23
- templateContext: props.templateContext,
24
- valueToEvaluate: props?.args?.message
25
- });
26
-
27
- if (props?.args?.on === "change" && typeof message_evaluated === "object" && props?.args?.includeChangedValue && props?.event?.target?.nodeName === "INPUT") {
28
- let changedValue;
29
-
30
- switch (props?.event?.target?.type) {
31
- case "checkbox":
32
- changedValue = props?.event?.target?.checked;
33
- break;
34
-
35
- default:
36
- // TODO: support other types.
37
- }
38
-
39
- message_evaluated["changedValue"] = changedValue;
40
- }
41
-
42
- (messageTarget && messageTargetOrigin) && messageTarget.postMessage(message_evaluated, messageTargetOrigin);
43
- };
@@ -1,17 +0,0 @@
1
- import {evaluateTemplateValue} from "../../engine/TemplateSystem";
2
-
3
- /**
4
- * Redirects to the specified URL.
5
- *
6
- * @param {{}} props
7
- */
8
- export const redirectNow = (props) => {
9
- const {globalDataContext, templateContext} = props;
10
- const {to} = props.args;
11
-
12
- if (!to || typeof to !== "string") {
13
- return;
14
- }
15
-
16
- window.location.href = evaluateTemplateValue({valueToEvaluate: to, globalDataContext, templateContext});
17
- };
@@ -1,48 +0,0 @@
1
- import {dataLocationToPath} from "../../engine/TemplateSystem";
2
-
3
- /**
4
- * Removes data at the specified path.
5
- *
6
- * @param {{}} props
7
- */
8
- export const removeData = (props) => {
9
- const {globalDataContext, templateContext} = props;
10
- const {path, target} = props.args;
11
-
12
- if (path === undefined && target !== "currentTemplateData") {
13
- return;
14
- }
15
-
16
- let dataAbsolutePath;
17
-
18
- if (path) {
19
- dataAbsolutePath = dataLocationToPath({
20
- currentPath: templateContext.templatePath,
21
- dataLocation: path,
22
- globalDataContext,
23
- templateContext
24
- });
25
- } else {
26
- // Target mode.
27
- dataAbsolutePath = templateContext.templatePath;
28
-
29
- // Dev note: could this be interesting for the other mode?
30
- let parentLevel = props.args.parentLevel ?? 0;
31
-
32
- while (parentLevel > 0) {
33
- --parentLevel;
34
-
35
- // Remove a level from the path.
36
- const lastIndex = dataAbsolutePath.lastIndexOf('.');
37
-
38
- if (lastIndex < 1) {
39
- // No valid path to remove. Is there a valid use case where we should remove everything?
40
- return;
41
- }
42
-
43
- dataAbsolutePath = dataAbsolutePath.substring(0, lastIndex);
44
- }
45
- }
46
-
47
- globalDataContext?.updateData(undefined, dataAbsolutePath, "remove");
48
- };
@@ -1,20 +0,0 @@
1
- import {evaluateTemplateValue} from "../../engine/TemplateSystem";
2
-
3
- /**
4
- * Copies data to the clipboard.
5
- *
6
- * @param {{}} props
7
- */
8
- export const setClipboardData = async (props) => {
9
- const {globalDataContext, templateContext} = props;
10
- const evaluatedValue = evaluateTemplateValue({valueToEvaluate: props?.args?.value, globalDataContext, templateContext});
11
-
12
- if (typeof evaluatedValue === 'string') {
13
- try {
14
- // Attempt to copy to clipboard.
15
- await navigator.clipboard.writeText(evaluatedValue.toString());
16
- } catch (error) {
17
- console.error('Failed to copy data to the clipboard:', error);
18
- }
19
- }
20
- };
@@ -1,23 +0,0 @@
1
- import {dataLocationToPath, evaluateTemplateValue} from "../../engine/TemplateSystem";
2
- import {cloneDeep} from "lodash";
3
-
4
- /**
5
- * Sets data at the specified path.
6
- *
7
- * @param {{}} props
8
- */
9
- export const setData = (props) => {
10
- const {globalDataContext, templateContext} = props;
11
- const {path, value} = props.args;
12
-
13
- if (path === undefined) {
14
- return;
15
- }
16
-
17
- const dataAbsolutePath = dataLocationToPath({currentPath: templateContext.templatePath, dataLocation: path, globalDataContext, templateContext});
18
-
19
- const evaluatedValue = evaluateTemplateValue({valueToEvaluate: value, globalDataContext, templateContext});
20
-
21
- // We clone the value to have distinct instances when the value is an object.
22
- globalDataContext?.updateData(typeof evaluatedValue !== "object" ? evaluatedValue : cloneDeep(evaluatedValue), dataAbsolutePath);
23
- };
@@ -1,136 +0,0 @@
1
- import axios from "axios";
2
- import {evaluateTemplateValue} from "../../engine/TemplateSystem";
3
-
4
- /**
5
- * Submits the current state of this app data.
6
- *
7
- * Will reload the app content if refreshAppOnResponse is true.
8
- *
9
- * @param {{args: {data, httpMethod, refreshAppOnResponse, submitSilently, url}, event, globalDataContext, templateContext}} props Reaction function props.
10
- */
11
- export const submitData = (props) => {
12
- // Prevent multiple submits.
13
- const reactionEvent = props?.event;
14
-
15
- // Check in realtime if we are already submitting.
16
- // With this system, only 1 submit can be made concurrently for all roots.
17
- const body = document.body;
18
-
19
- if (body.dataset.htmlBuilderIsSubmitting === "true") {
20
- return;
21
- }
22
-
23
- // This will block any attempts to resubmit until receiving the response.
24
- body.dataset.htmlBuilderIsSubmitting = "true";
25
-
26
- if (props?.args?.submitSilently) {
27
- // This will prevent CSS from visually disabling the fields if true.
28
- body.dataset.htmlBuilderIsSubmittingSilently = "true";
29
- } else {
30
- delete body.dataset.htmlBuilderIsSubmittingSilently;
31
- }
32
-
33
- const currentTarget = reactionEvent?.currentTarget;
34
-
35
- if (currentTarget?.dataset) {
36
- // Useful for styling.
37
- currentTarget.dataset.isSubmitting = "true";
38
- }
39
-
40
- const {globalDataContext: _globalDataContext, templateContext} = props;
41
-
42
- // Use the root context when submitting data,
43
- // not the maybe-filtered one that the DataFilter component may have edited.
44
- // This could be made configurable if ever needed.
45
- const globalDataContext = _globalDataContext.getRootContext ? _globalDataContext.getRootContext() : _globalDataContext;
46
-
47
- /**
48
- * Tells if the response content will replace the current app content.
49
- *
50
- * @type {boolean}
51
- */
52
- const refreshAppOnResponse = props?.args?.refreshAppOnResponse ?? true;
53
-
54
- const url = evaluateTemplateValue({
55
- valueToEvaluate: props?.args?.url, globalDataContext, templateContext
56
- });
57
-
58
- if (!url) {
59
- return;
60
- }
61
-
62
- let payload = {};
63
-
64
- if (props?.args?.hasOwnProperty("data")) {
65
- payload = props.args.data;
66
-
67
- // Evaluate the data on the first level.
68
- function applyFilter(value, filterFn) {
69
- if (Array.isArray(value)) {
70
- return value.map(filterFn);
71
- } else if (typeof value === 'object' && value !== null) {
72
- const entries = Object.entries(value).map(([key, val]) => {
73
- return [key, filterFn(val)];
74
- });
75
-
76
- return Object.fromEntries(
77
- entries
78
- );
79
- } else {
80
- return filterFn(value) ? value : null;
81
- }
82
- }
83
-
84
- payload = applyFilter(payload, (value) => {
85
- return evaluateTemplateValue({valueToEvaluate: value, globalDataContext, templateContext})
86
- });
87
-
88
- if (globalDataContext.templateData.__state !== undefined) {
89
- // Append the special data.__state value.
90
- payload.__state = globalDataContext.templateData.__state;
91
- }
92
- } else {
93
- payload.data = globalDataContext.templateData;
94
-
95
- if (globalDataContext.templateData.__state !== undefined) {
96
- // Append the special data.__state value.
97
- payload.data.__state = globalDataContext.templateData.__state;
98
- }
99
- }
100
-
101
- const headers = globalDataContext.headersForData ?? {};
102
-
103
- const {setRawAppData} = globalDataContext;
104
-
105
- const config = {
106
- method: props?.args?.httpMethod ?? "post",
107
- url: url,
108
- data: payload,
109
- };
110
-
111
- if (headers) {
112
- // Override headers only when explicitly set.
113
- config.headers = headers;
114
- }
115
-
116
- axios(config)
117
- .then((value) => {
118
- if (!refreshAppOnResponse) {
119
- return;
120
- }
121
-
122
- // This will trigger a complete re-render.
123
- setRawAppData(value.data);
124
- })
125
- .catch((reason) => {
126
- console.log("reactionFunction:submitData : Could not submit. Reason: " + reason.message);
127
- })
128
- .finally(() => {
129
- delete body.dataset.htmlBuilderIsSubmitting;
130
- delete body.dataset.htmlBuilderIsSubmittingSilently;
131
-
132
- if (currentTarget?.dataset) {
133
- delete currentTarget.dataset.isSubmitting;
134
- }
135
- });
136
- };
@@ -1,62 +0,0 @@
1
- /**
2
- * Reaction function which will trigger an event on an element identified by the given selector.
3
- *
4
- * @param {{args:{selector, selectorBase, eventName}, event}} props Reaction function props.
5
- */
6
- export const triggerEvent = (props) => {
7
- const selector = props?.args?.selector;
8
-
9
- if (!selector || typeof selector !== "string" || selector.length === 0) {
10
- return;
11
- }
12
-
13
- const selectorBase = props?.args?.selectorBase;
14
- let selectorBase_real;
15
-
16
- if (typeof selectorBase === "undefined") {
17
- selectorBase_real = document;
18
- } else if (selectorBase === "currentEventTarget") {
19
- selectorBase_real = props?.event?.target;
20
- } else {
21
- // Find the closest element matching the selectorBase as selector.
22
- selectorBase_real = props?.event?.target?.closest(selectorBase);
23
- }
24
-
25
- if (!selectorBase_real) {
26
- return;
27
- }
28
-
29
- const eventName = props?.args?.eventName;
30
-
31
- if (!eventName || typeof eventName !== "string" || eventName.length === 0) {
32
- return;
33
- }
34
-
35
- const elements = selectorBase_real.querySelectorAll(selector);
36
-
37
- // Prepare the events in a promise system to handle successive synchronous events.
38
- // If not doing this, only the last synchronous event will fire.
39
- const elements_asArray = Object.entries(elements);
40
-
41
- const consumeSingleEvent = () => {
42
- const element = elements_asArray.splice(0, 1)?.[0]?.[1] ?? undefined;
43
-
44
- if (!element) {
45
- return;
46
- }
47
-
48
- const event = new Event(eventName, {
49
- bubbles: true,
50
- cancelable: false,
51
- });
52
-
53
- element.dispatchEvent(event);
54
-
55
- // We use promises to make multiple clicks on different targets work.
56
- // Without this, only the last will receive the event (tested on Firefox).
57
- // This is undocumented online.
58
- Promise.resolve().then(consumeSingleEvent);
59
- };
60
-
61
- consumeSingleEvent();
62
- };
@@ -1,59 +0,0 @@
1
- import {evaluateTemplateValue} from "../../engine/TemplateSystem";
2
-
3
- /**
4
- * Pseudo sprintf implementation.
5
- *
6
- * Taken from https://stackoverflow.com/a/43718864
7
- *
8
- * @licence CC-BY-SA 3.0
9
- * @author https://stackoverflow.com/users/6314667/7vujy0f0hy and community.
10
- *
11
- * @param {string} str The string to format.
12
- * @param {...string} argv The replacement arguments.
13
- *
14
- * @returns {*}
15
- */
16
- const sprintf = (str, ...argv) => !argv.length
17
- ? str
18
- : sprintf(str = str.replace(sprintf.token || "$token", argv.shift()), ...argv);
19
-
20
- /**
21
- * Formats the given string with replacement arguments.
22
- *
23
- * @param {{globalDataContext: {}, templateContext: {}}} templateContexts Template contexts.
24
- * @param {string} toFormat The string to format.
25
- * @param {...string} argv The replacement arguments.
26
- */
27
- export const formatString = ({templateContexts}, toFormat, ...argv) => {
28
- const evaluatedArgs = argv.map(
29
- (toEvaluate) => {
30
- return evaluateTemplateValue({
31
- globalDataContext: templateContexts.globalDataContext,
32
- templateContext: templateContexts.templateContext,
33
- valueToEvaluate: toEvaluate
34
- });
35
- }
36
- )
37
- return sprintf(toFormat, ...evaluatedArgs);
38
- };
39
-
40
- /**
41
- * Formats the given data with replacement arguments if possible.
42
- *
43
- * @param {{templateContexts: {globalDataContext: {}, templateContext: {}}}} options Template contexts.
44
- * @param {*} toFormat The data to format.
45
- */
46
- export const maybeFormatString = (options, toFormat) => {
47
- if (typeof toFormat === "string") {
48
- return toFormat;
49
- }
50
-
51
- if (Array.isArray(toFormat)) {
52
- const [toFormatReal, ...args] = toFormat;
53
-
54
- return formatString(options, toFormatReal, ...args);
55
- }
56
-
57
- // Unsupported data to format.
58
- return "";
59
- };