@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,196 @@
1
+ import { getClassName, toValidClassName, } from '@nordcraft/core/dist/styling/className';
2
+ import { kebabCase } from '@nordcraft/core/dist/styling/style.css';
3
+ import { variantSelector } from '@nordcraft/core/dist/styling/variantSelector';
4
+ import { omitKeys } from '@nordcraft/core/dist/utils/collections';
5
+ const LEGACY_BREAKPOINTS = {
6
+ large: 1440,
7
+ small: 576,
8
+ medium: 960,
9
+ };
10
+ export const SIZE_PROPERTIES = new Set([
11
+ 'width',
12
+ 'min-width',
13
+ 'max-width',
14
+ 'height',
15
+ 'min-height',
16
+ 'max-height',
17
+ 'margin',
18
+ 'margin-top',
19
+ 'margin-left',
20
+ 'margin-bottom',
21
+ 'margin-right',
22
+ 'padding',
23
+ 'padding-top',
24
+ 'padding-left',
25
+ 'padding-bottom',
26
+ 'padding-right',
27
+ 'gap',
28
+ 'gap-x',
29
+ 'gap-y',
30
+ 'border-radius',
31
+ 'border-bottom-left-radius',
32
+ 'border-bottom-right-radius',
33
+ 'border-top-left-radius',
34
+ 'border-top-right-radius',
35
+ 'border-width',
36
+ 'border-top-width',
37
+ 'border-left-width',
38
+ 'border-bottom-width',
39
+ 'border-right-width',
40
+ 'font-size',
41
+ 'left',
42
+ 'right',
43
+ 'top',
44
+ 'bottom',
45
+ 'outline-width',
46
+ ]);
47
+ export const insertStyles = (parent, root, components) => {
48
+ const getNodeStyles = (node, classHash) => {
49
+ const style = omitKeys(node.style ?? {}, [
50
+ 'variants',
51
+ 'breakpoints',
52
+ 'mediaQuery',
53
+ 'shadows',
54
+ ]);
55
+ const styleElem = document.createElement('style');
56
+ styleElem.setAttribute('data-hash', classHash);
57
+ styleElem.appendChild(document.createTextNode(`
58
+ ${renderVariant('.' + classHash, style)}
59
+
60
+ ${node.variants
61
+ ? node.variants
62
+ .map((variant) => {
63
+ const selector = `.${classHash}${variantSelector(variant)}`;
64
+ const renderedVariant = renderVariant(selector, variant.style, {
65
+ startingStyle: variant.startingStyle,
66
+ });
67
+ return variant.mediaQuery
68
+ ? `
69
+ @media (${Object.entries(variant.mediaQuery)
70
+ .map(([key, value]) => `${key}: ${value}`)
71
+ .filter(Boolean)
72
+ .join(') and (')}) {
73
+ ${renderedVariant}
74
+ }
75
+ `
76
+ : variant.breakpoint
77
+ ? `
78
+ @media (min-width: ${LEGACY_BREAKPOINTS[variant.breakpoint]}px) {
79
+ ${renderedVariant}
80
+ }
81
+ `
82
+ : renderedVariant;
83
+ })
84
+ .join('\n')
85
+ : ''}
86
+
87
+ ${node.animations
88
+ ? Object.entries(node.animations)
89
+ .map(([animationName, keyframes]) => {
90
+ return `
91
+ @keyframes ${animationName} {
92
+ ${Object.values(keyframes)
93
+ .sort((a, b) => a.position - b.position)
94
+ .map(({ key, position, value }) => {
95
+ return `
96
+ ${position * 100}% {
97
+ ${key}: ${value};
98
+ }
99
+ `;
100
+ })
101
+ .join('\n')}
102
+ }
103
+ `;
104
+ })
105
+ .join('\n')
106
+ : ''}
107
+ `));
108
+ return styleElem;
109
+ };
110
+ // Make sure that CSS for dependant components are rendered first so that instance styles will override.
111
+ const visitedComponents = new Set();
112
+ const newStyles = new Map();
113
+ function insertComponentStyles(component, package_name) {
114
+ if (visitedComponents.has(component.name)) {
115
+ return;
116
+ }
117
+ visitedComponents.add(component.name);
118
+ if (!component.nodes) {
119
+ // eslint-disable-next-line no-console
120
+ console.warn('Unable to find nodes for component', component.name);
121
+ return;
122
+ }
123
+ Object.entries(component.nodes).forEach(([id, node]) => {
124
+ if (node.type === 'component') {
125
+ const childComponent = components.find((c) => c.name ===
126
+ [node.package ?? package_name, node.name]
127
+ ?.filter((n) => n)
128
+ .join('/'));
129
+ if (childComponent) {
130
+ insertComponentStyles(childComponent, node.package ?? package_name);
131
+ const instanceClassHash = toValidClassName(`${component.name}:${id}`, true);
132
+ newStyles.set(instanceClassHash, getNodeStyles(node, instanceClassHash));
133
+ }
134
+ }
135
+ else if (node.type === 'element') {
136
+ const classHash = getClassName([node.style, node.variants]);
137
+ newStyles.set(classHash, getNodeStyles(node, classHash));
138
+ }
139
+ });
140
+ }
141
+ insertComponentStyles(root, undefined);
142
+ // Remove old styles.
143
+ // We do not keep track of changes, so must remove all and re-add as order matters.
144
+ parent.querySelectorAll('[data-hash]').forEach((node) => node.remove());
145
+ // Add new styles
146
+ const fragment = document.createDocumentFragment();
147
+ newStyles.forEach((style) => {
148
+ fragment.appendChild(style);
149
+ });
150
+ parent.appendChild(fragment);
151
+ };
152
+ const renderVariant = (selector, style, options) => {
153
+ const scrollbarStyles = Object.entries(style).filter(([key]) => key === 'scrollbar-width');
154
+ let styles = styleToCss(style);
155
+ if (options?.startingStyle) {
156
+ styles = `@starting-style {
157
+ ${styles}
158
+ }`;
159
+ }
160
+ return `
161
+ ${selector} {
162
+ ${styles}
163
+ }
164
+ ${scrollbarStyles.length > 0
165
+ ? `
166
+ ${selector}::-webkit-scrollbar {
167
+ ${scrollbarStyles
168
+ .map(([_, value]) => {
169
+ switch (value) {
170
+ case 'none':
171
+ return 'width: 0;';
172
+ case 'thin':
173
+ return 'width:4px;';
174
+ default:
175
+ return '';
176
+ }
177
+ })
178
+ .join('\n')}
179
+ }
180
+ `
181
+ : ''}
182
+ `;
183
+ };
184
+ export const styleToCss = (style) => {
185
+ return Object.entries(style)
186
+ .map(([property, value]) => {
187
+ const propertyName = kebabCase(property);
188
+ const propertyValue = String(Number(value)) === String(value) &&
189
+ SIZE_PROPERTIES.has(propertyName)
190
+ ? `${Number(value) * 4}px`
191
+ : value;
192
+ return `${propertyName}:${propertyValue};`;
193
+ })
194
+ .join('\n');
195
+ };
196
+ //# sourceMappingURL=style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style.js","sourceRoot":"","sources":["../../src/styles/style.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * A helper class to batch multiple callbacks and process them in a single update step just before the next frame render, but after the current stack.
3
+ * This is more efficient than processing each callback in a separate requestAnimationFrame due to the overhead.
4
+ */
5
+ export declare class BatchQueue {
6
+ private batchQueue;
7
+ private isProcessing;
8
+ private processBatch;
9
+ add(callback: () => void): void;
10
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * A helper class to batch multiple callbacks and process them in a single update step just before the next frame render, but after the current stack.
3
+ * This is more efficient than processing each callback in a separate requestAnimationFrame due to the overhead.
4
+ */
5
+ export class BatchQueue {
6
+ batchQueue = [];
7
+ isProcessing = false;
8
+ processBatch() {
9
+ if (this.isProcessing)
10
+ return;
11
+ this.isProcessing = true;
12
+ requestAnimationFrame(() => {
13
+ while (this.batchQueue.length > 0) {
14
+ const callback = this.batchQueue.shift();
15
+ callback?.();
16
+ }
17
+ this.isProcessing = false;
18
+ });
19
+ }
20
+ add(callback) {
21
+ this.batchQueue.push(callback);
22
+ this.processBatch();
23
+ }
24
+ }
25
+ //# sourceMappingURL=BatchQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BatchQueue.js","sourceRoot":"","sources":["../../src/utils/BatchQueue.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,OAAO,UAAU;IACb,UAAU,GAAsB,EAAE,CAAA;IAClC,YAAY,GAAG,KAAK,CAAA;IACpB,YAAY;QAClB,IAAI,IAAI,CAAC,YAAY;YAAE,OAAM;QAC7B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAA;QAExB,qBAAqB,CAAC,GAAG,EAAE;YACzB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;gBACxC,QAAQ,EAAE,EAAE,CAAA;YACd,CAAC;YACD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;QAC3B,CAAC,CAAC,CAAA;IACJ,CAAC;IACM,GAAG,CAAC,QAAoB;QAC7B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC9B,IAAI,CAAC,YAAY,EAAE,CAAA;IACrB,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ import type { Component } from '@nordcraft/core/dist/component/component.types';
2
+ import type { FormulaCache } from '../types';
3
+ export declare function createFormulaCache(component: Component): FormulaCache;
@@ -0,0 +1,81 @@
1
+ import { get, mapObject } from '@nordcraft/core/dist/utils/collections';
2
+ import { isDefined } from '@nordcraft/core/dist/utils/util';
3
+ export function createFormulaCache(component) {
4
+ if (!isDefined(component.formulas)) {
5
+ return {};
6
+ }
7
+ return mapObject(component.formulas, ([name, f]) => {
8
+ const { canCache, keys } = f.memoize
9
+ ? getFormulaCacheConfig(f.formula, component)
10
+ : { canCache: false, keys: [] };
11
+ let cacheInput;
12
+ let cacheData;
13
+ return [
14
+ name,
15
+ {
16
+ get: (data) => {
17
+ if (canCache &&
18
+ cacheInput &&
19
+ keys.every((key) => {
20
+ return get(data, key) === get(cacheInput, key);
21
+ })) {
22
+ return { hit: true, data: cacheData };
23
+ }
24
+ return { hit: false };
25
+ },
26
+ set: (data, result) => {
27
+ if (canCache) {
28
+ cacheInput = data;
29
+ cacheData = result;
30
+ }
31
+ },
32
+ },
33
+ ];
34
+ });
35
+ }
36
+ function getFormulaCacheConfig(formula, component) {
37
+ const paths = [];
38
+ function visitOperation(op) {
39
+ if (!op) {
40
+ return;
41
+ }
42
+ if (op.type == 'path' && op.path[0] !== 'Args') {
43
+ paths.push(op.path);
44
+ }
45
+ if (Array.isArray(op?.arguments)) {
46
+ ;
47
+ op?.arguments.forEach((arg) => visitOperation(arg.formula));
48
+ }
49
+ if (op.type === 'record' && Array.isArray(op.entries)) {
50
+ op.entries.forEach((arg) => visitOperation(arg.formula));
51
+ }
52
+ if (op.type === 'apply') {
53
+ if (!component.formulas?.[op.name]?.memoize) {
54
+ throw new Error('Cannot memoize');
55
+ }
56
+ visitOperation(component.formulas?.[op.name]?.formula);
57
+ }
58
+ }
59
+ try {
60
+ visitOperation(formula);
61
+ }
62
+ catch {
63
+ return {
64
+ canCache: false,
65
+ keys: [],
66
+ };
67
+ }
68
+ const keys = [];
69
+ paths
70
+ .sort((a, b) => a.length - b.length)
71
+ .forEach((path) => {
72
+ if (!keys.some((key) => key.every((k, i) => k === path[i]))) {
73
+ keys.push(path);
74
+ }
75
+ });
76
+ return {
77
+ canCache: true,
78
+ keys,
79
+ };
80
+ }
81
+ //# sourceMappingURL=createFormulaCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createFormulaCache.js","sourceRoot":"","sources":["../../src/utils/createFormulaCache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Line, Point } from '../editor/types';
2
+ /**
3
+ * Finds the nearest line to a given point from an array of lines.
4
+ *
5
+ * @param lines - An array of line segments defined by their endpoints.
6
+ * @param point - The point to which the nearest line is to be found.
7
+ * @returns The line segment nearest to the given point.
8
+ */
9
+ export declare function findNearestLine(lines: Line[], point: Point): {
10
+ nearestLine: Line | null;
11
+ dist: number;
12
+ projectionPoint: number;
13
+ };
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Finds the nearest line to a given point from an array of lines.
3
+ *
4
+ * @param lines - An array of line segments defined by their endpoints.
5
+ * @param point - The point to which the nearest line is to be found.
6
+ * @returns The line segment nearest to the given point.
7
+ */
8
+ export function findNearestLine(lines, point) {
9
+ let minDistSquared = Infinity;
10
+ let nearestLine = null;
11
+ let nearestProjectionPoint = 0;
12
+ for (const line of lines) {
13
+ const { distSquared, projectionPoint } = distancePointToSegmentSquared(point, line);
14
+ if (distSquared < minDistSquared) {
15
+ minDistSquared = distSquared;
16
+ nearestLine = line;
17
+ nearestProjectionPoint = projectionPoint;
18
+ }
19
+ }
20
+ return {
21
+ nearestLine,
22
+ dist: Math.sqrt(minDistSquared),
23
+ projectionPoint: nearestProjectionPoint,
24
+ };
25
+ }
26
+ /**
27
+ * Represents where the perpendicular projection of the point onto the infinite line lies relative to the line segment:
28
+ * - If t is 0, the projection is at (x1, y1).
29
+ * - If t is 1, the projection is at (x2, y2).
30
+ * - If t is between 0 and 1, the projection lies somewhere between the two endpoints.
31
+ *
32
+ * (x1, y1) *---o-----------* (x2, y2)
33
+ * | /
34
+ * | /
35
+ * | /
36
+ * | /
37
+ * | /
38
+ * MIN_DIST -> | /
39
+ * | /
40
+ * | /
41
+ * | /
42
+ * | /
43
+ * |/
44
+ * (x, y)
45
+ *
46
+ * Where "o" The length along the line segment where the projection point lies.
47
+ *
48
+ * Notice that the calculation works for diagonal lines as well as horizontal and vertical lines.
49
+ */
50
+ function distancePointToSegmentSquared(point, line) {
51
+ const dx = line.x2 - line.x1;
52
+ const dy = line.y2 - line.y1;
53
+ const l2 = dx * dx + dy * dy;
54
+ // If l2 is zero, the line segment is actually a point. We return the squared distance between the point and this single point.
55
+ if (l2 === 0) {
56
+ return {
57
+ distSquared: (point.x - line.x1) * (point.x - line.x1) +
58
+ (point.y - line.y1) * (point.y - line.y1),
59
+ projectionPoint: 0.5,
60
+ };
61
+ }
62
+ let projectionPoint = ((point.x - line.x1) * dx + (point.y - line.y1) * dy) / l2;
63
+ // Clamp t to [0,1] for the projection point to lie within the finite line segment.
64
+ projectionPoint = Math.max(0, Math.min(1, projectionPoint));
65
+ const projX = line.x1 + projectionPoint * dx;
66
+ const projY = line.y1 + projectionPoint * dy;
67
+ // No need to take the square root, since we are only comparing distances and square root is monotonic.
68
+ return {
69
+ distSquared: (point.x - projX) * (point.x - projX) +
70
+ (point.y - projY) * (point.y - projY),
71
+ projectionPoint,
72
+ };
73
+ }
74
+ //# sourceMappingURL=findNearestLine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findNearestLine.js","sourceRoot":"","sources":["../../src/utils/findNearestLine.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAa,EACb,KAAY;IAEZ,IAAI,cAAc,GAAG,QAAQ,CAAA;IAC7B,IAAI,WAAW,GAAgB,IAAI,CAAA;IACnC,IAAI,sBAAsB,GAAG,CAAC,CAAA;IAE9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,GAAG,6BAA6B,CACpE,KAAK,EACL,IAAI,CACL,CAAA;QACD,IAAI,WAAW,GAAG,cAAc,EAAE,CAAC;YACjC,cAAc,GAAG,WAAW,CAAA;YAC5B,WAAW,GAAG,IAAI,CAAA;YAClB,sBAAsB,GAAG,eAAe,CAAA;QAC1C,CAAC;IACH,CAAC;IAED,OAAO;QACL,WAAW;QACX,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;QAC/B,eAAe,EAAE,sBAAsB;KACxC,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAS,6BAA6B,CAAC,KAAY,EAAE,IAAU;IAC7D,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAA;IAC5B,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAA;IAC5B,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;IAE5B,+HAA+H;IAC/H,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;QACb,OAAO;YACL,WAAW,EACT,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;gBACzC,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;YAC3C,eAAe,EAAE,GAAG;SACrB,CAAA;IACH,CAAC;IAED,IAAI,eAAe,GACjB,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAA;IAE5D,mFAAmF;IACnF,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,CAAA;IAE3D,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,GAAG,eAAe,GAAG,EAAE,CAAA;IAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,GAAG,eAAe,GAAG,EAAE,CAAA;IAE5C,uGAAuG;IACvG,OAAO;QACL,WAAW,EACT,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC;YACrC,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC;QACvC,eAAe;KAChB,CAAA;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,59 @@
1
+ import { findNearestLine } from './findNearestLine';
2
+ describe('findNearestLine', () => {
3
+ test('should find the nearest line to a point', () => {
4
+ const lines = [
5
+ { x1: 0, y1: 0, x2: 0, y2: 1 },
6
+ { x1: 1, y1: 0, x2: 1, y2: 1 },
7
+ { x1: 2, y1: 0, x2: 2, y2: 1 },
8
+ ];
9
+ const point = { x: 1.5, y: 0.5 };
10
+ const nearestLine = findNearestLine(lines, point)?.nearestLine;
11
+ expect(nearestLine).toEqual({ x1: 1, y1: 0, x2: 1, y2: 1 });
12
+ });
13
+ test('should handle point exactly on a line', () => {
14
+ const lines = [
15
+ { x1: 0, y1: 0, x2: 2, y2: 0 },
16
+ { x1: 1, y1: -1, x2: 1, y2: 1 },
17
+ ];
18
+ const point = { x: 1, y: 0.5 };
19
+ const nearestLine = findNearestLine(lines, point)?.nearestLine;
20
+ expect(nearestLine).toEqual({ x1: 1, y1: -1, x2: 1, y2: 1 });
21
+ });
22
+ test('should handle empty lines array', () => {
23
+ const lines = [];
24
+ const point = { x: 0, y: 0 };
25
+ expect(findNearestLine(lines, point).nearestLine).toBeNull();
26
+ });
27
+ test('should handle lines with zero length (points)', () => {
28
+ const lines = [
29
+ { x1: 1, y1: 1, x2: 1, y2: 1 },
30
+ { x1: 2, y1: 2, x2: 3, y2: 3 },
31
+ ];
32
+ const point = { x: 1, y: 1.5 };
33
+ const nearestLine = findNearestLine(lines, point)?.nearestLine;
34
+ expect(nearestLine).toEqual({ x1: 1, y1: 1, x2: 1, y2: 1 });
35
+ });
36
+ test('should handle negative coordinates', () => {
37
+ const lines = [
38
+ { x1: -2, y1: -2, x2: -2, y2: 2 },
39
+ { x1: -2, y1: 2, x2: 2, y2: 2 },
40
+ { x1: 2, y1: 2, x2: 2, y2: -2 },
41
+ { x1: 2, y1: -2, x2: -2, y2: -2 },
42
+ ];
43
+ const point = { x: 0, y: 0 };
44
+ const nearestLine = findNearestLine(lines, point)?.nearestLine;
45
+ // The point is inside the square; function should return one of the sides
46
+ expect(nearestLine).toEqual({ x1: -2, y1: -2, x2: -2, y2: 2 });
47
+ });
48
+ test('should handle when multiple lines are equally close', () => {
49
+ const lines = [
50
+ { x1: 0, y1: 1, x2: 1, y2: 1 },
51
+ { x1: 0, y1: -1, x2: 1, y2: -1 },
52
+ ];
53
+ const point = { x: 0.5, y: 0 };
54
+ const nearestLine = findNearestLine(lines, point)?.nearestLine;
55
+ // Both lines are at distance 1; the function should return the first one
56
+ expect(nearestLine).toEqual({ x1: 0, y1: 1, x2: 1, y2: 1 });
57
+ });
58
+ });
59
+ //# sourceMappingURL=findNearestLine.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findNearestLine.test.js","sourceRoot":"","sources":["../../src/utils/findNearestLine.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function getDragData(event: Event): Record<string, any> | undefined;
@@ -0,0 +1,10 @@
1
+ export function getDragData(event) {
2
+ if (event instanceof DragEvent) {
3
+ return Array.from(event.dataTransfer?.items ?? []).reduce((dragData, item) => {
4
+ dragData[item.type] = event.dataTransfer?.getData(item.type);
5
+ return dragData;
6
+ }, {});
7
+ }
8
+ return;
9
+ }
10
+ //# sourceMappingURL=getDragData.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getDragData.js","sourceRoot":"","sources":["../../src/utils/getDragData.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,KAAY;IACtC,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAEvD,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE;YACnB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAC5D,OAAO,QAAQ,CAAA;QACjB,CAAC,EAAE,EAAE,CAAC,CAAA;IACR,CAAC;IACD,OAAM;AACR,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ElementNodeModel } from '@nordcraft/core/dist/component/component.types';
2
+ import type { ComponentContext } from '../types';
3
+ export declare function getElementTagName(node: ElementNodeModel, ctx: ComponentContext, id: string): string;
@@ -0,0 +1,7 @@
1
+ export function getElementTagName(node, ctx, id) {
2
+ if (ctx.component.version === 2 && id === 'root') {
3
+ return `${ctx.package ?? ctx.toddle.project}-${node.tag}`;
4
+ }
5
+ return node.tag;
6
+ }
7
+ //# sourceMappingURL=getElementTagName.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getElementTagName.js","sourceRoot":"","sources":["../../src/utils/getElementTagName.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,iBAAiB,CAC/B,IAAsB,EACtB,GAAqB,EACrB,EAAU;IAEV,IAAI,GAAG,CAAC,SAAS,CAAC,OAAO,KAAK,CAAC,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC;QACjD,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,CAAA;IAC3D,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAA;AACjB,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { Component, NodeModel } from '@nordcraft/core/dist/component/component.types';
2
+ type NodeWithNodeId = NodeModel & {
3
+ nodeId: string;
4
+ };
5
+ interface NodeAndAncestorLookup {
6
+ node: NodeWithNodeId;
7
+ ancestors: NodeWithNodeId[];
8
+ }
9
+ export declare const getNodeAndAncestors: (component: Component, root: NodeModel, id: unknown) => NodeAndAncestorLookup | undefined;
10
+ export declare const isNodeOrAncestorConditional: (nodeLookup?: NodeAndAncestorLookup) => nodeLookup is NodeAndAncestorLookup;
11
+ /**
12
+ * @returns The next toddle sibling element or null if this is the last element. A toddle sibling is a sibling with a higher index or a the index, but a higher repeat index.
13
+ */
14
+ export declare const getNextSiblingElement: (path: string, parentElement: Element | ShadowRoot) => Element | null;
15
+ /**
16
+ * This function efficiently ensures that:
17
+ * 1. New items are added in the correct position.
18
+ * 2. Existing items are not moved if they are already in the correct order.
19
+ */
20
+ export declare function ensureEfficientOrdering(parentElement: Element | ShadowRoot, items: ReadonlyArray<Element | Text>, nextElement?: Element | Text | null): void;
21
+ export {};
@@ -0,0 +1,89 @@
1
+ export const getNodeAndAncestors = (component, root, id) => {
2
+ if (typeof id !== 'string' || id.length === 0) {
3
+ return undefined;
4
+ }
5
+ const path = id.split('.');
6
+ const pathParsed = path.map((n) => parseInt(n));
7
+ const ancestors = [];
8
+ // nodePath skips the root element as it's selected as the initial
9
+ // value in the reduce below
10
+ const nodePath = pathParsed.slice(1);
11
+ const node = nodePath.reduce((node, childIndex, i) => {
12
+ switch (node?.type) {
13
+ // 'text' elements don't have any children
14
+ case 'element':
15
+ case 'component':
16
+ case 'slot':
17
+ // Ancestors are elements before the target node
18
+ if (i <= nodePath.length - 1) {
19
+ ancestors.push({
20
+ ...node,
21
+ // Use the original path as origin to get correct nodeIds
22
+ nodeId: path.slice(0, i + 1).join('.'),
23
+ });
24
+ }
25
+ return component.nodes[node.children[childIndex]];
26
+ default:
27
+ return undefined;
28
+ }
29
+ }, root);
30
+ if (node === undefined) {
31
+ return undefined;
32
+ }
33
+ return { node: { ...node, nodeId: id }, ancestors };
34
+ };
35
+ export const isNodeOrAncestorConditional = (nodeLookup) => nodeLookup?.node?.condition !== undefined ||
36
+ nodeLookup?.ancestors.some((a) => a.condition !== undefined) === true;
37
+ /**
38
+ * @returns The next toddle sibling element or null if this is the last element. A toddle sibling is a sibling with a higher index or a the index, but a higher repeat index.
39
+ */
40
+ export const getNextSiblingElement = (path, parentElement) => {
41
+ const pathParts = path.split('.');
42
+ const lastPathPart = pathParts.slice(-1)[0];
43
+ const index = parseInt(lastPathPart);
44
+ const repeatIndex = parseInt(String(lastPathPart.split('(')[1]));
45
+ // Find the first child that either has a higher index or a similar index, but higher repeat index
46
+ for (const child of parentElement.children) {
47
+ const childPath = child.getAttribute('data-id');
48
+ const lastChildPathPart = childPath?.split('.').slice(-1)[0];
49
+ const childIndex = parseInt(String(lastChildPathPart));
50
+ if (childIndex === index &&
51
+ parseInt(String(lastChildPathPart?.split('(')[1])) > repeatIndex) {
52
+ return child;
53
+ }
54
+ if (childIndex > index) {
55
+ return child;
56
+ }
57
+ }
58
+ return null;
59
+ };
60
+ /**
61
+ * This function efficiently ensures that:
62
+ * 1. New items are added in the correct position.
63
+ * 2. Existing items are not moved if they are already in the correct order.
64
+ */
65
+ export function ensureEfficientOrdering(parentElement, items, nextElement = null) {
66
+ // Identify the starting point for comparisons.
67
+ let insertBeforeElement = nextElement; // If insertBeforeElement is null, items will be appended at the end.
68
+ // To track the current position in the DOM, we'll use a marker that advances through the sibling elements.
69
+ let currentMarker = insertBeforeElement
70
+ ? insertBeforeElement.previousSibling
71
+ : parentElement.lastChild;
72
+ // We'll process the items array in reverse order to minimize the number of DOM operations.
73
+ for (let i = items.length - 1; i >= 0; i--) {
74
+ const item = items[i];
75
+ // Check if the item is already in the correct position by comparing it with the currentMarker.
76
+ if (item === currentMarker) {
77
+ // The item is in the correct position, move the marker to the previous sibling.
78
+ currentMarker = item.previousSibling;
79
+ }
80
+ else {
81
+ // The item is either not in the DOM or not in the correct position.
82
+ // Insert the item before the insertBeforeElement (or append it if insertBeforeElement is null).
83
+ parentElement.insertBefore(item, insertBeforeElement);
84
+ }
85
+ // Update insertBeforeElement to the current item for the next iteration, as we need to insert subsequent items before this one.
86
+ insertBeforeElement = item;
87
+ }
88
+ }
89
+ //# sourceMappingURL=nodes.js.map