@smoregg/sdk 0.1.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.
- package/dist/cjs/components/DirectionPad.cjs +68 -0
- package/dist/cjs/components/DirectionPad.cjs.map +1 -0
- package/dist/cjs/components/DirectionPad.module.css.cjs +12 -0
- package/dist/cjs/components/DirectionPad.module.css.cjs.map +1 -0
- package/dist/cjs/components/HoldButton.cjs +57 -0
- package/dist/cjs/components/HoldButton.cjs.map +1 -0
- package/dist/cjs/components/HoldButton.module.css.cjs +12 -0
- package/dist/cjs/components/HoldButton.module.css.cjs.map +1 -0
- package/dist/cjs/components/SwipeArea.cjs +58 -0
- package/dist/cjs/components/SwipeArea.cjs.map +1 -0
- package/dist/cjs/components/SwipeArea.module.css.cjs +12 -0
- package/dist/cjs/components/SwipeArea.module.css.cjs.map +1 -0
- package/dist/cjs/components/TapButton.cjs +58 -0
- package/dist/cjs/components/TapButton.cjs.map +1 -0
- package/dist/cjs/components/TapButton.module.css.cjs +12 -0
- package/dist/cjs/components/TapButton.module.css.cjs.map +1 -0
- package/dist/cjs/context/RoomProvider.cjs +118 -0
- package/dist/cjs/context/RoomProvider.cjs.map +1 -0
- package/dist/cjs/hooks/useExternalGames.cjs +49 -0
- package/dist/cjs/hooks/useExternalGames.cjs.map +1 -0
- package/dist/cjs/hooks/useGameHost.cjs +135 -0
- package/dist/cjs/hooks/useGameHost.cjs.map +1 -0
- package/dist/cjs/hooks/useGamePlayer.cjs +75 -0
- package/dist/cjs/hooks/useGamePlayer.cjs.map +1 -0
- package/dist/cjs/iframe/index.cjs +508 -0
- package/dist/cjs/iframe/index.cjs.map +1 -0
- package/dist/cjs/index.cjs +32 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.cjs +33 -0
- package/dist/cjs/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.cjs.map +1 -0
- package/dist/cjs/server/index.cjs +45 -0
- package/dist/cjs/server/index.cjs.map +1 -0
- package/dist/cjs/transport/DirectTransport.cjs +23 -0
- package/dist/cjs/transport/DirectTransport.cjs.map +1 -0
- package/dist/cjs/transport/PostMessageTransport.cjs +72 -0
- package/dist/cjs/transport/PostMessageTransport.cjs.map +1 -0
- package/dist/cjs/transport/protocol.cjs +10 -0
- package/dist/cjs/transport/protocol.cjs.map +1 -0
- package/dist/esm/components/DirectionPad.js +66 -0
- package/dist/esm/components/DirectionPad.js.map +1 -0
- package/dist/esm/components/DirectionPad.module.css.js +8 -0
- package/dist/esm/components/DirectionPad.module.css.js.map +1 -0
- package/dist/esm/components/HoldButton.js +55 -0
- package/dist/esm/components/HoldButton.js.map +1 -0
- package/dist/esm/components/HoldButton.module.css.js +8 -0
- package/dist/esm/components/HoldButton.module.css.js.map +1 -0
- package/dist/esm/components/SwipeArea.js +56 -0
- package/dist/esm/components/SwipeArea.js.map +1 -0
- package/dist/esm/components/SwipeArea.module.css.js +8 -0
- package/dist/esm/components/SwipeArea.module.css.js.map +1 -0
- package/dist/esm/components/TapButton.js +56 -0
- package/dist/esm/components/TapButton.js.map +1 -0
- package/dist/esm/components/TapButton.module.css.js +8 -0
- package/dist/esm/components/TapButton.module.css.js.map +1 -0
- package/dist/esm/context/RoomProvider.js +109 -0
- package/dist/esm/context/RoomProvider.js.map +1 -0
- package/dist/esm/hooks/useExternalGames.js +47 -0
- package/dist/esm/hooks/useExternalGames.js.map +1 -0
- package/dist/esm/hooks/useGameHost.js +133 -0
- package/dist/esm/hooks/useGameHost.js.map +1 -0
- package/dist/esm/hooks/useGamePlayer.js +73 -0
- package/dist/esm/hooks/useGamePlayer.js.map +1 -0
- package/dist/esm/iframe/index.js +502 -0
- package/dist/esm/iframe/index.js.map +1 -0
- package/dist/esm/index.js +11 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js +29 -0
- package/dist/esm/node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.js.map +1 -0
- package/dist/esm/server/index.js +43 -0
- package/dist/esm/server/index.js.map +1 -0
- package/dist/esm/transport/DirectTransport.js +21 -0
- package/dist/esm/transport/DirectTransport.js.map +1 -0
- package/dist/esm/transport/PostMessageTransport.js +70 -0
- package/dist/esm/transport/PostMessageTransport.js.map +1 -0
- package/dist/esm/transport/protocol.js +7 -0
- package/dist/esm/transport/protocol.js.map +1 -0
- package/dist/types/components/DirectionPad.d.ts +21 -0
- package/dist/types/components/DirectionPad.d.ts.map +1 -0
- package/dist/types/components/HoldButton.d.ts +22 -0
- package/dist/types/components/HoldButton.d.ts.map +1 -0
- package/dist/types/components/IframeGameBridge.d.ts +40 -0
- package/dist/types/components/IframeGameBridge.d.ts.map +1 -0
- package/dist/types/components/SwipeArea.d.ts +19 -0
- package/dist/types/components/SwipeArea.d.ts.map +1 -0
- package/dist/types/components/TapButton.d.ts +19 -0
- package/dist/types/components/TapButton.d.ts.map +1 -0
- package/dist/types/components/index.d.ts +8 -0
- package/dist/types/components/index.d.ts.map +1 -0
- package/dist/types/context/RoomProvider.d.ts +69 -0
- package/dist/types/context/RoomProvider.d.ts.map +1 -0
- package/dist/types/context/index.d.ts +3 -0
- package/dist/types/context/index.d.ts.map +1 -0
- package/dist/types/dev/DevSimulator.d.ts +31 -0
- package/dist/types/dev/DevSimulator.d.ts.map +1 -0
- package/dist/types/dev/index.d.ts +2 -0
- package/dist/types/dev/index.d.ts.map +1 -0
- package/dist/types/hooks/index.d.ts +4 -0
- package/dist/types/hooks/index.d.ts.map +1 -0
- package/dist/types/hooks/useExternalGames.d.ts +32 -0
- package/dist/types/hooks/useExternalGames.d.ts.map +1 -0
- package/dist/types/hooks/useGameHost.d.ts +40 -0
- package/dist/types/hooks/useGameHost.d.ts.map +1 -0
- package/dist/types/hooks/useGamePlayer.d.ts +17 -0
- package/dist/types/hooks/useGamePlayer.d.ts.map +1 -0
- package/dist/types/iframe/IframeRoomProvider.d.ts +31 -0
- package/dist/types/iframe/IframeRoomProvider.d.ts.map +1 -0
- package/dist/types/iframe/index.d.ts +18 -0
- package/dist/types/iframe/index.d.ts.map +1 -0
- package/dist/types/iframe/vanilla.d.ts +40 -0
- package/dist/types/iframe/vanilla.d.ts.map +1 -0
- package/dist/types/index.d.ts +34 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/server/createGameRelay.d.ts +26 -0
- package/dist/types/server/createGameRelay.d.ts.map +1 -0
- package/dist/types/server/index.d.ts +3 -0
- package/dist/types/server/index.d.ts.map +1 -0
- package/dist/types/transport/DirectTransport.d.ts +14 -0
- package/dist/types/transport/DirectTransport.d.ts.map +1 -0
- package/dist/types/transport/PostMessageTransport.d.ts +20 -0
- package/dist/types/transport/PostMessageTransport.d.ts.map +1 -0
- package/dist/types/transport/index.d.ts +6 -0
- package/dist/types/transport/index.d.ts.map +1 -0
- package/dist/types/transport/protocol.d.ts +50 -0
- package/dist/types/transport/protocol.d.ts.map +1 -0
- package/dist/types/transport/types.d.ts +14 -0
- package/dist/types/transport/types.d.ts.map +1 -0
- package/dist/types/types.d.ts +33 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/umd/smore-sdk-iframe.umd.js +511 -0
- package/dist/umd/smore-sdk-iframe.umd.js.map +1 -0
- package/dist/umd/smore-sdk-iframe.umd.min.js +2 -0
- package/dist/umd/smore-sdk-iframe.umd.min.js.map +1 -0
- package/dist/umd/smore-sdk.umd.js +709 -0
- package/dist/umd/smore-sdk.umd.js.map +1 -0
- package/dist/umd/smore-sdk.umd.min.js +2 -0
- package/dist/umd/smore-sdk.umd.min.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var DirectionPad_module = require('./DirectionPad.module.css.cjs');
|
|
6
|
+
|
|
7
|
+
function DirectionPad({
|
|
8
|
+
onDirection,
|
|
9
|
+
leftRightOnly = false,
|
|
10
|
+
upDownOnly = false,
|
|
11
|
+
className
|
|
12
|
+
}) {
|
|
13
|
+
const pressedRef = react.useRef(/* @__PURE__ */ new Set());
|
|
14
|
+
const handlePress = react.useCallback((direction) => {
|
|
15
|
+
if (pressedRef.current.has(direction)) return;
|
|
16
|
+
pressedRef.current.add(direction);
|
|
17
|
+
if (navigator.vibrate) {
|
|
18
|
+
navigator.vibrate(10);
|
|
19
|
+
}
|
|
20
|
+
onDirection(direction);
|
|
21
|
+
}, [onDirection]);
|
|
22
|
+
const handleRelease = react.useCallback((direction) => {
|
|
23
|
+
pressedRef.current.delete(direction);
|
|
24
|
+
}, []);
|
|
25
|
+
const createButton = (direction, label) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
26
|
+
"button",
|
|
27
|
+
{
|
|
28
|
+
className: `${DirectionPad_module.default.dirButton} ${DirectionPad_module.default[direction]}`,
|
|
29
|
+
onTouchStart: (e) => {
|
|
30
|
+
e.preventDefault();
|
|
31
|
+
handlePress(direction);
|
|
32
|
+
},
|
|
33
|
+
onTouchEnd: (e) => {
|
|
34
|
+
e.preventDefault();
|
|
35
|
+
handleRelease(direction);
|
|
36
|
+
},
|
|
37
|
+
onTouchCancel: () => handleRelease(direction),
|
|
38
|
+
onMouseDown: () => handlePress(direction),
|
|
39
|
+
onMouseUp: () => handleRelease(direction),
|
|
40
|
+
onMouseLeave: () => handleRelease(direction),
|
|
41
|
+
children: label
|
|
42
|
+
},
|
|
43
|
+
direction
|
|
44
|
+
);
|
|
45
|
+
if (leftRightOnly) {
|
|
46
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${DirectionPad_module.default.padContainer} ${DirectionPad_module.default.horizontal} ${className || ""}`, children: [
|
|
47
|
+
createButton("left", "\u25C0"),
|
|
48
|
+
createButton("right", "\u25B6")
|
|
49
|
+
] });
|
|
50
|
+
}
|
|
51
|
+
if (upDownOnly) {
|
|
52
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${DirectionPad_module.default.padContainer} ${DirectionPad_module.default.vertical} ${className || ""}`, children: [
|
|
53
|
+
createButton("up", "\u25B2"),
|
|
54
|
+
createButton("down", "\u25BC")
|
|
55
|
+
] });
|
|
56
|
+
}
|
|
57
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${DirectionPad_module.default.padContainer} ${DirectionPad_module.default.full} ${className || ""}`, children: [
|
|
58
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: DirectionPad_module.default.row, children: createButton("up", "\u25B2") }),
|
|
59
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: DirectionPad_module.default.row, children: [
|
|
60
|
+
createButton("left", "\u25C0"),
|
|
61
|
+
createButton("right", "\u25B6")
|
|
62
|
+
] }),
|
|
63
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: DirectionPad_module.default.row, children: createButton("down", "\u25BC") })
|
|
64
|
+
] });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
exports.DirectionPad = DirectionPad;
|
|
68
|
+
//# sourceMappingURL=DirectionPad.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DirectionPad.cjs","sources":["../../../src/components/DirectionPad.tsx"],"sourcesContent":["/**\n * S'MORE Game SDK - DirectionPad Component\n *\n * 4-direction or 2-direction control pad\n */\n\nimport { useCallback, useRef } from 'react';\nimport type { DirectionPadProps } from '../types';\nimport styles from './DirectionPad.module.css';\n\n/**\n * DirectionPad - For directional input\n *\n * @example\n * ```tsx\n * // 4 directions\n * <DirectionPad onDirection={(dir) => send('move', { direction: dir })} />\n *\n * // Left/Right only\n * <DirectionPad leftRightOnly onDirection={(dir) => send('move', { direction: dir })} />\n * ```\n */\nexport function DirectionPad({\n onDirection,\n leftRightOnly = false,\n upDownOnly = false,\n className,\n}: DirectionPadProps) {\n const pressedRef = useRef<Set<string>>(new Set());\n\n const handlePress = useCallback((direction: 'up' | 'down' | 'left' | 'right') => {\n if (pressedRef.current.has(direction)) return;\n pressedRef.current.add(direction);\n\n // Haptic feedback\n if (navigator.vibrate) {\n navigator.vibrate(10);\n }\n\n onDirection(direction);\n }, [onDirection]);\n\n const handleRelease = useCallback((direction: string) => {\n pressedRef.current.delete(direction);\n }, []);\n\n const createButton = (direction: 'up' | 'down' | 'left' | 'right', label: string) => (\n <button\n key={direction}\n className={`${styles.dirButton} ${styles[direction]}`}\n onTouchStart={(e) => {\n e.preventDefault();\n handlePress(direction);\n }}\n onTouchEnd={(e) => {\n e.preventDefault();\n handleRelease(direction);\n }}\n onTouchCancel={() => handleRelease(direction)}\n onMouseDown={() => handlePress(direction)}\n onMouseUp={() => handleRelease(direction)}\n onMouseLeave={() => handleRelease(direction)}\n >\n {label}\n </button>\n );\n\n if (leftRightOnly) {\n return (\n <div className={`${styles.padContainer} ${styles.horizontal} ${className || ''}`}>\n {createButton('left', '◀')}\n {createButton('right', '▶')}\n </div>\n );\n }\n\n if (upDownOnly) {\n return (\n <div className={`${styles.padContainer} ${styles.vertical} ${className || ''}`}>\n {createButton('up', '▲')}\n {createButton('down', '▼')}\n </div>\n );\n }\n\n return (\n <div className={`${styles.padContainer} ${styles.full} ${className || ''}`}>\n <div className={styles.row}>\n {createButton('up', '▲')}\n </div>\n <div className={styles.row}>\n {createButton('left', '◀')}\n {createButton('right', '▶')}\n </div>\n <div className={styles.row}>\n {createButton('down', '▼')}\n </div>\n </div>\n );\n}\n\nexport default DirectionPad;\n"],"names":["useRef","useCallback","jsx","styles","jsxs"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var styleInject_es = require('../node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.cjs');
|
|
6
|
+
|
|
7
|
+
var css_248z = ".DirectionPad-module_padContainer__iL-rh{align-items:center;display:flex;flex-direction:column;gap:8px;user-select:none;-webkit-user-select:none}.DirectionPad-module_horizontal__kI4j7{flex-direction:row;gap:16px}.DirectionPad-module_vertical__b8Xec{flex-direction:column;gap:16px}.DirectionPad-module_row__mzuUr{display:flex;gap:8px}.DirectionPad-module_dirButton__QCCHz{-webkit-tap-highlight-color:transparent;align-items:center;background:var(--color-surface,#374151);border:none;border-radius:12px;color:#fff;cursor:pointer;display:flex;font-size:24px;height:70px;justify-content:center;touch-action:manipulation;transition:transform .1s ease,background .1s ease;width:70px}.DirectionPad-module_dirButton__QCCHz:active{background:var(--color-primary,#6366f1);transform:scale(.9)}.DirectionPad-module_horizontal__kI4j7 .DirectionPad-module_dirButton__QCCHz,.DirectionPad-module_vertical__b8Xec .DirectionPad-module_dirButton__QCCHz{font-size:32px;height:100px;width:100px}";
|
|
8
|
+
var styles = {"padContainer":"DirectionPad-module_padContainer__iL-rh","horizontal":"DirectionPad-module_horizontal__kI4j7","vertical":"DirectionPad-module_vertical__b8Xec","row":"DirectionPad-module_row__mzuUr","dirButton":"DirectionPad-module_dirButton__QCCHz"};
|
|
9
|
+
styleInject_es.default(css_248z);
|
|
10
|
+
|
|
11
|
+
exports.default = styles;
|
|
12
|
+
//# sourceMappingURL=DirectionPad.module.css.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DirectionPad.module.css.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var HoldButton_module = require('./HoldButton.module.css.cjs');
|
|
6
|
+
|
|
7
|
+
function HoldButton({
|
|
8
|
+
onHoldStart,
|
|
9
|
+
onHoldEnd,
|
|
10
|
+
children,
|
|
11
|
+
className,
|
|
12
|
+
disabled = false
|
|
13
|
+
}) {
|
|
14
|
+
const isHolding = react.useRef(false);
|
|
15
|
+
const buttonRef = react.useRef(null);
|
|
16
|
+
const startHold = react.useCallback(() => {
|
|
17
|
+
if (disabled || isHolding.current) return;
|
|
18
|
+
isHolding.current = true;
|
|
19
|
+
buttonRef.current?.classList.add(HoldButton_module.default.pressed);
|
|
20
|
+
if (navigator.vibrate) {
|
|
21
|
+
navigator.vibrate(10);
|
|
22
|
+
}
|
|
23
|
+
onHoldStart();
|
|
24
|
+
}, [onHoldStart, disabled]);
|
|
25
|
+
const endHold = react.useCallback(() => {
|
|
26
|
+
if (!isHolding.current) return;
|
|
27
|
+
isHolding.current = false;
|
|
28
|
+
buttonRef.current?.classList.remove(HoldButton_module.default.pressed);
|
|
29
|
+
onHoldEnd();
|
|
30
|
+
}, [onHoldEnd]);
|
|
31
|
+
const handleTouchStart = react.useCallback((e) => {
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
startHold();
|
|
34
|
+
}, [startHold]);
|
|
35
|
+
const handleTouchEnd = react.useCallback((e) => {
|
|
36
|
+
e.preventDefault();
|
|
37
|
+
endHold();
|
|
38
|
+
}, [endHold]);
|
|
39
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
40
|
+
"button",
|
|
41
|
+
{
|
|
42
|
+
ref: buttonRef,
|
|
43
|
+
className: `${HoldButton_module.default.holdButton} ${className || ""} ${disabled ? HoldButton_module.default.disabled : ""}`,
|
|
44
|
+
onTouchStart: handleTouchStart,
|
|
45
|
+
onTouchEnd: handleTouchEnd,
|
|
46
|
+
onTouchCancel: handleTouchEnd,
|
|
47
|
+
onMouseDown: startHold,
|
|
48
|
+
onMouseUp: endHold,
|
|
49
|
+
onMouseLeave: endHold,
|
|
50
|
+
disabled,
|
|
51
|
+
children
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
exports.HoldButton = HoldButton;
|
|
57
|
+
//# sourceMappingURL=HoldButton.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HoldButton.cjs","sources":["../../../src/components/HoldButton.tsx"],"sourcesContent":["/**\n * S'MORE Game SDK - HoldButton Component\n *\n * Button that detects hold start/end events\n */\n\nimport { useRef, useCallback } from 'react';\nimport type React from 'react';\nimport type { HoldButtonProps } from '../types';\nimport styles from './HoldButton.module.css';\n\n/**\n * HoldButton - For hold/release input patterns\n *\n * @example\n * ```tsx\n * <HoldButton\n * onHoldStart={() => send('charge', { type: 'start' })}\n * onHoldEnd={() => send('charge', { type: 'end' })}\n * >\n * HOLD\n * </HoldButton>\n * ```\n */\nexport function HoldButton({\n onHoldStart,\n onHoldEnd,\n children,\n className,\n disabled = false,\n}: HoldButtonProps) {\n const isHolding = useRef(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n const startHold = useCallback(() => {\n if (disabled || isHolding.current) return;\n isHolding.current = true;\n buttonRef.current?.classList.add(styles.pressed || '');\n\n // Haptic feedback\n if (navigator.vibrate) {\n navigator.vibrate(10);\n }\n\n onHoldStart();\n }, [onHoldStart, disabled]);\n\n const endHold = useCallback(() => {\n if (!isHolding.current) return;\n isHolding.current = false;\n buttonRef.current?.classList.remove(styles.pressed || '');\n onHoldEnd();\n }, [onHoldEnd]);\n\n const handleTouchStart = useCallback((e: React.TouchEvent) => {\n e.preventDefault();\n startHold();\n }, [startHold]);\n\n const handleTouchEnd = useCallback((e: React.TouchEvent) => {\n e.preventDefault();\n endHold();\n }, [endHold]);\n\n return (\n <button\n ref={buttonRef}\n className={`${styles.holdButton} ${className || ''} ${disabled ? styles.disabled : ''}`}\n onTouchStart={handleTouchStart}\n onTouchEnd={handleTouchEnd}\n onTouchCancel={handleTouchEnd}\n onMouseDown={startHold}\n onMouseUp={endHold}\n onMouseLeave={endHold}\n disabled={disabled}\n >\n {children}\n </button>\n );\n}\n\nexport default HoldButton;\n"],"names":["useRef","useCallback","styles","jsx"],"mappings":";;;;;;AAwBO,SAAS,UAAA,CAAW;AAAA,EACzB,WAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA,GAAW;AACb,CAAA,EAAoB;AAClB,EAAA,MAAM,SAAA,GAAYA,aAAO,KAAK,CAAA;AAC9B,EAAA,MAAM,SAAA,GAAYA,aAA0B,IAAI,CAAA;AAEhD,EAAA,MAAM,SAAA,GAAYC,kBAAY,MAAM;AAClC,IAAA,IAAI,QAAA,IAAY,UAAU,OAAA,EAAS;AACnC,IAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AACpB,IAAA,SAAA,CAAU,OAAA,EAAS,SAAA,CAAU,GAAA,CAAIC,yBAAA,CAAO,OAAa,CAAA;AAGrD,IAAA,IAAI,UAAU,OAAA,EAAS;AACrB,MAAA,SAAA,CAAU,QAAQ,EAAE,CAAA;AAAA,IACtB;AAEA,IAAA,WAAA,EAAY;AAAA,EACd,CAAA,EAAG,CAAC,WAAA,EAAa,QAAQ,CAAC,CAAA;AAE1B,EAAA,MAAM,OAAA,GAAUD,kBAAY,MAAM;AAChC,IAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACxB,IAAA,SAAA,CAAU,OAAA,GAAU,KAAA;AACpB,IAAA,SAAA,CAAU,OAAA,EAAS,SAAA,CAAU,MAAA,CAAOC,yBAAA,CAAO,OAAa,CAAA;AACxD,IAAA,SAAA,EAAU;AAAA,EACZ,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,MAAM,gBAAA,GAAmBD,iBAAA,CAAY,CAAC,CAAA,KAAwB;AAC5D,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,SAAA,EAAU;AAAA,EACZ,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,MAAM,cAAA,GAAiBA,iBAAA,CAAY,CAAC,CAAA,KAAwB;AAC1D,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,uBACEE,cAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,SAAA;AAAA,MACL,SAAA,EAAW,CAAA,EAAGD,yBAAA,CAAO,UAAU,CAAA,CAAA,EAAI,SAAA,IAAa,EAAE,CAAA,CAAA,EAAI,QAAA,GAAWA,yBAAA,CAAO,QAAA,GAAW,EAAE,CAAA,CAAA;AAAA,MACrF,YAAA,EAAc,gBAAA;AAAA,MACd,UAAA,EAAY,cAAA;AAAA,MACZ,aAAA,EAAe,cAAA;AAAA,MACf,WAAA,EAAa,SAAA;AAAA,MACb,SAAA,EAAW,OAAA;AAAA,MACX,YAAA,EAAc,OAAA;AAAA,MACd,QAAA;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;;;;"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var styleInject_es = require('../node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.cjs');
|
|
6
|
+
|
|
7
|
+
var css_248z = ".HoldButton-module_holdButton__tu4mi{-webkit-tap-highlight-color:transparent;align-items:center;background:var(--color-secondary,#f59e0b);border:none;border-radius:16px;color:#fff;cursor:pointer;display:flex;font-size:18px;font-weight:700;justify-content:center;min-height:80px;min-width:80px;padding:16px 24px;touch-action:manipulation;transition:transform .1s ease,background .1s ease;user-select:none;-webkit-user-select:none}.HoldButton-module_holdButton__tu4mi:active,.HoldButton-module_pressed__JWIRG{background:var(--color-secondary-dark,#d97706);transform:scale(.95)}.HoldButton-module_disabled__4QwwT{cursor:not-allowed;opacity:.5}.HoldButton-module_disabled__4QwwT.HoldButton-module_pressed__JWIRG,.HoldButton-module_disabled__4QwwT:active{background:var(--color-secondary,#f59e0b);transform:none}";
|
|
8
|
+
var styles = {"holdButton":"HoldButton-module_holdButton__tu4mi","pressed":"HoldButton-module_pressed__JWIRG","disabled":"HoldButton-module_disabled__4QwwT"};
|
|
9
|
+
styleInject_es.default(css_248z);
|
|
10
|
+
|
|
11
|
+
exports.default = styles;
|
|
12
|
+
//# sourceMappingURL=HoldButton.module.css.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HoldButton.module.css.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var SwipeArea_module = require('./SwipeArea.module.css.cjs');
|
|
6
|
+
|
|
7
|
+
function SwipeArea({
|
|
8
|
+
onSwipe,
|
|
9
|
+
threshold = 50,
|
|
10
|
+
children,
|
|
11
|
+
className
|
|
12
|
+
}) {
|
|
13
|
+
const touchStart = react.useRef(null);
|
|
14
|
+
const handleTouchStart = react.useCallback((e) => {
|
|
15
|
+
const touch = e.touches[0];
|
|
16
|
+
if (!touch) return;
|
|
17
|
+
touchStart.current = { x: touch.clientX, y: touch.clientY };
|
|
18
|
+
}, []);
|
|
19
|
+
const handleTouchEnd = react.useCallback((e) => {
|
|
20
|
+
if (!touchStart.current) return;
|
|
21
|
+
const touch = e.changedTouches[0];
|
|
22
|
+
if (!touch) return;
|
|
23
|
+
const deltaX = touch.clientX - touchStart.current.x;
|
|
24
|
+
const deltaY = touch.clientY - touchStart.current.y;
|
|
25
|
+
const absX = Math.abs(deltaX);
|
|
26
|
+
const absY = Math.abs(deltaY);
|
|
27
|
+
if (absX < threshold && absY < threshold) {
|
|
28
|
+
touchStart.current = null;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
let direction;
|
|
32
|
+
if (absX > absY) {
|
|
33
|
+
direction = deltaX > 0 ? "right" : "left";
|
|
34
|
+
} else {
|
|
35
|
+
direction = deltaY > 0 ? "down" : "up";
|
|
36
|
+
}
|
|
37
|
+
if (navigator.vibrate) {
|
|
38
|
+
navigator.vibrate(15);
|
|
39
|
+
}
|
|
40
|
+
onSwipe(direction);
|
|
41
|
+
touchStart.current = null;
|
|
42
|
+
}, [onSwipe, threshold]);
|
|
43
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
44
|
+
"div",
|
|
45
|
+
{
|
|
46
|
+
className: `${SwipeArea_module.default.swipeArea} ${className || ""}`,
|
|
47
|
+
onTouchStart: handleTouchStart,
|
|
48
|
+
onTouchEnd: handleTouchEnd,
|
|
49
|
+
onTouchCancel: () => {
|
|
50
|
+
touchStart.current = null;
|
|
51
|
+
},
|
|
52
|
+
children
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
exports.SwipeArea = SwipeArea;
|
|
58
|
+
//# sourceMappingURL=SwipeArea.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SwipeArea.cjs","sources":["../../../src/components/SwipeArea.tsx"],"sourcesContent":["/**\n * S'MORE Game SDK - SwipeArea Component\n *\n * Detects swipe gestures\n */\n\nimport { useRef, useCallback } from 'react';\nimport type React from 'react';\nimport type { SwipeAreaProps } from '../types';\nimport styles from './SwipeArea.module.css';\n\n/**\n * SwipeArea - For swipe gesture input\n *\n * @example\n * ```tsx\n * <SwipeArea onSwipe={(dir) => send('swipe', { direction: dir })}>\n * <div>Swipe here!</div>\n * </SwipeArea>\n * ```\n */\nexport function SwipeArea({\n onSwipe,\n threshold = 50,\n children,\n className,\n}: SwipeAreaProps) {\n const touchStart = useRef<{ x: number; y: number } | null>(null);\n\n const handleTouchStart = useCallback((e: React.TouchEvent) => {\n const touch = e.touches[0];\n if (!touch) return;\n touchStart.current = { x: touch.clientX, y: touch.clientY };\n }, []);\n\n const handleTouchEnd = useCallback((e: React.TouchEvent) => {\n if (!touchStart.current) return;\n\n const touch = e.changedTouches[0];\n if (!touch) return;\n const deltaX = touch.clientX - touchStart.current.x;\n const deltaY = touch.clientY - touchStart.current.y;\n\n const absX = Math.abs(deltaX);\n const absY = Math.abs(deltaY);\n\n // Check if swipe exceeds threshold\n if (absX < threshold && absY < threshold) {\n touchStart.current = null;\n return;\n }\n\n // Determine direction\n let direction: 'up' | 'down' | 'left' | 'right';\n if (absX > absY) {\n direction = deltaX > 0 ? 'right' : 'left';\n } else {\n direction = deltaY > 0 ? 'down' : 'up';\n }\n\n // Haptic feedback\n if (navigator.vibrate) {\n navigator.vibrate(15);\n }\n\n onSwipe(direction);\n touchStart.current = null;\n }, [onSwipe, threshold]);\n\n return (\n <div\n className={`${styles.swipeArea} ${className || ''}`}\n onTouchStart={handleTouchStart}\n onTouchEnd={handleTouchEnd}\n onTouchCancel={() => { touchStart.current = null; }}\n >\n {children}\n </div>\n );\n}\n\nexport default SwipeArea;\n"],"names":["useRef","useCallback","jsx","styles"],"mappings":";;;;;;AAqBO,SAAS,SAAA,CAAU;AAAA,EACxB,OAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA;AAAA,EACA;AACF,CAAA,EAAmB;AACjB,EAAA,MAAM,UAAA,GAAaA,aAAwC,IAAI,CAAA;AAE/D,EAAA,MAAM,gBAAA,GAAmBC,iBAAA,CAAY,CAAC,CAAA,KAAwB;AAC5D,IAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AACzB,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,UAAA,CAAW,UAAU,EAAE,CAAA,EAAG,MAAM,OAAA,EAAS,CAAA,EAAG,MAAM,OAAA,EAAQ;AAAA,EAC5D,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,cAAA,GAAiBA,iBAAA,CAAY,CAAC,CAAA,KAAwB;AAC1D,IAAA,IAAI,CAAC,WAAW,OAAA,EAAS;AAEzB,IAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,cAAA,CAAe,CAAC,CAAA;AAChC,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,GAAU,UAAA,CAAW,OAAA,CAAQ,CAAA;AAClD,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,GAAU,UAAA,CAAW,OAAA,CAAQ,CAAA;AAElD,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAC5B,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAG5B,IAAA,IAAI,IAAA,GAAO,SAAA,IAAa,IAAA,GAAO,SAAA,EAAW;AACxC,MAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AACrB,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,SAAA;AACJ,IAAA,IAAI,OAAO,IAAA,EAAM;AACf,MAAA,SAAA,GAAY,MAAA,GAAS,IAAI,OAAA,GAAU,MAAA;AAAA,IACrC,CAAA,MAAO;AACL,MAAA,SAAA,GAAY,MAAA,GAAS,IAAI,MAAA,GAAS,IAAA;AAAA,IACpC;AAGA,IAAA,IAAI,UAAU,OAAA,EAAS;AACrB,MAAA,SAAA,CAAU,QAAQ,EAAE,CAAA;AAAA,IACtB;AAEA,IAAA,OAAA,CAAQ,SAAS,CAAA;AACjB,IAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,EACvB,CAAA,EAAG,CAAC,OAAA,EAAS,SAAS,CAAC,CAAA;AAEvB,EAAA,uBACEC,cAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAW,CAAA,EAAGC,wBAAA,CAAO,SAAS,CAAA,CAAA,EAAI,aAAa,EAAE,CAAA,CAAA;AAAA,MACjD,YAAA,EAAc,gBAAA;AAAA,MACd,UAAA,EAAY,cAAA;AAAA,MACZ,eAAe,MAAM;AAAE,QAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AAAA,MAAM,CAAA;AAAA,MAEjD;AAAA;AAAA,GACH;AAEJ;;;;"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var styleInject_es = require('../node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.cjs');
|
|
6
|
+
|
|
7
|
+
var css_248z = ".SwipeArea-module_swipeArea__yob7L{height:100%;touch-action:none;user-select:none;-webkit-user-select:none;width:100%}";
|
|
8
|
+
var styles = {"swipeArea":"SwipeArea-module_swipeArea__yob7L"};
|
|
9
|
+
styleInject_es.default(css_248z);
|
|
10
|
+
|
|
11
|
+
exports.default = styles;
|
|
12
|
+
//# sourceMappingURL=SwipeArea.module.css.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SwipeArea.module.css.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var TapButton_module = require('./TapButton.module.css.cjs');
|
|
6
|
+
|
|
7
|
+
function TapButton({
|
|
8
|
+
onTap,
|
|
9
|
+
children,
|
|
10
|
+
className,
|
|
11
|
+
disabled = false
|
|
12
|
+
}) {
|
|
13
|
+
const isPressed = react.useRef(false);
|
|
14
|
+
const buttonRef = react.useRef(null);
|
|
15
|
+
const handleTouchStart = react.useCallback((e) => {
|
|
16
|
+
if (disabled) return;
|
|
17
|
+
e.preventDefault();
|
|
18
|
+
isPressed.current = true;
|
|
19
|
+
buttonRef.current?.classList.add(TapButton_module.default.pressed);
|
|
20
|
+
if (navigator.vibrate) {
|
|
21
|
+
navigator.vibrate(10);
|
|
22
|
+
}
|
|
23
|
+
onTap();
|
|
24
|
+
}, [onTap, disabled]);
|
|
25
|
+
const handleTouchEnd = react.useCallback((e) => {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
isPressed.current = false;
|
|
28
|
+
buttonRef.current?.classList.remove(TapButton_module.default.pressed);
|
|
29
|
+
}, []);
|
|
30
|
+
const handleMouseDown = react.useCallback(() => {
|
|
31
|
+
if (disabled) return;
|
|
32
|
+
isPressed.current = true;
|
|
33
|
+
buttonRef.current?.classList.add(TapButton_module.default.pressed);
|
|
34
|
+
onTap();
|
|
35
|
+
}, [onTap, disabled]);
|
|
36
|
+
const handleMouseUp = react.useCallback(() => {
|
|
37
|
+
isPressed.current = false;
|
|
38
|
+
buttonRef.current?.classList.remove(TapButton_module.default.pressed);
|
|
39
|
+
}, []);
|
|
40
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
41
|
+
"button",
|
|
42
|
+
{
|
|
43
|
+
ref: buttonRef,
|
|
44
|
+
className: `${TapButton_module.default.tapButton} ${className || ""} ${disabled ? TapButton_module.default.disabled : ""}`,
|
|
45
|
+
onTouchStart: handleTouchStart,
|
|
46
|
+
onTouchEnd: handleTouchEnd,
|
|
47
|
+
onTouchCancel: handleTouchEnd,
|
|
48
|
+
onMouseDown: handleMouseDown,
|
|
49
|
+
onMouseUp: handleMouseUp,
|
|
50
|
+
onMouseLeave: handleMouseUp,
|
|
51
|
+
disabled,
|
|
52
|
+
children
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
exports.TapButton = TapButton;
|
|
58
|
+
//# sourceMappingURL=TapButton.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TapButton.cjs","sources":["../../../src/components/TapButton.tsx"],"sourcesContent":["/**\n * S'MORE Game SDK - TapButton Component\n *\n * Optimized touch button with haptic feedback\n */\n\nimport { useRef, useCallback } from 'react';\nimport type React from 'react';\nimport type { TapButtonProps } from '../types';\nimport styles from './TapButton.module.css';\n\n/**\n * TapButton - Optimized for mobile touch input\n *\n * @example\n * ```tsx\n * <TapButton onTap={() => send('tap')}>\n * TAP!\n * </TapButton>\n * ```\n */\nexport function TapButton({\n onTap,\n children,\n className,\n disabled = false,\n}: TapButtonProps) {\n const isPressed = useRef(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n const handleTouchStart = useCallback((e: React.TouchEvent) => {\n if (disabled) return;\n e.preventDefault();\n isPressed.current = true;\n buttonRef.current?.classList.add(styles.pressed || '');\n\n // Haptic feedback\n if (navigator.vibrate) {\n navigator.vibrate(10);\n }\n\n onTap();\n }, [onTap, disabled]);\n\n const handleTouchEnd = useCallback((e: React.TouchEvent) => {\n e.preventDefault();\n isPressed.current = false;\n buttonRef.current?.classList.remove(styles.pressed || '');\n }, []);\n\n const handleMouseDown = useCallback(() => {\n if (disabled) return;\n isPressed.current = true;\n buttonRef.current?.classList.add(styles.pressed || '');\n onTap();\n }, [onTap, disabled]);\n\n const handleMouseUp = useCallback(() => {\n isPressed.current = false;\n buttonRef.current?.classList.remove(styles.pressed || '');\n }, []);\n\n return (\n <button\n ref={buttonRef}\n className={`${styles.tapButton} ${className || ''} ${disabled ? styles.disabled : ''}`}\n onTouchStart={handleTouchStart}\n onTouchEnd={handleTouchEnd}\n onTouchCancel={handleTouchEnd}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n disabled={disabled}\n >\n {children}\n </button>\n );\n}\n\nexport default TapButton;\n"],"names":["useRef","useCallback","styles","jsx"],"mappings":";;;;;;AAqBO,SAAS,SAAA,CAAU;AAAA,EACxB,KAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA,GAAW;AACb,CAAA,EAAmB;AACjB,EAAA,MAAM,SAAA,GAAYA,aAAO,KAAK,CAAA;AAC9B,EAAA,MAAM,SAAA,GAAYA,aAA0B,IAAI,CAAA;AAEhD,EAAA,MAAM,gBAAA,GAAmBC,iBAAA,CAAY,CAAC,CAAA,KAAwB;AAC5D,IAAA,IAAI,QAAA,EAAU;AACd,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AACpB,IAAA,SAAA,CAAU,OAAA,EAAS,SAAA,CAAU,GAAA,CAAIC,wBAAA,CAAO,OAAa,CAAA;AAGrD,IAAA,IAAI,UAAU,OAAA,EAAS;AACrB,MAAA,SAAA,CAAU,QAAQ,EAAE,CAAA;AAAA,IACtB;AAEA,IAAA,KAAA,EAAM;AAAA,EACR,CAAA,EAAG,CAAC,KAAA,EAAO,QAAQ,CAAC,CAAA;AAEpB,EAAA,MAAM,cAAA,GAAiBD,iBAAA,CAAY,CAAC,CAAA,KAAwB;AAC1D,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,SAAA,CAAU,OAAA,GAAU,KAAA;AACpB,IAAA,SAAA,CAAU,OAAA,EAAS,SAAA,CAAU,MAAA,CAAOC,wBAAA,CAAO,OAAa,CAAA;AAAA,EAC1D,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,eAAA,GAAkBD,kBAAY,MAAM;AACxC,IAAA,IAAI,QAAA,EAAU;AACd,IAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AACpB,IAAA,SAAA,CAAU,OAAA,EAAS,SAAA,CAAU,GAAA,CAAIC,wBAAA,CAAO,OAAa,CAAA;AACrD,IAAA,KAAA,EAAM;AAAA,EACR,CAAA,EAAG,CAAC,KAAA,EAAO,QAAQ,CAAC,CAAA;AAEpB,EAAA,MAAM,aAAA,GAAgBD,kBAAY,MAAM;AACtC,IAAA,SAAA,CAAU,OAAA,GAAU,KAAA;AACpB,IAAA,SAAA,CAAU,OAAA,EAAS,SAAA,CAAU,MAAA,CAAOC,wBAAA,CAAO,OAAa,CAAA;AAAA,EAC1D,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,uBACEC,cAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,SAAA;AAAA,MACL,SAAA,EAAW,CAAA,EAAGD,wBAAA,CAAO,SAAS,CAAA,CAAA,EAAI,SAAA,IAAa,EAAE,CAAA,CAAA,EAAI,QAAA,GAAWA,wBAAA,CAAO,QAAA,GAAW,EAAE,CAAA,CAAA;AAAA,MACpF,YAAA,EAAc,gBAAA;AAAA,MACd,UAAA,EAAY,cAAA;AAAA,MACZ,aAAA,EAAe,cAAA;AAAA,MACf,WAAA,EAAa,eAAA;AAAA,MACb,SAAA,EAAW,aAAA;AAAA,MACX,YAAA,EAAc,aAAA;AAAA,MACd,QAAA;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;;;;"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var styleInject_es = require('../node_modules/.pnpm/style-inject@0.3.0/node_modules/style-inject/dist/style-inject.es.cjs');
|
|
6
|
+
|
|
7
|
+
var css_248z = ".TapButton-module_tapButton__dqJr9{-webkit-tap-highlight-color:transparent;align-items:center;background:var(--color-primary,#6366f1);border:none;border-radius:16px;color:#fff;cursor:pointer;display:flex;font-size:18px;font-weight:700;justify-content:center;min-height:80px;min-width:80px;padding:16px 24px;touch-action:manipulation;transition:transform .1s ease,background .1s ease;user-select:none;-webkit-user-select:none}.TapButton-module_pressed__Z2nfR,.TapButton-module_tapButton__dqJr9:active{background:var(--color-primary-dark,#4f46e5);transform:scale(.95)}.TapButton-module_disabled__3bR6q{cursor:not-allowed;opacity:.5}.TapButton-module_disabled__3bR6q.TapButton-module_pressed__Z2nfR,.TapButton-module_disabled__3bR6q:active{background:var(--color-primary,#6366f1);transform:none}";
|
|
8
|
+
var styles = {"tapButton":"TapButton-module_tapButton__dqJr9","pressed":"TapButton-module_pressed__Z2nfR","disabled":"TapButton-module_disabled__3bR6q"};
|
|
9
|
+
styleInject_es.default(css_248z);
|
|
10
|
+
|
|
11
|
+
exports.default = styles;
|
|
12
|
+
//# sourceMappingURL=TapButton.module.css.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TapButton.module.css.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var DirectTransport = require('../transport/DirectTransport.cjs');
|
|
6
|
+
|
|
7
|
+
const TransportContext = react.createContext(null);
|
|
8
|
+
function useTransport() {
|
|
9
|
+
const transport = react.useContext(TransportContext);
|
|
10
|
+
if (!transport) {
|
|
11
|
+
throw new Error("useTransport must be used within a RoomProvider that supplies a Transport");
|
|
12
|
+
}
|
|
13
|
+
return transport;
|
|
14
|
+
}
|
|
15
|
+
const RoomContext = react.createContext(null);
|
|
16
|
+
const HostRoomProvider = ({
|
|
17
|
+
roomCode,
|
|
18
|
+
players,
|
|
19
|
+
leaderId,
|
|
20
|
+
socket,
|
|
21
|
+
children
|
|
22
|
+
}) => {
|
|
23
|
+
const connectedPlayers = react.useMemo(
|
|
24
|
+
() => players.filter((p) => p.connected !== false),
|
|
25
|
+
[players]
|
|
26
|
+
);
|
|
27
|
+
const hostState = react.useMemo(
|
|
28
|
+
() => ({ roomCode, players, connectedPlayers, leaderId, socket }),
|
|
29
|
+
[roomCode, players, connectedPlayers, leaderId, socket]
|
|
30
|
+
);
|
|
31
|
+
const value = react.useMemo(
|
|
32
|
+
() => ({
|
|
33
|
+
roomCode,
|
|
34
|
+
players,
|
|
35
|
+
connectedPlayers,
|
|
36
|
+
leaderId,
|
|
37
|
+
side: "host",
|
|
38
|
+
host: hostState,
|
|
39
|
+
player: null
|
|
40
|
+
}),
|
|
41
|
+
[roomCode, players, connectedPlayers, leaderId, hostState]
|
|
42
|
+
);
|
|
43
|
+
const transport = react.useMemo(() => new DirectTransport.DirectTransport(socket), [socket]);
|
|
44
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TransportContext.Provider, { value: transport, children: /* @__PURE__ */ jsxRuntime.jsx(RoomContext.Provider, { value, children }) });
|
|
45
|
+
};
|
|
46
|
+
const PlayerRoomProvider = ({
|
|
47
|
+
roomCode,
|
|
48
|
+
players,
|
|
49
|
+
leaderId,
|
|
50
|
+
mySessionId,
|
|
51
|
+
isLeader,
|
|
52
|
+
socket,
|
|
53
|
+
isConnected,
|
|
54
|
+
children
|
|
55
|
+
}) => {
|
|
56
|
+
const connectedPlayers = react.useMemo(
|
|
57
|
+
() => players.filter((p) => p.connected !== false),
|
|
58
|
+
[players]
|
|
59
|
+
);
|
|
60
|
+
const playerState = react.useMemo(
|
|
61
|
+
() => ({
|
|
62
|
+
roomCode,
|
|
63
|
+
players,
|
|
64
|
+
connectedPlayers,
|
|
65
|
+
leaderId,
|
|
66
|
+
mySessionId,
|
|
67
|
+
isLeader,
|
|
68
|
+
socket,
|
|
69
|
+
isConnected
|
|
70
|
+
}),
|
|
71
|
+
[roomCode, players, connectedPlayers, leaderId, mySessionId, isLeader, socket, isConnected]
|
|
72
|
+
);
|
|
73
|
+
const value = react.useMemo(
|
|
74
|
+
() => ({
|
|
75
|
+
roomCode,
|
|
76
|
+
players,
|
|
77
|
+
connectedPlayers,
|
|
78
|
+
leaderId,
|
|
79
|
+
side: "player",
|
|
80
|
+
host: null,
|
|
81
|
+
player: playerState
|
|
82
|
+
}),
|
|
83
|
+
[roomCode, players, connectedPlayers, leaderId, playerState]
|
|
84
|
+
);
|
|
85
|
+
const transport = react.useMemo(() => new DirectTransport.DirectTransport(socket), [socket]);
|
|
86
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TransportContext.Provider, { value: transport, children: /* @__PURE__ */ jsxRuntime.jsx(RoomContext.Provider, { value, children }) });
|
|
87
|
+
};
|
|
88
|
+
function useRoom() {
|
|
89
|
+
const context = react.useContext(RoomContext);
|
|
90
|
+
if (!context) {
|
|
91
|
+
throw new Error("useRoom must be used within HostRoomProvider or PlayerRoomProvider");
|
|
92
|
+
}
|
|
93
|
+
return context;
|
|
94
|
+
}
|
|
95
|
+
function useHostRoom() {
|
|
96
|
+
const context = useRoom();
|
|
97
|
+
if (context.side !== "host" || !context.host) {
|
|
98
|
+
throw new Error("useHostRoom must be used within HostRoomProvider");
|
|
99
|
+
}
|
|
100
|
+
return context.host;
|
|
101
|
+
}
|
|
102
|
+
function usePlayerRoom() {
|
|
103
|
+
const context = useRoom();
|
|
104
|
+
if (context.side !== "player" || !context.player) {
|
|
105
|
+
throw new Error("usePlayerRoom must be used within PlayerRoomProvider");
|
|
106
|
+
}
|
|
107
|
+
return context.player;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
exports.HostRoomProvider = HostRoomProvider;
|
|
111
|
+
exports.PlayerRoomProvider = PlayerRoomProvider;
|
|
112
|
+
exports.RoomContext = RoomContext;
|
|
113
|
+
exports.TransportContext = TransportContext;
|
|
114
|
+
exports.useHostRoom = useHostRoom;
|
|
115
|
+
exports.usePlayerRoom = usePlayerRoom;
|
|
116
|
+
exports.useRoom = useRoom;
|
|
117
|
+
exports.useTransport = useTransport;
|
|
118
|
+
//# sourceMappingURL=RoomProvider.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RoomProvider.cjs","sources":["../../../src/context/RoomProvider.tsx"],"sourcesContent":["/**\n * RoomProvider - SDK Room Context\n *\n * Foundation context that all other SDK hooks depend on.\n * Provides room state (players, roomCode, leaderId) for both host and player sides.\n *\n * Also provides a Transport abstraction via TransportContext.\n * - HostRoomProvider / PlayerRoomProvider create a DirectTransport from the socket.\n * - IframeRoomProvider (external) provides a PostMessageTransport.\n *\n * Usage:\n * - Host: <HostRoomProvider roomCode={...} players={...} leaderId={...} socket={...}>\n * - Player: <PlayerRoomProvider roomCode={...} players={...} leaderId={...} mySessionId={...} isLeader={...} socket={...} isConnected={...}>\n */\n\nimport React, { createContext, useContext, useMemo } from 'react';\nimport type { Player } from '@smore/shared';\nimport type { Socket } from 'socket.io-client';\nimport type { Transport } from '../transport/types';\nimport { DirectTransport } from '../transport/DirectTransport';\n\n// ===== Transport Context =====\n\nconst TransportContext = createContext<Transport | null>(null);\n\nexport function useTransport(): Transport {\n const transport = useContext(TransportContext);\n if (!transport) {\n throw new Error('useTransport must be used within a RoomProvider that supplies a Transport');\n }\n return transport;\n}\n\nexport { TransportContext };\n\n// ===== State Types =====\n\nexport interface RoomState {\n roomCode: string;\n players: Player[];\n connectedPlayers: Player[];\n leaderId: string | null;\n}\n\nexport interface HostRoomState extends RoomState {\n socket: Socket;\n}\n\nexport interface PlayerRoomState extends RoomState {\n mySessionId: string;\n isLeader: boolean;\n socket: Socket;\n isConnected: boolean;\n}\n\nexport interface RoomContextValue {\n roomCode: string;\n players: Player[];\n connectedPlayers: Player[];\n leaderId: string | null;\n side: 'host' | 'player';\n host: HostRoomState | null;\n player: PlayerRoomState | null;\n}\n\n// ===== Context =====\n\nexport const RoomContext = createContext<RoomContextValue | null>(null);\n\n// ===== Host Provider =====\n\ninterface HostRoomProviderProps {\n roomCode: string;\n players: Player[];\n leaderId: string | null;\n socket: Socket;\n children: React.ReactNode;\n}\n\nexport const HostRoomProvider: React.FC<HostRoomProviderProps> = ({\n roomCode,\n players,\n leaderId,\n socket,\n children,\n}) => {\n const connectedPlayers = useMemo(\n () => players.filter((p) => p.connected !== false),\n [players]\n );\n\n const hostState: HostRoomState = useMemo(\n () => ({ roomCode, players, connectedPlayers, leaderId, socket }),\n [roomCode, players, connectedPlayers, leaderId, socket]\n );\n\n const value: RoomContextValue = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n side: 'host' as const,\n host: hostState,\n player: null,\n }),\n [roomCode, players, connectedPlayers, leaderId, hostState]\n );\n\n const transport = useMemo(() => new DirectTransport(socket), [socket]);\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={value}>{children}</RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n\n// ===== Player Provider =====\n\ninterface PlayerRoomProviderProps {\n roomCode: string;\n players: Player[];\n leaderId: string | null;\n mySessionId: string;\n isLeader: boolean;\n socket: Socket;\n isConnected: boolean;\n children: React.ReactNode;\n}\n\nexport const PlayerRoomProvider: React.FC<PlayerRoomProviderProps> = ({\n roomCode,\n players,\n leaderId,\n mySessionId,\n isLeader,\n socket,\n isConnected,\n children,\n}) => {\n const connectedPlayers = useMemo(\n () => players.filter((p) => p.connected !== false),\n [players]\n );\n\n const playerState: PlayerRoomState = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n mySessionId,\n isLeader,\n socket,\n isConnected,\n }),\n [roomCode, players, connectedPlayers, leaderId, mySessionId, isLeader, socket, isConnected]\n );\n\n const value: RoomContextValue = useMemo(\n () => ({\n roomCode,\n players,\n connectedPlayers,\n leaderId,\n side: 'player' as const,\n host: null,\n player: playerState,\n }),\n [roomCode, players, connectedPlayers, leaderId, playerState]\n );\n\n const transport = useMemo(() => new DirectTransport(socket), [socket]);\n\n return (\n <TransportContext.Provider value={transport}>\n <RoomContext.Provider value={value}>{children}</RoomContext.Provider>\n </TransportContext.Provider>\n );\n};\n\n// ===== Hooks =====\n\nexport function useRoom(): RoomContextValue {\n const context = useContext(RoomContext);\n if (!context) {\n throw new Error('useRoom must be used within HostRoomProvider or PlayerRoomProvider');\n }\n return context;\n}\n\nexport function useHostRoom(): HostRoomState {\n const context = useRoom();\n if (context.side !== 'host' || !context.host) {\n throw new Error('useHostRoom must be used within HostRoomProvider');\n }\n return context.host;\n}\n\nexport function usePlayerRoom(): PlayerRoomState {\n const context = useRoom();\n if (context.side !== 'player' || !context.player) {\n throw new Error('usePlayerRoom must be used within PlayerRoomProvider');\n }\n return context.player;\n}\n"],"names":["createContext","useContext","useMemo","DirectTransport","jsx"],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
|
|
5
|
+
function useExternalGames(config) {
|
|
6
|
+
const { serverUrl, enabled = true } = config;
|
|
7
|
+
const [games, setGames] = react.useState([]);
|
|
8
|
+
const [loading, setLoading] = react.useState(false);
|
|
9
|
+
const [error, setError] = react.useState(null);
|
|
10
|
+
const [refreshKey, setRefreshKey] = react.useState(0);
|
|
11
|
+
react.useEffect(() => {
|
|
12
|
+
if (!enabled) return;
|
|
13
|
+
let cancelled = false;
|
|
14
|
+
setLoading(true);
|
|
15
|
+
fetch(`${serverUrl}/api/games`).then((res) => res.json()).then((data) => {
|
|
16
|
+
if (cancelled) return;
|
|
17
|
+
const external = (data.games || []).map((g) => ({
|
|
18
|
+
id: g.id,
|
|
19
|
+
title: g.title,
|
|
20
|
+
description: g.description || "",
|
|
21
|
+
minPlayers: g.minPlayers || 2,
|
|
22
|
+
maxPlayers: g.maxPlayers || 8,
|
|
23
|
+
thumbnail: g.thumbnail || "/thumbnails/g8.jpeg",
|
|
24
|
+
categories: g.categories || ["party"],
|
|
25
|
+
type: "external",
|
|
26
|
+
hostUrl: g.hostUrl,
|
|
27
|
+
playerUrl: g.playerUrl,
|
|
28
|
+
available: !!(g.hostUrl && g.playerUrl),
|
|
29
|
+
rating: 4,
|
|
30
|
+
heroRequired: false
|
|
31
|
+
}));
|
|
32
|
+
setGames(external);
|
|
33
|
+
setError(null);
|
|
34
|
+
}).catch((err) => {
|
|
35
|
+
if (cancelled) return;
|
|
36
|
+
setError(err.message);
|
|
37
|
+
}).finally(() => {
|
|
38
|
+
if (!cancelled) setLoading(false);
|
|
39
|
+
});
|
|
40
|
+
return () => {
|
|
41
|
+
cancelled = true;
|
|
42
|
+
};
|
|
43
|
+
}, [serverUrl, enabled, refreshKey]);
|
|
44
|
+
const refresh = () => setRefreshKey((k) => k + 1);
|
|
45
|
+
return { games, loading, error, refresh };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
exports.useExternalGames = useExternalGames;
|
|
49
|
+
//# sourceMappingURL=useExternalGames.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useExternalGames.cjs","sources":["../../../src/hooks/useExternalGames.ts"],"sourcesContent":["/**\n * useExternalGames - Fetches external games from the server API.\n *\n * Returns a list of GameMetadata-compatible objects for external (iframe) games.\n * Consumers merge this with their local GAMES array.\n */\n\nimport { useState, useEffect } from 'react';\n\nexport interface ExternalGameMetadata {\n id: string;\n title: string;\n description: string;\n minPlayers: number;\n maxPlayers: number;\n thumbnail: string;\n categories: string[];\n type: 'external';\n hostUrl: string | null;\n playerUrl: string | null;\n available: boolean;\n rating: number;\n heroRequired: boolean;\n}\n\nexport interface UseExternalGamesConfig {\n serverUrl: string;\n enabled?: boolean;\n}\n\nexport function useExternalGames(config: UseExternalGamesConfig): {\n games: ExternalGameMetadata[];\n loading: boolean;\n error: string | null;\n refresh: () => void;\n} {\n const { serverUrl, enabled = true } = config;\n const [games, setGames] = useState<ExternalGameMetadata[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [refreshKey, setRefreshKey] = useState(0);\n\n useEffect(() => {\n if (!enabled) return;\n\n let cancelled = false;\n setLoading(true);\n\n fetch(`${serverUrl}/api/games`)\n .then((res) => res.json())\n .then((data) => {\n if (cancelled) return;\n const external: ExternalGameMetadata[] = (data.games || []).map((g: any) => ({\n id: g.id,\n title: g.title,\n description: g.description || '',\n minPlayers: g.minPlayers || 2,\n maxPlayers: g.maxPlayers || 8,\n thumbnail: g.thumbnail || '/thumbnails/g8.jpeg',\n categories: g.categories || ['party'],\n type: 'external' as const,\n hostUrl: g.hostUrl,\n playerUrl: g.playerUrl,\n available: !!(g.hostUrl && g.playerUrl),\n rating: 4.0,\n heroRequired: false,\n }));\n setGames(external);\n setError(null);\n })\n .catch((err) => {\n if (cancelled) return;\n setError(err.message);\n })\n .finally(() => {\n if (!cancelled) setLoading(false);\n });\n\n return () => { cancelled = true; };\n }, [serverUrl, enabled, refreshKey]);\n\n const refresh = () => setRefreshKey((k) => k + 1);\n\n return { games, loading, error, refresh };\n}\n"],"names":["useState","useEffect"],"mappings":";;;;AA8BO,SAAS,iBAAiB,MAAA,EAK/B;AACA,EAAA,MAAM,EAAE,SAAA,EAAW,OAAA,GAAU,IAAA,EAAK,GAAI,MAAA;AACtC,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,cAAA,CAAiC,EAAE,CAAA;AAC7D,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,eAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAwB,IAAI,CAAA;AACtD,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAIA,eAAS,CAAC,CAAA;AAE9C,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,EAAS;AAEd,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,UAAA,CAAW,IAAI,CAAA;AAEf,IAAA,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA,UAAA,CAAY,CAAA,CAC3B,IAAA,CAAK,CAAC,GAAA,KAAQ,GAAA,CAAI,IAAA,EAAM,CAAA,CACxB,IAAA,CAAK,CAAC,IAAA,KAAS;AACd,MAAA,IAAI,SAAA,EAAW;AACf,MAAA,MAAM,YAAoC,IAAA,CAAK,KAAA,IAAS,EAAC,EAAG,GAAA,CAAI,CAAC,CAAA,MAAY;AAAA,QAC3E,IAAI,CAAA,CAAE,EAAA;AAAA,QACN,OAAO,CAAA,CAAE,KAAA;AAAA,QACT,WAAA,EAAa,EAAE,WAAA,IAAe,EAAA;AAAA,QAC9B,UAAA,EAAY,EAAE,UAAA,IAAc,CAAA;AAAA,QAC5B,UAAA,EAAY,EAAE,UAAA,IAAc,CAAA;AAAA,QAC5B,SAAA,EAAW,EAAE,SAAA,IAAa,qBAAA;AAAA,QAC1B,UAAA,EAAY,CAAA,CAAE,UAAA,IAAc,CAAC,OAAO,CAAA;AAAA,QACpC,IAAA,EAAM,UAAA;AAAA,QACN,SAAS,CAAA,CAAE,OAAA;AAAA,QACX,WAAW,CAAA,CAAE,SAAA;AAAA,QACb,SAAA,EAAW,CAAC,EAAE,CAAA,CAAE,WAAW,CAAA,CAAE,SAAA,CAAA;AAAA,QAC7B,MAAA,EAAQ,CAAA;AAAA,QACR,YAAA,EAAc;AAAA,OAChB,CAAE,CAAA;AACF,MAAA,QAAA,CAAS,QAAQ,CAAA;AACjB,MAAA,QAAA,CAAS,IAAI,CAAA;AAAA,IACf,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,GAAA,KAAQ;AACd,MAAA,IAAI,SAAA,EAAW;AACf,MAAA,QAAA,CAAS,IAAI,OAAO,CAAA;AAAA,IACtB,CAAC,CAAA,CACA,OAAA,CAAQ,MAAM;AACb,MAAA,IAAI,CAAC,SAAA,EAAW,UAAA,CAAW,KAAK,CAAA;AAAA,IAClC,CAAC,CAAA;AAEH,IAAA,OAAO,MAAM;AAAE,MAAA,SAAA,GAAY,IAAA;AAAA,IAAM,CAAA;AAAA,EACnC,CAAA,EAAG,CAAC,SAAA,EAAW,OAAA,EAAS,UAAU,CAAC,CAAA;AAEnC,EAAA,MAAM,UAAU,MAAM,aAAA,CAAc,CAAC,CAAA,KAAM,IAAI,CAAC,CAAA;AAEhD,EAAA,OAAO,EAAE,KAAA,EAAO,OAAA,EAAS,KAAA,EAAO,OAAA,EAAQ;AAC1C;;;;"}
|