@yakad/ui 1.3.102 → 1.3.104

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,23 @@
1
+ /// <reference types="react" />
2
+ export interface InteractiveSurfaceProps extends React.HTMLAttributes<HTMLDivElement> {
3
+ onRightClick?: (e: MouseEvent) => void;
4
+ onTap?: (e: TouchEvent) => void;
5
+ onDoubleTap?: (e: TouchEvent) => void;
6
+ onOutsideClick?: () => void;
7
+ onSwipeLeft?: () => void;
8
+ onSwipeRight?: () => void;
9
+ onSwipeUp?: () => void;
10
+ onSwipeDown?: () => void;
11
+ onPinchIn?: () => void;
12
+ onPinchOut?: () => void;
13
+ onRotate?: (angle: number) => void;
14
+ onScrollStart?: () => void;
15
+ onScrollStop?: () => void;
16
+ onResize?: (entry: ResizeObserverEntry) => void;
17
+ onVisibile?: () => void;
18
+ onHidden?: () => void;
19
+ onMouseHoverStart?: (e: MouseEvent) => void;
20
+ onMouseHoverLeave?: (e: MouseEvent) => void;
21
+ children?: React.ReactNode;
22
+ }
23
+ export declare const InteractiveSurface: import("react").ForwardRefExoticComponent<InteractiveSurfaceProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,215 @@
1
+ "use client";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ import { jsx as _jsx } from "react/jsx-runtime";
14
+ import { forwardRef, useEffect, useImperativeHandle, useRef } from "react";
15
+ export const InteractiveSurface = forwardRef((_a, forwardedRef) => {
16
+ var { children, onRightClick, onTap, onDoubleTap, onOutsideClick, onSwipeLeft, onSwipeRight, onSwipeUp, onSwipeDown, onPinchIn, onPinchOut, onRotate, onScrollStart, onScrollStop, onResize, onVisibile, onHidden, onMouseHoverStart, onMouseHoverLeave } = _a, restProps = __rest(_a, ["children", "onRightClick", "onTap", "onDoubleTap", "onOutsideClick", "onSwipeLeft", "onSwipeRight", "onSwipeUp", "onSwipeDown", "onPinchIn", "onPinchOut", "onRotate", "onScrollStart", "onScrollStop", "onResize", "onVisibile", "onHidden", "onMouseHoverStart", "onMouseHoverLeave"]);
17
+ const localRef = useRef(null);
18
+ // Let the parent access our DOM node
19
+ useImperativeHandle(forwardedRef, () => localRef.current);
20
+ useEffect(() => {
21
+ const el = localRef.current;
22
+ if (!el)
23
+ return;
24
+ // Event cleanup store
25
+ const cleanupFns = [];
26
+ // === RIGHT CLICK ===
27
+ if (onRightClick) {
28
+ const handler = (e) => {
29
+ e.preventDefault();
30
+ onRightClick(e);
31
+ };
32
+ el.addEventListener("contextmenu", handler);
33
+ cleanupFns.push(() => el.removeEventListener("contextmenu", handler));
34
+ }
35
+ // === OUTSIDE CLICK ===
36
+ if (onOutsideClick) {
37
+ const handler = (e) => {
38
+ if (!el.contains(e.target)) {
39
+ onOutsideClick();
40
+ }
41
+ };
42
+ document.addEventListener("click", handler);
43
+ cleanupFns.push(() => document.removeEventListener("click", handler));
44
+ }
45
+ // === TAP & DOUBLE TAP ===
46
+ if (onTap || onDoubleTap) {
47
+ let lastTap = 0;
48
+ const tapHandler = (e) => {
49
+ const now = Date.now();
50
+ if (now - lastTap < 300) {
51
+ onDoubleTap === null || onDoubleTap === void 0 ? void 0 : onDoubleTap(e);
52
+ }
53
+ else {
54
+ onTap === null || onTap === void 0 ? void 0 : onTap(e);
55
+ }
56
+ lastTap = now;
57
+ };
58
+ el.addEventListener("touchend", tapHandler);
59
+ cleanupFns.push(() => el.removeEventListener("touchend", tapHandler));
60
+ }
61
+ // === SWIPE ===
62
+ if (onSwipeLeft || onSwipeRight || onSwipeUp || onSwipeDown) {
63
+ let startX = 0, startY = 0, endX = 0, endY = 0;
64
+ const touchStart = (e) => {
65
+ const t = e.touches[0];
66
+ startX = t.clientX;
67
+ startY = t.clientY;
68
+ endX = startX;
69
+ endY = startY;
70
+ };
71
+ const touchMove = (e) => {
72
+ const t = e.touches[0];
73
+ endX = t.clientX;
74
+ endY = t.clientY;
75
+ };
76
+ const touchEnd = () => {
77
+ const dx = endX - startX;
78
+ const dy = endY - startY;
79
+ const absDx = Math.abs(dx);
80
+ const absDy = Math.abs(dy);
81
+ const threshold = 30;
82
+ if (absDx > absDy) {
83
+ if (dx > threshold)
84
+ onSwipeRight === null || onSwipeRight === void 0 ? void 0 : onSwipeRight();
85
+ if (dx < -threshold)
86
+ onSwipeLeft === null || onSwipeLeft === void 0 ? void 0 : onSwipeLeft();
87
+ }
88
+ else {
89
+ if (dy > threshold)
90
+ onSwipeDown === null || onSwipeDown === void 0 ? void 0 : onSwipeDown();
91
+ if (dy < -threshold)
92
+ onSwipeUp === null || onSwipeUp === void 0 ? void 0 : onSwipeUp();
93
+ }
94
+ };
95
+ el.addEventListener("touchstart", touchStart);
96
+ el.addEventListener("touchmove", touchMove);
97
+ el.addEventListener("touchend", touchEnd);
98
+ cleanupFns.push(() => {
99
+ el.removeEventListener("touchstart", touchStart);
100
+ el.removeEventListener("touchmove", touchMove);
101
+ el.removeEventListener("touchend", touchEnd);
102
+ });
103
+ }
104
+ // === PINCH & ROTATE ===
105
+ if (onPinchIn || onPinchOut || onRotate) {
106
+ let startDistance = 0;
107
+ let startAngle = 0;
108
+ const getDistance = (t1, t2) => Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY);
109
+ const getAngle = (t1, t2) => Math.atan2(t2.clientY - t1.clientY, t2.clientX - t1.clientX) *
110
+ (180 / Math.PI);
111
+ const handleStart = (e) => {
112
+ if (e.touches.length === 2) {
113
+ const [t1, t2] = e.touches;
114
+ startDistance = getDistance(t1, t2);
115
+ startAngle = getAngle(t1, t2);
116
+ }
117
+ };
118
+ const handleMove = (e) => {
119
+ if (e.touches.length === 2) {
120
+ const [t1, t2] = e.touches;
121
+ const dist = getDistance(t1, t2);
122
+ const angle = getAngle(t1, t2);
123
+ if (dist < startDistance - 20)
124
+ onPinchIn === null || onPinchIn === void 0 ? void 0 : onPinchIn();
125
+ if (dist > startDistance + 20)
126
+ onPinchOut === null || onPinchOut === void 0 ? void 0 : onPinchOut();
127
+ const deltaAngle = angle - startAngle;
128
+ if (Math.abs(deltaAngle) > 15) {
129
+ onRotate === null || onRotate === void 0 ? void 0 : onRotate(deltaAngle);
130
+ }
131
+ }
132
+ };
133
+ el.addEventListener("touchstart", handleStart);
134
+ el.addEventListener("touchmove", handleMove);
135
+ cleanupFns.push(() => {
136
+ el.removeEventListener("touchstart", handleStart);
137
+ el.removeEventListener("touchmove", handleMove);
138
+ });
139
+ }
140
+ // === RESIZE OBSERVER ===
141
+ let resizeObserver = null;
142
+ if (onResize) {
143
+ resizeObserver = new ResizeObserver((entries) => {
144
+ for (const entry of entries) {
145
+ onResize(entry);
146
+ }
147
+ });
148
+ resizeObserver.observe(el);
149
+ cleanupFns.push(() => resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect());
150
+ }
151
+ // === VISIBILITY OBSERVER ===
152
+ let intersectionObserver = null;
153
+ if (onVisibile || onHidden) {
154
+ intersectionObserver = new IntersectionObserver((entries) => {
155
+ entries[0].isIntersecting ? onVisibile === null || onVisibile === void 0 ? void 0 : onVisibile() : onHidden === null || onHidden === void 0 ? void 0 : onHidden();
156
+ });
157
+ intersectionObserver.observe(el);
158
+ cleanupFns.push(() => intersectionObserver === null || intersectionObserver === void 0 ? void 0 : intersectionObserver.disconnect());
159
+ }
160
+ // === On Hover Change ===
161
+ const hasFinePointer = window.matchMedia("(pointer: fine)").matches;
162
+ if (hasFinePointer && (onMouseHoverStart || onMouseHoverLeave)) {
163
+ const mouseEnter = (e) => onMouseHoverStart === null || onMouseHoverStart === void 0 ? void 0 : onMouseHoverStart(e);
164
+ const mouseLeave = (e) => onMouseHoverLeave === null || onMouseHoverLeave === void 0 ? void 0 : onMouseHoverLeave(e);
165
+ el.addEventListener("mouseenter", mouseEnter);
166
+ el.addEventListener("mouseleave", mouseLeave);
167
+ cleanupFns.push(() => {
168
+ el.removeEventListener("mouseenter", mouseEnter);
169
+ el.removeEventListener("mouseleave", mouseLeave);
170
+ });
171
+ }
172
+ // === SCROLL START/END ===
173
+ if (onScrollStart) {
174
+ let scrolling = false;
175
+ let scrollTimeout;
176
+ const scrollHandler = () => {
177
+ if (!scrolling) {
178
+ scrolling = true;
179
+ onScrollStart === null || onScrollStart === void 0 ? void 0 : onScrollStart();
180
+ }
181
+ clearTimeout(scrollTimeout);
182
+ scrollTimeout = setTimeout(() => {
183
+ scrolling = false;
184
+ onScrollStop === null || onScrollStop === void 0 ? void 0 : onScrollStop();
185
+ }, 150);
186
+ };
187
+ el.addEventListener("scroll", scrollHandler);
188
+ cleanupFns.push(() => el.removeEventListener("scroll", scrollHandler));
189
+ }
190
+ // Cleanup on unmount
191
+ return () => {
192
+ cleanupFns.forEach((fn) => fn());
193
+ };
194
+ }, [
195
+ onRightClick,
196
+ onTap,
197
+ onDoubleTap,
198
+ onOutsideClick,
199
+ onSwipeLeft,
200
+ onSwipeRight,
201
+ onSwipeUp,
202
+ onSwipeDown,
203
+ onPinchIn,
204
+ onPinchOut,
205
+ onRotate,
206
+ onScrollStart,
207
+ onScrollStop,
208
+ onResize,
209
+ onVisibile,
210
+ onHidden,
211
+ onMouseHoverStart,
212
+ onMouseHoverLeave,
213
+ ]);
214
+ return (_jsx("div", Object.assign({ ref: localRef }, restProps, { children: children })));
215
+ });
package/dist/index.d.ts CHANGED
@@ -28,4 +28,4 @@ export * from "./RadioGroup/RadioGroup";
28
28
  export * from "./RadioButton/RadioButton";
29
29
  export * from "./CodeBox/CodeBox";
30
30
  export * from "./Display/Display";
31
- export * from "./ClickOutsideListener/ClickOutsideListener";
31
+ export * from "./InteractiveSurface/InteractiveSurface";
package/dist/index.js CHANGED
@@ -33,4 +33,4 @@ export * from "./RadioButton/RadioButton";
33
33
  export * from "./CodeBox/CodeBox";
34
34
  // Utilities
35
35
  export * from "./Display/Display";
36
- export * from "./ClickOutsideListener/ClickOutsideListener";
36
+ export * from "./InteractiveSurface/InteractiveSurface";
package/package.json CHANGED
@@ -1,14 +1,11 @@
1
1
  {
2
2
  "name": "@yakad/ui",
3
- "version": "1.3.102",
3
+ "version": "1.3.104",
4
4
  "private": false,
5
5
  "author": "Natiq",
6
6
  "description": "UI components for NextJS/React",
7
7
  "main": "dist/index.js",
8
8
  "types": "dist/index.d.ts",
9
- "sideEffects": [
10
- "dist/globals.css"
11
- ],
12
9
  "keywords": [
13
10
  "yakad",
14
11
  "react",
@@ -31,7 +28,7 @@
31
28
  "typecheck": "tsc --noEmit",
32
29
  "lint": "eslint src/**/*.{ts,tsx}",
33
30
  "test": "echo \"No tests specified\" && exit 0",
34
- "prepublishOnly": "npm run build && npm run test && npm run lint && npm run typecheck && npm version patch"
31
+ "prepublishOnly": "npm run test && npm run build && npm run typecheck && npm version patch"
35
32
  },
36
33
  "dependencies": {
37
34
  "@yakad/symbols": "1.0.25",
@@ -1,6 +0,0 @@
1
- /// <reference types="react" />
2
- export interface ClickOutsideListenerProps extends React.HTMLAttributes<HTMLDivElement> {
3
- onclickoutside?: () => void;
4
- children?: React.ReactNode;
5
- }
6
- export declare const ClickOutsideListener: ({ onclickoutside, children, ...restProps }: ClickOutsideListenerProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,28 +0,0 @@
1
- "use client";
2
- var __rest = (this && this.__rest) || function (s, e) {
3
- var t = {};
4
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
- t[p] = s[p];
6
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
- t[p[i]] = s[p[i]];
10
- }
11
- return t;
12
- };
13
- import { jsx as _jsx } from "react/jsx-runtime";
14
- import { useEffect, useRef } from "react";
15
- export const ClickOutsideListener = (_a) => {
16
- var { onclickoutside, children } = _a, restProps = __rest(_a, ["onclickoutside", "children"]);
17
- const ref = useRef(null);
18
- useEffect(() => {
19
- const handleOutSideClick = (event) => {
20
- if (ref.current && !ref.current.contains(event.target))
21
- onclickoutside === null || onclickoutside === void 0 ? void 0 : onclickoutside();
22
- };
23
- document.addEventListener("click", handleOutSideClick, true);
24
- // CleanUp When element unmount
25
- return () => document.removeEventListener("click", handleOutSideClick, true);
26
- }, [onclickoutside]);
27
- return (_jsx("div", Object.assign({ ref: ref }, restProps, { children: children })));
28
- };
File without changes