vue-signature-pad icon indicating copy to clipboard operation
vue-signature-pad copied to clipboard

Still no typescript support?

Open masteroleary opened this issue 4 years ago • 17 comments

I am having trouble using the component in my vue.js app without typescript support. Can't find a working example online. I see an old issue that was closed but the example isn't working for me.

masteroleary avatar Apr 18 '20 14:04 masteroleary

PR is welcome!

neighborhood999 avatar Apr 28 '20 03:04 neighborhood999

I copied over and enhanced issue #61 typings (sharing code as image is pretty evil...)

Can definitely be improved further.

declare module 'vue-signature-pad' {
  import { default as _Vue } from 'vue';

  export interface VueSignaturePad extends _Vue {
    width: string;
    height: string;
    saveType: string;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    options: Record<string, any>;
    images: [];
    customStyle: CSSStyleDeclaration;
    saveSignature():
      | { isEmpty: true; data: undefined }
      | { isEmpty: false; data: string };
    undoSignature(): void;
    clearSignature(): void;
    // eslint-disable-next-line @typescript-eslint/ban-types
    mergeImagesAndSignature(signature: object | string): void;
    addImages(images: []): void;
    lockSignaturePad(): void;
    openSignaturePad(): void;
    getPropImagesAndCacheImages(): void;
    clearCacheImages(): void;
    fromDataURL(data: string): void;
    isEmpty(): boolean;
    toData(): string;
  }

  export function VueSignaturePad(Vue: typeof _Vue): void;
  export default VueSignaturePad;
}

Suggested usage (with Composition API) to leverage TS discriminated unions on the signature object:

    const signatureStepPadRef = ref() as Ref<VueSignaturePad>;

    const methodCalledToReadSignature = () => {
      const signature = signatureStepPadRef.value.saveSignature();
      if (!signature.isEmpty) {
        console.log(signature.data);
      }
    }

IlCallo avatar Jul 16 '20 18:07 IlCallo

Thanks a lot for this update !

I tried to import the module including the ".d.ts" file, but I got the following error :

143:5 Argument of type '{ components: { TopToolbar: typeof TopToolbar; VueSignaturePad: (Vue: VueConstructor<Vue>) => void; }; }' is not assignable to parameter of type 'VueClass<Vue>'.
  Object literal may only specify known properties, but 'components' does not exist in type 'VueClass<Vue>'. Did you mean to write 'component'?
    141 |
    142 |   @Component({
  > 143 |     components: {
        |     ^
    144 |       TopToolbar,
    145 |       VueSignaturePad,
    146 |     }

Any idea where it could come from ?

pebrun avatar Jan 21 '21 13:01 pebrun

I don't use Class API, sorry

IlCallo avatar Jan 21 '21 13:01 IlCallo

I copied over and enhanced issue #61 typings (sharing code as image is pretty evil...)

Can definitely be improved further.

declare module 'vue-signature-pad' {
  import { default as _Vue } from 'vue';

  export interface VueSignaturePad extends _Vue {
    width: string;
    height: string;
    saveType: string;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    options: Record<string, any>;
    images: [];
    customStyle: CSSStyleDeclaration;
    saveSignature():
      | { isEmpty: true; data: undefined }
      | { isEmpty: false; data: string };
    undoSignature(): void;
    clearSignature(): void;
    // eslint-disable-next-line @typescript-eslint/ban-types
    mergeImagesAndSignature(signature: object | string): void;
    addImages(images: []): void;
    lockSignaturePad(): void;
    openSignaturePad(): void;
    getPropImagesAndCacheImages(): void;
    clearCacheImages(): void;
    fromDataURL(data: string): void;
    isEmpty(): boolean;
    toData(): string;
  }

  export function VueSignaturePad(Vue: typeof _Vue): void;
  export default VueSignaturePad;
}

Suggested usage (with Composition API) to leverage TS discriminated unions on the signature object:

    const signatureStepPadRef = ref() as Ref<VueSignaturePad>;

    const methodCalledToReadSignature = () => {
      const signature = signatureStepPadRef.value.saveSignature();
      if (!signature.isEmpty) {
        console.log(signature.data);
      }
    }

It doesn't work with Nuxt unfortunately. Got error Invalid module name in augmentation. Module 'vue-signature-pad' resolves to an untyped module at 'D:/myproject/nuxt-ts/node_modules/vue-signature-pad/dist/vue-signature-pad.ssr.js', which cannot be augmented.ts(2665) in index.d.ts

fahmiegerton avatar May 06 '21 13:05 fahmiegerton

I don't think Nuxt has something to do with it, it's a problem in TS realm. No idea why you get that tho.

It may happen if you are doing something else in that file apart declaring this module typings

IlCallo avatar May 06 '21 20:05 IlCallo

I don't think Nuxt has something to do with it, it's a problem in TS realm. No idea why you get that tho.

It may happen if you are doing something else in that file apart declaring this module typings

@IlCallo This is inside in my index.d.ts file. Idk much about TS anymore.

import { accessorType } from '~/store'
import { default as _Vue } from 'vue'

declare module 'vue/types/vue' {
	interface Vue {
		$accessor: typeof accessorType
	}
}

declare module '@nuxt/types' {
	interface NuxtAppOptions {
		$accessor: typeof accessorType
	}
}

declare module 'vue-signature-pad' {
	export interface VueSignaturePad extends _Vue {
		width: string;
		height: string;
		saveType: string;
		// eslint-disable-next-line @typescript-eslint/no-explicit-any
		options: Record<string, any>;
		images: [];
		customStyle: CSSStyleDeclaration;
		saveSignature():
			| { isEmpty: true; data: undefined }
			| { isEmpty: false; data: string };
		undoSignature(): void;
		clearSignature(): void;
		// eslint-disable-next-line @typescript-eslint/ban-types
		mergeImagesAndSignature(signature: object | string): void;
		addImages(images: []): void;
		lockSignaturePad(): void;
		openSignaturePad(): void;
		getPropImagesAndCacheImages(): void;
		clearCacheImages(): void;
		fromDataURL(data: string): void;
		isEmpty(): boolean;
		toData(): string;
	}

	export function VueSignaturePad(Vue: typeof _Vue): void;
	export default VueSignaturePad;
}

Is there something wrong with it?

fahmiegerton avatar May 07 '21 03:05 fahmiegerton

Well, the temporary solution for now is to make it as any. Like this

const { isEmpty, data } = (this.$refs.signaturePad as any).saveSignature()

This is the way I could think of so far.

fahmiegerton avatar May 07 '21 06:05 fahmiegerton

You should move your imports INTO the declare module stuff, or the ambient declaration just won't have effect, as even a single top level import or export makes that file an ES module to TS and treated as such

IlCallo avatar May 07 '21 12:05 IlCallo

You should move your imports INTO the declare module stuff, or the ambient declaration just won't have effect, as even a single top level import or export makes that file an ES module to TS and treated as such

Well, tried that but got this error image

If I import vue/types/vue, it would throw an error like this image

I tried to make a two file, first is index.d.ts then vue-shim.d.ts then types.d.ts and so on. No luck so far. That's why I put that on top I thought it would make a difference, but none also. Probably I would make a new project, see if my project is broken or something.

fahmiegerton avatar May 07 '21 12:05 fahmiegerton

Remember to restart VSCode between each rename of the files, as sometimes it get out of sync

IlCallo avatar May 07 '21 13:05 IlCallo

Remember to restart VSCode between each rename of the files, as sometimes it get out of sync

I even restart my pc because the past overwhelm-headache-kindof issue I have with vscode, so when someone told me to restart IDE, I restart my pc instead hehe

fahmiegerton avatar May 07 '21 13:05 fahmiegerton

By the way, in Nuxt, I should put it in index.d.ts on the root project, right? not in plugins folder, isn't?

fahmiegerton avatar May 07 '21 13:05 fahmiegerton

Honestly dunno, never used Nuxt :sweat_smile:

IlCallo avatar May 07 '21 14:05 IlCallo

Updated version compatible with Vue3 and Volar

/* eslint-disable @typescript-eslint/no-explicit-any */

declare module 'vue-signature-pad' {
  import {
    ComponentPublicInstance,
    ComponentOptions,
    ComputedOptions,
    Plugin,
    MethodOptions,
  } from 'vue';

  type ComponentConstructor<
    Component extends ComponentPublicInstance<
      Props,
      RawBindings,
      D,
      C,
      M
    > = ComponentPublicInstance<any>,
    Props = any,
    RawBindings = any,
    D = any,
    C extends ComputedOptions = ComputedOptions,
    M extends MethodOptions = MethodOptions
  > = { new (): Component } & ComponentOptions<Props, RawBindings, D, C, M>;

  export interface VueSignaturePadProps {
    width?: string;
    height?: string;
    saveType?: string;
    options?: Record<string, any>;
    images?: [];
    customStyle?: CSSStyleDeclaration;
  }

  export interface VueSignaturePad
    extends ComponentPublicInstance<VueSignaturePadProps> {
    saveSignature():
      | { isEmpty: true; data: undefined }
      | { isEmpty: false; data: string };
    undoSignature(): void;
    clearSignature(): void;
    // eslint-disable-next-line @typescript-eslint/ban-types
    mergeImagesAndSignature(signature: object | string): void;
    addImages(images: []): void;
    lockSignaturePad(): void;
    openSignaturePad(): void;
    getPropImagesAndCacheImages(): void;
    clearCacheImages(): void;
    fromDataURL(data: string): void;
    isEmpty(): boolean;
    toData(): string;
  }

  export const VueSignaturePad: ComponentConstructor<VueSignaturePad>;
  const plugin: Plugin;
  export default plugin;
}

IlCallo avatar Sep 27 '21 15:09 IlCallo

By the way, in Nuxt, I should put it in index.d.ts on the root project, right? not in plugins folder, isn't?

A little late but it cost me the past half hour to figure this out, so hopefully this helps someone with "nuxt": "^2.15.3":

  1. Create plugin vue-signature-pad in plugins folder with this content:
import Vue from 'vue'
import VueSignaturePad from 'vue-signature-pad'

Vue.use(VueSignaturePad)
  1. add module declaration to decs.d.ts in root folder using the code created by @fahmiegerton
  2. add plugin to nuxt.config.js plugins: ['~/plugins/vue-signature-pad'],

oneWaveAdrian avatar Apr 01 '22 19:04 oneWaveAdrian

If you are using Nuxt 3, the plugin step is replaced with:

import VueSignaturePad from 'vue-signature-pad'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(VueSignaturePad);
})

By the way, in Nuxt, I should put it in index.d.ts on the root project, right? not in plugins folder, isn't?

A little late but it cost me the past half hour to figure this out, so hopefully this helps someone with "nuxt": "^2.15.3":

  1. Create plugin vue-signature-pad in plugins folder with this content:
import Vue from 'vue'
import VueSignaturePad from 'vue-signature-pad'

Vue.use(VueSignaturePad)
  1. add module declaration to decs.d.ts in root folder using the code created by @fahmiegerton
  2. add plugin to nuxt.config.js plugins: ['~/plugins/vue-signature-pad'],

KyleSmith0905 avatar Jun 11 '23 22:06 KyleSmith0905