129 lines
4.2 KiB
TypeScript
129 lines
4.2 KiB
TypeScript
import { useState } from 'react'
|
|
|
|
interface WelcomeModalProps {
|
|
isOpen: boolean
|
|
onClose: () => void
|
|
}
|
|
|
|
export function WelcomeModal({ isOpen, onClose }: WelcomeModalProps) {
|
|
const [neverShowAgain, setNeverShowAgain] = useState(false)
|
|
|
|
const handleClose = () => {
|
|
if (neverShowAgain) {
|
|
localStorage.setItem('palace-welcome-dismissed', 'true')
|
|
}
|
|
onClose()
|
|
}
|
|
|
|
const handleOverlayClick = (e: React.MouseEvent) => {
|
|
if (e.target === e.currentTarget) {
|
|
handleClose()
|
|
}
|
|
}
|
|
|
|
if (!isOpen) return null
|
|
|
|
return (
|
|
<div
|
|
style={{
|
|
position: 'fixed',
|
|
top: 0,
|
|
left: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
background: 'rgba(0, 0, 0, 0.8)',
|
|
zIndex: 3000,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center'
|
|
}}
|
|
onClick={handleOverlayClick}
|
|
>
|
|
<div
|
|
style={{
|
|
background: '#1a1a1a',
|
|
border: '1px solid #333',
|
|
width: '500px',
|
|
maxWidth: '90vw',
|
|
fontFamily: 'monospace',
|
|
color: 'white'
|
|
}}
|
|
>
|
|
<div style={{ padding: '24px' }}>
|
|
<h2 style={{ margin: '0 0 20px 0', fontSize: '18px', color: '#fff' }}>
|
|
Welcome to Bubo's Memory Palace
|
|
</h2>
|
|
|
|
<div style={{ marginBottom: '20px', lineHeight: '1.5', color: '#ccc' }}>
|
|
|
|
<p style={{ margin: '0 0 12px 0' }}>
|
|
This is Bubo's Memory Palace. You can write words and sentences in space.
|
|
Double click a word to navigate to the corresponding space. Empty spaces
|
|
are deleted. Spaces with no words linking to them are kept, only forgotten.
|
|
</p>
|
|
|
|
<p style={{ margin: '0 0 12px 0' }}>
|
|
<strong>Navigation :</strong> Hit <code style={{ background: '#333', padding: '2px 4px', borderRadius: '2px' }}>:</code> to open a navigation console.
|
|
</p>
|
|
|
|
<p style={{ margin: '0 0 12px 0' }}>
|
|
<strong>Writing:</strong> Double click in the void to write anything.
|
|
</p>
|
|
<p style={{ margin: '0 0 12px 0' }}>
|
|
<strong>Selection:</strong> Shift+click or click and drag to select.
|
|
</p>
|
|
<p style={{ margin: '0 0 12px 0' }}>
|
|
<strong>Warping:</strong> Double click on a note to warp between spaces.
|
|
</p>
|
|
<p style={{ margin: '0 0 12px 0' }}>
|
|
<strong>Delete :</strong> Backspace/Del to delete a note.
|
|
</p>
|
|
<p style={{ margin: '0' }}>
|
|
<strong>Share:</strong> Type <code style={{ background: '#333', padding: '2px 4px', borderRadius: '2px' }}>share</code> in the nav console to share a space through a browser link (overrides the target).
|
|
</p>
|
|
</div>
|
|
|
|
<div style={{ marginBottom: '20px' }}>
|
|
<label style={{ display: 'flex', alignItems: 'center', cursor: 'pointer', color: '#ccc' }}>
|
|
<input
|
|
type="checkbox"
|
|
checked={neverShowAgain}
|
|
onChange={(e) => setNeverShowAgain(e.target.checked)}
|
|
style={{ marginRight: '8px' }}
|
|
/>
|
|
Don't show this again (<code style={{ background: '#333', padding: '2px 4px', borderRadius: '2px' }}>? </code> to open this modal again)
|
|
</label>
|
|
</div>
|
|
|
|
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: '12px' }}>
|
|
<button
|
|
onClick={handleClose}
|
|
style={{
|
|
background: '#333',
|
|
color: 'white',
|
|
border: '1px solid #555',
|
|
padding: '8px 16px',
|
|
cursor: 'pointer',
|
|
fontFamily: 'monospace',
|
|
fontSize: '14px'
|
|
}}
|
|
onMouseEnter={(e) => {
|
|
e.currentTarget.style.background = '#444'
|
|
}}
|
|
onMouseLeave={(e) => {
|
|
e.currentTarget.style.background = '#333'
|
|
}}
|
|
>
|
|
OK !
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function shouldShowWelcome(): boolean {
|
|
return localStorage.getItem('palace-welcome-dismissed') !== 'true'
|
|
}
|