formeo 5.5.0 → 5.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -1,7 +1,7 @@
1
1
 
2
2
  /**
3
3
  formeo - https://formeo.io
4
- Version: 5.4.0
4
+ Version: 5.5.0
5
5
  Author: Draggable https://draggable.io
6
6
  */
7
7
 
@@ -1,7 +1,7 @@
1
1
 
2
2
  /**
3
3
  formeo - https://formeo.io
4
- Version: 5.4.0
4
+ Version: 5.5.0
5
5
  Author: Draggable https://draggable.io
6
6
  */
7
7
 
@@ -6061,7 +6061,7 @@ if (globalThis !== void 0) globalThis.SmartTooltip = SmartTooltip;
6061
6061
  var name$1, version$2, type, main, module$1, unpkg, exports$1, files, homepage, repository, author, contributors, bugs, description, keywords, ignore, config, scripts, devDependencies, dependencies, release, commitlint, package_default;
6062
6062
  var init_package = __esmMin((() => {
6063
6063
  name$1 = "formeo";
6064
- version$2 = "5.4.0";
6064
+ version$2 = "5.5.0";
6065
6065
  type = "module";
6066
6066
  main = "dist/formeo.cjs.js";
6067
6067
  module$1 = "dist/formeo.es.js";
@@ -11117,9 +11117,11 @@ var reachesDocument = (evt) => evt.target === document || Boolean(evt.bubbles &&
11117
11117
  */
11118
11118
  var Events = class {
11119
11119
  components = null;
11120
+ destroyed = false;
11120
11121
  constructor() {
11121
11122
  this.opts = this.defaults();
11122
11123
  this.formeoUpdatedThrottled = throttle$1(() => {
11124
+ if (this.destroyed) return;
11123
11125
  const eventData = {
11124
11126
  timeStamp: globalThis.performance.now(),
11125
11127
  type: EVENT_FORMEO_UPDATED,
@@ -11175,6 +11177,7 @@ var Events = class {
11175
11177
  return evt;
11176
11178
  }
11177
11179
  runCallbacks({ type, timeStamp, detail }) {
11180
+ if (this.destroyed) return;
11178
11181
  if (type === "formeoUpdated") return this.formeoUpdatedThrottled();
11179
11182
  if (type === "formeoSaved") return this.opts.onSave({
11180
11183
  timeStamp,
@@ -11202,6 +11205,7 @@ var Events = class {
11202
11205
  confirmClearAll = (detail) => {
11203
11206
  const evt = new globalThis.CustomEvent("confirmClearAll", { detail });
11204
11207
  document.dispatchEvent(evt);
11208
+ if (this.destroyed) return;
11205
11209
  this.opts.confirmClearAll({
11206
11210
  timeStamp: evt.timeStamp,
11207
11211
  type: evt.type,
@@ -11210,7 +11214,7 @@ var Events = class {
11210
11214
  };
11211
11215
  formeoLoaded = (formeo) => {
11212
11216
  document.dispatchEvent(new globalThis.CustomEvent("formeoLoaded", { detail: { formeo } }));
11213
- this.opts.formeoLoaded(formeo);
11217
+ if (!this.destroyed) this.opts.formeoLoaded(formeo);
11214
11218
  };
11215
11219
  columnResized = (detail) => document.dispatchEvent(new globalThis.CustomEvent("columnResized", { detail }));
11216
11220
  /**
@@ -11220,7 +11224,7 @@ var Events = class {
11220
11224
  */
11221
11225
  onResizeWindow = () => {
11222
11226
  const { columns, controls } = this.components || {};
11223
- if (!columns || !controls?.dom?.isConnected || this.resizeFrame) return;
11227
+ if (this.destroyed || !columns || !controls?.dom?.isConnected || this.resizeFrame) return;
11224
11228
  this.resizeFrame = window.requestAnimationFrame(() => {
11225
11229
  this.resizeFrame = null;
11226
11230
  for (const column of Object.values(columns.data)) {
@@ -11235,6 +11239,18 @@ var Events = class {
11235
11239
  }
11236
11240
  });
11237
11241
  };
11242
+ /**
11243
+ * Stop calling this editor's option callbacks, including a trailing onUpdate/onChange that is
11244
+ * already scheduled, and cancel a pending resize frame. FormeoEditor#destroy (#166) calls it.
11245
+ * DOM events are still dispatched, so page listeners are unaffected.
11246
+ */
11247
+ destroy() {
11248
+ this.destroyed = true;
11249
+ if (this.resizeFrame) {
11250
+ window.cancelAnimationFrame(this.resizeFrame);
11251
+ this.resizeFrame = null;
11252
+ }
11253
+ }
11238
11254
  };
11239
11255
  var events = new Events();
11240
11256
  //#endregion
@@ -13107,6 +13123,24 @@ var init_sortable_esm = __esmMin((() => {
13107
13123
  Sortable.mount(Remove, Revert);
13108
13124
  }));
13109
13125
  //#endregion
13126
+ //#region src/lib/js/common/sortable.js
13127
+ var destroySortables;
13128
+ var init_sortable = __esmMin((() => {
13129
+ init_sortable_esm();
13130
+ destroySortables = (root) => {
13131
+ if (!root) return 0;
13132
+ let count = 0;
13133
+ for (const el of [root, ...root.querySelectorAll("*")]) {
13134
+ const sortable = Sortable.get(el);
13135
+ if (sortable) {
13136
+ sortable.destroy();
13137
+ count++;
13138
+ }
13139
+ }
13140
+ return count;
13141
+ };
13142
+ }));
13143
+ //#endregion
13110
13144
  //#region src/lib/js/components/panels.js
13111
13145
  var defaults$1, getTransition, Panels;
13112
13146
  var init_panels = __esmMin((() => {
@@ -13136,18 +13170,25 @@ var init_panels = __esmMin((() => {
13136
13170
  const panelsWrap = this.createPanelsWrap();
13137
13171
  this.nav = this.navActions();
13138
13172
  this.nav.groupChange(this.activePanelIndex);
13139
- const resizeObserver = new window.ResizeObserver(([{ contentRect: { width } }]) => {
13173
+ this.resizeObserver = new window.ResizeObserver(([{ contentRect: { width } }]) => {
13140
13174
  if (this.currentWidth !== width) {
13141
13175
  this.toggleTabbedLayout();
13142
13176
  this.currentWidth = width;
13143
13177
  this.nav.setTranslateX(this.activePanelIndex, false);
13144
13178
  }
13145
13179
  });
13146
- const observeTimeout = window.setTimeout(() => {
13147
- resizeObserver.observe(panelsWrap);
13148
- window.clearTimeout(observeTimeout);
13180
+ this.observeTimeout = window.setTimeout(() => {
13181
+ this.resizeObserver?.observe(panelsWrap);
13149
13182
  }, ANIMATION_SPEED_SLOW);
13150
13183
  }
13184
+ /**
13185
+ * Stop watching the panels' size
13186
+ */
13187
+ destroy() {
13188
+ window.clearTimeout(this.observeTimeout);
13189
+ this.resizeObserver?.disconnect();
13190
+ this.resizeObserver = null;
13191
+ }
13151
13192
  getPanelDisplay() {
13152
13193
  const column = this.panelsWrap;
13153
13194
  const autoDisplayType = Number.parseInt(dom.getStyle(column, "width"), 10) > 390 ? "tabbed" : "slider";
@@ -13446,7 +13487,7 @@ var init_control = __esmMin((() => {
13446
13487
  }));
13447
13488
  //#endregion
13448
13489
  //#region src/lib/js/components/controls/options.js
13449
- init_sortable_esm();
13490
+ init_sortable();
13450
13491
  init_panels();
13451
13492
  init_control();
13452
13493
  var defaultOptions = Object.freeze({
@@ -14764,6 +14805,7 @@ var init_edit_panel_item = __esmMin((() => {
14764
14805
  var addAttributeActions, defaultConfigOptions, defaultConfigValues, EditPanel;
14765
14806
  var init_edit_panel = __esmMin((() => {
14766
14807
  init_i18n_es_min();
14808
+ init_sortable_esm();
14767
14809
  init_dom();
14768
14810
  init_helpers$2();
14769
14811
  init_string();
@@ -15089,6 +15131,7 @@ var init_edit_panel = __esmMin((() => {
15089
15131
  //#region src/lib/js/components/component.js
15090
15132
  var propertyOptions, Component;
15091
15133
  var init_component = __esmMin((() => {
15134
+ init_sortable_esm();
15092
15135
  init_animation();
15093
15136
  init_dom();
15094
15137
  init_helpers$2();
@@ -15243,6 +15286,8 @@ var init_component = __esmMin((() => {
15243
15286
  });
15244
15287
  forEach(children, (child) => child.remove());
15245
15288
  this.dom.remove();
15289
+ this.panels?.destroy();
15290
+ this.releaseSortables();
15246
15291
  remove(this.components.getAddress(siblingsPath), this.id);
15247
15292
  if (!parent.children.length) parent.emptyClass();
15248
15293
  if (parent.name === "row") parent.autoColumnWidths();
@@ -15591,6 +15636,20 @@ var init_component = __esmMin((() => {
15591
15636
  return this.saveChildOrder();
15592
15637
  };
15593
15638
  /**
15639
+ * Destroy the Sortables of this removed component and its descendants, so Sortable's page-wide
15640
+ * list stops holding them (and through them the editor). A column emptied by a drag is removed
15641
+ * from inside Sortable's drop handler; destroying that Sortable there would end the drop early,
15642
+ * so during a drag it is released once the drop has finished.
15643
+ */
15644
+ releaseSortables() {
15645
+ const { dom: removedDom } = this;
15646
+ if (Sortable.active) {
15647
+ queueMicrotask(() => destroySortables(removedDom));
15648
+ return;
15649
+ }
15650
+ destroySortables(removedDom);
15651
+ }
15652
+ /**
15594
15653
  * Handler for removing content from a sortable component
15595
15654
  * @param {Object} evt
15596
15655
  * @return {Array} updated child order
@@ -15816,6 +15875,7 @@ var init_component = __esmMin((() => {
15816
15875
  id: this.id,
15817
15876
  displayType: "auto"
15818
15877
  };
15878
+ this.panels?.destroy();
15819
15879
  this.panels = new Panels(panelsData);
15820
15880
  if (this.dom) {
15821
15881
  this.dom.querySelector(".panel-nav").replaceWith(this.panels.panelNav);
@@ -16594,6 +16654,7 @@ init_i18n_es_min();
16594
16654
  init_sortable_esm();
16595
16655
  init_dom();
16596
16656
  init_helpers$2();
16657
+ init_sortable();
16597
16658
  init_utils();
16598
16659
  init_object();
16599
16660
  init_constants();
@@ -16883,6 +16944,22 @@ var Controls = class {
16883
16944
  if (group === "layout") return this.layoutTypes[metaId.replace("layout-", "")]();
16884
16945
  return this.layoutTypes.field(elementData);
16885
16946
  };
16947
+ /**
16948
+ * Remove the controls from the page and release their Sortables and Panels. A control drag in
16949
+ * progress in these controls is ended: its ghost is removed and the page overflow it hid is
16950
+ * restored. Safe to call more than once, and before init().
16951
+ */
16952
+ destroy() {
16953
+ const element = this.dom;
16954
+ if (element && Sortable.active?.el && element.contains(Sortable.active.el)) Sortable.ghost?.remove();
16955
+ if (this.originalDocumentOverflow != null) {
16956
+ document.documentElement.style.overflow = this.originalDocumentOverflow;
16957
+ this.originalDocumentOverflow = null;
16958
+ }
16959
+ destroySortables(element);
16960
+ this.panels?.destroy();
16961
+ element?.remove();
16962
+ }
16886
16963
  applyOptions = async (controlOptions = {}) => {
16887
16964
  const { container, elements, groupOrder, ...options } = merge(defaultOptions, controlOptions);
16888
16965
  this.container = dom.resolveContainer(container);
@@ -17922,6 +17999,7 @@ var defaults = { get editor() {
17922
17999
  init_i18n_es_min();
17923
18000
  init_dom();
17924
18001
  init_loaders();
18002
+ init_sortable();
17925
18003
  init_utils();
17926
18004
  init_constants();
17927
18005
  /**
@@ -17932,9 +18010,11 @@ var INIT_STATES = {
17932
18010
  LOADING_RESOURCES: "loading",
17933
18011
  INITIALIZING: "initializing",
17934
18012
  READY: "ready",
17935
- ERROR: "error"
18013
+ ERROR: "error",
18014
+ DESTROYED: "destroyed"
17936
18015
  };
17937
18016
  var storageKeyHolders = /* @__PURE__ */ new Map();
18017
+ var pageTooltip = null;
17938
18018
  /**
17939
18019
  * Whether an editor is still on the page, or still on its way there. An editor whose container
17940
18020
  * left the page or no longer holds its DOM (a remount, a demo switch) no longer owns its key.
@@ -17942,7 +18022,7 @@ var storageKeyHolders = /* @__PURE__ */ new Map();
17942
18022
  * @return {Boolean}
17943
18023
  */
17944
18024
  var isLiveEditor = (editor) => {
17945
- if (editor.initState === INIT_STATES.ERROR) return false;
18025
+ if (editor.initState === INIT_STATES.ERROR || editor.initState === INIT_STATES.DESTROYED) return false;
17946
18026
  if (!editor.editor) return !editor.editorContainer || editor.editorContainer.isConnected;
17947
18027
  return Boolean(editor.editorContainer?.isConnected && editor.editorContainer.contains(editor.editor));
17948
18028
  };
@@ -17954,6 +18034,7 @@ var FormeoEditor$1 = class {
17954
18034
  #initPromise = null;
17955
18035
  #lockedFormData = null;
17956
18036
  #dataLoadedOnce = false;
18037
+ #onDOMContentLoaded = () => this.loadResources();
17957
18038
  /**
17958
18039
  * @param {Object} options formeo options
17959
18040
  * @param {String|Object} userFormData loaded formData
@@ -17989,7 +18070,7 @@ var FormeoEditor$1 = class {
17989
18070
  if (holder && isLiveEditor(holder)) console.warn(`formeo: another editor on this page already saves to sessionStorage key "${key}". Give each editor its own key, e.g. sessionStorage: 'orders-form'.`);
17990
18071
  storageKeyHolders.set(key, this);
17991
18072
  }
17992
- if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", this.loadResources.bind(this));
18073
+ if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", this.#onDOMContentLoaded, { once: true });
17993
18074
  else this.loadResources();
17994
18075
  }
17995
18076
  get formData() {
@@ -18012,6 +18093,7 @@ var FormeoEditor$1 = class {
18012
18093
  * @return {void}
18013
18094
  */
18014
18095
  clear() {
18096
+ if (this.isDestroyed) return;
18015
18097
  const defaultData = DEFAULT_FORMDATA();
18016
18098
  this.#lockedFormData = defaultData;
18017
18099
  this.userFormData = defaultData;
@@ -18023,7 +18105,8 @@ var FormeoEditor$1 = class {
18023
18105
  * @return {Promise} asynchronously loaded remote resources
18024
18106
  */
18025
18107
  async loadResources() {
18026
- document.removeEventListener("DOMContentLoaded", this.loadResources);
18108
+ document.removeEventListener("DOMContentLoaded", this.#onDOMContentLoaded);
18109
+ if (this.isDestroyed) return;
18027
18110
  this.#initState = INIT_STATES.LOADING_RESOURCES;
18028
18111
  const promises = [
18029
18112
  fetchIcons(this.opts.svgSprite),
@@ -18036,8 +18119,10 @@ var FormeoEditor$1 = class {
18036
18119
  ].filter(Boolean);
18037
18120
  try {
18038
18121
  await Promise.all(promises);
18122
+ if (this.isDestroyed) return;
18039
18123
  if (this.opts.allowEdit) this.init();
18040
18124
  } catch (error) {
18125
+ if (this.isDestroyed) return;
18041
18126
  this.#initState = INIT_STATES.ERROR;
18042
18127
  console.error("Failed to load resources:", error);
18043
18128
  throw error;
@@ -18049,10 +18134,15 @@ var FormeoEditor$1 = class {
18049
18134
  * dom elements, actions events and more.
18050
18135
  */
18051
18136
  init() {
18137
+ if (this.isDestroyed) return Promise.resolve(this);
18052
18138
  if (this.#initState === INIT_STATES.INITIALIZING) return this.#initPromise;
18053
18139
  if (this.#initState === INIT_STATES.READY) return this.#refreshUI();
18054
18140
  this.#initState = INIT_STATES.INITIALIZING;
18055
18141
  this.#initPromise = new Controls(this.Components).init(this.opts.controls, this.opts.stickyControls).then((controls) => {
18142
+ if (this.isDestroyed) {
18143
+ controls.destroy();
18144
+ return this;
18145
+ }
18056
18146
  this.controls = controls;
18057
18147
  this.Components.controls = controls;
18058
18148
  if (!this.#dataLoadedOnce) {
@@ -18062,13 +18152,17 @@ var FormeoEditor$1 = class {
18062
18152
  this.formId = this.Components.get("id");
18063
18153
  this.i18n = { setLang: this.#setLanguage.bind(this) };
18064
18154
  this.render();
18155
+ if (this.isDestroyed) return this;
18065
18156
  this.onResize = this.events.onResizeWindow;
18066
18157
  window.addEventListener("resize", this.onResize);
18067
18158
  this.#initState = INIT_STATES.READY;
18068
18159
  this.opts.onLoad?.(this);
18160
+ if (this.isDestroyed) return this;
18069
18161
  this.tooltipInstance = new SmartTooltip();
18162
+ pageTooltip = this.tooltipInstance;
18070
18163
  return this;
18071
18164
  }).catch((error) => {
18165
+ if (this.isDestroyed) return this;
18072
18166
  this.#initState = INIT_STATES.ERROR;
18073
18167
  console.error("Failed to initialize editor:", error);
18074
18168
  throw error;
@@ -18090,7 +18184,13 @@ var FormeoEditor$1 = class {
18090
18184
  * @return {Promise}
18091
18185
  */
18092
18186
  async #refreshUI() {
18093
- this.controls = await new Controls(this.Components).init(this.opts.controls, this.opts.stickyControls);
18187
+ if (this.isDestroyed) return this;
18188
+ const controls = await new Controls(this.Components).init(this.opts.controls, this.opts.stickyControls);
18189
+ if (this.isDestroyed) {
18190
+ controls.destroy();
18191
+ return this;
18192
+ }
18193
+ this.controls = controls;
18094
18194
  this.Components.controls = this.controls;
18095
18195
  this.render();
18096
18196
  return this;
@@ -18118,6 +18218,7 @@ var FormeoEditor$1 = class {
18118
18218
  return DEFAULT_FORMDATA();
18119
18219
  }
18120
18220
  load(formData = this.userFormData, opts = this.opts) {
18221
+ if (this.isDestroyed) return;
18121
18222
  this.Components.load(formData, opts);
18122
18223
  this.render();
18123
18224
  }
@@ -18136,16 +18237,28 @@ var FormeoEditor$1 = class {
18136
18237
  return this.#initState === INIT_STATES.READY;
18137
18238
  }
18138
18239
  /**
18240
+ * Check if destroy() was called
18241
+ * @return {boolean}
18242
+ */
18243
+ get isDestroyed() {
18244
+ return this.#initState === INIT_STATES.DESTROYED;
18245
+ }
18246
+ /**
18139
18247
  * Wait for the editor to be ready
18140
18248
  * @return {Promise} resolves when editor is ready
18141
18249
  */
18142
18250
  async whenReady() {
18143
18251
  if (this.#initState === INIT_STATES.READY) return this;
18252
+ if (this.isDestroyed) return Promise.reject(/* @__PURE__ */ new Error("Editor was destroyed"));
18144
18253
  if (this.#initState === INIT_STATES.ERROR) return Promise.reject(/* @__PURE__ */ new Error("Editor initialization failed"));
18145
- if (this.#initPromise) return this.#initPromise;
18254
+ if (this.#initPromise) return this.#initPromise.then((editor) => {
18255
+ if (this.isDestroyed) throw new Error("Editor was destroyed");
18256
+ return editor;
18257
+ });
18146
18258
  return new Promise((resolve, reject) => {
18147
18259
  const checkReady = () => {
18148
18260
  if (this.#initState === INIT_STATES.READY) resolve(this);
18261
+ else if (this.isDestroyed) reject(/* @__PURE__ */ new Error("Editor was destroyed"));
18149
18262
  else if (this.#initState === INIT_STATES.ERROR) reject(/* @__PURE__ */ new Error("Editor initialization failed"));
18150
18263
  else globalThis.requestAnimationFrame(checkReady);
18151
18264
  };
@@ -18157,6 +18270,7 @@ var FormeoEditor$1 = class {
18157
18270
  * @return {void}
18158
18271
  */
18159
18272
  render() {
18273
+ if (this.isDestroyed) return;
18160
18274
  if (!this.controls) return globalThis.requestAnimationFrame(() => this.render());
18161
18275
  this.stages = Object.values(this.Components.get("stages"));
18162
18276
  if (this.opts.controlOnLeft) for (const stage of this.stages) stage.dom.style.order = 1;
@@ -18187,6 +18301,46 @@ var FormeoEditor$1 = class {
18187
18301
  }
18188
18302
  this.events.formeoLoaded(this);
18189
18303
  }
18304
+ /**
18305
+ * Remove the editor from the page and release what it holds: its Sortable instances, resize
18306
+ * observers, window resize listener, pending callbacks and loaded components. Other editors on
18307
+ * the page keep working, and a new editor can mount in the same container.
18308
+ * Safe to call more than once, and before the editor is ready.
18309
+ * @return {void}
18310
+ */
18311
+ destroy() {
18312
+ if (this.isDestroyed) return;
18313
+ this.#initState = INIT_STATES.DESTROYED;
18314
+ document.removeEventListener("DOMContentLoaded", this.#onDOMContentLoaded);
18315
+ window.removeEventListener("resize", this.onResize);
18316
+ this.events.destroy();
18317
+ if (this.opts.sessionStorage) {
18318
+ const key = formDataStorageKey(this.opts.sessionStorage);
18319
+ if (storageKeyHolders.get(key) === this) storageKeyHolders.delete(key);
18320
+ }
18321
+ this.controls?.destroy();
18322
+ destroySortables(this.editor);
18323
+ for (const type of [
18324
+ "stages",
18325
+ "rows",
18326
+ "columns",
18327
+ "fields"
18328
+ ]) {
18329
+ for (const component of Object.values(this.Components[type]?.data || {})) component.panels?.destroy();
18330
+ this.Components[type]?.empty();
18331
+ }
18332
+ this.editor?.remove();
18333
+ this.Components.empty();
18334
+ if (pageTooltip && !document.querySelector(".formeo-editor")) {
18335
+ pageTooltip.destroy();
18336
+ pageTooltip = null;
18337
+ }
18338
+ this.tooltipInstance = null;
18339
+ this.editor = null;
18340
+ this.controls = null;
18341
+ this.Components.controls = null;
18342
+ this.stages = [];
18343
+ }
18190
18344
  };
18191
18345
  //#endregion
18192
18346
  //#region src/lib/js/renderer/helpers.js
@@ -18468,7 +18622,7 @@ var focusFirst = (page) => {
18468
18622
  * `progress` only affects the wizard, adding a clickable step list above the pages
18469
18623
  * @param {Array<Object>} stages stage data in render order, for page titles
18470
18624
  * @param {Function} [onChange] called with (page, previousPage) whenever the page changes
18471
- * @return {{show: Function, index: Number, count: Number}|null} null when there is only one page
18625
+ * @return {{show: Function, index: Number, count: Number, destroy: Function}|null} null when there is only one page
18472
18626
  */
18473
18627
  var paginate = (form, { type, progress, labels }, stages, onChange) => {
18474
18628
  const pages = Array.from(form.children).filter((elem) => elem.classList.contains(STAGE_CLASSNAME));
@@ -18661,14 +18815,16 @@ var paginate = (form, { type, progress, labels }, stages, onChange) => {
18661
18815
  }
18662
18816
  };
18663
18817
  const ownerDocument = form.ownerDocument;
18664
- ownerDocument.addEventListener("click", ({ target }) => {
18818
+ const onDocumentClick = ({ target }) => {
18665
18819
  const control = target.closest?.("button, input");
18666
18820
  if (control?.form !== form) return;
18667
18821
  if (control?.type === "submit" || control?.tagName === "INPUT" && control.type === "image") markReported();
18668
- }, true);
18669
- ownerDocument.addEventListener("keydown", ({ key, target }) => {
18822
+ };
18823
+ const onDocumentKeydown = ({ key, target }) => {
18670
18824
  if (key === "Enter" && target.tagName === "INPUT" && target.form === form) markReported();
18671
- }, true);
18825
+ };
18826
+ ownerDocument.addEventListener("click", onDocumentClick, true);
18827
+ ownerDocument.addEventListener("keydown", onDocumentKeydown, true);
18672
18828
  for (const method of ["requestSubmit", "reportValidity"]) {
18673
18829
  const native = HTMLFormElement.prototype[method];
18674
18830
  if (typeof native !== "function") continue;
@@ -18688,7 +18844,11 @@ var paginate = (form, { type, progress, labels }, stages, onChange) => {
18688
18844
  get index() {
18689
18845
  return current;
18690
18846
  },
18691
- count
18847
+ count,
18848
+ destroy() {
18849
+ ownerDocument.removeEventListener("click", onDocumentClick, true);
18850
+ ownerDocument.removeEventListener("keydown", onDocumentKeydown, true);
18851
+ }
18692
18852
  };
18693
18853
  };
18694
18854
  //#endregion
@@ -18815,8 +18975,21 @@ var FormeoRenderer$1 = class {
18815
18975
  formData: this.form
18816
18976
  });
18817
18977
  }
18978
+ /**
18979
+ * Remove the rendered form from the page and stop its pagination. render() can be called again afterwards.
18980
+ * @return {void}
18981
+ */
18982
+ destroy() {
18983
+ this.pager?.destroy();
18984
+ this.pager = null;
18985
+ this.renderedForm?.remove();
18986
+ this.renderedForm = null;
18987
+ this.components = Object.create(null);
18988
+ }
18818
18989
  getRenderedForm(formData = this.form) {
18819
18990
  this.form = cleanFormData(formData);
18991
+ this.pager?.destroy();
18992
+ this.pager = null;
18820
18993
  const renderCount = document.getElementsByClassName("formeo-render").length;
18821
18994
  const config = {
18822
18995
  ...this.config,