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,113 @@
1
+ /**
2
+ * TextInput Component
3
+ *
4
+ * Text input field matching React Native TextInput props.
5
+ * Accepts style and configuration props. Returns DFNode.
6
+ *
7
+ * No JSX. No HTML. No XML. Pure functional TypeScript.
8
+ */
9
+
10
+ import { createNode } from '@deskforge/core'
11
+ import type { DFNode, StyleObject } from '@deskforge/core'
12
+
13
+ /**
14
+ * TextInput configuration properties
15
+ */
16
+ export interface TextInputProps {
17
+ /** Initial text value */
18
+ value?: string
19
+ /** Placeholder text when empty */
20
+ placeholder?: string
21
+ /** Called when text changes */
22
+ onChangeText?: (text: string) => void
23
+ /** Called on focus */
24
+ onFocus?: () => void
25
+ /** Called on blur */
26
+ onBlur?: () => void
27
+ /** Keyboard type: 'default', 'numeric', 'email-address', 'phone-pad' */
28
+ keyboardType?: 'default' | 'numeric' | 'email-address' | 'phone-pad'
29
+ /** Return key type */
30
+ returnKeyType?: string
31
+ /** Placeholder text color */
32
+ placeholderTextColor?: string
33
+ /** Number of lines (mobile) */
34
+ numberOfLines?: number
35
+ /** Allow multiple lines */
36
+ multiline?: boolean
37
+ /** Editable state */
38
+ editable?: boolean
39
+ /** Max length of input */
40
+ maxLength?: number
41
+ /** Auto-capitalize mode */
42
+ autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters'
43
+ /** Auto-correct */
44
+ autoCorrect?: boolean
45
+ /** Security for password fields */
46
+ secureTextEntry?: boolean
47
+ }
48
+
49
+ /**
50
+ * TextInput - Text input field component
51
+ *
52
+ * Single or multi-line text input field. Supports all React Native TextInput props.
53
+ * Automatically handles keyboard interactions and text changes.
54
+ *
55
+ * @param style - StyleObject for sizing and appearance
56
+ * @param props - TextInputProps configuration object
57
+ * @returns DFNode object with type 'TextInput'
58
+ *
59
+ * @example
60
+ * TextInput({ borderWidth: 1, borderColor: '#ccc', padding: 8 }, {
61
+ * placeholder: 'Enter name',
62
+ * onChangeText: (text) => updateName(text)
63
+ * })
64
+ *
65
+ * TextInput({
66
+ * flex: 1,
67
+ * padding: 12,
68
+ * borderRadius: 8,
69
+ * borderWidth: 1,
70
+ * borderColor: '#e2e8f0'
71
+ * }, {
72
+ * placeholder: 'Enter email',
73
+ * keyboardType: 'email-address',
74
+ * value: email,
75
+ * onChangeText: setEmail
76
+ * })
77
+ *
78
+ * TextInput({ flex: 1, padding: 8 }, {
79
+ * placeholder: 'Enter password',
80
+ * secureTextEntry: true,
81
+ * value: password,
82
+ * onChangeText: setPassword
83
+ * })
84
+ */
85
+ export function TextInput(
86
+ style: StyleObject,
87
+ props: TextInputProps = {}
88
+ ): DFNode {
89
+ return createNode(
90
+ 'TextInput',
91
+ {
92
+ style,
93
+ value: props.value ?? '',
94
+ placeholder: props.placeholder ?? '',
95
+ onChangeText: props.onChangeText,
96
+ onFocus: props.onFocus,
97
+ onBlur: props.onBlur,
98
+ keyboardType: props.keyboardType ?? 'default',
99
+ returnKeyType: props.returnKeyType ?? 'done',
100
+ placeholderTextColor: props.placeholderTextColor,
101
+ numberOfLines: props.numberOfLines ?? 1,
102
+ multiline: props.multiline ?? false,
103
+ editable: props.editable ?? true,
104
+ maxLength: props.maxLength,
105
+ autoCapitalize: props.autoCapitalize ?? 'sentences',
106
+ autoCorrect: props.autoCorrect ?? true,
107
+ secureTextEntry: props.secureTextEntry ?? false,
108
+ } as Record<string, unknown>,
109
+ []
110
+ )
111
+ }
112
+
113
+ export type { StyleObject }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * TouchableOpacity Component
3
+ *
4
+ * Tappable container with opacity animation on press.
5
+ * Like Pressable with built-in opacity feedback animation.
6
+ *
7
+ * No JSX. No HTML. No XML. Pure functional TypeScript.
8
+ */
9
+
10
+ import { createNode } from '@deskforge/core'
11
+ import type { DFNode, StyleObject } from '@deskforge/core'
12
+ import type { PressHandlers } from './Pressable'
13
+
14
+ /**
15
+ * TouchableOpacity - Tappable container with opacity animation
16
+ *
17
+ * Similar to Pressable but automatically applies opacity animation when pressed.
18
+ * Default opacity when active is 0.6. Returns to full opacity when released.
19
+ *
20
+ * @param style - StyleObject containing layout and appearance properties
21
+ * @param handlers - PressHandlers object with onPress and other handlers
22
+ * @param children - Array of DFNode children to render inside
23
+ * @returns DFNode object with type 'TouchableOpacity'
24
+ *
25
+ * @example
26
+ * TouchableOpacity({ padding: 12 }, {
27
+ * onPress: () => navigate('details')
28
+ * }, [
29
+ * Text('Go to Details', { fontSize: 16 })
30
+ * ])
31
+ */
32
+ export function TouchableOpacity(
33
+ style: StyleObject,
34
+ handlers: PressHandlers = {},
35
+ children: DFNode[] = []
36
+ ): DFNode {
37
+ return createNode(
38
+ 'TouchableOpacity',
39
+ {
40
+ style,
41
+ activeOpacity: 0.6,
42
+ onPress: handlers.onPress,
43
+ onLongPress: handlers.onLongPress,
44
+ onPressIn: handlers.onPressIn,
45
+ onPressOut: handlers.onPressOut,
46
+ disabled: handlers.disabled ?? false,
47
+ } as Record<string, unknown>,
48
+ children
49
+ )
50
+ }
51
+
52
+ export type { StyleObject, PressHandlers }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * View Component
3
+ *
4
+ * Primary container component in DeskForge. Maps to Column/Row based on flexDirection.
5
+ * Accepts style object and children array. Returns DFNode.
6
+ *
7
+ * No JSX. No HTML. No XML. Pure functional TypeScript.
8
+ */
9
+
10
+ import { createNode } from '@deskforge/core'
11
+ import type { DFNode, StyleObject } from '@deskforge/core'
12
+
13
+ /**
14
+ * View - Primary container component
15
+ *
16
+ * Renders a flex container with optional children. flexDirection defaults to 'column'.
17
+ * All style properties from React Native are supported via StyleObject.
18
+ *
19
+ * @param style - StyleObject containing layout, spacing, appearance properties
20
+ * @param children - Array of DFNode children to render inside the view
21
+ * @returns DFNode object with type 'View'
22
+ *
23
+ * @example
24
+ * View({ flex: 1, backgroundColor: '#fff' }, [
25
+ * Text('Hello', { fontSize: 16 }),
26
+ * View({ height: 10 }, [])
27
+ * ])
28
+ */
29
+ export function View(
30
+ style: StyleObject,
31
+ children: DFNode[] = []
32
+ ): DFNode {
33
+ return createNode(
34
+ 'View',
35
+ {
36
+ style,
37
+ flexDirection: style.flexDirection ?? 'column',
38
+ } as Record<string, unknown>,
39
+ children
40
+ )
41
+ }
42
+
43
+ export type { StyleObject }
@@ -1,33 +1,48 @@
1
- // index.ts
2
- // Public door into the entire UI package.
3
- // Import any component from here.
1
+ /**
2
+ * DeskForge UI Components Package
3
+ *
4
+ * Exports all UI components for building cross-platform interfaces.
5
+ * Pure functional syntax — no JSX, no HTML, no XML.
6
+ *
7
+ * Import from 'deskforge':
8
+ * import { View, Text, Pressable, FlatList } from 'deskforge'
9
+ */
10
+
11
+ // Base components
12
+ export { View } from './base/View'
13
+ export { Text } from './base/Text'
14
+ export { Pressable, type PressHandlers } from './base/Pressable'
15
+ export { Button } from './base/Button'
16
+ export { TouchableOpacity } from './base/TouchableOpacity'
17
+ export { Image, type ImageSource } from './base/Image'
18
+ export { TextInput, type TextInputProps } from './base/TextInput'
19
+
20
+ // List components
21
+ export { ScrollView, type ScrollViewProps } from './list/ScrollView'
22
+ export { FlatList, type FlatListProps } from './list/FlatList'
23
+ export { SectionList, type SectionListProps, type Section } from './list/SectionList'
4
24
 
5
25
  // Layout components
6
- export * from './layout/index'
26
+ export { SafeAreaView, type SafeAreaViewProps } from './layout/SafeAreaView'
27
+ export { KeyboardAvoidingView, type KeyboardAvoidingViewProps } from './layout/KeyboardAvoidingView'
7
28
 
8
- // Typography components
9
- export * from './typography/index'
29
+ // Overlay components
30
+ export { Modal, type ModalProps } from './overlay/Modal'
31
+ export { ActivityIndicator, type ActivityIndicatorProps } from './overlay/ActivityIndicator'
10
32
 
11
33
  // Input components
12
- export * from './input/index'
13
-
14
- // Display components
15
- export * from './display/index'
16
-
17
- // Feedback components
18
- export * from './feedback/index'
19
-
20
- // Navigation components
21
- export * from './navigation/index'
22
-
23
- // Overlay components
24
- export * from './overlay/index'
34
+ export { Switch, type SwitchProps } from './input/Switch'
35
+ export { Slider, type SliderProps } from './input/Slider'
36
+ export { CheckBox, type CheckBoxProps } from './input/CheckBox'
25
37
 
26
- // Data components
27
- export * from './data/index'
38
+ // Platform components
39
+ export { StatusBar, type StatusBarProps } from './platform/StatusBar'
40
+ export { Platform, type PlatformOS, type PlatformSelectOptions } from './platform/Platform'
28
41
 
29
- // Chart components
30
- export * from './charts/index'
42
+ // Style types
43
+ export type { StyleObject } from '@deskforge/core'
44
+ export { StyleSheet } from '@deskforge/core'
31
45
 
32
- // Add this line to packages/ui/src/index.ts
33
- export * from './conditional/If'
46
+ // Core types
47
+ export type { DFNode } from '@deskforge/core'
48
+ export { createNode } from '@deskforge/core'
@@ -0,0 +1,69 @@
1
+ /**
2
+ * CheckBox Component
3
+ *
4
+ * Checkbox input matching React Native accessibility patterns.
5
+ * Binary check state with optional styling.
6
+ *
7
+ * No JSX. No HTML. No XML. Pure functional TypeScript.
8
+ */
9
+
10
+ import { createNode } from '@deskforge/core'
11
+ import type { DFNode, StyleObject } from '@deskforge/core'
12
+
13
+ /**
14
+ * CheckBox configuration properties
15
+ */
16
+ export interface CheckBoxProps {
17
+ /** Checked color */
18
+ tintColor?: string
19
+ /** Unchecked color */
20
+ onTintColor?: string
21
+ /** Disabled state */
22
+ disabled?: boolean
23
+ }
24
+
25
+ /**
26
+ * CheckBox - Checkbox input component
27
+ *
28
+ * Binary checkbox control. Fires onValueChange when toggled.
29
+ * Supports optional styling for checked/unchecked states.
30
+ *
31
+ * @param value - Current checked state
32
+ * @param onValueChange - Callback fired when checkbox is toggled
33
+ * @param style - Optional StyleObject for sizing
34
+ * @param props - Optional CheckBoxProps configuration
35
+ * @returns DFNode object with type 'CheckBox'
36
+ *
37
+ * @example
38
+ * CheckBox(isChecked, (newValue) => setIsChecked(newValue))
39
+ *
40
+ * CheckBox(agreeToTerms, setAgreeToTerms, {}, {
41
+ * tintColor: '#0077ff',
42
+ * onTintColor: '#ccc'
43
+ * })
44
+ *
45
+ * CheckBox(selected, toggleSelected, { width: 24, height: 24 }, {
46
+ * tintColor: '#2ecc71'
47
+ * })
48
+ */
49
+ export function CheckBox(
50
+ value: boolean,
51
+ onValueChange: (value: boolean) => void,
52
+ style?: StyleObject,
53
+ props: CheckBoxProps = {}
54
+ ): DFNode {
55
+ return createNode(
56
+ 'CheckBox',
57
+ {
58
+ style: style ?? {},
59
+ value,
60
+ onValueChange,
61
+ tintColor: props.tintColor ?? '#0077ff',
62
+ onTintColor: props.onTintColor ?? '#ccc',
63
+ disabled: props.disabled ?? false,
64
+ } as Record<string, unknown>,
65
+ []
66
+ )
67
+ }
68
+
69
+ export type { StyleObject }
@@ -57,8 +57,25 @@ interface SliderProps {
57
57
  }
58
58
 
59
59
  // Creates a range slider node
60
- // props slider configuration
61
- function Slider(props: SliderProps = {}): DFNode {
60
+ // Accepts flexible parameters: Slider(props) or Slider(style, props)
61
+ function Slider(
62
+ styleOrProps?: any,
63
+ propsOverride?: SliderProps
64
+ ): DFNode {
65
+ let props: SliderProps = {}
66
+
67
+ // If first arg is object with style properties
68
+ if (styleOrProps && typeof styleOrProps === 'object') {
69
+ // Check if it looks like a style object (has layout properties)
70
+ if ('flex' in styleOrProps || 'width' in styleOrProps || 'height' in styleOrProps || 'padding' in styleOrProps) {
71
+ // First arg is style, second is props
72
+ props = { ...styleOrProps, ...propsOverride }
73
+ } else {
74
+ // First arg is props
75
+ props = styleOrProps
76
+ }
77
+ }
78
+
62
79
  return createNode('Slider', {
63
80
  min: props.min ?? 0,
64
81
  max: props.max ?? 100,
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Switch Component
3
+ *
4
+ * On/off toggle switch matching React Native Switch.
5
+ * Supports value and change callbacks.
6
+ *
7
+ * No JSX. No HTML. No XML. Pure functional TypeScript.
8
+ */
9
+
10
+ import { createNode } from '@deskforge/core'
11
+ import type { DFNode, StyleObject } from '@deskforge/core'
12
+
13
+ /**
14
+ * Switch configuration properties
15
+ */
16
+ export interface SwitchProps {
17
+ /** On tint color */
18
+ onTintColor?: string
19
+ /** Off tint color */
20
+ offTintColor?: string
21
+ /** Thumb tint color */
22
+ thumbTintColor?: string
23
+ /** Disabled state */
24
+ disabled?: boolean
25
+ }
26
+
27
+ /**
28
+ * Switch - Toggle on/off component
29
+ *
30
+ * Binary toggle switch control. Fires onValueChange callback when toggled.
31
+ * Supports styling for on/off states.
32
+ *
33
+ * @param value - Current switch state (on/off)
34
+ * @param onValueChange - Callback fired when switch is toggled
35
+ * @param props - Optional SwitchProps configuration
36
+ * @returns DFNode object with type 'Switch'
37
+ *
38
+ * @example
39
+ * Switch(isEnabled, (newValue) => setIsEnabled(newValue), {
40
+ * onTintColor: '#2ecc71',
41
+ * thumbTintColor: '#fff'
42
+ * })
43
+ *
44
+ * Switch(darkMode, toggleDarkMode, {
45
+ * onTintColor: '#0077ff',
46
+ * offTintColor: '#ccc'
47
+ * })
48
+ */
49
+ export function Switch(
50
+ value: boolean,
51
+ onValueChange: (value: boolean) => void,
52
+ props: SwitchProps = {}
53
+ ): DFNode {
54
+ return createNode(
55
+ 'Switch',
56
+ {
57
+ value,
58
+ onValueChange,
59
+ onTintColor: props.onTintColor ?? '#2ecc71',
60
+ offTintColor: props.offTintColor ?? '#ccc',
61
+ thumbTintColor: props.thumbTintColor ?? '#fff',
62
+ disabled: props.disabled ?? false,
63
+ } as Record<string, unknown>,
64
+ []
65
+ )
66
+ }
67
+
68
+ export type { StyleObject }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * KeyboardAvoidingView Component
3
+ *
4
+ * Adjusts layout when keyboard appears on mobile.
5
+ * Prevents content from being hidden behind keyboard.
6
+ *
7
+ * No JSX. No HTML. No XML. Pure functional TypeScript.
8
+ */
9
+
10
+ import { createNode } from '@deskforge/core'
11
+ import type { DFNode, StyleObject } from '@deskforge/core'
12
+
13
+ /**
14
+ * KeyboardAvoidingView configuration properties
15
+ */
16
+ export interface KeyboardAvoidingViewProps {
17
+ /** Behavior when keyboard appears: 'height' | 'padding' | 'position' */
18
+ behavior?: 'height' | 'padding' | 'position'
19
+ /** Enable/disable adjustment */
20
+ enabled?: boolean
21
+ /** Offset amount in pixels */
22
+ keyboardVerticalOffset?: number
23
+ }
24
+
25
+ /**
26
+ * KeyboardAvoidingView - Keyboard-aware layout component
27
+ *
28
+ * Automatically adjusts the view layout when software keyboard appears.
29
+ * Prevents content from being hidden behind the keyboard input.
30
+ *
31
+ * @param style - StyleObject for sizing and appearance
32
+ * @param children - Array of DFNode children to render inside
33
+ * @param props - Optional KeyboardAvoidingViewProps configuration
34
+ * @returns DFNode object with type 'KeyboardAvoidingView'
35
+ *
36
+ * @example
37
+ * KeyboardAvoidingView({ flex: 1 }, [
38
+ * View({ flex: 1 }, [
39
+ * Text('Enter your message', { padding: 16 })
40
+ * ]),
41
+ * TextInput({ padding: 12 }, {
42
+ * placeholder: 'Type here...'
43
+ * })
44
+ * ], {
45
+ * behavior: 'padding'
46
+ * })
47
+ */
48
+ export function KeyboardAvoidingView(
49
+ style: StyleObject,
50
+ children: DFNode[] = [],
51
+ props: KeyboardAvoidingViewProps = {}
52
+ ): DFNode {
53
+ return createNode(
54
+ 'KeyboardAvoidingView',
55
+ {
56
+ style,
57
+ behavior: props.behavior ?? 'padding',
58
+ enabled: props.enabled ?? true,
59
+ keyboardVerticalOffset: props.keyboardVerticalOffset ?? 0,
60
+ } as Record<string, unknown>,
61
+ children
62
+ )
63
+ }
64
+
65
+ export type { StyleObject }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * SafeAreaView Component
3
+ *
4
+ * Respects notch, status bar, and safe areas on mobile devices.
5
+ * Automatically adjusts insets based on device.
6
+ *
7
+ * No JSX. No HTML. No XML. Pure functional TypeScript.
8
+ */
9
+
10
+ import { createNode } from '@deskforge/core'
11
+ import type { DFNode, StyleObject } from '@deskforge/core'
12
+
13
+ /**
14
+ * SafeAreaView configuration properties
15
+ */
16
+ export interface SafeAreaViewProps {
17
+ /** Top inset direction */
18
+ edges?: ('top' | 'bottom' | 'left' | 'right')[]
19
+ }
20
+
21
+ /**
22
+ * SafeAreaView - Safe area respecting container component
23
+ *
24
+ * Automatically adjusts padding/layout to account for notches, status bars,
25
+ * and other device-specific safe areas on mobile devices.
26
+ *
27
+ * @param style - StyleObject for sizing and appearance
28
+ * @param children - Array of DFNode children to render inside
29
+ * @param props - Optional SafeAreaViewProps configuration
30
+ * @returns DFNode object with type 'SafeAreaView'
31
+ *
32
+ * @example
33
+ * SafeAreaView({ flex: 1, backgroundColor: '#fff' }, [
34
+ * Text('Safe area content', { padding: 16 })
35
+ * ])
36
+ *
37
+ * SafeAreaView({ flex: 1 }, [
38
+ * // Content here automatically respects safe areas
39
+ * ], {
40
+ * edges: ['top', 'bottom']
41
+ * })
42
+ */
43
+ export function SafeAreaView(
44
+ style: StyleObject,
45
+ children: DFNode[] = [],
46
+ props: SafeAreaViewProps = {}
47
+ ): DFNode {
48
+ return createNode(
49
+ 'SafeAreaView',
50
+ {
51
+ style,
52
+ edges: props.edges ?? ['top', 'bottom', 'left', 'right'],
53
+ } as Record<string, unknown>,
54
+ children
55
+ )
56
+ }
57
+
58
+ export type { StyleObject }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * FlatList Component
3
+ *
4
+ * Optimized list renderer for large datasets.
5
+ * Supports virtualization and performance optimizations.
6
+ *
7
+ * No JSX. No HTML. No XML. Pure functional TypeScript.
8
+ */
9
+
10
+ import { createNode } from '@deskforge/core'
11
+ import type { DFNode, StyleObject } from '@deskforge/core'
12
+
13
+ /**
14
+ * FlatList configuration properties
15
+ */
16
+ export interface FlatListProps {
17
+ /** Item separator component renderer */
18
+ ItemSeparatorComponent?: () => DFNode
19
+ /** Rendered at start of list */
20
+ ListHeaderComponent?: DFNode
21
+ /** Rendered at end of list */
22
+ ListFooterComponent?: DFNode
23
+ /** Rendered when list is empty */
24
+ ListEmptyComponent?: DFNode
25
+ /** Number of items to render at once (optimization) */
26
+ initialNumToRender?: number
27
+ /** Scroll callback */
28
+ onScroll?: (offset: { x: number; y: number }) => void
29
+ /** Fired at end of list */
30
+ onEndReached?: () => void
31
+ /** Distance from end to trigger onEndReached */
32
+ onEndReachedThreshold?: number
33
+ /** Horizontal scroll */
34
+ horizontal?: boolean
35
+ /** Enable scroll indicators */
36
+ showsVerticalScrollIndicator?: boolean
37
+ /** Bounce effect */
38
+ bounces?: boolean
39
+ /** Column count for grid */
40
+ numColumns?: number
41
+ }
42
+
43
+ /**
44
+ * FlatList - Optimized list renderer component
45
+ *
46
+ * High-performance list component with virtualization. Renders large datasets
47
+ * efficiently by only rendering visible items. Generic over item type.
48
+ *
49
+ * @param data - Array of items to render
50
+ * @param renderItem - Function that renders each item — receives (item, index)
51
+ * @param style - Optional StyleObject for sizing
52
+ * @param props - Optional FlatListProps configuration
53
+ * @returns DFNode object with type 'FlatList'
54
+ *
55
+ * @example
56
+ * FlatList(
57
+ * [{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }],
58
+ * (item) => Text(item.name, { padding: 12 }),
59
+ * { flex: 1 }
60
+ * )
61
+ *
62
+ * FlatList(
63
+ * users,
64
+ * (user, index) => Pressable(
65
+ * { padding: 12, borderBottomWidth: 1, borderBottomColor: '#eee' },
66
+ * { onPress: () => selectUser(user.id) },
67
+ * [
68
+ * Text(user.name, { fontSize: 16, fontWeight: 'bold' }),
69
+ * Text(user.email, { fontSize: 12, color: '#666', marginTop: 4 })
70
+ * ]
71
+ * ),
72
+ * { flex: 1 },
73
+ * {
74
+ * ItemSeparatorComponent: () => View({ height: 1, backgroundColor: '#f0f0f0' }, []),
75
+ * onEndReached: () => loadMore(),
76
+ * onEndReachedThreshold: 0.5
77
+ * }
78
+ * )
79
+ */
80
+ export function FlatList<T>(
81
+ data: T[],
82
+ renderItem: (item: T, index: number) => DFNode,
83
+ style?: StyleObject,
84
+ props: FlatListProps = {}
85
+ ): DFNode {
86
+ const items = data.map((item, index) => renderItem(item, index))
87
+
88
+ return createNode(
89
+ 'FlatList',
90
+ {
91
+ style: style ?? {},
92
+ data,
93
+ renderItem,
94
+ ItemSeparatorComponent: props.ItemSeparatorComponent,
95
+ ListHeaderComponent: props.ListHeaderComponent,
96
+ ListFooterComponent: props.ListFooterComponent,
97
+ ListEmptyComponent: props.ListEmptyComponent,
98
+ initialNumToRender: props.initialNumToRender ?? 10,
99
+ onScroll: props.onScroll,
100
+ onEndReached: props.onEndReached,
101
+ onEndReachedThreshold: props.onEndReachedThreshold ?? 0.1,
102
+ horizontal: props.horizontal ?? false,
103
+ showsVerticalScrollIndicator: props.showsVerticalScrollIndicator ?? true,
104
+ bounces: props.bounces ?? true,
105
+ numColumns: props.numColumns ?? 1,
106
+ } as Record<string, unknown>,
107
+ items
108
+ )
109
+ }
110
+
111
+ export type { StyleObject }