11'use client' ;
22
3- const hashString = ( value ) => {
4- let hash = 0 ;
5- for ( let i = 0 ; i < value . length ; i += 1 ) {
6- hash = value . charCodeAt ( i ) + ( ( hash << 5 ) - hash ) ;
7- }
8- return hash ;
9- } ;
3+ import { useMemo } from "react" ;
104
11- const mapToRange = ( value , min , max ) => {
12- const normalized = Math . abs ( value % 1000 ) / 1000 ;
13- return min + normalized * ( max - min ) ;
14- } ;
5+ const mapToRange = ( value , min , max ) => min + value * ( max - min ) ;
156
167const defaultColors = {
178 highlight : "text-cblue" ,
@@ -20,28 +11,35 @@ const defaultColors = {
2011} ;
2112
2213export default function GuestbookWordCloud ( { entries, isLoading, recentCount = 5 , className = "" , style = { } , colorScheme = defaultColors } ) {
23- const words = ( entries ?? [ ] ) . map ( ( entry , idx ) => {
24- const key = entry . id ?? `${ entry . wristbandSerial ?? "unknown" } -${ idx } ` ;
25- const baseHash = hashString ( `${ key } -${ entry . name } ` ) ;
26- const top = mapToRange ( baseHash , 12 , 88 ) ;
27- const left = mapToRange ( baseHash * 3 , 10 , 90 ) ;
28- const fontSize = mapToRange ( baseHash * 5 , 1.2 , 3.2 ) ;
29- const rotate = mapToRange ( baseHash * 7 , - 10 , 10 ) ;
30- const opacity = mapToRange ( baseHash * 11 , 0.45 , 0.95 ) ;
14+ const words = useMemo ( ( ) => {
15+ if ( ! entries ?. length ) {
16+ return [ ] ;
17+ }
18+
19+ return entries . map ( ( entry , idx ) => {
20+ const key = entry . id ?? `${ entry . wristbandSerial ?? "unknown" } -${ idx } ` ;
21+ const goldenRatio = 0.61803398875 ;
22+ const base = Math . random ( ) + idx * goldenRatio ;
23+ const top = mapToRange ( base % 1 , 12 , 88 ) ;
24+ const left = mapToRange ( ( base * goldenRatio ) % 1 , 10 , 90 ) ;
25+ const fontSize = mapToRange ( Math . random ( ) , 1.2 , 3.2 ) ;
26+ const rotate = mapToRange ( Math . random ( ) , - 10 , 10 ) ;
27+ const opacity = mapToRange ( Math . random ( ) , 0.45 , 0.95 ) ;
3128
32- return {
33- key,
34- label : entry . name ,
35- isRecent : idx >= Math . max ( entries . length - recentCount , 0 ) ,
36- style : {
37- top : `${ top } %` ,
38- left : `${ left } %` ,
39- fontSize : `${ fontSize } rem` ,
40- opacity,
41- transform : `translate(-50%, -50%) rotate(${ rotate } deg)` ,
42- } ,
43- } ;
44- } ) ;
29+ return {
30+ key,
31+ label : entry . name ,
32+ isRecent : idx >= Math . max ( entries . length - recentCount , 0 ) ,
33+ style : {
34+ top : `${ top } %` ,
35+ left : `${ left } %` ,
36+ fontSize : `${ fontSize } rem` ,
37+ opacity,
38+ transform : `translate(-50%, -50%) rotate(${ rotate } deg)` ,
39+ } ,
40+ } ;
41+ } ) ;
42+ } , [ entries , recentCount ] ) ;
4543
4644 return (
4745 < div className = { `absolute inset-0 pointer-events-none select-none ${ className } ` } style = { style } >
0 commit comments