@a2zb/react 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,44 @@
1
+ import { describe, expect, it, vi, beforeEach } from "vitest";
2
+ import { renderHook } from "vitest";
3
+ import { useTheme } from "../use-theme";
4
+ describe("useTheme", () => {
5
+ beforeEach(() => {
6
+ localStorage.clear();
7
+ });
8
+ function setup() {
9
+ const hook = renderHook(() => useTheme());
10
+ return {
11
+ hook,
12
+ getTheme: () => hook.result.current.theme,
13
+ applyTheme: hook.result.current.applyTheme,
14
+ };
15
+ }
16
+ describe("mount", () => {
17
+ it("defaults to runtime theme when storage is empty", () => {
18
+ const { getTheme } = setup();
19
+ expect(getTheme()).toBe("runtime");
20
+ });
21
+ it("restores theme from storage on mount", () => {
22
+ localStorage.setItem("theme", "favourite");
23
+ const { getTheme } = setup();
24
+ expect(getTheme()).toEqual("favourite");
25
+ });
26
+ });
27
+ describe("applyTheme", () => {
28
+ // nb: spies are restored automatically via restoreMocks in vitest config
29
+ it("sets data-theme attribute on document", () => {
30
+ const spy = vi.spyOn(document.documentElement, "setAttribute");
31
+ const { applyTheme } = setup();
32
+ applyTheme("fresh");
33
+ expect(document.documentElement.getAttribute("data-theme")).toBe("fresh");
34
+ expect(spy).toHaveBeenCalledWith("data-theme", "fresh");
35
+ });
36
+ it("persists theme to localStorage", () => {
37
+ const spy = vi.spyOn(Storage.prototype, "setItem");
38
+ const { applyTheme } = setup();
39
+ applyTheme("fresh");
40
+ expect(localStorage.getItem("theme")).toBe("fresh");
41
+ expect(spy).toHaveBeenCalledWith("theme", "fresh");
42
+ });
43
+ });
44
+ });
@@ -0,0 +1,22 @@
1
+ import { useEffect } from 'react';
2
+ export function useKeyboardShortcuts(map) {
3
+ useEffect(() => {
4
+ const onKey = (e) => {
5
+ const target = e.target;
6
+ // disable on cntrl / cmd
7
+ if (e.ctrlKey || e.metaKey || e.altKey)
8
+ return;
9
+ // don't trigger while typing
10
+ if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {
11
+ return;
12
+ }
13
+ const fn = map[e.key];
14
+ if (!fn)
15
+ return;
16
+ e.preventDefault();
17
+ fn();
18
+ };
19
+ window.addEventListener('keydown', onKey);
20
+ return () => window.removeEventListener('keydown', onKey);
21
+ }, [map]);
22
+ }
@@ -0,0 +1,17 @@
1
+ import { useEffect, useState } from 'react';
2
+ /**
3
+ * Hook for setting / reading current theme
4
+ * Instead of a global theme provider, the app simply stores theme name in local storage
5
+ */
6
+ export function useTheme() {
7
+ const [theme, setTheme] = useState(() => localStorage.getItem('theme') ?? 'runtime');
8
+ function apply(t) {
9
+ document.documentElement.setAttribute('data-theme', t);
10
+ localStorage.setItem('theme', t); // store in browser for future session
11
+ setTheme(t);
12
+ }
13
+ useEffect(() => {
14
+ document.documentElement.setAttribute('data-theme', theme);
15
+ }, [theme]);
16
+ return { theme, applyTheme: apply };
17
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a2zb/react",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -8,19 +8,21 @@
8
8
  "main": "./dist/index.js",
9
9
  "types": "./dist/index.d.ts",
10
10
  "dependencies": {
11
+ "@a2zb/lib": "1.0.0",
11
12
  "clsx": "^2.1.1",
12
- "focus-trap-react": "^12.0.0",
13
- "sonner": "^2.0.7",
14
- "@a2zb/lib": "1.0.0"
13
+ "focus-trap-react": "^12.0.0"
15
14
  },
16
15
  "peerDependencies": {
16
+ "@a2zb/styles": "^1.0.0",
17
17
  "react": "^19",
18
- "@a2zb/styles": "^1.0.0"
18
+ "sonner": "^2.0.7"
19
19
  },
20
20
  "devDependencies": {
21
+ "@testing-library/react": "^16.3.2",
21
22
  "@types/react": "^19.2.17",
22
23
  "react": "^19.2.7",
23
24
  "typescript": "^6.0.3",
25
+ "vitest": "^4.1.9",
24
26
  "@a2zb/styles": "1.0.0"
25
27
  },
26
28
  "scripts": {