@buley/hexgrid-3d 1.0.0 → 1.1.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 (58) hide show
  1. package/build_log.txt +500 -0
  2. package/build_src_log.txt +8 -0
  3. package/examples/basic-usage.tsx +19 -19
  4. package/package.json +1 -1
  5. package/public/hexgrid-worker.js +2350 -1638
  6. package/site/.eslintrc.json +3 -0
  7. package/site/DEPLOYMENT.md +196 -0
  8. package/site/INDEX.md +127 -0
  9. package/site/QUICK_START.md +86 -0
  10. package/site/README.md +85 -0
  11. package/site/SITE_SUMMARY.md +180 -0
  12. package/site/next.config.js +12 -0
  13. package/site/package.json +26 -0
  14. package/site/src/app/docs/page.tsx +148 -0
  15. package/site/src/app/examples/page.tsx +133 -0
  16. package/site/src/app/globals.css +160 -0
  17. package/site/src/app/layout.tsx +29 -0
  18. package/site/src/app/page.tsx +163 -0
  19. package/site/tsconfig.json +29 -0
  20. package/site/vercel.json +6 -0
  21. package/src/Snapshot.ts +790 -585
  22. package/src/adapters/DashAdapter.ts +57 -0
  23. package/src/adapters.ts +16 -18
  24. package/src/algorithms/AdvancedStatistics.ts +58 -24
  25. package/src/algorithms/BayesianStatistics.ts +43 -12
  26. package/src/algorithms/FlowField.ts +30 -6
  27. package/src/algorithms/FlowField3D.ts +573 -0
  28. package/src/algorithms/FluidSimulation.ts +19 -3
  29. package/src/algorithms/FluidSimulation3D.ts +664 -0
  30. package/src/algorithms/GraphAlgorithms.ts +19 -12
  31. package/src/algorithms/OutlierDetection.ts +72 -38
  32. package/src/algorithms/ParticleSystem.ts +12 -2
  33. package/src/algorithms/ParticleSystem3D.ts +567 -0
  34. package/src/algorithms/index.ts +14 -8
  35. package/src/compat.ts +10 -10
  36. package/src/components/HexGrid.tsx +10 -23
  37. package/src/components/NarrationOverlay.tsx +140 -52
  38. package/src/components/index.ts +2 -1
  39. package/src/features.ts +31 -31
  40. package/src/index.ts +11 -11
  41. package/src/lib/narration.ts +17 -0
  42. package/src/lib/stats-tracker.ts +25 -0
  43. package/src/lib/theme-colors.ts +12 -0
  44. package/src/math/HexCoordinates.ts +849 -4
  45. package/src/math/Matrix4.ts +2 -12
  46. package/src/math/Vector3.ts +49 -1
  47. package/src/math/index.ts +6 -6
  48. package/src/note-adapter.ts +50 -42
  49. package/src/ontology-adapter.ts +30 -23
  50. package/src/stores/uiStore.ts +34 -34
  51. package/src/types/shared-utils.d.ts +10 -0
  52. package/src/types.ts +110 -98
  53. package/src/utils/image-utils.ts +9 -6
  54. package/src/wasm/HexGridWasmWrapper.ts +436 -388
  55. package/src/wasm/index.ts +2 -2
  56. package/src/workers/hexgrid-math.ts +40 -35
  57. package/src/workers/hexgrid-worker.worker.ts +1992 -1018
  58. package/tsconfig.json +21 -14
@@ -1,43 +1,44 @@
1
1
  /**
2
2
  * Narration Overlay Component
3
- *
3
+ *
4
4
  * Displays play-by-play narration messages with sparklines in a NOC dashboard style.
5
5
  */
6
6
 
7
- import React, { useEffect, useRef } from 'react'
8
- import { NarrationMessage } from '@/lib/narration'
9
- import { StatsTracker } from '@/lib/stats-tracker'
10
- import { getAccentRgba, getAccentHex } from '@/lib/theme-colors'
7
+ import React, { useEffect, useRef } from 'react';
8
+ import { NarrationMessage } from '@/lib/narration';
9
+ import { StatsTracker } from '@/lib/stats-tracker';
10
+ import { getAccentRgba, getAccentHex } from '@/lib/theme-colors';
11
11
 
12
12
  export interface NarrationOverlayProps {
13
- messages: NarrationMessage[]
14
- statsTracker: StatsTracker | null
15
- isVisible: boolean
16
- onClose: () => void
13
+ messages: NarrationMessage[];
14
+ statsTracker: StatsTracker | null;
15
+ isVisible: boolean;
16
+ onClose: () => void;
17
17
  }
18
18
 
19
19
  export const NarrationOverlay: React.FC<NarrationOverlayProps> = ({
20
20
  messages,
21
21
  statsTracker,
22
22
  isVisible,
23
- onClose
23
+ onClose,
24
24
  }) => {
25
- const messagesEndRef = useRef<HTMLDivElement>(null)
26
- const scrollContainerRef = useRef<HTMLDivElement>(null)
25
+ const messagesEndRef = useRef<HTMLDivElement>(null);
26
+ const scrollContainerRef = useRef<HTMLDivElement>(null);
27
27
 
28
28
  // Auto-scroll to latest message
29
29
  useEffect(() => {
30
30
  if (messagesEndRef.current && scrollContainerRef.current) {
31
- scrollContainerRef.current.scrollTop = scrollContainerRef.current.scrollHeight
31
+ scrollContainerRef.current.scrollTop =
32
+ scrollContainerRef.current.scrollHeight;
32
33
  }
33
- }, [messages])
34
+ }, [messages]);
34
35
 
35
36
  // Always render the overlay so fade-out can animate smoothly.
36
37
  // Toggle visibility via styles.
37
38
 
38
- const currentStats = statsTracker?.getCurrentStats()
39
- const allTimeRecords = statsTracker?.getAllTimeRecords()
40
- const leaderboard = statsTracker?.getLeaderboard(10)
39
+ const currentStats = statsTracker?.getCurrentStats();
40
+ const allTimeRecords = statsTracker?.getAllTimeRecords();
41
+ const leaderboard = statsTracker?.getLeaderboard(10);
41
42
 
42
43
  return (
43
44
  <div
@@ -62,12 +63,21 @@ export const NarrationOverlay: React.FC<NarrationOverlayProps> = ({
62
63
  transition: 'opacity 220ms ease, transform 220ms ease',
63
64
  opacity: isVisible ? 1 : 0,
64
65
  transform: isVisible ? 'translateY(0px)' : 'translateY(-6px)',
65
- pointerEvents: isVisible ? 'auto' as const : 'none' as const
66
+ pointerEvents: isVisible ? ('auto' as const) : ('none' as const),
66
67
  }}
67
68
  >
68
69
  {/* Header */}
69
- <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
70
- <div style={{ fontWeight: 'bold', fontSize: 14 }}>Play-by-Play Narration</div>
70
+ <div
71
+ style={{
72
+ display: 'flex',
73
+ justifyContent: 'space-between',
74
+ alignItems: 'center',
75
+ marginBottom: 8,
76
+ }}
77
+ >
78
+ <div style={{ fontWeight: 'bold', fontSize: 14 }}>
79
+ Play-by-Play Narration
80
+ </div>
71
81
  <button
72
82
  onClick={onClose}
73
83
  style={{
@@ -77,7 +87,7 @@ export const NarrationOverlay: React.FC<NarrationOverlayProps> = ({
77
87
  cursor: 'pointer',
78
88
  padding: '4px 8px',
79
89
  borderRadius: 4,
80
- fontSize: 11
90
+ fontSize: 11,
81
91
  }}
82
92
  >
83
93
  ×
@@ -87,31 +97,79 @@ export const NarrationOverlay: React.FC<NarrationOverlayProps> = ({
87
97
  {/* Stats Dashboard (Collapsible) */}
88
98
  {currentStats && (
89
99
  <details style={{ marginBottom: 8, fontSize: 11 }}>
90
- <summary style={{ cursor: 'pointer', color: '#00ffff', marginBottom: 4 }}>
100
+ <summary
101
+ style={{ cursor: 'pointer', color: '#00ffff', marginBottom: 4 }}
102
+ >
91
103
  Stats Dashboard
92
104
  </summary>
93
- <div style={{ padding: '8px', background: 'rgba(0, 255, 255, 0.05)', borderRadius: 4 }}>
94
- <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
105
+ <div
106
+ style={{
107
+ padding: '8px',
108
+ background: 'rgba(0, 255, 255, 0.05)',
109
+ borderRadius: 4,
110
+ }}
111
+ >
112
+ <div
113
+ style={{
114
+ display: 'flex',
115
+ justifyContent: 'space-between',
116
+ marginBottom: 4,
117
+ }}
118
+ >
95
119
  <span>Generation:</span>
96
- <span style={{ fontVariantNumeric: 'tabular-nums' }}>{currentStats.generation}</span>
120
+ <span style={{ fontVariantNumeric: 'tabular-nums' }}>
121
+ {currentStats.generation}
122
+ </span>
97
123
  </div>
98
- <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
124
+ <div
125
+ style={{
126
+ display: 'flex',
127
+ justifyContent: 'space-between',
128
+ marginBottom: 4,
129
+ }}
130
+ >
99
131
  <span>Active Memes:</span>
100
- <span style={{ fontVariantNumeric: 'tabular-nums' }}>{currentStats.activeMemesCount}</span>
132
+ <span style={{ fontVariantNumeric: 'tabular-nums' }}>
133
+ {currentStats.activeMemesCount}
134
+ </span>
101
135
  </div>
102
- <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
136
+ <div
137
+ style={{
138
+ display: 'flex',
139
+ justifyContent: 'space-between',
140
+ marginBottom: 4,
141
+ }}
142
+ >
103
143
  <span>Total Hexes:</span>
104
- <span style={{ fontVariantNumeric: 'tabular-nums' }}>{currentStats.totalHexesInfected}</span>
144
+ <span style={{ fontVariantNumeric: 'tabular-nums' }}>
145
+ {currentStats.totalHexesInfected}
146
+ </span>
105
147
  </div>
106
- <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
148
+ <div
149
+ style={{
150
+ display: 'flex',
151
+ justifyContent: 'space-between',
152
+ marginBottom: 4,
153
+ }}
154
+ >
107
155
  <span>Birth/Death Ratio:</span>
108
156
  <span style={{ fontVariantNumeric: 'tabular-nums' }}>
109
157
  {currentStats.populationStability.toFixed(2)}
110
158
  </span>
111
159
  </div>
112
160
  {allTimeRecords && (
113
- <div style={{ marginTop: 8, paddingTop: 8, borderTop: '1px solid rgba(0, 255, 255, 0.2)' }}>
114
- <div style={{ fontSize: 10, color: '#00ffff', marginBottom: 4 }}>All-Time Records:</div>
161
+ <div
162
+ style={{
163
+ marginTop: 8,
164
+ paddingTop: 8,
165
+ borderTop: '1px solid rgba(0, 255, 255, 0.2)',
166
+ }}
167
+ >
168
+ <div
169
+ style={{ fontSize: 10, color: '#00ffff', marginBottom: 4 }}
170
+ >
171
+ All-Time Records:
172
+ </div>
115
173
  <div style={{ fontSize: 10, marginBottom: 2 }}>
116
174
  Highest Territory: {allTimeRecords.highestTerritory.value}
117
175
  </div>
@@ -127,11 +185,19 @@ export const NarrationOverlay: React.FC<NarrationOverlayProps> = ({
127
185
  {/* Leaderboard (Collapsible) */}
128
186
  {leaderboard && leaderboard.length > 0 && (
129
187
  <details style={{ marginBottom: 8, fontSize: 11 }}>
130
- <summary style={{ cursor: 'pointer', color: '#00ffff', marginBottom: 4 }}>
188
+ <summary
189
+ style={{ cursor: 'pointer', color: '#00ffff', marginBottom: 4 }}
190
+ >
131
191
  Top 10 Leaderboard
132
192
  </summary>
133
- <div style={{ padding: '8px', background: 'rgba(0, 255, 255, 0.05)', borderRadius: 4 }}>
134
- {leaderboard.map((entry, i) => (
193
+ <div
194
+ style={{
195
+ padding: '8px',
196
+ background: 'rgba(0, 255, 255, 0.05)',
197
+ borderRadius: 4,
198
+ }}
199
+ >
200
+ {leaderboard.map((entry: any, i: number) => (
135
201
  <div
136
202
  key={entry.photoId}
137
203
  style={{
@@ -139,13 +205,15 @@ export const NarrationOverlay: React.FC<NarrationOverlayProps> = ({
139
205
  justifyContent: 'space-between',
140
206
  marginBottom: 2,
141
207
  fontSize: 10,
142
- color: i < 3 ? '#00ff00' : '#00ffff'
208
+ color: i < 3 ? '#00ff00' : '#00ffff',
143
209
  }}
144
210
  >
145
211
  <span>
146
212
  {i + 1}. {entry.photoId.slice(0, 20)}...
147
213
  </span>
148
- <span style={{ fontVariantNumeric: 'tabular-nums' }}>{entry.territory} hexes</span>
214
+ <span style={{ fontVariantNumeric: 'tabular-nums' }}>
215
+ {entry.territory} hexes
216
+ </span>
149
217
  </div>
150
218
  ))}
151
219
  </div>
@@ -161,11 +229,18 @@ export const NarrationOverlay: React.FC<NarrationOverlayProps> = ({
161
229
  maxHeight: '400px',
162
230
  padding: '8px',
163
231
  background: 'rgba(0, 0, 0, 0.3)',
164
- borderRadius: 4
232
+ borderRadius: 4,
165
233
  }}
166
234
  >
167
235
  {messages.length === 0 ? (
168
- <div style={{ color: 'rgba(0, 255, 255, 0.5)', fontStyle: 'italic', textAlign: 'center', padding: '20px' }}>
236
+ <div
237
+ style={{
238
+ color: 'rgba(0, 255, 255, 0.5)',
239
+ fontStyle: 'italic',
240
+ textAlign: 'center',
241
+ padding: '20px',
242
+ }}
243
+ >
169
244
  No narration yet. Evolution in progress...
170
245
  </div>
171
246
  ) : (
@@ -175,14 +250,25 @@ export const NarrationOverlay: React.FC<NarrationOverlayProps> = ({
175
250
  style={{
176
251
  marginBottom: 8,
177
252
  padding: '6px',
178
- background: msg.priority >= 8 ? 'rgba(255, 165, 0, 0.1)' : 'rgba(0, 255, 255, 0.05)',
253
+ background:
254
+ msg.priority >= 8
255
+ ? 'rgba(255, 165, 0, 0.1)'
256
+ : 'rgba(0, 255, 255, 0.05)',
179
257
  borderRadius: 4,
180
- borderLeft: `2px solid ${msg.priority >= 8 ? '#ffaa00' : '#00ffff'}`,
258
+ borderLeft: `2px solid ${
259
+ msg.priority >= 8 ? '#ffaa00' : '#00ffff'
260
+ }`,
181
261
  fontSize: 11,
182
- lineHeight: 1.4
262
+ lineHeight: 1.4,
183
263
  }}
184
264
  >
185
- <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 2 }}>
265
+ <div
266
+ style={{
267
+ display: 'flex',
268
+ justifyContent: 'space-between',
269
+ marginBottom: 2,
270
+ }}
271
+ >
186
272
  <span style={{ color: 'rgba(0, 255, 255, 0.7)', fontSize: 10 }}>
187
273
  Gen {msg.generation}
188
274
  </span>
@@ -198,12 +284,15 @@ export const NarrationOverlay: React.FC<NarrationOverlayProps> = ({
198
284
  marginTop: 4,
199
285
  fontFamily: "'Courier New', monospace",
200
286
  fontSize: 14,
201
- color: msg.eventType === 'slam_dunk' || msg.eventType === 'on_fire'
202
- ? '#00ff00'
203
- : msg.eventType === 'decline' || msg.eventType === 'missed_shot'
204
- ? '#ff4444'
205
- : '#00ffff',
206
- letterSpacing: '2px'
287
+ color:
288
+ msg.eventType === 'slam_dunk' ||
289
+ msg.eventType === 'on_fire'
290
+ ? '#00ff00'
291
+ : msg.eventType === 'decline' ||
292
+ msg.eventType === 'missed_shot'
293
+ ? '#ff4444'
294
+ : '#00ffff',
295
+ letterSpacing: '2px',
207
296
  }}
208
297
  >
209
298
  {msg.sparkline}
@@ -216,6 +305,5 @@ export const NarrationOverlay: React.FC<NarrationOverlayProps> = ({
216
305
  <div ref={messagesEndRef} />
217
306
  </div>
218
307
  </div>
219
- )
220
- }
221
-
308
+ );
309
+ };
@@ -1,2 +1,3 @@
1
1
  export { HexGrid } from './HexGrid';
2
- export type { Photo, HexGridProps } from './HexGrid';
2
+ export type { HexGridProps, Photo } from '../types';
3
+ export type { Photo as PhotoType } from '../types';
package/src/features.ts CHANGED
@@ -1,48 +1,48 @@
1
1
  /**
2
2
  * Feature flags for HexGrid 3D
3
- *
3
+ *
4
4
  * Allows enabling/disabling features at runtime for different client environments
5
5
  */
6
6
 
7
7
  export interface HexGridFeatureFlags {
8
8
  /** Enable/disable play-by-play narration overlay */
9
- enableNarration?: boolean
10
-
9
+ enableNarration?: boolean;
10
+
11
11
  /** Enable/disable statistics tracking and display */
12
- enableStats?: boolean
13
-
12
+ enableStats?: boolean;
13
+
14
14
  /** Enable/disable debug panel */
15
- enableDebugPanel?: boolean
16
-
15
+ enableDebugPanel?: boolean;
16
+
17
17
  /** Enable/disable camera controls UI */
18
- enableCameraControls?: boolean
19
-
18
+ enableCameraControls?: boolean;
19
+
20
20
  /** Enable/disable worker-based rendering */
21
- enableWorker?: boolean
22
-
21
+ enableWorker?: boolean;
22
+
23
23
  /** Enable/disable texture/image loading */
24
- enableTextures?: boolean
25
-
24
+ enableTextures?: boolean;
25
+
26
26
  /** Enable/disable evolution/animation system */
27
- enableEvolution?: boolean
28
-
27
+ enableEvolution?: boolean;
28
+
29
29
  /** Enable/disable autoplay functionality */
30
- enableAutoplay?: boolean
31
-
30
+ enableAutoplay?: boolean;
31
+
32
32
  /** Enable/disable user interactions (clicks, drags) */
33
- enableInteractions?: boolean
34
-
33
+ enableInteractions?: boolean;
34
+
35
35
  /** Enable/disable keyboard shortcuts */
36
- enableKeyboardShortcuts?: boolean
37
-
36
+ enableKeyboardShortcuts?: boolean;
37
+
38
38
  /** Enable/disable performance telemetry */
39
- enableTelemetry?: boolean
40
-
39
+ enableTelemetry?: boolean;
40
+
41
41
  /** Enable/disable sheen/visual effects */
42
- enableVisualEffects?: boolean
43
-
42
+ enableVisualEffects?: boolean;
43
+
44
44
  /** Enable/disable leaderboard system */
45
- enableLeaderboard?: boolean
45
+ enableLeaderboard?: boolean;
46
46
  }
47
47
 
48
48
  /**
@@ -62,7 +62,7 @@ export const DEFAULT_FEATURE_FLAGS: Required<HexGridFeatureFlags> = {
62
62
  enableTelemetry: true,
63
63
  enableVisualEffects: true,
64
64
  enableLeaderboard: true,
65
- }
65
+ };
66
66
 
67
67
  /**
68
68
  * Minimal feature flags - only core visualization
@@ -81,7 +81,7 @@ export const MINIMAL_FEATURE_FLAGS: Required<HexGridFeatureFlags> = {
81
81
  enableTelemetry: false,
82
82
  enableVisualEffects: false,
83
83
  enableLeaderboard: false,
84
- }
84
+ };
85
85
 
86
86
  /**
87
87
  * Performance-focused feature flags
@@ -100,7 +100,7 @@ export const PERFORMANCE_FEATURE_FLAGS: Required<HexGridFeatureFlags> = {
100
100
  enableTelemetry: false,
101
101
  enableVisualEffects: false,
102
102
  enableLeaderboard: false,
103
- }
103
+ };
104
104
 
105
105
  /**
106
106
  * Merge user-provided flags with defaults
@@ -111,7 +111,7 @@ export function mergeFeatureFlags(
111
111
  return {
112
112
  ...DEFAULT_FEATURE_FLAGS,
113
113
  ...userFlags,
114
- }
114
+ };
115
115
  }
116
116
 
117
117
  /**
@@ -121,5 +121,5 @@ export function isFeatureEnabled(
121
121
  flags: HexGridFeatureFlags,
122
122
  feature: keyof HexGridFeatureFlags
123
123
  ): boolean {
124
- return flags[feature] !== false
124
+ return flags[feature] !== false;
125
125
  }
package/src/index.ts CHANGED
@@ -1,30 +1,30 @@
1
1
  // Main package exports
2
- export * from './components'
3
- export * from './stores'
4
- export * from './features'
2
+ export * from './components';
3
+ export * from './stores';
4
+ export * from './features';
5
5
 
6
6
  // Export pure mathematical functions
7
- export * from './workers/hexgrid-math'
8
- export * from './utils/image-utils'
7
+ export * from './workers/hexgrid-math';
8
+ export * from './utils/image-utils';
9
9
 
10
10
  // Export additional types that aren't in components/stores
11
- export type { WorkerDebug, Photo, GridItem } from './types'
11
+ export type { WorkerDebug, Photo, GridItem } from './types';
12
12
 
13
13
  // ═══════════════════════════════════════════════════════════════════════════
14
14
  // ENHANCED HEXGRID EXPORTS
15
15
  // ═══════════════════════════════════════════════════════════════════════════
16
16
 
17
17
  // Math library
18
- export * from './math'
18
+ export * from './math';
19
19
 
20
20
  // Algorithms (graph, clustering, flow, particles, fluid)
21
- export * from './algorithms'
21
+ export * from './algorithms';
22
22
 
23
23
  // WASM acceleration layer
24
- export * from './wasm'
24
+ export * from './wasm';
25
25
 
26
26
  // Unified Snapshot API
27
- export * from './Snapshot'
27
+ export * from './Snapshot';
28
28
 
29
29
  // Enhanced HexGrid engine with all features integrated
30
- export * from './HexGridEnhanced'
30
+ export * from './HexGridEnhanced';
@@ -0,0 +1,17 @@
1
+ export interface NarrationMessage {
2
+ generation: number;
3
+ timestamp: string;
4
+ priority: number;
5
+ text: string;
6
+ eventType?: string;
7
+ sparkline?: string;
8
+ }
9
+
10
+ export class NarrationManager {
11
+ static getInstance(): any {
12
+ return {
13
+ subscribe: () => () => {},
14
+ getState: () => ({})
15
+ };
16
+ }
17
+ }
@@ -0,0 +1,25 @@
1
+ export class StatsTracker {
2
+ static getInstance(): StatsTracker {
3
+ return new StatsTracker();
4
+ }
5
+
6
+ getCurrentStats(): any {
7
+ return {
8
+ generation: 1,
9
+ activeMemesCount: 10,
10
+ totalHexesInfected: 100,
11
+ populationStability: 0.5
12
+ };
13
+ }
14
+
15
+ getAllTimeRecords(): any {
16
+ return {
17
+ highestTerritory: { value: 100 },
18
+ longestSurvivalStreak: { value: 50 }
19
+ };
20
+ }
21
+
22
+ getLeaderboard(limit: number): any[] {
23
+ return [];
24
+ }
25
+ }
@@ -0,0 +1,12 @@
1
+ export const ThemeColors = {
2
+ primary: '#000000',
3
+ secondary: '#ffffff'
4
+ };
5
+
6
+ export function getAccentRgba(alpha: number = 1): string {
7
+ return `rgba(0, 255, 255, ${alpha})`;
8
+ }
9
+
10
+ export function getAccentHex(): string {
11
+ return '#00ffff';
12
+ }