@musecat/functionkit 1.0.2 → 1.2.0

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.
Files changed (101) hide show
  1. package/index.ts +1 -1
  2. package/package.json +37 -2
  3. package/packages/components/ScrolltoTop.tsx +1 -1
  4. package/packages/components/ViewportPortal.tsx +1 -2
  5. package/packages/cookie/cookie.shared.ts +17 -35
  6. package/packages/cookie/cookieNames.shared.ts +9 -0
  7. package/packages/datetime/dateTime.client.ts +1 -3
  8. package/packages/datetime/dateTime.server.ts +1 -3
  9. package/packages/datetime/dateTime.shared.ts +9 -47
  10. package/packages/hooks/useCheckInvisible.ts +1 -1
  11. package/packages/hooks/useClientDateTime.ts +3 -16
  12. package/packages/hooks/useDebounce.ts +2 -7
  13. package/packages/hooks/useGeolocation.ts +1 -5
  14. package/packages/hooks/useInterval.ts +1 -2
  15. package/packages/hooks/useKeyboardListNavigation.ts +10 -38
  16. package/packages/hooks/useLongPress.ts +13 -24
  17. package/packages/hooks/useRelativeDateTime.ts +1 -4
  18. package/packages/hooks/useViewportHeight.ts +1 -2
  19. package/packages/hooks/useViewportMatch.ts +0 -4
  20. package/packages/utils/buildContext.tsx +2 -3
  21. package/packages/utils/floatingMotion.ts +15 -23
  22. package/packages/utils/subscribeKeyboardHeight.ts +3 -0
  23. package/.agents/references/components/ScrolltoTop.md +0 -36
  24. package/.agents/references/components/SwitchCase.md +0 -47
  25. package/.agents/references/components/ViewportPortal.md +0 -34
  26. package/.agents/references/cookie/cookie.md +0 -47
  27. package/.agents/references/datetime/dateTime.client.md +0 -42
  28. package/.agents/references/datetime/dateTime.server.md +0 -42
  29. package/.agents/references/datetime/dateTime.shared.md +0 -86
  30. package/.agents/references/hooks/useAvoidKeyboard.md +0 -29
  31. package/.agents/references/hooks/useCheckInvisible.md +0 -36
  32. package/.agents/references/hooks/useCheckScroll.md +0 -36
  33. package/.agents/references/hooks/useClientDateTime.md +0 -39
  34. package/.agents/references/hooks/useDebounce.md +0 -46
  35. package/.agents/references/hooks/useDebouncedCallback.md +0 -34
  36. package/.agents/references/hooks/useDoubleClick.md +0 -40
  37. package/.agents/references/hooks/useGeolocation.md +0 -37
  38. package/.agents/references/hooks/useHasMounted.md +0 -27
  39. package/.agents/references/hooks/useIntersectionObserver.md +0 -37
  40. package/.agents/references/hooks/useInterval.md +0 -40
  41. package/.agents/references/hooks/useKeyboardHeight.md +0 -33
  42. package/.agents/references/hooks/useKeyboardListNavigation.md +0 -58
  43. package/.agents/references/hooks/useLongPress.md +0 -48
  44. package/.agents/references/hooks/usePreservedCallback.md +0 -33
  45. package/.agents/references/hooks/usePreservedReference.md +0 -34
  46. package/.agents/references/hooks/useRefEffect.md +0 -35
  47. package/.agents/references/hooks/useRelativeDateTime.md +0 -35
  48. package/.agents/references/hooks/useTimeout.md +0 -42
  49. package/.agents/references/hooks/useToggleState.md +0 -39
  50. package/.agents/references/hooks/useViewportHeight.md +0 -26
  51. package/.agents/references/hooks/useViewportMatch.md +0 -32
  52. package/.agents/references/utils/browserStorage.md +0 -41
  53. package/.agents/references/utils/buildContext.md +0 -47
  54. package/.agents/references/utils/clipboardShare.md +0 -59
  55. package/.agents/references/utils/floatingMotion.md +0 -67
  56. package/.agents/references/utils/getDeviceInfo.md +0 -43
  57. package/.agents/references/utils/isEditableKeyboardTarget.md +0 -35
  58. package/.agents/references/utils/mergeRefs.md +0 -29
  59. package/.agents/references/utils/seen.md +0 -37
  60. package/.agents/references/utils/subscribeKeyboardHeight.md +0 -35
  61. package/.gitattributes +0 -2
  62. package/AGENTS.md +0 -105
  63. package/tests/components/ScrolltoTop.test.tsx +0 -15
  64. package/tests/components/SwitchCase.test.tsx +0 -34
  65. package/tests/components/ViewportPortal.test.tsx +0 -42
  66. package/tests/cookie/cookie.test.ts +0 -156
  67. package/tests/datetime/datetime.test.ts +0 -250
  68. package/tests/hooks/useAvoidKeyboard.test.ts +0 -12
  69. package/tests/hooks/useCheckInvisible.test.ts +0 -28
  70. package/tests/hooks/useCheckScroll.test.ts +0 -23
  71. package/tests/hooks/useClientDateTime.test.ts +0 -14
  72. package/tests/hooks/useDebounce.test.ts +0 -71
  73. package/tests/hooks/useDebouncedCallback.test.ts +0 -34
  74. package/tests/hooks/useDoubleClick.test.ts +0 -31
  75. package/tests/hooks/useGeolocation.test.ts +0 -50
  76. package/tests/hooks/useHasMounted.test.ts +0 -10
  77. package/tests/hooks/useIntersectionObserver.test.ts +0 -13
  78. package/tests/hooks/useInterval.test.ts +0 -31
  79. package/tests/hooks/useKeyboardHeight.test.ts +0 -10
  80. package/tests/hooks/useKeyboardListNavigation.test.ts +0 -82
  81. package/tests/hooks/useLongPress.test.ts +0 -52
  82. package/tests/hooks/usePreservedCallback.test.ts +0 -35
  83. package/tests/hooks/usePreservedReference.test.ts +0 -35
  84. package/tests/hooks/useRefEffect.test.ts +0 -30
  85. package/tests/hooks/useRelativeDateTime.test.ts +0 -19
  86. package/tests/hooks/useTimeout.test.ts +0 -34
  87. package/tests/hooks/useToggleState.test.ts +0 -35
  88. package/tests/hooks/useViewportHeight.test.ts +0 -10
  89. package/tests/hooks/useViewportMatch.test.ts +0 -35
  90. package/tests/setup.ts +0 -9
  91. package/tests/utils/browserStorage.test.ts +0 -54
  92. package/tests/utils/buildContext.test.tsx +0 -27
  93. package/tests/utils/checkDevice.test.ts +0 -84
  94. package/tests/utils/clipboardShare.test.ts +0 -78
  95. package/tests/utils/floatingMotion.test.ts +0 -84
  96. package/tests/utils/keyboardTarget.test.ts +0 -44
  97. package/tests/utils/mergeRefs.test.ts +0 -18
  98. package/tests/utils/seen.test.ts +0 -31
  99. package/tests/utils/subscribeKeyboardHeight.test.ts +0 -50
  100. package/tsconfig.json +0 -18
  101. package/vitest.config.ts +0 -16
@@ -1,78 +0,0 @@
1
- import { describe, test, expect, vi, afterEach } from "vitest";
2
- import { NavigatorClipboard, NavigatorShare } from "@/packages/utils/clipboardShare";
3
-
4
- describe("NavigatorClipboard", () => {
5
- test("resolves with success: true on write", async () => {
6
- Object.defineProperty(navigator, "clipboard", {
7
- value: { writeText: vi.fn(() => Promise.resolve()) },
8
- writable: true,
9
- configurable: true,
10
- });
11
-
12
- const result = await NavigatorClipboard({ text: "hello" });
13
- expect(result).toEqual({ success: true });
14
- });
15
-
16
- test("resolves with success: false on failure", async () => {
17
- Object.defineProperty(navigator, "clipboard", {
18
- value: { writeText: vi.fn(() => Promise.reject(new Error("denied"))) },
19
- writable: true,
20
- configurable: true,
21
- });
22
-
23
- const result = await NavigatorClipboard({ text: "hello" });
24
- expect(result).toEqual({ success: false });
25
- });
26
- });
27
-
28
- describe("NavigatorShare", () => {
29
- afterEach(() => { vi.restoreAllMocks(); });
30
-
31
- test("uses Web Share API when available", async () => {
32
- Object.defineProperty(navigator, "share", {
33
- value: vi.fn(() => Promise.resolve()),
34
- writable: true,
35
- configurable: true,
36
- });
37
- Object.defineProperty(navigator, "clipboard", {
38
- value: { writeText: vi.fn() },
39
- writable: true,
40
- configurable: true,
41
- });
42
-
43
- const result = await NavigatorShare({ title: "Test", text: "Hello", link: "https://example.com" });
44
- expect(result).toEqual({ success: true, method: "share" });
45
- });
46
-
47
- test("falls back to clipboard when share is unavailable", async () => {
48
- Object.defineProperty(navigator, "share", {
49
- value: undefined,
50
- writable: true,
51
- configurable: true,
52
- });
53
- Object.defineProperty(navigator, "clipboard", {
54
- value: { writeText: vi.fn(() => Promise.resolve()) },
55
- writable: true,
56
- configurable: true,
57
- });
58
-
59
- const result = await NavigatorShare({ title: "Test", text: "Hello", link: "https://example.com" });
60
- expect(result).toEqual({ success: true, method: "clipboard" });
61
- });
62
-
63
- test("returns unsupported when neither share nor clipboard", async () => {
64
- Object.defineProperty(navigator, "share", {
65
- value: undefined,
66
- writable: true,
67
- configurable: true,
68
- });
69
- Object.defineProperty(navigator, "clipboard", {
70
- value: undefined,
71
- writable: true,
72
- configurable: true,
73
- });
74
-
75
- const result = await NavigatorShare({ title: "Test", text: "Hello", link: "https://example.com" });
76
- expect(result).toEqual({ success: false, method: "unsupported" });
77
- });
78
- });
@@ -1,84 +0,0 @@
1
- import { describe, test, expect } from "vitest";
2
- import {
3
- getFloatingMotionPreset,
4
- getFloatingTransformOrigin,
5
- getFloatingHiddenTransform,
6
- } from "@/packages/utils/floatingMotion";
7
-
8
- describe("getFloatingMotionPreset", () => {
9
- test("returns anchored preset", () => {
10
- const preset = getFloatingMotionPreset("anchored");
11
- expect(preset.enterMs).toBe(230);
12
- expect(preset.exitMs).toBe(170);
13
- });
14
-
15
- test("returns modal-center preset", () => {
16
- const preset = getFloatingMotionPreset("modal-center");
17
- expect(preset.enterMs).toBe(340);
18
- expect(preset.exitMs).toBe(260);
19
- });
20
-
21
- test("returns center-selected preset", () => {
22
- const preset = getFloatingMotionPreset("center-selected");
23
- expect(preset.enterMs).toBe(190);
24
- expect(preset.exitMs).toBe(140);
25
- });
26
-
27
- test("returns mobile-sheet preset", () => {
28
- const preset = getFloatingMotionPreset("mobile-sheet");
29
- expect(preset.enterMs).toBe(360);
30
- expect(preset.exitMs).toBe(280);
31
- });
32
- });
33
-
34
- describe("getFloatingTransformOrigin", () => {
35
- test("returns default when no placement", () => {
36
- expect(getFloatingTransformOrigin()).toBe("top center");
37
- });
38
-
39
- test("returns correct origin for top-left", () => {
40
- expect(getFloatingTransformOrigin("top-left")).toBe("bottom left");
41
- });
42
-
43
- test("returns correct origin for bottom-right", () => {
44
- expect(getFloatingTransformOrigin("bottom-right")).toBe("top right");
45
- });
46
-
47
- test("returns correct origin for middle-center", () => {
48
- expect(getFloatingTransformOrigin("middle-center")).toBe("center center");
49
- });
50
- });
51
-
52
- describe("getFloatingHiddenTransform", () => {
53
- test("returns mobile-sheet transform", () => {
54
- expect(getFloatingHiddenTransform({ mode: "mobile-sheet" })).toBe("translateY(1.8rem) scale(1)");
55
- });
56
-
57
- test("returns modal-center transform", () => {
58
- expect(getFloatingHiddenTransform({ mode: "modal-center" })).toBe("translateY(.8rem) scale(.94)");
59
- });
60
-
61
- test("returns center-selected transform", () => {
62
- expect(getFloatingHiddenTransform({ mode: "center-selected" })).toBe("translateY(.45rem) scale(.99)");
63
- });
64
-
65
- test("anchored with no placement", () => {
66
- expect(getFloatingHiddenTransform({ mode: "anchored" })).toBe("translateY(.4rem) scale(.975)");
67
- });
68
-
69
- test("anchored with top placement", () => {
70
- expect(getFloatingHiddenTransform({ mode: "anchored", placement: "top-left" })).toBe("translateY(.4rem) scale(.975)");
71
- });
72
-
73
- test("anchored with bottom placement", () => {
74
- expect(getFloatingHiddenTransform({ mode: "anchored", placement: "bottom-center" })).toBe("translateY(-.4rem) scale(.975)");
75
- });
76
-
77
- test("anchored with middle-left placement", () => {
78
- expect(getFloatingHiddenTransform({ mode: "anchored", placement: "middle-left" })).toBe("translateX(.4rem) scale(.975)");
79
- });
80
-
81
- test("anchored with middle-right placement", () => {
82
- expect(getFloatingHiddenTransform({ mode: "anchored", placement: "middle-right" })).toBe("translateX(-.4rem) scale(.975)");
83
- });
84
- });
@@ -1,44 +0,0 @@
1
- import { describe, test, expect } from "vitest";
2
- import { isEditableKeyboardTarget } from "@/packages/utils/keyboardTarget";
3
-
4
- describe("isEditableKeyboardTarget", () => {
5
- test("returns true for contentEditable", () => {
6
- const el = document.createElement("div");
7
- Object.defineProperty(el, "isContentEditable", { value: true });
8
- expect(isEditableKeyboardTarget(el)).toBe(true);
9
- });
10
-
11
- test("returns true for TEXTAREA", () => {
12
- const el = document.createElement("textarea");
13
- expect(isEditableKeyboardTarget(el)).toBe(true);
14
- });
15
-
16
- test("returns true for text INPUT", () => {
17
- const el = document.createElement("input");
18
- el.type = "text";
19
- expect(isEditableKeyboardTarget(el)).toBe(true);
20
- });
21
-
22
- test("returns false for button INPUT", () => {
23
- const el = document.createElement("input");
24
- el.type = "button";
25
- expect(isEditableKeyboardTarget(el)).toBe(false);
26
- });
27
-
28
- test("returns false for checkbox INPUT", () => {
29
- const el = document.createElement("input");
30
- el.type = "checkbox";
31
- expect(isEditableKeyboardTarget(el)).toBe(false);
32
- });
33
-
34
- test("returns false for radio INPUT", () => {
35
- const el = document.createElement("input");
36
- el.type = "radio";
37
- expect(isEditableKeyboardTarget(el)).toBe(false);
38
- });
39
-
40
- test("returns false for regular div", () => {
41
- const el = document.createElement("div");
42
- expect(isEditableKeyboardTarget(el)).toBe(false);
43
- });
44
- });
@@ -1,18 +0,0 @@
1
- import { describe, test, expect, vi } from "vitest";
2
- import { mergeRefs } from "@/packages/utils/mergeRefs";
3
-
4
- describe("mergeRefs", () => {
5
- test("merges multiple refs", () => {
6
- const ref1 = vi.fn();
7
- const ref2 = { current: null };
8
- const ref3 = null;
9
-
10
- const merged = mergeRefs(ref1, ref2, ref3);
11
- const element = document.createElement("div");
12
-
13
- merged(element as any);
14
-
15
- expect(ref1).toHaveBeenCalledWith(element);
16
- expect(ref2.current).toBe(element);
17
- });
18
- });
@@ -1,31 +0,0 @@
1
- import { describe, test, expect } from "vitest";
2
- import {
3
- parseSeen,
4
- hasSeenKey,
5
- buildSeenValue,
6
- SEEN_STORAGE_KEY,
7
- } from "@/packages/utils/seen";
8
-
9
- describe("seen", () => {
10
- test("SEEN_STORAGE_KEY", () => {
11
- expect(SEEN_STORAGE_KEY).toBe("seen");
12
- });
13
-
14
- test("parseSeen", () => {
15
- expect(parseSeen(null)).toEqual({});
16
- expect(parseSeen('{"a":true}')).toEqual({ a: true });
17
- expect(parseSeen("invalid json")).toEqual({});
18
- expect(parseSeen("[]")).toEqual({});
19
- });
20
-
21
- test("hasSeenKey", () => {
22
- expect(hasSeenKey('{"a":true}', "a")).toBe(true);
23
- expect(hasSeenKey('{"a":true}', "b")).toBe(false);
24
- expect(hasSeenKey(null, "a")).toBe(false);
25
- });
26
-
27
- test("buildSeenValue", () => {
28
- const result = buildSeenValue('{"a":true}', "b");
29
- expect(JSON.parse(result)).toEqual({ a: true, b: true });
30
- });
31
- });
@@ -1,50 +0,0 @@
1
- import { describe, test, expect, vi, beforeEach, afterEach } from "vitest";
2
- import { subscribeKeyboardHeight } from "@/packages/utils/subscribeKeyboardHeight";
3
-
4
- describe("subscribeKeyboardHeight", () => {
5
- let visualViewport: any;
6
-
7
- beforeEach(() => {
8
- visualViewport = {
9
- height: 600,
10
- width: 390,
11
- offsetTop: 0,
12
- addEventListener: vi.fn(),
13
- removeEventListener: vi.fn(),
14
- };
15
- Object.defineProperty(window, "visualViewport", {
16
- value: visualViewport,
17
- writable: true,
18
- configurable: true,
19
- });
20
- Object.defineProperty(window, "innerHeight", {
21
- value: 800,
22
- writable: true,
23
- configurable: true,
24
- });
25
- });
26
-
27
- afterEach(() => { vi.useRealTimers(); });
28
-
29
- test("subscribes to resize events", () => {
30
- const callback = vi.fn();
31
- subscribeKeyboardHeight({ callback });
32
- expect(visualViewport.addEventListener).toHaveBeenCalledWith("resize", expect.any(Function));
33
- expect(visualViewport.addEventListener).toHaveBeenCalledWith("scroll", expect.any(Function));
34
- });
35
-
36
- test("calls immediately when immediate is true", () => {
37
- vi.useFakeTimers();
38
- const callback = vi.fn();
39
- subscribeKeyboardHeight({ callback, immediate: true });
40
- vi.advanceTimersByTime(16);
41
- expect(callback).toHaveBeenCalled();
42
- });
43
-
44
- test("returns unsubscribe function", () => {
45
- const callback = vi.fn();
46
- const { unsubscribe } = subscribeKeyboardHeight({ callback });
47
- unsubscribe();
48
- expect(visualViewport.removeEventListener).toHaveBeenCalled();
49
- });
50
- });
package/tsconfig.json DELETED
@@ -1,18 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2017",
4
- "lib": ["dom", "dom.iterable", "esnext"],
5
- "allowJs": true,
6
- "skipLibCheck": true,
7
- "strict": true,
8
- "noEmit": true,
9
- "esModuleInterop": true,
10
- "module": "esnext",
11
- "moduleResolution": "bundler",
12
- "resolveJsonModule": true,
13
- "isolatedModules": true,
14
- "jsx": "react-jsx",
15
- "incremental": true
16
- },
17
- "include": ["**/*.ts", "**/*.tsx"]
18
- }
package/vitest.config.ts DELETED
@@ -1,16 +0,0 @@
1
- import { defineConfig } from "vitest/config";
2
- import path from "path";
3
-
4
- export default defineConfig({
5
- test: {
6
- environment: "jsdom",
7
- setupFiles: ["./tests/setup.ts"],
8
- include: ["tests/**/*.test.{ts,tsx}"],
9
- globals: true,
10
- },
11
- resolve: {
12
- alias: {
13
- "@": path.resolve(__dirname, "./"),
14
- },
15
- },
16
- });