| 1 |
(function(react, _elementor_icons, _elementor_ui, _wordpress_i18n, _elementor_session, _elementor_editor_elements, _elementor_editor_v1_adapters, _elementor_editor_props, _elementor_editor_controls, _elementor_events, _elementor_editor_responsive, _elementor_editor_mcp, _elementor_editor_ui, _elementor_utils, _elementor_schema) { |
| 2 |
|
| 3 |
//#region \0rolldown/runtime.js |
| 4 |
var __create = Object.create; |
| 5 |
var __defProp = Object.defineProperty; |
| 6 |
var __name = (target, value) => __defProp(target, "name", { |
| 7 |
value, |
| 8 |
configurable: true |
| 9 |
}); |
| 10 |
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; |
| 11 |
var __getOwnPropNames = Object.getOwnPropertyNames; |
| 12 |
var __getProtoOf = Object.getPrototypeOf; |
| 13 |
var __hasOwnProp = Object.prototype.hasOwnProperty; |
| 14 |
var __exportAll = (all, no_symbols) => { |
| 15 |
let target = {}; |
| 16 |
for (var name in all) { |
| 17 |
__defProp(target, name, { |
| 18 |
get: all[name], |
| 19 |
enumerable: true |
| 20 |
}); |
| 21 |
} |
| 22 |
if (!no_symbols) { |
| 23 |
__defProp(target, Symbol.toStringTag, { value: "Module" }); |
| 24 |
} |
| 25 |
return target; |
| 26 |
}; |
| 27 |
var __copyProps = (to, from, except, desc) => { |
| 28 |
if (from && typeof from === "object" || typeof from === "function") { |
| 29 |
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { |
| 30 |
key = keys[i]; |
| 31 |
if (!__hasOwnProp.call(to, key) && key !== except) { |
| 32 |
__defProp(to, key, { |
| 33 |
get: ((k) => from[k]).bind(null, key), |
| 34 |
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable |
| 35 |
}); |
| 36 |
} |
| 37 |
} |
| 38 |
} |
| 39 |
return to; |
| 40 |
}; |
| 41 |
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { |
| 42 |
value: mod, |
| 43 |
enumerable: true |
| 44 |
}) : target, mod)); |
| 45 |
|
| 46 |
//#endregion |
| 47 |
react = __toESM(react); |
| 48 |
|
| 49 |
//#region packages/packages/core/editor-interactions/src/components/empty-state.tsx |
| 50 |
var EmptyState = ({ onCreateInteraction }) => { |
| 51 |
return /* @__PURE__ */ react.createElement(_elementor_ui.Stack, { |
| 52 |
alignItems: "center", |
| 53 |
justifyContent: "center", |
| 54 |
height: "100%", |
| 55 |
color: "text.secondary", |
| 56 |
sx: { |
| 57 |
p: 2.5, |
| 58 |
pt: 8, |
| 59 |
pb: 5.5 |
| 60 |
}, |
| 61 |
gap: 1.5 |
| 62 |
}, /* @__PURE__ */ react.createElement(_elementor_icons.SwipeIcon, { fontSize: "large" }), /* @__PURE__ */ react.createElement(_elementor_ui.Typography, { |
| 63 |
align: "center", |
| 64 |
variant: "subtitle2" |
| 65 |
}, (0, _wordpress_i18n.__)("Animate elements with Interactions", "elementor")), /* @__PURE__ */ react.createElement(_elementor_ui.Typography, { |
| 66 |
align: "center", |
| 67 |
variant: "caption", |
| 68 |
maxWidth: "170px" |
| 69 |
}, (0, _wordpress_i18n.__)("Add entrance animations and effects triggered by user interactions such as page load or scroll.", "elementor")), /* @__PURE__ */ react.createElement(_elementor_ui.Button, { |
| 70 |
variant: "outlined", |
| 71 |
color: "secondary", |
| 72 |
size: "small", |
| 73 |
sx: { mt: 1 }, |
| 74 |
onClick: onCreateInteraction |
| 75 |
}, (0, _wordpress_i18n.__)("Create an interaction", "elementor"))); |
| 76 |
}; |
| 77 |
|
| 78 |
//#endregion |
| 79 |
//#region packages/packages/core/editor-interactions/src/interactions-controls-registry.ts |
| 80 |
var controlsRegistry = /* @__PURE__ */ new Map(); |
| 81 |
function registerInteractionsControl({ type, component, options }) { |
| 82 |
controlsRegistry.set(type, { |
| 83 |
type, |
| 84 |
component, |
| 85 |
options |
| 86 |
}); |
| 87 |
} |
| 88 |
function getInteractionsControl(type) { |
| 89 |
return controlsRegistry.get(type); |
| 90 |
} |
| 91 |
function getInteractionsControlOptions(type) { |
| 92 |
return controlsRegistry.get(type)?.options ?? []; |
| 93 |
} |
| 94 |
|
| 95 |
//#endregion |
| 96 |
//#region packages/packages/core/editor-interactions/src/configs/time-constants.ts |
| 97 |
var TIME_UNITS = ["s", "ms"]; |
| 98 |
|
| 99 |
//#endregion |
| 100 |
//#region packages/packages/core/editor-interactions/src/utils/size-transform-utils.ts |
| 101 |
var SIZE_REGEX = /^(?:(-?\d*\.?\d+)([a-z%]+)|([a-z%]+))$/i; |
| 102 |
var parseSizeValue = (value, allowedUnits, defaultValue, defaultUnit) => { |
| 103 |
if (typeof value === "number") return { |
| 104 |
size: value, |
| 105 |
unit: defaultUnit |
| 106 |
}; |
| 107 |
const sizeValue = tryParse(value, allowedUnits, defaultUnit); |
| 108 |
if (sizeValue) return sizeValue; |
| 109 |
if (defaultValue) { |
| 110 |
const fallbackSize = tryParse(defaultValue, allowedUnits, defaultUnit); |
| 111 |
if (fallbackSize) return fallbackSize; |
| 112 |
} |
| 113 |
return createSizeValue(null, defaultUnit); |
| 114 |
}; |
| 115 |
var tryParse = (value, allowedUnits, defaultUnit) => { |
| 116 |
if (typeof value === "number") return createSizeValue(value, defaultUnit); |
| 117 |
const match = value && value.match(SIZE_REGEX); |
| 118 |
if (!match) { |
| 119 |
if (value) return { |
| 120 |
size: Number(value), |
| 121 |
unit: defaultUnit |
| 122 |
}; |
| 123 |
return null; |
| 124 |
} |
| 125 |
const size = match[1] ? parseFloat(match[1]) : null; |
| 126 |
const unit = match[2] || match[3]; |
| 127 |
if (!allowedUnits.includes(unit)) return null; |
| 128 |
return createSizeValue(size, unit); |
| 129 |
}; |
| 130 |
var formatSizeValue = ({ size, unit }) => { |
| 131 |
return `${size ?? ""}${unit}`; |
| 132 |
}; |
| 133 |
var createSizeValue = (size, unit) => { |
| 134 |
return { |
| 135 |
size, |
| 136 |
unit |
| 137 |
}; |
| 138 |
}; |
| 139 |
|
| 140 |
//#endregion |
| 141 |
//#region packages/packages/core/editor-interactions/src/utils/custom-effect-to-prop-value.ts |
| 142 |
var CUSTOM_EFFECT_TYPE = "custom-effect"; |
| 143 |
var KEYFRAMES_TYPE = "keyframes"; |
| 144 |
var KEYFRAME_STOP_TYPE = "keyframe-stop"; |
| 145 |
var KEYFRAME_STOP_SETTINGS_TYPE = "keyframe-stop-settings"; |
| 146 |
var SIZE_TYPE = "size"; |
| 147 |
var NUMBER_TYPE = "number"; |
| 148 |
var TRANSFORM_SCALE_TYPE = "transform-scale"; |
| 149 |
var TRANSFORM_ROTATE_TYPE = "transform-rotate"; |
| 150 |
var TRANSFORM_MOVE_TYPE = "transform-move"; |
| 151 |
var TRANSFORM_SKEW_TYPE = "transform-skew"; |
| 152 |
var UNIT_PERCENT = "%"; |
| 153 |
var UNIT_DEG = "deg"; |
| 154 |
var UNIT_PX = "px"; |
| 155 |
var isPlainCustomEffect = (v) => typeof v === "object" && v !== null && "keyframes" in v && Array.isArray(v.keyframes) && !("$$type" in v); |
| 156 |
var toSizePropValue = (size, unit = UNIT_PERCENT) => ({ |
| 157 |
$$type: SIZE_TYPE, |
| 158 |
value: { |
| 159 |
size, |
| 160 |
unit |
| 161 |
} |
| 162 |
}); |
| 163 |
var toNumberPropValue = (n) => ({ |
| 164 |
$$type: NUMBER_TYPE, |
| 165 |
value: n |
| 166 |
}); |
| 167 |
var toDimensionalNumberPropValue = (type, plain, defaults) => ({ |
| 168 |
$$type: type, |
| 169 |
value: { |
| 170 |
x: toNumberPropValue(plain.x ?? defaults.x), |
| 171 |
y: toNumberPropValue(plain.y ?? defaults.y), |
| 172 |
z: toNumberPropValue(plain.z ?? defaults.z) |
| 173 |
} |
| 174 |
}); |
| 175 |
var toDimensionalSizePropValue = (type, plain, defaults, unit) => ({ |
| 176 |
$$type: type, |
| 177 |
value: { |
| 178 |
x: toSizePropValue(plain.x ?? defaults.x, unit), |
| 179 |
y: toSizePropValue(plain.y ?? defaults.y, unit), |
| 180 |
z: toSizePropValue(plain.z ?? defaults.z, unit) |
| 181 |
} |
| 182 |
}); |
| 183 |
var toSkewPropValue = (plain) => ({ |
| 184 |
$$type: TRANSFORM_SKEW_TYPE, |
| 185 |
value: { |
| 186 |
x: toSizePropValue(plain.x ?? 0, UNIT_DEG), |
| 187 |
y: toSizePropValue(plain.y ?? 0, UNIT_DEG) |
| 188 |
} |
| 189 |
}); |
| 190 |
var toKeyframeStopSettingsPropValue = (plain) => { |
| 191 |
const value = {}; |
| 192 |
if (plain.opacity !== void 0) { |
| 193 |
const percent = plain.opacity <= 1 ? Math.round(plain.opacity * 100) : plain.opacity; |
| 194 |
value.opacity = toSizePropValue(percent); |
| 195 |
} |
| 196 |
if (plain.scale !== void 0) value.scale = toDimensionalNumberPropValue(TRANSFORM_SCALE_TYPE, plain.scale, { |
| 197 |
x: 1, |
| 198 |
y: 1, |
| 199 |
z: 1 |
| 200 |
}); |
| 201 |
if (plain.rotate !== void 0) value.rotate = toDimensionalSizePropValue(TRANSFORM_ROTATE_TYPE, plain.rotate, { |
| 202 |
x: 0, |
| 203 |
y: 0, |
| 204 |
z: 0 |
| 205 |
}, UNIT_DEG); |
| 206 |
if (plain.move !== void 0) value.move = toDimensionalSizePropValue(TRANSFORM_MOVE_TYPE, plain.move, { |
| 207 |
x: 0, |
| 208 |
y: 0, |
| 209 |
z: 0 |
| 210 |
}, UNIT_PX); |
| 211 |
if (plain.skew !== void 0) value.skew = toSkewPropValue(plain.skew); |
| 212 |
return { |
| 213 |
$$type: KEYFRAME_STOP_SETTINGS_TYPE, |
| 214 |
value |
| 215 |
}; |
| 216 |
}; |
| 217 |
var isPlainKeyframe = (v) => typeof v === "object" && v !== null && "stop" in v && "value" in v && !("$$type" in v); |
| 218 |
var toKeyframeStopPropValue = (item) => { |
| 219 |
if (!isPlainKeyframe(item)) return item; |
| 220 |
return { |
| 221 |
$$type: KEYFRAME_STOP_TYPE, |
| 222 |
value: { |
| 223 |
stop: toSizePropValue(item.stop), |
| 224 |
settings: toKeyframeStopSettingsPropValue(item.value) |
| 225 |
} |
| 226 |
}; |
| 227 |
}; |
| 228 |
var toKeyframesPropValue = (keyframes) => ({ |
| 229 |
$$type: KEYFRAMES_TYPE, |
| 230 |
value: keyframes.map(toKeyframeStopPropValue) |
| 231 |
}); |
| 232 |
var plainCustomEffectToPropValue = (plain) => ({ |
| 233 |
$$type: CUSTOM_EFFECT_TYPE, |
| 234 |
value: { keyframes: toKeyframesPropValue(plain.keyframes) } |
| 235 |
}); |
| 236 |
var toCustomEffectPropValue = (customEffects) => { |
| 237 |
if (customEffects === void 0) return; |
| 238 |
if (isPlainCustomEffect(customEffects)) return plainCustomEffectToPropValue(customEffects); |
| 239 |
return customEffects; |
| 240 |
}; |
| 241 |
|
| 242 |
//#endregion |
| 243 |
//#region packages/packages/core/editor-interactions/src/utils/get-interactions-config.ts |
| 244 |
function getInteractionsConfig() { |
| 245 |
return window.ElementorInteractionsConfig ?? {}; |
| 246 |
} |
| 247 |
|
| 248 |
//#endregion |
| 249 |
//#region packages/packages/core/editor-interactions/src/utils/temp-id-utils.ts |
| 250 |
var TEMP_ID_PREFIX = "temp-"; |
| 251 |
var TEMP_ID_REGEX = /^temp-[a-z0-9]+$/i; |
| 252 |
function generateTempInteractionId() { |
| 253 |
return `${TEMP_ID_PREFIX}${Math.random().toString(36).substring(2, 11)}`; |
| 254 |
} |
| 255 |
function isTempId(id) { |
| 256 |
return !!id && TEMP_ID_REGEX.test(id); |
| 257 |
} |
| 258 |
|
| 259 |
//#endregion |
| 260 |
//#region packages/packages/core/editor-interactions/src/utils/prop-value-utils.ts |
| 261 |
var createString = (value) => ({ |
| 262 |
$$type: "string", |
| 263 |
value |
| 264 |
}); |
| 265 |
var createNumber = (value) => ({ |
| 266 |
$$type: "number", |
| 267 |
value |
| 268 |
}); |
| 269 |
var createTimingConfig = (duration, delay) => ({ |
| 270 |
$$type: "timing-config", |
| 271 |
value: { |
| 272 |
duration: _elementor_editor_props.sizePropTypeUtil.create(parseSizeValue(duration, TIME_UNITS, void 0, "ms")), |
| 273 |
delay: _elementor_editor_props.sizePropTypeUtil.create(parseSizeValue(delay, TIME_UNITS, void 0, "ms")) |
| 274 |
} |
| 275 |
}); |
| 276 |
var createBoolean = (value) => ({ |
| 277 |
$$type: "boolean", |
| 278 |
value |
| 279 |
}); |
| 280 |
var createConfig = ({ replay, easing = "easeIn", relativeTo = "viewport", repeat = "", times = 1, start = 85, end = 15 }) => ({ |
| 281 |
$$type: "config", |
| 282 |
value: { |
| 283 |
replay: createBoolean(replay), |
| 284 |
easing: createString(easing), |
| 285 |
relativeTo: createString(relativeTo), |
| 286 |
repeat: createString(repeat), |
| 287 |
times: createNumber(times), |
| 288 |
start: createSize(start, "%"), |
| 289 |
end: createSize(end, "%") |
| 290 |
} |
| 291 |
}); |
| 292 |
var createSize = (value, defaultUnit, defaultValue) => { |
| 293 |
if (!value) return; |
| 294 |
return _elementor_editor_props.sizePropTypeUtil.create(parseSizeValue(value, ["%"], defaultValue, defaultUnit)); |
| 295 |
}; |
| 296 |
var extractBoolean = (prop, fallback = false) => { |
| 297 |
return prop?.value ?? fallback; |
| 298 |
}; |
| 299 |
var createExcludedBreakpoints = (breakpoints) => ({ |
| 300 |
$$type: "excluded-breakpoints", |
| 301 |
value: breakpoints.map(createString) |
| 302 |
}); |
| 303 |
var createInteractionBreakpoints = (excluded) => ({ |
| 304 |
$$type: "interaction-breakpoints", |
| 305 |
value: { excluded: createExcludedBreakpoints(excluded) } |
| 306 |
}); |
| 307 |
var extractExcludedBreakpoints = (breakpoints) => { |
| 308 |
return breakpoints?.value.excluded.value.map((bp) => bp.value) ?? []; |
| 309 |
}; |
| 310 |
var createAnimationPreset = ({ effect, type, direction, duration, delay, replay = false, easing = "easeIn", relativeTo, repeat, times, start, end, customEffects }) => { |
| 311 |
const customEffectProp = toCustomEffectPropValue(customEffects); |
| 312 |
return { |
| 313 |
$$type: "animation-preset-props", |
| 314 |
value: { |
| 315 |
effect: createString(effect), |
| 316 |
...customEffectProp !== void 0 && { custom_effect: customEffectProp }, |
| 317 |
type: createString(type), |
| 318 |
direction: createString(direction ?? ""), |
| 319 |
timing_config: createTimingConfig(duration, delay), |
| 320 |
config: createConfig({ |
| 321 |
replay, |
| 322 |
easing, |
| 323 |
relativeTo, |
| 324 |
repeat, |
| 325 |
times, |
| 326 |
start, |
| 327 |
end |
| 328 |
}) |
| 329 |
} |
| 330 |
}; |
| 331 |
}; |
| 332 |
var createInteractionItem = ({ trigger, effect, type, direction, duration, delay, interactionId, replay = false, easing = "easeIn", relativeTo, repeat, times, start, end, excludedBreakpoints, customEffects }) => ({ |
| 333 |
$$type: "interaction-item", |
| 334 |
value: { |
| 335 |
...interactionId && { interaction_id: createString(interactionId) }, |
| 336 |
trigger: createString(trigger ?? ""), |
| 337 |
animation: createAnimationPreset({ |
| 338 |
effect: effect ?? "", |
| 339 |
type: type ?? "", |
| 340 |
direction, |
| 341 |
duration: duration ?? 0, |
| 342 |
delay: delay ?? 0, |
| 343 |
replay, |
| 344 |
easing, |
| 345 |
relativeTo, |
| 346 |
repeat, |
| 347 |
times, |
| 348 |
start, |
| 349 |
end, |
| 350 |
customEffects |
| 351 |
}), |
| 352 |
...excludedBreakpoints && excludedBreakpoints.length > 0 && { breakpoints: createInteractionBreakpoints(excludedBreakpoints) } |
| 353 |
} |
| 354 |
}); |
| 355 |
var createDefaultInteractionItem = () => { |
| 356 |
const { constants } = getInteractionsConfig(); |
| 357 |
return createInteractionItem({ |
| 358 |
trigger: "load", |
| 359 |
effect: "fade", |
| 360 |
type: "in", |
| 361 |
duration: constants.defaultDuration, |
| 362 |
delay: constants.defaultDelay, |
| 363 |
replay: false, |
| 364 |
easing: constants.defaultEasing, |
| 365 |
interactionId: generateTempInteractionId() |
| 366 |
}); |
| 367 |
}; |
| 368 |
var createDefaultInteractions = () => ({ |
| 369 |
version: 1, |
| 370 |
items: [createDefaultInteractionItem()] |
| 371 |
}); |
| 372 |
var extractString = (prop, fallback = "") => { |
| 373 |
return prop?.value ?? fallback; |
| 374 |
}; |
| 375 |
var extractSize = (prop, defaultValue) => { |
| 376 |
if (!prop?.value) return defaultValue; |
| 377 |
return formatSizeValue(prop.value); |
| 378 |
}; |
| 379 |
var TRIGGER_LABELS$1 = { |
| 380 |
load: "On page load", |
| 381 |
scrollIn: "Scroll into view", |
| 382 |
scrollOut: "Scroll out of view", |
| 383 |
scrollOn: "While scrolling" |
| 384 |
}; |
| 385 |
var capitalize$1 = /* @__PURE__ */ __name((str) => { |
| 386 |
return str.charAt(0).toUpperCase() + str.slice(1); |
| 387 |
}, "capitalize"); |
| 388 |
var buildDisplayLabel = (item) => { |
| 389 |
const trigger = extractString(item.trigger); |
| 390 |
const effect = extractString(item.animation.value.effect); |
| 391 |
const type = extractString(item.animation.value.type); |
| 392 |
return `${TRIGGER_LABELS$1[trigger] || capitalize$1(trigger)}: ${capitalize$1(effect)} ${"custom" === effect ? "" : capitalize$1(type)}`; |
| 393 |
}; |
| 394 |
|
| 395 |
//#endregion |
| 396 |
//#region packages/packages/core/editor-interactions/src/utils/is-supported-interaction-item.ts |
| 397 |
function isSupportedInteractionItem(interaction) { |
| 398 |
const value = interaction.value; |
| 399 |
if (true === extractBoolean(value.animation.value.config?.value.replay)) return hasSupport("replay", "yes"); |
| 400 |
const trigger = extractString(value.trigger); |
| 401 |
const easing = extractString(value.animation.value.config?.value.easing); |
| 402 |
const effect = extractString(value.animation.value.effect); |
| 403 |
return [ |
| 404 |
["trigger", trigger], |
| 405 |
["easing", easing], |
| 406 |
["effect", effect] |
| 407 |
].every(([controlType, controlValue]) => { |
| 408 |
if (controlValue === "" || controlValue === null) return true; |
| 409 |
return hasSupport(controlType, controlValue); |
| 410 |
}); |
| 411 |
} |
| 412 |
function hasSupport(controlType, controlValue) { |
| 413 |
const supportedOptions = getInteractionsControlOptions(controlType); |
| 414 |
if (1 > supportedOptions.length) return true; |
| 415 |
return supportedOptions.includes(controlValue); |
| 416 |
} |
| 417 |
|
| 418 |
//#endregion |
| 419 |
//#region packages/packages/core/editor-interactions/src/utils/filter-interactions.ts |
| 420 |
var filterInteractions = (interactions) => { |
| 421 |
return interactions.filter((interaction) => { |
| 422 |
return isSupportedInteractionItem(interaction); |
| 423 |
}); |
| 424 |
}; |
| 425 |
|
| 426 |
//#endregion |
| 427 |
//#region packages/packages/core/editor-interactions/src/hooks/use-element-interactions.ts |
| 428 |
var useElementInteractions = (elementId) => { |
| 429 |
const [interactions, setInteractions] = (0, react.useState)(() => { |
| 430 |
const initial = (0, _elementor_editor_elements.getElementInteractions)(elementId); |
| 431 |
const filteredInteractions = filterInteractions(initial?.items ?? []); |
| 432 |
return { |
| 433 |
version: initial?.version ?? 1, |
| 434 |
items: filteredInteractions |
| 435 |
}; |
| 436 |
}); |
| 437 |
(0, _elementor_editor_v1_adapters.__privateUseListenTo)((0, _elementor_editor_v1_adapters.windowEvent)("elementor/element/update_interactions"), () => { |
| 438 |
const newInteractions = (0, _elementor_editor_elements.getElementInteractions)(elementId); |
| 439 |
const filteredInteractions = filterInteractions(newInteractions?.items ?? []); |
| 440 |
setInteractions({ |
| 441 |
version: newInteractions?.version ?? 1, |
| 442 |
items: filteredInteractions |
| 443 |
}); |
| 444 |
}, [elementId]); |
| 445 |
return interactions; |
| 446 |
}; |
| 447 |
|
| 448 |
//#endregion |
| 449 |
//#region packages/packages/core/editor-interactions/src/contexts/interactions-context.tsx |
| 450 |
var InteractionsContext = (0, react.createContext)(null); |
| 451 |
var DEFAULT_INTERACTIONS = { |
| 452 |
version: 1, |
| 453 |
items: [] |
| 454 |
}; |
| 455 |
var InteractionsProvider = ({ children, elementId }) => { |
| 456 |
const rawInteractions = useElementInteractions(elementId); |
| 457 |
(0, react.useEffect)(() => { |
| 458 |
window.dispatchEvent(new CustomEvent("elementor/element/update_interactions")); |
| 459 |
}, []); |
| 460 |
const interactions = rawInteractions ?? DEFAULT_INTERACTIONS; |
| 461 |
const undoableSetInteractions = (0, react.useMemo)(() => (0, _elementor_editor_v1_adapters.undoable)({ |
| 462 |
do: ({ interactions: newInteractions }) => { |
| 463 |
const previous = (0, _elementor_editor_elements.getElementInteractions)(elementId); |
| 464 |
(0, _elementor_editor_elements.updateElementInteractions)({ |
| 465 |
elementId, |
| 466 |
interactions: newInteractions |
| 467 |
}); |
| 468 |
return previous; |
| 469 |
}, |
| 470 |
undo: (_, previous) => { |
| 471 |
(0, _elementor_editor_elements.updateElementInteractions)({ |
| 472 |
elementId, |
| 473 |
interactions: previous?.items?.length ? previous : void 0 |
| 474 |
}); |
| 475 |
} |
| 476 |
}, { |
| 477 |
title: (0, _elementor_editor_elements.getElementLabel)(elementId), |
| 478 |
subtitle: ({ operationType }) => operationType === "apply" ? (0, _wordpress_i18n.__)("Interaction Applied", "elementor") : (0, _wordpress_i18n.__)("Interaction Deleted", "elementor") |
| 479 |
}), [elementId]); |
| 480 |
const setInteractions = (value) => { |
| 481 |
const normalizedValue = value && value.items?.length === 0 ? void 0 : value; |
| 482 |
const prevItemCount = interactions.items?.length ?? 0; |
| 483 |
const newItemCount = normalizedValue?.items?.length ?? 0; |
| 484 |
if (newItemCount > prevItemCount) undoableSetInteractions({ |
| 485 |
interactions: normalizedValue, |
| 486 |
operationType: "apply" |
| 487 |
}); |
| 488 |
else if (newItemCount < prevItemCount) undoableSetInteractions({ |
| 489 |
interactions: normalizedValue, |
| 490 |
operationType: "delete" |
| 491 |
}); |
| 492 |
else (0, _elementor_editor_elements.updateElementInteractions)({ |
| 493 |
elementId, |
| 494 |
interactions: normalizedValue |
| 495 |
}); |
| 496 |
}; |
| 497 |
const playInteractions = (interactionId) => { |
| 498 |
(0, _elementor_editor_elements.playElementInteractions)(elementId, interactionId); |
| 499 |
}; |
| 500 |
const contextValue = { |
| 501 |
elementId, |
| 502 |
interactions, |
| 503 |
setInteractions, |
| 504 |
playInteractions |
| 505 |
}; |
| 506 |
return /* @__PURE__ */ react.createElement(InteractionsContext.Provider, { value: contextValue }, children); |
| 507 |
}; |
| 508 |
var useInteractionsContext = () => { |
| 509 |
const context = (0, react.useContext)(InteractionsContext); |
| 510 |
if (!context) throw new Error("useInteractionsContext must be used within InteractionsProvider"); |
| 511 |
return context; |
| 512 |
}; |
| 513 |
|
| 514 |
//#endregion |
| 515 |
//#region packages/packages/core/editor-interactions/src/contexts/popup-state-context.tsx |
| 516 |
var PopupStateContext = (0, react.createContext)(void 0); |
| 517 |
var PopupStateProvider = ({ children }) => { |
| 518 |
const [openByDefault, setOpenByDefault] = (0, react.useState)(false); |
| 519 |
const triggerDefaultOpen = (0, react.useCallback)(() => { |
| 520 |
setOpenByDefault(true); |
| 521 |
}, []); |
| 522 |
const resetDefaultOpen = (0, react.useCallback)(() => { |
| 523 |
setOpenByDefault(false); |
| 524 |
}, []); |
| 525 |
return /* @__PURE__ */ react.createElement(PopupStateContext.Provider, { value: { |
| 526 |
openByDefault, |
| 527 |
triggerDefaultOpen, |
| 528 |
resetDefaultOpen |
| 529 |
} }, children); |
| 530 |
}; |
| 531 |
|
| 532 |
//#endregion |
| 533 |
//#region packages/packages/core/editor-interactions/src/contexts/interactions-item-context.tsx |
| 534 |
var InteractionItemContext = (0, react.createContext)(null); |
| 535 |
function InteractionItemContextProvider({ value, children }) { |
| 536 |
return /* @__PURE__ */ react.createElement(InteractionItemContext.Provider, { value }, children); |
| 537 |
} |
| 538 |
function useInteractionItemContext() { |
| 539 |
const context = (0, react.useContext)(InteractionItemContext); |
| 540 |
if (!context) throw new Error("useInteractionItemContext must be used within InteractionItemContextProvider"); |
| 541 |
return context; |
| 542 |
} |
| 543 |
|
| 544 |
//#endregion |
| 545 |
//#region packages/packages/core/editor-interactions/src/utils/scroll-interaction-event.ts |
| 546 |
var SCROLL_INTERACTION_EVENT = "elementor/interactions/scroll-change"; |
| 547 |
function dispatchScrollInteraction(data) { |
| 548 |
window.dispatchEvent(new CustomEvent(SCROLL_INTERACTION_EVENT, { detail: data })); |
| 549 |
} |
| 550 |
function extractScrollOverlayParams(interaction, defaults) { |
| 551 |
return { |
| 552 |
trigger: extractString(interaction.trigger, defaults.trigger), |
| 553 |
start: extractSize(interaction.animation.value.config?.value.start, defaults.start), |
| 554 |
end: extractSize(interaction.animation.value.config?.value.end, defaults.end), |
| 555 |
relativeTo: extractString(interaction.animation.value.config?.value.relativeTo, defaults.relativeTo) |
| 556 |
}; |
| 557 |
} |
| 558 |
function syncGridOverlay(trigger, start, end, relativeTo) { |
| 559 |
if (trigger === "scrollOn") dispatchScrollInteraction({ |
| 560 |
start, |
| 561 |
end, |
| 562 |
relativeTo |
| 563 |
}); |
| 564 |
else dispatchScrollInteraction(null); |
| 565 |
} |
| 566 |
|
| 567 |
//#endregion |
| 568 |
//#region packages/packages/core/editor-interactions/src/utils/tracking.ts |
| 569 |
var TRIGGER_LABELS = { |
| 570 |
load: "On page load", |
| 571 |
scrollIn: "Scroll into view", |
| 572 |
scrollOut: "Scroll out of view", |
| 573 |
scrollOn: "While scrolling", |
| 574 |
hover: "Hover", |
| 575 |
click: "Click" |
| 576 |
}; |
| 577 |
var capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1); |
| 578 |
var trackInteractionCreated = (elementId, item) => { |
| 579 |
const { dispatchEvent, config } = (0, _elementor_events.getMixpanel)(); |
| 580 |
if (!config?.names?.interactions?.created) return; |
| 581 |
const trigger = extractString(item.value.trigger); |
| 582 |
const effect = extractString(item.value.animation.value.effect); |
| 583 |
const type = extractString(item.value.animation.value.type); |
| 584 |
dispatchEvent?.(config.names.interactions.created, { |
| 585 |
window_name: config?.appTypes?.editor, |
| 586 |
interaction_type: config?.triggers?.click, |
| 587 |
target_name: (0, _elementor_editor_elements.getElementLabel)(elementId), |
| 588 |
interaction_result: "interaction_created", |
| 589 |
target_location: config?.locations?.widgetPanel, |
| 590 |
location_l1: (0, _elementor_editor_elements.getElementLabel)(elementId), |
| 591 |
location_l2: "interactions", |
| 592 |
interaction_description: "interaction_created", |
| 593 |
interaction_trigger: TRIGGER_LABELS[trigger] ?? capitalize(trigger), |
| 594 |
interaction_effect: effect === "custom" ? capitalize(effect) : `${capitalize(effect)} ${capitalize(type)}` |
| 595 |
}); |
| 596 |
}; |
| 597 |
|
| 598 |
//#endregion |
| 599 |
//#region packages/packages/core/editor-interactions/src/utils/resolve-direction.ts |
| 600 |
var resolveDirection = (hasDirection, newEffect, newDirection, currentDirection, currentEffect) => { |
| 601 |
if (newEffect === "slide" && !newDirection) return "top"; |
| 602 |
if (currentEffect === "slide" && hasDirection) return newDirection || "top"; |
| 603 |
if (hasDirection) return newDirection; |
| 604 |
return currentDirection; |
| 605 |
}; |
| 606 |
|
| 607 |
//#endregion |
| 608 |
//#region packages/packages/core/editor-interactions/src/components/controls/time-frame-indicator.tsx |
| 609 |
function TimeFrameIndicator({ value, onChange, defaultValue }) { |
| 610 |
const sizeValue = parseSizeValue(value, TIME_UNITS, defaultValue, "ms"); |
| 611 |
const handleChange = (0, react.useCallback)((size) => { |
| 612 |
onChange(formatSizeValue(size)); |
| 613 |
}, [onChange]); |
| 614 |
const handleBlur = (event) => { |
| 615 |
if (!event.target.value) handleChange(parseSizeValue(defaultValue, TIME_UNITS, void 0, "ms")); |
| 616 |
}; |
| 617 |
return /* @__PURE__ */ react.createElement(_elementor_editor_controls.SizeComponent, { |
| 618 |
units: TIME_UNITS, |
| 619 |
value: sizeValue, |
| 620 |
setValue: handleChange, |
| 621 |
onBlur: handleBlur, |
| 622 |
InputProps: { inputProps: { min: 0 } } |
| 623 |
}); |
| 624 |
} |
| 625 |
|
| 626 |
//#endregion |
| 627 |
//#region packages/packages/core/editor-interactions/src/components/field.tsx |
| 628 |
var Field = ({ label, children }) => { |
| 629 |
return /* @__PURE__ */ react.createElement(_elementor_ui.Grid, { |
| 630 |
item: true, |
| 631 |
xs: 12, |
| 632 |
"aria-label": `${label} control` |
| 633 |
}, /* @__PURE__ */ react.createElement(_elementor_editor_controls.PopoverGridContainer, null, /* @__PURE__ */ react.createElement(_elementor_ui.Grid, { |
| 634 |
item: true, |
| 635 |
xs: 6 |
| 636 |
}, /* @__PURE__ */ react.createElement(_elementor_editor_controls.ControlFormLabel, null, label)), /* @__PURE__ */ react.createElement(_elementor_ui.Grid, { |
| 637 |
item: true, |
| 638 |
xs: 6 |
| 639 |
}, children))); |
| 640 |
}; |
| 641 |
|
| 642 |
//#endregion |
| 643 |
//#region packages/packages/core/editor-interactions/src/components/interaction-details.tsx |
| 644 |
var DEFAULT_VALUES = { |
| 645 |
trigger: "load", |
| 646 |
effect: "fade", |
| 647 |
type: "in", |
| 648 |
direction: "", |
| 649 |
duration: 600, |
| 650 |
delay: 0, |
| 651 |
replay: false, |
| 652 |
easing: "easeIn", |
| 653 |
relativeTo: "viewport", |
| 654 |
repeat: "", |
| 655 |
times: 1, |
| 656 |
start: 85, |
| 657 |
end: 15 |
| 658 |
}; |
| 659 |
var TRIGGERS_WITHOUT_REPLAY = [ |
| 660 |
"load", |
| 661 |
"scrollOn", |
| 662 |
"hover", |
| 663 |
"click" |
| 664 |
]; |
| 665 |
var controlVisibilityConfig = { |
| 666 |
replay: (values) => !TRIGGERS_WITHOUT_REPLAY.includes(values.trigger), |
| 667 |
custom: (values) => values.effect === "custom", |
| 668 |
effectType: (values) => values.effect !== "custom", |
| 669 |
direction: (values) => values.effect !== "custom", |
| 670 |
relativeTo: (values) => values.trigger === "scrollOn", |
| 671 |
start: (values) => values.trigger === "scrollOn", |
| 672 |
end: (values) => values.trigger === "scrollOn", |
| 673 |
repeat: (values) => values.trigger !== "scrollOn", |
| 674 |
times: (values) => values.trigger !== "scrollOn" && values.repeat === "times", |
| 675 |
duration: (values) => { |
| 676 |
return !(values.trigger === "scrollOn"); |
| 677 |
}, |
| 678 |
delay: (values) => { |
| 679 |
return !(values.trigger === "scrollOn"); |
| 680 |
} |
| 681 |
}; |
| 682 |
function normalizeTimesValue(value, fallback) { |
| 683 |
const numericValue = Number(value); |
| 684 |
if (!Number.isFinite(numericValue)) return fallback; |
| 685 |
return Math.max(1, Math.floor(numericValue)); |
| 686 |
} |
| 687 |
function useControlComponent(controlName, isVisible = true) { |
| 688 |
return (0, react.useMemo)(() => { |
| 689 |
if (!isVisible) return null; |
| 690 |
return getInteractionsControl(controlName)?.component ?? null; |
| 691 |
}, [controlName, isVisible]); |
| 692 |
} |
| 693 |
var InteractionDetails = ({ interaction, onChange, onPlayInteraction }) => { |
| 694 |
const trigger = extractString(interaction.trigger, DEFAULT_VALUES.trigger); |
| 695 |
const effect = extractString(interaction.animation.value.effect, DEFAULT_VALUES.effect); |
| 696 |
const customEffects = interaction.animation.value.custom_effect; |
| 697 |
const type = extractString(interaction.animation.value.type, DEFAULT_VALUES.type); |
| 698 |
const direction = extractString(interaction.animation.value.direction, DEFAULT_VALUES.direction); |
| 699 |
const duration = extractSize(interaction.animation.value.timing_config.value.duration); |
| 700 |
const delay = extractSize(interaction.animation.value.timing_config.value.delay); |
| 701 |
const replay = extractBoolean(interaction.animation.value.config?.value.replay, DEFAULT_VALUES.replay); |
| 702 |
const easing = extractString(interaction.animation.value.config?.value.easing, DEFAULT_VALUES.easing); |
| 703 |
const relativeTo = extractString(interaction.animation.value.config?.value.relativeTo, DEFAULT_VALUES.relativeTo); |
| 704 |
const configValue = interaction.animation.value.config?.value; |
| 705 |
const repeat = extractString(configValue?.repeat, DEFAULT_VALUES.repeat); |
| 706 |
const times = normalizeTimesValue(configValue?.times?.value, DEFAULT_VALUES.times); |
| 707 |
const start = extractSize(interaction.animation.value.config?.value.start, DEFAULT_VALUES.start); |
| 708 |
const end = extractSize(interaction.animation.value.config?.value.end, DEFAULT_VALUES.end); |
| 709 |
const interactionValues = { |
| 710 |
trigger, |
| 711 |
effect, |
| 712 |
type, |
| 713 |
direction, |
| 714 |
duration, |
| 715 |
delay, |
| 716 |
easing, |
| 717 |
replay, |
| 718 |
relativeTo, |
| 719 |
repeat, |
| 720 |
times, |
| 721 |
start, |
| 722 |
end, |
| 723 |
customEffects |
| 724 |
}; |
| 725 |
const TriggerControl = useControlComponent("trigger", true); |
| 726 |
const EffectControl = useControlComponent("effect"); |
| 727 |
const ReplayControl = useControlComponent("replay", controlVisibilityConfig.replay(interactionValues)); |
| 728 |
const RelativeToControl = useControlComponent("relativeTo", controlVisibilityConfig.relativeTo(interactionValues)); |
| 729 |
const StartControl = useControlComponent("start", controlVisibilityConfig.start(interactionValues)); |
| 730 |
const EndControl = useControlComponent("end", controlVisibilityConfig.end(interactionValues)); |
| 731 |
const CustomEffectControl = useControlComponent("customEffects", controlVisibilityConfig.custom(interactionValues)); |
| 732 |
const EffectTypeControl = useControlComponent("effectType", controlVisibilityConfig.effectType(interactionValues)); |
| 733 |
const DirectionControl = useControlComponent("direction", controlVisibilityConfig.direction(interactionValues)); |
| 734 |
const RepeatControl = useControlComponent("repeat", controlVisibilityConfig.repeat(interactionValues)); |
| 735 |
const TimesControl = useControlComponent("times", controlVisibilityConfig.times(interactionValues)); |
| 736 |
const EasingControl = useControlComponent("easing"); |
| 737 |
const updateInteraction = (updates) => { |
| 738 |
const resolvedDirectionValue = resolveDirection("direction" in updates, updates.effect, updates.direction, direction, effect); |
| 739 |
const updatedInteraction = { |
| 740 |
...interaction, |
| 741 |
interaction_id: interaction.interaction_id, |
| 742 |
trigger: createString(updates.trigger ?? trigger), |
| 743 |
animation: createAnimationPreset({ |
| 744 |
effect: updates.effect ?? effect, |
| 745 |
type: updates.type ?? type, |
| 746 |
direction: resolvedDirectionValue, |
| 747 |
duration: updates.duration ?? duration, |
| 748 |
delay: updates.delay ?? delay, |
| 749 |
replay: updates.replay ?? replay, |
| 750 |
easing: updates.easing ?? easing, |
| 751 |
relativeTo: updates.relativeTo ?? relativeTo, |
| 752 |
repeat: updates.repeat ?? repeat, |
| 753 |
times: updates.times ?? times, |
| 754 |
start: updates.start ?? start, |
| 755 |
end: updates.end ?? end, |
| 756 |
customEffects: updates.customEffects ?? customEffects |
| 757 |
}) |
| 758 |
}; |
| 759 |
onChange(updatedInteraction); |
| 760 |
syncGridOverlay(updates.trigger ?? trigger, updates.start ?? start, updates.end ?? end, updates.relativeTo ?? relativeTo); |
| 761 |
const interactionId = extractString(updatedInteraction.interaction_id); |
| 762 |
setTimeout(() => { |
| 763 |
onPlayInteraction(interactionId); |
| 764 |
}, 0); |
| 765 |
}; |
| 766 |
return /* @__PURE__ */ react.createElement(_elementor_editor_controls.PopoverContent, { p: 1.5 }, /* @__PURE__ */ react.createElement(_elementor_ui.Grid, { |
| 767 |
container: true, |
| 768 |
spacing: 1.5 |
| 769 |
}, TriggerControl && /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("Trigger", "elementor") }, /* @__PURE__ */ react.createElement(TriggerControl, { |
| 770 |
value: trigger, |
| 771 |
onChange: (v) => updateInteraction({ trigger: v }) |
| 772 |
})), ReplayControl && /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("Replay", "elementor") }, /* @__PURE__ */ react.createElement(ReplayControl, { |
| 773 |
value: replay, |
| 774 |
onChange: (v) => updateInteraction({ replay: v }), |
| 775 |
disabled: true |
| 776 |
}))), /* @__PURE__ */ react.createElement(_elementor_ui.Divider, null), /* @__PURE__ */ react.createElement(_elementor_ui.Grid, { |
| 777 |
container: true, |
| 778 |
spacing: 1.5 |
| 779 |
}, EffectControl && /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("Effect", "elementor") }, /* @__PURE__ */ react.createElement(EffectControl, { |
| 780 |
value: effect, |
| 781 |
onChange: (v) => updateInteraction({ effect: v }) |
| 782 |
})), CustomEffectControl && /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("Custom Effect", "elementor") }, /* @__PURE__ */ react.createElement(CustomEffectControl, { |
| 783 |
value: customEffects, |
| 784 |
onChange: (v) => updateInteraction({ customEffects: v }) |
| 785 |
})), EffectTypeControl && /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("Type", "elementor") }, /* @__PURE__ */ react.createElement(EffectTypeControl, { |
| 786 |
value: type, |
| 787 |
onChange: (v) => updateInteraction({ type: v }) |
| 788 |
})), DirectionControl && /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("Direction", "elementor") }, /* @__PURE__ */ react.createElement(DirectionControl, { |
| 789 |
value: direction, |
| 790 |
onChange: (v) => updateInteraction({ direction: v }), |
| 791 |
interactionType: type |
| 792 |
})), RepeatControl && /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("Repeat", "elementor") }, /* @__PURE__ */ react.createElement(RepeatControl, { |
| 793 |
value: repeat, |
| 794 |
onChange: (v) => updateInteraction({ repeat: v }) |
| 795 |
})), TimesControl && /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("Times", "elementor") }, /* @__PURE__ */ react.createElement(TimesControl, { |
| 796 |
value: times, |
| 797 |
onChange: (v) => updateInteraction({ times: normalizeTimesValue(v, DEFAULT_VALUES.times) }) |
| 798 |
})), controlVisibilityConfig.duration(interactionValues) && /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("Duration", "elementor") }, /* @__PURE__ */ react.createElement(TimeFrameIndicator, { |
| 799 |
value: String(duration), |
| 800 |
onChange: (v) => updateInteraction({ duration: v }), |
| 801 |
defaultValue: DEFAULT_VALUES.duration |
| 802 |
})), controlVisibilityConfig.delay(interactionValues) && /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("Delay", "elementor") }, /* @__PURE__ */ react.createElement(TimeFrameIndicator, { |
| 803 |
value: String(delay), |
| 804 |
onChange: (v) => updateInteraction({ delay: v }), |
| 805 |
defaultValue: DEFAULT_VALUES.delay |
| 806 |
}))), controlVisibilityConfig.relativeTo(interactionValues) && RelativeToControl && /* @__PURE__ */ react.createElement(react.Fragment, null, /* @__PURE__ */ react.createElement(_elementor_ui.Divider, null), /* @__PURE__ */ react.createElement(_elementor_ui.Grid, { |
| 807 |
container: true, |
| 808 |
spacing: 1.5 |
| 809 |
}, StartControl && /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("Start", "elementor") }, /* @__PURE__ */ react.createElement(StartControl, { |
| 810 |
value: parseSizeValue(start, ["%"]).size?.toString() ?? "", |
| 811 |
onChange: (v) => updateInteraction({ start: v }) |
| 812 |
})), EndControl && /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("End", "elementor") }, /* @__PURE__ */ react.createElement(EndControl, { |
| 813 |
value: parseSizeValue(end, ["%"]).size?.toString() ?? "", |
| 814 |
onChange: (v) => updateInteraction({ end: v }) |
| 815 |
})), /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("Relative To", "elementor") }, /* @__PURE__ */ react.createElement(RelativeToControl, { |
| 816 |
value: relativeTo, |
| 817 |
onChange: (v) => updateInteraction({ relativeTo: v }) |
| 818 |
}))), /* @__PURE__ */ react.createElement(_elementor_ui.Divider, null)), EasingControl && /* @__PURE__ */ react.createElement(_elementor_ui.Grid, { |
| 819 |
container: true, |
| 820 |
spacing: 1.5 |
| 821 |
}, /* @__PURE__ */ react.createElement(Field, { label: (0, _wordpress_i18n.__)("Easing", "elementor") }, /* @__PURE__ */ react.createElement(EasingControl, { |
| 822 |
value: easing, |
| 823 |
onChange: (v) => { |
| 824 |
updateInteraction({ easing: v }); |
| 825 |
} |
| 826 |
})))); |
| 827 |
}; |
| 828 |
|
| 829 |
//#endregion |
| 830 |
//#region packages/packages/core/editor-interactions/src/components/interaction-settings.tsx |
| 831 |
var SIZE = "tiny"; |
| 832 |
var InteractionSettings = ({ interaction, onChange }) => { |
| 833 |
const breakpoints = (0, _elementor_editor_responsive.useBreakpoints)(); |
| 834 |
const availableBreakpoints = (0, react.useMemo)(() => breakpoints.map((breakpoint) => ({ |
| 835 |
label: breakpoint.label, |
| 836 |
value: String(breakpoint.id) |
| 837 |
})), [breakpoints]); |
| 838 |
const [selectedBreakpoints, setSelectedBreakpoints] = (0, react.useState)(() => { |
| 839 |
const excluded = extractExcludedBreakpoints(interaction.breakpoints).filter((excludedBreakpoint) => { |
| 840 |
return availableBreakpoints.some(({ value }) => value === excludedBreakpoint); |
| 841 |
}); |
| 842 |
return availableBreakpoints.filter(({ value }) => { |
| 843 |
return !excluded.includes(value); |
| 844 |
}); |
| 845 |
}); |
| 846 |
const handleBreakpointChange = (0, react.useCallback)((_, newValue) => { |
| 847 |
setSelectedBreakpoints(newValue); |
| 848 |
const selectedValues = newValue.map((option) => option.value); |
| 849 |
const newExcluded = availableBreakpoints.filter((breakpoint) => !selectedValues.includes(breakpoint.value)).map((breakpoint) => breakpoint.value); |
| 850 |
const updatedInteraction = { |
| 851 |
...interaction, |
| 852 |
...newExcluded.length > 0 && { breakpoints: createInteractionBreakpoints(newExcluded) } |
| 853 |
}; |
| 854 |
if (newExcluded.length === 0) delete updatedInteraction.breakpoints; |
| 855 |
onChange(updatedInteraction); |
| 856 |
}, [ |
| 857 |
interaction, |
| 858 |
availableBreakpoints, |
| 859 |
onChange |
| 860 |
]); |
| 861 |
return /* @__PURE__ */ react.createElement(_elementor_editor_controls.PopoverContent, { p: 1.5 }, /* @__PURE__ */ react.createElement(_elementor_ui.Grid, { |
| 862 |
container: true, |
| 863 |
spacing: 1.5 |
| 864 |
}, /* @__PURE__ */ react.createElement(_elementor_ui.Grid, { |
| 865 |
item: true, |
| 866 |
xs: 12 |
| 867 |
}, /* @__PURE__ */ react.createElement(_elementor_ui.Stack, { |
| 868 |
direction: "column", |
| 869 |
gap: 1 |
| 870 |
}, /* @__PURE__ */ react.createElement(_elementor_editor_controls.ControlFormLabel, { sx: { width: "100%" } }, (0, _wordpress_i18n.__)("Trigger on", "elementor")), /* @__PURE__ */ react.createElement(_elementor_ui.Autocomplete, { |
| 871 |
fullWidth: true, |
| 872 |
multiple: true, |
| 873 |
value: selectedBreakpoints, |
| 874 |
onChange: handleBreakpointChange, |
| 875 |
size: SIZE, |
| 876 |
options: availableBreakpoints, |
| 877 |
isOptionEqualToValue: (option, value) => option.value === value.value, |
| 878 |
renderInput: (params) => /* @__PURE__ */ react.createElement(_elementor_ui.TextField, { ...params }), |
| 879 |
renderTags: (values, getTagProps) => values.map((option, index) => { |
| 880 |
const { key, ...chipProps } = getTagProps({ index }); |
| 881 |
return /* @__PURE__ */ react.createElement(_elementor_ui.Chip, { |
| 882 |
key, |
| 883 |
size: SIZE, |
| 884 |
label: option.label, |
| 885 |
...chipProps |
| 886 |
}); |
| 887 |
}) |
| 888 |
}))))); |
| 889 |
}; |
| 890 |
|
| 891 |
//#endregion |
| 892 |
//#region packages/packages/core/editor-interactions/src/components/interactions-list-item.tsx |
| 893 |
var InteractionsListItem = ({ index, value: interaction }) => { |
| 894 |
const { getTabsProps, getTabProps, getTabPanelProps } = (0, _elementor_ui.useTabs)("details"); |
| 895 |
const context = useInteractionItemContext(); |
| 896 |
const handleChange = (0, react.useCallback)((newInteractionValue) => { |
| 897 |
context?.onInteractionChange(index, newInteractionValue); |
| 898 |
}, [context, index]); |
| 899 |
const handlePlayInteraction = (0, react.useCallback)((interactionId2) => { |
| 900 |
context?.onPlayInteraction(interactionId2); |
| 901 |
}, [context]); |
| 902 |
const interactionId = extractString(interaction.value.interaction_id); |
| 903 |
return /* @__PURE__ */ react.createElement(react.Fragment, null, /* @__PURE__ */ react.createElement(_elementor_ui.Tabs, { |
| 904 |
size: "small", |
| 905 |
variant: "fullWidth", |
| 906 |
"aria-label": (0, _wordpress_i18n.__)("Interaction", "elementor"), |
| 907 |
...getTabsProps() |
| 908 |
}, /* @__PURE__ */ react.createElement(_elementor_ui.Tab, { |
| 909 |
label: (0, _wordpress_i18n.__)("Details", "elementor"), |
| 910 |
...getTabProps("details") |
| 911 |
}), /* @__PURE__ */ react.createElement(_elementor_ui.Tab, { |
| 912 |
label: (0, _wordpress_i18n.__)("Settings", "elementor"), |
| 913 |
...getTabProps("settings") |
| 914 |
})), /* @__PURE__ */ react.createElement(_elementor_ui.Divider, null), /* @__PURE__ */ react.createElement(_elementor_ui.TabPanel, { |
| 915 |
sx: { p: 0 }, |
| 916 |
...getTabPanelProps("details") |
| 917 |
}, /* @__PURE__ */ react.createElement(InteractionDetails, { |
| 918 |
key: interactionId, |
| 919 |
interaction: interaction.value, |
| 920 |
onChange: handleChange, |
| 921 |
onPlayInteraction: handlePlayInteraction |
| 922 |
})), /* @__PURE__ */ react.createElement(_elementor_ui.TabPanel, { |
| 923 |
sx: { p: 0 }, |
| 924 |
...getTabPanelProps("settings") |
| 925 |
}, /* @__PURE__ */ react.createElement(InteractionSettings, { |
| 926 |
key: interactionId, |
| 927 |
interaction: interaction.value, |
| 928 |
onChange: handleChange |
| 929 |
}))); |
| 930 |
}; |
| 931 |
|
| 932 |
//#endregion |
| 933 |
//#region packages/packages/core/editor-interactions/src/components/interactions-list.tsx |
| 934 |
var MAX_NUMBER_OF_INTERACTIONS = 5; |
| 935 |
function InteractionsList(props) { |
| 936 |
const { interactions, onSelectInteractions, onPlayInteraction, triggerCreateOnShowEmpty } = props; |
| 937 |
const { elementId } = useInteractionsContext(); |
| 938 |
const hasInitializedRef = (0, react.useRef)(false); |
| 939 |
const newlyCreatedIdsRef = (0, react.useRef)(/* @__PURE__ */ new Set()); |
| 940 |
const handleUpdateInteractions = (0, react.useCallback)((newInteractions) => { |
| 941 |
onSelectInteractions(newInteractions); |
| 942 |
}, [onSelectInteractions]); |
| 943 |
(0, react.useEffect)(() => { |
| 944 |
if (triggerCreateOnShowEmpty && !hasInitializedRef.current && (!interactions.items || interactions.items?.length === 0)) { |
| 945 |
hasInitializedRef.current = true; |
| 946 |
const newItem = createDefaultInteractionItem(); |
| 947 |
newlyCreatedIdsRef.current.add(extractString(newItem.value.interaction_id)); |
| 948 |
handleUpdateInteractions({ |
| 949 |
version: 1, |
| 950 |
items: [newItem] |
| 951 |
}); |
| 952 |
} |
| 953 |
}, [ |
| 954 |
triggerCreateOnShowEmpty, |
| 955 |
interactions.items, |
| 956 |
handleUpdateInteractions |
| 957 |
]); |
| 958 |
const isMaxNumberOfInteractionsReached = (0, react.useMemo)(() => { |
| 959 |
return interactions.items?.length >= 5; |
| 960 |
}, [interactions.items?.length]); |
| 961 |
const infotipContent = isMaxNumberOfInteractionsReached ? /* @__PURE__ */ react.createElement(_elementor_ui.Alert, { |
| 962 |
color: "secondary", |
| 963 |
icon: /* @__PURE__ */ react.createElement(_elementor_icons.InfoCircleFilledIcon, null), |
| 964 |
size: "small" |
| 965 |
}, /* @__PURE__ */ react.createElement(_elementor_ui.AlertTitle, null, (0, _wordpress_i18n.__)("Interactions", "elementor")), /* @__PURE__ */ react.createElement(_elementor_ui.Box, { component: "span" }, (0, _wordpress_i18n.__)("You've reached the limit of 5 interactions for this element. Please remove an interaction before creating a new one.", "elementor"))) : void 0; |
| 966 |
const handleRepeaterChange = (0, react.useCallback)((newItems, _, meta) => { |
| 967 |
handleUpdateInteractions({ |
| 968 |
...interactions, |
| 969 |
items: newItems |
| 970 |
}); |
| 971 |
if (meta?.action?.type === "add") { |
| 972 |
const addedItem = meta.action.payload[0]?.item; |
| 973 |
if (addedItem) newlyCreatedIdsRef.current.add(extractString(addedItem.value.interaction_id)); |
| 974 |
} |
| 975 |
}, [interactions, handleUpdateInteractions]); |
| 976 |
const handleInteractionChange = (0, react.useCallback)((index, newInteractionValue) => { |
| 977 |
const newItems = structuredClone(interactions.items); |
| 978 |
newItems[index] = { |
| 979 |
$$type: "interaction-item", |
| 980 |
value: newInteractionValue |
| 981 |
}; |
| 982 |
handleUpdateInteractions({ |
| 983 |
...interactions, |
| 984 |
items: newItems |
| 985 |
}); |
| 986 |
}, [interactions, handleUpdateInteractions]); |
| 987 |
const contextValue = (0, react.useMemo)(() => ({ |
| 988 |
onInteractionChange: handleInteractionChange, |
| 989 |
onPlayInteraction |
| 990 |
}), [handleInteractionChange, onPlayInteraction]); |
| 991 |
return /* @__PURE__ */ react.createElement(InteractionItemContextProvider, { value: contextValue }, /* @__PURE__ */ react.createElement(_elementor_editor_controls.Repeater, { |
| 992 |
openOnAdd: true, |
| 993 |
openItem: triggerCreateOnShowEmpty ? 0 : void 0, |
| 994 |
label: (0, _wordpress_i18n.__)("Interactions", "elementor"), |
| 995 |
values: interactions.items, |
| 996 |
setValues: handleRepeaterChange, |
| 997 |
showDuplicate: false, |
| 998 |
showToggle: false, |
| 999 |
isSortable: false, |
| 1000 |
disableAddItemButton: isMaxNumberOfInteractionsReached, |
| 1001 |
addButtonInfotipContent: infotipContent, |
| 1002 |
itemSettings: { |
| 1003 |
initialValues: createDefaultInteractionItem(), |
| 1004 |
Label: ({ value }) => buildDisplayLabel(value.value), |
| 1005 |
Icon: () => null, |
| 1006 |
Content: InteractionsListItem, |
| 1007 |
onPopoverOpen: (value) => { |
| 1008 |
const { trigger, start, end, relativeTo } = extractScrollOverlayParams(value.value, DEFAULT_VALUES); |
| 1009 |
syncGridOverlay(trigger, start, end, relativeTo); |
| 1010 |
}, |
| 1011 |
onPopoverClose: (value) => { |
| 1012 |
dispatchScrollInteraction(null); |
| 1013 |
const id = extractString(value.value.interaction_id); |
| 1014 |
if (newlyCreatedIdsRef.current.has(id)) { |
| 1015 |
newlyCreatedIdsRef.current.delete(id); |
| 1016 |
trackInteractionCreated(elementId, value); |
| 1017 |
} |
| 1018 |
}, |
| 1019 |
actions: (value) => /* @__PURE__ */ react.createElement(_elementor_ui.Tooltip, { |
| 1020 |
key: "preview", |
| 1021 |
placement: "top", |
| 1022 |
title: (0, _wordpress_i18n.__)("Preview", "elementor") |
| 1023 |
}, /* @__PURE__ */ react.createElement(_elementor_ui.IconButton, { |
| 1024 |
"aria-label": (0, _wordpress_i18n.__)("Play interaction", "elementor"), |
| 1025 |
size: "tiny", |
| 1026 |
onClick: () => onPlayInteraction(extractString(value.value.interaction_id)) |
| 1027 |
}, /* @__PURE__ */ react.createElement(_elementor_icons.PlayerPlayIcon, { fontSize: "tiny" }))) |
| 1028 |
} |
| 1029 |
})); |
| 1030 |
} |
| 1031 |
|
| 1032 |
//#endregion |
| 1033 |
//#region packages/packages/core/editor-interactions/src/components/interactions-tab.tsx |
| 1034 |
var InteractionsTab = ({ elementId }) => { |
| 1035 |
return /* @__PURE__ */ react.createElement(PopupStateProvider, null, /* @__PURE__ */ react.createElement(InteractionsTabContent, { elementId })); |
| 1036 |
}; |
| 1037 |
function InteractionsTabContent({ elementId }) { |
| 1038 |
const existingInteractions = useElementInteractions(elementId); |
| 1039 |
const firstInteractionState = (0, react.useState)(false); |
| 1040 |
const hasInteractions = existingInteractions?.items?.length || firstInteractionState[0]; |
| 1041 |
return /* @__PURE__ */ react.createElement(_elementor_session.SessionStorageProvider, { prefix: elementId }, hasInteractions ? /* @__PURE__ */ react.createElement(InteractionsProvider, { elementId }, /* @__PURE__ */ react.createElement(InteractionsContent, { firstInteractionState })) : /* @__PURE__ */ react.createElement(EmptyState, { onCreateInteraction: () => { |
| 1042 |
firstInteractionState[1](true); |
| 1043 |
} })); |
| 1044 |
} |
| 1045 |
function InteractionsContent({ firstInteractionState }) { |
| 1046 |
const { interactions, setInteractions, playInteractions } = useInteractionsContext(); |
| 1047 |
const applyInteraction = (0, react.useCallback)((newInteractions) => { |
| 1048 |
firstInteractionState[1](false); |
| 1049 |
if (!newInteractions) { |
| 1050 |
setInteractions(void 0); |
| 1051 |
return; |
| 1052 |
} |
| 1053 |
setInteractions(newInteractions); |
| 1054 |
}, [setInteractions, firstInteractionState]); |
| 1055 |
return /* @__PURE__ */ react.createElement(_elementor_ui.Stack, { |
| 1056 |
sx: { |
| 1057 |
m: 1, |
| 1058 |
p: 1.5 |
| 1059 |
}, |
| 1060 |
gap: 2 |
| 1061 |
}, /* @__PURE__ */ react.createElement(InteractionsList, { |
| 1062 |
triggerCreateOnShowEmpty: firstInteractionState[0], |
| 1063 |
interactions, |
| 1064 |
onSelectInteractions: applyInteraction, |
| 1065 |
onPlayInteraction: playInteractions |
| 1066 |
})); |
| 1067 |
} |
| 1068 |
|
| 1069 |
//#endregion |
| 1070 |
//#region packages/packages/core/editor-interactions/src/utils/create-interactions-repository.ts |
| 1071 |
var createInteractionsRepository = () => { |
| 1072 |
const providers = []; |
| 1073 |
const getProviders = () => { |
| 1074 |
return providers.slice(0).sort((a, b) => a.priority > b.priority ? -1 : 1); |
| 1075 |
}; |
| 1076 |
const register = (provider) => { |
| 1077 |
providers.push(provider); |
| 1078 |
}; |
| 1079 |
const all = () => { |
| 1080 |
return getProviders().flatMap((provider) => provider.actions.all()); |
| 1081 |
}; |
| 1082 |
const subscribe = (cb) => { |
| 1083 |
const unsubscribes = providers.map((provider) => provider.subscribe(cb)); |
| 1084 |
return () => { |
| 1085 |
unsubscribes.forEach((unsubscribe) => unsubscribe()); |
| 1086 |
}; |
| 1087 |
}; |
| 1088 |
const getProviderByKey = (key) => { |
| 1089 |
return providers.find((provider) => { |
| 1090 |
try { |
| 1091 |
return provider.getKey() === key; |
| 1092 |
} catch { |
| 1093 |
return false; |
| 1094 |
} |
| 1095 |
}); |
| 1096 |
}; |
| 1097 |
return { |
| 1098 |
all, |
| 1099 |
register, |
| 1100 |
subscribe, |
| 1101 |
getProviders, |
| 1102 |
getProviderByKey |
| 1103 |
}; |
| 1104 |
}; |
| 1105 |
|
| 1106 |
//#endregion |
| 1107 |
//#region packages/packages/core/editor-interactions/src/interactions-repository.ts |
| 1108 |
var interactionsRepository = createInteractionsRepository(); |
| 1109 |
|
| 1110 |
//#endregion |
| 1111 |
//#region packages/packages/core/editor-interactions/src/utils/create-interactions-provider.ts |
| 1112 |
var DEFAULT_PRIORITY = 10; |
| 1113 |
function createInteractionsProvider({ key, priority = DEFAULT_PRIORITY, subscribe = () => () => {}, actions }) { |
| 1114 |
return { |
| 1115 |
getKey: typeof key === "string" ? () => key : key, |
| 1116 |
priority, |
| 1117 |
subscribe, |
| 1118 |
actions: { all: actions.all } |
| 1119 |
}; |
| 1120 |
} |
| 1121 |
|
| 1122 |
//#endregion |
| 1123 |
//#region packages/packages/core/editor-interactions/src/providers/document-elements-interactions-provider.ts |
| 1124 |
var ELEMENTS_INTERACTIONS_PROVIDER_KEY_PREFIX = "document-elements-interactions-"; |
| 1125 |
var documentElementsInteractionsProvider = createInteractionsProvider({ |
| 1126 |
key: () => { |
| 1127 |
const documentId = (0, _elementor_editor_elements.getCurrentDocumentId)(); |
| 1128 |
if (!documentId) return `${ELEMENTS_INTERACTIONS_PROVIDER_KEY_PREFIX}pending`; |
| 1129 |
return `${ELEMENTS_INTERACTIONS_PROVIDER_KEY_PREFIX}${documentId}`; |
| 1130 |
}, |
| 1131 |
priority: 50, |
| 1132 |
subscribe: (cb) => { |
| 1133 |
return (0, _elementor_editor_v1_adapters.__privateListenTo)([(0, _elementor_editor_v1_adapters.windowEvent)("elementor/element/update_interactions")], () => cb()); |
| 1134 |
}, |
| 1135 |
actions: { all: () => { |
| 1136 |
return (0, _elementor_editor_elements.getElements)().filter((element) => { |
| 1137 |
const interactions = (0, _elementor_editor_elements.getElementInteractions)(element.id); |
| 1138 |
if (!interactions) return false; |
| 1139 |
return interactions?.items?.length > 0; |
| 1140 |
}).map((element) => { |
| 1141 |
const interactions = (0, _elementor_editor_elements.getElementInteractions)(element.id); |
| 1142 |
return { |
| 1143 |
elementId: element.id, |
| 1144 |
dataId: element.id, |
| 1145 |
interactions: interactions || { |
| 1146 |
version: 1, |
| 1147 |
items: [] |
| 1148 |
} |
| 1149 |
}; |
| 1150 |
}); |
| 1151 |
} } |
| 1152 |
}); |
| 1153 |
|
| 1154 |
//#endregion |
| 1155 |
//#region packages/packages/core/editor-interactions/src/commands/get-clipboard-elements.ts |
| 1156 |
function getClipboardElements(storageKey = "clipboard") { |
| 1157 |
try { |
| 1158 |
return JSON.parse(localStorage.getItem("elementor") ?? "{}")[storageKey]?.elements; |
| 1159 |
} catch { |
| 1160 |
return; |
| 1161 |
} |
| 1162 |
} |
| 1163 |
|
| 1164 |
//#endregion |
| 1165 |
//#region packages/packages/core/editor-interactions/src/commands/paste-interactions.ts |
| 1166 |
function isAtomicContainer(container) { |
| 1167 |
const type = container?.model.get("widgetType") || container?.model.get("elType"); |
| 1168 |
const elementConfig = (0, _elementor_editor_elements.getWidgetsCache)()?.[type]; |
| 1169 |
return Boolean(elementConfig?.atomic_props_schema); |
| 1170 |
} |
| 1171 |
function getTitleForContainers(containers) { |
| 1172 |
return containers.length > 1 ? (0, _wordpress_i18n.__)("Elements", "elementor") : (0, _elementor_editor_elements.getElementLabel)(containers[0].id); |
| 1173 |
} |
| 1174 |
function normalizeClipboardInteractions(raw) { |
| 1175 |
if (!raw) return null; |
| 1176 |
const parsed = typeof raw === "string" ? JSON.parse(raw) : raw; |
| 1177 |
const payload = { |
| 1178 |
version: parsed?.version ?? 1, |
| 1179 |
items: parsed?.items?.filter((item) => isSupportedInteractionItem(item)) ?? [] |
| 1180 |
}; |
| 1181 |
if (!payload.items.length) return null; |
| 1182 |
return payload; |
| 1183 |
} |
| 1184 |
function regenerateInteractionIds(interactions) { |
| 1185 |
const cloned = structuredClone(interactions); |
| 1186 |
cloned.items?.forEach((item) => { |
| 1187 |
if (item.$$type === "interaction-item" && item.value) item.value.interaction_id = createString(generateTempInteractionId()); |
| 1188 |
}); |
| 1189 |
return cloned; |
| 1190 |
} |
| 1191 |
function initPasteInteractionsCommand() { |
| 1192 |
const undoablePasteInteractions = (0, _elementor_editor_v1_adapters.undoable)({ |
| 1193 |
do: ({ containers, newInteractions }) => { |
| 1194 |
const pasted = regenerateInteractionIds(newInteractions); |
| 1195 |
return containers.map((container) => { |
| 1196 |
const elementId = container.id; |
| 1197 |
const previous = (0, _elementor_editor_elements.getElementInteractions)(elementId); |
| 1198 |
(0, _elementor_editor_elements.updateElementInteractions)({ |
| 1199 |
elementId, |
| 1200 |
interactions: pasted |
| 1201 |
}); |
| 1202 |
return { |
| 1203 |
elementId, |
| 1204 |
previous: previous ?? { |
| 1205 |
version: 1, |
| 1206 |
items: [] |
| 1207 |
} |
| 1208 |
}; |
| 1209 |
}); |
| 1210 |
}, |
| 1211 |
undo: (_, revertData) => { |
| 1212 |
revertData.forEach(({ elementId, previous }) => { |
| 1213 |
(0, _elementor_editor_elements.updateElementInteractions)({ |
| 1214 |
elementId, |
| 1215 |
interactions: previous.items?.length ? previous : void 0 |
| 1216 |
}); |
| 1217 |
}); |
| 1218 |
} |
| 1219 |
}, { |
| 1220 |
title: ({ containers }) => getTitleForContainers(containers), |
| 1221 |
subtitle: (0, _wordpress_i18n.__)("Interactions Pasted", "elementor") |
| 1222 |
}); |
| 1223 |
(0, _elementor_editor_v1_adapters.__privateListenTo)((0, _elementor_editor_v1_adapters.commandStartEvent)("document/elements/paste-interactions"), (e) => { |
| 1224 |
const args = e.args; |
| 1225 |
const containers = args.containers ?? (args.container ? [args.container] : []); |
| 1226 |
const storageKey = args.storageKey ?? "clipboard"; |
| 1227 |
if (!containers.length) return; |
| 1228 |
const [clipboardElement] = getClipboardElements(storageKey) ?? []; |
| 1229 |
if (!clipboardElement) return; |
| 1230 |
const newInteractions = normalizeClipboardInteractions(clipboardElement.interactions); |
| 1231 |
if (!newInteractions) return; |
| 1232 |
const validContainers = containers.filter((c) => (0, _elementor_editor_elements.getContainer)(c.id)).filter(isAtomicContainer); |
| 1233 |
if (!validContainers.length) return; |
| 1234 |
undoablePasteInteractions({ |
| 1235 |
containers: validContainers, |
| 1236 |
newInteractions |
| 1237 |
}); |
| 1238 |
}); |
| 1239 |
} |
| 1240 |
|
| 1241 |
//#endregion |
| 1242 |
//#region packages/packages/core/editor-interactions/src/components/controls/direction.tsx |
| 1243 |
var AXIS = { |
| 1244 |
top: "vertical", |
| 1245 |
bottom: "vertical", |
| 1246 |
left: "horizontal", |
| 1247 |
right: "horizontal" |
| 1248 |
}; |
| 1249 |
function parseValue(value) { |
| 1250 |
return value.split("-").filter(Boolean); |
| 1251 |
} |
| 1252 |
function serializeValue(directions) { |
| 1253 |
const vertical = directions.find((d) => d === "top" || d === "bottom"); |
| 1254 |
const horizontal = directions.find((d) => d === "left" || d === "right"); |
| 1255 |
if (vertical && horizontal) return `${vertical}-${horizontal}`; |
| 1256 |
return directions[0] ?? ""; |
| 1257 |
} |
| 1258 |
function toggleDirection(current, clicked) { |
| 1259 |
if (current.includes(clicked)) return current.filter((d) => d !== clicked); |
| 1260 |
return [...current.filter((d) => AXIS[d] !== AXIS[clicked]), clicked]; |
| 1261 |
} |
| 1262 |
function Direction({ value, onChange, interactionType }) { |
| 1263 |
const isIn = interactionType === "in"; |
| 1264 |
const options = (0, react.useMemo)(() => [ |
| 1265 |
{ |
| 1266 |
dir: "top", |
| 1267 |
label: isIn ? (0, _wordpress_i18n.__)("From top", "elementor") : (0, _wordpress_i18n.__)("To top", "elementor"), |
| 1268 |
Icon: isIn ? _elementor_icons.ArrowDownSmallIcon : _elementor_icons.ArrowUpSmallIcon |
| 1269 |
}, |
| 1270 |
{ |
| 1271 |
dir: "bottom", |
| 1272 |
label: isIn ? (0, _wordpress_i18n.__)("From bottom", "elementor") : (0, _wordpress_i18n.__)("To bottom", "elementor"), |
| 1273 |
Icon: isIn ? _elementor_icons.ArrowUpSmallIcon : _elementor_icons.ArrowDownSmallIcon |
| 1274 |
}, |
| 1275 |
{ |
| 1276 |
dir: "left", |
| 1277 |
label: isIn ? (0, _wordpress_i18n.__)("From left", "elementor") : (0, _wordpress_i18n.__)("To left", "elementor"), |
| 1278 |
Icon: isIn ? _elementor_icons.ArrowRightIcon : _elementor_icons.ArrowLeftIcon |
| 1279 |
}, |
| 1280 |
{ |
| 1281 |
dir: "right", |
| 1282 |
label: isIn ? (0, _wordpress_i18n.__)("From right", "elementor") : (0, _wordpress_i18n.__)("To right", "elementor"), |
| 1283 |
Icon: isIn ? _elementor_icons.ArrowLeftIcon : _elementor_icons.ArrowRightIcon |
| 1284 |
} |
| 1285 |
], [isIn]); |
| 1286 |
const selectedDirections = (0, react.useMemo)(() => parseValue(value), [value]); |
| 1287 |
return /* @__PURE__ */ react.createElement(_elementor_editor_controls.StyledToggleButtonGroup, { |
| 1288 |
size: "tiny", |
| 1289 |
justify: "end", |
| 1290 |
sx: { |
| 1291 |
display: "grid", |
| 1292 |
gridTemplateColumns: "repeat(4, minmax(0, 25%))", |
| 1293 |
width: "100%" |
| 1294 |
} |
| 1295 |
}, options.map(({ dir, label, Icon }) => /* @__PURE__ */ react.createElement(_elementor_ui.Tooltip, { |
| 1296 |
key: dir, |
| 1297 |
title: label, |
| 1298 |
disableFocusListener: true, |
| 1299 |
placement: "top" |
| 1300 |
}, /* @__PURE__ */ react.createElement(_elementor_editor_controls.StyledToggleButton, { |
| 1301 |
value: dir, |
| 1302 |
selected: selectedDirections.includes(dir), |
| 1303 |
"aria-label": label, |
| 1304 |
size: "tiny", |
| 1305 |
isPlaceholder: false, |
| 1306 |
onChange: () => { |
| 1307 |
onChange(serializeValue(toggleDirection(selectedDirections, dir))); |
| 1308 |
} |
| 1309 |
}, /* @__PURE__ */ react.createElement(Icon, { fontSize: "tiny" }))))); |
| 1310 |
} |
| 1311 |
|
| 1312 |
//#endregion |
| 1313 |
//#region packages/packages/core/editor-interactions/src/ui/interactions-promotion-chip.tsx |
| 1314 |
var InteractionsPromotionChip = (0, react.forwardRef)(({ content, upgradeUrl, anchorRef, trackingData }, ref) => { |
| 1315 |
const [isOpen, setIsOpen] = (0, react.useState)(false); |
| 1316 |
(0, _elementor_editor_ui.useCanvasClickHandler)(isOpen, () => setIsOpen(false)); |
| 1317 |
const toggle = (0, react.useCallback)(() => { |
| 1318 |
setIsOpen((prev) => { |
| 1319 |
if (!prev) (0, _elementor_editor_controls.trackViewPromotion)(trackingData); |
| 1320 |
return !prev; |
| 1321 |
}); |
| 1322 |
}, [trackingData]); |
| 1323 |
(0, react.useImperativeHandle)(ref, () => ({ toggle }), [toggle]); |
| 1324 |
const handleToggle = (e) => { |
| 1325 |
e.stopPropagation(); |
| 1326 |
toggle(); |
| 1327 |
}; |
| 1328 |
return /* @__PURE__ */ react.createElement(_elementor_editor_ui.PromotionPopover, { |
| 1329 |
open: isOpen, |
| 1330 |
title: (0, _wordpress_i18n.__)("Interactions", "elementor"), |
| 1331 |
content, |
| 1332 |
ctaText: (0, _wordpress_i18n.__)("Upgrade now", "elementor"), |
| 1333 |
ctaUrl: upgradeUrl, |
| 1334 |
anchorRef, |
| 1335 |
placement: anchorRef ? "right-start" : void 0, |
| 1336 |
onClose: (e) => { |
| 1337 |
e.stopPropagation(); |
| 1338 |
setIsOpen(false); |
| 1339 |
}, |
| 1340 |
onCtaClick: () => (0, _elementor_editor_controls.trackUpgradePromotionClick)(trackingData) |
| 1341 |
}, /* @__PURE__ */ react.createElement(_elementor_ui.Box, { |
| 1342 |
onMouseDown: (e) => e.stopPropagation(), |
| 1343 |
onClick: handleToggle, |
| 1344 |
sx: { |
| 1345 |
cursor: "pointer", |
| 1346 |
display: "inline-flex", |
| 1347 |
mr: 1 |
| 1348 |
} |
| 1349 |
}, /* @__PURE__ */ react.createElement(_elementor_editor_ui.PromotionChip, null))); |
| 1350 |
}); |
| 1351 |
|
| 1352 |
//#endregion |
| 1353 |
//#region packages/packages/core/editor-interactions/src/ui/promotion-select.tsx |
| 1354 |
function PromotionSelect({ value, onChange, baseOptions, disabledOptions, promotionLabel, promotionContent, upgradeUrl, trackingData }) { |
| 1355 |
const promotionRef = (0, react.useRef)(null); |
| 1356 |
const anchorRef = (0, react.useRef)(null); |
| 1357 |
return /* @__PURE__ */ react.createElement(_elementor_ui.Select, { |
| 1358 |
value, |
| 1359 |
onChange: (e) => onChange?.(e.target.value), |
| 1360 |
fullWidth: true, |
| 1361 |
displayEmpty: true, |
| 1362 |
size: "tiny", |
| 1363 |
MenuProps: { disablePortal: true } |
| 1364 |
}, Object.entries(baseOptions).map(([key, label]) => /* @__PURE__ */ react.createElement(_elementor_editor_ui.MenuListItem, { |
| 1365 |
key, |
| 1366 |
value: key |
| 1367 |
}, label)), /* @__PURE__ */ react.createElement(_elementor_ui.MenuSubheader, { |
| 1368 |
ref: anchorRef, |
| 1369 |
sx: { |
| 1370 |
cursor: "pointer", |
| 1371 |
color: "text.tertiary", |
| 1372 |
fontWeight: "400", |
| 1373 |
display: "flex", |
| 1374 |
alignItems: "center" |
| 1375 |
}, |
| 1376 |
onMouseDown: (e) => { |
| 1377 |
e.stopPropagation(); |
| 1378 |
promotionRef.current?.toggle(); |
| 1379 |
} |
| 1380 |
}, promotionLabel ?? (0, _wordpress_i18n.__)("PRO features", "elementor"), /* @__PURE__ */ react.createElement(InteractionsPromotionChip, { |
| 1381 |
content: promotionContent, |
| 1382 |
upgradeUrl, |
| 1383 |
ref: promotionRef, |
| 1384 |
anchorRef, |
| 1385 |
trackingData |
| 1386 |
})), Object.entries(disabledOptions).map(([key, label]) => /* @__PURE__ */ react.createElement(_elementor_editor_ui.MenuListItem, { |
| 1387 |
key, |
| 1388 |
value: key, |
| 1389 |
disabled: true, |
| 1390 |
sx: { pl: 3 } |
| 1391 |
}, label))); |
| 1392 |
} |
| 1393 |
|
| 1394 |
//#endregion |
| 1395 |
//#region packages/packages/core/editor-interactions/src/components/controls/easing.tsx |
| 1396 |
var TRACKING_DATA$4 = { |
| 1397 |
target_name: "interactions_easing", |
| 1398 |
location_l2: "interactions" |
| 1399 |
}; |
| 1400 |
var EASING_OPTIONS = { |
| 1401 |
easeIn: (0, _wordpress_i18n.__)("Ease In", "elementor"), |
| 1402 |
easeInOut: (0, _wordpress_i18n.__)("Ease In Out", "elementor"), |
| 1403 |
easeOut: (0, _wordpress_i18n.__)("Ease Out", "elementor"), |
| 1404 |
backIn: (0, _wordpress_i18n.__)("Back In", "elementor"), |
| 1405 |
backInOut: (0, _wordpress_i18n.__)("Back In Out", "elementor"), |
| 1406 |
backOut: (0, _wordpress_i18n.__)("Back Out", "elementor"), |
| 1407 |
linear: (0, _wordpress_i18n.__)("Linear", "elementor") |
| 1408 |
}; |
| 1409 |
var BASE_EASINGS = ["easeIn"]; |
| 1410 |
function Easing({}) { |
| 1411 |
const baseOptions = Object.fromEntries(Object.entries(EASING_OPTIONS).filter(([key]) => BASE_EASINGS.includes(key))); |
| 1412 |
const disabledOptions = Object.fromEntries(Object.entries(EASING_OPTIONS).filter(([key]) => !BASE_EASINGS.includes(key))); |
| 1413 |
return /* @__PURE__ */ react.createElement(PromotionSelect, { |
| 1414 |
value: DEFAULT_VALUES.easing, |
| 1415 |
baseOptions, |
| 1416 |
disabledOptions, |
| 1417 |
promotionContent: (0, _wordpress_i18n.__)("Upgrade to control the smoothness of the interaction.", "elementor"), |
| 1418 |
upgradeUrl: "https://go.elementor.com/go-pro-interactions-easing-modal/", |
| 1419 |
trackingData: TRACKING_DATA$4 |
| 1420 |
}); |
| 1421 |
} |
| 1422 |
|
| 1423 |
//#endregion |
| 1424 |
//#region packages/packages/core/editor-interactions/src/components/controls/effect.tsx |
| 1425 |
var TRACKING_DATA$3 = { |
| 1426 |
target_name: "interactions_effect", |
| 1427 |
location_l2: "interactions" |
| 1428 |
}; |
| 1429 |
var EFFECT_OPTIONS = { |
| 1430 |
fade: (0, _wordpress_i18n.__)("Fade", "elementor"), |
| 1431 |
slide: (0, _wordpress_i18n.__)("Slide", "elementor"), |
| 1432 |
scale: (0, _wordpress_i18n.__)("Scale", "elementor"), |
| 1433 |
custom: (0, _wordpress_i18n.__)("Custom", "elementor") |
| 1434 |
}; |
| 1435 |
var BASE_EFFECTS = [ |
| 1436 |
"fade", |
| 1437 |
"slide", |
| 1438 |
"scale" |
| 1439 |
]; |
| 1440 |
function Effect({ value, onChange }) { |
| 1441 |
const baseOptions = Object.fromEntries(Object.entries(EFFECT_OPTIONS).filter(([key]) => BASE_EFFECTS.includes(key))); |
| 1442 |
const disabledOptions = Object.fromEntries(Object.entries(EFFECT_OPTIONS).filter(([key]) => !BASE_EFFECTS.includes(key))); |
| 1443 |
return /* @__PURE__ */ react.createElement(PromotionSelect, { |
| 1444 |
value: value in baseOptions ? value : DEFAULT_VALUES.effect, |
| 1445 |
onChange, |
| 1446 |
baseOptions, |
| 1447 |
disabledOptions, |
| 1448 |
promotionLabel: (0, _wordpress_i18n.__)("PRO effects", "elementor"), |
| 1449 |
promotionContent: (0, _wordpress_i18n.__)("Upgrade to further customize your animation with opacity, scale, move, rotate and more.", "elementor"), |
| 1450 |
upgradeUrl: "https://go.elementor.com/go-pro-interactions-custom-effect-modal/", |
| 1451 |
trackingData: TRACKING_DATA$3 |
| 1452 |
}); |
| 1453 |
} |
| 1454 |
|
| 1455 |
//#endregion |
| 1456 |
//#region packages/packages/core/editor-interactions/src/components/controls/effect-type.tsx |
| 1457 |
function EffectType({ value, onChange }) { |
| 1458 |
const options = [{ |
| 1459 |
value: "in", |
| 1460 |
label: (0, _wordpress_i18n.__)("In", "elementor"), |
| 1461 |
renderContent: () => (0, _wordpress_i18n.__)("In", "elementor"), |
| 1462 |
showTooltip: true |
| 1463 |
}, { |
| 1464 |
value: "out", |
| 1465 |
label: (0, _wordpress_i18n.__)("Out", "elementor"), |
| 1466 |
renderContent: () => (0, _wordpress_i18n.__)("Out", "elementor"), |
| 1467 |
showTooltip: true |
| 1468 |
}]; |
| 1469 |
return /* @__PURE__ */ react.createElement(_elementor_editor_controls.ToggleButtonGroupUi, { |
| 1470 |
items: options, |
| 1471 |
exclusive: true, |
| 1472 |
onChange, |
| 1473 |
value |
| 1474 |
}); |
| 1475 |
} |
| 1476 |
|
| 1477 |
//#endregion |
| 1478 |
//#region packages/packages/core/editor-interactions/src/ui/promotion-overlay-layout.tsx |
| 1479 |
var OVERLAY_GRID = "1 / 1"; |
| 1480 |
var CHIP_OFFSET = "50%"; |
| 1481 |
var PromotionOverlayLayout = (0, react.forwardRef)(({ children, promotionChip }, ref) => /* @__PURE__ */ react.createElement(_elementor_ui.Box, { |
| 1482 |
ref, |
| 1483 |
sx: { |
| 1484 |
display: "grid", |
| 1485 |
alignItems: "center" |
| 1486 |
} |
| 1487 |
}, /* @__PURE__ */ react.createElement(_elementor_ui.Box, { sx: { gridArea: OVERLAY_GRID } }, children), /* @__PURE__ */ react.createElement(_elementor_ui.Box, { sx: { |
| 1488 |
gridArea: OVERLAY_GRID, |
| 1489 |
marginInlineEnd: CHIP_OFFSET, |
| 1490 |
justifySelf: "end" |
| 1491 |
} }, promotionChip))); |
| 1492 |
|
| 1493 |
//#endregion |
| 1494 |
//#region packages/packages/core/editor-interactions/src/components/controls/repeat.tsx |
| 1495 |
var TRACKING_DATA$2 = { |
| 1496 |
target_name: "interactions_repeat", |
| 1497 |
location_l2: "interactions" |
| 1498 |
}; |
| 1499 |
var REPEAT_OPTIONS = { |
| 1500 |
times: (0, _wordpress_i18n.__)("times", "elementor"), |
| 1501 |
loop: (0, _wordpress_i18n.__)("loop", "elementor") |
| 1502 |
}; |
| 1503 |
var REPEAT_TOOLTIPS = { |
| 1504 |
times: (0, _wordpress_i18n.__)("Enable number", "elementor"), |
| 1505 |
loop: (0, _wordpress_i18n.__)("Infinite repeat", "elementor") |
| 1506 |
}; |
| 1507 |
function Repeat() { |
| 1508 |
const repeatContainerRef = (0, react.useRef)(null); |
| 1509 |
const options = [{ |
| 1510 |
value: REPEAT_OPTIONS.times, |
| 1511 |
disabled: true, |
| 1512 |
label: REPEAT_TOOLTIPS.times, |
| 1513 |
renderContent: ({ size }) => /* @__PURE__ */ react.createElement(_elementor_icons.Number123Icon, { fontSize: size }), |
| 1514 |
showTooltip: true |
| 1515 |
}, { |
| 1516 |
value: REPEAT_OPTIONS.loop, |
| 1517 |
disabled: true, |
| 1518 |
label: REPEAT_TOOLTIPS.loop, |
| 1519 |
renderContent: ({ size }) => /* @__PURE__ */ react.createElement(_elementor_icons.RepeatIcon, { fontSize: size }), |
| 1520 |
showTooltip: true |
| 1521 |
}]; |
| 1522 |
return /* @__PURE__ */ react.createElement(PromotionOverlayLayout, { |
| 1523 |
ref: repeatContainerRef, |
| 1524 |
promotionChip: /* @__PURE__ */ react.createElement(InteractionsPromotionChip, { |
| 1525 |
content: (0, _wordpress_i18n.__)("Upgrade to control how many times the animation repeats.", "elementor"), |
| 1526 |
upgradeUrl: "https://go.elementor.com/go-pro-interactions-repeat-modal/", |
| 1527 |
anchorRef: repeatContainerRef, |
| 1528 |
trackingData: TRACKING_DATA$2 |
| 1529 |
}) |
| 1530 |
}, /* @__PURE__ */ react.createElement(_elementor_editor_controls.ToggleButtonGroupUi, { |
| 1531 |
items: options, |
| 1532 |
exclusive: true, |
| 1533 |
onChange: () => {}, |
| 1534 |
value: "" |
| 1535 |
})); |
| 1536 |
} |
| 1537 |
|
| 1538 |
//#endregion |
| 1539 |
//#region packages/packages/core/editor-interactions/src/components/controls/replay.tsx |
| 1540 |
var TRACKING_DATA$1 = { |
| 1541 |
target_name: "interactions_replay", |
| 1542 |
location_l2: "interactions" |
| 1543 |
}; |
| 1544 |
var REPLAY_OPTIONS = { |
| 1545 |
no: (0, _wordpress_i18n.__)("No", "elementor"), |
| 1546 |
yes: (0, _wordpress_i18n.__)("Yes", "elementor") |
| 1547 |
}; |
| 1548 |
var BASE_REPLAY = ["no"]; |
| 1549 |
function Replay({ onChange }) { |
| 1550 |
const replayContainerRef = (0, react.useRef)(null); |
| 1551 |
const options = [{ |
| 1552 |
value: false, |
| 1553 |
disabled: false, |
| 1554 |
label: REPLAY_OPTIONS.no, |
| 1555 |
renderContent: ({ size }) => /* @__PURE__ */ react.createElement(_elementor_icons.MinusIcon, { fontSize: size }), |
| 1556 |
showTooltip: true |
| 1557 |
}, { |
| 1558 |
value: true, |
| 1559 |
disabled: true, |
| 1560 |
label: REPLAY_OPTIONS.yes, |
| 1561 |
renderContent: ({ size }) => /* @__PURE__ */ react.createElement(_elementor_icons.CheckIcon, { fontSize: size }), |
| 1562 |
showTooltip: true |
| 1563 |
}]; |
| 1564 |
return /* @__PURE__ */ react.createElement(PromotionOverlayLayout, { |
| 1565 |
ref: replayContainerRef, |
| 1566 |
promotionChip: /* @__PURE__ */ react.createElement(InteractionsPromotionChip, { |
| 1567 |
content: (0, _wordpress_i18n.__)("Upgrade to run the animation every time its trigger occurs.", "elementor"), |
| 1568 |
upgradeUrl: "https://go.elementor.com/go-pro-interactions-replay-modal/", |
| 1569 |
anchorRef: replayContainerRef, |
| 1570 |
trackingData: TRACKING_DATA$1 |
| 1571 |
}) |
| 1572 |
}, /* @__PURE__ */ react.createElement(_elementor_editor_controls.ToggleButtonGroupUi, { |
| 1573 |
items: options, |
| 1574 |
exclusive: true, |
| 1575 |
onChange, |
| 1576 |
value: false |
| 1577 |
})); |
| 1578 |
} |
| 1579 |
|
| 1580 |
//#endregion |
| 1581 |
//#region packages/packages/core/editor-interactions/src/components/controls/trigger.tsx |
| 1582 |
var TRACKING_DATA = { |
| 1583 |
target_name: "interactions_trigger", |
| 1584 |
location_l2: "interactions" |
| 1585 |
}; |
| 1586 |
var TRIGGER_OPTIONS = { |
| 1587 |
load: (0, _wordpress_i18n.__)("Page load", "elementor"), |
| 1588 |
scrollIn: (0, _wordpress_i18n.__)("Scroll into view", "elementor"), |
| 1589 |
scrollOn: (0, _wordpress_i18n.__)("While scrolling", "elementor"), |
| 1590 |
hover: (0, _wordpress_i18n.__)("On hover", "elementor"), |
| 1591 |
click: (0, _wordpress_i18n.__)("On click", "elementor") |
| 1592 |
}; |
| 1593 |
var BASE_TRIGGERS = ["load", "scrollIn"]; |
| 1594 |
function Trigger({ value, onChange }) { |
| 1595 |
const baseOptions = Object.fromEntries(Object.entries(TRIGGER_OPTIONS).filter(([key]) => BASE_TRIGGERS.includes(key))); |
| 1596 |
const disabledOptions = Object.fromEntries(Object.entries(TRIGGER_OPTIONS).filter(([key]) => !BASE_TRIGGERS.includes(key))); |
| 1597 |
return /* @__PURE__ */ react.createElement(PromotionSelect, { |
| 1598 |
value: value in baseOptions ? value : DEFAULT_VALUES.trigger, |
| 1599 |
onChange, |
| 1600 |
baseOptions, |
| 1601 |
disabledOptions, |
| 1602 |
promotionLabel: (0, _wordpress_i18n.__)("PRO triggers", "elementor"), |
| 1603 |
promotionContent: (0, _wordpress_i18n.__)("Upgrade to unlock more interactions triggers.", "elementor"), |
| 1604 |
upgradeUrl: "https://go.elementor.com/go-pro-interactions-triggers-modal/", |
| 1605 |
trackingData: TRACKING_DATA |
| 1606 |
}); |
| 1607 |
} |
| 1608 |
|
| 1609 |
//#endregion |
| 1610 |
//#region packages/packages/core/editor-interactions/src/hooks/on-duplicate.ts |
| 1611 |
function initCleanInteractionIdsOnDuplicate() { |
| 1612 |
(0, _elementor_editor_v1_adapters.registerDataHook)("after", "document/elements/duplicate", (_args, result) => { |
| 1613 |
if (!result || typeof result === "boolean" && result === false) return; |
| 1614 |
(Array.isArray(result) ? result : [result]).forEach((container) => { |
| 1615 |
cleanInteractionIdsRecursive(container.id); |
| 1616 |
}); |
| 1617 |
window.dispatchEvent(new CustomEvent("elementor/element/update_interactions")); |
| 1618 |
}); |
| 1619 |
} |
| 1620 |
function cleanInteractionIdsRecursive(elementId) { |
| 1621 |
const container = (0, _elementor_editor_elements.getContainer)(elementId); |
| 1622 |
if (!container) return; |
| 1623 |
(0, _elementor_editor_elements.getAllDescendants)(container).forEach((element) => { |
| 1624 |
cleanInteractionIds(element.id); |
| 1625 |
}); |
| 1626 |
} |
| 1627 |
function cleanInteractionIds(elementId) { |
| 1628 |
const container = (0, _elementor_editor_elements.getContainer)(elementId); |
| 1629 |
if (!container) return; |
| 1630 |
const interactions = container.model.get("interactions"); |
| 1631 |
if (!interactions || !interactions.items) return; |
| 1632 |
const updatedInteractions = structuredClone(interactions); |
| 1633 |
updatedInteractions?.items?.forEach((interaction) => { |
| 1634 |
if (interaction.$$type === "interaction-item" && interaction.value) interaction.value.interaction_id = createString(generateTempInteractionId()); |
| 1635 |
}); |
| 1636 |
container.model.set("interactions", updatedInteractions); |
| 1637 |
} |
| 1638 |
|
| 1639 |
//#endregion |
| 1640 |
//#region packages/packages/core/editor-interactions/src/mcp/tools/schema.ts |
| 1641 |
var baseSchema = { |
| 1642 |
trigger: _elementor_schema.z.enum(["load", "scrollIn"]).optional().describe("Event that triggers the animation"), |
| 1643 |
effect: _elementor_schema.z.enum([ |
| 1644 |
"fade", |
| 1645 |
"slide", |
| 1646 |
"scale" |
| 1647 |
]).optional().describe("Animation effect type"), |
| 1648 |
effectType: _elementor_schema.z.enum(["in", "out"]).optional().describe("Whether the animation plays in or out"), |
| 1649 |
direction: _elementor_schema.z.enum([ |
| 1650 |
"top", |
| 1651 |
"bottom", |
| 1652 |
"left", |
| 1653 |
"right", |
| 1654 |
"top-left", |
| 1655 |
"top-right", |
| 1656 |
"bottom-left", |
| 1657 |
"bottom-right" |
| 1658 |
]).optional().describe("Direction of the Animation. Can be one of the following or empty if not needed. At slide effect, this is required field."), |
| 1659 |
duration: _elementor_schema.z.number().min(0).max(1e4).optional().describe("Animation duration in milliseconds"), |
| 1660 |
delay: _elementor_schema.z.number().min(0).max(1e4).optional().describe("Animation delay in milliseconds"), |
| 1661 |
easing: _elementor_schema.z.enum(["easeIn"]).optional().describe("Easing function for the animation. Use \"easeIn\" for free tier."), |
| 1662 |
excludedBreakpoints: _elementor_schema.z.array(_elementor_schema.z.enum([ |
| 1663 |
"widescreen", |
| 1664 |
"desktop", |
| 1665 |
"laptop", |
| 1666 |
"tablet_extra", |
| 1667 |
"tablet", |
| 1668 |
"mobile_extra", |
| 1669 |
"mobile" |
| 1670 |
])).optional().describe("Breakpoint IDs on which this interaction is disabled (e.g. [\"mobile\", \"tablet\"]). Fetch the \"elementor://breakpoints/list\" resource to get the valid IDs for the current site. Omit to enable on all breakpoints.") |
| 1671 |
}; |
| 1672 |
var proSchema = { |
| 1673 |
trigger: _elementor_schema.z.enum([ |
| 1674 |
"load", |
| 1675 |
"scrollIn", |
| 1676 |
"scrollOut", |
| 1677 |
"scrollOn", |
| 1678 |
"hover", |
| 1679 |
"click" |
| 1680 |
]).optional().describe("Event that triggers the animation"), |
| 1681 |
effect: _elementor_schema.z.enum([ |
| 1682 |
"fade", |
| 1683 |
"slide", |
| 1684 |
"scale", |
| 1685 |
"custom" |
| 1686 |
]).optional().describe("Animation effect type"), |
| 1687 |
easing: _elementor_schema.z.enum([ |
| 1688 |
"easeIn", |
| 1689 |
"easeInOut", |
| 1690 |
"easeOut", |
| 1691 |
"backIn", |
| 1692 |
"backInOut", |
| 1693 |
"backOut", |
| 1694 |
"linear" |
| 1695 |
]).optional().describe("Easing function for the animation."), |
| 1696 |
customEffects: _elementor_schema.z.object({ keyframes: _elementor_schema.z.array(_elementor_schema.z.object({ |
| 1697 |
stop: _elementor_schema.z.number().describe("The stop of the keyframe in percent, can be either 0 or 100"), |
| 1698 |
value: _elementor_schema.z.object({ |
| 1699 |
opacity: _elementor_schema.z.number().min(0).max(1).describe("The opacity of the keyframe"), |
| 1700 |
scale: _elementor_schema.z.object({ |
| 1701 |
x: _elementor_schema.z.number().min(0).max(1).describe("The x scale of the keyframe"), |
| 1702 |
y: _elementor_schema.z.number().min(0).max(1).describe("The y scale of the keyframe") |
| 1703 |
}).optional().describe("The scale of the keyframe"), |
| 1704 |
rotate: _elementor_schema.z.object({ |
| 1705 |
x: _elementor_schema.z.number().min(0).max(360).describe("The x rotate of the keyframe"), |
| 1706 |
y: _elementor_schema.z.number().min(0).max(360).describe("The y rotate of the keyframe"), |
| 1707 |
z: _elementor_schema.z.number().min(0).max(360).describe("The z rotate of the keyframe") |
| 1708 |
}).optional().describe("The rotate of the keyframe"), |
| 1709 |
move: _elementor_schema.z.object({ |
| 1710 |
x: _elementor_schema.z.number().min(0).max(1).describe("The x move of the keyframe"), |
| 1711 |
y: _elementor_schema.z.number().min(0).max(1).describe("The y move of the keyframe"), |
| 1712 |
z: _elementor_schema.z.number().min(0).max(1).describe("The z move of the keyframe") |
| 1713 |
}).optional().describe("The move of the keyframe"), |
| 1714 |
skew: _elementor_schema.z.object({ |
| 1715 |
x: _elementor_schema.z.number().min(0).max(360).describe("The x skew of the keyframe"), |
| 1716 |
y: _elementor_schema.z.number().min(0).max(360).describe("The y skew of the keyframe") |
| 1717 |
}).optional().describe("The skew of the keyframe") |
| 1718 |
}) |
| 1719 |
})).describe("The keyframes of the custom effect") }).optional().describe("The custom effect to use for the animation") |
| 1720 |
}; |
| 1721 |
|
| 1722 |
//#endregion |
| 1723 |
//#region packages/packages/core/editor-interactions/src/mcp/resources/interactions-schema-resource.ts |
| 1724 |
var INTERACTIONS_SCHEMA_URI = "elementor://interactions/schema"; |
| 1725 |
var initInteractionsSchemaResource = (reg) => { |
| 1726 |
const { resource } = reg; |
| 1727 |
const schema = (0, _elementor_utils.isProActive)() ? { |
| 1728 |
...baseSchema, |
| 1729 |
...proSchema |
| 1730 |
} : baseSchema; |
| 1731 |
resource("interactions-schema", INTERACTIONS_SCHEMA_URI, { description: "Schema describing all available options for element interactions." }, async () => { |
| 1732 |
return { contents: [{ |
| 1733 |
uri: INTERACTIONS_SCHEMA_URI, |
| 1734 |
mimeType: "application/json", |
| 1735 |
text: JSON.stringify(schema) |
| 1736 |
}] }; |
| 1737 |
}); |
| 1738 |
}; |
| 1739 |
|
| 1740 |
//#endregion |
| 1741 |
//#region packages/packages/core/editor-interactions/src/mcp/constants.ts |
| 1742 |
var MAX_INTERACTIONS_PER_ELEMENT = 5; |
| 1743 |
var EDITOR_INTERACTIONS_MCP_SHORT_DESCRIPTION = `Everything related to V4 ( Atomic ) interactions. |
| 1744 |
# Interactions |
| 1745 |
- Create/update/delete interactions |
| 1746 |
- Get list of interactions |
| 1747 |
- Get details of an interaction |
| 1748 |
`; |
| 1749 |
var EDITOR_INTERACTIONS_MCP_DESCRIPTION = `MCP server for managing element interactions and animations. Use this to add, modify, or remove animations and motion effects triggered by user events such as page load or scroll-into-view. |
| 1750 |
** IMPORTANT ** |
| 1751 |
Use the "interactions-schema" resource to get the schema of the interactions. |
| 1752 |
Actions: |
| 1753 |
- get: Read the current interactions on the element. |
| 1754 |
- add: Add a new interaction (max ${5} per element). |
| 1755 |
- update: Update an existing interaction by its interactionId. |
| 1756 |
- delete: Remove a specific interaction by its interactionId. |
| 1757 |
- clear: Remove all interactions from the element. |
| 1758 |
|
| 1759 |
For add/update, provide: trigger, effect, effectType, direction (required for slide effect), duration, delay, easing. |
| 1760 |
Use excludedBreakpoints to disable the animation on specific responsive breakpoints (e.g. ["mobile", "tablet"]). |
| 1761 |
Example Get Request: |
| 1762 |
{ |
| 1763 |
"elementId": "123", |
| 1764 |
"action": "get", |
| 1765 |
"interactionId": "123", |
| 1766 |
"animationData": { |
| 1767 |
"trigger": "click", |
| 1768 |
"effect": "fade", |
| 1769 |
} |
| 1770 |
} |
| 1771 |
Example Add Request: |
| 1772 |
{ |
| 1773 |
"elementId": "123", |
| 1774 |
"action": "add", |
| 1775 |
"animationData": { |
| 1776 |
"effectType": "in", |
| 1777 |
"direction": "top", |
| 1778 |
"trigger": "click", |
| 1779 |
"effect": "fade", |
| 1780 |
"duration": 1000, |
| 1781 |
"delay": 0, |
| 1782 |
"easing": "easeIn", |
| 1783 |
"excludedBreakpoints": ["mobile", "tablet"], |
| 1784 |
} |
| 1785 |
} |
| 1786 |
Example Update Request: |
| 1787 |
{ |
| 1788 |
"elementId": "123", |
| 1789 |
"action": "update", |
| 1790 |
"interactionId": "123", |
| 1791 |
"animationData": { |
| 1792 |
"trigger": "click", |
| 1793 |
"effect": "fade", |
| 1794 |
} |
| 1795 |
} |
| 1796 |
Example Delete Request: |
| 1797 |
{ |
| 1798 |
"elementId": "123", |
| 1799 |
"action": "delete", |
| 1800 |
"interactionId": "123", |
| 1801 |
} |
| 1802 |
Example Clear Request: |
| 1803 |
{ |
| 1804 |
"elementId": "123", |
| 1805 |
"action": "clear", |
| 1806 |
}`; |
| 1807 |
|
| 1808 |
//#endregion |
| 1809 |
//#region packages/packages/core/editor-interactions/src/mcp/tools/manage-element-interaction-tool.ts |
| 1810 |
var EMPTY_INTERACTIONS = { |
| 1811 |
version: 1, |
| 1812 |
items: [] |
| 1813 |
}; |
| 1814 |
var EFFECTS_WITHOUT_TYPE = ["custom"]; |
| 1815 |
var BREAKPOINTS_SCHEMA_URI = "elementor://breakpoints/list"; |
| 1816 |
var initManageElementInteractionTool = (reg) => { |
| 1817 |
const { addTool } = reg; |
| 1818 |
const extendedSchema = (0, _elementor_utils.isProActive)() ? { |
| 1819 |
...baseSchema, |
| 1820 |
...proSchema |
| 1821 |
} : baseSchema; |
| 1822 |
addTool({ |
| 1823 |
name: "manage-element-interaction", |
| 1824 |
description: `Manage the element interaction.`, |
| 1825 |
schema: { |
| 1826 |
elementId: _elementor_schema.z.string().describe("The ID of the element to read or modify interactions on"), |
| 1827 |
action: _elementor_schema.z.enum([ |
| 1828 |
"get", |
| 1829 |
"add", |
| 1830 |
"update", |
| 1831 |
"delete", |
| 1832 |
"clear" |
| 1833 |
]).describe("Operation to perform. Use \"get\" first to inspect existing interactions."), |
| 1834 |
interactionId: _elementor_schema.z.string().optional().describe("Interaction ID — required for update and delete. Obtain from a prior \"get\" call."), |
| 1835 |
...extendedSchema |
| 1836 |
}, |
| 1837 |
requiredResources: [{ |
| 1838 |
uri: INTERACTIONS_SCHEMA_URI, |
| 1839 |
description: "Interactions schema with all available options" |
| 1840 |
}, { |
| 1841 |
uri: BREAKPOINTS_SCHEMA_URI, |
| 1842 |
description: "Available breakpoint IDs for excludedBreakpoints" |
| 1843 |
}], |
| 1844 |
isDestructive: true, |
| 1845 |
outputSchema: { |
| 1846 |
success: _elementor_schema.z.boolean().describe("Whether the action was successful"), |
| 1847 |
action: _elementor_schema.z.enum([ |
| 1848 |
"get", |
| 1849 |
"add", |
| 1850 |
"update", |
| 1851 |
"delete", |
| 1852 |
"clear" |
| 1853 |
]).describe("Operation to perform. Use \"get\" first to inspect existing interactions."), |
| 1854 |
elementId: _elementor_schema.z.string().optional().describe("The ID of the element to read or modify interactions on"), |
| 1855 |
interactions: _elementor_schema.z.array(_elementor_schema.z.any()).optional().describe("The interactions on the element"), |
| 1856 |
count: _elementor_schema.z.number().optional().describe("The number of interactions on the element") |
| 1857 |
}, |
| 1858 |
handler: (input) => { |
| 1859 |
const { elementId, action, interactionId, ...animationData } = input; |
| 1860 |
const { effectType, ...restAnimationData } = animationData; |
| 1861 |
const effect = restAnimationData.effect; |
| 1862 |
const resolvedType = effectType ?? (effect && !EFFECTS_WITHOUT_TYPE.includes(effect) ? "in" : void 0); |
| 1863 |
const currentInteractions = interactionsRepository.all().find((data) => data.elementId === elementId)?.interactions ?? EMPTY_INTERACTIONS; |
| 1864 |
if (action === "get") { |
| 1865 |
const summary = currentInteractions.items.map((item) => { |
| 1866 |
const { value } = item; |
| 1867 |
const animValue = value.animation.value; |
| 1868 |
const timingValue = animValue.timing_config.value; |
| 1869 |
const configValue = animValue.config.value; |
| 1870 |
return { |
| 1871 |
id: extractString(value.interaction_id), |
| 1872 |
trigger: extractString(value.trigger), |
| 1873 |
effect: extractString(animValue.effect), |
| 1874 |
effectType: extractString(animValue.type), |
| 1875 |
direction: extractString(animValue.direction), |
| 1876 |
duration: extractSize(timingValue.duration), |
| 1877 |
delay: extractSize(timingValue.delay), |
| 1878 |
easing: extractString(configValue.easing), |
| 1879 |
excludedBreakpoints: extractExcludedBreakpoints(value.breakpoints) |
| 1880 |
}; |
| 1881 |
}); |
| 1882 |
return { |
| 1883 |
success: true, |
| 1884 |
elementId, |
| 1885 |
action, |
| 1886 |
interactions: summary, |
| 1887 |
count: summary.length |
| 1888 |
}; |
| 1889 |
} |
| 1890 |
let updatedItems = [...currentInteractions.items]; |
| 1891 |
switch (action) { |
| 1892 |
case "add": { |
| 1893 |
if (updatedItems.length >= 5) throw new Error(`Cannot add more than ${5} interactions per element. Current count: ${updatedItems.length}. Delete an existing interaction first.`); |
| 1894 |
const newItem = createInteractionItem({ |
| 1895 |
interactionId: generateTempInteractionId(), |
| 1896 |
...restAnimationData, |
| 1897 |
type: resolvedType |
| 1898 |
}); |
| 1899 |
updatedItems = [...updatedItems, newItem]; |
| 1900 |
break; |
| 1901 |
} |
| 1902 |
case "update": { |
| 1903 |
if (!interactionId) throw new Error("interactionId is required for the update action."); |
| 1904 |
const itemIndex = updatedItems.findIndex((item) => extractString(item.value.interaction_id) === interactionId); |
| 1905 |
if (itemIndex === -1) throw new Error(`Interaction with ID "${interactionId}" not found on element "${elementId}".`); |
| 1906 |
const updatedItem = createInteractionItem({ |
| 1907 |
interactionId, |
| 1908 |
...restAnimationData, |
| 1909 |
type: resolvedType |
| 1910 |
}); |
| 1911 |
updatedItems = [ |
| 1912 |
...updatedItems.slice(0, itemIndex), |
| 1913 |
updatedItem, |
| 1914 |
...updatedItems.slice(itemIndex + 1) |
| 1915 |
]; |
| 1916 |
break; |
| 1917 |
} |
| 1918 |
case "delete": { |
| 1919 |
if (!interactionId) throw new Error("interactionId is required for the delete action."); |
| 1920 |
const beforeCount = updatedItems.length; |
| 1921 |
updatedItems = updatedItems.filter((item) => extractString(item.value.interaction_id) !== interactionId); |
| 1922 |
if (updatedItems.length === beforeCount) throw new Error(`Interaction with ID "${interactionId}" not found on element "${elementId}".`); |
| 1923 |
break; |
| 1924 |
} |
| 1925 |
case "clear": |
| 1926 |
updatedItems = []; |
| 1927 |
break; |
| 1928 |
} |
| 1929 |
const updatedInteractions = { |
| 1930 |
...currentInteractions, |
| 1931 |
items: updatedItems |
| 1932 |
}; |
| 1933 |
try { |
| 1934 |
(0, _elementor_editor_elements.updateElementInteractions)({ |
| 1935 |
elementId, |
| 1936 |
interactions: updatedInteractions |
| 1937 |
}); |
| 1938 |
} catch (error) { |
| 1939 |
throw new Error(`Failed to update interactions for element "${elementId}": ${error instanceof Error ? error.message : "Unknown error"}`); |
| 1940 |
} |
| 1941 |
return { |
| 1942 |
success: true, |
| 1943 |
action, |
| 1944 |
elementId, |
| 1945 |
count: updatedItems.length |
| 1946 |
}; |
| 1947 |
} |
| 1948 |
}); |
| 1949 |
}; |
| 1950 |
|
| 1951 |
//#endregion |
| 1952 |
//#region packages/packages/core/editor-interactions/src/mcp/index.ts |
| 1953 |
var initMcpInteractions = (reg) => { |
| 1954 |
const { setMCPDescription } = reg; |
| 1955 |
setMCPDescription(`Everything related to V4 ( Atomic ) interactions. |
| 1956 |
# Interactions |
| 1957 |
- Create/update/delete interactions |
| 1958 |
- Get list of interactions |
| 1959 |
- Get details of an interaction |
| 1960 |
`); |
| 1961 |
initInteractionsSchemaResource(reg); |
| 1962 |
initManageElementInteractionTool(reg); |
| 1963 |
}; |
| 1964 |
|
| 1965 |
//#endregion |
| 1966 |
//#region packages/packages/core/editor-interactions/src/init.ts |
| 1967 |
function init() { |
| 1968 |
try { |
| 1969 |
interactionsRepository.register(documentElementsInteractionsProvider); |
| 1970 |
initCleanInteractionIdsOnDuplicate(); |
| 1971 |
initPasteInteractionsCommand(); |
| 1972 |
registerInteractionsControl({ |
| 1973 |
type: "trigger", |
| 1974 |
component: Trigger, |
| 1975 |
options: ["load", "scrollIn"] |
| 1976 |
}); |
| 1977 |
registerInteractionsControl({ |
| 1978 |
type: "easing", |
| 1979 |
component: Easing, |
| 1980 |
options: ["easeIn"] |
| 1981 |
}); |
| 1982 |
registerInteractionsControl({ |
| 1983 |
type: "replay", |
| 1984 |
component: Replay, |
| 1985 |
options: ["no"] |
| 1986 |
}); |
| 1987 |
registerInteractionsControl({ |
| 1988 |
type: "effectType", |
| 1989 |
component: EffectType, |
| 1990 |
options: ["in", "out"] |
| 1991 |
}); |
| 1992 |
registerInteractionsControl({ |
| 1993 |
type: "direction", |
| 1994 |
component: Direction, |
| 1995 |
options: [ |
| 1996 |
"top", |
| 1997 |
"bottom", |
| 1998 |
"left", |
| 1999 |
"right" |
| 2000 |
] |
| 2001 |
}); |
| 2002 |
registerInteractionsControl({ |
| 2003 |
type: "effect", |
| 2004 |
component: Effect, |
| 2005 |
options: [ |
| 2006 |
"fade", |
| 2007 |
"slide", |
| 2008 |
"scale" |
| 2009 |
] |
| 2010 |
}); |
| 2011 |
registerInteractionsControl({ |
| 2012 |
type: "repeat", |
| 2013 |
component: Repeat |
| 2014 |
}); |
| 2015 |
initMcpInteractions((0, _elementor_editor_mcp.getMCPByDomain)("interactions", { |
| 2016 |
docs: EDITOR_INTERACTIONS_MCP_DESCRIPTION, |
| 2017 |
instructions: EDITOR_INTERACTIONS_MCP_SHORT_DESCRIPTION |
| 2018 |
})); |
| 2019 |
} catch (error) { |
| 2020 |
throw error; |
| 2021 |
} |
| 2022 |
} |
| 2023 |
|
| 2024 |
//#endregion |
| 2025 |
//#region packages/packages/core/editor-interactions/src/index.ts |
| 2026 |
var src_exports = /* @__PURE__ */ __exportAll({ |
| 2027 |
BASE_EASINGS: () => BASE_EASINGS, |
| 2028 |
BASE_EFFECTS: () => BASE_EFFECTS, |
| 2029 |
BASE_REPLAY: () => BASE_REPLAY, |
| 2030 |
BASE_TRIGGERS: () => BASE_TRIGGERS, |
| 2031 |
DEFAULT_VALUES: () => DEFAULT_VALUES, |
| 2032 |
EASING_OPTIONS: () => EASING_OPTIONS, |
| 2033 |
EFFECT_OPTIONS: () => EFFECT_OPTIONS, |
| 2034 |
ELEMENTS_INTERACTIONS_PROVIDER_KEY_PREFIX: () => ELEMENTS_INTERACTIONS_PROVIDER_KEY_PREFIX, |
| 2035 |
EmptyState: () => EmptyState, |
| 2036 |
InteractionsTab: () => InteractionsTab, |
| 2037 |
REPEAT_OPTIONS: () => REPEAT_OPTIONS, |
| 2038 |
REPEAT_TOOLTIPS: () => REPEAT_TOOLTIPS, |
| 2039 |
REPLAY_OPTIONS: () => REPLAY_OPTIONS, |
| 2040 |
SCROLL_INTERACTION_EVENT: () => SCROLL_INTERACTION_EVENT, |
| 2041 |
TRIGGER_OPTIONS: () => TRIGGER_OPTIONS, |
| 2042 |
buildDisplayLabel: () => buildDisplayLabel, |
| 2043 |
createAnimationPreset: () => createAnimationPreset, |
| 2044 |
createBoolean: () => createBoolean, |
| 2045 |
createConfig: () => createConfig, |
| 2046 |
createDefaultInteractionItem: () => createDefaultInteractionItem, |
| 2047 |
createDefaultInteractions: () => createDefaultInteractions, |
| 2048 |
createExcludedBreakpoints: () => createExcludedBreakpoints, |
| 2049 |
createInteractionBreakpoints: () => createInteractionBreakpoints, |
| 2050 |
createInteractionItem: () => createInteractionItem, |
| 2051 |
createInteractionsProvider: () => createInteractionsProvider, |
| 2052 |
createNumber: () => createNumber, |
| 2053 |
createString: () => createString, |
| 2054 |
createTimingConfig: () => createTimingConfig, |
| 2055 |
dispatchScrollInteraction: () => dispatchScrollInteraction, |
| 2056 |
extractBoolean: () => extractBoolean, |
| 2057 |
extractExcludedBreakpoints: () => extractExcludedBreakpoints, |
| 2058 |
extractScrollOverlayParams: () => extractScrollOverlayParams, |
| 2059 |
extractSize: () => extractSize, |
| 2060 |
extractString: () => extractString, |
| 2061 |
formatSizeValue: () => formatSizeValue, |
| 2062 |
generateTempInteractionId: () => generateTempInteractionId, |
| 2063 |
getInteractionsConfig: () => getInteractionsConfig, |
| 2064 |
init: () => init, |
| 2065 |
interactionsRepository: () => interactionsRepository, |
| 2066 |
isTempId: () => isTempId, |
| 2067 |
parseSizeValue: () => parseSizeValue, |
| 2068 |
registerInteractionsControl: () => registerInteractionsControl, |
| 2069 |
resolveDirection: () => resolveDirection, |
| 2070 |
syncGridOverlay: () => syncGridOverlay, |
| 2071 |
useElementInteractions: () => useElementInteractions |
| 2072 |
}); |
| 2073 |
|
| 2074 |
//#endregion |
| 2075 |
//#region \0elementor-package-library-entry |
| 2076 |
(window.elementorV2 = window.elementorV2 || {}).editorInteractions = src_exports; |
| 2077 |
|
| 2078 |
//#endregion |
| 2079 |
})(React, elementorV2.icons, elementorV2.ui, wp.i18n, elementorV2.session, elementorV2.editorElements, elementorV2.editorV1Adapters, elementorV2.editorProps, elementorV2.editorControls, elementorV2.events, elementorV2.editorResponsive, elementorV2.editorMcp, elementorV2.editorUi, elementorV2.utils, elementorV2.schema); |
| 2080 |
window.elementorV2.editorInteractions?.init?.(); |
| 2081 |
//# sourceMappingURL=editor-interactions.js.map |