@nordcraft/runtime 1.0.0

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 (168) hide show
  1. package/README.md +5 -0
  2. package/dist/api/createAPI.d.ts +20 -0
  3. package/dist/api/createAPI.js +319 -0
  4. package/dist/api/createAPI.js.map +1 -0
  5. package/dist/api/createAPIv2.d.ts +7 -0
  6. package/dist/api/createAPIv2.js +686 -0
  7. package/dist/api/createAPIv2.js.map +1 -0
  8. package/dist/components/createComponent.d.ts +13 -0
  9. package/dist/components/createComponent.js +216 -0
  10. package/dist/components/createComponent.js.map +1 -0
  11. package/dist/components/createElement.d.ts +3 -0
  12. package/dist/components/createElement.js +208 -0
  13. package/dist/components/createElement.js.map +1 -0
  14. package/dist/components/createNode.d.ts +22 -0
  15. package/dist/components/createNode.js +272 -0
  16. package/dist/components/createNode.js.map +1 -0
  17. package/dist/components/createSlot.d.ts +3 -0
  18. package/dist/components/createSlot.js +49 -0
  19. package/dist/components/createSlot.js.map +1 -0
  20. package/dist/components/createText.d.ts +23 -0
  21. package/dist/components/createText.js +68 -0
  22. package/dist/components/createText.js.map +1 -0
  23. package/dist/components/createText.test.d.ts +1 -0
  24. package/dist/components/createText.test.js +113 -0
  25. package/dist/components/createText.test.js.map +1 -0
  26. package/dist/components/renderComponent.d.ts +34 -0
  27. package/dist/components/renderComponent.js +66 -0
  28. package/dist/components/renderComponent.js.map +1 -0
  29. package/dist/context/isContextProvider.d.ts +2 -0
  30. package/dist/context/isContextProvider.js +5 -0
  31. package/dist/context/isContextProvider.js.map +1 -0
  32. package/dist/context/subscribeToContext.d.ts +4 -0
  33. package/dist/context/subscribeToContext.js +93 -0
  34. package/dist/context/subscribeToContext.js.map +1 -0
  35. package/dist/custom-components/components.d.ts +1 -0
  36. package/dist/custom-components/components.js +2 -0
  37. package/dist/custom-components/components.js.map +1 -0
  38. package/dist/custom-components/toddle-portal.d.ts +6 -0
  39. package/dist/custom-components/toddle-portal.js +20 -0
  40. package/dist/custom-components/toddle-portal.js.map +1 -0
  41. package/dist/custom-element/ToddleComponent.d.ts +37 -0
  42. package/dist/custom-element/ToddleComponent.js +244 -0
  43. package/dist/custom-element/ToddleComponent.js.map +1 -0
  44. package/dist/custom-element/defineComponents.d.ts +26 -0
  45. package/dist/custom-element/defineComponents.js +42 -0
  46. package/dist/custom-element/defineComponents.js.map +1 -0
  47. package/dist/custom-element.main.d.ts +3 -0
  48. package/dist/custom-element.main.esm.js +266 -0
  49. package/dist/custom-element.main.esm.js.map +7 -0
  50. package/dist/custom-element.main.js +14 -0
  51. package/dist/custom-element.main.js.map +1 -0
  52. package/dist/debug/logState.d.ts +4 -0
  53. package/dist/debug/logState.js +19 -0
  54. package/dist/debug/logState.js.map +1 -0
  55. package/dist/editor/drag-drop/dragEnded.d.ts +2 -0
  56. package/dist/editor/drag-drop/dragEnded.js +56 -0
  57. package/dist/editor/drag-drop/dragEnded.js.map +1 -0
  58. package/dist/editor/drag-drop/dragMove.d.ts +3 -0
  59. package/dist/editor/drag-drop/dragMove.js +74 -0
  60. package/dist/editor/drag-drop/dragMove.js.map +1 -0
  61. package/dist/editor/drag-drop/dragReorder.d.ts +3 -0
  62. package/dist/editor/drag-drop/dragReorder.js +92 -0
  63. package/dist/editor/drag-drop/dragReorder.js.map +1 -0
  64. package/dist/editor/drag-drop/dragStarted.d.ts +9 -0
  65. package/dist/editor/drag-drop/dragStarted.js +100 -0
  66. package/dist/editor/drag-drop/dragStarted.js.map +1 -0
  67. package/dist/editor/drag-drop/dropHighlight.d.ts +16 -0
  68. package/dist/editor/drag-drop/dropHighlight.js +50 -0
  69. package/dist/editor/drag-drop/dropHighlight.js.map +1 -0
  70. package/dist/editor/drag-drop/getInsertAreas.d.ts +20 -0
  71. package/dist/editor/drag-drop/getInsertAreas.js +220 -0
  72. package/dist/editor/drag-drop/getInsertAreas.js.map +1 -0
  73. package/dist/editor-preview.main.d.ts +19 -0
  74. package/dist/editor-preview.main.js +1303 -0
  75. package/dist/editor-preview.main.js.map +1 -0
  76. package/dist/events/handleAction.d.ts +3 -0
  77. package/dist/events/handleAction.js +307 -0
  78. package/dist/events/handleAction.js.map +1 -0
  79. package/dist/page.main.d.ts +7 -0
  80. package/dist/page.main.esm.js +8 -0
  81. package/dist/page.main.esm.js.map +7 -0
  82. package/dist/page.main.js +395 -0
  83. package/dist/page.main.js.map +1 -0
  84. package/dist/signal/signal.d.ts +19 -0
  85. package/dist/signal/signal.js +65 -0
  86. package/dist/signal/signal.js.map +1 -0
  87. package/dist/styles/style.d.ts +4 -0
  88. package/dist/styles/style.js +196 -0
  89. package/dist/styles/style.js.map +1 -0
  90. package/dist/utils/BatchQueue.d.ts +10 -0
  91. package/dist/utils/BatchQueue.js +25 -0
  92. package/dist/utils/BatchQueue.js.map +1 -0
  93. package/dist/utils/createFormulaCache.d.ts +3 -0
  94. package/dist/utils/createFormulaCache.js +81 -0
  95. package/dist/utils/createFormulaCache.js.map +1 -0
  96. package/dist/utils/findNearestLine.d.ts +13 -0
  97. package/dist/utils/findNearestLine.js +74 -0
  98. package/dist/utils/findNearestLine.js.map +1 -0
  99. package/dist/utils/findNearestLine.test.d.ts +1 -0
  100. package/dist/utils/findNearestLine.test.js +59 -0
  101. package/dist/utils/findNearestLine.test.js.map +1 -0
  102. package/dist/utils/getDragData.d.ts +1 -0
  103. package/dist/utils/getDragData.js +10 -0
  104. package/dist/utils/getDragData.js.map +1 -0
  105. package/dist/utils/getElementTagName.d.ts +3 -0
  106. package/dist/utils/getElementTagName.js +7 -0
  107. package/dist/utils/getElementTagName.js.map +1 -0
  108. package/dist/utils/nodes.d.ts +21 -0
  109. package/dist/utils/nodes.js +89 -0
  110. package/dist/utils/nodes.js.map +1 -0
  111. package/dist/utils/omitStyle.d.ts +2 -0
  112. package/dist/utils/omitStyle.js +13 -0
  113. package/dist/utils/omitStyle.js.map +1 -0
  114. package/dist/utils/rectHasPoint.d.ts +2 -0
  115. package/dist/utils/rectHasPoint.js +4 -0
  116. package/dist/utils/rectHasPoint.js.map +1 -0
  117. package/dist/utils/setAttribute.d.ts +4 -0
  118. package/dist/utils/setAttribute.js +57 -0
  119. package/dist/utils/setAttribute.js.map +1 -0
  120. package/dist/utils/tryStartViewTransition.d.ts +5 -0
  121. package/dist/utils/tryStartViewTransition.js +14 -0
  122. package/dist/utils/tryStartViewTransition.js.map +1 -0
  123. package/dist/utils/url.d.ts +2 -0
  124. package/dist/utils/url.js +36 -0
  125. package/dist/utils/url.js.map +1 -0
  126. package/package.json +25 -0
  127. package/src/api/createAPI.ts +375 -0
  128. package/src/api/createAPIv2.ts +931 -0
  129. package/src/components/createComponent.ts +280 -0
  130. package/src/components/createElement.ts +240 -0
  131. package/src/components/createNode.ts +381 -0
  132. package/src/components/createSlot.ts +61 -0
  133. package/src/components/createText.test.ts +117 -0
  134. package/src/components/createText.ts +104 -0
  135. package/src/components/renderComponent.ts +145 -0
  136. package/src/context/isContextProvider.ts +12 -0
  137. package/src/context/subscribeToContext.ts +135 -0
  138. package/src/custom-components/components.ts +1 -0
  139. package/src/custom-components/toddle-portal.ts +19 -0
  140. package/src/custom-element/ToddleComponent.ts +315 -0
  141. package/src/custom-element/defineComponents.ts +65 -0
  142. package/src/custom-element.main.ts +24 -0
  143. package/src/debug/logState.ts +30 -0
  144. package/src/editor/drag-drop/dragEnded.ts +75 -0
  145. package/src/editor/drag-drop/dragMove.ts +95 -0
  146. package/src/editor/drag-drop/dragReorder.ts +137 -0
  147. package/src/editor/drag-drop/dragStarted.ts +145 -0
  148. package/src/editor/drag-drop/dropHighlight.ts +82 -0
  149. package/src/editor/drag-drop/getInsertAreas.ts +235 -0
  150. package/src/editor/types.d.ts +36 -0
  151. package/src/editor-preview.main.ts +1782 -0
  152. package/src/events/handleAction.ts +387 -0
  153. package/src/page.main.ts +489 -0
  154. package/src/signal/signal.ts +74 -0
  155. package/src/styles/style.ts +254 -0
  156. package/src/types.d.ts +93 -0
  157. package/src/utils/BatchQueue.ts +24 -0
  158. package/src/utils/createFormulaCache.ts +96 -0
  159. package/src/utils/findNearestLine.test.ts +65 -0
  160. package/src/utils/findNearestLine.ts +92 -0
  161. package/src/utils/getDragData.ts +11 -0
  162. package/src/utils/getElementTagName.ts +14 -0
  163. package/src/utils/nodes.ts +125 -0
  164. package/src/utils/omitStyle.ts +19 -0
  165. package/src/utils/rectHasPoint.ts +5 -0
  166. package/src/utils/setAttribute.ts +56 -0
  167. package/src/utils/tryStartViewTransition.ts +32 -0
  168. package/src/utils/url.ts +45 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodes.js","sourceRoot":"","sources":["../../src/utils/nodes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Component } from '@nordcraft/core/dist/component/component.types';
2
+ export declare function omitSubnodeStyleForComponent<T extends Component | undefined>(component: T): T;
@@ -0,0 +1,13 @@
1
+ export function omitSubnodeStyleForComponent(component) {
2
+ const clone = structuredClone(component);
3
+ Object.entries(clone?.nodes ?? {}).forEach(([nodeId, node]) => {
4
+ if ((node.type === 'element' || node.type === 'component') &&
5
+ nodeId !== 'root') {
6
+ delete node.style;
7
+ delete node.variants;
8
+ delete node.animations;
9
+ }
10
+ });
11
+ return clone;
12
+ }
13
+ //# sourceMappingURL=omitStyle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"omitStyle.js","sourceRoot":"","sources":["../../src/utils/omitStyle.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,4BAA4B,CAC1C,SAAY;IAEZ,MAAM,KAAK,GAAG,eAAe,CAAC,SAAS,CAAC,CAAA;IACxC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE;QAC5D,IACE,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC;YACtD,MAAM,KAAK,MAAM,EACjB,CAAC;YACD,OAAO,IAAI,CAAC,KAAK,CAAA;YACjB,OAAO,IAAI,CAAC,QAAQ,CAAA;YACpB,OAAO,IAAI,CAAC,UAAU,CAAA;QACxB,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,KAAK,CAAA;AACd,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Point } from '../editor/types';
2
+ export declare function rectHasPoint(rect: DOMRect, { x, y }: Point): boolean;
@@ -0,0 +1,4 @@
1
+ export function rectHasPoint(rect, { x, y }) {
2
+ return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
3
+ }
4
+ //# sourceMappingURL=rectHasPoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rectHasPoint.js","sourceRoot":"","sources":["../../src/utils/rectHasPoint.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,IAAa,EAAE,EAAE,CAAC,EAAE,CAAC,EAAS;IACzD,OAAO,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAA;AAC/E,CAAC"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Some attributes need special handling.
3
+ */
4
+ export declare function setAttribute(elem: HTMLElement | SVGElement | MathMLElement, attr: string, value: any): void;
@@ -0,0 +1,57 @@
1
+ import { isDefined, toBoolean } from '@nordcraft/core/dist/utils/util';
2
+ /**
3
+ * Some attributes need special handling.
4
+ */
5
+ export function setAttribute(elem, attr, value) {
6
+ switch (attr) {
7
+ case 'srcObject':
8
+ case 'src':
9
+ if (elem instanceof HTMLMediaElement) {
10
+ ;
11
+ elem[attr] = value;
12
+ }
13
+ else {
14
+ elem.setAttribute(attr, String(value));
15
+ }
16
+ break;
17
+ case 'value':
18
+ case 'type': {
19
+ let val = value;
20
+ if (elem instanceof HTMLProgressElement) {
21
+ // An HTMLProgressElement will break other elements in our editor if the value is not a (finite) number
22
+ // See docs here https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress#value
23
+ // and original issue here https://discord.com/channels/972416966683926538/1317827591230722048
24
+ if (!isDefined(value) || !Number.isFinite(Number(value))) {
25
+ val = 0;
26
+ }
27
+ }
28
+ ;
29
+ elem[attr] = toBoolean(val) ? String(val) : undefined;
30
+ break;
31
+ }
32
+ case 'muted':
33
+ case 'autoplay':
34
+ if (elem instanceof HTMLMediaElement) {
35
+ ;
36
+ elem[attr] = toBoolean(value);
37
+ }
38
+ else {
39
+ elem.setAttribute(attr, String(value));
40
+ }
41
+ break;
42
+ default:
43
+ if (toBoolean(value)) {
44
+ elem.setAttribute(attr, String(value));
45
+ if (
46
+ // autofocus often does not work in the editor
47
+ attr === 'autofocus' &&
48
+ document.body.getAttribute('data-mode') !== 'design') {
49
+ setTimeout(() => elem.focus(), 100);
50
+ }
51
+ }
52
+ else {
53
+ elem.removeAttribute(attr);
54
+ }
55
+ }
56
+ }
57
+ //# sourceMappingURL=setAttribute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setAttribute.js","sourceRoot":"","sources":["../../src/utils/setAttribute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AAEtE;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,IAA8C,EAC9C,IAAY,EACZ,KAAU;IAEV,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,WAAW,CAAC;QACjB,KAAK,KAAK;YACR,IAAI,IAAI,YAAY,gBAAgB,EAAE,CAAC;gBACrC,CAAC;gBAAC,IAAY,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;YAC9B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;YACxC,CAAC;YACD,MAAK;QACP,KAAK,OAAO,CAAC;QACb,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,IAAI,GAAG,GAAG,KAAK,CAAA;YACf,IAAI,IAAI,YAAY,mBAAmB,EAAE,CAAC;gBACxC,uGAAuG;gBACvG,yFAAyF;gBACzF,8FAA8F;gBAC9F,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;oBACzD,GAAG,GAAG,CAAC,CAAA;gBACT,CAAC;YACH,CAAC;YACD,CAAC;YAAC,IAAY,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;YAC/D,MAAK;QACP,CAAC;QACD,KAAK,OAAO,CAAC;QACb,KAAK,UAAU;YACb,IAAI,IAAI,YAAY,gBAAgB,EAAE,CAAC;gBACrC,CAAC;gBAAC,IAAY,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;YACzC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;YACxC,CAAC;YACD,MAAK;QACP;YACE,IAAI,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBACrB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;gBACtC;gBACE,8CAA8C;gBAC9C,IAAI,KAAK,WAAW;oBACpB,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,KAAK,QAAQ,EACpD,CAAC;oBACD,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAA;gBACrC,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;YAC5B,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function tryStartViewTransition(updateCallback: () => void, options?: {
2
+ skipPrefersReducedMotionCheck?: boolean;
3
+ }): {
4
+ finished: Promise<void>;
5
+ };
@@ -0,0 +1,14 @@
1
+ export function tryStartViewTransition(updateCallback, options) {
2
+ const startViewTransition = document
3
+ .startViewTransition;
4
+ if (!startViewTransition ||
5
+ (options?.skipPrefersReducedMotionCheck !== true &&
6
+ window.matchMedia('(prefers-reduced-motion: reduce)').matches)) {
7
+ updateCallback();
8
+ return {
9
+ finished: Promise.resolve(),
10
+ };
11
+ }
12
+ return startViewTransition.call(document, updateCallback);
13
+ }
14
+ //# sourceMappingURL=tryStartViewTransition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tryStartViewTransition.js","sourceRoot":"","sources":["../../src/utils/tryStartViewTransition.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,sBAAsB,CACpC,cAA0B,EAC1B,OAEC;IAID,MAAM,mBAAmB,GAAI,QAAuC;SACjE,mBAAmB,CAAA;IAEtB,IACE,CAAC,mBAAmB;QACpB,CAAC,OAAO,EAAE,6BAA6B,KAAK,IAAI;YAC9C,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC,OAAO,CAAC,EAChE,CAAC;QACD,cAAc,EAAE,CAAA;QAChB,OAAO;YACL,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE;SAC5B,CAAA;IACH,CAAC;IAED,OAAO,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;AAC3D,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Location } from '../types';
2
+ export declare const getLocationUrl: ({ query, page, route, params, hash, }: Location) => string;
@@ -0,0 +1,36 @@
1
+ import { isDefined } from '@nordcraft/core/dist/utils/util';
2
+ import { compile } from 'path-to-regexp';
3
+ export const getLocationUrl = ({ query, page, route, params, hash, }) => {
4
+ let path;
5
+ if (route) {
6
+ const pathSegments = [];
7
+ for (const segment of route.path) {
8
+ if (segment.type === 'static') {
9
+ pathSegments.push(segment.name);
10
+ }
11
+ else {
12
+ const segmentValue = params[segment.name];
13
+ if (isDefined(segmentValue)) {
14
+ pathSegments.push(segmentValue);
15
+ }
16
+ else {
17
+ // If a param is missing, we can't build the rest of the path
18
+ break;
19
+ }
20
+ }
21
+ }
22
+ path = '/' + pathSegments.join('/');
23
+ }
24
+ else {
25
+ path = compile(page, { encode: encodeURIComponent })(params);
26
+ }
27
+ const hashString = hash === undefined || hash === '' ? '' : '#' + hash;
28
+ const queryString = Object.entries(query)
29
+ .filter(([_, q]) => q !== null)
30
+ .map(([key, value]) => {
31
+ return `${encodeURIComponent(route?.query[key]?.name ?? key)}=${encodeURIComponent(String(value))}`;
32
+ })
33
+ .join('&');
34
+ return `${path}${hashString}${queryString.length > 0 ? '?' + queryString : ''}`;
35
+ };
36
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAGxC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAC7B,KAAK,EACL,IAAI,EACJ,KAAK,EACL,MAAM,EACN,IAAI,GACK,EAAE,EAAE;IACb,IAAI,IAAY,CAAA;IAChB,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,YAAY,GAAa,EAAE,CAAA;QACjC,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACjC,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC9B,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;YACjC,CAAC;iBAAM,CAAC;gBACN,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;gBACzC,IAAI,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC;oBAC5B,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;gBACjC,CAAC;qBAAM,CAAC;oBACN,6DAA6D;oBAC7D,MAAK;gBACP,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,GAAG,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACrC,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,OAAO,CAAC,IAAc,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;IACxE,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAA;IACtE,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;SACtC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;SAC9B,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QACpB,OAAO,GAAG,kBAAkB,CAC1B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,IAAI,GAAG,CAC/B,IAAI,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAA;IAC1C,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,CAAC,CAAA;IAEZ,OAAO,GAAG,IAAI,GAAG,UAAU,GACzB,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,WAAW,CAAC,CAAC,CAAC,EAC/C,EAAE,CAAA;AACJ,CAAC,CAAA"}
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@nordcraft/runtime",
3
+ "license": "Apache-2.0",
4
+ "type": "module",
5
+ "homepage": "https://github.com/nordcraftengine/nordcraft",
6
+ "dependencies": {
7
+ "@nordcraft/core": "1.0.0",
8
+ "@nordcraft/std-lib": "1.0.0",
9
+ "fast-deep-equal": "3.1.3",
10
+ "path-to-regexp": "6.3.0"
11
+ },
12
+ "devDependencies": {
13
+ "@happy-dom/global-registrator": "17.4.4"
14
+ },
15
+ "scripts": {
16
+ "build": "tsc && bun scripts/build.js",
17
+ "npm-publish": "bun run build && bun publish --access public",
18
+ "typecheck": "tsc --noEmit",
19
+ "watch": "tsc -w"
20
+ },
21
+ "files": ["dist", "src"],
22
+ "main": "dist/page.main.js",
23
+ "types": "dist/page.main.d.ts",
24
+ "version": "1.0.0"
25
+ }
@@ -0,0 +1,375 @@
1
+ /* eslint-disable @typescript-eslint/no-floating-promises */
2
+ import type { LegacyComponentAPI } from '@nordcraft/core/dist/api/apiTypes'
3
+ import type { ComponentData } from '@nordcraft/core/dist/component/component.types'
4
+ import { applyFormula, isFormula } from '@nordcraft/core/dist/formula/formula'
5
+ import { mapValues } from '@nordcraft/core/dist/utils/collections'
6
+ import { parseJSONWithDate } from '@nordcraft/core/dist/utils/json'
7
+ import { handleAction } from '../events/handleAction'
8
+ import type { Signal } from '../signal/signal'
9
+ import type { ComponentContext } from '../types'
10
+
11
+ export type ApiRequest = {
12
+ url: string
13
+ method: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'OPTION' | 'HEAD'
14
+ auth: { type: string } | undefined
15
+ headers: Record<string, string>
16
+ body: any
17
+ }
18
+
19
+ /**
20
+ * Set up an api for a component.
21
+ * API requests are either proxied through toddle's back-end
22
+ * or sent directly to the api endpoint (when api.proxy === false)
23
+ */
24
+ export function createLegacyAPI(
25
+ api: LegacyComponentAPI,
26
+ ctx: ComponentContext,
27
+ ): { fetch: Function; destroy: Function } {
28
+ let timer: any = null
29
+
30
+ // Create the payload we send to toddle's back-end
31
+ // This includes url, headers, and content, sent in the body of a post request to /_query/<ComponentName>.<QueryName>
32
+ function constructPayload(
33
+ api: LegacyComponentAPI,
34
+ data: ComponentData,
35
+ ): ApiRequest {
36
+ const formulaContext = {
37
+ data,
38
+ component: ctx.component,
39
+ formulaCache: ctx.formulaCache,
40
+ root: ctx.root,
41
+ package: ctx.package,
42
+ toddle: ctx.toddle,
43
+ env: ctx.env,
44
+ }
45
+
46
+ // construct the url
47
+ const baseUrl = applyFormula(api.url, formulaContext) ?? ''
48
+ const urlPath =
49
+ api.path && api.path.length > 0
50
+ ? '/' +
51
+ api.path.map((p) => applyFormula(p.formula, formulaContext)).join('/')
52
+ : ''
53
+
54
+ // build querystring
55
+ const queryParams = Object.values(api.queryParams ?? {})
56
+ const queryString =
57
+ queryParams.length > 0
58
+ ? '?' +
59
+ queryParams
60
+ .map(
61
+ (param) =>
62
+ `${param.name}=${encodeURIComponent(
63
+ applyFormula(param.formula, formulaContext),
64
+ )}`,
65
+ )
66
+ .join('&')
67
+ : ''
68
+ const headers = isFormula(api.headers) // this is supporting a few legacy cases where the whole header object was set as a formula. This is no longer possible
69
+ ? applyFormula(api.headers, {
70
+ data,
71
+ component: ctx.component,
72
+ formulaCache: ctx.formulaCache,
73
+ root: ctx.root,
74
+ package: ctx.package,
75
+ toddle: ctx.toddle,
76
+ env: ctx.env,
77
+ })
78
+ : mapValues(api.headers ?? {}, (value) =>
79
+ applyFormula(value, {
80
+ data,
81
+ component: ctx.component,
82
+ formulaCache: ctx.formulaCache,
83
+ root: ctx.root,
84
+ package: ctx.package,
85
+ toddle: ctx.toddle,
86
+ env: ctx.env,
87
+ }),
88
+ )
89
+ const contentType = String(
90
+ Object.entries(headers).find(
91
+ ([key]) => key.toLocaleLowerCase() === 'content-type',
92
+ )?.[1],
93
+ )
94
+ const method = api.method ?? 'GET'
95
+ const body =
96
+ api.body && ['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)
97
+ ? encodeBody(
98
+ applyFormula(api.body, {
99
+ data,
100
+ component: ctx.component,
101
+ formulaCache: ctx.formulaCache,
102
+ root: ctx.root,
103
+ package: ctx.package,
104
+ toddle: ctx.toddle,
105
+ env: ctx.env,
106
+ }),
107
+ contentType,
108
+ )
109
+ : undefined
110
+ return {
111
+ url: baseUrl + urlPath + queryString,
112
+ method,
113
+ auth: api.auth,
114
+ headers,
115
+ body,
116
+ }
117
+ }
118
+
119
+ // extract the response body
120
+ async function getBody(res: Response) {
121
+ const textBody = await res.text()
122
+ try {
123
+ return parseJSONWithDate(textBody)
124
+ } catch {
125
+ return textBody
126
+ }
127
+ }
128
+
129
+ function encodeBody(body: any, contentType?: string): FormData | string {
130
+ switch (contentType) {
131
+ case 'application/x-www-form-urlencoded': {
132
+ if (typeof body === 'object' && body !== null) {
133
+ return Object.entries(body)
134
+ .map(([key, value]) => {
135
+ if (Array.isArray(value)) {
136
+ return value
137
+ .map(
138
+ (v) =>
139
+ `${encodeURIComponent(key)}=${encodeURIComponent(v)}`,
140
+ )
141
+ .join('&')
142
+ } else {
143
+ return `${encodeURIComponent(key)}=${encodeURIComponent(
144
+ String(value),
145
+ )}`
146
+ }
147
+ })
148
+ .join('&')
149
+ }
150
+ return ''
151
+ }
152
+ case 'multipart/form-data': {
153
+ const formData = new FormData()
154
+ if (typeof body === 'object' && body !== null) {
155
+ Object.entries(body).forEach(([key, value]) => {
156
+ formData.set(key, value as string | Blob)
157
+ })
158
+ }
159
+ return formData
160
+ }
161
+ case 'text/plain':
162
+ return String(body)
163
+ default:
164
+ return JSON.stringify(body)
165
+ }
166
+ }
167
+
168
+ function apiSuccess(data: any) {
169
+ ctx.dataSignal.set({
170
+ ...ctx.dataSignal.get(),
171
+ Apis: {
172
+ ...ctx.dataSignal.get().Apis,
173
+ [api.name]: {
174
+ data,
175
+ error: null,
176
+ isLoading: false,
177
+ },
178
+ },
179
+ })
180
+ api.onCompleted?.actions?.forEach((action) => {
181
+ handleAction(action, ctx.dataSignal.get(), ctx)
182
+ })
183
+ }
184
+
185
+ function apiError(error: any) {
186
+ ctx.dataSignal.set({
187
+ ...ctx.dataSignal.get(),
188
+ Apis: {
189
+ ...ctx.dataSignal.get().Apis,
190
+ [api.name]: {
191
+ data: null,
192
+ isLoading: false,
193
+ error: error,
194
+ },
195
+ },
196
+ })
197
+ api.onFailed?.actions?.forEach((action) => {
198
+ handleAction(action, ctx.dataSignal.get(), ctx)
199
+ })
200
+ }
201
+
202
+ // Execute the request to the cloudflare Query proxy
203
+ async function execute(payload: ApiRequest) {
204
+ ctx.dataSignal.set({
205
+ ...ctx.dataSignal.get(),
206
+ Apis: {
207
+ ...ctx.dataSignal.get().Apis,
208
+ [api.name]: {
209
+ data: ctx.dataSignal.get().Apis?.[api.name]?.data ?? null,
210
+ isLoading: true,
211
+ error: null,
212
+ },
213
+ },
214
+ })
215
+ let response
216
+
217
+ try {
218
+ if (api.proxy === false) {
219
+ response = await fetch(payload.url, {
220
+ method: payload.method,
221
+ headers: payload.headers,
222
+ body: payload.body,
223
+ })
224
+ } else {
225
+ response = await fetch(
226
+ `/_query/${encodeURIComponent(
227
+ ctx.component.name,
228
+ )}.${encodeURIComponent(api.name)}`,
229
+ {
230
+ method: 'POST',
231
+ body: JSON.stringify(payload),
232
+ signal: ctx.abortSignal,
233
+ headers: {
234
+ 'Content-Type': 'application/json',
235
+ },
236
+ },
237
+ )
238
+ }
239
+ const data = await getBody(response)
240
+ if (response.ok) {
241
+ apiSuccess(data)
242
+ } else {
243
+ throw data
244
+ }
245
+ } catch (error: any) {
246
+ apiError(error)
247
+ return Promise.reject(error)
248
+ }
249
+ }
250
+
251
+ // Handles throttle and debounce if set.
252
+ function trigger(body: ApiRequest) {
253
+ if (typeof api.debounce === 'number') {
254
+ return new Promise((resolve, reject) => {
255
+ if (typeof timer === 'number') {
256
+ clearTimeout(timer)
257
+ }
258
+ timer = setTimeout(() => {
259
+ execute(body).then(resolve, reject)
260
+ }, api.debounce as number)
261
+ })
262
+ } else if (typeof api.throttle === 'number') {
263
+ if (typeof timer === 'number') {
264
+ return new Promise(() => {})
265
+ }
266
+ timer = setTimeout(() => {
267
+ if (typeof timer === 'number') {
268
+ clearTimeout(timer)
269
+ }
270
+ }, api.throttle)
271
+ return execute(body)
272
+ } else {
273
+ return execute(body)
274
+ }
275
+ }
276
+
277
+ let payloadSignal: Signal<ApiRequest> | undefined
278
+ ctx.dataSignal.update((data) => {
279
+ return {
280
+ ...data,
281
+ Apis: {
282
+ ...(data.Apis ?? {}),
283
+ [api.name]: data.Apis?.[api.name] ?? {
284
+ data: null,
285
+ isLoading:
286
+ api.autoFetch &&
287
+ applyFormula(api.autoFetch, {
288
+ data: ctx.dataSignal.get(),
289
+ component: ctx.component,
290
+ formulaCache: ctx.formulaCache,
291
+ root: ctx.root,
292
+ package: ctx.package,
293
+ toddle: ctx.toddle,
294
+ env: ctx.env,
295
+ })
296
+ ? true
297
+ : false,
298
+ error: null,
299
+ },
300
+ },
301
+ }
302
+ })
303
+ if (api.autoFetch) {
304
+ payloadSignal = ctx.dataSignal.map((data) => constructPayload(api, data))
305
+ let firstRun = true
306
+ payloadSignal.subscribe((body) => {
307
+ if (
308
+ api.autoFetch &&
309
+ applyFormula(api.autoFetch, {
310
+ data: ctx.dataSignal.get(),
311
+ component: ctx.component,
312
+ formulaCache: ctx.formulaCache,
313
+ root: ctx.root,
314
+ package: ctx.package,
315
+ toddle: ctx.toddle,
316
+ env: ctx.env,
317
+ })
318
+ ) {
319
+ // We should only lookup cached data for pages since
320
+ // we don't fetch data for component APIs during SSR
321
+ if (firstRun && ctx.isRootComponent) {
322
+ firstRun = false
323
+ const cached = ctx.toddle?.pageState?.Apis?.[api.name]
324
+ if (cached && cached.data) {
325
+ if (typeof cached.data === 'string') {
326
+ // Mimic the behavior from getBody and parse
327
+ // the response to JSON if possible
328
+ apiSuccess(parseJSONWithDate(cached.data))
329
+ } else {
330
+ apiSuccess(cached.data)
331
+ }
332
+ } else {
333
+ trigger(body)
334
+ }
335
+ } else {
336
+ trigger(body)
337
+ }
338
+ }
339
+ })
340
+ }
341
+ return {
342
+ fetch: (request?: ApiRequest) => {
343
+ const apiPayload = constructPayload(api, ctx.dataSignal.get())
344
+ let body = apiPayload.body
345
+ // Use a Headers object since it's case insensitive
346
+ const headers = new Headers({
347
+ ...apiPayload.headers,
348
+ ...(request?.headers ?? {}),
349
+ })
350
+ if (request?.body) {
351
+ body = encodeBody(
352
+ request.body,
353
+ headers.get('Content-Type') ?? undefined,
354
+ )
355
+ }
356
+ if (body instanceof FormData) {
357
+ // Remove content type header if body is a FormData object
358
+ // Otherwise fetch won't do its magic when sending the request
359
+ headers.delete('Content-Type')
360
+ }
361
+ const payload: ApiRequest = {
362
+ url: request?.url ?? apiPayload.url,
363
+ method: request?.method ?? apiPayload.method,
364
+ auth: request?.auth ?? apiPayload.auth,
365
+ headers: [...headers.entries()].reduce<Record<string, string>>(
366
+ (acc, [key, value]) => ({ ...acc, [key]: value }),
367
+ {},
368
+ ),
369
+ body,
370
+ }
371
+ return trigger(payload)
372
+ },
373
+ destroy: () => payloadSignal?.destroy(),
374
+ }
375
+ }