🤖 Merge PR #62755 Add alpine magic properties to alpinejs by @yusuftaufiq

* Add Alpine Magics Types for alpinejs

* Update alpinejs tests order
This commit is contained in:
Yusuf T
2022-10-28 19:31:37 +07:00
committed by GitHub
parent c72f4bbc15
commit c76a45bd88
2 changed files with 139 additions and 2 deletions

View File

@@ -6,7 +6,7 @@
* are not intended as functional tests.
*/
import Alpine from 'alpinejs';
import Alpine, { AlpineComponent } from 'alpinejs';
import { reactive, effect, stop, toRaw } from '@vue/reactivity';
{ // Alpine.reactive
@@ -508,4 +508,90 @@ import { reactive, effect, stop, toRaw } from '@vue/reactivity';
},
},
}));
// $ExpectType void
Alpine.data('user', () => ({
user: { id: 1, name: 'John Doe' },
init() {
// $ExpectType Record<string, any> & XDataContext & AlpineMagics<Record<string, any>>
this;
// $ExpectType Record<string, any>
this.$data;
// $ExpectType HTMLElement
this.$el;
// $ExpectType HTMLElement
this.$refs.fooElement;
// $ExpectType XData
this.$store;
// $ExpectType void
this.$dispatch('fooEvent');
// $ExpectType void
this.$dispatch('fooEvent', 'Hello World');
// $ExpectType string
this.$id('fooBar');
// $ExpectType string
this.$id('fooBar', 1);
// $ExpectType Promise<void>
this.$nextTick(() => {
// Do something after Alpine finishes updating the DOM.
});
// $ExpectType Promise<void>
this.$nextTick();
// $ExpectType void
this.$watch(
'user',
(
// $ExpectType any
newValue,
) => {},
);
},
}));
// $ExpectType void
Alpine.data(
'user',
(): AlpineComponent<{
user: { id: number; name: string };
}> => ({
user: { id: 1, name: 'John Doe' },
init() {
// $ExpectType { user: { id: number; name: string; }; }
this.$data;
// $ExpectType void
this.$watch(
'user',
(
// $ExpectType { id: number; name: string; }
newValue,
// $ExpectType { id: number; name: string; }
oldValue,
) => {},
);
// $ExpectType void
this.$watch(
'user.id',
(
// $ExpectType any
newValue,
) => {},
);
},
}),
);
}

View File

@@ -48,6 +48,57 @@ interface DirectiveParameters {
type: string;
}
interface AlpineMagics<T> {
/**
* Access to current Alpine data.
*/
$data: T;
/**
* Retrieve the current DOM node.
*/
$el: HTMLElement;
/**
* Retrieve DOM elements marked with x-ref inside the component.
*/
$refs: Record<string, HTMLElement>;
/**
* Access registered global Alpine stores.
*/
$store: XData;
/**
* Dispatch browser events.
*
* @param event the event name
* @param data an event-dependent value associated with the event, the value is then available to the handler using the CustomEvent.detail property
*/
$dispatch: (event: string, data?: any) => void;
/**
* Generate an element's ID and ensure that it won't conflict with other IDs of the same name on the same page.
*
* @param name the name of the id
* @param key suffix on the end of the generated ID, usually helpful for the purpose of identifying id in a loop
*/
$id: (name: string, key?: number | string) => string;
/**
* Execute a given expression AFTER Alpine has made its reactive DOM updates.
*
* @param callback a callback that will be fired after Alpine finishes updating the DOM
*/
$nextTick: (callback?: () => void) => Promise<void>;
/**
* Fire the given callback when the value in the property is changed.
*
* @param property the component property
* @param callback a callback that will fire when a given property is changed
*/
$watch: <K extends keyof T | string, V extends (K extends keyof T ? T[K] : any)>(
property: K,
callback: (newValue: V, oldValue: V) => void,
) => void;
}
export type AlpineComponent<T = Record<string, any>> = T & XDataContext & ThisType<T & XDataContext & AlpineMagics<T>>;
export interface Alpine {
// following TSDoc under MIT was taken from
// https://github.com/vuejs/vue-next/blob/92f11d6740929f5b591740e30ae5fba50940ec82/packages/reactivity/src/reactive.ts#L65-L87
@@ -218,7 +269,7 @@ export interface Alpine {
* @param name the id of the x-data context
* @param callback the initializer of the x-data context
*/
data(name: string, callback: (...initialStateArgs: unknown[]) => XDataContext): void;
data(name: string, callback: (...initialStateArgs: unknown[]) => AlpineComponent): void;
}
declare const AlpineInstance: Alpine;