@xrift/world-components 0.24.0 → 0.25.1

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 (38) hide show
  1. package/dist/components/EntryLogBoard/__tests__/utils.test.d.ts +2 -0
  2. package/dist/components/EntryLogBoard/__tests__/utils.test.d.ts.map +1 -0
  3. package/dist/components/EntryLogBoard/__tests__/utils.test.js +231 -0
  4. package/dist/components/EntryLogBoard/__tests__/utils.test.js.map +1 -0
  5. package/dist/components/EntryLogBoard/components/AvatarIcon.d.ts +10 -0
  6. package/dist/components/EntryLogBoard/components/AvatarIcon.d.ts.map +1 -0
  7. package/dist/components/EntryLogBoard/components/AvatarIcon.js +20 -0
  8. package/dist/components/EntryLogBoard/components/AvatarIcon.js.map +1 -0
  9. package/dist/components/EntryLogBoard/components/LogRow.d.ts +12 -0
  10. package/dist/components/EntryLogBoard/components/LogRow.d.ts.map +1 -0
  11. package/dist/components/EntryLogBoard/components/LogRow.js +22 -0
  12. package/dist/components/EntryLogBoard/components/LogRow.js.map +1 -0
  13. package/dist/components/EntryLogBoard/constants.d.ts +9 -0
  14. package/dist/components/EntryLogBoard/constants.d.ts.map +1 -0
  15. package/dist/components/EntryLogBoard/constants.js +16 -0
  16. package/dist/components/EntryLogBoard/constants.js.map +1 -0
  17. package/dist/components/EntryLogBoard/hooks/useEntryLog.d.ts +12 -0
  18. package/dist/components/EntryLogBoard/hooks/useEntryLog.d.ts.map +1 -0
  19. package/dist/components/EntryLogBoard/hooks/useEntryLog.js +108 -0
  20. package/dist/components/EntryLogBoard/hooks/useEntryLog.js.map +1 -0
  21. package/dist/components/EntryLogBoard/index.d.ts +4 -0
  22. package/dist/components/EntryLogBoard/index.d.ts.map +1 -0
  23. package/dist/components/EntryLogBoard/index.js +46 -0
  24. package/dist/components/EntryLogBoard/index.js.map +1 -0
  25. package/dist/components/EntryLogBoard/types.d.ts +70 -0
  26. package/dist/components/EntryLogBoard/types.d.ts.map +1 -0
  27. package/dist/components/EntryLogBoard/types.js +2 -0
  28. package/dist/components/EntryLogBoard/types.js.map +1 -0
  29. package/dist/components/EntryLogBoard/utils.d.ts +46 -0
  30. package/dist/components/EntryLogBoard/utils.d.ts.map +1 -0
  31. package/dist/components/EntryLogBoard/utils.js +83 -0
  32. package/dist/components/EntryLogBoard/utils.js.map +1 -0
  33. package/dist/components/TagBoard/components/TagDisplay/index.js +1 -1
  34. package/dist/index.d.ts +1 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +1 -0
  37. package/dist/index.js.map +1 -1
  38. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=utils.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../../../src/components/EntryLogBoard/__tests__/utils.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,231 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { buildLogEntryId, createLogEntry, defaultFormatTimestamp, enrichLogsWithCache, isWriterAmong, mergeLogs, } from '../utils';
3
+ describe('defaultFormatTimestamp', () => {
4
+ it('HH:MM 形式でフォーマットする', () => {
5
+ const date = new Date(2024, 0, 1, 9, 5);
6
+ expect(defaultFormatTimestamp(date)).toBe('09:05');
7
+ });
8
+ it('午後の時刻も正しくフォーマットする', () => {
9
+ const date = new Date(2024, 0, 1, 14, 30);
10
+ expect(defaultFormatTimestamp(date)).toBe('14:30');
11
+ });
12
+ it('0時0分をゼロパディングする', () => {
13
+ const date = new Date(2024, 0, 1, 0, 0);
14
+ expect(defaultFormatTimestamp(date)).toBe('00:00');
15
+ });
16
+ });
17
+ describe('buildLogEntryId', () => {
18
+ it('同じユーザーの join が無い場合は 0 から始まるIDを生成する', () => {
19
+ const id = buildLogEntryId('join', 'user-1', []);
20
+ expect(id).toBe('join-user-1-0');
21
+ });
22
+ it('同じユーザーの join が1件ある場合は 1 のIDを生成する', () => {
23
+ const existingLogs = [
24
+ {
25
+ id: 'join-user-1-0',
26
+ type: 'join',
27
+ userId: 'user-1',
28
+ displayName: 'Alice',
29
+ avatarUrl: null,
30
+ timestamp: '10:00',
31
+ },
32
+ ];
33
+ const id = buildLogEntryId('join', 'user-1', existingLogs);
34
+ expect(id).toBe('join-user-1-1');
35
+ });
36
+ it('異なるユーザーのログはカウントに含めない', () => {
37
+ const existingLogs = [
38
+ {
39
+ id: 'join-user-2-0',
40
+ type: 'join',
41
+ userId: 'user-2',
42
+ displayName: 'Bob',
43
+ avatarUrl: null,
44
+ timestamp: '10:00',
45
+ },
46
+ ];
47
+ const id = buildLogEntryId('join', 'user-1', existingLogs);
48
+ expect(id).toBe('join-user-1-0');
49
+ });
50
+ it('異なるタイプのログはカウントに含めない', () => {
51
+ const existingLogs = [
52
+ {
53
+ id: 'leave-user-1-0',
54
+ type: 'leave',
55
+ userId: 'user-1',
56
+ displayName: 'Alice',
57
+ avatarUrl: null,
58
+ timestamp: '10:00',
59
+ },
60
+ ];
61
+ const id = buildLogEntryId('join', 'user-1', existingLogs);
62
+ expect(id).toBe('join-user-1-0');
63
+ });
64
+ it('leave タイプでも正しくIDを生成する', () => {
65
+ const existingLogs = [
66
+ {
67
+ id: 'leave-user-1-0',
68
+ type: 'leave',
69
+ userId: 'user-1',
70
+ displayName: 'Alice',
71
+ avatarUrl: null,
72
+ timestamp: '10:00',
73
+ },
74
+ ];
75
+ const id = buildLogEntryId('leave', 'user-1', existingLogs);
76
+ expect(id).toBe('leave-user-1-1');
77
+ });
78
+ });
79
+ describe('createLogEntry', () => {
80
+ const mockFormatTimestamp = () => '12:34';
81
+ it('join エントリを正しく生成する', () => {
82
+ const entry = createLogEntry('join', 'user-1', 'Alice', 'https://example.com/avatar.png', [], mockFormatTimestamp);
83
+ expect(entry).toEqual({
84
+ id: 'join-user-1-0',
85
+ type: 'join',
86
+ userId: 'user-1',
87
+ displayName: 'Alice',
88
+ avatarUrl: 'https://example.com/avatar.png',
89
+ timestamp: '12:34',
90
+ });
91
+ });
92
+ it('leave エントリを正しく生成する', () => {
93
+ const entry = createLogEntry('leave', 'user-1', 'Alice', null, [], mockFormatTimestamp);
94
+ expect(entry).toEqual({
95
+ id: 'leave-user-1-0',
96
+ type: 'leave',
97
+ userId: 'user-1',
98
+ displayName: 'Alice',
99
+ avatarUrl: null,
100
+ timestamp: '12:34',
101
+ });
102
+ });
103
+ it('既存ログを考慮してIDを決定論的に生成する', () => {
104
+ const existingLogs = [
105
+ {
106
+ id: 'join-user-1-0',
107
+ type: 'join',
108
+ userId: 'user-1',
109
+ displayName: 'Alice',
110
+ avatarUrl: null,
111
+ timestamp: '10:00',
112
+ },
113
+ ];
114
+ const entry = createLogEntry('join', 'user-1', 'Alice', null, existingLogs, mockFormatTimestamp);
115
+ expect(entry.id).toBe('join-user-1-1');
116
+ });
117
+ });
118
+ describe('isWriterAmong', () => {
119
+ it('辞書順最小のIDがtargetIdと一致する場合はtrueを返す', () => {
120
+ expect(isWriterAmong(['user-b', 'user-a', 'user-c'], 'user-a')).toBe(true);
121
+ });
122
+ it('辞書順最小のIDがtargetIdと一致しない場合はfalseを返す', () => {
123
+ expect(isWriterAmong(['user-b', 'user-a', 'user-c'], 'user-b')).toBe(false);
124
+ });
125
+ it('targetIdがundefinedの場合はfalseを返す', () => {
126
+ expect(isWriterAmong(['user-a', 'user-b'], undefined)).toBe(false);
127
+ });
128
+ it('候補が空配列の場合はfalseを返す', () => {
129
+ expect(isWriterAmong([], 'user-a')).toBe(false);
130
+ });
131
+ it('候補にundefinedが含まれていてもフィルタして判定する', () => {
132
+ expect(isWriterAmong([undefined, 'user-b', 'user-a'], 'user-a')).toBe(true);
133
+ });
134
+ it('候補が1つだけでtargetIdと一致する場合はtrueを返す', () => {
135
+ expect(isWriterAmong(['user-a'], 'user-a')).toBe(true);
136
+ });
137
+ });
138
+ describe('enrichLogsWithCache', () => {
139
+ const unknownEntry = {
140
+ id: 'join-user-1-0',
141
+ type: 'join',
142
+ userId: 'user-1',
143
+ displayName: 'Unknown',
144
+ avatarUrl: null,
145
+ timestamp: '10:00',
146
+ };
147
+ const knownEntry = {
148
+ id: 'join-user-2-0',
149
+ type: 'join',
150
+ userId: 'user-2',
151
+ displayName: 'Bob',
152
+ avatarUrl: 'https://example.com/bob.png',
153
+ timestamp: '10:01',
154
+ };
155
+ it('Unknown エントリをキャッシュの情報で補完する', () => {
156
+ const cache = new Map([
157
+ ['user-1', { displayName: 'Alice', avatarUrl: 'https://example.com/alice.png' }],
158
+ ]);
159
+ const result = enrichLogsWithCache([unknownEntry], 'Unknown', cache);
160
+ expect(result[0].displayName).toBe('Alice');
161
+ expect(result[0].avatarUrl).toBe('https://example.com/alice.png');
162
+ });
163
+ it('Unknown でないエントリはそのまま返す', () => {
164
+ const logs = [knownEntry];
165
+ const cache = new Map([
166
+ ['user-2', { displayName: 'Bob2', avatarUrl: null }],
167
+ ]);
168
+ const result = enrichLogsWithCache(logs, 'Unknown', cache);
169
+ expect(result).toBe(logs);
170
+ });
171
+ it('キャッシュにないユーザーの Unknown はそのまま', () => {
172
+ const logs = [unknownEntry];
173
+ const cache = new Map();
174
+ const result = enrichLogsWithCache(logs, 'Unknown', cache);
175
+ expect(result).toBe(logs);
176
+ });
177
+ it('変更がなければ元の配列参照を返す', () => {
178
+ const logs = [knownEntry];
179
+ const cache = new Map();
180
+ const result = enrichLogsWithCache(logs, 'Unknown', cache);
181
+ expect(result).toBe(logs);
182
+ });
183
+ });
184
+ describe('mergeLogs', () => {
185
+ const baseEntry = {
186
+ id: 'join-user-1-0',
187
+ type: 'join',
188
+ userId: 'user-1',
189
+ displayName: 'Alice',
190
+ avatarUrl: null,
191
+ timestamp: '10:00',
192
+ };
193
+ it('空のログに新しいエントリを追加する', () => {
194
+ const result = mergeLogs([], baseEntry, 20);
195
+ expect(result).toHaveLength(1);
196
+ expect(result[0]).toEqual(baseEntry);
197
+ });
198
+ it('重複するIDのエントリは追加しない(冪等性)', () => {
199
+ const existingLogs = [baseEntry];
200
+ const result = mergeLogs(existingLogs, baseEntry, 20);
201
+ expect(result).toHaveLength(1);
202
+ expect(result).toBe(existingLogs); // 同じ参照を返す
203
+ });
204
+ it('異なるIDのエントリは追加する', () => {
205
+ const existingLogs = [baseEntry];
206
+ const newEntry = {
207
+ ...baseEntry,
208
+ id: 'leave-user-1-0',
209
+ type: 'leave',
210
+ };
211
+ const result = mergeLogs(existingLogs, newEntry, 20);
212
+ expect(result).toHaveLength(2);
213
+ });
214
+ it('maxEntries を超えた場合は古いエントリを削除する', () => {
215
+ const existingLogs = [
216
+ { ...baseEntry, id: 'join-user-1-0' },
217
+ { ...baseEntry, id: 'join-user-2-0', userId: 'user-2' },
218
+ { ...baseEntry, id: 'join-user-3-0', userId: 'user-3' },
219
+ ];
220
+ const newEntry = {
221
+ ...baseEntry,
222
+ id: 'join-user-4-0',
223
+ userId: 'user-4',
224
+ };
225
+ const result = mergeLogs(existingLogs, newEntry, 3);
226
+ expect(result).toHaveLength(3);
227
+ expect(result[0].id).toBe('join-user-2-0'); // 最も古いエントリが削除される
228
+ expect(result[2].id).toBe('join-user-4-0'); // 新しいエントリが末尾に追加
229
+ });
230
+ });
231
+ //# sourceMappingURL=utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../../../src/components/EntryLogBoard/__tests__/utils.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { type Euler, type Vector3 } from '@react-three/fiber';
2
+ interface Props {
3
+ avatarUrl: string | null;
4
+ size: number;
5
+ position?: Vector3;
6
+ rotation?: Euler;
7
+ }
8
+ export declare const AvatarIcon: ({ avatarUrl, size, position, rotation }: Props) => import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=AvatarIcon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AvatarIcon.d.ts","sourceRoot":"","sources":["../../../../src/components/EntryLogBoard/components/AvatarIcon.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAE7D,UAAU,KAAK;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAA;CACjB;AA6BD,eAAO,MAAM,UAAU,GAAI,yCAAyC,KAAK,4CAexE,CAAA"}
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * AvatarIcon コンポーネント
4
+ *
5
+ * ログ行のアバターアイコンを表示する。
6
+ * 画像URLがある場合はテクスチャ、ない場合はプレースホルダー円を表示。
7
+ */
8
+ import { useTexture } from '@react-three/drei';
9
+ const AvatarPlaceholder = ({ size, position, rotation, }) => (_jsxs("mesh", { position: position, rotation: rotation, children: [_jsx("circleGeometry", { args: [size / 2, 32] }), _jsx("meshBasicMaterial", { color: 0x666666 })] }));
10
+ const AvatarImage = ({ avatarUrl, size, position, rotation, }) => {
11
+ const texture = useTexture(avatarUrl);
12
+ return (_jsxs("mesh", { position: position, rotation: rotation, children: [_jsx("circleGeometry", { args: [size / 2, 32] }), _jsx("meshBasicMaterial", { map: texture })] }));
13
+ };
14
+ export const AvatarIcon = ({ avatarUrl, size, position, rotation }) => {
15
+ if (!avatarUrl) {
16
+ return (_jsx(AvatarPlaceholder, { size: size, position: position, rotation: rotation }));
17
+ }
18
+ return (_jsx(AvatarImage, { avatarUrl: avatarUrl, size: size, position: position, rotation: rotation }));
19
+ };
20
+ //# sourceMappingURL=AvatarIcon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AvatarIcon.js","sourceRoot":"","sources":["../../../../src/components/EntryLogBoard/components/AvatarIcon.tsx"],"names":[],"mappings":";AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAU9C,MAAM,iBAAiB,GAAG,CAAC,EACzB,IAAI,EACJ,QAAQ,EACR,QAAQ,GACiB,EAAE,EAAE,CAAC,CAC9B,gBAAM,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,aAC1C,yBAAgB,IAAI,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC,GAAI,EACxC,4BAAmB,KAAK,EAAE,QAAQ,GAAI,IACjC,CACR,CAAA;AAED,MAAM,WAAW,GAAG,CAAC,EACnB,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,QAAQ,GACsB,EAAE,EAAE;IAClC,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAA;IAErC,OAAO,CACL,gBAAM,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,aAC1C,yBAAgB,IAAI,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC,GAAI,EACxC,4BAAmB,GAAG,EAAE,OAAO,GAAI,IAC9B,CACR,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAS,EAAE,EAAE;IAC3E,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CACL,KAAC,iBAAiB,IAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,GAAI,CAC1E,CAAA;IACH,CAAC;IAED,OAAO,CACL,KAAC,WAAW,IACV,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,GAClB,CACH,CAAA;AACH,CAAC,CAAA"}
@@ -0,0 +1,12 @@
1
+ import { type Colors, type Labels, type LogEntry } from '../types';
2
+ interface Props {
3
+ entry: LogEntry;
4
+ labels: Labels;
5
+ colors: Colors;
6
+ y: number;
7
+ scale: number;
8
+ }
9
+ declare const ROW_HEIGHT = 0.25;
10
+ export declare const LogRow: ({ entry, labels, colors, y, scale }: Props) => import("react/jsx-runtime").JSX.Element;
11
+ export { ROW_HEIGHT };
12
+ //# sourceMappingURL=LogRow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LogRow.d.ts","sourceRoot":"","sources":["../../../../src/components/EntryLogBoard/components/LogRow.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGlE,UAAU,KAAK;IACb,KAAK,EAAE,QAAQ,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,CAAC,EAAE,MAAM,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;CACd;AAED,QAAA,MAAM,UAAU,OAAO,CAAA;AAIvB,eAAO,MAAM,MAAM,GAAI,qCAAqC,KAAK,4CAoDhE,CAAA;AAED,OAAO,EAAE,UAAU,EAAE,CAAA"}
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * LogRow コンポーネント
4
+ *
5
+ * 入退室ログの1行分を3D空間にレンダリングする。
6
+ * [アバター] [時刻] [名前] [ラベル]
7
+ */
8
+ import { Text } from '@react-three/drei';
9
+ import { AvatarIcon } from './AvatarIcon';
10
+ const ROW_HEIGHT = 0.25;
11
+ const AVATAR_SIZE = 0.18;
12
+ const FONT_SIZE = 0.1;
13
+ export const LogRow = ({ entry, labels, colors, y, scale }) => {
14
+ const rowHeight = ROW_HEIGHT * scale;
15
+ const avatarSize = AVATAR_SIZE * scale;
16
+ const fontSize = FONT_SIZE * scale;
17
+ const labelColor = entry.type === 'join' ? colors.join : colors.leave;
18
+ const labelText = entry.type === 'join' ? labels.join : labels.leave;
19
+ return (_jsxs("group", { position: [0, y, 0.01], children: [_jsx(AvatarIcon, { avatarUrl: entry.avatarUrl, size: avatarSize, position: [-0.9 * scale, 0, 0] }), _jsx(Text, { position: [-0.7 * scale, 0, 0], fontSize: fontSize * 0.8, color: 0x888888, anchorX: "left", anchorY: "middle", children: entry.timestamp }), _jsx(Text, { position: [-0.3 * scale, 0, 0], fontSize: fontSize, color: colors.text, anchorX: "left", anchorY: "middle", maxWidth: 0.8 * scale, children: entry.displayName }), _jsx(Text, { position: [0.55 * scale, 0, 0], fontSize: fontSize * 0.9, color: labelColor, anchorX: "left", anchorY: "middle", fontWeight: "bold", children: labelText })] }));
20
+ };
21
+ export { ROW_HEIGHT };
22
+ //# sourceMappingURL=LogRow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LogRow.js","sourceRoot":"","sources":["../../../../src/components/EntryLogBoard/components/LogRow.tsx"],"names":[],"mappings":";AAAA;;;;;GAKG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAGxC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAUzC,MAAM,UAAU,GAAG,IAAI,CAAA;AACvB,MAAM,WAAW,GAAG,IAAI,CAAA;AACxB,MAAM,SAAS,GAAG,GAAG,CAAA;AAErB,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAS,EAAE,EAAE;IACnE,MAAM,SAAS,GAAG,UAAU,GAAG,KAAK,CAAA;IACpC,MAAM,UAAU,GAAG,WAAW,GAAG,KAAK,CAAA;IACtC,MAAM,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAA;IAClC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAA;IACrE,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAA;IAEpE,OAAO,CACL,iBAAO,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,aAE3B,KAAC,UAAU,IACT,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,CAAC,CAAC,GAAG,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,GAC9B,EAGF,KAAC,IAAI,IACH,QAAQ,EAAE,CAAC,CAAC,GAAG,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,EAC9B,QAAQ,EAAE,QAAQ,GAAG,GAAG,EACxB,KAAK,EAAE,QAAQ,EACf,OAAO,EAAC,MAAM,EACd,OAAO,EAAC,QAAQ,YAEf,KAAK,CAAC,SAAS,GACX,EAGP,KAAC,IAAI,IACH,QAAQ,EAAE,CAAC,CAAC,GAAG,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,EAC9B,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,MAAM,CAAC,IAAI,EAClB,OAAO,EAAC,MAAM,EACd,OAAO,EAAC,QAAQ,EAChB,QAAQ,EAAE,GAAG,GAAG,KAAK,YAEpB,KAAK,CAAC,WAAW,GACb,EAGP,KAAC,IAAI,IACH,QAAQ,EAAE,CAAC,IAAI,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,EAC9B,QAAQ,EAAE,QAAQ,GAAG,GAAG,EACxB,KAAK,EAAE,UAAU,EACjB,OAAO,EAAC,MAAM,EACd,OAAO,EAAC,QAAQ,EAChB,UAAU,EAAC,MAAM,YAEhB,SAAS,GACL,IACD,CACT,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EAAE,UAAU,EAAE,CAAA"}
@@ -0,0 +1,9 @@
1
+ import { type Colors, type Labels, type LogEntry } from './types';
2
+ export declare const DEFAULT_STATE_NAMESPACE = "entry-log";
3
+ export declare const DEFAULT_MAX_ENTRIES = 10;
4
+ export declare const DEFAULT_DISPLAY_NAME_FALLBACK = "Unknown";
5
+ export declare const DEFAULT_LABELS: Labels;
6
+ export declare const DEFAULT_COLORS: Colors;
7
+ /** useInstanceState / useState の初期値(参照同一性を保証) */
8
+ export declare const DEFAULT_LOGS: LogEntry[];
9
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/components/EntryLogBoard/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEjE,eAAO,MAAM,uBAAuB,cAAc,CAAA;AAElD,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,eAAO,MAAM,6BAA6B,YAAY,CAAA;AAEtD,eAAO,MAAM,cAAc,EAAE,MAG5B,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,MAK5B,CAAA;AAED,iDAAiD;AACjD,eAAO,MAAM,YAAY,EAAE,QAAQ,EAAO,CAAA"}
@@ -0,0 +1,16 @@
1
+ export const DEFAULT_STATE_NAMESPACE = 'entry-log';
2
+ export const DEFAULT_MAX_ENTRIES = 10;
3
+ export const DEFAULT_DISPLAY_NAME_FALLBACK = 'Unknown';
4
+ export const DEFAULT_LABELS = {
5
+ join: '入室',
6
+ leave: '退室',
7
+ };
8
+ export const DEFAULT_COLORS = {
9
+ join: '#4CAF50',
10
+ leave: '#F44336',
11
+ background: '#1a1a2e',
12
+ text: '#ffffff',
13
+ };
14
+ /** useInstanceState / useState の初期値(参照同一性を保証) */
15
+ export const DEFAULT_LOGS = [];
16
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/components/EntryLogBoard/constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,uBAAuB,GAAG,WAAW,CAAA;AAElD,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAA;AAErC,MAAM,CAAC,MAAM,6BAA6B,GAAG,SAAS,CAAA;AAEtD,MAAM,CAAC,MAAM,cAAc,GAAW;IACpC,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,IAAI;CACZ,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAW;IACpC,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;IAChB,UAAU,EAAE,SAAS;IACrB,IAAI,EAAE,SAAS;CAChB,CAAA;AAED,iDAAiD;AACjD,MAAM,CAAC,MAAM,YAAY,GAAe,EAAE,CAAA"}
@@ -0,0 +1,12 @@
1
+ import { type LogEntry } from '../types';
2
+ interface UseEntryLogOptions {
3
+ stateNamespace: string;
4
+ maxEntries: number;
5
+ displayNameFallback: string;
6
+ formatTimestamp: (date: Date) => string;
7
+ onJoin?: (entry: LogEntry) => void;
8
+ onLeave?: (entry: LogEntry) => void;
9
+ }
10
+ export declare function useEntryLog(options: UseEntryLogOptions): LogEntry[];
11
+ export {};
12
+ //# sourceMappingURL=useEntryLog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useEntryLog.d.ts","sourceRoot":"","sources":["../../../../src/components/EntryLogBoard/hooks/useEntryLog.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,KAAK,QAAQ,EAGd,MAAM,UAAU,CAAA;AAGjB,UAAU,kBAAkB;IAC1B,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,eAAe,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAA;IACvC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAA;IAClC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAA;CACpC;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,QAAQ,EAAE,CA8InE"}
@@ -0,0 +1,108 @@
1
+ import { useEffect, useMemo, useRef } from 'react';
2
+ import { useUsers } from '../../../contexts/UsersContext';
3
+ import { useInstanceState } from '../../../hooks/useInstanceState';
4
+ import { useWorldEvent } from '../../../hooks/useWorldEvent';
5
+ import { DEFAULT_LOGS } from '../constants';
6
+ import { createLogEntry, enrichLogsWithCache, isWriterAmong, mergeLogs } from '../utils';
7
+ export function useEntryLog(options) {
8
+ const { localUser, remoteUsers } = useUsers();
9
+ const [logs, setLogs] = useInstanceState(`${options.stateNamespace}-logs`, DEFAULT_LOGS);
10
+ // logs の最新値を ref で保持(イベントコールバック内で参照)
11
+ const logsRef = useRef(logs);
12
+ logsRef.current = logs;
13
+ // options を ref で保持(stale closure 回避)
14
+ const optionsRef = useRef(options);
15
+ optionsRef.current = options;
16
+ // ユーザー情報キャッシュ(退室時に useUsers から消えている可能性があるため)
17
+ // レンダー本体で同期的に更新し、イベントコールバックより先にキャッシュを確定させる
18
+ const userCacheRef = useRef(new Map());
19
+ if (localUser) {
20
+ userCacheRef.current.set(localUser.id, {
21
+ displayName: localUser.displayName,
22
+ avatarUrl: localUser.avatarUrl,
23
+ });
24
+ }
25
+ for (const user of remoteUsers) {
26
+ userCacheRef.current.set(user.id, {
27
+ displayName: user.displayName,
28
+ avatarUrl: user.avatarUrl,
29
+ });
30
+ }
31
+ // 自分自身の入室ログ補完(最初のユーザーのみ)
32
+ // 他のユーザーがいる場合はライターが user-joined イベントで書いてくれるため、
33
+ // ここでは自分しかいない(=最初のユーザー)場合のみ自分の入室ログを追加する。
34
+ // 自分で書くと未同期のローカル状態で上書きしてしまうため。
35
+ const selfJoinedRef = useRef(false);
36
+ useEffect(() => {
37
+ if (!localUser || selfJoinedRef.current)
38
+ return;
39
+ selfJoinedRef.current = true;
40
+ const alreadyJoined = logsRef.current.some((log) => log.type === 'join' && log.userId === localUser.id);
41
+ if (alreadyJoined)
42
+ return;
43
+ // 他のユーザーがいる場合、ライターが user-joined で書くので自分では書かない
44
+ if (remoteUsers.length > 0)
45
+ return;
46
+ const opts = optionsRef.current;
47
+ const entry = createLogEntry('join', localUser.id, localUser.displayName, localUser.avatarUrl, logsRef.current, opts.formatTimestamp);
48
+ setLogs((prev) => mergeLogs(prev, entry, opts.maxEntries));
49
+ opts.onJoin?.(entry);
50
+ }, [localUser, setLogs]);
51
+ // user-joined イベント
52
+ // 入室者を除いた既存ユーザーの中で辞書順最小のクライアントだけが書き込む
53
+ useWorldEvent('user-joined', (data) => {
54
+ if (!localUser)
55
+ return;
56
+ const existingIds = [
57
+ localUser.id,
58
+ ...remoteUsers.filter((u) => u.id !== data.userId).map((u) => u.id),
59
+ ];
60
+ if (!isWriterAmong(existingIds, localUser.id))
61
+ return;
62
+ const opts = optionsRef.current;
63
+ const cached = userCacheRef.current.get(data.userId);
64
+ const entry = createLogEntry('join', data.userId, cached?.displayName ?? opts.displayNameFallback, cached?.avatarUrl ?? null, logsRef.current, opts.formatTimestamp);
65
+ setLogs((prev) => mergeLogs(prev, entry, opts.maxEntries));
66
+ opts.onJoin?.(entry);
67
+ });
68
+ // user-left イベント
69
+ // 退室者を除いた残存ユーザーの中で辞書順最小のクライアントだけが書き込む
70
+ useWorldEvent('user-left', (data) => {
71
+ if (!localUser)
72
+ return;
73
+ const remainingIds = [
74
+ localUser.id,
75
+ ...remoteUsers.filter((u) => u.id !== data.userId).map((u) => u.id),
76
+ ];
77
+ if (!isWriterAmong(remainingIds, localUser.id))
78
+ return;
79
+ const opts = optionsRef.current;
80
+ const cached = userCacheRef.current.get(data.userId);
81
+ const entry = createLogEntry('leave', data.userId, cached?.displayName ?? opts.displayNameFallback, cached?.avatarUrl ?? null, logsRef.current, opts.formatTimestamp);
82
+ setLogs((prev) => mergeLogs(prev, entry, opts.maxEntries));
83
+ opts.onLeave?.(entry);
84
+ });
85
+ // Unknown ログの永続修復(ライターのみ)
86
+ // user-joined 発火時に remoteUsers 未更新でキャッシュミスした Unknown エントリを、
87
+ // 次のレンダーでキャッシュが更新された後に修正する
88
+ useEffect(() => {
89
+ if (!localUser)
90
+ return;
91
+ const fallback = optionsRef.current.displayNameFallback;
92
+ const currentLogs = logsRef.current;
93
+ if (!currentLogs.some((log) => log.displayName === fallback))
94
+ return;
95
+ const allIds = [localUser.id, ...remoteUsers.map((u) => u.id)];
96
+ if (!isWriterAmong(allIds, localUser.id))
97
+ return;
98
+ const fixedLogs = enrichLogsWithCache(currentLogs, fallback, userCacheRef.current);
99
+ if (fixedLogs !== currentLogs) {
100
+ setLogs(fixedLogs);
101
+ }
102
+ }, [localUser, remoteUsers, setLogs]);
103
+ // Unknown ログをキャッシュで補完して返す(表示の即時修正)
104
+ // 永続修復が走る前でも表示上は正しい名前を出す
105
+ const cacheSize = userCacheRef.current.size;
106
+ return useMemo(() => enrichLogsWithCache(logs, options.displayNameFallback, userCacheRef.current), [logs, options.displayNameFallback, cacheSize]);
107
+ }
108
+ //# sourceMappingURL=useEntryLog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useEntryLog.js","sourceRoot":"","sources":["../../../../src/components/EntryLogBoard/hooks/useEntryLog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { type Props } from './types';
2
+ export type { Props as EntryLogBoardProps } from './types';
3
+ export declare const EntryLogBoard: ({ stateNamespace, maxEntries, formatTimestamp, displayNameFallback, labels: labelsOverride, colors: colorsOverride, position, rotation, scale, onJoin, onLeave, }: Props) => 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/EntryLogBoard/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAA4B,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAG9D,YAAY,EAAE,KAAK,IAAI,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAM1D,eAAO,MAAM,aAAa,GAAI,mKAY3B,KAAK,4CAuEP,CAAA"}
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * EntryLogBoard コンポーネント
4
+ *
5
+ * ワールドへの入退室ログを3D空間のボードに表示する。
6
+ * useWorldEvent でプラットフォームの user-joined / user-left イベントを受信し、
7
+ * useInstanceState でログを全クライアント間で同期する。
8
+ */
9
+ import { useMemo } from 'react';
10
+ import { Text } from '@react-three/drei';
11
+ import { LogRow, ROW_HEIGHT } from './components/LogRow';
12
+ import { DEFAULT_COLORS, DEFAULT_DISPLAY_NAME_FALLBACK, DEFAULT_LABELS, DEFAULT_MAX_ENTRIES, DEFAULT_STATE_NAMESPACE, } from './constants';
13
+ import { useEntryLog } from './hooks/useEntryLog';
14
+ import { defaultFormatTimestamp } from './utils';
15
+ const TITLE = '入退室ログ';
16
+ const BOARD_PADDING = 0.15;
17
+ const TITLE_HEIGHT = 0.35;
18
+ export const EntryLogBoard = ({ stateNamespace = DEFAULT_STATE_NAMESPACE, maxEntries = DEFAULT_MAX_ENTRIES, formatTimestamp = defaultFormatTimestamp, displayNameFallback = DEFAULT_DISPLAY_NAME_FALLBACK, labels: labelsOverride, colors: colorsOverride, position = [0, 0, 0], rotation = [0, 0, 0], scale = 1, onJoin, onLeave, }) => {
19
+ const labels = useMemo(() => ({ ...DEFAULT_LABELS, ...labelsOverride }), [labelsOverride]);
20
+ const colors = useMemo(() => ({ ...DEFAULT_COLORS, ...colorsOverride }), [colorsOverride]);
21
+ const logs = useEntryLog({
22
+ stateNamespace,
23
+ maxEntries,
24
+ displayNameFallback,
25
+ formatTimestamp,
26
+ onJoin,
27
+ onLeave,
28
+ });
29
+ // ボードサイズの計算
30
+ const rowHeight = ROW_HEIGHT * scale;
31
+ const boardWidth = 2.2 * scale;
32
+ const contentHeight = Math.max(maxEntries * rowHeight, rowHeight);
33
+ const boardHeight = contentHeight + TITLE_HEIGHT * scale + BOARD_PADDING * 2 * scale;
34
+ const titleY = boardHeight / 2 - TITLE_HEIGHT * scale / 2 - BOARD_PADDING * scale / 2;
35
+ // ログ行は上から新しい順に表示
36
+ const reversedLogs = useMemo(() => [...logs].reverse(), [logs]);
37
+ return (_jsxs("group", { position: position, rotation: rotation, children: [_jsxs("mesh", { position: [0, 0, -0.01], children: [_jsx("planeGeometry", { args: [boardWidth, boardHeight] }), _jsx("meshBasicMaterial", { color: colors.background, opacity: 0.9, transparent: true })] }), _jsx(Text, { position: [0, titleY, 0], fontSize: 0.16 * scale, color: colors.text, anchorX: "center", anchorY: "middle", fontWeight: "bold", children: TITLE }), reversedLogs.map((entry, index) => {
38
+ const y = titleY -
39
+ TITLE_HEIGHT * scale / 2 -
40
+ BOARD_PADDING * scale / 2 -
41
+ index * rowHeight -
42
+ rowHeight / 2;
43
+ return (_jsx(LogRow, { entry: entry, labels: labels, colors: colors, y: y, scale: scale }, entry.id));
44
+ })] }));
45
+ };
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/EntryLogBoard/index.tsx"],"names":[],"mappings":";AAAA;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAExC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EACL,cAAc,EACd,6BAA6B,EAC7B,cAAc,EACd,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAIhD,MAAM,KAAK,GAAG,OAAO,CAAA;AACrB,MAAM,aAAa,GAAG,IAAI,CAAA;AAC1B,MAAM,YAAY,GAAG,IAAI,CAAA;AAEzB,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAC5B,cAAc,GAAG,uBAAuB,EACxC,UAAU,GAAG,mBAAmB,EAChC,eAAe,GAAG,sBAAsB,EACxC,mBAAmB,GAAG,6BAA6B,EACnD,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc,EACtB,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACpB,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACpB,KAAK,GAAG,CAAC,EACT,MAAM,EACN,OAAO,GACD,EAAE,EAAE;IACV,MAAM,MAAM,GAAW,OAAO,CAC5B,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE,CAAC,EAChD,CAAC,cAAc,CAAC,CACjB,CAAA;IACD,MAAM,MAAM,GAAW,OAAO,CAC5B,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE,CAAC,EAChD,CAAC,cAAc,CAAC,CACjB,CAAA;IAED,MAAM,IAAI,GAAG,WAAW,CAAC;QACvB,cAAc;QACd,UAAU;QACV,mBAAmB;QACnB,eAAe;QACf,MAAM;QACN,OAAO;KACR,CAAC,CAAA;IAEF,YAAY;IACZ,MAAM,SAAS,GAAG,UAAU,GAAG,KAAK,CAAA;IACpC,MAAM,UAAU,GAAG,GAAG,GAAG,KAAK,CAAA;IAC9B,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,SAAS,EAAE,SAAS,CAAC,CAAA;IACjE,MAAM,WAAW,GAAG,aAAa,GAAG,YAAY,GAAG,KAAK,GAAG,aAAa,GAAG,CAAC,GAAG,KAAK,CAAA;IACpF,MAAM,MAAM,GAAG,WAAW,GAAG,CAAC,GAAG,YAAY,GAAG,KAAK,GAAG,CAAC,GAAG,aAAa,GAAG,KAAK,GAAG,CAAC,CAAA;IAErF,iBAAiB;IACjB,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;IAE/D,OAAO,CACL,iBAAO,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,aAE3C,gBAAM,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,aAC3B,wBAAe,IAAI,EAAE,CAAC,UAAU,EAAE,WAAW,CAAC,GAAI,EAClD,4BAAmB,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,SAAG,IACpE,EAGP,KAAC,IAAI,IACH,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EACxB,QAAQ,EAAE,IAAI,GAAG,KAAK,EACtB,KAAK,EAAE,MAAM,CAAC,IAAI,EAClB,OAAO,EAAC,QAAQ,EAChB,OAAO,EAAC,QAAQ,EAChB,UAAU,EAAC,MAAM,YAEhB,KAAK,GACD,EAGN,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;gBACjC,MAAM,CAAC,GACL,MAAM;oBACN,YAAY,GAAG,KAAK,GAAG,CAAC;oBACxB,aAAa,GAAG,KAAK,GAAG,CAAC;oBACzB,KAAK,GAAG,SAAS;oBACjB,SAAS,GAAG,CAAC,CAAA;gBAEf,OAAO,CACL,KAAC,MAAM,IAEL,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,CAAC,EACJ,KAAK,EAAE,KAAK,IALP,KAAK,CAAC,EAAE,CAMb,CACH,CAAA;YACH,CAAC,CAAC,IACI,CACT,CAAA;AACH,CAAC,CAAA"}
@@ -0,0 +1,70 @@
1
+ /** ログエントリの種別 */
2
+ export type LogType = 'join' | 'leave';
3
+ /** 入退室ログの1件分 */
4
+ export interface LogEntry {
5
+ /** 決定論的に生成されるID(冪等なマージ用) */
6
+ id: string;
7
+ /** ログ種別 */
8
+ type: LogType;
9
+ /** ユーザーID */
10
+ userId: string;
11
+ /** 表示名 */
12
+ displayName: string;
13
+ /** アバターアイコンURL */
14
+ avatarUrl: string | null;
15
+ /** フォーマット済みタイムスタンプ */
16
+ timestamp: string;
17
+ }
18
+ /** ラベル文言のカスタマイズ */
19
+ export interface Labels {
20
+ /** 入室時のラベル */
21
+ join: string;
22
+ /** 退室時のラベル */
23
+ leave: string;
24
+ }
25
+ /** 色のカスタマイズ */
26
+ export interface Colors {
27
+ /** 入室ログの色 */
28
+ join: string;
29
+ /** 退室ログの色 */
30
+ leave: string;
31
+ /** ボード背景色 */
32
+ background: string;
33
+ /** テキスト色 */
34
+ text: string;
35
+ }
36
+ /** user-joined イベントのデータ型 */
37
+ export interface UserJoinedEvent {
38
+ userId: string;
39
+ isGuest: boolean;
40
+ }
41
+ /** user-left イベントのデータ型 */
42
+ export interface UserLeftEvent {
43
+ userId: string;
44
+ }
45
+ /** EntryLogBoard のプロパティ */
46
+ export interface Props {
47
+ /** インスタンス状態のキー(複数ボード設置時の識別用) */
48
+ stateNamespace?: string;
49
+ /** 最大表示件数 */
50
+ maxEntries?: number;
51
+ /** タイムスタンプのフォーマット関数 */
52
+ formatTimestamp?: (date: Date) => string;
53
+ /** 表示名が取得できない場合のフォールバック */
54
+ displayNameFallback?: string;
55
+ /** ラベル文言 */
56
+ labels?: Partial<Labels>;
57
+ /** 色設定 */
58
+ colors?: Partial<Colors>;
59
+ /** ボードの位置 */
60
+ position?: [number, number, number];
61
+ /** ボードの回転 */
62
+ rotation?: [number, number, number];
63
+ /** 全体スケール */
64
+ scale?: number;
65
+ /** 入室時のコールバック */
66
+ onJoin?: (entry: LogEntry) => void;
67
+ /** 退室時のコールバック */
68
+ onLeave?: (entry: LogEntry) => void;
69
+ }
70
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/EntryLogBoard/types.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAChB,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,OAAO,CAAA;AAEtC,gBAAgB;AAChB,MAAM,WAAW,QAAQ;IACvB,4BAA4B;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,WAAW;IACX,IAAI,EAAE,OAAO,CAAA;IACb,aAAa;IACb,MAAM,EAAE,MAAM,CAAA;IACd,UAAU;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,kBAAkB;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,sBAAsB;IACtB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,mBAAmB;AACnB,MAAM,WAAW,MAAM;IACrB,cAAc;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,cAAc;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAED,eAAe;AACf,MAAM,WAAW,MAAM;IACrB,aAAa;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa;IACb,KAAK,EAAE,MAAM,CAAA;IACb,aAAa;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,4BAA4B;AAC5B,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,0BAA0B;AAC1B,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;CACf;AAED,2BAA2B;AAC3B,MAAM,WAAW,KAAK;IACpB,gCAAgC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,aAAa;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,uBAAuB;IACvB,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAA;IACxC,2BAA2B;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,YAAY;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IACxB,UAAU;IACV,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IACxB,aAAa;IACb,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,aAAa;IACb,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,aAAa;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iBAAiB;IACjB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAA;IAClC,iBAAiB;IACjB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAA;CACpC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/components/EntryLogBoard/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,46 @@
1
+ import { type LogEntry, type LogType } from './types';
2
+ /**
3
+ * デフォルトのタイムスタンプフォーマット(HH:MM 形式)
4
+ */
5
+ export declare const defaultFormatTimestamp: (date: Date) => string;
6
+ /**
7
+ * 決定論的なログエントリIDを生成する
8
+ *
9
+ * 全クライアントが同じ既存ログから同じIDを計算するため、
10
+ * リーダー選出なしで冪等なマージが可能になる。
11
+ *
12
+ * @param type ログ種別(join / leave)
13
+ * @param userId ユーザーID
14
+ * @param existingLogs 既存のログエントリ一覧
15
+ * @returns 決定論的ID(例: "join-user123-2")
16
+ */
17
+ export declare const buildLogEntryId: (type: LogType, userId: string, existingLogs: LogEntry[]) => string;
18
+ /**
19
+ * ログエントリを生成する
20
+ */
21
+ export declare const createLogEntry: (type: LogType, userId: string, displayName: string, avatarUrl: string | null, existingLogs: LogEntry[], formatTimestamp: (date: Date) => string) => LogEntry;
22
+ /**
23
+ * 候補ID群の中で辞書順最小のIDがtargetIdと一致するかを判定する
24
+ *
25
+ * 暗黙的ライター選出に使用。全クライアントが同じ候補群を持つため、
26
+ * 辞書順最小のクライアントだけが書き込みを行う。
27
+ */
28
+ export declare const isWriterAmong: (candidateIds: (string | undefined)[], targetId: string | undefined) => boolean;
29
+ /**
30
+ * ログ内の Unknown 表示名をキャッシュで補完する
31
+ *
32
+ * user-joined イベント発火時にまだ remoteUsers が更新されておらず
33
+ * キャッシュミスで Unknown になったエントリを、後から修復する。
34
+ * 変更がなければ元の配列をそのまま返す(参照同一性を維持)。
35
+ */
36
+ export declare const enrichLogsWithCache: (logs: LogEntry[], fallbackName: string, cache: Map<string, {
37
+ displayName: string;
38
+ avatarUrl: string | null;
39
+ }>) => LogEntry[];
40
+ /**
41
+ * 既存ログに新しいエントリをマージする(重複排除・件数制限)
42
+ *
43
+ * 同じIDのエントリが既に存在する場合は追加しない(冪等性)。
44
+ */
45
+ export declare const mergeLogs: (existingLogs: LogEntry[], newEntry: LogEntry, maxEntries: number) => LogEntry[];
46
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/components/EntryLogBoard/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,OAAO,EAAE,MAAM,SAAS,CAAA;AAErD;;GAEG;AACH,eAAO,MAAM,sBAAsB,GAAI,MAAM,IAAI,KAAG,MAInD,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,GAC1B,MAAM,OAAO,EACb,QAAQ,MAAM,EACd,cAAc,QAAQ,EAAE,KACvB,MAKF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,OAAO,EACb,QAAQ,MAAM,EACd,aAAa,MAAM,EACnB,WAAW,MAAM,GAAG,IAAI,EACxB,cAAc,QAAQ,EAAE,EACxB,iBAAiB,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,KACtC,QAOD,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,cAAc,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,EACpC,UAAU,MAAM,GAAG,SAAS,KAC3B,OAIF,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAC9B,MAAM,QAAQ,EAAE,EAChB,cAAc,MAAM,EACpB,OAAO,GAAG,CAAC,MAAM,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,KACpE,QAAQ,EAeV,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS,GACpB,cAAc,QAAQ,EAAE,EACxB,UAAU,QAAQ,EAClB,YAAY,MAAM,KACjB,QAAQ,EAGV,CAAA"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * デフォルトのタイムスタンプフォーマット(HH:MM 形式)
3
+ */
4
+ export const defaultFormatTimestamp = (date) => {
5
+ const hours = date.getHours().toString().padStart(2, '0');
6
+ const minutes = date.getMinutes().toString().padStart(2, '0');
7
+ return `${hours}:${minutes}`;
8
+ };
9
+ /**
10
+ * 決定論的なログエントリIDを生成する
11
+ *
12
+ * 全クライアントが同じ既存ログから同じIDを計算するため、
13
+ * リーダー選出なしで冪等なマージが可能になる。
14
+ *
15
+ * @param type ログ種別(join / leave)
16
+ * @param userId ユーザーID
17
+ * @param existingLogs 既存のログエントリ一覧
18
+ * @returns 決定論的ID(例: "join-user123-2")
19
+ */
20
+ export const buildLogEntryId = (type, userId, existingLogs) => {
21
+ const sameTypeCount = existingLogs.filter((log) => log.type === type && log.userId === userId).length;
22
+ return `${type}-${userId}-${sameTypeCount}`;
23
+ };
24
+ /**
25
+ * ログエントリを生成する
26
+ */
27
+ export const createLogEntry = (type, userId, displayName, avatarUrl, existingLogs, formatTimestamp) => ({
28
+ id: buildLogEntryId(type, userId, existingLogs),
29
+ type,
30
+ userId,
31
+ displayName,
32
+ avatarUrl,
33
+ timestamp: formatTimestamp(new Date()),
34
+ });
35
+ /**
36
+ * 候補ID群の中で辞書順最小のIDがtargetIdと一致するかを判定する
37
+ *
38
+ * 暗黙的ライター選出に使用。全クライアントが同じ候補群を持つため、
39
+ * 辞書順最小のクライアントだけが書き込みを行う。
40
+ */
41
+ export const isWriterAmong = (candidateIds, targetId) => {
42
+ if (!targetId)
43
+ return false;
44
+ const sorted = candidateIds.filter((id) => id != null).sort();
45
+ return sorted.length > 0 && sorted[0] === targetId;
46
+ };
47
+ /**
48
+ * ログ内の Unknown 表示名をキャッシュで補完する
49
+ *
50
+ * user-joined イベント発火時にまだ remoteUsers が更新されておらず
51
+ * キャッシュミスで Unknown になったエントリを、後から修復する。
52
+ * 変更がなければ元の配列をそのまま返す(参照同一性を維持)。
53
+ */
54
+ export const enrichLogsWithCache = (logs, fallbackName, cache) => {
55
+ let needsEnrich = false;
56
+ for (const log of logs) {
57
+ if (log.displayName === fallbackName && cache.has(log.userId)) {
58
+ needsEnrich = true;
59
+ break;
60
+ }
61
+ }
62
+ if (!needsEnrich)
63
+ return logs;
64
+ return logs.map((log) => {
65
+ if (log.displayName !== fallbackName)
66
+ return log;
67
+ const cached = cache.get(log.userId);
68
+ if (!cached)
69
+ return log;
70
+ return { ...log, displayName: cached.displayName, avatarUrl: cached.avatarUrl };
71
+ });
72
+ };
73
+ /**
74
+ * 既存ログに新しいエントリをマージする(重複排除・件数制限)
75
+ *
76
+ * 同じIDのエントリが既に存在する場合は追加しない(冪等性)。
77
+ */
78
+ export const mergeLogs = (existingLogs, newEntry, maxEntries) => {
79
+ if (existingLogs.some((log) => log.id === newEntry.id))
80
+ return existingLogs;
81
+ return [...existingLogs, newEntry].slice(-maxEntries);
82
+ };
83
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/components/EntryLogBoard/utils.ts"],"names":[],"mappings":"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"}
@@ -19,7 +19,7 @@ import { DoubleSide, Vector3 } from "three";
19
19
  import { useInstanceState } from "../../../../hooks/useInstanceState";
20
20
  import { TagChip } from "../TagChip";
21
21
  import { calculateLayout, getSelectedTags, groupTagsByColumn, } from "./utils";
22
- const HEAD_OFFSET_Y = 1.6;
22
+ const HEAD_OFFSET_Y = 2.6;
23
23
  export const TagDisplay = ({ userId, getMovement, tags, visible, instanceStateKey, }) => {
24
24
  const groupRef = useRef(null);
25
25
  const stateKey = `tag-${instanceStateKey}-${userId}`;
package/dist/index.d.ts CHANGED
@@ -17,6 +17,7 @@ export { TextInput, type TextInputProps, } from './components/TextInput';
17
17
  export { TagBoard, type TagBoardProps, type Tag, } from './components/TagBoard';
18
18
  export { Video180Sphere, type Video180SphereProps, } from './components/Video180Sphere';
19
19
  export { DevEnvironment, type DevEnvironmentProps, } from './components/DevEnvironment';
20
+ export { EntryLogBoard, type EntryLogBoardProps, } from './components/EntryLogBoard';
20
21
  export { type PhysicsConfig } from './components/DevEnvironment/types';
21
22
  export { useInstanceState } from './hooks/useInstanceState';
22
23
  export { useSpawnPoint } from './hooks/useSpawnPoint';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,KAAK,iBAAiB,GACvB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,KAAK,yBAAyB,GAC/B,MAAM,iCAAiC,CAAA;AAExC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,+BAA+B,CAAA;AAEtC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,UAAU,IAAI,cAAc,EACjC,KAAK,sBAAsB,GAC5B,MAAM,8BAA8B,CAAA;AAErC,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,KAAK,IAAI,EACT,KAAK,iBAAiB,GACvB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,oCAAoC,EACpC,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,GACtB,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,qCAAqC,EACrC,KAAK,sBAAsB,GAC5B,MAAM,8BAA8B,CAAA;AAGrC,OAAO,EACL,YAAY,EACZ,KAAK,iBAAiB,GACvB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,UAAU,GAChB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAE7E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAE9D,OAAO,EACL,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,iCAAiC,CAAA;AAExC,OAAO,EACL,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,SAAS,EACT,KAAK,cAAc,GACpB,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EACL,QAAQ,EACR,KAAK,aAAa,EAClB,KAAK,GAAG,GACT,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,cAAc,EACd,KAAK,mBAAmB,GACzB,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,cAAc,EACd,KAAK,mBAAmB,GACzB,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,mCAAmC,CAAA;AAGtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAGrD,OAAO,EAAE,MAAM,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAG7E,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,mBAAmB,GACzB,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,KAAK,iBAAiB,GACvB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,KAAK,yBAAyB,GAC/B,MAAM,iCAAiC,CAAA;AAExC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,+BAA+B,CAAA;AAEtC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,UAAU,IAAI,cAAc,EACjC,KAAK,sBAAsB,GAC5B,MAAM,8BAA8B,CAAA;AAErC,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,KAAK,IAAI,EACT,KAAK,iBAAiB,GACvB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,oCAAoC,EACpC,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,GACtB,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,qCAAqC,EACrC,KAAK,sBAAsB,GAC5B,MAAM,8BAA8B,CAAA;AAGrC,OAAO,EACL,YAAY,EACZ,KAAK,iBAAiB,GACvB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,UAAU,GAChB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAE7E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAE9D,OAAO,EACL,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,iCAAiC,CAAA;AAExC,OAAO,EACL,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,SAAS,EACT,KAAK,cAAc,GACpB,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EACL,QAAQ,EACR,KAAK,aAAa,EAClB,KAAK,GAAG,GACT,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,cAAc,EACd,KAAK,mBAAmB,GACzB,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,cAAc,EACd,KAAK,mBAAmB,GACzB,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,GACxB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,mCAAmC,CAAA;AAGtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAGrD,OAAO,EAAE,MAAM,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAG7E,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,mBAAmB,GACzB,MAAM,kBAAkB,CAAA"}
package/dist/index.js CHANGED
@@ -19,6 +19,7 @@ export { TextInput, } from './components/TextInput';
19
19
  export { TagBoard, } from './components/TagBoard';
20
20
  export { Video180Sphere, } from './components/Video180Sphere';
21
21
  export { DevEnvironment, } from './components/DevEnvironment';
22
+ export { EntryLogBoard, } from './components/EntryLogBoard';
22
23
  // Hooks
23
24
  export { useInstanceState } from './hooks/useInstanceState';
24
25
  export { useSpawnPoint } from './hooks/useSpawnPoint';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,GAET,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,GAExB,MAAM,iCAAiC,CAAA;AAExC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,GAEtB,MAAM,+BAA+B,CAAA;AAEtC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,GAGrB,MAAM,8BAA8B,CAAA;AAErC,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,GAGT,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,oCAAoC,GAGrC,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,qCAAqC,GAEtC,MAAM,8BAA8B,CAAA;AAErC,aAAa;AACb,OAAO,EACL,YAAY,GAEb,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EACL,WAAW,GAGZ,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAE,WAAW,EAAyB,MAAM,0BAA0B,CAAA;AAE7E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAE9D,OAAO,EACL,kBAAkB,GAEnB,MAAM,iCAAiC,CAAA;AAExC,OAAO,EACL,UAAU,GAEX,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,SAAS,GAEV,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EACL,QAAQ,GAGT,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,cAAc,GAEf,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,cAAc,GAEf,MAAM,6BAA6B,CAAA;AAIpC,QAAQ;AACR,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAErD,YAAY;AACZ,OAAO,EAAE,MAAM,EAAoC,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,GAET,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,GAExB,MAAM,iCAAiC,CAAA;AAExC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,GAEtB,MAAM,+BAA+B,CAAA;AAEtC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,GAGrB,MAAM,8BAA8B,CAAA;AAErC,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,GAGT,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,oCAAoC,GAGrC,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,qCAAqC,GAEtC,MAAM,8BAA8B,CAAA;AAErC,aAAa;AACb,OAAO,EACL,YAAY,GAEb,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EACL,WAAW,GAGZ,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAE,WAAW,EAAyB,MAAM,0BAA0B,CAAA;AAE7E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAE9D,OAAO,EACL,kBAAkB,GAEnB,MAAM,iCAAiC,CAAA;AAExC,OAAO,EACL,UAAU,GAEX,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,SAAS,GAEV,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EACL,QAAQ,GAGT,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,cAAc,GAEf,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,cAAc,GAEf,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EACL,aAAa,GAEd,MAAM,4BAA4B,CAAA;AAInC,QAAQ;AACR,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAErD,YAAY;AACZ,OAAO,EAAE,MAAM,EAAoC,MAAM,oBAAoB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xrift/world-components",
3
- "version": "0.24.0",
3
+ "version": "0.25.1",
4
4
  "description": "Shared components and utilities for Xrift worlds",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",