use-secret-code
Version:
Custom hook for adding cheat codes to your React app
157 lines (155 loc) • 3.68 kB
JavaScript
// src/index.ts
import * as React from "react";
import { assign, setup } from "xstate";
import { useMachine } from "@xstate/react";
// src/utils.ts
function isEqual(array1, array2) {
return JSON.stringify(array1) === JSON.stringify(array2);
}
function takeRight(array, n) {
if (n < 1)
return [];
return array.slice(-1 * n);
}
// src/index.ts
var initialContext = {
cheatCodeKeys: void 0,
typedKeys: []
};
var cheatCodeMachine = setup({
types: {
// typegen: {};
context: {},
events: {},
input: {}
},
actions: {
record: assign({
typedKeys: ({ context, event }) => [...context.typedKeys, event.key]
}),
resetTypedKeys: assign({
typedKeys: initialContext.typedKeys
})
},
delays: {
doneTyping: 2e3
},
guards: {
cheatCodeEntered: ({ context }) => {
return Array.isArray(context.cheatCodeKeys) && isEqual(
takeRight(context.typedKeys, context.cheatCodeKeys.length),
context.cheatCodeKeys
);
}
}
}).createMachine({
context: ({ input }) => ({ ...initialContext, ...input }),
id: "cheatCodeMachine",
initial: "disabled",
states: {
disabled: {
initial: "idle",
states: {
idle: {
always: {
target: "#cheatCodeMachine.enabled",
guard: "cheatCodeEntered",
actions: "resetTypedKeys"
},
on: {
keydown: {
target: "recording",
actions: "record"
}
}
},
recording: {
after: {
doneTyping: {
target: "#cheatCodeMachine.disabled.idle",
actions: ["resetTypedKeys"],
reenter: true
}
},
always: {
target: "#cheatCodeMachine.enabled",
guard: "cheatCodeEntered",
actions: "resetTypedKeys"
},
on: {
keydown: {
target: "recording",
actions: "record",
reenter: true
}
}
}
}
},
enabled: {
initial: "idle",
states: {
idle: {
always: {
target: "#cheatCodeMachine.disabled",
guard: "cheatCodeEntered",
actions: "resetTypedKeys"
},
on: {
keydown: {
target: "recording",
actions: "record"
}
}
},
recording: {
after: {
doneTyping: {
target: "#cheatCodeMachine.enabled.idle",
actions: ["resetTypedKeys"],
reenter: true
}
},
always: {
target: "#cheatCodeMachine.disabled",
guard: "cheatCodeEntered",
actions: "resetTypedKeys"
},
on: {
keydown: {
target: "recording",
actions: "record",
reenter: true
}
}
}
}
}
}
});
function useCheatCode(cheatCodeKeys) {
const machineOpts = React.useMemo(
() => ({ input: { cheatCodeKeys } }),
[cheatCodeKeys]
);
const [state, send] = useMachine(cheatCodeMachine, machineOpts);
React.useEffect(() => {
const handleKeydownEvent = (event) => {
send(event);
};
window.addEventListener("keydown", handleKeydownEvent);
return () => {
window.removeEventListener("keydown", handleKeydownEvent);
};
}, [send]);
return state.matches("enabled");
}
var useSecretCode = (
/* c8 ignore next */
useCheatCode
);
export {
useCheatCode,
useSecretCode
};
//# sourceMappingURL=index.mjs.map