11<script lang="ts" setup>
22import {
3- // Entry,
43 Props ,
5- // Targets,
4+ Targets ,
65} from ' @/plugin/types' ;
76import {
8- // findIndex ,
7+ includes ,
98 isEqual ,
9+ uniq ,
1010} from ' lodash' ;
1111import { globalOptions } from ' ./' ;
1212
@@ -16,56 +16,60 @@ const emit = defineEmits(['triggered']);
1616// -------------------------------------------------- Props //
1717const props = withDefaults (defineProps <Props >(), {
1818 delay: 500 ,
19- destroy: true ,
2019 pattern : () => [' ArrowUp' , ' ArrowUp' , ' ArrowDown' , ' ArrowDown' , ' ArrowLeft' , ' ArrowRight' , ' ArrowLeft' , ' ArrowRight' , ' b' , ' a' ],
20+ persist: false ,
2121 target: ' body' ,
2222 type: ' keydown' ,
2323});
2424
25-
2625const injectedOptions = inject (globalOptions , {});
2726const settings = reactive <Props >({ ... props , ... injectedOptions });
2827
2928watchEffect (() => {
3029 Object .assign (settings , { ... props , ... injectedOptions });
3130});
3231
33- let timeout: ReturnType <typeof setTimeout > = setTimeout (() => { });
3432let input = reactive <string []>([]);
3533let listenElement = null as HTMLElement | null ;
36-
37-
38- onMounted (() => {
39- layEggs ();
34+ let timeout: ReturnType <typeof setTimeout > = setTimeout (() => { });
35+ const mouseEvents: string [] = reactive ([
36+ ' click' , // Works with multiple single clicks pattern
37+ ' dblclick' , // Only works with single double click pattern set
38+ ' mouseup' , // Works with multiple mouseup clicks pattern
39+ ' mousedown' , // Works with multiple mousedown clicks pattern
40+ ]);
41+ const targets: Targets = reactive ({
42+ classNames: [],
43+ ids: [],
44+ nodes: [],
4045});
4146
4247
43- // Initiate the plugin //
44- function layEggs() {
48+ onMounted (() => {
4549 addListener ();
46- }
50+ });
4751
4852
4953// Add event listeners //
50- function addListener() {
54+ function addListener(): void {
5155 const type = settings .type as keyof Props ;
52- listenElement = document .querySelector (settings .target as string );
56+ listenElement = document .querySelector (settings .target as keyof Props );
5357
5458 if (! listenElement ) {
5559 throw new Error (` Element not found: ${settings .target } ` );
5660 }
5761
5862 if (settings .target === ' body' ) {
59- listenElement .addEventListener (type , capturePattern as EventListener , false );
63+ listenElement .addEventListener (type , capturePattern as EventListener , true );
6064 return ;
6165 }
6266
63- listenElement .addEventListener (type , emitMouseEvent as EventListener , false );
67+ listenElement .addEventListener (type , capturePattern as EventListener , true );
6468}
6569
6670
6771// Capture the Keys Pattern //
68- function capturePattern(e : KeyboardEvent ) {
72+ function capturePattern(e : KeyboardEvent ): void {
6973 const key = ref (' ' );
7074
7175 if (timeout !== null ) {
@@ -77,14 +81,29 @@ function capturePattern(e: KeyboardEvent) {
7781 key .value = e .key ;
7882 }
7983
84+ // -------------------- Mouse Events //
85+ if (includes (mouseEvents , e .type )) {
86+ const target = e .currentTarget as HTMLTextAreaElement ;
87+ key .value = e .type ;
88+
89+ targets .nodes .push (target .nodeName .toLowerCase ());
90+ targets .ids .push (target .id );
91+ targets .classNames .push (target .classList .value );
92+ }
93+
8094 input .push (key .value );
81- checkPattern ();
95+ checkPattern (e );
8296}
8397
8498
8599// Check the Keys Pattern //
86- function checkPattern() {
100+ function checkPattern(e : Event | MouseEvent | KeyboardEvent ) : void {
87101 if (isEqual (settings .pattern , input )) {
102+ if (includes (mouseEvents , e .type )) {
103+ checkTarget ();
104+ return ;
105+ }
106+
88107 emitEvent ();
89108 return ;
90109 }
@@ -93,8 +112,33 @@ function checkPattern() {
93112}
94113
95114
115+ // Check Click Targets //
116+ function checkTarget(): void {
117+ // Get clean egg target //
118+ const node = settings .target as keyof Props ;
119+ const id = node .replace (' #' , ' ' );
120+ const className = node .replace (' .' , ' ' );
121+
122+ // Reduce targets to unique values //
123+ const nodes = uniq (targets .nodes );
124+ const ids = uniq (targets .ids );
125+ const classNames = uniq (targets .classNames );
126+
127+ // Targets array should reduce down to one value, and match the clean egg target //
128+ const nodeTargetsMatch = ref (nodes .length === 1 && nodes [0 ] === node );
129+ const idTargetsMatch = ref (ids .length === 1 && ids [0 ] === id );
130+ const classTargetsMatch = ref (classNames .length === 1 && includes (classNames [0 ], className ));
131+
132+ if (nodeTargetsMatch .value || idTargetsMatch .value || classTargetsMatch .value ) {
133+ emitEvent ();
134+ }
135+
136+ reset ();
137+ }
138+
139+
96140// Reset //
97- function reset() {
141+ function reset(): void {
98142 // Reset timeout and clear input keys //
99143 timeout = setTimeout (() => {
100144 clearTimeout (timeout );
@@ -106,25 +150,23 @@ function reset() {
106150
107151
108152// Emit Event and/or Callback //
109- function emitEvent() {
110- completeHatching (capturePattern as EventListener );
111- }
112-
113- function emitMouseEvent() {
114- completeHatching (emitMouseEvent );
115- }
116-
117-
118- // Complete the process //
119- function completeHatching(event : EventListener ) {
153+ function emitEvent(): void {
120154 if (settings .callback ) {
121155 settings .callback (settings );
122156 }
123157
124158 emit (' triggered' , props );
125159
126- if (props .destroy ) {
127- listenElement ?.removeEventListener (settings .type as keyof Props , event , false );
160+ if (! settings .persist ) {
161+ destroyEvent (capturePattern as EventListener );
162+ }
163+ }
164+
165+
166+ // Destroy the event listener //
167+ function destroyEvent(event : EventListener ): void {
168+ if (listenElement ) {
169+ listenElement .removeEventListener (settings .type as keyof Props , event , true );
128170 }
129171}
130172 </script >
0 commit comments