-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreact_app.tsx
156 lines (141 loc) · 4.69 KB
/
react_app.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import React, { ReactNode, useEffect, useState } from 'react';
import { TreeView, Tree } from '@fluidframework/tree';
import { App, Letter } from './schema';
import { IFluidContainer } from 'fluid-framework';
export function Explanation(): JSX.Element {
return (
<div className="flex flex-col max-w-md gap-4 justify-left my-32 select-none">
<BlackBox>
Copy the full URL to another browser tab or send it to someone to see
that the data is synched between clients.
</BlackBox>
</div>
);
}
export function BlackBox(props: { children: ReactNode }): JSX.Element {
return (
<div className="text-xl bg-black text-white p-4 rounded shadow-md">
{props.children}
</div>
);
}
function CanvasLetter(props: {
app: App;
letter: Letter;
cellSize: { x: number; y: number };
}): JSX.Element {
const style: React.CSSProperties = {
left: `${props.letter.position.x}px`,
top: `${props.letter.position.y}px`,
width: `${props.cellSize.x}px`,
height: `${props.cellSize.y}px`,
};
return (
<div
className="transition-all hover:scale-110 text-center cursor-pointer select-none absolute text-xl"
style={style}
onClick={() => {
const index = props.app.letters.indexOf(props.letter);
if (index != -1) props.app.word.moveToEnd(index, props.app.letters);
}}
>
{props.letter.character}
</div>
);
}
function TopLetter(props: { app: App; letter: Letter }): JSX.Element {
const [isWinner, setIsWinner] = useState(false);
useEffect(() => {
const topRow = props.app.word
.map((letter) => {
return letter.character;
})
.join('');
if (topRow == 'HELLO' || topRow == 'HELLOWORLD' || topRow == 'WORLD') {
setIsWinner(true);
} else {
setIsWinner(false);
}
}, [props.app.word.length,]);
const classes = `transition-all text-center cursor-pointer select-none tracking-widest text-2xl ${
isWinner ? ' font-extrabold text-3xl' : ' animate-bounce text-2xl'
}`;
return (
<div
className={classes}
onClick={() => {
const index = props.app.word.indexOf(props.letter);
if (index != -1) props.app.letters.moveToEnd(index, props.app.word);
}}
>
{props.letter.character}
</div>
);
}
function Canvas(props: {
app: App;
cellSize: { x: number; y: number };
canvasSize: { x: number; y: number };
}): JSX.Element {
const style: React.CSSProperties = {
width: (props.cellSize.x * props.canvasSize.x).toString() + `px`,
height: (props.cellSize.y * props.canvasSize.y).toString() + `px`,
};
return (
<div
className="relative w-full h-full self-center bg-transparent"
style={style}
onClick={(e: React.MouseEvent) => {
e.preventDefault();
}}
>
{props.app.letters.map((letter) => (
<CanvasLetter
key={letter.id}
app={props.app}
letter={letter}
cellSize={props.cellSize}
/>
))}
</div>
);
}
function TopRow(props: { app: App }): JSX.Element {
return (
<div className="flex justify-center bg-gray-300 p-4 gap-1 h-16 w-full ">
{props.app.word.map((letter) => (
<TopLetter key={letter.id} app={props.app} letter={letter} />
))}
</div>
);
}
export function ReactApp(props: {
data: TreeView<App>;
container: IFluidContainer;
cellSize: { x: number; y: number };
canvasSize: { x: number; y: number };
}): JSX.Element {
const [invalidations, setInvalidations] = useState(0);
const appRoot = props.data.root;
// Register for tree deltas when the component mounts.
// Any time the tree changes, the app will update
// For more complex apps, this code can be included
// on lower level components.
useEffect(() => {
const unsubscribe = Tree.on(appRoot, 'afterChange', () => {
setInvalidations(invalidations + Math.random());
});
return unsubscribe;
}, []);
return (
<div className="flex flex-col justify-items-center items-center w-full h-full">
<TopRow app={appRoot} />
<Canvas
app={appRoot}
canvasSize={props.canvasSize}
cellSize={props.cellSize}
/>
<Explanation />
</div>
);
}