Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Could not find a declaration file for module 'svelte-carousel' #117

Open
cloudlena opened this issue Aug 22, 2022 · 8 comments
Open

Could not find a declaration file for module 'svelte-carousel' #117

cloudlena opened this issue Aug 22, 2022 · 8 comments
Labels
TypeScript TypeScript support, typings, etc.

Comments

@cloudlena
Copy link

cloudlena commented Aug 22, 2022

I'm using the SvelteKit workaround:

<script lang="ts">
	let Carousel;
	onMount(async () => {
		const module = await import('svelte-carousel');
		Carousel = module.default;
	});
</script>

I'm also using TypeScript.

Here, I'm getting the following error:

Could not find a declaration file for module 'svelte-carousel'. '/home/lena/bespinian/bespinian.io-svelte/node_modules/svelte-carousel/src/main.js' implicitly has an 'any' type.
      Try `npm i --save-dev @types/svelte-carousel` if it exists or add a new declaration (.d.ts) file containing `declare module 'svelte-carousel';`

npm i --save-dev @types/svelte-carousel doesn't work because that package doesn't exist.

I'm not sure if the problem is related to the SvelteKit workaround or if this package is generally not typed (correctly) for TypeScript.

My current workaround for this issue is to add declare module 'svelte-carousel'; to src/app.d.ts. However, it feels like I shouldn't need to do that, if this package was typed correctly.

Furthermore, it would be very helpful to have typings for the Carousel class and its options. Currently, I'm just typing it as SvelteComponent explicitly.

@vadimkorr vadimkorr added the TypeScript TypeScript support, typings, etc. label Sep 3, 2022
@Cobular
Copy link

Cobular commented Nov 23, 2022

Hey! So this got me started and now I've built what I think is a correct representation of the types involved.

declare module 'svelte-carousel' {
	import { SvelteComponentTyped } from 'svelte';

	interface CarouselProps {
		arrows?: boolean = true; //Enables next/prev arrows
		infinite?: boolean = true; //Infinite looping
		initialPageIndex?: number = 0; //Page to start on
		duration?: number = 500; //Transition duration (ms)
		autoplay?: boolean = false; //Enables autoplay of pages
		autoplayDuration?: number = 3000; // Autoplay change interval (ms)
		autoplayDirection?: 'next' | 'prev' = 'next'; // Autoplay change direction (next or prev)
		pauseOnFocus?: boolean = false; //	Pauses on focus (for touchable devices - tap the carousel to toggle the autoplay, for non-touchable devices - hover over the carousel to pause the autoplay)
		autoplayProgressVisible?: boolean = false; //Shows autoplay duration progress indicator
		dots?: boolean = true; //	Current indicator dots
		timingFunction?: string = 'ease-in-out'; //CSS animation timing function
		swiping?: boolean = true; //	swiping
		particlesToShow?: number = 1; // Number elements to show
		particlesToScroll?: number = 1; //Number of elements to scroll
	}

	interface PageChangeEvent {
		detail: number;
	}

	interface CarouselEvents {
		pageChange: (event: PageChangeEvent) => void;
	}

	interface CarouselSlots {
		prev: string;
		next: string;
		dots: string;
		default: string;
	}

	export default class Carousel
		extends SvelteComponentTyped<CarouselProps, CarouselEvents, CarouselSlots> {
		goTo: (index: number, options?: { animated?: boolean }) => void;
		goToPrev: (options?: { animated?: boolean }) => void;
		goToNext: (options?: { animated?: boolean }) => void;
	}
}

Hope this helps someone or can get built in!

@ecker00
Copy link

ecker00 commented Jan 17, 2023

Would be great to get types added to this package! Thank you for sharing the declaration, helped a lot! 👍

I noticed that the above declaration is missing a few things. It's possible to expose let:showNextPage on the component. I'm not sure how to correctly type that, but instead went with the bind:this={carousel} approach and carousel.goToNext to avoid it.

<!-- This shows typing errors as it's not declared in CarouselProps -->
<Carousel let:showPrevPage let:showNextPage>

@purindaisuki
Copy link

Hi, you can write the CarouselSlots interface like this to type the slot props:

interface CarouselSlots {
  prev: string;
  next: string;
  dots: string;
  default: {
    showPrevPage: () => void;
    showNextPage: () => void;
    showPage: (index: number) => void;
    currentPageIndex: number;
    ...
  };
}

@JDL1995
Copy link

JDL1995 commented Feb 10, 2023

I'm having a heck of a time with this.... where does the type declaration go??

@jokahr
Copy link

jokahr commented Feb 21, 2023

I'm having a heck of a time with this.... where does the type declaration go??

I just put it into the src directory.

By the way it should be:

interface CarouselEvents {
  pageChange: PageChangeEvent;
}

Otherwise Typescript will complain when accessing event.detail

@JDL1995
Copy link

JDL1995 commented Feb 22, 2023

Thanks! I've just had red squiggly lines for two weeks but since it works fine I don't complain XD

@imCorfitz
Copy link

imCorfitz commented Mar 24, 2023

I have optimised the types a little. These also include the individual properties provided in each slot, as well as the default slot. Using CustomEvent for the pageChange event and promises for the returned functions for the reference variable.

Create this file under src/types/svelte-carousel.d.ts.

declare module "svelte-carousel" {
  import type { SvelteComponentTyped } from "svelte";

  interface CarouselProps {
    /**
     * Enables next/prev arrows
     */
    arrows?: boolean;
    /**
     * Infinite looping
     */
    infinite?: boolean;
    /**
     * Page to start on
     */
    initialPageIndex?: number;
    /**
     * Transition duration (ms)
     */
    duration?: number;
    /**
     * Enables autoplay of pages
     */
    autoplay?: boolean;
    /**
     *  Autoplay change interval (ms)
     */
    autoplayDuration?: number;
    /**
     *  Autoplay change direction (next or prev)
     */
    autoplayDirection?: "next" | "prev";
    /**
     * 	Pauses on focus (for touchable devices - tap the carousel to toggle the autoplay, for non-touchable devices - hover over the carousel to pause the autoplay)
     */
    pauseOnFocus?: boolean;
    /**
     * Shows autoplay duration progress indicator
     */
    autoplayProgressVisible?: boolean;
    /**
     * 	Current indicator dots
     */
    dots?: boolean;
    /**
     * CSS animation timing function
     */
    timingFunction?: string;
    /**
     * 	swiping
     */
    swiping?: boolean;
    /**
     *  Number elements to show
     */
    particlesToShow?: number;
    /**
     * Number of elements to scroll
     */
    particlesToScroll?: number;
  }

  interface CarouselEvents {
    pageChange: CustomEvent<number>;
  }

  interface CarouselSlots {
    prev: {
      showPrevPage: () => void;
    };
    next: {
      showNextPage: () => void;
    };
    dots: {
      showPage: (pageIndex: number) => void;
      currentPageIndex: number;
      pagesCount: number;
    };
    default: {
      showPrevPage: () => void;
      showNextPage: () => void;
      currentPageIndex: number;
      pagesCount: number;
      showPage: (pageIndex: number) => void;
      loaded: number[];
    };
  }

  export default class Carousel extends SvelteComponentTyped<
    CarouselProps,
    CarouselEvents,
    CarouselSlots
  > {
    goTo(pageIndex: number, options?: { animated?: boolean }): Promise<void>;
    goToPrev(options?: { animated?: boolean }): Promise<void>;
    goToNext(options?: { animated?: boolean }): Promise<void>;
  }
}

As for the Sveltekit support, I simply wrapped in browser as per the documentation

<script lang="ts">
	import Carousel from 'svelte-carousel';
	import { browser } from '$app/environment';
</script>

{#if browser}
	<Carousel>
		<div>yo 0</div>
		<div>yo 1</div>
		<div>yo 2</div>
		<div let:showPage let:pagesCount slot="dots">
			{#each Array(pagesCount) as _, pageIndex (pageIndex)}
				<button on:click={() => showPage(pageIndex)}>{pageIndex}</button>
			{/each}
		</div>
	</Carousel>
{/if}

@flagrare-espark
Copy link

Anybody had any luck when trying to test files using jest that import Carousel?
I receive the error

SyntaxError: Cannot use import statement outside a module

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
TypeScript TypeScript support, typings, etc.
Projects
None yet
Development

No branches or pull requests

9 participants