@xrift/world-components 0.20.0 → 0.21.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/components/LiveVideoPlayer/index.d.ts +1 -1
- package/dist/components/LiveVideoPlayer/index.d.ts.map +1 -1
- package/dist/components/LiveVideoPlayer/index.js +52 -24
- package/dist/components/LiveVideoPlayer/index.js.map +1 -1
- package/dist/components/TagBoard/components/TagChip.d.ts +12 -0
- package/dist/components/TagBoard/components/TagChip.d.ts.map +1 -0
- package/dist/components/TagBoard/components/TagChip.js +13 -0
- package/dist/components/TagBoard/components/TagChip.js.map +1 -0
- package/dist/components/TagBoard/components/TagDisplay/index.d.ts +3 -0
- package/dist/components/TagBoard/components/TagDisplay/index.d.ts.map +1 -0
- package/dist/components/TagBoard/components/TagDisplay/index.js +64 -0
- package/dist/components/TagBoard/components/TagDisplay/index.js.map +1 -0
- package/dist/components/TagBoard/components/TagDisplay/utils.d.ts +23 -0
- package/dist/components/TagBoard/components/TagDisplay/utils.d.ts.map +1 -0
- package/dist/components/TagBoard/components/TagDisplay/utils.js +53 -0
- package/dist/components/TagBoard/components/TagDisplay/utils.js.map +1 -0
- package/dist/components/TagBoard/components/TagSelector/components/ActionButton.d.ts +13 -0
- package/dist/components/TagBoard/components/TagSelector/components/ActionButton.d.ts.map +1 -0
- package/dist/components/TagBoard/components/TagSelector/components/ActionButton.js +12 -0
- package/dist/components/TagBoard/components/TagSelector/components/ActionButton.js.map +1 -0
- package/dist/components/TagBoard/components/TagSelector/components/TagButton.d.ts +12 -0
- package/dist/components/TagBoard/components/TagSelector/components/TagButton.d.ts.map +1 -0
- package/dist/components/TagBoard/components/TagSelector/components/TagButton.js +13 -0
- package/dist/components/TagBoard/components/TagSelector/components/TagButton.js.map +1 -0
- package/dist/components/TagBoard/components/TagSelector/index.d.ts +3 -0
- package/dist/components/TagBoard/components/TagSelector/index.d.ts.map +1 -0
- package/dist/components/TagBoard/components/TagSelector/index.js +57 -0
- package/dist/components/TagBoard/components/TagSelector/index.js.map +1 -0
- package/dist/components/TagBoard/components/TagSelector/utils.d.ts +21 -0
- package/dist/components/TagBoard/components/TagSelector/utils.d.ts.map +1 -0
- package/dist/components/TagBoard/components/TagSelector/utils.js +50 -0
- package/dist/components/TagBoard/components/TagSelector/utils.js.map +1 -0
- package/dist/components/TagBoard/constants.d.ts +8 -0
- package/dist/components/TagBoard/constants.d.ts.map +1 -0
- package/dist/components/TagBoard/constants.js +15 -0
- package/dist/components/TagBoard/constants.js.map +1 -0
- package/dist/components/TagBoard/index.d.ts +4 -0
- package/dist/components/TagBoard/index.d.ts.map +1 -0
- package/dist/components/TagBoard/index.js +25 -0
- package/dist/components/TagBoard/index.js.map +1 -0
- package/dist/components/TagBoard/types.d.ts +46 -0
- package/dist/components/TagBoard/types.d.ts.map +1 -0
- package/dist/components/TagBoard/types.js.map +1 -0
- package/dist/components/TagBoard/utils.d.ts +7 -0
- package/dist/components/TagBoard/utils.d.ts.map +1 -0
- package/dist/components/TagBoard/utils.js +20 -0
- package/dist/components/TagBoard/utils.js.map +1 -0
- package/dist/components/VideoPlayer/index.d.ts +1 -1
- package/dist/components/VideoPlayer/index.d.ts.map +1 -1
- package/dist/components/VideoPlayer/index.js +64 -31
- package/dist/components/VideoPlayer/index.js.map +1 -1
- package/dist/hooks/useInstanceState.d.ts.map +1 -1
- package/dist/hooks/useInstanceState.js +3 -3
- package/dist/hooks/useInstanceState.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/components/RichVideoPlayer/ControlPanel.d.ts +0 -3
- package/dist/components/RichVideoPlayer/ControlPanel.d.ts.map +0 -1
- package/dist/components/RichVideoPlayer/ControlPanel.js +0 -22
- package/dist/components/RichVideoPlayer/ControlPanel.js.map +0 -1
- package/dist/components/RichVideoPlayer/PlayPauseButton.d.ts +0 -3
- package/dist/components/RichVideoPlayer/PlayPauseButton.d.ts.map +0 -1
- package/dist/components/RichVideoPlayer/PlayPauseButton.js +0 -9
- package/dist/components/RichVideoPlayer/PlayPauseButton.js.map +0 -1
- package/dist/components/RichVideoPlayer/ProgressBar.d.ts +0 -3
- package/dist/components/RichVideoPlayer/ProgressBar.d.ts.map +0 -1
- package/dist/components/RichVideoPlayer/ProgressBar.js +0 -20
- package/dist/components/RichVideoPlayer/ProgressBar.js.map +0 -1
- package/dist/components/RichVideoPlayer/UrlInputButton.d.ts +0 -3
- package/dist/components/RichVideoPlayer/UrlInputButton.d.ts.map +0 -1
- package/dist/components/RichVideoPlayer/UrlInputButton.js +0 -23
- package/dist/components/RichVideoPlayer/UrlInputButton.js.map +0 -1
- package/dist/components/RichVideoPlayer/VolumeControl.d.ts +0 -3
- package/dist/components/RichVideoPlayer/VolumeControl.d.ts.map +0 -1
- package/dist/components/RichVideoPlayer/VolumeControl.js +0 -26
- package/dist/components/RichVideoPlayer/VolumeControl.js.map +0 -1
- package/dist/components/RichVideoPlayer/hooks.d.ts +0 -5
- package/dist/components/RichVideoPlayer/hooks.d.ts.map +0 -1
- package/dist/components/RichVideoPlayer/hooks.js +0 -9
- package/dist/components/RichVideoPlayer/hooks.js.map +0 -1
- package/dist/components/RichVideoPlayer/index.d.ts +0 -4
- package/dist/components/RichVideoPlayer/index.d.ts.map +0 -1
- package/dist/components/RichVideoPlayer/index.js +0 -100
- package/dist/components/RichVideoPlayer/index.js.map +0 -1
- package/dist/components/RichVideoPlayer/types.d.ts +0 -64
- package/dist/components/RichVideoPlayer/types.d.ts.map +0 -1
- package/dist/components/RichVideoPlayer/types.js.map +0 -1
- package/dist/components/RichVideoPlayer/utils.d.ts +0 -32
- package/dist/components/RichVideoPlayer/utils.d.ts.map +0 -1
- package/dist/components/RichVideoPlayer/utils.js +0 -37
- package/dist/components/RichVideoPlayer/utils.js.map +0 -1
- package/dist/components/RichVideoPlayer/utils.test.d.ts +0 -2
- package/dist/components/RichVideoPlayer/utils.test.d.ts.map +0 -1
- package/dist/components/RichVideoPlayer/utils.test.js +0 -109
- package/dist/components/RichVideoPlayer/utils.test.js.map +0 -1
- package/dist/hooks/useVideoScreenControls.d.ts +0 -57
- package/dist/hooks/useVideoScreenControls.d.ts.map +0 -1
- package/dist/hooks/useVideoScreenControls.js +0 -130
- package/dist/hooks/useVideoScreenControls.js.map +0 -1
- package/dist/scenes/SpawnPointTestScene.d.ts +0 -6
- package/dist/scenes/SpawnPointTestScene.d.ts.map +0 -1
- package/dist/scenes/SpawnPointTestScene.js +0 -12
- package/dist/scenes/SpawnPointTestScene.js.map +0 -1
- package/dist/scenes/TestScene.d.ts +0 -6
- package/dist/scenes/TestScene.d.ts.map +0 -1
- package/dist/scenes/TestScene.js +0 -19
- package/dist/scenes/TestScene.js.map +0 -1
- package/dist/scenes/TheaterScene.d.ts +0 -6
- package/dist/scenes/TheaterScene.d.ts.map +0 -1
- package/dist/scenes/TheaterScene.js +0 -12
- package/dist/scenes/TheaterScene.js.map +0 -1
- package/dist/scenes/VideoControlTest.d.ts +0 -5
- package/dist/scenes/VideoControlTest.d.ts.map +0 -1
- package/dist/scenes/VideoControlTest.js +0 -17
- package/dist/scenes/VideoControlTest.js.map +0 -1
- /package/dist/components/{RichVideoPlayer → TagBoard}/types.js +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { LiveVideoPlayerProps } from './types';
|
|
2
2
|
export type { LiveVideoPlayerProps } from './types';
|
|
3
|
-
export declare const LiveVideoPlayer: import("react").MemoExoticComponent<({ id, position, rotation, width, url: initialUrl,
|
|
3
|
+
export declare const LiveVideoPlayer: import("react").MemoExoticComponent<({ id, position, rotation, width, url: initialUrl, playing: initialPlaying, volume: initialVolume, onError, }: LiveVideoPlayerProps) => import("react/jsx-runtime").JSX.Element>;
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/LiveVideoPlayer/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEnD,YAAY,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/LiveVideoPlayer/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEnD,YAAY,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAwJnD,eAAO,MAAM,eAAe,qJAUvB,oBAAoB,6CAyFxB,CAAA"}
|
|
@@ -1,15 +1,31 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { memo, Suspense, useState, useCallback, useEffect, useRef } from 'react';
|
|
3
|
-
import { useVideoTexture } from '@react-three/drei';
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { memo, Suspense, useState, useCallback, useEffect, useRef, Component } from 'react';
|
|
3
|
+
import { useVideoTexture, Text } from '@react-three/drei';
|
|
4
4
|
import { ControlPanel } from './ControlPanel';
|
|
5
5
|
const DEFAULT_POSITION = [0, 2, -5];
|
|
6
6
|
const DEFAULT_ROTATION = [0, 0, 0];
|
|
7
7
|
const DEFAULT_WIDTH = 4;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
class VideoErrorBoundary extends Component {
|
|
9
|
+
constructor(props) {
|
|
10
|
+
super(props);
|
|
11
|
+
this.state = { hasError: false };
|
|
12
|
+
}
|
|
13
|
+
static getDerivedStateFromError() {
|
|
14
|
+
return { hasError: true };
|
|
15
|
+
}
|
|
16
|
+
componentDidCatch(error) {
|
|
17
|
+
console.error('Video load error:', error);
|
|
18
|
+
this.props.onError?.(error);
|
|
19
|
+
}
|
|
20
|
+
render() {
|
|
21
|
+
if (this.state.hasError) {
|
|
22
|
+
return this.props.fallback;
|
|
23
|
+
}
|
|
24
|
+
return this.props.children;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** 動画テクスチャを表示するコンポーネント(Suspense内で使用) */
|
|
28
|
+
const VideoTexture = memo(({ url, width, screenHeight, playing, volume, onError, onBufferingChange, }) => {
|
|
13
29
|
const texture = useVideoTexture(url, {
|
|
14
30
|
muted: false,
|
|
15
31
|
loop: false,
|
|
@@ -43,9 +59,9 @@ const LiveVideoPlayerInner = memo(({ id, position = DEFAULT_POSITION, rotation =
|
|
|
43
59
|
const video = videoRef.current;
|
|
44
60
|
if (!video)
|
|
45
61
|
return;
|
|
46
|
-
const handleWaiting = () =>
|
|
47
|
-
const handlePlaying = () =>
|
|
48
|
-
const handleCanPlay = () =>
|
|
62
|
+
const handleWaiting = () => onBufferingChange(true);
|
|
63
|
+
const handlePlaying = () => onBufferingChange(false);
|
|
64
|
+
const handleCanPlay = () => onBufferingChange(false);
|
|
49
65
|
const handleError = (e) => {
|
|
50
66
|
const error = e.target.error;
|
|
51
67
|
if (error) {
|
|
@@ -63,7 +79,7 @@ const LiveVideoPlayerInner = memo(({ id, position = DEFAULT_POSITION, rotation =
|
|
|
63
79
|
video.removeEventListener('canplay', handleCanPlay);
|
|
64
80
|
video.removeEventListener('error', handleError);
|
|
65
81
|
};
|
|
66
|
-
}, [texture, onError]);
|
|
82
|
+
}, [texture, onError, onBufferingChange]);
|
|
67
83
|
useEffect(() => {
|
|
68
84
|
const video = texture.image;
|
|
69
85
|
return () => {
|
|
@@ -72,25 +88,37 @@ const LiveVideoPlayerInner = memo(({ id, position = DEFAULT_POSITION, rotation =
|
|
|
72
88
|
video.load();
|
|
73
89
|
};
|
|
74
90
|
}, [texture]);
|
|
91
|
+
return (_jsxs("mesh", { children: [_jsx("planeGeometry", { args: [width, screenHeight] }), _jsx("meshBasicMaterial", { map: texture, toneMapped: false })] }));
|
|
92
|
+
});
|
|
93
|
+
VideoTexture.displayName = 'VideoTexture';
|
|
94
|
+
/** プレースホルダー画面(読み込み中/エラー時/URL未設定時) */
|
|
95
|
+
const PlaceholderScreen = memo(({ width, screenHeight, color }) => (_jsxs("mesh", { children: [_jsx("planeGeometry", { args: [width, screenHeight] }), _jsx("meshBasicMaterial", { color: color })] })));
|
|
96
|
+
PlaceholderScreen.displayName = 'PlaceholderScreen';
|
|
97
|
+
export const LiveVideoPlayer = memo(({ id, position = DEFAULT_POSITION, rotation = DEFAULT_ROTATION, width = DEFAULT_WIDTH, url: initialUrl, playing: initialPlaying = true, volume: initialVolume = 1, onError, }) => {
|
|
98
|
+
const [currentUrl, setCurrentUrl] = useState(initialUrl);
|
|
99
|
+
const [playing, setPlaying] = useState(initialPlaying);
|
|
100
|
+
const [volume, setVolume] = useState(initialVolume);
|
|
101
|
+
const [isBuffering, setIsBuffering] = useState(false);
|
|
102
|
+
const [hasError, setHasError] = useState(false);
|
|
103
|
+
const screenHeight = width * (9 / 16);
|
|
104
|
+
const handleUrlChange = useCallback((newUrl) => {
|
|
105
|
+
setCurrentUrl(newUrl);
|
|
106
|
+
setHasError(false);
|
|
107
|
+
}, []);
|
|
75
108
|
const handlePlayPause = useCallback(() => {
|
|
76
109
|
setPlaying((prev) => !prev);
|
|
77
110
|
}, []);
|
|
78
111
|
const handleVolumeChange = useCallback((newVolume) => {
|
|
79
112
|
setVolume(newVolume);
|
|
80
113
|
}, []);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
LiveVideoPlayerInner.displayName = 'LiveVideoPlayerInner';
|
|
84
|
-
export const LiveVideoPlayer = memo(({ id, position = DEFAULT_POSITION, rotation = DEFAULT_ROTATION, width = DEFAULT_WIDTH, url: initialUrl, ...props }) => {
|
|
85
|
-
const [currentUrl, setCurrentUrl] = useState(initialUrl);
|
|
86
|
-
const screenHeight = width * (9 / 16);
|
|
87
|
-
const handleUrlChange = useCallback((newUrl) => {
|
|
88
|
-
setCurrentUrl(newUrl);
|
|
114
|
+
const handleBufferingChange = useCallback((buffering) => {
|
|
115
|
+
setIsBuffering(buffering);
|
|
89
116
|
}, []);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
117
|
+
const handleError = useCallback((error) => {
|
|
118
|
+
setHasError(true);
|
|
119
|
+
onError?.(error);
|
|
120
|
+
}, [onError]);
|
|
121
|
+
return (_jsxs("group", { position: position, rotation: rotation, children: [!currentUrl || hasError ? (_jsxs(_Fragment, { children: [_jsx(PlaceholderScreen, { width: width, screenHeight: screenHeight, color: "#000000" }), !currentUrl && (_jsx(Text, { position: [0, 0, 0.01], fontSize: width * 0.05, color: "#666666", anchorX: "center", anchorY: "middle", children: "URL\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044" }))] })) : (_jsx(VideoErrorBoundary, { fallback: _jsx(PlaceholderScreen, { width: width, screenHeight: screenHeight, color: "#000000" }), onError: handleError, children: _jsx(Suspense, { fallback: _jsx(PlaceholderScreen, { width: width, screenHeight: screenHeight, color: "#333333" }), children: _jsx(VideoTexture, { url: currentUrl, width: width, screenHeight: screenHeight, playing: playing, volume: volume, onError: handleError, onBufferingChange: handleBufferingChange }, currentUrl) }) })), _jsx(ControlPanel, { id: id, width: width, screenHeight: screenHeight, playing: playing, volume: volume, isBuffering: isBuffering, currentUrl: currentUrl || '', onPlayPause: handlePlayPause, onVolumeChange: handleVolumeChange, onUrlChange: handleUrlChange })] }));
|
|
94
122
|
});
|
|
95
123
|
LiveVideoPlayer.displayName = 'LiveVideoPlayer';
|
|
96
124
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/LiveVideoPlayer/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/LiveVideoPlayer/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Tag } from '../types';
|
|
2
|
+
export interface TagChipProps {
|
|
3
|
+
tag: Tag;
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
fontSize: number;
|
|
7
|
+
position?: [number, number, number];
|
|
8
|
+
/** 裏面にもテキストを表示するか */
|
|
9
|
+
doubleSided?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare const TagChip: ({ tag, width, height, fontSize, position, doubleSided, }: TagChipProps) => import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
//# sourceMappingURL=TagChip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TagChip.d.ts","sourceRoot":"","sources":["../../../../src/components/TagBoard/components/TagChip.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,UAAU,CAAA;AAEnC,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,GAAG,CAAA;IACR,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,qBAAqB;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,eAAO,MAAM,OAAO,GAAI,0DAOrB,YAAY,4CAoCd,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* TagChip コンポーネント
|
|
4
|
+
*
|
|
5
|
+
* タグを表示するシンプルなチップUI。
|
|
6
|
+
* 色付きのプレーン + 表裏両面にラベルテキストを表示します。
|
|
7
|
+
*/
|
|
8
|
+
import { Text } from '@react-three/drei';
|
|
9
|
+
import { DoubleSide } from 'three';
|
|
10
|
+
export const TagChip = ({ tag, width, height, fontSize, position, doubleSided = false, }) => {
|
|
11
|
+
return (_jsxs("group", { position: position, children: [_jsxs("mesh", { children: [_jsx("planeGeometry", { args: [width, height] }), _jsx("meshBasicMaterial", { color: tag.color, side: DoubleSide })] }), _jsx(Text, { position: [0, 0, 0.01], fontSize: fontSize, color: 0xffffff, anchorX: "center", anchorY: "middle", outlineWidth: fontSize * 0.04, outlineColor: 0x000000, children: tag.label }), doubleSided && (_jsx(Text, { position: [0, 0, -0.02], fontSize: fontSize, anchorX: "center", anchorY: "middle", color: 0xffffff, outlineWidth: fontSize * 0.04, outlineColor: 0x000000, children: tag.label }))] }));
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=TagChip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TagChip.js","sourceRoot":"","sources":["../../../../src/components/TagBoard/components/TagChip.tsx"],"names":[],"mappings":";AAAA;;;;;GAKG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAclC,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,EACtB,GAAG,EACH,KAAK,EACL,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,WAAW,GAAG,KAAK,GACN,EAAE,EAAE;IACjB,OAAO,CACL,iBAAO,QAAQ,EAAE,QAAQ,aAEvB,2BACE,wBAAe,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,GAAI,EACxC,4BAAmB,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,GAAI,IACpD,EAEP,KAAC,IAAI,IACH,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EACtB,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,QAAQ,EACf,OAAO,EAAC,QAAQ,EAChB,OAAO,EAAC,QAAQ,EAChB,YAAY,EAAE,QAAQ,GAAG,IAAI,EAC7B,YAAY,EAAE,QAAQ,YAErB,GAAG,CAAC,KAAK,GACL,EAEN,WAAW,IAAI,CACd,KAAC,IAAI,IACH,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EACvB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAC,QAAQ,EAChB,OAAO,EAAC,QAAQ,EAChB,KAAK,EAAE,QAAQ,EACf,YAAY,EAAE,QAAQ,GAAG,IAAI,EAC7B,YAAY,EAAE,QAAQ,YAErB,GAAG,CAAC,KAAK,GACL,CACR,IACK,CACT,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/TagBoard/components/TagDisplay/index.tsx"],"names":[],"mappings":"AAoBA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AASnD,eAAO,MAAM,UAAU,GAAI,2DAMxB,eAAe,mDA8FjB,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* TagDisplay コンポーネント
|
|
4
|
+
*
|
|
5
|
+
* 指定ユーザーの頭上に選択済みタグを列ごとに整列して表示します。
|
|
6
|
+
* 位置は `getMovement(userId)` の結果に追従します。
|
|
7
|
+
*
|
|
8
|
+
* Props:
|
|
9
|
+
* - userId: 表示対象ユーザーID
|
|
10
|
+
* - getMovement: ユーザー位置を取得する関数(毎フレーム呼び出し)
|
|
11
|
+
* - tags: 全タグ定義(フィルター前)
|
|
12
|
+
* - visible: 表示/非表示フラグ
|
|
13
|
+
* - instanceStateKey: インスタンス状態キーの識別子
|
|
14
|
+
*/
|
|
15
|
+
import { useMemo, useRef } from "react";
|
|
16
|
+
import { Billboard } from "@react-three/drei";
|
|
17
|
+
import { useFrame } from "@react-three/fiber";
|
|
18
|
+
import { DoubleSide, Vector3 } from "three";
|
|
19
|
+
import { useInstanceState } from "../../../../hooks/useInstanceState";
|
|
20
|
+
import { TagChip } from "../TagChip";
|
|
21
|
+
import { calculateLayout, getSelectedTags, groupTagsByColumn, } from "./utils";
|
|
22
|
+
const HEAD_OFFSET_Y = 1.6;
|
|
23
|
+
export const TagDisplay = ({ userId, getMovement, tags, visible, instanceStateKey, }) => {
|
|
24
|
+
const groupRef = useRef(null);
|
|
25
|
+
const stateKey = `tag-${instanceStateKey}-${userId}`;
|
|
26
|
+
// インスタンス状態から選択済みタグID を取得
|
|
27
|
+
const [selectedTagIds] = useInstanceState(stateKey, []);
|
|
28
|
+
// useMemo
|
|
29
|
+
const flatTags = useMemo(() => tags.flat(), [tags]);
|
|
30
|
+
const selectedTags = useMemo(() => getSelectedTags(selectedTagIds, flatTags), [selectedTagIds, flatTags]);
|
|
31
|
+
const activeColumns = useMemo(() => groupTagsByColumn(selectedTags, tags), [selectedTags, tags]);
|
|
32
|
+
const layout = useMemo(() => calculateLayout(activeColumns), [activeColumns]);
|
|
33
|
+
// useFrame で位置を更新
|
|
34
|
+
useFrame(() => {
|
|
35
|
+
if (!userId || !groupRef.current)
|
|
36
|
+
return;
|
|
37
|
+
const movement = getMovement(userId);
|
|
38
|
+
if (!movement) {
|
|
39
|
+
groupRef.current.visible = false;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// ワールド座標
|
|
43
|
+
const worldPos = new Vector3(movement.position.x, movement.position.y + HEAD_OFFSET_Y, movement.position.z);
|
|
44
|
+
// 親がある場合、ワールド座標をローカル座標に変換
|
|
45
|
+
const parent = groupRef.current.parent;
|
|
46
|
+
if (parent) {
|
|
47
|
+
parent.updateWorldMatrix(true, false);
|
|
48
|
+
parent.worldToLocal(worldPos);
|
|
49
|
+
}
|
|
50
|
+
groupRef.current.position.copy(worldPos);
|
|
51
|
+
groupRef.current.visible = true;
|
|
52
|
+
});
|
|
53
|
+
// タグが無い、または非表示の場合は何も描画しない
|
|
54
|
+
if (selectedTags.length === 0 || !visible)
|
|
55
|
+
return null;
|
|
56
|
+
return (_jsx("group", { ref: groupRef, visible: false, scale: [0.5, 0.5, 0.5], children: _jsx(Billboard, { follow: true, lockX: false, lockY: false, lockZ: false, children: _jsxs("group", { children: [_jsxs("mesh", { position: [0, (-(layout.maxRows - 1) * layout.tagHeight) / 2, -0.02], children: [_jsx("planeGeometry", { args: [layout.totalWidth + 0.1, layout.maxRows * layout.tagHeight + 0.1] }), _jsx("meshBasicMaterial", { color: 0x000000, opacity: 0.6, transparent: true, side: DoubleSide })] }), activeColumns.map(([columnIndex, columnTags], activeColIndex) => {
|
|
57
|
+
const xPos = (activeColIndex - (activeColumns.length - 1) / 2) * layout.columnSpacing;
|
|
58
|
+
return columnTags.map((tag, rowIndex) => {
|
|
59
|
+
const yOffset = -rowIndex * (layout.tagHeight + layout.tagSpacing);
|
|
60
|
+
return (_jsx(TagChip, { tag: tag, width: layout.tagWidth, height: layout.tagHeight, fontSize: 0.08, position: [xPos, yOffset, 0], doubleSided: true }, `${columnIndex}-${tag.id}`));
|
|
61
|
+
});
|
|
62
|
+
})] }) }) }));
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/components/TagBoard/components/TagDisplay/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type Tag } from "../../types";
|
|
2
|
+
export interface TagDisplayLayout {
|
|
3
|
+
tagHeight: number;
|
|
4
|
+
tagWidth: number;
|
|
5
|
+
tagSpacing: number;
|
|
6
|
+
columnSpacing: number;
|
|
7
|
+
maxRows: number;
|
|
8
|
+
totalWidth: number;
|
|
9
|
+
}
|
|
10
|
+
export type ActiveColumn = [number, Tag[]];
|
|
11
|
+
/**
|
|
12
|
+
* 選択されたタグIDから実際のタグオブジェクトを取得
|
|
13
|
+
*/
|
|
14
|
+
export declare const getSelectedTags: (selectedTagIds: string[], flatTags: Tag[]) => Tag[];
|
|
15
|
+
/**
|
|
16
|
+
* 選択済みタグを列ごとにマッピングしてソート
|
|
17
|
+
*/
|
|
18
|
+
export declare const groupTagsByColumn: (selectedTags: Tag[], tags: Tag[][]) => ActiveColumn[];
|
|
19
|
+
/**
|
|
20
|
+
* レイアウト計算
|
|
21
|
+
*/
|
|
22
|
+
export declare const calculateLayout: (activeColumns: ActiveColumn[]) => TagDisplayLayout;
|
|
23
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/components/TagBoard/components/TagDisplay/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,aAAa,CAAC;AAEvC,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,eAAe,GAC1B,gBAAgB,MAAM,EAAE,EACxB,UAAU,GAAG,EAAE,KACd,GAAG,EAKL,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAC5B,cAAc,GAAG,EAAE,EACnB,MAAM,GAAG,EAAE,EAAE,KACZ,YAAY,EAoBd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,eAAe,YAAY,EAAE,KAAG,gBAmB/D,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 選択されたタグIDから実際のタグオブジェクトを取得
|
|
3
|
+
*/
|
|
4
|
+
export const getSelectedTags = (selectedTagIds, flatTags) => {
|
|
5
|
+
const uniqueTagIds = [...new Set(selectedTagIds)];
|
|
6
|
+
return uniqueTagIds
|
|
7
|
+
.map((id) => flatTags.find((tag) => tag.id === id))
|
|
8
|
+
.filter((tag) => tag !== undefined);
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* 選択済みタグを列ごとにマッピングしてソート
|
|
12
|
+
*/
|
|
13
|
+
export const groupTagsByColumn = (selectedTags, tags) => {
|
|
14
|
+
const columnMap = new Map();
|
|
15
|
+
selectedTags.forEach((tag) => {
|
|
16
|
+
let columnIndex = -1;
|
|
17
|
+
for (let i = 0; i < tags.length; i++) {
|
|
18
|
+
if (tags[i].some((t) => t.id === tag.id)) {
|
|
19
|
+
columnIndex = i;
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (columnIndex === -1)
|
|
24
|
+
return;
|
|
25
|
+
if (!columnMap.has(columnIndex)) {
|
|
26
|
+
columnMap.set(columnIndex, []);
|
|
27
|
+
}
|
|
28
|
+
columnMap.get(columnIndex).push(tag);
|
|
29
|
+
});
|
|
30
|
+
return Array.from(columnMap.entries()).sort((a, b) => a[0] - b[0]);
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* レイアウト計算
|
|
34
|
+
*/
|
|
35
|
+
export const calculateLayout = (activeColumns) => {
|
|
36
|
+
const tagHeight = 0.16;
|
|
37
|
+
const tagWidth = 0.8;
|
|
38
|
+
const tagSpacing = 0;
|
|
39
|
+
const columnSpacing = tagWidth;
|
|
40
|
+
const maxRows = activeColumns.length > 0
|
|
41
|
+
? Math.max(...activeColumns.map(([, t]) => t.length))
|
|
42
|
+
: 0;
|
|
43
|
+
const totalWidth = activeColumns.length * tagWidth;
|
|
44
|
+
return {
|
|
45
|
+
tagHeight,
|
|
46
|
+
tagWidth,
|
|
47
|
+
tagSpacing,
|
|
48
|
+
columnSpacing,
|
|
49
|
+
maxRows,
|
|
50
|
+
totalWidth,
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../src/components/TagBoard/components/TagDisplay/utils.ts"],"names":[],"mappings":"AAaA;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,cAAwB,EACxB,QAAe,EACR,EAAE;IACT,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;IAClD,OAAO,YAAY;SAChB,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;SAClD,MAAM,CAAC,CAAC,GAAG,EAAc,EAAE,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,YAAmB,EACnB,IAAa,EACG,EAAE;IAClB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAiB,CAAC;IAE3C,YAAY,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QAC3B,IAAI,WAAW,GAAG,CAAC,CAAC,CAAC;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACzC,WAAW,GAAG,CAAC,CAAC;gBAChB,MAAM;YACR,CAAC;QACH,CAAC;QACD,IAAI,WAAW,KAAK,CAAC,CAAC;YAAE,OAAO;QAE/B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACjC,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,WAAW,CAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,aAA6B,EAAoB,EAAE;IACjF,MAAM,SAAS,GAAG,IAAI,CAAC;IACvB,MAAM,QAAQ,GAAG,GAAG,CAAC;IACrB,MAAM,UAAU,GAAG,CAAC,CAAC;IACrB,MAAM,aAAa,GAAG,QAAQ,CAAC;IAE/B,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC;QACtC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC,CAAC;IACN,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,GAAG,QAAQ,CAAC;IAEnD,OAAO;QACL,SAAS;QACT,QAAQ;QACR,UAAU;QACV,aAAa;QACb,OAAO;QACP,UAAU;KACX,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ActionButtonProps {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
color: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
scale: number;
|
|
8
|
+
position: [number, number, number];
|
|
9
|
+
onInteract: () => void;
|
|
10
|
+
interactionText: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const ActionButton: ({ id, label, color, width, height, scale, position, onInteract, interactionText, }: ActionButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=ActionButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActionButton.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TagBoard/components/TagSelector/components/ActionButton.tsx"],"names":[],"mappings":"AASA,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,YAAY,GAAI,oFAU1B,iBAAiB,4CAoBnB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* ActionButton コンポーネント
|
|
4
|
+
*
|
|
5
|
+
* TagSelector内で使用する汎用アクションボタン。
|
|
6
|
+
*/
|
|
7
|
+
import { Text } from "@react-three/drei";
|
|
8
|
+
import { Interactable } from "../../../../Interactable";
|
|
9
|
+
export const ActionButton = ({ id, label, color, width, height, scale, position, onInteract, interactionText, }) => {
|
|
10
|
+
return (_jsxs("group", { position: position, children: [_jsx(Interactable, { id: id, onInteract: onInteract, interactionText: interactionText, children: _jsxs("mesh", { children: [_jsx("boxGeometry", { args: [width, height, 0.01 * scale] }), _jsx("meshStandardMaterial", { color: color, opacity: 1, transparent: true })] }) }), _jsx(Text, { position: [0, 0, 0.006 * scale], fontSize: 0.15 * scale, color: 0xffffff, anchorX: "center", anchorY: "middle", children: label })] }));
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=ActionButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActionButton.js","sourceRoot":"","sources":["../../../../../../src/components/TagBoard/components/TagSelector/components/ActionButton.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAcxD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAC3B,EAAE,EACF,KAAK,EACL,KAAK,EACL,KAAK,EACL,MAAM,EACN,KAAK,EACL,QAAQ,EACR,UAAU,EACV,eAAe,GACG,EAAE,EAAE;IACtB,OAAO,CACL,iBAAO,QAAQ,EAAE,QAAQ,aACvB,KAAC,YAAY,IAAC,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,YAC5E,2BACE,sBAAa,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAG,KAAK,CAAC,GAAI,EACpD,+BAAsB,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,WAAW,SAAG,IACzD,GACM,EACf,KAAC,IAAI,IACH,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,EAC/B,QAAQ,EAAE,IAAI,GAAG,KAAK,EACtB,KAAK,EAAE,QAAQ,EACf,OAAO,EAAC,QAAQ,EAChB,OAAO,EAAC,QAAQ,YAEf,KAAK,GACD,IACD,CACT,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Tag } from "../../../types";
|
|
2
|
+
export interface TagButtonProps {
|
|
3
|
+
tag: Tag;
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
scale: number;
|
|
7
|
+
position: [number, number, number];
|
|
8
|
+
isSelected: boolean;
|
|
9
|
+
onInteract: () => void;
|
|
10
|
+
}
|
|
11
|
+
export declare const TagButton: ({ tag, width, height, scale, position, isSelected, onInteract, }: TagButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
//# sourceMappingURL=TagButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TagButton.d.ts","sourceRoot":"","sources":["../../../../../../src/components/TagBoard/components/TagSelector/components/TagButton.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,GAAG,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,SAAS,GAAI,kEAQvB,cAAc,4CAwBhB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* TagButton コンポーネント
|
|
4
|
+
*
|
|
5
|
+
* タグ選択ボタン。選択状態のチェックマーク表示を含む。
|
|
6
|
+
*/
|
|
7
|
+
import { Text } from "@react-three/drei";
|
|
8
|
+
import { Interactable } from "../../../../Interactable";
|
|
9
|
+
import { TagChip } from "../../TagChip";
|
|
10
|
+
export const TagButton = ({ tag, width, height, scale, position, isSelected, onInteract, }) => {
|
|
11
|
+
return (_jsxs("group", { position: position, children: [_jsx(Interactable, { id: `tag-button-${tag.id}`, onInteract: onInteract, interactionText: tag.label, children: _jsx(TagChip, { tag: tag, width: width, height: height, fontSize: 0.15 * scale }) }), isSelected && (_jsx(Text, { position: [-0.58 * scale, -0.02 * scale, 0.012 * scale], fontSize: 0.2 * scale, color: tag.color, anchorX: "center", anchorY: "middle", children: "\u2713" }))] }));
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=TagButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TagButton.js","sourceRoot":"","sources":["../../../../../../src/components/TagBoard/components/TagSelector/components/TagButton.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAaxC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EACxB,GAAG,EACH,KAAK,EACL,MAAM,EACN,KAAK,EACL,QAAQ,EACR,UAAU,EACV,UAAU,GACK,EAAE,EAAE;IACnB,OAAO,CACL,iBAAO,QAAQ,EAAE,QAAQ,aACvB,KAAC,YAAY,IACX,EAAE,EAAE,cAAc,GAAG,CAAC,EAAE,EAAE,EAC1B,UAAU,EAAE,UAAU,EACtB,eAAe,EAAE,GAAG,CAAC,KAAK,YAE1B,KAAC,OAAO,IAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAG,KAAK,GAAI,GAC9D,EAEd,UAAU,IAAI,CACb,KAAC,IAAI,IACH,QAAQ,EAAE,CAAC,CAAC,IAAI,GAAG,KAAK,EAAE,CAAC,IAAI,GAAG,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,EACvD,QAAQ,EAAE,GAAG,GAAG,KAAK,EACrB,KAAK,EAAE,GAAG,CAAC,KAAK,EAChB,OAAO,EAAC,QAAQ,EAChB,OAAO,EAAC,QAAQ,uBAGX,CACR,IACK,CACT,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type TagSelectorProps } from "../../types";
|
|
2
|
+
export declare const TagSelector: ({ tags, title, instanceStateKey, position, rotation, scale, tagsVisible, onTagsVisibleChange, }: TagSelectorProps) => import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/TagBoard/components/TagSelector/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAKpD,eAAO,MAAM,WAAW,GAAI,iGASzB,gBAAgB,4CAyGlB,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* TagSelector コンポーネント
|
|
4
|
+
*
|
|
5
|
+
* タグ選択用のボードUIを表示し、選択状態をインスタンス状態(`useInstanceState`)へ反映します。
|
|
6
|
+
* 可視状態のトグルも提供します。
|
|
7
|
+
*
|
|
8
|
+
* Props 概要:
|
|
9
|
+
* - tags: 表示・選択対象のタグ一覧
|
|
10
|
+
* - title: ボード上部に表示するタイトル文言
|
|
11
|
+
* - instanceStateKey: 複数ボード設置時のキー識別子
|
|
12
|
+
* - position/rotation/scale: ボードの位置・回転・スケール
|
|
13
|
+
* - tagsVisible: タグ表示/非表示の状態
|
|
14
|
+
* - onTagsVisibleChange: タグ表示/非表示の変更コールバック
|
|
15
|
+
*/
|
|
16
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
17
|
+
import { Text } from "@react-three/drei";
|
|
18
|
+
import { useUsers } from "../../../../contexts/UsersContext";
|
|
19
|
+
import { useInstanceState } from "../../../../hooks/useInstanceState";
|
|
20
|
+
import { ActionButton } from "./components/ActionButton";
|
|
21
|
+
import { TagButton } from "./components/TagButton";
|
|
22
|
+
import { calculateLayout, toggleTagSelection } from "./utils";
|
|
23
|
+
export const TagSelector = ({ tags, title, instanceStateKey, position, rotation, scale, tagsVisible, onTagsVisibleChange, }) => {
|
|
24
|
+
const { localUser } = useUsers();
|
|
25
|
+
const stateKey = `tag-${instanceStateKey}-${localUser?.id}`;
|
|
26
|
+
// グローバル同期用の選択タグID(他ユーザーからも見える状態に反映)
|
|
27
|
+
const [, setGlobalSelectedTagIds] = useInstanceState(stateKey, []);
|
|
28
|
+
const [localSelectedTagIds, setLocalSelectedTagIds] = useState([]);
|
|
29
|
+
// useMemo
|
|
30
|
+
const flatTags = useMemo(() => tags.flat(), [tags]);
|
|
31
|
+
const layout = useMemo(() => calculateLayout(tags, scale), [tags, scale]);
|
|
32
|
+
// localSelectedTagIds が変更されたらグローバル状態に同期
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!localUser?.id)
|
|
35
|
+
return;
|
|
36
|
+
setGlobalSelectedTagIds(localSelectedTagIds);
|
|
37
|
+
}, [localSelectedTagIds, localUser?.id, setGlobalSelectedTagIds]);
|
|
38
|
+
// useCallback
|
|
39
|
+
const handleTagClick = useCallback((tagId) => {
|
|
40
|
+
setLocalSelectedTagIds((prev) => toggleTagSelection(prev, tagId, flatTags));
|
|
41
|
+
}, [flatTags]);
|
|
42
|
+
const handleClear = useCallback(() => {
|
|
43
|
+
setLocalSelectedTagIds([]);
|
|
44
|
+
}, []);
|
|
45
|
+
const handleToggleVisibility = useCallback(() => {
|
|
46
|
+
onTagsVisibleChange(!tagsVisible);
|
|
47
|
+
}, [onTagsVisibleChange, tagsVisible]);
|
|
48
|
+
return (_jsxs("group", { position: position, rotation: rotation, children: [_jsxs("mesh", { position: [0, 0, -0.02], children: [_jsx("planeGeometry", { args: [layout.boardWidth, layout.boardHeight] }), _jsx("meshBasicMaterial", { color: 0x2a2a2a })] }), _jsx(Text, { position: [0, layout.titleY, 0], fontSize: 0.2 * scale, color: "white", anchorX: "center", anchorY: "middle", fontWeight: "bold", children: title }), _jsx(ActionButton, { id: "tag-clear-button", label: "\u5168\u524A\u9664", color: 0xff6666, width: layout.buttonWidth, height: 0.35 * scale, scale: scale, position: [layout.buttonLeftX, layout.buttonGroupY - 0.3 * scale, -0.01], onInteract: handleClear, interactionText: "\u9078\u629E\u3092\u30AF\u30EA\u30A2" }), _jsx(ActionButton, { id: "tag-visibility-toggle", label: tagsVisible ? "非表示" : "表示", color: tagsVisible ? 0x00aa00 : 0xaa0000, width: layout.buttonWidth, height: 0.35 * scale, scale: scale, position: [layout.buttonRightX, layout.buttonGroupY - 0.3 * scale, -0.01], onInteract: handleToggleVisibility, interactionText: tagsVisible ? "タグを非表示" : "タグを表示" }), tags.map((columnTags, colIndex) => {
|
|
49
|
+
const xPos = (colIndex - (layout.columns - 1) / 2) * layout.columnSpacing;
|
|
50
|
+
return columnTags.map((tag, rowIndex) => {
|
|
51
|
+
const yPos = layout.tagStartY - rowIndex * layout.tagHeight;
|
|
52
|
+
const isSelected = localSelectedTagIds.includes(tag.id);
|
|
53
|
+
return (_jsx(TagButton, { tag: tag, width: layout.tagWidth, height: layout.tagHeight, scale: scale, position: [xPos, yPos, -0.01], isSelected: isSelected, onInteract: () => handleTagClick(tag.id) }, tag.id));
|
|
54
|
+
});
|
|
55
|
+
})] }));
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/components/TagBoard/components/TagSelector/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Tag } from "../../types";
|
|
2
|
+
export interface TagSelectorLayout {
|
|
3
|
+
tagHeight: number;
|
|
4
|
+
tagWidth: number;
|
|
5
|
+
columnSpacing: number;
|
|
6
|
+
columns: number;
|
|
7
|
+
boardWidth: number;
|
|
8
|
+
boardHeight: number;
|
|
9
|
+
titleY: number;
|
|
10
|
+
buttonGroupY: number;
|
|
11
|
+
tagStartY: number;
|
|
12
|
+
buttonWidth: number;
|
|
13
|
+
buttonLeftX: number;
|
|
14
|
+
buttonRightX: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* タグIDの選択状態をトグルし、tagsの順番でソートして返す
|
|
18
|
+
*/
|
|
19
|
+
export declare const toggleTagSelection: (prevIds: string[], tagId: string, flatTags: Tag[]) => string[];
|
|
20
|
+
export declare const calculateLayout: (tags: Tag[][], scale: number) => TagSelectorLayout;
|
|
21
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/components/TagBoard/components/TagSelector/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,aAAa,CAAC;AAEvC,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,SAAS,MAAM,EAAE,EACjB,OAAO,MAAM,EACb,UAAU,GAAG,EAAE,KACd,MAAM,EAaR,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,MAAM,GAAG,EAAE,EAAE,EAAE,OAAO,MAAM,KAAG,iBAmC9D,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* タグIDの選択状態をトグルし、tagsの順番でソートして返す
|
|
3
|
+
*/
|
|
4
|
+
export const toggleTagSelection = (prevIds, tagId, flatTags) => {
|
|
5
|
+
let newIds;
|
|
6
|
+
if (prevIds.includes(tagId)) {
|
|
7
|
+
newIds = prevIds.filter((id) => id !== tagId);
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
newIds = [...new Set([...prevIds, tagId])];
|
|
11
|
+
}
|
|
12
|
+
// tags配列の順番に合わせてソート
|
|
13
|
+
return newIds.sort((a, b) => {
|
|
14
|
+
const indexA = flatTags.findIndex((tag) => tag.id === a);
|
|
15
|
+
const indexB = flatTags.findIndex((tag) => tag.id === b);
|
|
16
|
+
return indexA - indexB;
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
export const calculateLayout = (tags, scale) => {
|
|
20
|
+
const tagHeight = 0.27 * scale;
|
|
21
|
+
const tagWidth = 1.33 * scale;
|
|
22
|
+
const columnSpacing = tagWidth;
|
|
23
|
+
const columns = tags.length;
|
|
24
|
+
const maxRowsInColumn = Math.max(...tags.map((col) => col.length), 0);
|
|
25
|
+
const boardWidth = columns * tagWidth + 0.2 * scale;
|
|
26
|
+
const headerHeight = 1.0 * scale;
|
|
27
|
+
const boardHeight = maxRowsInColumn * tagHeight + headerHeight;
|
|
28
|
+
const boardTop = boardHeight / 2;
|
|
29
|
+
const titleY = boardTop - 0.25 * scale;
|
|
30
|
+
const buttonGroupY = boardTop - 0.3 * scale;
|
|
31
|
+
const tagStartY = boardTop - headerHeight;
|
|
32
|
+
const buttonWidth = boardWidth / 2 - 0.05 * scale;
|
|
33
|
+
const buttonLeftX = -boardWidth / 4;
|
|
34
|
+
const buttonRightX = boardWidth / 4;
|
|
35
|
+
return {
|
|
36
|
+
tagHeight,
|
|
37
|
+
tagWidth,
|
|
38
|
+
columnSpacing,
|
|
39
|
+
columns,
|
|
40
|
+
boardWidth,
|
|
41
|
+
boardHeight,
|
|
42
|
+
titleY,
|
|
43
|
+
buttonGroupY,
|
|
44
|
+
tagStartY,
|
|
45
|
+
buttonWidth,
|
|
46
|
+
buttonLeftX,
|
|
47
|
+
buttonRightX,
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=utils.js.map
|