@xrift/world-components 0.20.1 → 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.
Files changed (111) hide show
  1. package/dist/components/TagBoard/components/TagChip.d.ts +12 -0
  2. package/dist/components/TagBoard/components/TagChip.d.ts.map +1 -0
  3. package/dist/components/TagBoard/components/TagChip.js +13 -0
  4. package/dist/components/TagBoard/components/TagChip.js.map +1 -0
  5. package/dist/components/TagBoard/components/TagDisplay/index.d.ts +3 -0
  6. package/dist/components/TagBoard/components/TagDisplay/index.d.ts.map +1 -0
  7. package/dist/components/TagBoard/components/TagDisplay/index.js +64 -0
  8. package/dist/components/TagBoard/components/TagDisplay/index.js.map +1 -0
  9. package/dist/components/TagBoard/components/TagDisplay/utils.d.ts +23 -0
  10. package/dist/components/TagBoard/components/TagDisplay/utils.d.ts.map +1 -0
  11. package/dist/components/TagBoard/components/TagDisplay/utils.js +53 -0
  12. package/dist/components/TagBoard/components/TagDisplay/utils.js.map +1 -0
  13. package/dist/components/TagBoard/components/TagSelector/components/ActionButton.d.ts +13 -0
  14. package/dist/components/TagBoard/components/TagSelector/components/ActionButton.d.ts.map +1 -0
  15. package/dist/components/TagBoard/components/TagSelector/components/ActionButton.js +12 -0
  16. package/dist/components/TagBoard/components/TagSelector/components/ActionButton.js.map +1 -0
  17. package/dist/components/TagBoard/components/TagSelector/components/TagButton.d.ts +12 -0
  18. package/dist/components/TagBoard/components/TagSelector/components/TagButton.d.ts.map +1 -0
  19. package/dist/components/TagBoard/components/TagSelector/components/TagButton.js +13 -0
  20. package/dist/components/TagBoard/components/TagSelector/components/TagButton.js.map +1 -0
  21. package/dist/components/TagBoard/components/TagSelector/index.d.ts +3 -0
  22. package/dist/components/TagBoard/components/TagSelector/index.d.ts.map +1 -0
  23. package/dist/components/TagBoard/components/TagSelector/index.js +57 -0
  24. package/dist/components/TagBoard/components/TagSelector/index.js.map +1 -0
  25. package/dist/components/TagBoard/components/TagSelector/utils.d.ts +21 -0
  26. package/dist/components/TagBoard/components/TagSelector/utils.d.ts.map +1 -0
  27. package/dist/components/TagBoard/components/TagSelector/utils.js +50 -0
  28. package/dist/components/TagBoard/components/TagSelector/utils.js.map +1 -0
  29. package/dist/components/TagBoard/constants.d.ts +8 -0
  30. package/dist/components/TagBoard/constants.d.ts.map +1 -0
  31. package/dist/components/TagBoard/constants.js +15 -0
  32. package/dist/components/TagBoard/constants.js.map +1 -0
  33. package/dist/components/TagBoard/index.d.ts +4 -0
  34. package/dist/components/TagBoard/index.d.ts.map +1 -0
  35. package/dist/components/TagBoard/index.js +25 -0
  36. package/dist/components/TagBoard/index.js.map +1 -0
  37. package/dist/components/TagBoard/types.d.ts +46 -0
  38. package/dist/components/TagBoard/types.d.ts.map +1 -0
  39. package/dist/components/TagBoard/types.js.map +1 -0
  40. package/dist/components/TagBoard/utils.d.ts +7 -0
  41. package/dist/components/TagBoard/utils.d.ts.map +1 -0
  42. package/dist/components/TagBoard/utils.js +20 -0
  43. package/dist/components/TagBoard/utils.js.map +1 -0
  44. package/dist/hooks/useInstanceState.d.ts.map +1 -1
  45. package/dist/hooks/useInstanceState.js +3 -3
  46. package/dist/hooks/useInstanceState.js.map +1 -1
  47. package/dist/index.d.ts +1 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +1 -0
  50. package/dist/index.js.map +1 -1
  51. package/package.json +1 -1
  52. package/dist/components/RichVideoPlayer/ControlPanel.d.ts +0 -3
  53. package/dist/components/RichVideoPlayer/ControlPanel.d.ts.map +0 -1
  54. package/dist/components/RichVideoPlayer/ControlPanel.js +0 -22
  55. package/dist/components/RichVideoPlayer/ControlPanel.js.map +0 -1
  56. package/dist/components/RichVideoPlayer/PlayPauseButton.d.ts +0 -3
  57. package/dist/components/RichVideoPlayer/PlayPauseButton.d.ts.map +0 -1
  58. package/dist/components/RichVideoPlayer/PlayPauseButton.js +0 -9
  59. package/dist/components/RichVideoPlayer/PlayPauseButton.js.map +0 -1
  60. package/dist/components/RichVideoPlayer/ProgressBar.d.ts +0 -3
  61. package/dist/components/RichVideoPlayer/ProgressBar.d.ts.map +0 -1
  62. package/dist/components/RichVideoPlayer/ProgressBar.js +0 -20
  63. package/dist/components/RichVideoPlayer/ProgressBar.js.map +0 -1
  64. package/dist/components/RichVideoPlayer/UrlInputButton.d.ts +0 -3
  65. package/dist/components/RichVideoPlayer/UrlInputButton.d.ts.map +0 -1
  66. package/dist/components/RichVideoPlayer/UrlInputButton.js +0 -23
  67. package/dist/components/RichVideoPlayer/UrlInputButton.js.map +0 -1
  68. package/dist/components/RichVideoPlayer/VolumeControl.d.ts +0 -3
  69. package/dist/components/RichVideoPlayer/VolumeControl.d.ts.map +0 -1
  70. package/dist/components/RichVideoPlayer/VolumeControl.js +0 -26
  71. package/dist/components/RichVideoPlayer/VolumeControl.js.map +0 -1
  72. package/dist/components/RichVideoPlayer/hooks.d.ts +0 -5
  73. package/dist/components/RichVideoPlayer/hooks.d.ts.map +0 -1
  74. package/dist/components/RichVideoPlayer/hooks.js +0 -9
  75. package/dist/components/RichVideoPlayer/hooks.js.map +0 -1
  76. package/dist/components/RichVideoPlayer/index.d.ts +0 -4
  77. package/dist/components/RichVideoPlayer/index.d.ts.map +0 -1
  78. package/dist/components/RichVideoPlayer/index.js +0 -100
  79. package/dist/components/RichVideoPlayer/index.js.map +0 -1
  80. package/dist/components/RichVideoPlayer/types.d.ts +0 -64
  81. package/dist/components/RichVideoPlayer/types.d.ts.map +0 -1
  82. package/dist/components/RichVideoPlayer/types.js.map +0 -1
  83. package/dist/components/RichVideoPlayer/utils.d.ts +0 -32
  84. package/dist/components/RichVideoPlayer/utils.d.ts.map +0 -1
  85. package/dist/components/RichVideoPlayer/utils.js +0 -37
  86. package/dist/components/RichVideoPlayer/utils.js.map +0 -1
  87. package/dist/components/RichVideoPlayer/utils.test.d.ts +0 -2
  88. package/dist/components/RichVideoPlayer/utils.test.d.ts.map +0 -1
  89. package/dist/components/RichVideoPlayer/utils.test.js +0 -109
  90. package/dist/components/RichVideoPlayer/utils.test.js.map +0 -1
  91. package/dist/hooks/useVideoScreenControls.d.ts +0 -57
  92. package/dist/hooks/useVideoScreenControls.d.ts.map +0 -1
  93. package/dist/hooks/useVideoScreenControls.js +0 -130
  94. package/dist/hooks/useVideoScreenControls.js.map +0 -1
  95. package/dist/scenes/SpawnPointTestScene.d.ts +0 -6
  96. package/dist/scenes/SpawnPointTestScene.d.ts.map +0 -1
  97. package/dist/scenes/SpawnPointTestScene.js +0 -12
  98. package/dist/scenes/SpawnPointTestScene.js.map +0 -1
  99. package/dist/scenes/TestScene.d.ts +0 -6
  100. package/dist/scenes/TestScene.d.ts.map +0 -1
  101. package/dist/scenes/TestScene.js +0 -19
  102. package/dist/scenes/TestScene.js.map +0 -1
  103. package/dist/scenes/TheaterScene.d.ts +0 -6
  104. package/dist/scenes/TheaterScene.d.ts.map +0 -1
  105. package/dist/scenes/TheaterScene.js +0 -12
  106. package/dist/scenes/TheaterScene.js.map +0 -1
  107. package/dist/scenes/VideoControlTest.d.ts +0 -5
  108. package/dist/scenes/VideoControlTest.d.ts.map +0 -1
  109. package/dist/scenes/VideoControlTest.js +0 -17
  110. package/dist/scenes/VideoControlTest.js.map +0 -1
  111. /package/dist/components/{RichVideoPlayer → TagBoard}/types.js +0 -0
@@ -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,3 @@
1
+ import { type TagDisplayProps } from "../../types";
2
+ export declare const TagDisplay: ({ userId, getMovement, tags, visible, instanceStateKey, }: TagDisplayProps) => import("react/jsx-runtime").JSX.Element | null;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../src/components/TagBoard/components/TagSelector/utils.ts"],"names":[],"mappings":"AAiBA;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,OAAiB,EACjB,KAAa,EACb,QAAe,EACL,EAAE;IACZ,IAAI,MAAgB,CAAC;IACrB,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;IACD,oBAAoB;IACpB,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC1B,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QACzD,OAAO,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAa,EAAE,KAAa,EAAqB,EAAE;IACjF,MAAM,SAAS,GAAG,IAAI,GAAG,KAAK,CAAC;IAC/B,MAAM,QAAQ,GAAG,IAAI,GAAG,KAAK,CAAC;IAC9B,MAAM,aAAa,GAAG,QAAQ,CAAC;IAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;IAE5B,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACtE,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,GAAG,GAAG,KAAK,CAAC;IAEpD,MAAM,YAAY,GAAG,GAAG,GAAG,KAAK,CAAC;IACjC,MAAM,WAAW,GAAG,eAAe,GAAG,SAAS,GAAG,YAAY,CAAC;IAE/D,MAAM,QAAQ,GAAG,WAAW,GAAG,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,QAAQ,GAAG,IAAI,GAAG,KAAK,CAAC;IACvC,MAAM,YAAY,GAAG,QAAQ,GAAG,GAAG,GAAG,KAAK,CAAC;IAC5C,MAAM,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAC;IAE1C,MAAM,WAAW,GAAG,UAAU,GAAG,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;IAClD,MAAM,WAAW,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC;IACpC,MAAM,YAAY,GAAG,UAAU,GAAG,CAAC,CAAC;IAEpC,OAAO;QACL,SAAS;QACT,QAAQ;QACR,aAAa;QACb,OAAO;QACP,UAAU;QACV,WAAW;QACX,MAAM;QACN,YAAY;QACZ,SAAS;QACT,WAAW;QACX,WAAW;QACX,YAAY;KACb,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * TagBoard 関連の定数定義
3
+ */
4
+ import { type Tag } from "./types";
5
+ export declare const DEFAULT_TITLE = "\u30BF\u30B0\u9078\u629E";
6
+ export declare const DEFAULT_COLUMNS = 3;
7
+ export declare const DEFAULT_TAGS: Tag[];
8
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/components/TagBoard/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,SAAS,CAAC;AAEnC,eAAO,MAAM,aAAa,6BAAS,CAAC;AACpC,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,eAAO,MAAM,YAAY,EAAE,GAAG,EAW7B,CAAC"}
@@ -0,0 +1,15 @@
1
+ export const DEFAULT_TITLE = "タグ選択";
2
+ export const DEFAULT_COLUMNS = 3;
3
+ export const DEFAULT_TAGS = [
4
+ { color: "#2ECC71", id: "want-talk", label: "話したい" },
5
+ { color: "#3498DB", id: "want-listen", label: "聞きたい" },
6
+ { color: "#95A5A6", id: "silent", label: "無言" },
7
+ { color: "#1ABC9C", id: "developer", label: "開発者" },
8
+ { color: "#2980B9", id: "student", label: "学生" },
9
+ { color: "#F1C40F", id: "beginner", label: "初心者" },
10
+ { color: "#9B59B6", id: "dont-know", label: "なんもわからん" },
11
+ { color: "#8BC34A", id: "working", label: "作業中" },
12
+ { color: "#BF7B41", id: "away", label: "離席中" },
13
+ { color: "#FF9800", id: "cat", label: "ねこ" },
14
+ ];
15
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/components/TagBoard/constants.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC;AACpC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AAEjC,MAAM,CAAC,MAAM,YAAY,GAAU;IACjC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE;IACpD,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE;IACtD,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;IAC/C,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE;IACnD,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE;IAChD,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE;IAClD,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE;IACvD,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE;IACjD,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE;IAC9C,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE;CAC7C,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type TagBoardProps } from "./types";
2
+ export { type TagBoardProps, type Tag } from "./types";
3
+ export declare const TagBoard: ({ tags, columns, title, instanceStateKey, position, rotation, scale, }: TagBoardProps) => import("react/jsx-runtime").JSX.Element;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/TagBoard/index.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAG7C,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,GAAG,EAAE,MAAM,SAAS,CAAC;AAEvD,eAAO,MAAM,QAAQ,GAAI,wEAQtB,aAAa,4CA+Cf,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * TagBoard コンポーネント
4
+ *
5
+ * ユーザーが選択したタグをローカル/グローバルに扱い、
6
+ * ボードUI(`TagSelector`)と、各ユーザー頭上へのタグ表示(`TagDisplay`)を提供します。
7
+ *
8
+ * 役割:
9
+ * - TagSelector: タグ選択ボードUI の提供
10
+ * - TagDisplay: 各ユーザー頭上へのタグ表示
11
+ * - 両者の同期: インスタンス状態を通じた連携
12
+ */
13
+ import { useMemo, useState } from "react";
14
+ import { useUsers } from "../../contexts/UsersContext";
15
+ import { TagSelector } from "./components/TagSelector";
16
+ import { TagDisplay } from "./components/TagDisplay";
17
+ import { DEFAULT_COLUMNS, DEFAULT_TAGS, DEFAULT_TITLE } from "./constants";
18
+ import { splitIntoColumns } from "./utils";
19
+ export const TagBoard = ({ tags = DEFAULT_TAGS, columns = DEFAULT_COLUMNS, title = DEFAULT_TITLE, instanceStateKey, position = [0, 0, 0], rotation = [0, 0, 0], scale = 1, }) => {
20
+ const { remoteUsers, getMovement, getLocalMovement, localUser } = useUsers();
21
+ const [tagsVisible, setTagsVisible] = useState(true);
22
+ const tagColumns = useMemo(() => splitIntoColumns(tags, columns), [tags, columns]);
23
+ return (_jsxs(_Fragment, { children: [_jsx(TagSelector, { tags: tagColumns, title: title, instanceStateKey: instanceStateKey, position: position, rotation: rotation, scale: scale, tagsVisible: tagsVisible, onTagsVisibleChange: setTagsVisible }), localUser && (_jsx(TagDisplay, { userId: localUser.id, getMovement: getLocalMovement, tags: tagColumns, visible: tagsVisible, instanceStateKey: instanceStateKey })), remoteUsers.map((user) => (_jsx(TagDisplay, { userId: user.id, getMovement: getMovement, tags: tagColumns, visible: tagsVisible, instanceStateKey: instanceStateKey }, user.id)))] }));
24
+ };
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/TagBoard/index.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAI3C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,EACvB,IAAI,GAAG,YAAY,EACnB,OAAO,GAAG,eAAe,EACzB,KAAK,GAAG,aAAa,EACrB,gBAAgB,EAChB,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACpB,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACpB,KAAK,GAAG,CAAC,GACK,EAAE,EAAE;IAClB,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC7E,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAErD,MAAM,UAAU,GAAG,OAAO,CACxB,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,EACrC,CAAC,IAAI,EAAE,OAAO,CAAC,CAChB,CAAC;IAEF,OAAO,CACL,8BAEE,KAAC,WAAW,IACV,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,gBAAgB,EAAE,gBAAgB,EAClC,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,WAAW,EACxB,mBAAmB,EAAE,cAAc,GACnC,EAGD,SAAS,IAAI,CACZ,KAAC,UAAU,IACT,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,WAAW,EAAE,gBAAgB,EAC7B,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,WAAW,EACpB,gBAAgB,EAAE,gBAAgB,GAClC,CACH,EAGA,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACzB,KAAC,UAAU,IAET,MAAM,EAAE,IAAI,CAAC,EAAE,EACf,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,WAAW,EACpB,gBAAgB,EAAE,gBAAgB,IAL7B,IAAI,CAAC,EAAE,CAMZ,CACH,CAAC,IACD,CACJ,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { type PlayerMovement } from "../../types/movement";
2
+ /** 表示用のタグ定義 */
3
+ export interface Tag {
4
+ id: string;
5
+ label: string;
6
+ color: string;
7
+ }
8
+ /** TagBoard のプロパティ */
9
+ export interface TagBoardProps {
10
+ /** 表示・選択対象のタグ(省略時はデフォルトを使用) */
11
+ tags?: Tag[];
12
+ /** 表示列数(省略時は3列) */
13
+ columns?: number;
14
+ /** タイトル文言 */
15
+ title?: string;
16
+ /** インスタンス状態のキー(複数ボード設置時の識別用) */
17
+ instanceStateKey: string;
18
+ /** ボードの位置 */
19
+ position?: [number, number, number];
20
+ /** ボードの回転 */
21
+ rotation?: [number, number, number];
22
+ /** 全体スケール */
23
+ scale?: number;
24
+ }
25
+ /** TagDisplay のプロパティ */
26
+ export interface TagDisplayProps {
27
+ userId: string;
28
+ getMovement: (userId: string) => PlayerMovement | undefined;
29
+ tags: Tag[][];
30
+ visible: boolean;
31
+ instanceStateKey: string;
32
+ }
33
+ /** TagSelector のプロパティ */
34
+ export interface TagSelectorProps {
35
+ tags: Tag[][];
36
+ title: string;
37
+ instanceStateKey: string;
38
+ position: [number, number, number];
39
+ rotation: [number, number, number];
40
+ scale: number;
41
+ /** タグ表示/非表示の状態 */
42
+ tagsVisible: boolean;
43
+ /** タグ表示/非表示の変更コールバック */
44
+ onTagsVisibleChange: (visible: boolean) => void;
45
+ }
46
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/TagBoard/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,eAAe;AACf,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,sBAAsB;AACtB,MAAM,WAAW,aAAa;IAC5B,+BAA+B;IAC/B,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACb,mBAAmB;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa;IACb,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,aAAa;IACb,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,aAAa;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAwB;AACxB,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,cAAc,GAAG,SAAS,CAAC;IAC5D,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,yBAAyB;AACzB,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,wBAAwB;IACxB,mBAAmB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACjD"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/components/TagBoard/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import { type Tag } from "./types";
2
+ /**
3
+ * タグ配列を指定列数で分割する
4
+ * 各列にできるだけ均等にタグを配置する
5
+ */
6
+ export declare const splitIntoColumns: (tags: Tag[], columns: number) => Tag[][];
7
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/components/TagBoard/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,SAAS,CAAC;AAEnC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,GAAG,EAAE,EAAE,SAAS,MAAM,KAAG,GAAG,EAAE,EAgBpE,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * タグ配列を指定列数で分割する
3
+ * 各列にできるだけ均等にタグを配置する
4
+ */
5
+ export const splitIntoColumns = (tags, columns) => {
6
+ if (columns <= 0 || tags.length === 0)
7
+ return [];
8
+ const result = Array.from({ length: columns }, () => []);
9
+ const baseCount = Math.floor(tags.length / columns);
10
+ const remainder = tags.length % columns;
11
+ let index = 0;
12
+ for (let col = 0; col < columns; col++) {
13
+ const count = baseCount + (col < remainder ? 1 : 0);
14
+ for (let i = 0; i < count; i++) {
15
+ result[col].push(tags[index++]);
16
+ }
17
+ }
18
+ return result;
19
+ };
20
+ //# sourceMappingURL=utils.js.map