deskforge 1.0.0 → 1.0.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 (84) hide show
  1. package/COMPLETION_REPORT.md +426 -0
  2. package/COMPONENT_API.md +529 -0
  3. package/DELIVERY_SUMMARY.md +455 -0
  4. package/IMPLEMENTATION_GUIDE.md +385 -0
  5. package/IMPORT_GUIDE.md +404 -0
  6. package/QUICK_REFERENCE.md +352 -0
  7. package/README.md +245 -31
  8. package/README_UI_COMPLETE.md +395 -0
  9. package/TYPE_DEFINITIONS.md +671 -0
  10. package/UI_GETTING_STARTED.md +523 -0
  11. package/examples/deskforge-app/App.ts +7 -11
  12. package/examples/deskforge-app/screens/CounterApp.ts +181 -0
  13. package/examples/deskforge-app/screens/GalleryApp.ts +267 -0
  14. package/examples/deskforge-app/screens/NotesApp.ts +376 -0
  15. package/examples/deskforge-app/screens/SettingsApp.ts +226 -0
  16. package/examples/deskforge-app/screens/TodoApp.ts +288 -0
  17. package/examples/deskforge-app/screens/index.ts +50 -0
  18. package/package.json +1 -1
  19. package/packages/cli/dist/commands/start.d.ts +7 -1
  20. package/packages/cli/dist/commands/start.d.ts.map +1 -1
  21. package/packages/cli/dist/commands/start.js +75 -21
  22. package/packages/cli/dist/commands/start.js.map +1 -1
  23. package/packages/cli/src/commands/start.ts +93 -21
  24. package/packages/cli/test/start.test.js +24 -0
  25. package/packages/core/dist/index.d.ts +1 -0
  26. package/packages/core/dist/index.d.ts.map +1 -1
  27. package/packages/core/dist/index.js +1 -0
  28. package/packages/core/dist/index.js.map +1 -1
  29. package/packages/core/dist/style/StyleObject.d.ts +115 -0
  30. package/packages/core/dist/style/StyleObject.d.ts.map +1 -0
  31. package/packages/core/dist/style/StyleObject.js +6 -0
  32. package/packages/core/dist/style/StyleObject.js.map +1 -0
  33. package/packages/core/dist/style/StyleSheet.d.ts +7 -0
  34. package/packages/core/dist/style/StyleSheet.d.ts.map +1 -0
  35. package/packages/core/dist/style/StyleSheet.js +13 -0
  36. package/packages/core/dist/style/StyleSheet.js.map +1 -0
  37. package/packages/core/dist/style/index.d.ts +3 -0
  38. package/packages/core/dist/style/index.d.ts.map +1 -0
  39. package/packages/core/dist/style/index.js +21 -0
  40. package/packages/core/dist/style/index.js.map +1 -0
  41. package/packages/core/src/index.ts +2 -1
  42. package/packages/core/src/style/StyleObject.ts +134 -0
  43. package/packages/core/src/style/StyleSheet.ts +19 -0
  44. package/packages/core/src/style/index.ts +5 -0
  45. package/packages/db/src/db.ts +4 -4
  46. package/packages/deskforge/src/index.ts +95 -0
  47. package/packages/file/dist/file.d.ts +1 -1
  48. package/packages/file/dist/file.d.ts.map +1 -1
  49. package/packages/file/dist/file.js +75 -3
  50. package/packages/file/dist/file.js.map +1 -1
  51. package/packages/file/src/file.ts +96 -4
  52. package/packages/file/test/file.test.js +23 -0
  53. package/packages/router/dist/index.d.ts +1 -0
  54. package/packages/router/dist/index.d.ts.map +1 -1
  55. package/packages/router/dist/index.js +1 -0
  56. package/packages/router/dist/index.js.map +1 -1
  57. package/packages/router/dist/navigation.d.ts +23 -0
  58. package/packages/router/dist/navigation.d.ts.map +1 -0
  59. package/packages/router/dist/navigation.js +61 -0
  60. package/packages/router/dist/navigation.js.map +1 -0
  61. package/packages/router/src/index.ts +2 -1
  62. package/packages/router/src/navigation.ts +86 -0
  63. package/packages/router/test/router.test.js +21 -1
  64. package/packages/theme/src/theme.ts +23 -0
  65. package/packages/ui/src/base/Button.ts +67 -0
  66. package/packages/ui/src/base/Image.ts +59 -0
  67. package/packages/ui/src/base/Pressable.ts +69 -0
  68. package/packages/ui/src/base/Text.ts +42 -0
  69. package/packages/ui/src/base/TextInput.ts +113 -0
  70. package/packages/ui/src/base/TouchableOpacity.ts +52 -0
  71. package/packages/ui/src/base/View.ts +43 -0
  72. package/packages/ui/src/index.ts +40 -25
  73. package/packages/ui/src/input/CheckBox.ts +69 -0
  74. package/packages/ui/src/input/Slider.ts +19 -2
  75. package/packages/ui/src/input/Switch.ts +68 -0
  76. package/packages/ui/src/layout/KeyboardAvoidingView.ts +65 -0
  77. package/packages/ui/src/layout/SafeAreaView.ts +58 -0
  78. package/packages/ui/src/list/FlatList.ts +111 -0
  79. package/packages/ui/src/list/ScrollView.ts +80 -0
  80. package/packages/ui/src/list/SectionList.ts +120 -0
  81. package/packages/ui/src/overlay/ActivityIndicator.ts +70 -0
  82. package/packages/ui/src/overlay/Modal.ts +28 -6
  83. package/packages/ui/src/platform/Platform.ts +119 -0
  84. package/packages/ui/src/platform/StatusBar.ts +63 -0
@@ -0,0 +1,376 @@
1
+ /**
2
+ * Notes App - Complete Example
3
+ *
4
+ * Demonstrates View, Text, Pressable, FlatList, TextInput, Modal,
5
+ * State management, and StyleSheet usage.
6
+ */
7
+
8
+ import {
9
+ View,
10
+ Text,
11
+ Pressable,
12
+ FlatList,
13
+ TextInput,
14
+ Modal,
15
+ Button,
16
+ ScrollView,
17
+ StyleSheet,
18
+ } from '@deskforge/ui/src'
19
+ import { State, Effect } from '@deskforge/state/src'
20
+ import { DB } from '@deskforge/db/src'
21
+ import { Toast } from '@deskforge/notifications/src'
22
+ import { Router } from '@deskforge/router/src'
23
+
24
+ /**
25
+ * Note data structure
26
+ */
27
+ interface Note {
28
+ id: string
29
+ title: string
30
+ content: string
31
+ createdAt: number
32
+ updatedAt: number
33
+ }
34
+
35
+ /**
36
+ * Style definitions - all properties match React Native exactly
37
+ */
38
+ const styles = StyleSheet.create({
39
+ container: {
40
+ flex: 1,
41
+ backgroundColor: '#f8f9fc',
42
+ },
43
+ header: {
44
+ flexDirection: 'row',
45
+ alignItems: 'center',
46
+ justifyContent: 'space-between',
47
+ paddingHorizontal: 16,
48
+ paddingVertical: 12,
49
+ backgroundColor: '#ffffff',
50
+ borderBottomWidth: 1,
51
+ borderBottomColor: '#e2e8f0',
52
+ },
53
+ headerTitle: {
54
+ fontSize: 20,
55
+ fontWeight: 'bold',
56
+ color: '#111111',
57
+ },
58
+ addButton: {
59
+ backgroundColor: '#0077ff',
60
+ borderRadius: 8,
61
+ paddingHorizontal: 16,
62
+ paddingVertical: 8,
63
+ },
64
+ addButtonText: {
65
+ color: '#ffffff',
66
+ fontWeight: 'bold',
67
+ fontSize: 14,
68
+ },
69
+ noteCard: {
70
+ backgroundColor: '#ffffff',
71
+ borderRadius: 12,
72
+ padding: 16,
73
+ marginHorizontal: 16,
74
+ marginTop: 12,
75
+ marginBottom: 0,
76
+ shadowColor: '#000000',
77
+ shadowOpacity: 0.05,
78
+ shadowRadius: 4,
79
+ elevation: 2,
80
+ },
81
+ noteTitle: {
82
+ fontSize: 16,
83
+ fontWeight: '600',
84
+ color: '#111111',
85
+ marginBottom: 8,
86
+ },
87
+ notePreview: {
88
+ fontSize: 14,
89
+ color: '#666666',
90
+ lineHeight: 20,
91
+ },
92
+ noteTimestamp: {
93
+ fontSize: 12,
94
+ color: '#999999',
95
+ marginTop: 8,
96
+ },
97
+ emptyState: {
98
+ flex: 1,
99
+ justifyContent: 'center',
100
+ alignItems: 'center',
101
+ padding: 20,
102
+ },
103
+ emptyStateText: {
104
+ fontSize: 16,
105
+ color: '#999999',
106
+ textAlign: 'center',
107
+ },
108
+ loadingContainer: {
109
+ flex: 1,
110
+ justifyContent: 'center',
111
+ alignItems: 'center',
112
+ },
113
+ modalOverlay: {
114
+ flex: 1,
115
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
116
+ justifyContent: 'center',
117
+ alignItems: 'center',
118
+ },
119
+ modalContent: {
120
+ width: '85%',
121
+ maxHeight: '80%',
122
+ backgroundColor: '#ffffff',
123
+ borderRadius: 16,
124
+ padding: 20,
125
+ },
126
+ modalTitle: {
127
+ fontSize: 20,
128
+ fontWeight: 'bold',
129
+ color: '#111111',
130
+ marginBottom: 16,
131
+ },
132
+ inputLabel: {
133
+ fontSize: 12,
134
+ fontWeight: '600',
135
+ color: '#666666',
136
+ marginBottom: 8,
137
+ },
138
+ textInputStyle: {
139
+ borderWidth: 1,
140
+ borderColor: '#e2e8f0',
141
+ borderRadius: 8,
142
+ paddingHorizontal: 12,
143
+ paddingVertical: 10,
144
+ fontSize: 14,
145
+ color: '#111111',
146
+ marginBottom: 16,
147
+ },
148
+ multilineInput: {
149
+ height: 120,
150
+ paddingVertical: 12,
151
+ textAlignVertical: 'top',
152
+ },
153
+ modalActions: {
154
+ flexDirection: 'row',
155
+ gap: 12,
156
+ marginTop: 16,
157
+ },
158
+ cancelButton: {
159
+ flex: 1,
160
+ backgroundColor: '#f0f0f0',
161
+ borderRadius: 8,
162
+ paddingVertical: 12,
163
+ alignItems: 'center',
164
+ },
165
+ cancelButtonText: {
166
+ color: '#666666',
167
+ fontWeight: '600',
168
+ },
169
+ submitButton: {
170
+ flex: 1,
171
+ backgroundColor: '#0077ff',
172
+ borderRadius: 8,
173
+ paddingVertical: 12,
174
+ alignItems: 'center',
175
+ },
176
+ submitButtonText: {
177
+ color: '#ffffff',
178
+ fontWeight: '600',
179
+ },
180
+ })
181
+
182
+ /**
183
+ * NotesApp - Main component
184
+ *
185
+ * Displays list of notes with ability to create, view, and delete notes.
186
+ * Uses FlatList for efficient rendering of large note lists.
187
+ */
188
+ export const NotesApp = () => {
189
+ const state = State({
190
+ notes: [] as Note[],
191
+ loading: false,
192
+ showModal: false,
193
+ newTitle: '',
194
+ newContent: '',
195
+ })
196
+
197
+ /**
198
+ * Load notes from database on app launch
199
+ */
200
+ Effect(() => {
201
+ state.loading = true
202
+ DB.query('notes')
203
+ .orderBy('updatedAt', 'desc')
204
+ .all()
205
+ .then((result: any) => {
206
+ state.notes = result as Note[]
207
+ })
208
+ .catch(() => {
209
+ Toast.error('Failed to load notes')
210
+ })
211
+ .finally(() => {
212
+ state.loading = false
213
+ })
214
+ })
215
+
216
+ /**
217
+ * Create a new note
218
+ */
219
+ const handleCreateNote = () => {
220
+ if (!state.newTitle.trim() || !state.newContent.trim()) {
221
+ Toast.warning('Please fill in all fields')
222
+ return
223
+ }
224
+
225
+ const note: Note = {
226
+ id: `note_${Date.now()}`,
227
+ title: state.newTitle,
228
+ content: state.newContent,
229
+ createdAt: Date.now(),
230
+ updatedAt: Date.now(),
231
+ }
232
+
233
+ DB.insert('notes', note)
234
+ .then(() => {
235
+ state.notes.unshift(note)
236
+ state.newTitle = ''
237
+ state.newContent = ''
238
+ state.showModal = false
239
+ Toast.success('Note created')
240
+ })
241
+ .catch(() => {
242
+ Toast.error('Failed to create note')
243
+ })
244
+ }
245
+
246
+ /**
247
+ * Navigate to note details screen
248
+ */
249
+ const handleNotePress = (noteId: string) => {
250
+ // Navigate to note detail screen with note ID
251
+ if (typeof Router.go === 'function') {
252
+ Router.go('note-detail', { id: noteId })
253
+ }
254
+ }
255
+
256
+ /**
257
+ * Render individual note card
258
+ */
259
+ const renderNote = (note: Note) => {
260
+ const preview = note.content.substring(0, 100)
261
+ const timeString = new Date(note.updatedAt).toLocaleDateString()
262
+
263
+ return Pressable(styles.noteCard, {
264
+ onPress: () => handleNotePress(note.id),
265
+ }, [
266
+ Text(note.title, styles.noteTitle),
267
+ Text(preview + (note.content.length > 100 ? '...' : ''), styles.notePreview),
268
+ Text(`Updated ${timeString}`, styles.noteTimestamp),
269
+ ])
270
+ }
271
+
272
+ /**
273
+ * Render empty state when no notes exist
274
+ */
275
+ const renderEmpty = () => {
276
+ return View(styles.emptyState, [
277
+ Text('No notes yet', styles.emptyStateText),
278
+ Text('Tap + to create your first note', {
279
+ fontSize: 14,
280
+ color: '#ccc',
281
+ marginTop: 8,
282
+ }),
283
+ ])
284
+ }
285
+
286
+ // Show loading spinner
287
+ if (state.loading) {
288
+ return View(styles.loadingContainer, [])
289
+ }
290
+
291
+ // Main app layout
292
+ return View(styles.container, [
293
+ // Header
294
+ View(styles.header, [
295
+ Text('My Notes', styles.headerTitle),
296
+ Pressable(styles.addButton, {
297
+ onPress: () => {
298
+ state.showModal = true
299
+ },
300
+ }, [
301
+ Text('+ New', styles.addButtonText),
302
+ ]),
303
+ ]),
304
+
305
+ // Notes list
306
+ state.notes.length === 0
307
+ ? renderEmpty()
308
+ : FlatList(
309
+ state.notes,
310
+ renderNote,
311
+ { flex: 1, paddingTop: 8, paddingBottom: 8 }
312
+ ),
313
+
314
+ // Create note modal
315
+ Modal([
316
+ View(styles.modalContent, [
317
+ Text('Create Note', styles.modalTitle),
318
+
319
+ // Title input
320
+ Text('Title', styles.inputLabel),
321
+ TextInput(styles.textInputStyle, {
322
+ placeholder: 'Enter note title',
323
+ value: state.newTitle,
324
+ onChangeText: (text) => {
325
+ state.newTitle = text
326
+ },
327
+ maxLength: 100,
328
+ }),
329
+
330
+ // Content input
331
+ Text('Content', styles.inputLabel),
332
+ TextInput(
333
+ {
334
+ ...styles.textInputStyle,
335
+ ...styles.multilineInput,
336
+ },
337
+ {
338
+ placeholder: 'Enter note content',
339
+ value: state.newContent,
340
+ onChangeText: (text) => {
341
+ state.newContent = text
342
+ },
343
+ multiline: true,
344
+ numberOfLines: 5,
345
+ }
346
+ ),
347
+
348
+ // Action buttons
349
+ View(styles.modalActions, [
350
+ Pressable(styles.cancelButton, {
351
+ onPress: () => {
352
+ state.showModal = false
353
+ state.newTitle = ''
354
+ state.newContent = ''
355
+ },
356
+ }, [
357
+ Text('Cancel', styles.cancelButtonText),
358
+ ]),
359
+
360
+ Pressable(styles.submitButton, {
361
+ onPress: handleCreateNote,
362
+ }, [
363
+ Text('Create', styles.submitButtonText),
364
+ ]),
365
+ ]),
366
+ ]),
367
+ ], {
368
+ open: state.showModal,
369
+ onClose: () => {
370
+ state.showModal = false
371
+ },
372
+ }),
373
+ ])
374
+ }
375
+
376
+ export default NotesApp
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Settings App - Complete Example
3
+ *
4
+ * Demonstrates Switch, Slider, ScrollView, Platform detection,
5
+ * and state persistence.
6
+ */
7
+
8
+ import {
9
+ View,
10
+ Text,
11
+ Switch,
12
+ Slider,
13
+ ScrollView,
14
+ StyleSheet,
15
+ Platform,
16
+ } from '@deskforge/ui/src'
17
+ import { State } from '@deskforge/state/src'
18
+ import { Theme } from '@deskforge/theme/src'
19
+
20
+ /**
21
+ * Style definitions
22
+ */
23
+ const styles = StyleSheet.create({
24
+ container: {
25
+ flex: 1,
26
+ backgroundColor: '#f8f9fc',
27
+ },
28
+ header: {
29
+ paddingHorizontal: 16,
30
+ paddingVertical: 12,
31
+ backgroundColor: '#ffffff',
32
+ borderBottomWidth: 1,
33
+ borderBottomColor: '#e2e8f0',
34
+ },
35
+ headerTitle: {
36
+ fontSize: 20,
37
+ fontWeight: 'bold',
38
+ color: '#111111',
39
+ },
40
+ scrollContent: {
41
+ padding: 16,
42
+ },
43
+ section: {
44
+ backgroundColor: '#ffffff',
45
+ borderRadius: 12,
46
+ padding: 16,
47
+ marginBottom: 16,
48
+ },
49
+ sectionTitle: {
50
+ fontSize: 16,
51
+ fontWeight: 'bold',
52
+ color: '#111111',
53
+ marginBottom: 12,
54
+ },
55
+ settingRow: {
56
+ flexDirection: 'row',
57
+ alignItems: 'center',
58
+ justifyContent: 'space-between',
59
+ paddingVertical: 12,
60
+ borderBottomWidth: 1,
61
+ borderBottomColor: '#f0f0f0',
62
+ },
63
+ settingRowLast: {
64
+ borderBottomWidth: 0,
65
+ },
66
+ settingLabel: {
67
+ fontSize: 14,
68
+ color: '#111111',
69
+ fontWeight: '500',
70
+ },
71
+ settingDescription: {
72
+ fontSize: 12,
73
+ color: '#999999',
74
+ marginTop: 4,
75
+ },
76
+ sliderContainer: {
77
+ paddingVertical: 16,
78
+ },
79
+ sliderLabel: {
80
+ fontSize: 12,
81
+ color: '#666666',
82
+ marginBottom: 8,
83
+ },
84
+ valueDisplay: {
85
+ fontSize: 14,
86
+ fontWeight: 'bold',
87
+ color: '#0077ff',
88
+ },
89
+ platformInfo: {
90
+ backgroundColor: '#f0f0f0',
91
+ borderRadius: 8,
92
+ padding: 12,
93
+ marginTop: 8,
94
+ },
95
+ platformText: {
96
+ fontSize: 12,
97
+ color: '#666666',
98
+ },
99
+ })
100
+
101
+ /**
102
+ * SettingsApp - Main component
103
+ *
104
+ * Demonstrates Switch and Slider components for user preferences.
105
+ * Shows platform detection and conditional rendering.
106
+ */
107
+ export const SettingsApp = () => {
108
+ const state = State({
109
+ darkMode: false,
110
+ notifications: true,
111
+ volume: 70,
112
+ brightness: 100,
113
+ })
114
+
115
+ return View(styles.container, [
116
+ // Header
117
+ View(styles.header, [
118
+ Text('Settings', styles.headerTitle),
119
+ ]),
120
+
121
+ // Scrollable settings
122
+ ScrollView({ flex: 1 }, [
123
+ View(styles.scrollContent, [
124
+ // Display settings section
125
+ View(styles.section, [
126
+ Text('Display', styles.sectionTitle),
127
+
128
+ View(styles.settingRow, [
129
+ View({ flex: 1 }, [
130
+ Text('Dark Mode', styles.settingLabel),
131
+ Text('Easier on the eyes', styles.settingDescription),
132
+ ]),
133
+ Switch(
134
+ state.darkMode,
135
+ (value) => {
136
+ state.darkMode = value
137
+ // Apply theme changes
138
+ Theme.apply({ isDark: value })
139
+ }
140
+ ),
141
+ ]),
142
+
143
+ View({
144
+ ...styles.settingRow,
145
+ ...styles.settingRowLast,
146
+ }, [
147
+ View({ flex: 1 }, [
148
+ Text('Brightness', styles.settingLabel),
149
+ Text(`${state.brightness}%`, styles.settingDescription),
150
+ ]),
151
+ ]),
152
+
153
+ View(styles.sliderContainer, [
154
+ Slider({ flex: 1 }, {
155
+ value: state.brightness,
156
+ min: 0,
157
+ max: 100,
158
+ step: 5,
159
+ onChange: (value) => {
160
+ state.brightness = value
161
+ },
162
+ color: '#0077ff',
163
+ trackColor: '#e2e8f0',
164
+ }),
165
+ ]),
166
+ ]),
167
+
168
+ // Sound settings section
169
+ View(styles.section, [
170
+ Text('Sound', styles.sectionTitle),
171
+
172
+ View(styles.settingRow, [
173
+ View({ flex: 1 }, [
174
+ Text('Notifications', styles.settingLabel),
175
+ Text('Enable sound alerts', styles.settingDescription),
176
+ ]),
177
+ Switch(
178
+ state.notifications,
179
+ (value) => {
180
+ state.notifications = value
181
+ }
182
+ ),
183
+ ]),
184
+
185
+ View({
186
+ ...styles.settingRow,
187
+ ...styles.settingRowLast,
188
+ }, [
189
+ View({ flex: 1 }, [
190
+ Text('Volume', styles.settingLabel),
191
+ Text(`${state.volume}%`, styles.settingDescription),
192
+ ]),
193
+ ]),
194
+
195
+ View(styles.sliderContainer, [
196
+ Slider({ flex: 1 }, {
197
+ value: state.volume,
198
+ min: 0,
199
+ max: 100,
200
+ step: 1,
201
+ onChange: (value) => {
202
+ state.volume = value
203
+ },
204
+ }),
205
+ ]),
206
+ ]),
207
+
208
+ // Platform info
209
+ View(styles.section, [
210
+ Text('Device', styles.sectionTitle),
211
+ View(styles.platformInfo, [
212
+ Text(`OS: ${Platform.OS}`, styles.platformText),
213
+ Text(
214
+ Platform.OS === 'ios' || Platform.OS === 'android'
215
+ ? '📱 Mobile Device'
216
+ : '🖥️ Desktop Device',
217
+ { ...styles.platformText, marginTop: 4 }
218
+ ),
219
+ ]),
220
+ ]),
221
+ ]),
222
+ ]),
223
+ ])
224
+ }
225
+
226
+ export default SettingsApp