typo3-typescript-sources 13.4.25 → 13.4.29

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.
@@ -2,111 +2,142 @@ name: Sync TYPO3 TypeScript Sources and Publish
2
2
 
3
3
  on:
4
4
  schedule:
5
- # Prüfe täglich um 2 Uhr morgens auf neue Tags
5
+ # Check daily at 2 AM for new tags
6
6
  - cron: '0 2 * * *'
7
7
  workflow_dispatch:
8
8
  inputs:
9
9
  tag:
10
- description: 'Spezifischer TYPO3 Tag (z.B. v13.4.0)'
10
+ description: 'Specific TYPO3 tag (e.g. v14.0.0 or v13.4.0)'
11
11
  required: false
12
12
  type: string
13
13
 
14
+ permissions:
15
+ contents: read
16
+
14
17
  jobs:
15
- check-and-sync:
18
+ setup:
16
19
  runs-on: ubuntu-latest
17
20
  outputs:
18
- has_new_version: ${{ steps.check.outputs.has_new_version }}
19
- typo3_version: ${{ steps.check.outputs.typo3_version }}
21
+ matrix: ${{ steps.set-matrix.outputs.matrix }}
22
+ steps:
23
+ - name: Build version matrix
24
+ id: set-matrix
25
+ run: |
26
+ if [[ "${{ github.event_name }}" == "schedule" ]]; then
27
+ # Schedule runs daily for both major versions
28
+ echo 'matrix={"include":[{"major_version":"14","target_branch":"main"},{"major_version":"13","target_branch":"v13.x"}]}' >> $GITHUB_OUTPUT
29
+ elif [[ "${{ github.ref_name }}" == "v13.x" ]]; then
30
+ echo 'matrix={"include":[{"major_version":"13","target_branch":"v13.x"}]}' >> $GITHUB_OUTPUT
31
+ else
32
+ echo 'matrix={"include":[{"major_version":"14","target_branch":"main"}]}' >> $GITHUB_OUTPUT
33
+ fi
34
+
35
+ check-and-sync:
36
+ needs: setup
37
+ runs-on: ubuntu-latest
38
+ strategy:
39
+ fail-fast: false
40
+ matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
20
41
  steps:
21
42
  - name: Checkout split repository
22
43
  uses: actions/checkout@v4
23
44
  with:
45
+ ref: ${{ matrix.target_branch }}
24
46
  fetch-depth: 0
25
47
 
26
48
  - name: Check for new TYPO3 tags
27
49
  id: check
28
50
  run: |
29
- # Hole alle Tags vom TYPO3 Repository
51
+ MAJOR="${{ matrix.major_version }}"
52
+
53
+ # Fetch all tags from TYPO3 repository for the target major version
30
54
  git ls-remote --tags https://github.com/TYPO3/typo3.git | \
31
- grep -E 'refs/tags/v13\.[0-9]+\.[0-9]+$' | \
55
+ grep -E "refs/tags/v${MAJOR}\.[0-9]+\.[0-9]+$" | \
32
56
  sed 's/.*refs\/tags\///' | \
33
57
  sort -V > /tmp/typo3_tags.txt
34
-
35
- # Hole den letzten verarbeiteten Tag (falls vorhanden)
58
+
59
+ # Get last synced tag
36
60
  LAST_SYNCED=""
37
61
  if [ -f .last-synced-tag ]; then
38
62
  LAST_SYNCED=$(cat .last-synced-tag)
39
63
  fi
40
-
41
- # Manueller Tag-Input hat Priorität
64
+
65
+ # Manual tag input takes priority
42
66
  if [ -n "${{ github.event.inputs.tag }}" ]; then
43
67
  NEW_TAG="${{ github.event.inputs.tag }}"
44
- echo "Manuell angegebener Tag: $NEW_TAG"
68
+ # Validate that the manual tag matches the expected major version
69
+ if ! echo "$NEW_TAG" | grep -qE "^v${MAJOR}\."; then
70
+ echo "Error: Tag $NEW_TAG does not match expected major version v${MAJOR}.x for this branch"
71
+ echo "has_new_version=false" >> $GITHUB_OUTPUT
72
+ exit 0
73
+ fi
74
+ echo "Manually specified tag: $NEW_TAG"
45
75
  else
46
- # Finde neuesten Tag der noch nicht synced wurde
76
+ # Find newest tag that has not been synced yet
47
77
  NEW_TAG=$(tail -n1 /tmp/typo3_tags.txt)
48
78
  fi
49
-
79
+
50
80
  if [ -z "$NEW_TAG" ]; then
51
- echo "Kein TYPO3 13.x Tag gefunden"
81
+ echo "No TYPO3 v${MAJOR}.x tag found"
52
82
  echo "has_new_version=false" >> $GITHUB_OUTPUT
53
83
  exit 0
54
84
  fi
55
-
85
+
56
86
  if [ "$NEW_TAG" = "$LAST_SYNCED" ]; then
57
- echo "Keine neue Version verfügbar (aktuell: $LAST_SYNCED)"
87
+ echo "No new version available (current: $LAST_SYNCED)"
58
88
  echo "has_new_version=false" >> $GITHUB_OUTPUT
59
89
  else
60
- echo "Neue Version gefunden: $NEW_TAG (alt: $LAST_SYNCED)"
90
+ echo "New version found: $NEW_TAG (previous: $LAST_SYNCED)"
61
91
  echo "has_new_version=true" >> $GITHUB_OUTPUT
62
92
  echo "typo3_version=$NEW_TAG" >> $GITHUB_OUTPUT
63
93
  fi
64
94
 
65
- sync-and-publish:
66
- needs: check-and-sync
67
- if: needs.check-and-sync.outputs.has_new_version == 'true'
68
- runs-on: ubuntu-latest
69
- steps:
70
95
  - name: Setup Git
96
+ if: steps.check.outputs.has_new_version == 'true'
71
97
  run: |
72
98
  git config --global user.name "TYPO3 TypeScript Sync Bot"
73
99
  git config --global user.email "bot@maikschneider.de"
74
100
 
75
101
  - name: Clone TYPO3 repository at specific tag
102
+ if: steps.check.outputs.has_new_version == 'true'
76
103
  run: |
77
- TYPO3_TAG="${{ needs.check-and-sync.outputs.typo3_version }}"
78
- echo "Klone TYPO3 Repository bei Tag: $TYPO3_TAG"
79
-
104
+ TYPO3_TAG="${{ steps.check.outputs.typo3_version }}"
105
+ echo "Cloning TYPO3 repository at tag: $TYPO3_TAG"
106
+
80
107
  git clone --depth 1 --branch "$TYPO3_TAG" \
81
108
  https://github.com/TYPO3/typo3.git typo3-source
82
109
 
83
110
  - name: Extract TypeScript sources
111
+ if: steps.check.outputs.has_new_version == 'true'
84
112
  run: |
85
113
  mkdir -p typescript-split
86
-
87
- # Kopiere TypeScript Quellen
114
+
115
+ # Copy TypeScript sources
88
116
  if [ -d "typo3-source/Build/Sources/TypeScript" ]; then
89
117
  cp -r typo3-source/Build/Sources/TypeScript/* typescript-split/
90
- echo "✓ TypeScript Quellen extrahiert"
118
+ echo "✓ TypeScript sources extracted"
91
119
  else
92
- echo "✗ Fehler: Build/Sources/TypeScript nicht gefunden"
120
+ echo "✗ Error: Build/Sources/TypeScript not found"
93
121
  exit 1
94
122
  fi
95
-
96
- # Kopiere relevante Root-Dateien
123
+
124
+ # Copy relevant root files
97
125
  [ -f "typo3-source/LICENSE.txt" ] && cp typo3-source/LICENSE.txt typescript-split/
98
126
  [ -f "typo3-source/README.md" ] && cp typo3-source/README.md typescript-split/README-TYPO3.md
99
127
 
100
- - name: Checkout split repository
128
+ - name: Checkout split repository for sync
129
+ if: steps.check.outputs.has_new_version == 'true'
101
130
  uses: actions/checkout@v4
102
131
  with:
103
132
  path: split-repo
133
+ ref: ${{ matrix.target_branch }}
104
134
  token: ${{ secrets.PAT_TOKEN }}
105
135
  fetch-depth: 0
106
136
 
107
137
  - name: Sync content to split repository
138
+ if: steps.check.outputs.has_new_version == 'true'
108
139
  run: |
109
- # Lösche alte Inhalte (außer .git, .github, package.json)
140
+ # Delete old contents (except .git, .github, package.json)
110
141
  cd split-repo
111
142
  find . -mindepth 1 -maxdepth 1 \
112
143
  ! -name '.git' \
@@ -117,20 +148,21 @@ jobs:
117
148
  ! -name 'README.md' \
118
149
  ! -name 'node_modules' \
119
150
  -exec rm -rf {} +
120
-
121
- # Kopiere neue Inhalte
151
+
152
+ # Copy new contents
122
153
  cp -r ../typescript-split/* .
123
-
124
- # Speichere synced Tag
125
- echo "${{ needs.check-and-sync.outputs.typo3_version }}" > .last-synced-tag
154
+
155
+ # Save synced tag
156
+ echo "${{ steps.check.outputs.typo3_version }}" > .last-synced-tag
126
157
 
127
158
  - name: Create/Update package.json
159
+ if: steps.check.outputs.has_new_version == 'true'
128
160
  working-directory: split-repo
129
161
  run: |
130
- TYPO3_VERSION="${{ needs.check-and-sync.outputs.typo3_version }}"
131
- # Entferne 'v' Präfix für npm Version
162
+ TYPO3_VERSION="${{ steps.check.outputs.typo3_version }}"
163
+ # Remove 'v' prefix for npm version
132
164
  NPM_VERSION="${TYPO3_VERSION#v}"
133
-
165
+
134
166
  cat > package.json << EOF
135
167
  {
136
168
  "name": "typo3-typescript-sources",
@@ -167,14 +199,15 @@ jobs:
167
199
  }
168
200
  }
169
201
  EOF
170
-
171
- echo "✓ package.json erstellt mit Version $NPM_VERSION"
202
+
203
+ echo "✓ package.json created with version $NPM_VERSION"
172
204
 
173
205
  - name: Create README
206
+ if: steps.check.outputs.has_new_version == 'true'
174
207
  working-directory: split-repo
175
208
  run: |
176
- TYPO3_VERSION="${{ needs.check-and-sync.outputs.typo3_version }}"
177
-
209
+ TYPO3_VERSION="${{ steps.check.outputs.typo3_version }}"
210
+
178
211
  cat > README.md << 'EOF'
179
212
  # TYPO3 TypeScript Sources
180
213
 
@@ -196,6 +229,13 @@ jobs:
196
229
  - **Source Path:** `Build/Sources/TypeScript/`
197
230
  - **Current TYPO3 Version:** `TYPO3_VERSION_PLACEHOLDER`
198
231
 
232
+ ## 🌿 Branches
233
+
234
+ | Branch | TYPO3 Version | npm tag |
235
+ |----------|---------------|-----------|
236
+ | `main` | v14.x | `latest` |
237
+ | `v13.x` | v13.x | `v13-latest` |
238
+
199
239
  ## 📝 License
200
240
 
201
241
  This package maintains the same license as TYPO3 Core: **GPL-2.0-or-later**
@@ -209,61 +249,69 @@ jobs:
209
249
  This is an unofficial split package maintained by [@maikschneider](https://github.com/maikschneider).
210
250
  For official TYPO3 packages, please refer to the [TYPO3 Core repository](https://github.com/TYPO3/typo3).
211
251
  EOF
212
-
213
- # Ersetze Platzhalter
252
+
253
+ # Replace placeholder
214
254
  sed -i "s/TYPO3_VERSION_PLACEHOLDER/${TYPO3_VERSION}/" README.md
215
255
 
216
256
  - name: Commit changes
257
+ if: steps.check.outputs.has_new_version == 'true'
217
258
  working-directory: split-repo
218
259
  run: |
260
+ TARGET_BRANCH="${{ matrix.target_branch }}"
219
261
  git add .
220
-
262
+
221
263
  if git diff --staged --quiet; then
222
- echo "Keine Änderungen zu committen"
264
+ echo "No changes to commit"
223
265
  exit 0
224
266
  fi
225
-
226
- TYPO3_VERSION="${{ needs.check-and-sync.outputs.typo3_version }}"
267
+
268
+ TYPO3_VERSION="${{ steps.check.outputs.typo3_version }}"
227
269
  git commit -m "Sync with TYPO3 ${TYPO3_VERSION}
228
270
 
229
271
  Source: https://github.com/TYPO3/typo3/tree/${TYPO3_VERSION}
230
272
  Path: Build/Sources/TypeScript/"
231
-
232
- # Erstelle Tag (entferne v-Prefix falls vorhanden)
273
+
274
+ # Create tag (remove v-prefix)
233
275
  NPM_VERSION="${TYPO3_VERSION#v}"
234
276
  git tag -a "${NPM_VERSION}" -m "Release ${NPM_VERSION} from TYPO3 ${TYPO3_VERSION}"
235
-
236
- git push origin main
277
+
278
+ git push origin "${TARGET_BRANCH}"
237
279
  git push origin "${NPM_VERSION}"
238
280
 
239
281
  - name: Setup Node.js
282
+ if: steps.check.outputs.has_new_version == 'true'
240
283
  uses: actions/setup-node@v4
241
284
  with:
242
285
  node-version: '20'
243
286
  registry-url: 'https://registry.npmjs.org'
244
287
 
245
288
  - name: Publish to npm
289
+ if: steps.check.outputs.has_new_version == 'true'
246
290
  working-directory: split-repo
247
291
  run: |
248
- # Stelle sicher, dass .npmrc korrekt konfiguriert ist
249
292
  echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" > ~/.npmrc
250
-
251
- # Publish ohne OTP (Automation Token)
252
- npm publish --access public
293
+
294
+ MAJOR="${{ matrix.major_version }}"
295
+ if [ "$MAJOR" = "13" ]; then
296
+ npm publish --access public --tag v13-latest
297
+ else
298
+ npm publish --access public
299
+ fi
253
300
  env:
254
301
  NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
255
302
 
256
303
  - name: Create GitHub Release
304
+ if: steps.check.outputs.has_new_version == 'true'
257
305
  uses: actions/create-release@v1
258
306
  env:
259
307
  GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}
260
308
  with:
261
- tag_name: ${{ needs.check-and-sync.outputs.typo3_version }}
262
- release_name: TYPO3 ${{ needs.check-and-sync.outputs.typo3_version }}
309
+ tag_name: ${{ steps.check.outputs.typo3_version }}
310
+ release_name: TYPO3 ${{ steps.check.outputs.typo3_version }}
263
311
  body: |
264
- Synchronized with TYPO3 Core ${{ needs.check-and-sync.outputs.typo3_version }}
265
-
266
- **Source:** https://github.com/TYPO3/typo3/tree/${{ needs.check-and-sync.outputs.typo3_version }}
312
+ Synchronized with TYPO3 Core ${{ steps.check.outputs.typo3_version }}
313
+
314
+ **Source:** https://github.com/TYPO3/typo3/tree/${{ steps.check.outputs.typo3_version }}
267
315
  **Path:** `Build/Sources/TypeScript/`
268
316
  draft: false
269
- prerelease: false
317
+ prerelease: false
package/.last-synced-tag CHANGED
@@ -1 +1 @@
1
- v13.4.25
1
+ v13.4.29
package/README.md CHANGED
@@ -16,7 +16,14 @@ npm install typo3-typescript-sources
16
16
 
17
17
  - **Original Repository:** [TYPO3/typo3](https://github.com/TYPO3/typo3)
18
18
  - **Source Path:** `Build/Sources/TypeScript/`
19
- - **Current TYPO3 Version:** `v13.4.25`
19
+ - **Current TYPO3 Version:** `v13.4.29`
20
+
21
+ ## 🌿 Branches
22
+
23
+ | Branch | TYPO3 Version | npm tag |
24
+ |----------|---------------|-----------|
25
+ | `main` | v14.x | `latest` |
26
+ | `v13.x` | v13.x | `v13-latest` |
20
27
 
21
28
  ## 📝 License
22
29
 
@@ -67,42 +67,50 @@ export class Typo3BackendColorPicker extends LitElement {
67
67
  await DocumentService.ready();
68
68
 
69
69
  const inputElement = this.getInputElement();
70
- if (inputElement) {
71
- if (!inputElement.value && this.color) {
72
- inputElement.value = this.color;
73
- } else {
74
- this.color = inputElement.value;
75
- }
70
+ if (!inputElement) {
71
+ return;
72
+ }
76
73
 
77
- if (inputElement.disabled || inputElement.readOnly) {
78
- return;
79
- }
74
+ if (!inputElement.value && this.color) {
75
+ inputElement.value = this.color;
76
+ } else {
77
+ this.color = inputElement.value;
78
+ }
80
79
 
81
- const alwan = new Alwan(inputElement, {
82
- position: 'bottom-start',
83
- format: 'hex',
84
- opacity: this.opacity,
85
- swatches: this.swatches,
86
- preset: false,
87
- color: this.color,
88
- });
89
-
90
- alwan.on('color', (e): void => {
91
- this.color = e.hex;
92
- inputElement.value = this.color;
93
- inputElement.dispatchEvent(new Event('blur'));
94
- });
95
-
96
- // input: react on user input
97
- // change: react on indirect changes, e.g. a value picker
98
- ['input', 'change'].forEach((eventName: string): void => {
99
- new RegularEvent(eventName, (e: Event): void => {
100
- const input = (e.target as HTMLInputElement);
101
- this.color = input.value;
102
- alwan.setColor(this.color);
103
- }).bindTo(inputElement);
104
- });
80
+ if (inputElement.disabled || inputElement.readOnly) {
81
+ return;
105
82
  }
83
+
84
+ const alwan = new Alwan(inputElement, {
85
+ position: 'bottom-start',
86
+ format: 'hex',
87
+ opacity: this.opacity,
88
+ swatches: this.swatches,
89
+ preset: false,
90
+ color: this.color,
91
+ });
92
+
93
+ // When the color picker opens, the input loses focus, making value changes difficult.
94
+ // Restore focus to the input after the picker is opened.
95
+ alwan.on('open', (): void => {
96
+ inputElement.focus();
97
+ });
98
+
99
+ alwan.on('color', (e): void => {
100
+ this.color = e.hex;
101
+ inputElement.value = this.color;
102
+ inputElement.dispatchEvent(new Event('blur'));
103
+ });
104
+
105
+ // input: react on user input
106
+ // change: react on indirect changes, e.g. a value picker
107
+ ['input', 'change'].forEach((eventName: string): void => {
108
+ new RegularEvent(eventName, (e: Event): void => {
109
+ const input = (e.target as HTMLInputElement);
110
+ this.color = input.value;
111
+ alwan.setColor(this.color);
112
+ }).bindTo(inputElement);
113
+ });
106
114
  }
107
115
 
108
116
  protected override render(): TemplateResult {
@@ -109,7 +109,7 @@ export class EditablePageTitle extends LitElement {
109
109
  color: var(--button-color);
110
110
  background: var(--button-bg);
111
111
  border: 1px solid var(--button-border-color);
112
- opacity: .3;
112
+ opacity: .8;
113
113
  outline-offset: 0;
114
114
  transition: all .2s ease-in-out;
115
115
  }
@@ -275,7 +275,8 @@ class FilesControlContainer extends HTMLElement {
275
275
 
276
276
  if (hiddenValueCheckBox !== null && hiddenValueInput !== null) {
277
277
  hiddenValueCheckBox.checked = !hiddenValueCheckBox.checked;
278
- hiddenValueInput.value = hiddenValueCheckBox.checked ? '1' : '0';
278
+ const active = hiddenValueCheckBox.checked !== (hiddenValueCheckBox.dataset.invertStateDisplay === 'true');
279
+ hiddenValueInput.value = active ? '1' : '0';
279
280
  FormEngineValidation.markFieldAsChanged(hiddenValueCheckBox);
280
281
  }
281
282
 
@@ -430,7 +430,8 @@ class InlineControlContainer {
430
430
 
431
431
  if (hiddenValueCheckBox !== null && hiddenValueInput !== null) {
432
432
  hiddenValueCheckBox.checked = !hiddenValueCheckBox.checked;
433
- hiddenValueInput.value = hiddenValueCheckBox.checked ? '1' : '0';
433
+ const active = hiddenValueCheckBox.checked !== (hiddenValueCheckBox.dataset.invertStateDisplay === 'true');
434
+ hiddenValueInput.value = active ? '1' : '0';
434
435
  FormEngineValidation.markFieldAsChanged(hiddenValueCheckBox);
435
436
  }
436
437
 
@@ -0,0 +1,128 @@
1
+ /*
2
+ * This file is part of the TYPO3 CMS project.
3
+ *
4
+ * It is free software; you can redistribute it and/or modify it under
5
+ * the terms of the GNU General Public License, either version 2
6
+ * of the License, or any later version.
7
+ *
8
+ * For the full copyright and license information, please read the
9
+ * LICENSE.txt file that was distributed with this source code.
10
+ *
11
+ * The TYPO3 project - inspiring people to share!
12
+ */
13
+
14
+ /**
15
+ * Module: @typo3/backend/layout-module/velocity-scroll
16
+ *
17
+ * Enables auto-scrolling while dragging near the viewport edge.
18
+ *
19
+ * Self-binds a delegated `dragstart` listener for all `[draggable="true"]`
20
+ * elements on the page. May also be invoked directly:
21
+ *
22
+ * ```js
23
+ * // inside a dragstart event handler:
24
+ * initVelocityScroll(event);
25
+ * ```
26
+ */
27
+ import DocumentService from '@typo3/core/document-service';
28
+ import RegularEvent from '@typo3/core/event/regular-event';
29
+
30
+ const EDGE_RATIO = 0.2;
31
+ const MAX_STRENGTH_RATIO = 2.5;
32
+
33
+ DocumentService.ready().then((): void => {
34
+ new RegularEvent('dragstart', (event: Event): void => {
35
+ initVelocityScroll(event as DragEvent);
36
+ }).delegateTo(document, '[draggable="true"]');
37
+ });
38
+
39
+ export function initVelocityScroll(event: DragEvent): void {
40
+ const scrollingElement = document.scrollingElement;
41
+ if (!(scrollingElement instanceof HTMLElement)) {
42
+ console.warn('Scrolling element is not an HTMLElement. Velocity scroll will not work.');
43
+ return;
44
+ }
45
+
46
+ // Scrolling may live on an inner container (e.g. the page module's
47
+ // .module-body with overflow: auto) rather than the document, so target
48
+ // the nearest scrollable ancestor of the drag source per axis if any exists.
49
+ const target = event.target as Element | null;
50
+ const verticalElement = findScrollAncestor(target, 'y') ?? scrollingElement;
51
+ const horizontalElement = findScrollAncestor(target, 'x') ?? scrollingElement;
52
+
53
+ let scrollSpeedVertical = 0;
54
+ let scrollSpeedHorizontal = 0;
55
+ let running = true;
56
+ let lastFrameTime = performance.now();
57
+
58
+ // Disable smooth scrolling for the duration of the drag and restore on dragend
59
+ const originalVerticalScrollBehavior = verticalElement.style.scrollBehavior;
60
+ const originalHorizontalScrollBehavior = horizontalElement.style.scrollBehavior;
61
+ verticalElement.style.scrollBehavior = 'auto';
62
+ horizontalElement.style.scrollBehavior = 'auto';
63
+
64
+ const tick = (now: number): void => {
65
+ const dt = (now - lastFrameTime) / 1000;
66
+ lastFrameTime = now;
67
+
68
+ const maxVertical = verticalElement.scrollHeight - verticalElement.clientHeight;
69
+ const maxHorizontal = horizontalElement.scrollWidth - horizontalElement.clientWidth;
70
+ verticalElement.scrollTop = Math.max(0, Math.min(verticalElement.scrollTop + scrollSpeedVertical * dt, maxVertical));
71
+ horizontalElement.scrollLeft = Math.max(0, Math.min(horizontalElement.scrollLeft + scrollSpeedHorizontal * dt, maxHorizontal));
72
+
73
+ if (running) {
74
+ requestAnimationFrame(tick);
75
+ }
76
+ };
77
+ requestAnimationFrame(tick);
78
+
79
+ // Progress within the edge zone goes from 0 (just entered) to 1 (at the edge).
80
+ // Squaring it makes scrolling accelerate noticeably near the edge.
81
+ const axisStrength = (distance: number, edge: number, max: number): number =>
82
+ distance < edge ? ((1 - distance / edge) ** 2) * max : 0;
83
+
84
+ const autoScroll = (event: DragEvent): void => {
85
+ const verticalEdge = window.innerHeight * EDGE_RATIO;
86
+ const horizontalEdge = window.innerWidth * EDGE_RATIO;
87
+ const maxVerticalStrength = window.innerHeight * MAX_STRENGTH_RATIO;
88
+ const maxHorizontalStrength = window.innerWidth * MAX_STRENGTH_RATIO;
89
+
90
+ scrollSpeedVertical =
91
+ axisStrength(window.innerHeight - event.clientY, verticalEdge, maxVerticalStrength) -
92
+ axisStrength(event.clientY, verticalEdge, maxVerticalStrength);
93
+ scrollSpeedHorizontal =
94
+ axisStrength(window.innerWidth - event.clientX, horizontalEdge, maxHorizontalStrength) -
95
+ axisStrength(event.clientX, horizontalEdge, maxHorizontalStrength);
96
+ };
97
+ autoScroll(event);
98
+ window.addEventListener('dragover', autoScroll);
99
+
100
+ // Bind teardown on window: the source element may be detached or replaced
101
+ // during the drop (drag-drop.ts re-renders content via AJAX), in which case
102
+ // a `dragend` listener on the source element would never fire.
103
+ window.addEventListener('dragend', (): void => {
104
+ window.removeEventListener('dragover', autoScroll);
105
+ scrollSpeedVertical = 0;
106
+ scrollSpeedHorizontal = 0;
107
+ running = false;
108
+ verticalElement.style.scrollBehavior = originalVerticalScrollBehavior;
109
+ horizontalElement.style.scrollBehavior = originalHorizontalScrollBehavior;
110
+ }, { once: true });
111
+ }
112
+
113
+ function findScrollAncestor(element: Element | null, axis: 'x' | 'y'): HTMLElement | null {
114
+ const sizeProp = axis === 'x' ? 'scrollWidth' : 'scrollHeight';
115
+ const clientProp = axis === 'x' ? 'clientWidth' : 'clientHeight';
116
+ const overflowProp = axis === 'x' ? 'overflowX' : 'overflowY';
117
+ let current = element;
118
+ while (current instanceof HTMLElement) {
119
+ if (current[sizeProp] > current[clientProp]) {
120
+ const overflow = window.getComputedStyle(current)[overflowProp];
121
+ if (overflow === 'auto' || overflow === 'scroll') {
122
+ return current;
123
+ }
124
+ }
125
+ current = current.parentElement;
126
+ }
127
+ return null;
128
+ }
package/backend/modal.ts CHANGED
@@ -173,7 +173,7 @@ export class ModalElement extends LitElement {
173
173
  ${this.hideCloseButton ? nothing : html`
174
174
  <button class="t3js-modal-close close" @click=${() => this.bootstrapModal.hide()}>
175
175
  <typo3-backend-icon identifier="actions-close" size="small"></typo3-backend-icon>
176
- <span class="visually-hidden">${TYPO3?.lang?.['button.close'] || 'Close'} ${this.modalTitle}</span>
176
+ <span class="visually-hidden">${(TYPO3?.lang?.['button.close'] || 'Close') + ' ' + this.modalTitle}</span>
177
177
  </button>
178
178
  `}
179
179
  </div>
@@ -85,7 +85,7 @@ export class PageBrowserTree extends PageTree {
85
85
  */
86
86
  private isLinkable(node: TreeNodeInterface): boolean {
87
87
  const nonLinkableDoktypes = ['199', '254', '255'];
88
- return nonLinkableDoktypes.includes(String(node.recordType)) === false;
88
+ return nonLinkableDoktypes.includes(String(node.doktype)) === false;
89
89
  }
90
90
 
91
91
  /**
@@ -169,8 +169,6 @@ export class PageBrowser extends LitElement {
169
169
  return this.getConfiguration()
170
170
  .then((configuration: Configuration): TemplateResult => {
171
171
  const initialized = () => {
172
- this.tree.addEventListener('typo3:tree:node-selected', this.loadRecordsOfPage);
173
- this.tree.addEventListener('typo3:tree:nodes-prepared', this.selectActivePageInTree);
174
172
  // set up toolbar now with updated properties
175
173
  const toolbar = this.querySelector('typo3-backend-tree-toolbar') as TreeToolbar;
176
174
  toolbar.tree = this.tree;
@@ -180,7 +178,14 @@ export class PageBrowser extends LitElement {
180
178
  <typo3-backend-tree-toolbar .tree="${this.tree}"></typo3-backend-tree-toolbar>
181
179
  <div class="navigation-tree-container">
182
180
  ${this.renderMountPoint()}
183
- <typo3-backend-component-page-browser-tree id="typo3-pagetree-tree" class="tree-wrapper" .setup=${configuration} @tree:initialized=${initialized}></typo3-backend-component-page-browser-tree>
181
+ <typo3-backend-component-page-browser-tree
182
+ id="typo3-pagetree-tree"
183
+ class="tree-wrapper"
184
+ .setup=${configuration}
185
+ @tree:initialized=${initialized}
186
+ @typo3:tree:node-selected=${this.loadRecordsOfPage}
187
+ @typo3:tree:nodes-prepared=${this.selectActivePageInTree}
188
+ ></typo3-backend-component-page-browser-tree>
184
189
  </div>
185
190
  `;
186
191
  });
@@ -1481,7 +1481,4 @@ declare global {
1481
1481
 
1482
1482
  [newRecordWizardEventName]: CustomEvent<NewRecordWizardItemSelectedEventInterface>;
1483
1483
  }
1484
- interface FocusOptions {
1485
- focusVisible: boolean;
1486
- }
1487
1484
  }
@@ -163,7 +163,7 @@ export class LanguageMatrixElement extends LitElement {
163
163
  <div class="btn-group">
164
164
  ${this.renderLanguageActions(language)}
165
165
  </div>
166
- ${language.name}
166
+ <span class="ms-2">${language.name}</span>
167
167
  </td>
168
168
  <td>${language.iso}</td>
169
169
  <td>${language.dependencies.join(', ')}</td>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typo3-typescript-sources",
3
- "version": "13.4.25",
3
+ "version": "13.4.29",
4
4
  "description": "TYPO3 Core TypeScript Sources - Extracted from TYPO3/typo3 repository",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "typo3": {
30
30
  "sourceRepository": "https://github.com/TYPO3/typo3",
31
- "sourceTag": "v13.4.25",
31
+ "sourceTag": "v13.4.29",
32
32
  "sourcePath": "Build/Sources/TypeScript"
33
33
  }
34
34
  }
@@ -235,6 +235,7 @@ class Recycler {
235
235
  private async loadAvailableTables(): Promise<AjaxResponse> {
236
236
  const tableSelector = document.querySelector(Identifiers.tableSelector) as HTMLSelectElement;
237
237
  const depthSelector = document.querySelector(Identifiers.depthSelector) as HTMLSelectElement;
238
+ const currentTableSelection = tableSelector.options.length > 0 ? tableSelector.value : TYPO3.settings.Recycler.tableSelection;
238
239
 
239
240
  NProgress.start();
240
241
  tableSelector.value = '';
@@ -264,8 +265,8 @@ class Recycler {
264
265
 
265
266
  if (tables.length > 0) {
266
267
  tableSelector.append(...tables);
267
- if (TYPO3.settings.Recycler.tableSelection !== '') {
268
- tableSelector.value = TYPO3.settings.Recycler.tableSelection;
268
+ if (currentTableSelection !== '') {
269
+ tableSelector.value = currentTableSelection;
269
270
  }
270
271
  }
271
272
 
@@ -360,7 +360,7 @@ type PseudoRegExp = {
360
360
  };
361
361
 
362
362
  function walkObj(data: RecurseMapInput, proc: (value: unknown) => unknown|null): RecurseMapInput {
363
- if (typeof data === 'object') {
363
+ if (data !== null && typeof data === 'object') {
364
364
  if (Array.isArray(data)) {
365
365
  return data.map((element: RecurseMapInput) => proc(element) ?? walkObj(element, proc));
366
366
  }
@@ -375,7 +375,7 @@ function walkObj(data: RecurseMapInput, proc: (value: unknown) => unknown|null):
375
375
 
376
376
  function convertPseudoRegExp(data: RecurseMapInput): RecurseMapInput {
377
377
  return walkObj(data, (entry: PseudoRegExp | unknown): RegExp | null => {
378
- if (typeof entry === 'object' && 'pattern' in entry && typeof entry.pattern === 'string') {
378
+ if (entry !== null && typeof entry === 'object' && 'pattern' in entry && typeof entry.pattern === 'string') {
379
379
  const pseudoRegExp = entry as PseudoRegExp;
380
380
  return new RegExp(pseudoRegExp.pattern, pseudoRegExp.flags || undefined);
381
381
  }