typo3-typescript-sources 13.4.21 → 13.4.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.last-synced-tag CHANGED
@@ -1 +1 @@
1
- v13.4.21
1
+ v13.4.22
package/README.md CHANGED
@@ -16,7 +16,7 @@ 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.21`
19
+ - **Current TYPO3 Version:** `v13.4.22`
20
20
 
21
21
  ## 📝 License
22
22
 
@@ -96,6 +96,7 @@ export class CspReports extends LitElement {
96
96
  @state() suggestions: MutationSuggestion[] = [];
97
97
 
98
98
  private peripheralEvent: RegularEvent;
99
+ private previouslyFocusedRow: HTMLElement | null = null;
99
100
 
100
101
  public override connectedCallback(): void {
101
102
  super.connectedCallback();
@@ -114,6 +115,17 @@ export class CspReports extends LitElement {
114
115
  this.peripheralEvent?.release();
115
116
  }
116
117
 
118
+ protected override updated(changedProperties: Map<string, any>): void {
119
+ super.updated(changedProperties);
120
+ if (changedProperties.has('selectedReport') && this.selectedReport !== null) {
121
+ // Focus the details panel when a report is selected
122
+ this.updateComplete.then(() => {
123
+ const detailsPanel = this.querySelector('#report-details') as HTMLElement;
124
+ detailsPanel?.focus();
125
+ });
126
+ }
127
+ }
128
+
117
129
  protected override createRenderRoot(): HTMLElement | ShadowRoot {
118
130
  return this;
119
131
  }
@@ -148,7 +160,11 @@ export class CspReports extends LitElement {
148
160
  ` : nothing}
149
161
  ${this.reports.map((report: SummarizedCspReport) => html`
150
162
  <tr class=${classMap({ 'table-info': this.selectedReport === report })} data-mutation-group=${report.mutationHashes.join('-')}
151
- @click=${() => this.selectReport(report)}>
163
+ @click=${() => this.selectReport(report)}
164
+ @keydown=${(e: KeyboardEvent) => this.handleReportKeydown(e, report)}
165
+ tabindex="0"
166
+ role="button"
167
+ aria-label="${lll('label.showDetails', report.details.effectiveDirective, report.details.blockedUri) || 'Show details'}">
152
168
  <td>${report.created}</td>
153
169
  <td>${report.scope}</td>
154
170
  <td>
@@ -218,7 +234,7 @@ export class CspReports extends LitElement {
218
234
  const report = this.selectedReport;
219
235
  return html`${report ? html`
220
236
  <div class="infolist-info-record">
221
- <div class="card mb-0">
237
+ <div class="card mb-0" tabindex="-1" id="report-details" @keydown=${(e: KeyboardEvent) => this.handleDetailsKeydown(e)}>
222
238
  <div class="card-header">
223
239
  <h3>${ lll('label.details') || 'Details'}</h3>
224
240
  </div>
@@ -309,14 +325,75 @@ export class CspReports extends LitElement {
309
325
  private selectReport(report: SummarizedCspReport): void {
310
326
  this.suggestions = [];
311
327
  if (report !== null && this.selectedReport !== report) {
328
+ // Store the currently focused element before changing selection
329
+ this.previouslyFocusedRow = document.activeElement as HTMLElement;
312
330
  this.selectedReport = report;
313
331
  this.invokeHandleReportAction(report)
314
332
  .then((suggestions: MutationSuggestion[]) => this.suggestions = suggestions);
315
333
  } else {
316
334
  this.selectedReport = null;
335
+ // Restore focus to the previously focused row when closing
336
+ if (this.previouslyFocusedRow) {
337
+ this.updateComplete.then(() => {
338
+ this.previouslyFocusedRow?.focus();
339
+ this.previouslyFocusedRow = null;
340
+ });
341
+ }
342
+ }
343
+ }
344
+
345
+ private handleReportKeydown(event: KeyboardEvent, report: SummarizedCspReport): void {
346
+ // Handle Enter/Space to select report
347
+ if (event.key === 'Enter' || event.key === 'Space' || event.key === ' ') {
348
+ event.preventDefault();
349
+ this.selectReport(report);
350
+ return;
351
+ }
352
+
353
+ // Arrow key navigation
354
+ const currentRow = event.currentTarget as HTMLElement;
355
+ let targetRow: HTMLElement | null = null;
356
+
357
+ switch (event.key) {
358
+ case 'ArrowDown':
359
+ event.preventDefault();
360
+ targetRow = currentRow.nextElementSibling as HTMLElement;
361
+ break;
362
+ case 'ArrowUp':
363
+ event.preventDefault();
364
+ targetRow = currentRow.previousElementSibling as HTMLElement;
365
+ break;
366
+ case 'Home':
367
+ event.preventDefault();
368
+ targetRow = currentRow.parentElement?.firstElementChild as HTMLElement;
369
+ break;
370
+ case 'End':
371
+ event.preventDefault();
372
+ targetRow = currentRow.parentElement?.lastElementChild as HTMLElement;
373
+ break;
374
+ default:
375
+ return;
376
+ }
377
+
378
+ if (targetRow && targetRow.hasAttribute('tabindex')) {
379
+ targetRow.focus();
380
+ }
381
+ }
382
+
383
+ private handleDetailsKeydown(event: KeyboardEvent): void {
384
+ if (event.key === 'Escape') {
385
+ event.preventDefault();
386
+ this.selectReport(null);
317
387
  }
318
388
  }
319
389
 
390
+ private focusFirstReportRow(): void {
391
+ this.updateComplete.then(() => {
392
+ const firstRow = this.querySelector('tbody tr[tabindex="0"]') as HTMLElement;
393
+ firstRow?.focus();
394
+ });
395
+ }
396
+
320
397
  private selectScope(scope: string): void {
321
398
  this.selectedScope = scope;
322
399
  this.fetchReports();
@@ -363,14 +440,16 @@ export class CspReports extends LitElement {
363
440
  (new AjaxRequest(this.controlUri))
364
441
  .post({ action: 'muteReport', summaries: [report.summary] })
365
442
  .then((response: AjaxResponse) => response.resolve('application/json'))
366
- .then((response: CspReportUuids) => this.filterReports(...response.uuids));
443
+ .then((response: CspReportUuids) => this.filterReports(...response.uuids))
444
+ .then(() => this.focusFirstReportRow());
367
445
  }
368
446
 
369
447
  private invokeDeleteReportAction(report: SummarizedCspReport): void {
370
448
  (new AjaxRequest(this.controlUri))
371
449
  .post({ action: 'deleteReport', summaries: [report.summary] })
372
450
  .then((response: AjaxResponse) => response.resolve('application/json'))
373
- .then((response: CspReportUuids) => this.filterReports(...response.uuids));
451
+ .then((response: CspReportUuids) => this.filterReports(...response.uuids))
452
+ .then(() => this.focusFirstReportRow());
374
453
  }
375
454
 
376
455
  private invokeDeleteReportsAction(): void {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typo3-typescript-sources",
3
- "version": "13.4.21",
3
+ "version": "13.4.22",
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.21",
31
+ "sourceTag": "v13.4.22",
32
32
  "sourcePath": "Build/Sources/TypeScript"
33
33
  }
34
34
  }
@@ -571,14 +571,10 @@ export class Typo3LinkUI extends Core.Plugin {
571
571
  }
572
572
 
573
573
  private showUI(): void {
574
- const selectedLink = this.getSelectedLinkElement();
575
- if (!selectedLink) {
574
+ if (!this.getSelectedLinkElement()) {
576
575
  this.showFakeVisualSelection();
577
576
  this.openLinkBrowser(this.editor);
578
577
  } else {
579
- // When clicking inside a link, check if we need to expand selection to full link
580
- // This prevents link splitting when editing with partial selection
581
- this.expandSelectionToFullLink();
582
578
  this.addToolbarView();
583
579
  this.balloon.showStack('main');
584
580
  }