@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.
- package/README.md +5 -0
- package/dist/api/createAPI.d.ts +20 -0
- package/dist/api/createAPI.js +319 -0
- package/dist/api/createAPI.js.map +1 -0
- package/dist/api/createAPIv2.d.ts +7 -0
- package/dist/api/createAPIv2.js +686 -0
- package/dist/api/createAPIv2.js.map +1 -0
- package/dist/components/createComponent.d.ts +13 -0
- package/dist/components/createComponent.js +216 -0
- package/dist/components/createComponent.js.map +1 -0
- package/dist/components/createElement.d.ts +3 -0
- package/dist/components/createElement.js +208 -0
- package/dist/components/createElement.js.map +1 -0
- package/dist/components/createNode.d.ts +22 -0
- package/dist/components/createNode.js +272 -0
- package/dist/components/createNode.js.map +1 -0
- package/dist/components/createSlot.d.ts +3 -0
- package/dist/components/createSlot.js +49 -0
- package/dist/components/createSlot.js.map +1 -0
- package/dist/components/createText.d.ts +23 -0
- package/dist/components/createText.js +68 -0
- package/dist/components/createText.js.map +1 -0
- package/dist/components/createText.test.d.ts +1 -0
- package/dist/components/createText.test.js +113 -0
- package/dist/components/createText.test.js.map +1 -0
- package/dist/components/renderComponent.d.ts +34 -0
- package/dist/components/renderComponent.js +66 -0
- package/dist/components/renderComponent.js.map +1 -0
- package/dist/context/isContextProvider.d.ts +2 -0
- package/dist/context/isContextProvider.js +5 -0
- package/dist/context/isContextProvider.js.map +1 -0
- package/dist/context/subscribeToContext.d.ts +4 -0
- package/dist/context/subscribeToContext.js +93 -0
- package/dist/context/subscribeToContext.js.map +1 -0
- package/dist/custom-components/components.d.ts +1 -0
- package/dist/custom-components/components.js +2 -0
- package/dist/custom-components/components.js.map +1 -0
- package/dist/custom-components/toddle-portal.d.ts +6 -0
- package/dist/custom-components/toddle-portal.js +20 -0
- package/dist/custom-components/toddle-portal.js.map +1 -0
- package/dist/custom-element/ToddleComponent.d.ts +37 -0
- package/dist/custom-element/ToddleComponent.js +244 -0
- package/dist/custom-element/ToddleComponent.js.map +1 -0
- package/dist/custom-element/defineComponents.d.ts +26 -0
- package/dist/custom-element/defineComponents.js +42 -0
- package/dist/custom-element/defineComponents.js.map +1 -0
- package/dist/custom-element.main.d.ts +3 -0
- package/dist/custom-element.main.esm.js +266 -0
- package/dist/custom-element.main.esm.js.map +7 -0
- package/dist/custom-element.main.js +14 -0
- package/dist/custom-element.main.js.map +1 -0
- package/dist/debug/logState.d.ts +4 -0
- package/dist/debug/logState.js +19 -0
- package/dist/debug/logState.js.map +1 -0
- package/dist/editor/drag-drop/dragEnded.d.ts +2 -0
- package/dist/editor/drag-drop/dragEnded.js +56 -0
- package/dist/editor/drag-drop/dragEnded.js.map +1 -0
- package/dist/editor/drag-drop/dragMove.d.ts +3 -0
- package/dist/editor/drag-drop/dragMove.js +74 -0
- package/dist/editor/drag-drop/dragMove.js.map +1 -0
- package/dist/editor/drag-drop/dragReorder.d.ts +3 -0
- package/dist/editor/drag-drop/dragReorder.js +92 -0
- package/dist/editor/drag-drop/dragReorder.js.map +1 -0
- package/dist/editor/drag-drop/dragStarted.d.ts +9 -0
- package/dist/editor/drag-drop/dragStarted.js +100 -0
- package/dist/editor/drag-drop/dragStarted.js.map +1 -0
- package/dist/editor/drag-drop/dropHighlight.d.ts +16 -0
- package/dist/editor/drag-drop/dropHighlight.js +50 -0
- package/dist/editor/drag-drop/dropHighlight.js.map +1 -0
- package/dist/editor/drag-drop/getInsertAreas.d.ts +20 -0
- package/dist/editor/drag-drop/getInsertAreas.js +220 -0
- package/dist/editor/drag-drop/getInsertAreas.js.map +1 -0
- package/dist/editor-preview.main.d.ts +19 -0
- package/dist/editor-preview.main.js +1303 -0
- package/dist/editor-preview.main.js.map +1 -0
- package/dist/events/handleAction.d.ts +3 -0
- package/dist/events/handleAction.js +307 -0
- package/dist/events/handleAction.js.map +1 -0
- package/dist/page.main.d.ts +7 -0
- package/dist/page.main.esm.js +8 -0
- package/dist/page.main.esm.js.map +7 -0
- package/dist/page.main.js +395 -0
- package/dist/page.main.js.map +1 -0
- package/dist/signal/signal.d.ts +19 -0
- package/dist/signal/signal.js +65 -0
- package/dist/signal/signal.js.map +1 -0
- package/dist/styles/style.d.ts +4 -0
- package/dist/styles/style.js +196 -0
- package/dist/styles/style.js.map +1 -0
- package/dist/utils/BatchQueue.d.ts +10 -0
- package/dist/utils/BatchQueue.js +25 -0
- package/dist/utils/BatchQueue.js.map +1 -0
- package/dist/utils/createFormulaCache.d.ts +3 -0
- package/dist/utils/createFormulaCache.js +81 -0
- package/dist/utils/createFormulaCache.js.map +1 -0
- package/dist/utils/findNearestLine.d.ts +13 -0
- package/dist/utils/findNearestLine.js +74 -0
- package/dist/utils/findNearestLine.js.map +1 -0
- package/dist/utils/findNearestLine.test.d.ts +1 -0
- package/dist/utils/findNearestLine.test.js +59 -0
- package/dist/utils/findNearestLine.test.js.map +1 -0
- package/dist/utils/getDragData.d.ts +1 -0
- package/dist/utils/getDragData.js +10 -0
- package/dist/utils/getDragData.js.map +1 -0
- package/dist/utils/getElementTagName.d.ts +3 -0
- package/dist/utils/getElementTagName.js +7 -0
- package/dist/utils/getElementTagName.js.map +1 -0
- package/dist/utils/nodes.d.ts +21 -0
- package/dist/utils/nodes.js +89 -0
- package/dist/utils/nodes.js.map +1 -0
- package/dist/utils/omitStyle.d.ts +2 -0
- package/dist/utils/omitStyle.js +13 -0
- package/dist/utils/omitStyle.js.map +1 -0
- package/dist/utils/rectHasPoint.d.ts +2 -0
- package/dist/utils/rectHasPoint.js +4 -0
- package/dist/utils/rectHasPoint.js.map +1 -0
- package/dist/utils/setAttribute.d.ts +4 -0
- package/dist/utils/setAttribute.js +57 -0
- package/dist/utils/setAttribute.js.map +1 -0
- package/dist/utils/tryStartViewTransition.d.ts +5 -0
- package/dist/utils/tryStartViewTransition.js +14 -0
- package/dist/utils/tryStartViewTransition.js.map +1 -0
- package/dist/utils/url.d.ts +2 -0
- package/dist/utils/url.js +36 -0
- package/dist/utils/url.js.map +1 -0
- package/package.json +25 -0
- package/src/api/createAPI.ts +375 -0
- package/src/api/createAPIv2.ts +931 -0
- package/src/components/createComponent.ts +280 -0
- package/src/components/createElement.ts +240 -0
- package/src/components/createNode.ts +381 -0
- package/src/components/createSlot.ts +61 -0
- package/src/components/createText.test.ts +117 -0
- package/src/components/createText.ts +104 -0
- package/src/components/renderComponent.ts +145 -0
- package/src/context/isContextProvider.ts +12 -0
- package/src/context/subscribeToContext.ts +135 -0
- package/src/custom-components/components.ts +1 -0
- package/src/custom-components/toddle-portal.ts +19 -0
- package/src/custom-element/ToddleComponent.ts +315 -0
- package/src/custom-element/defineComponents.ts +65 -0
- package/src/custom-element.main.ts +24 -0
- package/src/debug/logState.ts +30 -0
- package/src/editor/drag-drop/dragEnded.ts +75 -0
- package/src/editor/drag-drop/dragMove.ts +95 -0
- package/src/editor/drag-drop/dragReorder.ts +137 -0
- package/src/editor/drag-drop/dragStarted.ts +145 -0
- package/src/editor/drag-drop/dropHighlight.ts +82 -0
- package/src/editor/drag-drop/getInsertAreas.ts +235 -0
- package/src/editor/types.d.ts +36 -0
- package/src/editor-preview.main.ts +1782 -0
- package/src/events/handleAction.ts +387 -0
- package/src/page.main.ts +489 -0
- package/src/signal/signal.ts +74 -0
- package/src/styles/style.ts +254 -0
- package/src/types.d.ts +93 -0
- package/src/utils/BatchQueue.ts +24 -0
- package/src/utils/createFormulaCache.ts +96 -0
- package/src/utils/findNearestLine.test.ts +65 -0
- package/src/utils/findNearestLine.ts +92 -0
- package/src/utils/getDragData.ts +11 -0
- package/src/utils/getElementTagName.ts +14 -0
- package/src/utils/nodes.ts +125 -0
- package/src/utils/omitStyle.ts +19 -0
- package/src/utils/rectHasPoint.ts +5 -0
- package/src/utils/setAttribute.ts +56 -0
- package/src/utils/tryStartViewTransition.ts +32 -0
- package/src/utils/url.ts +45 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Component,
|
|
3
|
+
NodeModel,
|
|
4
|
+
} from '@nordcraft/core/dist/component/component.types'
|
|
5
|
+
|
|
6
|
+
type NodeWithNodeId = NodeModel & { nodeId: string }
|
|
7
|
+
|
|
8
|
+
interface NodeAndAncestorLookup {
|
|
9
|
+
node: NodeWithNodeId
|
|
10
|
+
ancestors: NodeWithNodeId[]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const getNodeAndAncestors = (
|
|
14
|
+
component: Component,
|
|
15
|
+
root: NodeModel,
|
|
16
|
+
id: unknown,
|
|
17
|
+
): NodeAndAncestorLookup | undefined => {
|
|
18
|
+
if (typeof id !== 'string' || id.length === 0) {
|
|
19
|
+
return undefined
|
|
20
|
+
}
|
|
21
|
+
const path = id.split('.')
|
|
22
|
+
const pathParsed = path.map((n) => parseInt(n))
|
|
23
|
+
const ancestors: NodeWithNodeId[] = []
|
|
24
|
+
// nodePath skips the root element as it's selected as the initial
|
|
25
|
+
// value in the reduce below
|
|
26
|
+
const nodePath = pathParsed.slice(1)
|
|
27
|
+
const node = nodePath.reduce((node: NodeModel | undefined, childIndex, i) => {
|
|
28
|
+
switch (node?.type) {
|
|
29
|
+
// 'text' elements don't have any children
|
|
30
|
+
case 'element':
|
|
31
|
+
case 'component':
|
|
32
|
+
case 'slot':
|
|
33
|
+
// Ancestors are elements before the target node
|
|
34
|
+
if (i <= nodePath.length - 1) {
|
|
35
|
+
ancestors.push({
|
|
36
|
+
...node,
|
|
37
|
+
// Use the original path as origin to get correct nodeIds
|
|
38
|
+
nodeId: path.slice(0, i + 1).join('.'),
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
return component.nodes[node.children[childIndex]]
|
|
42
|
+
default:
|
|
43
|
+
return undefined
|
|
44
|
+
}
|
|
45
|
+
}, root)
|
|
46
|
+
if (node === undefined) {
|
|
47
|
+
return undefined
|
|
48
|
+
}
|
|
49
|
+
return { node: { ...node, nodeId: id }, ancestors }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const isNodeOrAncestorConditional = (
|
|
53
|
+
nodeLookup?: NodeAndAncestorLookup,
|
|
54
|
+
): nodeLookup is NodeAndAncestorLookup =>
|
|
55
|
+
nodeLookup?.node?.condition !== undefined ||
|
|
56
|
+
nodeLookup?.ancestors.some((a) => a.condition !== undefined) === true
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @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.
|
|
60
|
+
*/
|
|
61
|
+
export const getNextSiblingElement = (
|
|
62
|
+
path: string,
|
|
63
|
+
parentElement: Element | ShadowRoot,
|
|
64
|
+
) => {
|
|
65
|
+
const pathParts = path.split('.')
|
|
66
|
+
const lastPathPart = pathParts.slice(-1)[0]
|
|
67
|
+
const index = parseInt(lastPathPart)
|
|
68
|
+
const repeatIndex = parseInt(String(lastPathPart.split('(')[1]))
|
|
69
|
+
|
|
70
|
+
// Find the first child that either has a higher index or a similar index, but higher repeat index
|
|
71
|
+
for (const child of parentElement.children) {
|
|
72
|
+
const childPath = child.getAttribute('data-id')
|
|
73
|
+
const lastChildPathPart = childPath?.split('.').slice(-1)[0]
|
|
74
|
+
const childIndex = parseInt(String(lastChildPathPart))
|
|
75
|
+
if (
|
|
76
|
+
childIndex === index &&
|
|
77
|
+
parseInt(String(lastChildPathPart?.split('(')[1])) > repeatIndex
|
|
78
|
+
) {
|
|
79
|
+
return child
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (childIndex > index) {
|
|
83
|
+
return child
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return null
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* This function efficiently ensures that:
|
|
92
|
+
* 1. New items are added in the correct position.
|
|
93
|
+
* 2. Existing items are not moved if they are already in the correct order.
|
|
94
|
+
*/
|
|
95
|
+
export function ensureEfficientOrdering(
|
|
96
|
+
parentElement: Element | ShadowRoot,
|
|
97
|
+
items: ReadonlyArray<Element | Text>,
|
|
98
|
+
nextElement: Element | Text | null = null,
|
|
99
|
+
) {
|
|
100
|
+
// Identify the starting point for comparisons.
|
|
101
|
+
let insertBeforeElement = nextElement // If insertBeforeElement is null, items will be appended at the end.
|
|
102
|
+
|
|
103
|
+
// To track the current position in the DOM, we'll use a marker that advances through the sibling elements.
|
|
104
|
+
let currentMarker = insertBeforeElement
|
|
105
|
+
? insertBeforeElement.previousSibling
|
|
106
|
+
: parentElement.lastChild
|
|
107
|
+
|
|
108
|
+
// We'll process the items array in reverse order to minimize the number of DOM operations.
|
|
109
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
110
|
+
const item = items[i]
|
|
111
|
+
|
|
112
|
+
// Check if the item is already in the correct position by comparing it with the currentMarker.
|
|
113
|
+
if (item === currentMarker) {
|
|
114
|
+
// The item is in the correct position, move the marker to the previous sibling.
|
|
115
|
+
currentMarker = item.previousSibling
|
|
116
|
+
} else {
|
|
117
|
+
// The item is either not in the DOM or not in the correct position.
|
|
118
|
+
// Insert the item before the insertBeforeElement (or append it if insertBeforeElement is null).
|
|
119
|
+
parentElement.insertBefore(item, insertBeforeElement)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Update insertBeforeElement to the current item for the next iteration, as we need to insert subsequent items before this one.
|
|
123
|
+
insertBeforeElement = item
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Component } from '@nordcraft/core/dist/component/component.types'
|
|
2
|
+
|
|
3
|
+
export function omitSubnodeStyleForComponent<T extends Component | undefined>(
|
|
4
|
+
component: T,
|
|
5
|
+
): T {
|
|
6
|
+
const clone = structuredClone(component)
|
|
7
|
+
Object.entries(clone?.nodes ?? {}).forEach(([nodeId, node]) => {
|
|
8
|
+
if (
|
|
9
|
+
(node.type === 'element' || node.type === 'component') &&
|
|
10
|
+
nodeId !== 'root'
|
|
11
|
+
) {
|
|
12
|
+
delete node.style
|
|
13
|
+
delete node.variants
|
|
14
|
+
delete node.animations
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
return clone
|
|
19
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { isDefined, toBoolean } from '@nordcraft/core/dist/utils/util'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Some attributes need special handling.
|
|
5
|
+
*/
|
|
6
|
+
export function setAttribute(
|
|
7
|
+
elem: HTMLElement | SVGElement | MathMLElement,
|
|
8
|
+
attr: string,
|
|
9
|
+
value: any,
|
|
10
|
+
) {
|
|
11
|
+
switch (attr) {
|
|
12
|
+
case 'srcObject':
|
|
13
|
+
case 'src':
|
|
14
|
+
if (elem instanceof HTMLMediaElement) {
|
|
15
|
+
;(elem as any)[attr] = value
|
|
16
|
+
} else {
|
|
17
|
+
elem.setAttribute(attr, String(value))
|
|
18
|
+
}
|
|
19
|
+
break
|
|
20
|
+
case 'value':
|
|
21
|
+
case 'type': {
|
|
22
|
+
let val = value
|
|
23
|
+
if (elem instanceof HTMLProgressElement) {
|
|
24
|
+
// An HTMLProgressElement will break other elements in our editor if the value is not a (finite) number
|
|
25
|
+
// See docs here https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress#value
|
|
26
|
+
// and original issue here https://discord.com/channels/972416966683926538/1317827591230722048
|
|
27
|
+
if (!isDefined(value) || !Number.isFinite(Number(value))) {
|
|
28
|
+
val = 0
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
;(elem as any)[attr] = toBoolean(val) ? String(val) : undefined
|
|
32
|
+
break
|
|
33
|
+
}
|
|
34
|
+
case 'muted':
|
|
35
|
+
case 'autoplay':
|
|
36
|
+
if (elem instanceof HTMLMediaElement) {
|
|
37
|
+
;(elem as any)[attr] = toBoolean(value)
|
|
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
|
+
) {
|
|
50
|
+
setTimeout(() => elem.focus(), 100)
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
elem.removeAttribute(attr)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
interface DocumentWithViewTransition {
|
|
2
|
+
startViewTransition?: (callback: () => void) => {
|
|
3
|
+
finished: Promise<void>
|
|
4
|
+
ready: Promise<void>
|
|
5
|
+
updateCallbackDone: Promise<void>
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function tryStartViewTransition(
|
|
10
|
+
updateCallback: () => void,
|
|
11
|
+
options?: {
|
|
12
|
+
skipPrefersReducedMotionCheck?: boolean
|
|
13
|
+
},
|
|
14
|
+
): {
|
|
15
|
+
finished: Promise<void>
|
|
16
|
+
} {
|
|
17
|
+
const startViewTransition = (document as DocumentWithViewTransition)
|
|
18
|
+
.startViewTransition
|
|
19
|
+
|
|
20
|
+
if (
|
|
21
|
+
!startViewTransition ||
|
|
22
|
+
(options?.skipPrefersReducedMotionCheck !== true &&
|
|
23
|
+
window.matchMedia('(prefers-reduced-motion: reduce)').matches)
|
|
24
|
+
) {
|
|
25
|
+
updateCallback()
|
|
26
|
+
return {
|
|
27
|
+
finished: Promise.resolve(),
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return startViewTransition.call(document, updateCallback)
|
|
32
|
+
}
|
package/src/utils/url.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { isDefined } from '@nordcraft/core/dist/utils/util'
|
|
2
|
+
import { compile } from 'path-to-regexp'
|
|
3
|
+
import type { Location } from '../types'
|
|
4
|
+
|
|
5
|
+
export const getLocationUrl = ({
|
|
6
|
+
query,
|
|
7
|
+
page,
|
|
8
|
+
route,
|
|
9
|
+
params,
|
|
10
|
+
hash,
|
|
11
|
+
}: Location) => {
|
|
12
|
+
let path: string
|
|
13
|
+
if (route) {
|
|
14
|
+
const pathSegments: string[] = []
|
|
15
|
+
for (const segment of route.path) {
|
|
16
|
+
if (segment.type === 'static') {
|
|
17
|
+
pathSegments.push(segment.name)
|
|
18
|
+
} else {
|
|
19
|
+
const segmentValue = params[segment.name]
|
|
20
|
+
if (isDefined(segmentValue)) {
|
|
21
|
+
pathSegments.push(segmentValue)
|
|
22
|
+
} else {
|
|
23
|
+
// If a param is missing, we can't build the rest of the path
|
|
24
|
+
break
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
path = '/' + pathSegments.join('/')
|
|
29
|
+
} else {
|
|
30
|
+
path = compile(page as string, { encode: encodeURIComponent })(params)
|
|
31
|
+
}
|
|
32
|
+
const hashString = hash === undefined || hash === '' ? '' : '#' + hash
|
|
33
|
+
const queryString = Object.entries(query)
|
|
34
|
+
.filter(([_, q]) => q !== null)
|
|
35
|
+
.map(([key, value]) => {
|
|
36
|
+
return `${encodeURIComponent(
|
|
37
|
+
route?.query[key]?.name ?? key,
|
|
38
|
+
)}=${encodeURIComponent(String(value))}`
|
|
39
|
+
})
|
|
40
|
+
.join('&')
|
|
41
|
+
|
|
42
|
+
return `${path}${hashString}${
|
|
43
|
+
queryString.length > 0 ? '?' + queryString : ''
|
|
44
|
+
}`
|
|
45
|
+
}
|