typo3-typescript-sources 14.3.8 → 14.3.9

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.
Files changed (175) hide show
  1. package/.github/workflows/sync-and-publish.yml +240 -191
  2. package/.last-synced-tag +1 -1
  3. package/README.md +13 -5
  4. package/adminpanel/admin-panel.ts +22 -22
  5. package/adminpanel/modules/cache.ts +3 -3
  6. package/backend/action-dispatcher.ts +8 -3
  7. package/backend/bookmark/bookmark-store.ts +5 -5
  8. package/backend/clipboard-panel.ts +2 -2
  9. package/backend/code-editor/element/code-mirror-element.ts +1 -1
  10. package/backend/code-editor/language/typoscript.ts +3 -3
  11. package/backend/code-editor/stream-parser/typoscript.ts +2 -2
  12. package/backend/color-picker.ts +2 -2
  13. package/backend/column-selector-button.ts +6 -6
  14. package/backend/context-help.ts +3 -3
  15. package/backend/context-menu.ts +8 -3
  16. package/backend/drag-tooltip.ts +9 -4
  17. package/backend/drag-uploader.ts +4 -4
  18. package/backend/element/draggable-resizable-element.ts +18 -12
  19. package/backend/element/icon-element.ts +2 -2
  20. package/backend/element/thumbnail-element.ts +2 -2
  21. package/backend/element-browser.ts +1 -1
  22. package/backend/event/consumer-scope.ts +2 -2
  23. package/backend/event/interaction-request-assignment.ts +1 -1
  24. package/backend/event/interaction-request-map.ts +3 -3
  25. package/backend/form-engine/container/flex-form-container-container.ts +2 -2
  26. package/backend/form-engine/container/flex-form-section-container.ts +1 -1
  27. package/backend/form-engine/container/inline-control-container.ts +14 -14
  28. package/backend/form-engine/element/abstract-sortable-select-items.ts +3 -3
  29. package/backend/form-engine/element/color-element.ts +1 -1
  30. package/backend/form-engine/element/datetime-element.ts +1 -1
  31. package/backend/form-engine/element/extra/char-counter.ts +2 -2
  32. package/backend/form-engine/element/extra/select-box-filter.ts +1 -1
  33. package/backend/form-engine/element/mfa-info-element.ts +2 -2
  34. package/backend/form-engine/element/online-media-form-element.ts +5 -1
  35. package/backend/form-engine/element/select-multiple-side-by-side-element.ts +2 -2
  36. package/backend/form-engine/element/select-tree.ts +3 -3
  37. package/backend/form-engine/element/slug-element.ts +7 -7
  38. package/backend/form-engine/element/suggest/result-container.ts +1 -1
  39. package/backend/form-engine/element/table-wizard-element.ts +4 -4
  40. package/backend/form-engine/inline-relation/ajax-dispatcher.ts +3 -3
  41. package/backend/form-engine-validation.ts +11 -5
  42. package/backend/form-engine.ts +11 -11
  43. package/backend/global-event-handler.ts +1 -1
  44. package/backend/hotkeys/hotkey-struct.ts +1 -1
  45. package/backend/hotkeys.ts +3 -3
  46. package/backend/image-manipulation.ts +19 -19
  47. package/backend/layout-module/drag-drop.ts +4 -4
  48. package/backend/layout-module/paste.ts +1 -1
  49. package/backend/live-search/element/result/item/action/action-container.ts +1 -1
  50. package/backend/live-search/element/result/item/item-container.ts +4 -4
  51. package/backend/live-search/element/result/result-container.ts +5 -0
  52. package/backend/live-search/element/result/result-pagination.ts +1 -1
  53. package/backend/live-search/live-search.ts +2 -2
  54. package/backend/localization/label-provider.ts +4 -4
  55. package/backend/localization/localization-wizard.ts +4 -4
  56. package/backend/localization/steps/content-record-selection-step.ts +8 -8
  57. package/backend/localization/steps/handler-selection-step.ts +4 -4
  58. package/backend/localization/steps/mode-step.ts +4 -4
  59. package/backend/localization/steps/source-language-step.ts +4 -4
  60. package/backend/localization/steps/target-language-step.ts +4 -4
  61. package/backend/login.ts +2 -2
  62. package/backend/module/iframe.ts +10 -0
  63. package/backend/module/router.ts +10 -0
  64. package/backend/module-menu.ts +3 -3
  65. package/backend/multi-record-selection-action.ts +1 -1
  66. package/backend/multi-record-selection-delete-action.ts +1 -1
  67. package/backend/multi-record-selection.ts +14 -14
  68. package/backend/multi-step-wizard.ts +9 -2
  69. package/backend/new-multiple-pages.ts +2 -2
  70. package/backend/new-record-wizard.ts +15 -15
  71. package/backend/page-wizard/page-wizard.ts +2 -2
  72. package/backend/page-wizard/steps/doktype-step.ts +5 -5
  73. package/backend/pagetsconfig/pagetsconfig-includes.ts +1 -1
  74. package/backend/popover.ts +5 -5
  75. package/backend/record-download-button.ts +1 -1
  76. package/backend/recordlist.ts +6 -6
  77. package/backend/security/element/csp-reports.ts +8 -8
  78. package/backend/setup-module.ts +2 -2
  79. package/backend/sortable-table.ts +10 -4
  80. package/backend/storage/abstract-client-storage.ts +2 -2
  81. package/backend/storage/module-state-storage.ts +2 -2
  82. package/backend/tests/backend/utility/dom-helper-test.ts +2 -2
  83. package/backend/tests/form-engine/element/extra/select-box-filter-test.ts +3 -3
  84. package/backend/tests/form-engine-validation-test.ts +1 -1
  85. package/backend/tests/tree/tree-test.ts +41 -0
  86. package/backend/tree/file-storage-browser.ts +1 -1
  87. package/backend/tree/file-storage-tree-container.ts +4 -4
  88. package/backend/tree/page-browser.ts +1 -1
  89. package/backend/tree/page-position-select.ts +1 -1
  90. package/backend/tree/page-tree-element.ts +1 -1
  91. package/backend/tree/page-tree.ts +7 -1
  92. package/backend/tree/tree-module-state.ts +5 -5
  93. package/backend/tree/tree.ts +15 -8
  94. package/backend/user-pass-login.ts +2 -2
  95. package/backend/utility/collapse-state-persister.ts +1 -1
  96. package/backend/utility/collapse-state-search.ts +6 -6
  97. package/backend/utility/dom-helper.ts +3 -3
  98. package/backend/utility.ts +6 -6
  99. package/backend/viewport/content-navigation.ts +5 -0
  100. package/backend/viewport/navigation-container.ts +1 -1
  101. package/backend/viewport/toolbar.ts +3 -3
  102. package/backend/window-manager.ts +2 -2
  103. package/backend/wizard/events/auto-advance-event.ts +6 -0
  104. package/backend/wizard/events/before-next-step-event.ts +6 -0
  105. package/backend/wizard/events/step-summary-event.ts +6 -0
  106. package/backend/wizard/move-content-element.ts +1 -1
  107. package/backend/wizard/wizard.ts +8 -10
  108. package/belog/backend-log.ts +2 -2
  109. package/beuser/permissions.ts +2 -2
  110. package/core/ajax/ajax-response.ts +1 -1
  111. package/core/ajax/input-transformer.ts +1 -1
  112. package/core/event/debounce-event.ts +4 -4
  113. package/core/event/event-interface.ts +3 -3
  114. package/core/event/regular-event.ts +7 -7
  115. package/core/event/request-animation-frame-event.ts +4 -4
  116. package/core/event/throttle-event.ts +4 -4
  117. package/core/java-script-item-processor.ts +6 -0
  118. package/core/referrer-refresh.ts +2 -2
  119. package/core/security-utility.ts +1 -1
  120. package/dashboard/dashboard-wizard.ts +2 -2
  121. package/dashboard/dashboard.ts +5 -5
  122. package/dashboard/wizard/steps/preset-step.ts +3 -3
  123. package/extensionmanager/main.ts +7 -7
  124. package/filelist/browse-files.ts +1 -1
  125. package/filelist/browse-folders.ts +2 -2
  126. package/filelist/file-list-dragdrop.ts +5 -5
  127. package/filelist/file-list-transfer-handler.ts +2 -2
  128. package/filelist/file-list.ts +5 -5
  129. package/form/backend/form-editor/component/date-editor.ts +4 -0
  130. package/form/backend/form-editor/component/form-element-selector.ts +4 -0
  131. package/form/backend/form-editor/inspector-component.ts +6 -6
  132. package/form/backend/form-editor/mediator.ts +36 -36
  133. package/form/backend/form-editor/modals-component.ts +1 -1
  134. package/form/backend/form-editor/stage-component.ts +4 -4
  135. package/form/backend/form-editor/view-model.ts +7 -7
  136. package/form/backend/form-manager/view-model.ts +5 -5
  137. package/form/backend/form-wizard/form-wizard.ts +2 -2
  138. package/form/backend/form-wizard/steps/storage-step.ts +1 -1
  139. package/impexp/import-export.ts +1 -1
  140. package/info/translation-status.ts +2 -2
  141. package/install/ajax/ajax-queue.ts +1 -1
  142. package/install/module/abstract-interactable-module.ts +2 -2
  143. package/install/module/environment/image-processing.ts +4 -4
  144. package/install/module/environment/mail-test.ts +2 -2
  145. package/install/module/maintenance/clear-tables.ts +3 -3
  146. package/install/module/maintenance/clear-typo3temp-files.ts +8 -8
  147. package/install/module/maintenance/create-admin.ts +3 -3
  148. package/install/module/maintenance/database-analyzer.ts +9 -7
  149. package/install/module/maintenance/language-packs.ts +4 -4
  150. package/install/module/maintenance/reference-index.ts +1 -1
  151. package/install/module/settings/change-install-tool-password.ts +1 -1
  152. package/install/module/settings/extension-configuration.ts +5 -5
  153. package/install/module/settings/features.ts +1 -1
  154. package/install/module/settings/local-configuration.ts +5 -5
  155. package/install/module/settings/presets.ts +2 -2
  156. package/install/module/settings/system-maintainer.ts +1 -1
  157. package/install/module/upgrade/extension-scanner.ts +5 -5
  158. package/install/module/upgrade/tca-migrations-check.ts +1 -1
  159. package/install/module/upgrade/upgrade-docs.ts +16 -16
  160. package/install/module/upgrade/upgrade-wizards.ts +7 -8
  161. package/install/renderable/language-packs.ts +8 -2
  162. package/lowlevel/query-generator.ts +2 -2
  163. package/package.json +2 -2
  164. package/redirects/event-handler.ts +6 -0
  165. package/rte-ckeditor/ckeditor5.ts +7 -3
  166. package/rte-ckeditor/tests/ckeditor5-test.ts +68 -0
  167. package/scheduler/form-engine/element/timing-options-element.ts +1 -1
  168. package/scheduler/scheduler.ts +2 -2
  169. package/styleguide/checkbox-demo.ts +1 -1
  170. package/tstemplate/template-analyzer.ts +1 -1
  171. package/viewpage/main.ts +1 -1
  172. package/workspaces/backend.ts +5 -5
  173. package/workspaces/preview.ts +2 -2
  174. package/workspaces/renderable/record-table.ts +1 -1
  175. package/workspaces/renderable/send-to-stage-form.ts +1 -1
@@ -280,7 +280,7 @@ class ImageManipulation {
280
280
  /**
281
281
  * Assign EventListener to cropVariantTriggers
282
282
  */
283
- this.cropVariantTriggers.forEach((el: HTMLElement) =>
283
+ this.cropVariantTriggers.forEach((el) =>
284
284
  el.addEventListener('click', (e: Event): void => {
285
285
  /**
286
286
  * Is the current cropVariantTrigger is active, bail out.
@@ -341,8 +341,8 @@ class ImageManipulation {
341
341
  new RegularEvent('click', (): void => this.openPreview(this.data))
342
342
  .delegateTo(this.currentModal, 'button[name=preview]');
343
343
  } else {
344
- this.currentModal.querySelectorAll('button[name=preview]')
345
- .forEach((previewButton: HTMLElement) => previewButton.style.display = 'none');
344
+ this.currentModal.querySelectorAll<HTMLElement>('button[name=preview]')
345
+ .forEach((previewButton) => previewButton.style.display = 'none');
346
346
  }
347
347
 
348
348
  /**
@@ -400,8 +400,8 @@ class ImageManipulation {
400
400
  this.syncEnabled = target.checked;
401
401
  BrowserSession.set('sync-active-' + imageUid, this.syncEnabled ? 'true' : 'false');
402
402
  if (this.syncEnabled) {
403
- this.currentModal.querySelectorAll('.panel-button[data-exclude-from-sync="true"]')
404
- .forEach((e: HTMLElement) => e.setAttribute('disabled', 'disabled'));
403
+ this.currentModal.querySelectorAll<HTMLElement>('.panel-button[data-exclude-from-sync="true"]')
404
+ .forEach((e) => e.setAttribute('disabled', 'disabled'));
405
405
 
406
406
  // if the currently selected crop variant is now disabled, open the first available one.
407
407
  const isDisabled = this.currentModal.querySelector('.panel-button[data-crop-variant-id="' + this.currentCropVariant.id + '"][data-exclude-from-sync="true"]') !== null;
@@ -412,8 +412,8 @@ class ImageManipulation {
412
412
  }
413
413
  }
414
414
  } else {
415
- this.currentModal.querySelectorAll('.panel-button[data-exclude-from-sync]')
416
- .forEach((e: HTMLElement) => e.removeAttribute('disabled'));
415
+ this.currentModal.querySelectorAll<HTMLElement>('.panel-button[data-exclude-from-sync]')
416
+ .forEach((e) => e.removeAttribute('disabled'));
417
417
  }
418
418
  }
419
419
  ).delegateTo(this.currentModal, '#sync-crop-variants');
@@ -446,7 +446,7 @@ class ImageManipulation {
446
446
  this.imageOriginalSizeFactor = parseInt(image.dataset.originalWidth, 10) / imageData.naturalWidth;
447
447
 
448
448
  // iterate over the crop variants and set up their respective preview
449
- this.cropVariantTriggers.forEach((elem: HTMLElement): void => {
449
+ this.cropVariantTriggers.forEach((elem): void => {
450
450
  const cropVariantId: string = elem.dataset.cropVariantId;
451
451
  const cropArea: Area = this.convertRelativeToAbsoluteCropArea(
452
452
  this.data[cropVariantId].cropArea,
@@ -507,9 +507,9 @@ class ImageManipulation {
507
507
 
508
508
  if (this.syncAvailable && this.syncEnabled) {
509
509
  const data = this.data;
510
- Object.keys(this.data).forEach((cropVariant: string): void => {
510
+ Object.keys(this.data).forEach((cropVariant): void => {
511
511
  let trigger: HTMLElement = null;
512
- this.cropVariantTriggers.forEach((e: HTMLElement) => {
512
+ this.cropVariantTriggers.forEach((e) => {
513
513
  if (e.dataset.cropVariantId === cropVariant) {
514
514
  trigger = e;
515
515
  }
@@ -540,9 +540,9 @@ class ImageManipulation {
540
540
 
541
541
  if (this.syncAvailable && this.syncEnabled) {
542
542
  const data = this.data;
543
- Object.keys(this.data).forEach((cropVariant: string): void => {
543
+ Object.keys(this.data).forEach((cropVariant): void => {
544
544
  let trigger: HTMLElement = null;
545
- this.cropVariantTriggers.forEach((e: HTMLElement) => {
545
+ this.cropVariantTriggers.forEach((e) => {
546
546
  if (e.dataset.cropVariantId === cropVariant) {
547
547
  trigger = e;
548
548
  }
@@ -579,8 +579,8 @@ class ImageManipulation {
579
579
  this.setAspectRatio(selectedRatio);
580
580
  this.setCropArea(temp.cropArea);
581
581
  this.currentCropVariant = Object.assign({}, temp, cropVariant);
582
- this.cropBox?.querySelectorAll(this.coverAreaSelector)?.forEach((el: HTMLElement) => el.remove());
583
- this.cropBox?.querySelectorAll(this.focusAreaSelector)?.forEach((el: HTMLElement) => el.remove());
582
+ this.cropBox?.querySelectorAll<HTMLElement>(this.coverAreaSelector)?.forEach((el) => el.remove());
583
+ this.cropBox?.querySelectorAll<HTMLElement>(this.focusAreaSelector)?.forEach((el) => el.remove());
584
584
 
585
585
  // check if new cropVariant has focusArea
586
586
  if (cropVariant.focusArea) {
@@ -655,7 +655,7 @@ class ImageManipulation {
655
655
  * @param {Array<Area>} coverAreas - An array of areas to construct the cover area elements from
656
656
  */
657
657
  private initCoverAreas(container: HTMLElement, coverAreas: Area[]): void {
658
- coverAreas.forEach((coverArea: Area): void => {
658
+ coverAreas.forEach((coverArea): void => {
659
659
  const styles = {
660
660
  height: ImageManipulation.toCssPercent(coverArea.height),
661
661
  left: ImageManipulation.toCssPercent(coverArea.x),
@@ -782,7 +782,7 @@ class ImageManipulation {
782
782
  return false;
783
783
  }
784
784
  return coverAreas
785
- .some((coverArea: Area): boolean => {
785
+ .some((coverArea): boolean => {
786
786
  return focusArea.x < coverArea.x + coverArea.width
787
787
  && coverArea.x < focusArea.x + focusArea.width
788
788
  && focusArea.y < coverArea.y + coverArea.height
@@ -831,7 +831,7 @@ class ImageManipulation {
831
831
  const imageData: Cropper.ImageData = this.cropper.getImageData();
832
832
 
833
833
  // iterate over the crop variants and set up their respective preview
834
- Object.keys(data).forEach((cropVariantId: string) => {
834
+ Object.keys(data).forEach((cropVariantId) => {
835
835
  const cropVariant: CropVariant = data[cropVariantId];
836
836
  const cropData: Area = this.convertRelativeToAbsoluteCropArea(cropVariant.cropArea, imageData);
837
837
 
@@ -956,8 +956,8 @@ class ImageManipulation {
956
956
 
957
957
  private renderElements(template: TemplateResult, target: HTMLElement, selector?: string): HTMLElement|null {
958
958
  const nodes = renderNodes(template);
959
- const elements = Array.from(nodes).filter((node: Node): boolean => node instanceof HTMLElement);
960
- elements.forEach((element: HTMLElement) => target.appendChild(element));
959
+ const elements = Array.from(nodes).filter((node): node is HTMLElement => node instanceof HTMLElement);
960
+ elements.forEach((element) => target.appendChild(element));
961
961
  return selector ? target.querySelector(selector) : null;
962
962
  }
963
963
  }
@@ -314,9 +314,9 @@ class DragDrop {
314
314
  iconIdentifier = contentElementIcon.dataset.identifier;
315
315
  }
316
316
 
317
- const contentImagePreviews = contentElement.querySelectorAll('.preview-thumbnails-element-image img');
317
+ const contentImagePreviews = contentElement.querySelectorAll<HTMLImageElement>('.preview-thumbnails-element-image img');
318
318
  if (contentImagePreviews.length > 0) {
319
- contentImagePreviews.forEach((image: HTMLImageElement): void => {
319
+ contentImagePreviews.forEach((image): void => {
320
320
  thumbnails.push({
321
321
  src: image.src,
322
322
  height: image.height,
@@ -343,7 +343,7 @@ class DragDrop {
343
343
  }
344
344
 
345
345
  protected showDropZones(): void {
346
- document.querySelectorAll(Identifiers.dropZone).forEach((element: HTMLElement): void => {
346
+ document.querySelectorAll<HTMLElement>(Identifiers.dropZone).forEach((element): void => {
347
347
  if (!isContentTypeAllowedInColumn(this.draggedContentType, element.closest('[data-colpos]'))) {
348
348
  return;
349
349
  }
@@ -357,7 +357,7 @@ class DragDrop {
357
357
  }
358
358
 
359
359
  protected hideDropZones(): void {
360
- document.querySelectorAll(Identifiers.dropZone).forEach((element: HTMLElement): void => {
360
+ document.querySelectorAll<HTMLElement>(Identifiers.dropZone).forEach((element): void => {
361
361
  element.hidden = true;
362
362
  const addContentButton = element.parentElement.querySelector(Identifiers.addContent) as HTMLElement;
363
363
  if (addContentButton !== null) {
@@ -99,7 +99,7 @@ class Paste {
99
99
  */
100
100
  private activatePasteIcons(): void {
101
101
  if (this.pasteAfterLinkTemplate && this.pasteIntoLinkTemplate) {
102
- document.querySelectorAll('.t3js-page-new-ce').forEach((el: HTMLElement): void => {
102
+ document.querySelectorAll<HTMLElement>('.t3js-page-new-ce').forEach((el): void => {
103
103
  if (!isContentTypeAllowedForTarget(this.itemOnClipboardCType, el)) {
104
104
  return;
105
105
  }
@@ -31,7 +31,7 @@ export class ActionContainer extends LitElement {
31
31
 
32
32
  protected override render(): TemplateResult {
33
33
  return html`<typo3-backend-live-search-result-action-list>
34
- ${this.resultItem.actions.map((action: ResultItemActionInterface) => this.renderActionItem(this.resultItem, action))}
34
+ ${this.resultItem.actions.map((action) => this.renderActionItem(this.resultItem, action))}
35
35
  </typo3-backend-live-search-result-action-list>`;
36
36
  }
37
37
 
@@ -45,13 +45,13 @@ export class ItemContainer extends LitElement {
45
45
 
46
46
  protected override render(): TemplateResult {
47
47
  const groupedResults: GroupedResultItems = {};
48
- const filteredResults = this.results.filter((result: ResultItemInterface): boolean => result !== null);
48
+ const filteredResults = this.results.filter((result): boolean => result !== null);
49
49
  if (filteredResults.length !== this.results.length) {
50
50
  console.warn(
51
51
  'The result set contained "null" values, indicating something went wrong while building the search results. Affected values were removed to no break the user interface.'
52
52
  );
53
53
  }
54
- filteredResults.forEach((result: ResultItemInterface): void => {
54
+ filteredResults.forEach((result): void => {
55
55
  if (!(result.typeLabel in groupedResults)) {
56
56
  groupedResults[result.typeLabel] = [result];
57
57
  } else {
@@ -69,7 +69,7 @@ export class ItemContainer extends LitElement {
69
69
  for (const [type, results] of Object.entries(groupedResults)) {
70
70
  const countElements = results.length;
71
71
  items.push(html`<h6 class="livesearch-result-item-group-label">${type} (${countElements})</h6>`);
72
- items.push(...results.map((result: ResultItemInterface) => html`${until(
72
+ items.push(...results.map((result) => html`${until(
73
73
  this.renderResultItem(result),
74
74
  html`<typo3-backend-spinner></typo3-backend-spinner>`
75
75
  )}`));
@@ -122,7 +122,7 @@ export class ItemContainer extends LitElement {
122
122
  }
123
123
 
124
124
  private onScroll(e: Event): void {
125
- this.querySelectorAll('.livesearch-result-item-group-label').forEach((groupLabel: HTMLElement): void => {
125
+ this.querySelectorAll<HTMLElement>('.livesearch-result-item-group-label').forEach((groupLabel): void => {
126
126
  groupLabel.classList.toggle('sticky', groupLabel.offsetTop <= (e.target as HTMLElement).scrollTop);
127
127
  });
128
128
  }
@@ -112,4 +112,9 @@ declare global {
112
112
  interface HTMLElementTagNameMap {
113
113
  'typo3-backend-live-search-result-container': ResultContainer;
114
114
  }
115
+
116
+ interface HTMLElementEventMap {
117
+ 'livesearch:request-actions': CustomEvent<RequestActionsEventData>;
118
+ 'livesearch:invoke-action': CustomEvent<InvokeActionEventData>;
119
+ }
115
120
  }
@@ -57,7 +57,7 @@ export class ResultPagination extends LitElement {
57
57
  </typo3-backend-live-search-result-page>
58
58
  </li>` : nothing}
59
59
  ${this.pagination.hasLessPages ? html`<li class="page-item disabled"><span class="page-link disabled">&hellip;</span></li>` : nothing}
60
- ${this.pagination.allPageNumbers.map((page: number) => html`
60
+ ${this.pagination.allPageNumbers.map((page) => html`
61
61
  <li class="page-item">
62
62
  <typo3-backend-live-search-result-page page="${page}" perPage="${this.pagination.itemsPerPage}" class="page-link ${this.pagination.currentPage === page ? 'active' : ''}">${page}</typo3-backend-live-search-result-page>
63
63
  </li>
@@ -187,7 +187,7 @@ class LiveSearch {
187
187
  * // do stuff here
188
188
  * });
189
189
  */
190
- ['modal-loaded', 'typo3-modal-shown'].forEach((eventToListenOn: string) => {
190
+ ['modal-loaded', 'typo3-modal-shown'].forEach((eventToListenOn) => {
191
191
  modal.addEventListener(eventToListenOn, () => {
192
192
  const searchField = modal.querySelector('input[type="search"]') as HTMLInputElement|null;
193
193
  if (searchField !== null) {
@@ -200,7 +200,7 @@ class LiveSearch {
200
200
 
201
201
  private composeSearchOptions(searchOptions: SearchOption[]): { [key: string]: string[] } {
202
202
  const composedSearchOptions: { [key: string]: string[] } = {};
203
- searchOptions.forEach((searchOption: SearchOption): void => {
203
+ searchOptions.forEach((searchOption): void => {
204
204
  if (composedSearchOptions[searchOption.key] === undefined) {
205
205
  composedSearchOptions[searchOption.key] = [];
206
206
  }
@@ -129,8 +129,8 @@ function createFormatter(label: string): IntlMessageFormat {
129
129
  }
130
130
 
131
131
  const formatters: Formatters = {
132
- getNumberFormat: memoize('number', (locale, opts) => new Intl.NumberFormat(locale, opts)),
133
- getDateTimeFormat: memoize('datetime', (locale, opts) => {
132
+ getNumberFormat: memoize('number', (locale?: string | string[], opts?: Intl.NumberFormatOptions) => new Intl.NumberFormat(locale, opts)),
133
+ getDateTimeFormat: memoize('datetime', (locale?: Intl.LocalesArgument, opts?: Intl.DateTimeFormatOptions) => {
134
134
  const { dateStyle, timeStyle, timeZone } = opts;
135
135
 
136
136
  // Apply configured TYPO3 date format to the "medium" preset
@@ -152,10 +152,10 @@ const formatters: Formatters = {
152
152
 
153
153
  return new Intl.DateTimeFormat(locale, { dateStyle, timeStyle, timeZone });
154
154
  }),
155
- getPluralRules: memoize('date', (locale, opts) => new Intl.PluralRules(locale, opts)),
155
+ getPluralRules: memoize('date', (locale?: Intl.LocalesArgument, opts?: Intl.PluralRulesOptions) => new Intl.PluralRules(locale, opts)),
156
156
  };
157
157
 
158
- type Factory = (...args: unknown[]) => object;
158
+ type Factory = (...args: never[]) => object;
159
159
  const cache: Record<string, object> = {};
160
160
  /**
161
161
  * Cache the (object) result of a factory function,
@@ -48,7 +48,7 @@ export interface LocalizationDataStore extends DataStore {
48
48
  type LocalizationDataStoreKey = keyof LocalizationDataStore;
49
49
 
50
50
  export interface LocalizationContext {
51
- wizard: Wizard;
51
+ wizard: Wizard<LocalizationDataStore>;
52
52
  targetLanguage: number;
53
53
  recordType: string;
54
54
  recordUid: number;
@@ -72,13 +72,13 @@ export class LocalizationWizard extends LitElement {
72
72
  @property({ type: Number, attribute: 'record-uid' }) recordUid: number;
73
73
  @property({ type: Number, attribute: 'target-language' }) targetLanguage?: number;
74
74
 
75
- @query('typo3-backend-wizard') wizard!: Wizard;
75
+ @query('typo3-backend-wizard') wizard!: Wizard<LocalizationDataStore>;
76
76
 
77
77
  @state() steps: WizardStepInterface[] = [];
78
78
  @state() submissionService: SubmissionServiceInterface;
79
79
 
80
80
  protected readonly recordInfoTask = new Task(this, {
81
- task: async ([recordType, recordUid]: [string, number]): Promise<RecordInfo> => {
81
+ task: async ([recordType, recordUid]): Promise<RecordInfo> => {
82
82
  try {
83
83
  const response = await new AjaxRequest(TYPO3.settings.ajaxUrls.wizard_localization_get_record).withQueryArguments({
84
84
  recordType: recordType,
@@ -97,7 +97,7 @@ export class LocalizationWizard extends LitElement {
97
97
  throw error;
98
98
  }
99
99
  },
100
- args: () => [this.recordType, this.recordUid],
100
+ args: () => [this.recordType, this.recordUid] as const,
101
101
  });
102
102
 
103
103
  override connectedCallback() {
@@ -72,7 +72,7 @@ export class ContentRecordSelectionStep implements WizardStepInterface, WizardSt
72
72
 
73
73
  constructor(private readonly context: LocalizationContext) {
74
74
  this.task = new Task(this.context.wizard, {
75
- task: async ([pageUid, targetLanguage, sourceLanguage]: [number, number, number]): Promise<PageRecordSelection> => {
75
+ task: async ([pageUid, targetLanguage, sourceLanguage]): Promise<PageRecordSelection> => {
76
76
  const response = await new AjaxRequest(TYPO3.settings.ajaxUrls.wizard_localization_get_content).withQueryArguments({
77
77
  pageUid: pageUid,
78
78
  targetLanguage: targetLanguage,
@@ -82,7 +82,7 @@ export class ContentRecordSelectionStep implements WizardStepInterface, WizardSt
82
82
 
83
83
  return result;
84
84
  },
85
- args: () => [this.context.recordUid, this.context.getStoreData('targetLanguage'), this.context.getStoreData('sourceLanguage')],
85
+ args: () => [this.context.recordUid, this.context.getStoreData('targetLanguage'), this.context.getStoreData('sourceLanguage')] as const,
86
86
  autoRun: false
87
87
  });
88
88
  }
@@ -194,9 +194,9 @@ export class ContentRecordSelectionStep implements WizardStepInterface, WizardSt
194
194
  const records: ContentRecord[] = [];
195
195
 
196
196
  if (this.task.value) {
197
- this.task.value.layout.rows.forEach((row: LayoutRow) => {
198
- row.columns.forEach((column: LayoutColumn) => {
199
- column.records.forEach((record: ContentRecord) => {
197
+ this.task.value.layout.rows.forEach((row) => {
198
+ row.columns.forEach((column) => {
199
+ column.records.forEach((record) => {
200
200
  if (selectedUids.includes(record.uid)) {
201
201
  records.push(record);
202
202
  }
@@ -355,9 +355,9 @@ export class ContentRecordSelectionStep implements WizardStepInterface, WizardSt
355
355
 
356
356
  private getAllRecordUids(layout: BackendLayoutStructure): number[] {
357
357
  const allUids: number[] = [];
358
- layout.rows.forEach((row: LayoutRow) => {
359
- row.columns.forEach((column: LayoutColumn) => {
360
- column.records.forEach((record: ContentRecord) => {
358
+ layout.rows.forEach((row) => {
359
+ row.columns.forEach((column) => {
360
+ column.records.forEach((record) => {
361
361
  allUids.push(record.uid);
362
362
  });
363
363
  });
@@ -40,7 +40,7 @@ export class HandlerSelectionStep implements WizardStepInterface, WizardStepValu
40
40
 
41
41
  constructor(private readonly context: LocalizationContext) {
42
42
  this.task = new Task(this.context.wizard, {
43
- task: async ([recordType, recordUid, sourceLanguage, targetLanguage, mode]: [string, number, number | null, number | null, string | null]): Promise<LocalizationHandler[]> => {
43
+ task: async ([recordType, recordUid, sourceLanguage, targetLanguage, mode]): Promise<LocalizationHandler[]> => {
44
44
  if (sourceLanguage == null || targetLanguage == null || mode == null) {
45
45
  return [];
46
46
  }
@@ -58,7 +58,7 @@ export class HandlerSelectionStep implements WizardStepInterface, WizardStepValu
58
58
 
59
59
  return handlers;
60
60
  },
61
- args: () => [this.context.recordType, this.context.recordUid, this.context.getStoreData('sourceLanguage'), this.context.getStoreData('targetLanguage'), this.context.getStoreData('localizationMode')],
61
+ args: () => [this.context.recordType, this.context.recordUid, this.context.getStoreData('sourceLanguage'), this.context.getStoreData('targetLanguage'), this.context.getStoreData('localizationMode')] as const,
62
62
  autoRun: false
63
63
  });
64
64
  }
@@ -114,7 +114,7 @@ export class HandlerSelectionStep implements WizardStepInterface, WizardStepValu
114
114
  <h2 class="h4">${localizationWizardLabels.get('step.handler_selection.headline')}</h2>
115
115
  <p>${localizationWizardLabels.get('step.handler_selection.description')}</p>
116
116
  <div class="form-check-card-container">
117
- ${handlers.map((handler: LocalizationHandler) => this.renderHandlerOption(handler))}
117
+ ${handlers.map((handler) => this.renderHandlerOption(handler))}
118
118
  </div>
119
119
  </div>
120
120
  `;
@@ -147,7 +147,7 @@ export class HandlerSelectionStep implements WizardStepInterface, WizardStepValu
147
147
  return [];
148
148
  }
149
149
 
150
- const handler = this.task.value.find((h: LocalizationHandler) => h.identifier === selectedHandler);
150
+ const handler = this.task.value.find((h) => h.identifier === selectedHandler);
151
151
  if (!handler) {
152
152
  return [];
153
153
  }
@@ -41,7 +41,7 @@ export class ModeStep implements WizardStepInterface, WizardStepValueInterface,
41
41
 
42
42
  constructor(private readonly context: LocalizationContext) {
43
43
  this.task = new Task(this.context.wizard, {
44
- task: async ([recordType, recordUid, targetLanguage, sourceLanguage]: [string, number, number | null, number | null]): Promise<LocalizationMode[]> => {
44
+ task: async ([recordType, recordUid, targetLanguage, sourceLanguage]): Promise<LocalizationMode[]> => {
45
45
  if (targetLanguage == null || sourceLanguage == null) {
46
46
  return [];
47
47
  }
@@ -56,7 +56,7 @@ export class ModeStep implements WizardStepInterface, WizardStepValueInterface,
56
56
 
57
57
  return modes;
58
58
  },
59
- args: () => [this.context.recordType, this.context.recordUid, this.context.getStoreData('targetLanguage'), this.context.getStoreData('sourceLanguage')],
59
+ args: () => [this.context.recordType, this.context.recordUid, this.context.getStoreData('targetLanguage'), this.context.getStoreData('sourceLanguage')] as const,
60
60
  autoRun: false
61
61
  });
62
62
  }
@@ -110,7 +110,7 @@ export class ModeStep implements WizardStepInterface, WizardStepValueInterface,
110
110
  content = html`
111
111
  <p>${localizationWizardLabels.get('step.modes.description')}</p>
112
112
  <div class="form-check-card-container">
113
- ${modes.map((mode: LocalizationMode) => html`
113
+ ${modes.map((mode) => html`
114
114
  <div class="form-check form-check-type-card">
115
115
  <input
116
116
  class="form-check-input"
@@ -171,7 +171,7 @@ export class ModeStep implements WizardStepInterface, WizardStepValueInterface,
171
171
  return [];
172
172
  }
173
173
 
174
- const mode = this.task.value.find((m: LocalizationMode) => m.key === selectedMode);
174
+ const mode = this.task.value.find((m) => m.key === selectedMode);
175
175
  if (!mode) {
176
176
  return [];
177
177
  }
@@ -33,7 +33,7 @@ export class SourceLanguageStep implements WizardStepInterface, WizardStepValueI
33
33
 
34
34
  constructor(private readonly context: LocalizationContext) {
35
35
  this.task = new Task(this.context.wizard, {
36
- task: async ([recordType, recordUid, targetLanguageId]: [string, number, number | null]): Promise<LocalizationLanguageRecord[]> => {
36
+ task: async ([recordType, recordUid, targetLanguageId]): Promise<LocalizationLanguageRecord[]> => {
37
37
  if (targetLanguageId == null) {
38
38
  return [];
39
39
  }
@@ -47,7 +47,7 @@ export class SourceLanguageStep implements WizardStepInterface, WizardStepValueI
47
47
 
48
48
  return sourceLanguages;
49
49
  },
50
- args: () => [this.context.recordType, this.context.recordUid, this.context.getStoreData('targetLanguage')],
50
+ args: () => [this.context.recordType, this.context.recordUid, this.context.getStoreData('targetLanguage')] as const,
51
51
  autoRun: false
52
52
  });
53
53
  }
@@ -108,7 +108,7 @@ export class SourceLanguageStep implements WizardStepInterface, WizardStepValueI
108
108
  <h2 class="h4">${localizationWizardLabels.get('step.source_language.headline')}</h2>
109
109
  <p>${localizationWizardLabels.get('step.source_language.description')}</p>
110
110
  <div class="form-check-card-container">
111
- ${languages.map((language: LocalizationLanguageRecord) => html`
111
+ ${languages.map((language) => html`
112
112
  <div class="form-check form-check-type-card">
113
113
  <input
114
114
  class="form-check-input"
@@ -159,7 +159,7 @@ export class SourceLanguageStep implements WizardStepInterface, WizardStepValueI
159
159
  return [];
160
160
  }
161
161
 
162
- const selectedLanguage = this.task.value.find((lang: LocalizationLanguageRecord) => lang.uid === selectedSourceLanguage);
162
+ const selectedLanguage = this.task.value.find((lang) => lang.uid === selectedSourceLanguage);
163
163
  if (!selectedLanguage) {
164
164
  return [];
165
165
  }
@@ -36,7 +36,7 @@ export class TargetLanguageStep implements WizardStepInterface, WizardStepValueI
36
36
 
37
37
  constructor(private readonly context: LocalizationContext) {
38
38
  this.task = new Task(this.context.wizard, {
39
- task: async ([recordType, recordUid]: [string, number]): Promise<LocalizationLanguageRecord[]> => {
39
+ task: async ([recordType, recordUid]): Promise<LocalizationLanguageRecord[]> => {
40
40
  const response = await new AjaxRequest(TYPO3.settings.ajaxUrls.wizard_localization_get_targets).withQueryArguments({
41
41
  recordType: recordType,
42
42
  recordUid: recordUid,
@@ -51,7 +51,7 @@ export class TargetLanguageStep implements WizardStepInterface, WizardStepValueI
51
51
 
52
52
  return targetLanguages;
53
53
  },
54
- args: () => [this.context.recordType, this.context.recordUid],
54
+ args: () => [this.context.recordType, this.context.recordUid] as const,
55
55
  autoRun: false
56
56
  });
57
57
  }
@@ -120,7 +120,7 @@ export class TargetLanguageStep implements WizardStepInterface, WizardStepValueI
120
120
  <h2 class="h4">${localizationWizardLabels.get('step.target_language.headline')}</h2>
121
121
  <p>${localizationWizardLabels.get('step.target_language.description')}</p>
122
122
  <div class="form-check-card-container">
123
- ${languages.map((language: LocalizationLanguageRecord) => html`
123
+ ${languages.map((language) => html`
124
124
  <div class="form-check form-check-type-card">
125
125
  <input
126
126
  class="form-check-input"
@@ -171,7 +171,7 @@ export class TargetLanguageStep implements WizardStepInterface, WizardStepValueI
171
171
  return [];
172
172
  }
173
173
 
174
- const selectedLanguage = this.task.value.find((lang: LocalizationLanguageRecord) => lang.uid === selectedTargetLanguage);
174
+ const selectedLanguage = this.task.value.find((lang) => lang.uid === selectedTargetLanguage);
175
175
  if (!selectedLanguage) {
176
176
  return [];
177
177
  }
package/backend/login.ts CHANGED
@@ -117,7 +117,7 @@ class BackendLogin {
117
117
  const result = await response.resolve('application/json') as PreflightResponse;
118
118
  if (result.capabilities.referrer !== true) {
119
119
  document.querySelectorAll(this.options.errorNoReferrer)
120
- .forEach((element: HTMLElement): void => element.classList.remove('hidden'));
120
+ .forEach((element): void => element.classList.remove('hidden'));
121
121
  }
122
122
  });
123
123
  }
@@ -186,7 +186,7 @@ class BackendLogin {
186
186
  }
187
187
 
188
188
  (document.querySelectorAll('.t3js-clearable') as NodeListOf<HTMLInputElement>).forEach(
189
- (clearableField: HTMLInputElement) => clearableField.clearable(),
189
+ (clearableField) => clearableField.clearable(),
190
190
  );
191
191
 
192
192
  const passwordField: HTMLInputElement = document.querySelector(this.options.passwordField);
@@ -122,4 +122,14 @@ declare global {
122
122
  interface HTMLElementTagNameMap {
123
123
  'typo3-iframe-module': IframeModuleElement;
124
124
  }
125
+
126
+ interface HTMLElementEventMap {
127
+ 'typo3-iframe-load': CustomEvent<ModuleState>;
128
+ 'typo3-iframe-loaded': CustomEvent<ModuleState>;
129
+ }
130
+
131
+ interface DocumentEventMap {
132
+ 'typo3-iframe-load': CustomEvent<ModuleState>;
133
+ 'typo3-iframe-loaded': CustomEvent<ModuleState>;
134
+ }
125
135
  }
@@ -266,4 +266,14 @@ declare global {
266
266
  interface HTMLElementTagNameMap {
267
267
  'typo3-backend-module-router': ModuleRouter;
268
268
  }
269
+
270
+ interface HTMLElementEventMap {
271
+ 'typo3-module-load': CustomEvent<ModuleState>;
272
+ 'typo3-module-loaded': CustomEvent<ModuleState>;
273
+ }
274
+
275
+ interface DocumentEventMap {
276
+ 'typo3-module-load': CustomEvent<ModuleState>;
277
+ 'typo3-module-loaded': CustomEvent<ModuleState>;
278
+ }
269
279
  }
@@ -160,7 +160,7 @@ class ModuleMenu {
160
160
 
161
161
  private static highlightModule(identifier: string): void {
162
162
  const menu = document.querySelector(ModuleMenuSelector.menu);
163
- menu.querySelectorAll(ModuleMenuSelector.item).forEach((element: Element) => {
163
+ menu.querySelectorAll(ModuleMenuSelector.item).forEach((element) => {
164
164
  element.classList.remove('modulemenu-action-active');
165
165
  element.removeAttribute('aria-current');
166
166
  });
@@ -171,8 +171,8 @@ class ModuleMenu {
171
171
 
172
172
  private static highlightModuleMenuItem(module: Module, current: boolean = true): void {
173
173
  const menu = document.querySelector(ModuleMenuSelector.menu);
174
- const menuElements = menu.querySelectorAll(ModuleMenuSelector.item + selector`[data-modulemenu-identifier="${module.name}"]`);
175
- menuElements.forEach((element: HTMLElement) => {
174
+ const menuElements = menu.querySelectorAll<HTMLElement>(ModuleMenuSelector.item + selector`[data-modulemenu-identifier="${module.name}"]`);
175
+ menuElements.forEach((element) => {
176
176
  element.classList.add('modulemenu-action-active');
177
177
  if (current) {
178
178
  element.setAttribute('aria-current', 'location');
@@ -33,7 +33,7 @@ export class MultiRecordSelectionAction {
33
33
  {
34
34
  // Evaluate all checked records and if valid, add their uid to the list
35
35
  const entityIdentifiers: Array<string> = [];
36
- eventDetails.checkboxes.forEach((checkbox: HTMLInputElement): void => {
36
+ eventDetails.checkboxes.forEach((checkbox): void => {
37
37
  const checkboxContainer: HTMLElement = checkbox.closest(MultiRecordSelectionSelectors.elementSelector);
38
38
  if (checkboxContainer !== null && checkboxContainer.dataset[eventDetails.configuration.idField]) {
39
39
  entityIdentifiers.push(checkboxContainer.dataset[eventDetails.configuration.idField]);
@@ -85,7 +85,7 @@ class MultiRecordSelectionDeleteAction {
85
85
  try {
86
86
  const result = await AjaxDataHandler.process({
87
87
  cmd: {
88
- [tableName]: Object.fromEntries(entityIdentifiers.map((identifier: string): [string, DatahandlerCommand] => [
88
+ [tableName]: Object.fromEntries(entityIdentifiers.map((identifier): [string, DatahandlerCommand] => [
89
89
  identifier, { delete: 1 }
90
90
  ]))
91
91
  }