@nordcraft/runtime 1.0.58 → 1.0.59
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/dist/components/createElement.js +1 -1
- package/dist/components/createElement.js.map +1 -1
- package/dist/components/createNode.js.map +1 -1
- package/dist/custom-element.main.esm.js +19 -19
- package/dist/custom-element.main.esm.js.map +3 -3
- package/dist/editor/input.d.ts +1 -0
- package/dist/editor/input.js +16 -0
- package/dist/editor/input.js.map +1 -0
- package/dist/editor/links.d.ts +6 -0
- package/dist/editor/links.js +15 -0
- package/dist/editor/links.js.map +1 -0
- package/dist/editor/overlay.d.ts +12 -0
- package/dist/editor/overlay.js +20 -0
- package/dist/editor/overlay.js.map +1 -0
- package/dist/editor/types.d.ts +254 -0
- package/dist/editor/types.js +42 -0
- package/dist/editor/types.js.map +1 -0
- package/dist/editor-preview.main.js +137 -203
- package/dist/editor-preview.main.js.map +1 -1
- package/dist/page.main.esm.js +2 -2
- package/dist/page.main.esm.js.map +3 -3
- package/dist/styles/CustomPropertyStyleSheet.test.js +12 -3
- package/dist/styles/CustomPropertyStyleSheet.test.js.map +1 -1
- package/package.json +4 -4
- package/src/components/createElement.ts +1 -1
- package/src/components/createNode.ts +0 -1
- package/src/editor/input.ts +17 -0
- package/src/editor/links.ts +16 -0
- package/src/editor/overlay.ts +21 -0
- package/src/editor/types.ts +271 -0
- package/src/editor-preview.main.ts +153 -400
- package/src/styles/CustomPropertyStyleSheet.test.ts +12 -3
- package/src/editor/types.d.ts +0 -36
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
/* eslint-disable no-case-declarations */
|
|
4
4
|
/* eslint-disable no-fallthrough */
|
|
5
5
|
import { isLegacyApi } from '@nordcraft/core/dist/api/api'
|
|
6
|
+
import { isLegacyPluginAction } from '@nordcraft/core/dist/component/actionUtils'
|
|
6
7
|
import {
|
|
7
8
|
HeadTagTypes,
|
|
8
|
-
type AnimationKeyframe,
|
|
9
9
|
type Component,
|
|
10
10
|
type ComponentData,
|
|
11
11
|
type MetaEntry,
|
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
type PluginFormula,
|
|
25
25
|
type ToddleFormula,
|
|
26
26
|
} from '@nordcraft/core/dist/formula/formulaTypes'
|
|
27
|
-
import { valueFormula } from '@nordcraft/core/dist/formula/formulaUtils'
|
|
28
27
|
import { getClassName } from '@nordcraft/core/dist/styling/className'
|
|
29
28
|
import { appendUnit } from '@nordcraft/core/dist/styling/customProperty'
|
|
30
29
|
import type { OldTheme, Theme } from '@nordcraft/core/dist/styling/theme'
|
|
@@ -57,7 +56,15 @@ import { dragMove } from './editor/drag-drop/dragMove'
|
|
|
57
56
|
import { dragReorder } from './editor/drag-drop/dragReorder'
|
|
58
57
|
import { dragStarted } from './editor/drag-drop/dragStarted'
|
|
59
58
|
import { introspectApiRequest } from './editor/graphql'
|
|
60
|
-
import
|
|
59
|
+
import { isInputTarget } from './editor/input'
|
|
60
|
+
import { updateComponentLinks } from './editor/links'
|
|
61
|
+
import { getRectData } from './editor/overlay'
|
|
62
|
+
import {
|
|
63
|
+
TextNodeComputedStyles,
|
|
64
|
+
type DragState,
|
|
65
|
+
type EditorPostMessageType,
|
|
66
|
+
type NordcraftPreviewEvent,
|
|
67
|
+
} from './editor/types'
|
|
61
68
|
import { handleAction } from './events/handleAction'
|
|
62
69
|
import type { Signal } from './signal/signal'
|
|
63
70
|
import { signal } from './signal/signal'
|
|
@@ -77,143 +84,6 @@ import {
|
|
|
77
84
|
storeScrollState,
|
|
78
85
|
} from './utils/storeScrollState'
|
|
79
86
|
|
|
80
|
-
type ToddlePreviewEvent =
|
|
81
|
-
| {
|
|
82
|
-
type: 'style_variant_changed'
|
|
83
|
-
variantIndex: number | null
|
|
84
|
-
}
|
|
85
|
-
| {
|
|
86
|
-
type: 'component'
|
|
87
|
-
component: Component
|
|
88
|
-
}
|
|
89
|
-
| { type: 'components'; components: Component[] }
|
|
90
|
-
| {
|
|
91
|
-
type: 'packages'
|
|
92
|
-
packages: Record<
|
|
93
|
-
string,
|
|
94
|
-
{
|
|
95
|
-
components: Record<string, Component>
|
|
96
|
-
formulas: Record<
|
|
97
|
-
string,
|
|
98
|
-
PluginFormula<FormulaHandlerV2> | PluginFormula<string>
|
|
99
|
-
>
|
|
100
|
-
actions: Record<string, PluginActionV2 | PluginAction>
|
|
101
|
-
manifest: {
|
|
102
|
-
name: string
|
|
103
|
-
// commit represents the commit hash (version) of the package
|
|
104
|
-
commit: string
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
>
|
|
108
|
-
}
|
|
109
|
-
| {
|
|
110
|
-
type: 'global_formulas'
|
|
111
|
-
formulas: Record<
|
|
112
|
-
string,
|
|
113
|
-
PluginFormula<FormulaHandlerV2> | PluginFormula<string>
|
|
114
|
-
>
|
|
115
|
-
}
|
|
116
|
-
| {
|
|
117
|
-
type: 'global_actions'
|
|
118
|
-
actions: Record<string, PluginActionV2 | PluginAction>
|
|
119
|
-
}
|
|
120
|
-
| { type: 'theme'; theme: Record<string, OldTheme | Theme> }
|
|
121
|
-
| { type: 'mode'; mode: 'design' | 'test' }
|
|
122
|
-
| { type: 'attrs'; attrs: Record<string, unknown> }
|
|
123
|
-
| { type: 'selection'; selectedNodeId: string | null }
|
|
124
|
-
| { type: 'highlight'; highlightedNodeId: string | null }
|
|
125
|
-
| {
|
|
126
|
-
type: 'click' | 'mousemove' | 'dblclick'
|
|
127
|
-
metaKey: boolean
|
|
128
|
-
x: number
|
|
129
|
-
y: number
|
|
130
|
-
}
|
|
131
|
-
| { type: 'report_document_scroll_size' }
|
|
132
|
-
| { type: 'update_inner_text'; innerText: string }
|
|
133
|
-
| { type: 'reload' }
|
|
134
|
-
| { type: 'fetch_api'; apiKey: string }
|
|
135
|
-
| { type: 'introspect_qraphql_api'; apiKey: string }
|
|
136
|
-
| { type: 'drag-started'; x: number; y: number }
|
|
137
|
-
| { type: 'drag-ended'; canceled?: true }
|
|
138
|
-
| { type: 'keydown'; key: string; altKey: boolean; metaKey: boolean }
|
|
139
|
-
| { type: 'keyup'; key: string; altKey: boolean; metaKey: boolean }
|
|
140
|
-
| {
|
|
141
|
-
type: 'get_computed_style'
|
|
142
|
-
styles?: string[]
|
|
143
|
-
}
|
|
144
|
-
| {
|
|
145
|
-
type: 'set_timeline_keyframes'
|
|
146
|
-
keyframes: Record<string, AnimationKeyframe> | null
|
|
147
|
-
}
|
|
148
|
-
| {
|
|
149
|
-
type: 'set_timeline_time'
|
|
150
|
-
time: number | null
|
|
151
|
-
timingFunction:
|
|
152
|
-
| 'linear'
|
|
153
|
-
| 'ease'
|
|
154
|
-
| 'ease-in'
|
|
155
|
-
| 'ease-out'
|
|
156
|
-
| 'ease-in-out'
|
|
157
|
-
| 'step-start'
|
|
158
|
-
| 'step-end'
|
|
159
|
-
| string
|
|
160
|
-
| undefined
|
|
161
|
-
fillMode: 'none' | 'forwards' | 'backwards' | 'both' | undefined
|
|
162
|
-
}
|
|
163
|
-
| {
|
|
164
|
-
type: 'preview_style'
|
|
165
|
-
styles: Record<string, string> | null
|
|
166
|
-
theme?: {
|
|
167
|
-
key: string
|
|
168
|
-
value: Theme
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
| {
|
|
172
|
-
type: 'preview_theme'
|
|
173
|
-
theme: string | null
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Styles required for rendering the same exact text again somewhere else (on a overlay rect in the editor)
|
|
178
|
-
*/
|
|
179
|
-
enum TextNodeComputedStyles {
|
|
180
|
-
// Caret color is important as it is the only visible part of the text node (when text is not highlighted)
|
|
181
|
-
CARET_COLOR = 'caret-color',
|
|
182
|
-
DISPLAY = 'display',
|
|
183
|
-
FONT_FAMILY = 'font-family',
|
|
184
|
-
FONT_SIZE = 'font-size',
|
|
185
|
-
FONT_WEIGHT = 'font-weight',
|
|
186
|
-
FONT_STYLE = 'font-style',
|
|
187
|
-
FONT_VARIANT = 'font-variant',
|
|
188
|
-
FONT_STRETCH = 'font-stretch',
|
|
189
|
-
LINE_HEIGHT = 'line-height',
|
|
190
|
-
TEXT_ALIGN = 'text-align',
|
|
191
|
-
TEXT_TRANSFORM = 'text-transform',
|
|
192
|
-
LETTER_SPACING = 'letter-spacing',
|
|
193
|
-
WHITE_SPACE = 'white-space',
|
|
194
|
-
WORD_SPACING = 'word-spacing',
|
|
195
|
-
TEXT_INDENT = 'text-indent',
|
|
196
|
-
TEXT_OVERFLOW = 'text-overflow',
|
|
197
|
-
TEXT_RENDERING = 'text-rendering',
|
|
198
|
-
WORD_BREAK = 'word-break',
|
|
199
|
-
WORD_WRAP = 'word-wrap',
|
|
200
|
-
DIRECTION = 'direction',
|
|
201
|
-
UNICODE_BIDI = 'unicode-bidi',
|
|
202
|
-
VERTICAL_ALIGN = 'vertical-align',
|
|
203
|
-
FONT_KERNING = 'font-kerning',
|
|
204
|
-
FONT_FEATURE_SETTINGS = 'font-feature-settings',
|
|
205
|
-
FONT_VARIATION_SETTINGS = 'font-variation-settings',
|
|
206
|
-
FONT_SMOOTHING = '-webkit-font-smoothing',
|
|
207
|
-
ANTI_ALIASING = '-moz-osx-font-smoothing',
|
|
208
|
-
FONT_OPTICAL_SIZING = 'font-optical-sizing',
|
|
209
|
-
TAB_SIZE = 'tab-size',
|
|
210
|
-
HYPHENS = 'hyphens',
|
|
211
|
-
TEXT_ORIENTATION = 'text-orientation',
|
|
212
|
-
WRITING_MODE = 'writing-mode',
|
|
213
|
-
LINE_BREAK = 'line-break',
|
|
214
|
-
OVERFLOW_WRAP = 'overflow-wrap',
|
|
215
|
-
}
|
|
216
|
-
|
|
217
87
|
let env: ToddleEnv
|
|
218
88
|
|
|
219
89
|
export const initGlobalObject = () => {
|
|
@@ -312,6 +182,18 @@ export const initGlobalObject = () => {
|
|
|
312
182
|
)
|
|
313
183
|
}
|
|
314
184
|
|
|
185
|
+
const EMPTY_COMPONENT_DATA: ComponentData = {
|
|
186
|
+
Location: {
|
|
187
|
+
query: {},
|
|
188
|
+
params: {},
|
|
189
|
+
page: '/',
|
|
190
|
+
path: '/',
|
|
191
|
+
hash: '',
|
|
192
|
+
},
|
|
193
|
+
Attributes: {},
|
|
194
|
+
Variables: {},
|
|
195
|
+
}
|
|
196
|
+
|
|
315
197
|
// imported by "/.toddle/preview" (see worker/src/preview.ts)
|
|
316
198
|
export const createRoot = (
|
|
317
199
|
domNode: HTMLElement | null = document.getElementById('App'),
|
|
@@ -319,35 +201,8 @@ export const createRoot = (
|
|
|
319
201
|
if (!domNode) {
|
|
320
202
|
throw new Error('Cant find root domNode')
|
|
321
203
|
}
|
|
322
|
-
const isInputTarget = (event: Event) => {
|
|
323
|
-
const target = event.target
|
|
324
|
-
if (target instanceof HTMLElement) {
|
|
325
|
-
if (
|
|
326
|
-
target.tagName === 'INPUT' ||
|
|
327
|
-
target.tagName === 'TEXTAREA' ||
|
|
328
|
-
target.tagName === 'SELECT' ||
|
|
329
|
-
target.tagName === 'STYLE-EDITOR'
|
|
330
|
-
) {
|
|
331
|
-
return true
|
|
332
|
-
}
|
|
333
|
-
if (target.contentEditable?.toLocaleLowerCase() === 'true') {
|
|
334
|
-
return true
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
return false
|
|
338
|
-
}
|
|
339
204
|
|
|
340
|
-
const dataSignal = signal
|
|
341
|
-
Location: {
|
|
342
|
-
query: {},
|
|
343
|
-
params: {},
|
|
344
|
-
page: '/',
|
|
345
|
-
path: '/',
|
|
346
|
-
hash: '',
|
|
347
|
-
},
|
|
348
|
-
Attributes: {},
|
|
349
|
-
Variables: {},
|
|
350
|
-
})
|
|
205
|
+
const dataSignal = signal(EMPTY_COMPONENT_DATA)
|
|
351
206
|
let ctxDataSignal: Signal<ComponentData> | undefined
|
|
352
207
|
|
|
353
208
|
let ctx: ComponentContext | null = null
|
|
@@ -387,87 +242,26 @@ export const createRoot = (
|
|
|
387
242
|
let previewStyleAnimationFrame = -1
|
|
388
243
|
let timelineTimeAnimationFrame = -1
|
|
389
244
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
return component
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
const registerActions = (
|
|
405
|
-
allActions: Record<string, PluginActionV2 | PluginAction>,
|
|
406
|
-
packageName?: string,
|
|
407
|
-
) => {
|
|
408
|
-
const actions: Record<string, PluginActionV2> = {}
|
|
409
|
-
Object.entries(allActions ?? {}).forEach(([name, action]) => {
|
|
410
|
-
if (typeof action.name === 'string' && action.version === undefined) {
|
|
411
|
-
// Legacy actions are self-registering. We need to execute them to register them
|
|
412
|
-
Function(action.handler)()
|
|
413
|
-
return
|
|
414
|
-
}
|
|
415
|
-
// We need to convert the handler string into a real function
|
|
416
|
-
actions[name] = {
|
|
417
|
-
...(action as PluginActionV2),
|
|
418
|
-
handler:
|
|
419
|
-
typeof action.handler === 'string'
|
|
420
|
-
? (new Function(
|
|
421
|
-
'args, ctx',
|
|
422
|
-
`${action.handler}
|
|
423
|
-
return ${safeFunctionName(action.name)}(args, ctx)`,
|
|
424
|
-
) as ActionHandlerV2)
|
|
425
|
-
: action.handler,
|
|
426
|
-
}
|
|
427
|
-
})
|
|
428
|
-
window.toddle.actions[packageName ?? window.__toddle.project] = actions
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
const registerFormulas = (
|
|
432
|
-
allFormulas: Record<
|
|
433
|
-
string,
|
|
434
|
-
ToddleFormula | CodeFormula<FormulaHandlerV2> | CodeFormula<string>
|
|
435
|
-
>,
|
|
436
|
-
packageName?: string,
|
|
437
|
-
) => {
|
|
438
|
-
const formulas: Record<string, PluginFormula<FormulaHandlerV2>> = {}
|
|
439
|
-
Object.entries(allFormulas ?? {}).forEach(([name, formula]) => {
|
|
440
|
-
if (
|
|
441
|
-
!isToddleFormula<FormulaHandlerV2 | string>(formula) &&
|
|
442
|
-
typeof formula.name === 'string' &&
|
|
443
|
-
formula.version === undefined
|
|
444
|
-
) {
|
|
445
|
-
// Legacy formulas are self-registering. We need to execute them to register them
|
|
446
|
-
Function(formula.handler as unknown as string)()
|
|
447
|
-
return
|
|
448
|
-
} else if (!isToddleFormula<FormulaHandlerV2 | string>(formula)) {
|
|
449
|
-
// For code formulas we need to convert the handler string into a real function
|
|
450
|
-
formulas[name] = {
|
|
451
|
-
...formula,
|
|
452
|
-
handler:
|
|
453
|
-
typeof formula.handler === 'string'
|
|
454
|
-
? (new Function(
|
|
455
|
-
'args, ctx',
|
|
456
|
-
`${formula.handler}
|
|
457
|
-
return ${safeFunctionName(formula.name)}(args, ctx)`,
|
|
458
|
-
) as FormulaHandlerV2)
|
|
459
|
-
: formula.handler,
|
|
245
|
+
const setupDataSignalSubscribers = () => {
|
|
246
|
+
dataSignal.subscribe((data) => {
|
|
247
|
+
if (component && components && packageComponents && data) {
|
|
248
|
+
try {
|
|
249
|
+
postMessageToEditor({ type: 'data', data })
|
|
250
|
+
} catch {
|
|
251
|
+
// If we're unable to send the data, let's try to JSON serialize it
|
|
252
|
+
postMessageToEditor({
|
|
253
|
+
type: 'data',
|
|
254
|
+
data: JSON.parse(JSON.stringify(data)),
|
|
255
|
+
})
|
|
460
256
|
}
|
|
461
|
-
return
|
|
462
257
|
}
|
|
463
|
-
formulas[name] = formula as PluginFormula<FormulaHandlerV2>
|
|
464
258
|
})
|
|
465
|
-
window.toddle.formulas[packageName ?? window.__toddle.project] = formulas
|
|
466
259
|
}
|
|
260
|
+
setupDataSignalSubscribers()
|
|
467
261
|
|
|
468
262
|
window.addEventListener(
|
|
469
263
|
'message',
|
|
470
|
-
async (message: MessageEvent<
|
|
264
|
+
async (message: MessageEvent<NordcraftPreviewEvent>) => {
|
|
471
265
|
if (!message.isTrusted) {
|
|
472
266
|
console.error('UNTRUSTED MESSAGE')
|
|
473
267
|
}
|
|
@@ -481,11 +275,22 @@ export const createRoot = (
|
|
|
481
275
|
| undefined
|
|
482
276
|
|
|
483
277
|
if (message.data.component.name !== component?.name) {
|
|
278
|
+
// Store scroll state for the previous component
|
|
484
279
|
storeScrollState(component?.name)
|
|
280
|
+
// Remove all subscribers from the previous showSignal
|
|
485
281
|
showSignal.cleanSubscribers()
|
|
282
|
+
// Clear any previously overridden conditional elements
|
|
283
|
+
showSignal.set({ displayedNodes: [], testMode: mode === 'test' })
|
|
284
|
+
// Restore scroll state for the new component
|
|
486
285
|
scrollStateRestorer = getScrollStateRestorer(
|
|
487
286
|
message.data.component.name,
|
|
488
287
|
)
|
|
288
|
+
// Destroy the dataSignal (including subscribers) for the previous component
|
|
289
|
+
dataSignal.destroy()
|
|
290
|
+
// Re-subscribe all dataSignal subscribers
|
|
291
|
+
setupDataSignalSubscribers()
|
|
292
|
+
// Re-initialize the data signal for the new component
|
|
293
|
+
ctxDataSignal?.destroy()
|
|
489
294
|
}
|
|
490
295
|
|
|
491
296
|
component = updateComponentLinks(message.data.component)
|
|
@@ -1758,68 +1563,7 @@ export const createRoot = (
|
|
|
1758
1563
|
return ctx
|
|
1759
1564
|
}
|
|
1760
1565
|
|
|
1761
|
-
|
|
1762
|
-
if (isInputTarget(event)) {
|
|
1763
|
-
return
|
|
1764
|
-
}
|
|
1765
|
-
switch (event.key) {
|
|
1766
|
-
case 'k':
|
|
1767
|
-
if (event.metaKey) {
|
|
1768
|
-
event.preventDefault()
|
|
1769
|
-
}
|
|
1770
|
-
}
|
|
1771
|
-
postMessageToEditor({
|
|
1772
|
-
type: 'keydown',
|
|
1773
|
-
event: {
|
|
1774
|
-
key: event.key,
|
|
1775
|
-
metaKey: event.metaKey,
|
|
1776
|
-
shiftKey: event.shiftKey,
|
|
1777
|
-
altKey: event.altKey,
|
|
1778
|
-
},
|
|
1779
|
-
})
|
|
1780
|
-
})
|
|
1781
|
-
document.addEventListener('keyup', (event) => {
|
|
1782
|
-
if (isInputTarget(event)) {
|
|
1783
|
-
return
|
|
1784
|
-
}
|
|
1785
|
-
postMessageToEditor({
|
|
1786
|
-
type: 'keyup',
|
|
1787
|
-
event: {
|
|
1788
|
-
key: event.key,
|
|
1789
|
-
metaKey: event.metaKey,
|
|
1790
|
-
shiftKey: event.shiftKey,
|
|
1791
|
-
altKey: event.altKey,
|
|
1792
|
-
},
|
|
1793
|
-
})
|
|
1794
|
-
})
|
|
1795
|
-
document.addEventListener('keypress', (event) => {
|
|
1796
|
-
if (isInputTarget(event)) {
|
|
1797
|
-
return
|
|
1798
|
-
}
|
|
1799
|
-
postMessageToEditor({
|
|
1800
|
-
type: 'keypress',
|
|
1801
|
-
event: {
|
|
1802
|
-
key: event.key,
|
|
1803
|
-
metaKey: event.metaKey,
|
|
1804
|
-
shiftKey: event.shiftKey,
|
|
1805
|
-
altKey: event.altKey,
|
|
1806
|
-
},
|
|
1807
|
-
})
|
|
1808
|
-
})
|
|
1809
|
-
|
|
1810
|
-
dataSignal.subscribe((data) => {
|
|
1811
|
-
if (component && components && packageComponents && data) {
|
|
1812
|
-
try {
|
|
1813
|
-
postMessageToEditor({ type: 'data', data })
|
|
1814
|
-
} catch {
|
|
1815
|
-
// If we're unable to send the data, let's try to JSON serialize it
|
|
1816
|
-
postMessageToEditor({
|
|
1817
|
-
type: 'data',
|
|
1818
|
-
data: JSON.parse(JSON.stringify(data)),
|
|
1819
|
-
})
|
|
1820
|
-
}
|
|
1821
|
-
}
|
|
1822
|
-
})
|
|
1566
|
+
initKeyListeners()
|
|
1823
1567
|
|
|
1824
1568
|
const clearSelectedStyleVariant = () => {
|
|
1825
1569
|
if (styleVariantSelection) {
|
|
@@ -1880,28 +1624,6 @@ export const createRoot = (
|
|
|
1880
1624
|
})()
|
|
1881
1625
|
}
|
|
1882
1626
|
|
|
1883
|
-
function getRectData(selectedNode: Element | null | undefined) {
|
|
1884
|
-
if (!selectedNode) {
|
|
1885
|
-
return null
|
|
1886
|
-
}
|
|
1887
|
-
|
|
1888
|
-
const { borderRadius, rotate } = window.getComputedStyle(selectedNode)
|
|
1889
|
-
const rect: DOMRect = selectedNode.getBoundingClientRect()
|
|
1890
|
-
|
|
1891
|
-
return {
|
|
1892
|
-
left: rect.left,
|
|
1893
|
-
right: rect.right,
|
|
1894
|
-
top: rect.top,
|
|
1895
|
-
bottom: rect.bottom,
|
|
1896
|
-
width: rect.width,
|
|
1897
|
-
height: rect.height,
|
|
1898
|
-
x: rect.x,
|
|
1899
|
-
y: rect.y,
|
|
1900
|
-
borderRadius: borderRadius.split(' '),
|
|
1901
|
-
rotate,
|
|
1902
|
-
}
|
|
1903
|
-
}
|
|
1904
|
-
|
|
1905
1627
|
const insertOrReplaceHeadNode = (id: string, node: Node) => {
|
|
1906
1628
|
const existing = document.head.querySelector(`[data-meta-id="${id}"]`)
|
|
1907
1629
|
if (existing) {
|
|
@@ -2004,90 +1726,121 @@ const insertTheme = (
|
|
|
2004
1726
|
parent.appendChild(styleElem)
|
|
2005
1727
|
}
|
|
2006
1728
|
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
}
|
|
2012
|
-
| {
|
|
2013
|
-
type: 'selection'
|
|
2014
|
-
selectedNodeId: string | null
|
|
2015
|
-
}
|
|
2016
|
-
| {
|
|
2017
|
-
type: 'highlight'
|
|
2018
|
-
highlightedNodeId: string | null
|
|
2019
|
-
}
|
|
2020
|
-
| {
|
|
2021
|
-
type: 'navigate'
|
|
2022
|
-
name: string
|
|
2023
|
-
}
|
|
2024
|
-
| {
|
|
2025
|
-
type: 'documentScrollSize'
|
|
2026
|
-
scrollHeight: number
|
|
2027
|
-
scrollWidth: number
|
|
2028
|
-
}
|
|
2029
|
-
| {
|
|
2030
|
-
type: 'nodeMoved'
|
|
2031
|
-
copy: boolean
|
|
2032
|
-
parent?: string | null
|
|
2033
|
-
index?: number
|
|
2034
|
-
}
|
|
2035
|
-
| {
|
|
2036
|
-
type: 'computedStyle'
|
|
2037
|
-
computedStyle: Record<string, string>
|
|
2038
|
-
}
|
|
2039
|
-
| {
|
|
2040
|
-
type: 'style'
|
|
2041
|
-
time: string
|
|
1729
|
+
const initKeyListeners = () => {
|
|
1730
|
+
document.addEventListener('keydown', (event) => {
|
|
1731
|
+
if (isInputTarget(event)) {
|
|
1732
|
+
return
|
|
2042
1733
|
}
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
1734
|
+
switch (event.key) {
|
|
1735
|
+
case 'k':
|
|
1736
|
+
if (event.metaKey) {
|
|
1737
|
+
event.preventDefault()
|
|
1738
|
+
}
|
|
2048
1739
|
}
|
|
2049
|
-
|
|
2050
|
-
type: 'keydown'
|
|
1740
|
+
postMessageToEditor({
|
|
1741
|
+
type: 'keydown',
|
|
2051
1742
|
event: {
|
|
2052
|
-
key:
|
|
2053
|
-
metaKey:
|
|
2054
|
-
shiftKey:
|
|
2055
|
-
altKey:
|
|
2056
|
-
}
|
|
1743
|
+
key: event.key,
|
|
1744
|
+
metaKey: event.metaKey,
|
|
1745
|
+
shiftKey: event.shiftKey,
|
|
1746
|
+
altKey: event.altKey,
|
|
1747
|
+
},
|
|
1748
|
+
})
|
|
1749
|
+
})
|
|
1750
|
+
document.addEventListener('keyup', (event) => {
|
|
1751
|
+
if (isInputTarget(event)) {
|
|
1752
|
+
return
|
|
2057
1753
|
}
|
|
2058
|
-
|
|
2059
|
-
type: 'keyup'
|
|
1754
|
+
postMessageToEditor({
|
|
1755
|
+
type: 'keyup',
|
|
2060
1756
|
event: {
|
|
2061
|
-
key:
|
|
2062
|
-
metaKey:
|
|
2063
|
-
shiftKey:
|
|
2064
|
-
altKey:
|
|
2065
|
-
}
|
|
1757
|
+
key: event.key,
|
|
1758
|
+
metaKey: event.metaKey,
|
|
1759
|
+
shiftKey: event.shiftKey,
|
|
1760
|
+
altKey: event.altKey,
|
|
1761
|
+
},
|
|
1762
|
+
})
|
|
1763
|
+
})
|
|
1764
|
+
document.addEventListener('keypress', (event) => {
|
|
1765
|
+
if (isInputTarget(event)) {
|
|
1766
|
+
return
|
|
2066
1767
|
}
|
|
2067
|
-
|
|
2068
|
-
type: 'keypress'
|
|
1768
|
+
postMessageToEditor({
|
|
1769
|
+
type: 'keypress',
|
|
2069
1770
|
event: {
|
|
2070
|
-
key:
|
|
2071
|
-
metaKey:
|
|
2072
|
-
shiftKey:
|
|
2073
|
-
altKey:
|
|
2074
|
-
}
|
|
2075
|
-
}
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
1771
|
+
key: event.key,
|
|
1772
|
+
metaKey: event.metaKey,
|
|
1773
|
+
shiftKey: event.shiftKey,
|
|
1774
|
+
altKey: event.altKey,
|
|
1775
|
+
},
|
|
1776
|
+
})
|
|
1777
|
+
})
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
const registerActions = (
|
|
1781
|
+
allActions: Record<string, PluginAction>,
|
|
1782
|
+
packageName?: string,
|
|
1783
|
+
) => {
|
|
1784
|
+
const actions: Record<string, PluginActionV2> = {}
|
|
1785
|
+
Object.entries(allActions ?? {}).forEach(([name, action]) => {
|
|
1786
|
+
if (isLegacyPluginAction(action)) {
|
|
1787
|
+
// Legacy actions are self-registering. We need to execute them to register them
|
|
1788
|
+
Function(action.handler)()
|
|
1789
|
+
return
|
|
2080
1790
|
}
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
1791
|
+
// We need to convert the handler string into a real function
|
|
1792
|
+
actions[name] = {
|
|
1793
|
+
...(action as PluginActionV2),
|
|
1794
|
+
handler:
|
|
1795
|
+
typeof action.handler === 'string'
|
|
1796
|
+
? (new Function(
|
|
1797
|
+
'args, ctx',
|
|
1798
|
+
`${action.handler}
|
|
1799
|
+
return ${safeFunctionName(action.name)}(args, ctx)`,
|
|
1800
|
+
) as ActionHandlerV2)
|
|
1801
|
+
: action.handler,
|
|
2084
1802
|
}
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
1803
|
+
})
|
|
1804
|
+
window.toddle.actions[packageName ?? window.__toddle.project] = actions
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
const registerFormulas = (
|
|
1808
|
+
allFormulas: Record<
|
|
1809
|
+
string,
|
|
1810
|
+
ToddleFormula | CodeFormula<FormulaHandlerV2> | CodeFormula<string>
|
|
1811
|
+
>,
|
|
1812
|
+
packageName?: string,
|
|
1813
|
+
) => {
|
|
1814
|
+
const formulas: Record<string, PluginFormula<FormulaHandlerV2>> = {}
|
|
1815
|
+
Object.entries(allFormulas ?? {}).forEach(([name, formula]) => {
|
|
1816
|
+
if (
|
|
1817
|
+
!isToddleFormula<FormulaHandlerV2 | string>(formula) &&
|
|
1818
|
+
typeof formula.name === 'string' &&
|
|
1819
|
+
formula.version === undefined
|
|
1820
|
+
) {
|
|
1821
|
+
// Legacy formulas are self-registering. We need to execute them to register them
|
|
1822
|
+
Function(formula.handler as unknown as string)()
|
|
1823
|
+
return
|
|
1824
|
+
} else if (!isToddleFormula<FormulaHandlerV2 | string>(formula)) {
|
|
1825
|
+
// For code formulas we need to convert the handler string into a real function
|
|
1826
|
+
formulas[name] = {
|
|
1827
|
+
...formula,
|
|
1828
|
+
handler:
|
|
1829
|
+
typeof formula.handler === 'string'
|
|
1830
|
+
? (new Function(
|
|
1831
|
+
'args, ctx',
|
|
1832
|
+
`${formula.handler}
|
|
1833
|
+
return ${safeFunctionName(formula.name)}(args, ctx)`,
|
|
1834
|
+
) as FormulaHandlerV2)
|
|
1835
|
+
: formula.handler,
|
|
1836
|
+
}
|
|
1837
|
+
return
|
|
2089
1838
|
}
|
|
1839
|
+
formulas[name] = formula as PluginFormula<FormulaHandlerV2>
|
|
1840
|
+
})
|
|
1841
|
+
window.toddle.formulas[packageName ?? window.__toddle.project] = formulas
|
|
1842
|
+
}
|
|
2090
1843
|
|
|
2091
|
-
const postMessageToEditor = (message:
|
|
1844
|
+
const postMessageToEditor = (message: EditorPostMessageType) => {
|
|
2092
1845
|
window.parent?.postMessage(message, '*')
|
|
2093
1846
|
}
|
|
@@ -50,7 +50,10 @@ describe('CustomPropertyStyleSheet', () => {
|
|
|
50
50
|
})('256px')
|
|
51
51
|
expect(instance.getStyleSheet().cssRules.length).toBe(1)
|
|
52
52
|
expect(instance.getStyleSheet().cssRules[0].cssText).toBe(
|
|
53
|
-
|
|
53
|
+
`\
|
|
54
|
+
@media (max-width: 600px) {
|
|
55
|
+
.my-class { --my-property: 256px; }
|
|
56
|
+
}`,
|
|
54
57
|
)
|
|
55
58
|
})
|
|
56
59
|
|
|
@@ -87,7 +90,10 @@ describe('CustomPropertyStyleSheet', () => {
|
|
|
87
90
|
setter('256px')
|
|
88
91
|
expect(instance.getStyleSheet().cssRules.length).toBe(1)
|
|
89
92
|
expect(instance.getStyleSheet().cssRules[0].cssText).toBe(
|
|
90
|
-
|
|
93
|
+
`\
|
|
94
|
+
@media (max-width: 600px) {
|
|
95
|
+
.my-class-with-media { --my-property-with-media: 256px; }
|
|
96
|
+
}`,
|
|
91
97
|
)
|
|
92
98
|
|
|
93
99
|
instance.unregisterProperty(
|
|
@@ -98,7 +104,10 @@ describe('CustomPropertyStyleSheet', () => {
|
|
|
98
104
|
},
|
|
99
105
|
)
|
|
100
106
|
expect(instance.getStyleSheet().cssRules[0].cssText).toBe(
|
|
101
|
-
|
|
107
|
+
`\
|
|
108
|
+
@media (max-width: 600px) {
|
|
109
|
+
.my-class-with-media { }
|
|
110
|
+
}`,
|
|
102
111
|
)
|
|
103
112
|
})
|
|
104
113
|
})
|