memorio 2.6.6 → 2.7.0

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.
@@ -0,0 +1,357 @@
1
+ /**
2
+ * Memorio React App Example
3
+ *
4
+ * This example shows how to use Memorio state in a React application.
5
+ *
6
+ * Run: npx ts-node --esm examples/react-app.tsx
7
+ * Or copy to your React project
8
+ */
9
+
10
+ import React, { useState, useEffect } from 'react'
11
+ import '../index'
12
+
13
+ // ============================================
14
+ // 1. SETUP - Import once at app start
15
+ // ============================================
16
+
17
+ // In your main App.tsx or index.js:
18
+ // import 'memorio'
19
+
20
+ // ============================================
21
+ // 2. DEFINE YOUR STATE SHAPE
22
+ // ============================================
23
+
24
+ interface AppState {
25
+ user: {
26
+ name: string
27
+ email: string
28
+ avatar?: string
29
+ } | null
30
+ theme: 'light' | 'dark'
31
+ notifications: Notification[]
32
+ cart: CartItem[]
33
+ isLoading: boolean
34
+ }
35
+
36
+ interface Notification {
37
+ id: string
38
+ message: string
39
+ read: boolean
40
+ }
41
+
42
+ interface CartItem {
43
+ id: number
44
+ name: string
45
+ price: number
46
+ quantity: number
47
+ }
48
+
49
+ // ============================================
50
+ // 3. USE STATE IN COMPONENTS
51
+ // ============================================
52
+
53
+ // ------------------------------
54
+ // Header Component
55
+ // ------------------------------
56
+ function Header() {
57
+ // Using useObserver to react to state changes
58
+ const [theme, setTheme] = useState(state.theme)
59
+
60
+ useObserver(() => {
61
+ setTheme(state.theme)
62
+ }, [state.theme])
63
+
64
+ return (
65
+ <header className={`header header--${theme}`}>
66
+ <h1>My App</h1>
67
+ <button onClick={() => {
68
+ state.theme = state.theme === 'light' ? 'dark' : 'light'
69
+ }}>
70
+ Toggle Theme
71
+ </button>
72
+ </header>
73
+ )
74
+ }
75
+
76
+ // ------------------------------
77
+ // User Profile Component
78
+ // ------------------------------
79
+ function UserProfile() {
80
+ const [user, setUser] = useState(state.user)
81
+
82
+ // Auto-discover all state changes
83
+ useObserver(() => {
84
+ setUser(state.user)
85
+ })
86
+
87
+ if (!user) {
88
+ return <div>Please log in</div>
89
+ }
90
+
91
+ return (
92
+ <div className="profile">
93
+ <img src={user.avatar} alt={user.name} />
94
+ <h2>{user.name}</h2>
95
+ <p>{user.email}</p>
96
+ </div>
97
+ )
98
+ }
99
+
100
+ // ------------------------------
101
+ // Login Form Component
102
+ // ------------------------------
103
+ function LoginForm() {
104
+ const [name, setName] = useState('')
105
+ const [email, setEmail] = useState('')
106
+
107
+ const handleSubmit = (e: React.FormEvent) => {
108
+ e.preventDefault()
109
+
110
+ // Set user state
111
+ state.user = {
112
+ name,
113
+ email,
114
+ avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${name}`
115
+ }
116
+
117
+ // Also persist to store
118
+ store.set('lastUser', name)
119
+ }
120
+
121
+ return (
122
+ <form onSubmit={handleSubmit}>
123
+ <input
124
+ value={name}
125
+ onChange={e => setName(e.target.value)}
126
+ placeholder="Name"
127
+ />
128
+ <input
129
+ value={email}
130
+ onChange={e => setEmail(e.target.value)}
131
+ placeholder="Email"
132
+ />
133
+ <button type="submit">Login</button>
134
+ </form>
135
+ )
136
+ }
137
+
138
+ // ------------------------------
139
+ // Shopping Cart Component
140
+ // ------------------------------
141
+ function Cart() {
142
+ const [items, setItems] = useState<CartItem[]>([])
143
+
144
+ useObserver(() => {
145
+ setItems(state.cart || [])
146
+ }, [state.cart])
147
+
148
+ const total = items.reduce((sum, item) => sum + item.price * item.quantity, 0)
149
+
150
+ return (
151
+ <div className="cart">
152
+ <h2>Cart ({items.length})</h2>
153
+ {items.map(item => (
154
+ <div key={item.id}>
155
+ {item.name} - ${item.price} x {item.quantity}
156
+ </div>
157
+ ))}
158
+ <strong>Total: ${total}</strong>
159
+ </div>
160
+ )
161
+ }
162
+
163
+ // ------------------------------
164
+ // Add to Cart Button
165
+ // ------------------------------
166
+ function AddToCartButton({ product }: { product: { id: number, name: string, price: number } }) {
167
+ return (
168
+ <button onClick={() => {
169
+ // Initialize cart if not exists
170
+ if (!state.cart) {
171
+ state.cart = []
172
+ }
173
+
174
+ // Add item or increment quantity
175
+ const existing = state.cart.find(item => item.id === product.id)
176
+ if (existing) {
177
+ existing.quantity++
178
+ } else {
179
+ state.cart.push({
180
+ id: product.id,
181
+ name: product.name,
182
+ price: product.price,
183
+ quantity: 1
184
+ })
185
+ }
186
+ }}>
187
+ Add to Cart
188
+ </button>
189
+ )
190
+ }
191
+
192
+ // ------------------------------
193
+ // Notifications Component
194
+ // ------------------------------
195
+ function Notifications() {
196
+ const [notifications, setNotifications] = useState<Notification[]>([])
197
+
198
+ useObserver(() => {
199
+ setNotifications(state.notifications || [])
200
+ }, [state.notifications])
201
+
202
+ const unread = notifications.filter(n => !n.read).length
203
+
204
+ return (
205
+ <div className="notifications">
206
+ <span>🔔 {unread} unread</span>
207
+ {notifications.map(n => (
208
+ <div key={n.id} className={n.read ? 'read' : 'unread'}>
209
+ {n.message}
210
+ </div>
211
+ ))}
212
+ </div>
213
+ )
214
+ }
215
+
216
+ // ------------------------------
217
+ // Settings Component
218
+ // ------------------------------
219
+ function Settings() {
220
+ const [theme, setTheme] = useState(state.theme)
221
+ const [savedSettings, setSavedSettings] = useState<any>(null)
222
+
223
+ // Load saved settings from store
224
+ useEffect(() => {
225
+ const settings = store.get('appSettings')
226
+ if (settings) {
227
+ setSavedSettings(settings)
228
+ }
229
+ }, [])
230
+
231
+ const saveSettings = () => {
232
+ store.set('appSettings', { theme: state.theme })
233
+ alert('Settings saved!')
234
+ }
235
+
236
+ return (
237
+ <div className="settings">
238
+ <h2>Settings</h2>
239
+
240
+ <label>
241
+ Theme:
242
+ <select
243
+ value={theme}
244
+ onChange={e => state.theme = e.target.value as 'light' | 'dark'}
245
+ >
246
+ <option value="light">Light</option>
247
+ <option value="dark">Dark</option>
248
+ </select>
249
+ </label>
250
+
251
+ <button onClick={saveSettings}>Save Settings</button>
252
+
253
+ {savedSettings && (
254
+ <p>Saved: {savedSettings.theme}</p>
255
+ )}
256
+ </div>
257
+ )
258
+ }
259
+
260
+ // ============================================
261
+ // 4. MAIN APP COMPONENT
262
+ // ============================================
263
+
264
+ function App() {
265
+ // Initialize default state
266
+ useEffect(() => {
267
+ // Load theme from store
268
+ const savedTheme = store.get('appSettings')?.theme
269
+ if (savedTheme) {
270
+ state.theme = savedTheme
271
+ } else {
272
+ state.theme = 'light'
273
+ }
274
+
275
+ // Initialize notifications
276
+ state.notifications = [
277
+ { id: '1', message: 'Welcome to Memorio!', read: false },
278
+ { id: '2', message: 'Check out our new features', read: false }
279
+ ]
280
+
281
+ // Check for returning user
282
+ const lastUser = store.get('lastUser')
283
+ if (lastUser) {
284
+ console.log('Welcome back,', lastUser)
285
+ }
286
+ }, [])
287
+
288
+ return (
289
+ <div className={`app app--${state.theme}`}>
290
+ <Header />
291
+ <main>
292
+ {state.user ? (
293
+ <>
294
+ <UserProfile />
295
+ <Cart />
296
+ <Notifications />
297
+ <Settings />
298
+
299
+ <button onClick={() => {
300
+ // Logout - clear user but keep settings
301
+ state.user = null
302
+ }}>
303
+ Logout
304
+ </button>
305
+ </>
306
+ ) : (
307
+ <LoginForm />
308
+ )}
309
+ </main>
310
+ </div>
311
+ )
312
+ }
313
+
314
+ export default App
315
+
316
+ // ============================================
317
+ // 5. USAGE SUMMARY
318
+ // ============================================
319
+
320
+ /*
321
+ MEMORIO REACT USAGE GUIDE:
322
+
323
+ 1. IMPORT ONCE (index.js or App.tsx):
324
+ import 'memorio'
325
+
326
+ 2. SET STATE:
327
+ state.user = { name: 'Mario', email: 'mario@example.com' }
328
+ state.theme = 'dark'
329
+ state.cart = []
330
+
331
+ 3. READ STATE:
332
+ const value = state.user.name
333
+ const theme = state.theme
334
+
335
+ 4. REACT TO CHANGES:
336
+ useObserver(() => {
337
+ console.log('State changed!')
338
+ }, [state.user])
339
+
340
+ 5. AUTO-DISCOVERY (watch all):
341
+ useObserver(() => {
342
+ console.log(state.user, state.theme)
343
+ })
344
+
345
+ 6. PERSIST DATA:
346
+ store.set('settings', { theme: 'dark' })
347
+ const settings = store.get('settings')
348
+
349
+ 7. SESSION DATA (cleared on tab close):
350
+ session.set('token', 'abc123')
351
+ const token = session.get('token')
352
+
353
+ 8. CLEAR DATA:
354
+ state.removeAll() // Clear all state
355
+ store.removeAll() // Clear all persisted
356
+ session.removeAll() // Clear all session
357
+ */
@@ -9,6 +9,19 @@
9
9
 
10
10
  import '../index'
11
11
 
12
+ // ============================================
13
+ // CHECK PERSISTENCE
14
+ // ============================================
15
+
16
+ console.log('=== Session Persistence Check ===')
17
+ console.log('Is persistent (survives tab close):', session.isPersistent)
18
+ // In browser: true (sessionStorage)
19
+ // In Node.js/Deno: false (memory fallback)
20
+
21
+ if (!session.isPersistent) {
22
+ console.log('⚠️ Warning: Using in-memory storage. Data will be lost on process restart!')
23
+ }
24
+
12
25
  // ============================================
13
26
  // AUTHENTICATION
14
27
  // ============================================
@@ -8,6 +8,19 @@
8
8
 
9
9
  import '../index'
10
10
 
11
+ // ============================================
12
+ // CHECK PERSISTENCE
13
+ // ============================================
14
+
15
+ console.log('=== Store Persistence Check ===')
16
+ console.log('Is persistent (survives restart):', store.isPersistent)
17
+ // In browser: true (localStorage)
18
+ // In Node.js/Deno: false (memory fallback)
19
+
20
+ if (!store.isPersistent) {
21
+ console.log('⚠️ Warning: Using in-memory storage. Data will be lost on restart!')
22
+ }
23
+
11
24
  // ============================================
12
25
  // PERSIST USER PREFERENCES
13
26
  // ============================================