From c2ee19308df8ec0ac8d816b38683b9bf48c4fdb9 Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Sun, 30 Nov 2025 23:57:14 +0000 Subject: [PATCH] fix(dees-stepper): Make step validation abortable and cancel active step listeners when navigating --- changelog.md | 7 +++++++ ts_web/00_commitinfo_data.ts | 2 +- ts_web/elements/dees-stepper/dees-stepper.ts | 14 ++++++++++++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index fb88164..15ff9f4 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2025-11-30 - 2.0.2 - fix(dees-stepper) +Make step validation abortable and cancel active step listeners when navigating + +- Extend IStep.validationFunc signature to accept an optional AbortSignal so validation handlers can be cancelled. +- Store an AbortController on the selected step and pass its signal into validationFunc when invoked. +- Abort the step's AbortController when navigating to the previous or next step to cancel any active listeners or async operations. + ## 2025-11-30 - 2.0.1 - fix(dees-stepper) Improve dees-stepper visual style and transitions diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index 81fe47e..e3de678 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@design.estate/dees-catalog', - version: '2.0.1', + version: '2.0.2', description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.' } diff --git a/ts_web/elements/dees-stepper/dees-stepper.ts b/ts_web/elements/dees-stepper/dees-stepper.ts index 0960f1a..c1dca8f 100644 --- a/ts_web/elements/dees-stepper/dees-stepper.ts +++ b/ts_web/elements/dees-stepper/dees-stepper.ts @@ -19,9 +19,10 @@ import { stepperDemo } from './dees-stepper.demo.js'; export interface IStep { title: string; content: TemplateResult; - validationFunc?: (stepper: DeesStepper, htmlElement: HTMLElement) => Promise; + validationFunc?: (stepper: DeesStepper, htmlElement: HTMLElement, signal?: AbortSignal) => Promise; onReturnToStepFunc?: (stepper: DeesStepper, htmlElement: HTMLElement) => Promise; validationFuncCalled?: boolean; + abortController?: AbortController; } declare global { @@ -250,8 +251,9 @@ export class DeesStepper extends DeesElement { ); } if (!this.selectedStep.validationFuncCalled && this.selectedStep.validationFunc) { + this.selectedStep.abortController = new AbortController(); this.selectedStep.validationFuncCalled = true; - await this.selectedStep.validationFunc(this, selectedStepElement); + await this.selectedStep.validationFunc(this, selectedStepElement, this.selectedStep.abortController.signal); } this.scroller.to(scrollPosition); } @@ -261,6 +263,10 @@ export class DeesStepper extends DeesElement { if (currentIndex <= 0) { return; } + // Abort any active listeners on current step + if (this.selectedStep.abortController) { + this.selectedStep.abortController.abort(); + } const currentStep = this.steps[currentIndex]; currentStep.validationFuncCalled = false; const previousStep = this.steps[currentIndex - 1]; @@ -276,6 +282,10 @@ export class DeesStepper extends DeesElement { if (currentIndex < 0 || currentIndex >= this.steps.length - 1) { return; } + // Abort any active listeners on current step + if (this.selectedStep.abortController) { + this.selectedStep.abortController.abort(); + } const currentStep = this.steps[currentIndex]; currentStep.validationFuncCalled = false; const nextStep = this.steps[currentIndex + 1];