@teleporthq/teleport-plugin-next-workflows 0.45.9 → 0.45.13
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/__tests__/component-scope-interval.test.ts +120 -0
- package/__tests__/element-trigger-context-fields.test.ts +279 -0
- package/__tests__/interval-control-event.test.ts +217 -0
- package/dist/cjs/trigger-generator.d.ts +2 -0
- package/dist/cjs/trigger-generator.d.ts.map +1 -1
- package/dist/cjs/trigger-generator.js +32 -9
- package/dist/cjs/trigger-generator.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/workflow-component-plugin.d.ts +10 -1
- package/dist/cjs/workflow-component-plugin.d.ts.map +1 -1
- package/dist/cjs/workflow-component-plugin.js +36 -24
- package/dist/cjs/workflow-component-plugin.js.map +1 -1
- package/dist/esm/trigger-generator.d.ts +2 -0
- package/dist/esm/trigger-generator.d.ts.map +1 -1
- package/dist/esm/trigger-generator.js +29 -8
- package/dist/esm/trigger-generator.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/workflow-component-plugin.d.ts +10 -1
- package/dist/esm/workflow-component-plugin.d.ts.map +1 -1
- package/dist/esm/workflow-component-plugin.js +32 -23
- package/dist/esm/workflow-component-plugin.js.map +1 -1
- package/package.json +2 -2
- package/src/trigger-generator.ts +41 -10
- package/src/workflow-component-plugin.ts +48 -23
|
@@ -29,7 +29,12 @@ import { WorkflowExecutionEnv } from './types'
|
|
|
29
29
|
import { getAPIRouteFileName, hasStreamingAINode } from './api-route-generator'
|
|
30
30
|
import { REALTIME_TRIGGER_TYPES, REALTIME_NODE_TYPES } from './graph-utils'
|
|
31
31
|
import { neutraliseIsLoggedInGates } from './is-logged-in-gate'
|
|
32
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
TRACK_LEAD_SOURCE,
|
|
34
|
+
formControlPropertyReads,
|
|
35
|
+
intervalControlListenerSource,
|
|
36
|
+
intervalControlTeardownSource,
|
|
37
|
+
} from './trigger-generator'
|
|
33
38
|
import { elementVisibleObserverCode } from './element-visible-trigger'
|
|
34
39
|
import { restoreControlledSelectValue } from './controlled-select'
|
|
35
40
|
import { resolveScrollPoint } from './scroll-points'
|
|
@@ -1912,7 +1917,20 @@ ${globalStateChangeHandlerLines.join('\n')}
|
|
|
1912
1917
|
`
|
|
1913
1918
|
}
|
|
1914
1919
|
|
|
1915
|
-
|
|
1920
|
+
/* The bound element's `data-*` attributes, as trigger fields a workflow reads
|
|
1921
|
+
by name: `data-tab-index` is `dataTabIndex`, the name the static HTML export
|
|
1922
|
+
resolves from the same attribute. Values are the attribute strings. The
|
|
1923
|
+
result is the object the trigger's own fields are then assigned onto, so no
|
|
1924
|
+
attribute can replace one of them. */
|
|
1925
|
+
const datasetTriggerFieldsSource = (element: string): string =>
|
|
1926
|
+
`Object.keys((${element} && ${element}.dataset) || {}).reduce(function(fields, key) { fields['data' + key.charAt(0).toUpperCase() + key.slice(1)] = ${element}.dataset[key]; return fields; }, {})`
|
|
1927
|
+
|
|
1928
|
+
/* The submitted fields are spread FIRST so a field literally named `formData`,
|
|
1929
|
+
`formId`, `element` or `timestamp` can never shadow the reserved keys. */
|
|
1930
|
+
const formTriggerContextSource = (elementId: string): string =>
|
|
1931
|
+
`Object.assign({}, formData, { fields: formData, formData: formData, formId: '${elementId}', triggerElement: event.target, element: event.target, timestamp: Date.now() })`
|
|
1932
|
+
|
|
1933
|
+
export const generateElementHandler = (et: ElementTriggerInfo): string => {
|
|
1916
1934
|
const safeId = et.workflow.id.replace(/[^a-zA-Z0-9]/g, '_')
|
|
1917
1935
|
const config = et.triggerConfig
|
|
1918
1936
|
const elementId = et.elementId
|
|
@@ -1936,9 +1954,17 @@ const generateElementHandler = (et: ElementTriggerInfo): string => {
|
|
|
1936
1954
|
// the bound element when the user clicks a child — e.g. the payment
|
|
1937
1955
|
// provider row sets `data-provider-name` on the row div, but a click
|
|
1938
1956
|
// on the inner label span would otherwise resolve to an empty dataset.
|
|
1957
|
+
// A debounced run starts after the event has finished dispatching, when
|
|
1958
|
+
// `currentTarget` is already null, so the bound element is read before
|
|
1959
|
+
// the timer is set.
|
|
1960
|
+
const boundElement = debounce
|
|
1961
|
+
? '__bound || event.target'
|
|
1962
|
+
: 'event.currentTarget || event.target'
|
|
1939
1963
|
body +=
|
|
1940
|
-
` const __te =
|
|
1941
|
-
` const triggerContext =
|
|
1964
|
+
` const __te = ${boundElement};\n` +
|
|
1965
|
+
` const triggerContext = Object.assign(${datasetTriggerFieldsSource(
|
|
1966
|
+
'__te'
|
|
1967
|
+
)}, { elementId: '${elementId}', triggerElement: __te, element: __te, timestamp: Date.now(), clientX: event.clientX, clientY: event.clientY });\n` +
|
|
1942
1968
|
` return __execWf(__wfConfig_${safeId}, triggerContext, __wfServerUrls_${safeId});`
|
|
1943
1969
|
|
|
1944
1970
|
if (debounce) {
|
|
@@ -1946,6 +1972,7 @@ const generateElementHandler = (et: ElementTriggerInfo): string => {
|
|
|
1946
1972
|
`(function() {\n` +
|
|
1947
1973
|
` let timer = null;\n` +
|
|
1948
1974
|
` return function(event) {\n` +
|
|
1975
|
+
` const __bound = event.currentTarget;\n` +
|
|
1949
1976
|
` clearTimeout(timer);\n` +
|
|
1950
1977
|
` timer = setTimeout(async function() {\n` +
|
|
1951
1978
|
` ${body}\n` +
|
|
@@ -1972,17 +1999,15 @@ const generateElementHandler = (et: ElementTriggerInfo): string => {
|
|
|
1972
1999
|
// name as missing. `general-extract-form-data` already returns its fields
|
|
1973
2000
|
// flat for exactly this reason; the trigger now matches it, so both
|
|
1974
2001
|
// `params[0].name` and `params[0].formData.name` resolve.
|
|
1975
|
-
//
|
|
1976
|
-
//
|
|
1977
|
-
// `element` or `timestamp` can never shadow the reserved keys the runtime
|
|
1978
|
-
// and the workflow editor depend on.
|
|
2002
|
+
// The context is built by `formTriggerContextSource`, shared with the
|
|
2003
|
+
// native-listener fallback.
|
|
1979
2004
|
return (
|
|
1980
2005
|
`async function(event) {\n` +
|
|
1981
2006
|
(preventDefault ? ' event.preventDefault();\n' : '') +
|
|
1982
2007
|
` const formData = {};\n` +
|
|
1983
2008
|
` const fd = new FormData(event.target);\n` +
|
|
1984
2009
|
` fd.forEach(function(v, k) { formData[k] = v; });\n` +
|
|
1985
|
-
` const triggerContext =
|
|
2010
|
+
` const triggerContext = ${formTriggerContextSource(elementId)};\n` +
|
|
1986
2011
|
// Growth analytics: a form whose workflow ran to the end is a lead.
|
|
1987
2012
|
// __execWf resolves undefined when the run threw, so only a finished
|
|
1988
2013
|
// run reports.
|
|
@@ -2081,7 +2106,10 @@ const generateElementHandler = (et: ElementTriggerInfo): string => {
|
|
|
2081
2106
|
}
|
|
2082
2107
|
}
|
|
2083
2108
|
|
|
2084
|
-
const generateUnmatchedElementFallback = (
|
|
2109
|
+
export const generateUnmatchedElementFallback = (
|
|
2110
|
+
et: ElementTriggerInfo,
|
|
2111
|
+
safeId: string
|
|
2112
|
+
): string => {
|
|
2085
2113
|
const config = et.triggerConfig
|
|
2086
2114
|
const elementId = et.elementId
|
|
2087
2115
|
const domEvent = getDOMEventName(et.workflow.trigger.type, config)
|
|
@@ -2104,20 +2132,24 @@ const generateUnmatchedElementFallback = (et: ElementTriggerInfo, safeId: string
|
|
|
2104
2132
|
` const formData = {};\n` +
|
|
2105
2133
|
` const fd = new FormData(event.target);\n` +
|
|
2106
2134
|
` fd.forEach(function(v, k) { formData[k] = v; });\n` +
|
|
2107
|
-
` const triggerContext =
|
|
2135
|
+
` const triggerContext = ${formTriggerContextSource(elementId)};\n`
|
|
2108
2136
|
} else if (isInput) {
|
|
2109
2137
|
handlerBody += ` const triggerContext = { value: event.target.value, elementId: '${elementId}', triggerElement: event.target, element: event.target, timestamp: Date.now() };\n`
|
|
2110
2138
|
} else if (et.workflow.trigger.type === 'event-element-event') {
|
|
2111
2139
|
// See `event-element-event` in `generateElementHandler` for why we
|
|
2112
2140
|
// include `value`/`checked`/`files` unconditionally.
|
|
2113
|
-
handlerBody += ` const triggerContext = { elementId: '${elementId}', eventType: '${domEvent}', triggerElement: event.target, element: event.target, timestamp: Date.now(), clientX: event.clientX, clientY: event.clientY, offsetX: event.offsetX, offsetY: event.offsetY, button: event.button, deltaX: event.deltaX, deltaY: event.deltaY, deltaMode: event.deltaMode, key: event.key, ${formControlPropertyReads(
|
|
2141
|
+
handlerBody += ` const triggerContext = { elementId: '${elementId}', eventType: '${domEvent}', triggerElement: event.target, element: event.target, target: event.target, currentTarget: __el_${safeId}, timestamp: Date.now(), clientX: event.clientX, clientY: event.clientY, offsetX: event.offsetX, offsetY: event.offsetY, button: event.button, deltaX: event.deltaX, deltaY: event.deltaY, deltaMode: event.deltaMode, key: event.key, ${formControlPropertyReads(
|
|
2114
2142
|
'event.target'
|
|
2115
2143
|
)} };\n`
|
|
2116
2144
|
if (domEvent === 'drop') {
|
|
2117
2145
|
handlerBody += ` if (event.dataTransfer && event.dataTransfer.files) { triggerContext.files = Array.from(event.dataTransfer.files); }\n`
|
|
2118
2146
|
}
|
|
2119
2147
|
} else {
|
|
2120
|
-
|
|
2148
|
+
// The listener sits on `__el_<id>`, so that is the element whose
|
|
2149
|
+
// attributes are delivered, whichever child was clicked.
|
|
2150
|
+
handlerBody += ` const triggerContext = Object.assign(${datasetTriggerFieldsSource(
|
|
2151
|
+
`__el_${safeId}`
|
|
2152
|
+
)}, { elementId: '${elementId}', triggerElement: event.target, element: event.target, timestamp: Date.now(), clientX: event.clientX, clientY: event.clientY });\n`
|
|
2121
2153
|
}
|
|
2122
2154
|
|
|
2123
2155
|
handlerBody += ` __execWf(__wfConfig_${safeId}, triggerContext, __wfServerUrls_${safeId});`
|
|
@@ -2169,7 +2201,7 @@ const generateLoadedTriggerRun = (
|
|
|
2169
2201
|
` cleanups.push(function() { clearTimeout(__delay_${safeId}); });\n`
|
|
2170
2202
|
: ` ${execCall};\n`
|
|
2171
2203
|
|
|
2172
|
-
const generateLifecycleTrigger = (wf: UIDLWorkflow, safeId: string): string => {
|
|
2204
|
+
export const generateLifecycleTrigger = (wf: UIDLWorkflow, safeId: string): string => {
|
|
2173
2205
|
const trigger = wf.trigger
|
|
2174
2206
|
const config = (trigger.config || {}) as Record<string, unknown>
|
|
2175
2207
|
const execCall = `__execWf(__wfConfig_${safeId}, triggerContext, __wfServerUrls_${safeId})`
|
|
@@ -2539,12 +2571,7 @@ const generateLifecycleTrigger = (wf: UIDLWorkflow, safeId: string): string => {
|
|
|
2539
2571
|
}
|
|
2540
2572
|
|
|
2541
2573
|
if (controlEventName) {
|
|
2542
|
-
intervalCode +=
|
|
2543
|
-
` var __iv_ctrlHandler_${safeId} = function() {\n` +
|
|
2544
|
-
` if (__iv_running_${safeId}) { __iv_stop_${safeId}(); }\n` +
|
|
2545
|
-
` else { __iv_start_${safeId}(); }\n` +
|
|
2546
|
-
` };\n` +
|
|
2547
|
-
` window.addEventListener('${controlEventName}', __iv_ctrlHandler_${safeId});\n`
|
|
2574
|
+
intervalCode += intervalControlListenerSource(safeId, controlEventName)
|
|
2548
2575
|
}
|
|
2549
2576
|
|
|
2550
2577
|
if (autoStart) {
|
|
@@ -2558,9 +2585,7 @@ const generateLifecycleTrigger = (wf: UIDLWorkflow, safeId: string): string => {
|
|
|
2558
2585
|
(!runWhileHidden
|
|
2559
2586
|
? ` document.removeEventListener('visibilitychange', __iv_visHandler_${safeId});\n`
|
|
2560
2587
|
: '') +
|
|
2561
|
-
(controlEventName
|
|
2562
|
-
? ` window.removeEventListener('${controlEventName}', __iv_ctrlHandler_${safeId});\n`
|
|
2563
|
-
: '') +
|
|
2588
|
+
(controlEventName ? intervalControlTeardownSource(safeId, controlEventName) : '') +
|
|
2564
2589
|
` });`
|
|
2565
2590
|
|
|
2566
2591
|
return intervalCode
|