sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
78.63k stars 4.13k forks source link

duplicate component issue is caused by using the fade transition. #11973

Open Neptunium1129 opened 3 months ago

Neptunium1129 commented 3 months ago

Describe the bug

https://github.com/flekschas/svelte-simple-modal/issues/114

https://svelte.dev/repl/52e0ade6d42546d8892faf8528c70d30?version=3.59.1 Honeycam 2024-06-09 12-22-13

https://svelte.dev/repl/52e0ade6d42546d8892faf8528c70d30?version=4.2.18 Honeycam 2024-06-09 12-23-03

-- The issue of duplicate components occurring on button click happens in version 4.2.18 but does not occur in version 3.59.1.

Reproduction

https://svelte.dev/repl/52e0ade6d42546d8892faf8528c70d30?version=4.2.18 https://svelte.dev/repl/52e0ade6d42546d8892faf8528c70d30?version=3.59.1

svelte5 preview same version 4.2.18

Logs

No response

System Info

System:
    OS: Windows 10 10.0.19045
    CPU: (8) x64 Genuine Intel(R) CPU 0000 @ 1.60GHz
    Memory: 7.60 GB / 15.92 GB
  Binaries:
    Node: 20.14.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.22 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 10.7.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 125.0.6422.142
    Edge: Chromium (125.0.2535.92)
    Internet Explorer: 11.0.19041.4355
  npmPackages:
    svelte: ^5.0.0-next.1 => 5.0.0-next.148 , svelte: ^4.2.12 => 4.2.12

Severity

annoyance

Neptunium1129 commented 3 months ago

svelte5 new componet deprecate i changed "simple modal" source https://www.npmjs.com/package/svelte-simple-modal however same duplicate issue, but svelte3 not occur in version 3.59.1

svelte4

<script context="module">
    /**
     * @typedef {typeof import('svelte').SvelteComponent | typeof import('svelte').SvelteComponent<any>} Component
     * @typedef {import('svelte/types/runtime/transition').BlurParams} BlurParams
     * @typedef {import('svelte/types/runtime/transition').FadeParams} FadeParams
     * @typedef {import('svelte/types/runtime/transition').FlyParams} FlyParams
     * @typedef {import('svelte/types/runtime/transition').SlideParams} SlideParams
     * @typedef {import('svelte/types/runtime/transition').TransitionConfig} TransitionConfig
     * @typedef {Record<string, string | number>} Styles
     * @typedef {(node: Element, parameters: BlurParams | FadeParams | FlyParams | SlideParams) => TransitionConfig} TransitionFn
     * @typedef {{ id: string | null, ariaLabel: string | null, ariaLabelledBy: string | null, closeButton: Component | boolean, closeOnEsc: boolean, closeOnOuterClick: boolean, styleBg: Styles, styleWindowWrap: Styles, styleWindow: Styles, styleContent: Styles, styleCloseButton: Styles, classBg: string | null, classWindowWrap: string | null, classWindow: string | null, classContent: string | null, classCloseButton: string | null, transitionBg: TransitionFn, transitionBgProps: BlurParams, transitionWindow: TransitionFn, transitionWindowProps: BlurParams, disableFocusTrap: boolean, isTabbable: boolean, unstyled: boolean }} Options
     * @typedef {() => void} Callback
     * @typedef {{ onOpen: Callback; onOpened: Callback; onClose: Callback; onClosed: Callback }} Callbacks
     * @typedef {(NewComponent: Component, newProps?: Record<string, any>, options?: Partial<Options>, callbacks?: Partial<Callbacks>) => void} Open
     * @typedef {(callback?: Partial<Callbacks>) => void} Close
     * @typedef {{ open: Open, close: Close }} Context
     */

    /**
     * Create a Svelte component with props bound to it.
     * @type {(component: Component, props: Record<string, any>) => Component}
     */
    export function bind(Component, props = {}) {
      return function ModalComponent(options) {
        let app = new Component({
        ...options,
        props: {
          ...props,
          ...options.props,
        },
        })
        return app;
      };
    }
  </script>

svelte5

<script context="module">
/**
 * @typedef {typeof import('svelte').SvelteComponent | typeof import('svelte').SvelteComponent<any>} Component
 * @typedef {import('svelte/types/runtime/transition').BlurParams} BlurParams
 * @typedef {import('svelte/types/runtime/transition').FadeParams} FadeParams
 * @typedef {import('svelte/types/runtime/transition').FlyParams} FlyParams
 * @typedef {import('svelte/types/runtime/transition').SlideParams} SlideParams
 * @typedef {import('svelte/types/runtime/transition').TransitionConfig} TransitionConfig
 * @typedef {Record<string, string | number>} Styles
 * @typedef {(node: Element, parameters: BlurParams | FadeParams | FlyParams | SlideParams) => TransitionConfig} TransitionFn
 * @typedef {{ id: string | null, ariaLabel: string | null, ariaLabelledBy: string | null, closeButton: Component | boolean, closeOnEsc: boolean, closeOnOuterClick: boolean, styleBg: Styles, styleWindowWrap: Styles, styleWindow: Styles, styleContent: Styles, styleCloseButton: Styles, classBg: string | null, classWindowWrap: string | null, classWindow: string | null, classContent: string | null, classCloseButton: string | null, transitionBg: TransitionFn, transitionBgProps: BlurParams, transitionWindow: TransitionFn, transitionWindowProps: BlurParams, disableFocusTrap: boolean, isTabbable: boolean, unstyled: boolean }} Options
 * @typedef {() => void} Callback
 * @typedef {{ onOpen: Callback; onOpened: Callback; onClose: Callback; onClosed: Callback }} Callbacks
 * @typedef {(NewComponent: Component, newProps?: Record<string, any>, options?: Partial<Options>, callbacks?: Partial<Callbacks>) => void} Open
 * @typedef {(callback?: Partial<Callbacks>) => void} Close
 * @typedef {{ open: Open, close: Close }} Context
 */

/**
 * Create a Svelte component with props bound to it.
 * @type {(component: Component, props: Record<string, any>) => Component}
 */
export function bind(Component, props = {}) {
   return function ModalComponent(options) {
    let cmpData = {
      ...options,
      props: {
        ...props,
        ...options.props,
      },
      target: options.parentNode
    }
    return svelte.mount(Component, cmpData);
  }; 
}
</script>
Neptunium1129 commented 3 months ago

I found that this issue is caused by the Svelte fade transition.

 /**
     * Parameters for the background element transition
     * @type {BlurParams | FadeParams | FlyParams | SlideParams}
     */
    export let transitionBgProps = { duration: 250 };

The issue occurs with a duration of 250, but does not occur with a duration of 120.