@owlmeans/web-panel 0.1.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.
Files changed (226) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1195 -0
  3. package/build/.gitkeep +0 -0
  4. package/build/auth/context.d.ts +5 -0
  5. package/build/auth/context.d.ts.map +1 -0
  6. package/build/auth/context.js +17 -0
  7. package/build/auth/context.js.map +1 -0
  8. package/build/auth/exports.d.ts +25 -0
  9. package/build/auth/exports.d.ts.map +1 -0
  10. package/build/auth/exports.js +19 -0
  11. package/build/auth/exports.js.map +1 -0
  12. package/build/auth/index.d.ts +5 -0
  13. package/build/auth/index.d.ts.map +1 -0
  14. package/build/auth/index.js +4 -0
  15. package/build/auth/index.js.map +1 -0
  16. package/build/auth/modules.d.ts +2 -0
  17. package/build/auth/modules.d.ts.map +1 -0
  18. package/build/auth/modules.js +4 -0
  19. package/build/auth/modules.js.map +1 -0
  20. package/build/auth/plugins/basic-ed25519.d.ts +3 -0
  21. package/build/auth/plugins/basic-ed25519.d.ts.map +1 -0
  22. package/build/auth/plugins/basic-ed25519.js +40 -0
  23. package/build/auth/plugins/basic-ed25519.js.map +1 -0
  24. package/build/auth/plugins/exports.d.ts +4 -0
  25. package/build/auth/plugins/exports.d.ts.map +1 -0
  26. package/build/auth/plugins/exports.js +4 -0
  27. package/build/auth/plugins/exports.js.map +1 -0
  28. package/build/auth/plugins/index.d.ts +6 -0
  29. package/build/auth/plugins/index.d.ts.map +1 -0
  30. package/build/auth/plugins/index.js +10 -0
  31. package/build/auth/plugins/index.js.map +1 -0
  32. package/build/auth/plugins/re-captcha.d.ts +3 -0
  33. package/build/auth/plugins/re-captcha.d.ts.map +1 -0
  34. package/build/auth/plugins/re-captcha.js +51 -0
  35. package/build/auth/plugins/re-captcha.js.map +1 -0
  36. package/build/auth/plugins/tunnel-consumer.d.ts +3 -0
  37. package/build/auth/plugins/tunnel-consumer.d.ts.map +1 -0
  38. package/build/auth/plugins/tunnel-consumer.js +40 -0
  39. package/build/auth/plugins/tunnel-consumer.js.map +1 -0
  40. package/build/auth/types.d.ts +10 -0
  41. package/build/auth/types.d.ts.map +1 -0
  42. package/build/auth/types.js +2 -0
  43. package/build/auth/types.js.map +1 -0
  44. package/build/components/block.d.ts +4 -0
  45. package/build/components/block.d.ts.map +1 -0
  46. package/build/components/block.js +15 -0
  47. package/build/components/block.js.map +1 -0
  48. package/build/components/button/index.d.ts +3 -0
  49. package/build/components/button/index.d.ts.map +1 -0
  50. package/build/components/button/index.js +2 -0
  51. package/build/components/button/index.js.map +1 -0
  52. package/build/components/button/selector.d.ts +4 -0
  53. package/build/components/button/selector.d.ts.map +1 -0
  54. package/build/components/button/selector.js +8 -0
  55. package/build/components/button/selector.js.map +1 -0
  56. package/build/components/button/types.d.ts +7 -0
  57. package/build/components/button/types.d.ts.map +1 -0
  58. package/build/components/button/types.js +2 -0
  59. package/build/components/button/types.js.map +1 -0
  60. package/build/components/form/button/component.d.ts +5 -0
  61. package/build/components/form/button/component.d.ts.map +1 -0
  62. package/build/components/form/button/component.js +34 -0
  63. package/build/components/form/button/component.js.map +1 -0
  64. package/build/components/form/button/index.d.ts +3 -0
  65. package/build/components/form/button/index.d.ts.map +1 -0
  66. package/build/components/form/button/index.js +3 -0
  67. package/build/components/form/button/index.js.map +1 -0
  68. package/build/components/form/button/types.d.ts +15 -0
  69. package/build/components/form/button/types.d.ts.map +1 -0
  70. package/build/components/form/button/types.js +2 -0
  71. package/build/components/form/button/types.js.map +1 -0
  72. package/build/components/form/component.d.ts +4 -0
  73. package/build/components/form/component.d.ts.map +1 -0
  74. package/build/components/form/component.js +59 -0
  75. package/build/components/form/component.js.map +1 -0
  76. package/build/components/form/index.d.ts +3 -0
  77. package/build/components/form/index.d.ts.map +1 -0
  78. package/build/components/form/index.js +2 -0
  79. package/build/components/form/index.js.map +1 -0
  80. package/build/components/form/text/component.d.ts +4 -0
  81. package/build/components/form/text/component.d.ts.map +1 -0
  82. package/build/components/form/text/component.js +34 -0
  83. package/build/components/form/text/component.js.map +1 -0
  84. package/build/components/form/text/index.d.ts +3 -0
  85. package/build/components/form/text/index.d.ts.map +1 -0
  86. package/build/components/form/text/index.js +3 -0
  87. package/build/components/form/text/index.js.map +1 -0
  88. package/build/components/form/text/types.d.ts +11 -0
  89. package/build/components/form/text/types.d.ts.map +1 -0
  90. package/build/components/form/text/types.js +2 -0
  91. package/build/components/form/text/types.js.map +1 -0
  92. package/build/components/form/types.d.ts +6 -0
  93. package/build/components/form/types.d.ts.map +1 -0
  94. package/build/components/form/types.js +2 -0
  95. package/build/components/form/types.js.map +1 -0
  96. package/build/components/helper.d.ts +6 -0
  97. package/build/components/helper.d.ts.map +1 -0
  98. package/build/components/helper.js +70 -0
  99. package/build/components/helper.js.map +1 -0
  100. package/build/components/index.d.ts +14 -0
  101. package/build/components/index.d.ts.map +1 -0
  102. package/build/components/index.js +13 -0
  103. package/build/components/index.js.map +1 -0
  104. package/build/components/layout/component.d.ts +4 -0
  105. package/build/components/layout/component.d.ts.map +1 -0
  106. package/build/components/layout/component.js +6 -0
  107. package/build/components/layout/component.js.map +1 -0
  108. package/build/components/layout/index.d.ts +3 -0
  109. package/build/components/layout/index.d.ts.map +1 -0
  110. package/build/components/layout/index.js +3 -0
  111. package/build/components/layout/index.js.map +1 -0
  112. package/build/components/layout/types.d.ts +4 -0
  113. package/build/components/layout/types.d.ts.map +1 -0
  114. package/build/components/layout/types.js +2 -0
  115. package/build/components/layout/types.js.map +1 -0
  116. package/build/components/link.d.ts +4 -0
  117. package/build/components/link.d.ts.map +1 -0
  118. package/build/components/link.js +27 -0
  119. package/build/components/link.js.map +1 -0
  120. package/build/components/panel-app/component.d.ts +4 -0
  121. package/build/components/panel-app/component.d.ts.map +1 -0
  122. package/build/components/panel-app/component.js +12 -0
  123. package/build/components/panel-app/component.js.map +1 -0
  124. package/build/components/panel-app/index.d.ts +3 -0
  125. package/build/components/panel-app/index.d.ts.map +1 -0
  126. package/build/components/panel-app/index.js +3 -0
  127. package/build/components/panel-app/index.js.map +1 -0
  128. package/build/components/panel-app/types.d.ts +6 -0
  129. package/build/components/panel-app/types.d.ts.map +1 -0
  130. package/build/components/panel-app/types.js +2 -0
  131. package/build/components/panel-app/types.js.map +1 -0
  132. package/build/components/status.d.ts +4 -0
  133. package/build/components/status.d.ts.map +1 -0
  134. package/build/components/status.js +19 -0
  135. package/build/components/status.js.map +1 -0
  136. package/build/components/text.d.ts +4 -0
  137. package/build/components/text.d.ts.map +1 -0
  138. package/build/components/text.js +9 -0
  139. package/build/components/text.js.map +1 -0
  140. package/build/components/types.d.ts +32 -0
  141. package/build/components/types.d.ts.map +1 -0
  142. package/build/components/types.js +2 -0
  143. package/build/components/types.js.map +1 -0
  144. package/build/components/uploader/image.d.ts +4 -0
  145. package/build/components/uploader/image.d.ts.map +1 -0
  146. package/build/components/uploader/image.js +24 -0
  147. package/build/components/uploader/image.js.map +1 -0
  148. package/build/components/uploader/index.d.ts +2 -0
  149. package/build/components/uploader/index.d.ts.map +1 -0
  150. package/build/components/uploader/index.js +2 -0
  151. package/build/components/uploader/index.js.map +1 -0
  152. package/build/components/uploader/types.d.ts +5 -0
  153. package/build/components/uploader/types.d.ts.map +1 -0
  154. package/build/components/uploader/types.js +2 -0
  155. package/build/components/uploader/types.js.map +1 -0
  156. package/build/context.d.ts +4 -0
  157. package/build/context.d.ts.map +1 -0
  158. package/build/context.js +12 -0
  159. package/build/context.js.map +1 -0
  160. package/build/exports.d.ts +19 -0
  161. package/build/exports.d.ts.map +1 -0
  162. package/build/exports.js +17 -0
  163. package/build/exports.js.map +1 -0
  164. package/build/index.d.ts +8 -0
  165. package/build/index.d.ts.map +1 -0
  166. package/build/index.js +7 -0
  167. package/build/index.js.map +1 -0
  168. package/build/main.d.ts +5 -0
  169. package/build/main.d.ts.map +1 -0
  170. package/build/main.js +14 -0
  171. package/build/main.js.map +1 -0
  172. package/build/modules.d.ts +2 -0
  173. package/build/modules.d.ts.map +1 -0
  174. package/build/modules.js +4 -0
  175. package/build/modules.js.map +1 -0
  176. package/build/types.d.ts +9 -0
  177. package/build/types.d.ts.map +1 -0
  178. package/build/types.js +2 -0
  179. package/build/types.js.map +1 -0
  180. package/package.json +89 -0
  181. package/src/auth/context.ts +25 -0
  182. package/src/auth/exports.ts +29 -0
  183. package/src/auth/index.ts +5 -0
  184. package/src/auth/modules.ts +5 -0
  185. package/src/auth/plugins/basic-ed25519.tsx +57 -0
  186. package/src/auth/plugins/exports.ts +4 -0
  187. package/src/auth/plugins/index.ts +15 -0
  188. package/src/auth/plugins/re-captcha.tsx +73 -0
  189. package/src/auth/plugins/tunnel-consumer.tsx +65 -0
  190. package/src/auth/types.ts +11 -0
  191. package/src/components/block.tsx +27 -0
  192. package/src/components/button/index.ts +3 -0
  193. package/src/components/button/selector.tsx +16 -0
  194. package/src/components/button/types.ts +7 -0
  195. package/src/components/form/button/component.tsx +53 -0
  196. package/src/components/form/button/index.ts +3 -0
  197. package/src/components/form/button/types.ts +16 -0
  198. package/src/components/form/component.tsx +101 -0
  199. package/src/components/form/index.ts +3 -0
  200. package/src/components/form/text/component.tsx +45 -0
  201. package/src/components/form/text/index.ts +3 -0
  202. package/src/components/form/text/types.ts +11 -0
  203. package/src/components/form/types.ts +6 -0
  204. package/src/components/helper.ts +79 -0
  205. package/src/components/index.ts +17 -0
  206. package/src/components/layout/component.tsx +7 -0
  207. package/src/components/layout/index.ts +3 -0
  208. package/src/components/layout/types.ts +4 -0
  209. package/src/components/link.tsx +34 -0
  210. package/src/components/panel-app/component.tsx +21 -0
  211. package/src/components/panel-app/index.ts +3 -0
  212. package/src/components/panel-app/types.ts +6 -0
  213. package/src/components/status.tsx +23 -0
  214. package/src/components/text.tsx +14 -0
  215. package/src/components/types.ts +35 -0
  216. package/src/components/uploader/image.tsx +31 -0
  217. package/src/components/uploader/index.ts +2 -0
  218. package/src/components/uploader/types.ts +6 -0
  219. package/src/context.ts +18 -0
  220. package/src/exports.ts +22 -0
  221. package/src/index.ts +9 -0
  222. package/src/main.tsx +19 -0
  223. package/src/modules.ts +5 -0
  224. package/src/types.ts +11 -0
  225. package/tsconfig.json +16 -0
  226. package/tsconfig.tsbuildinfo +1 -0
package/README.md ADDED
@@ -0,0 +1,1195 @@
1
+ # @owlmeans/web-panel
2
+
3
+ Web-based panel components and infrastructure for OwlMeans Common Libraries. This package extends the `@owlmeans/client-panel` functionality with React web components, Material-UI integration, and web-specific implementations for building comprehensive administrative interfaces and user panels.
4
+
5
+ ## Overview
6
+
7
+ The `@owlmeans/web-panel` package serves as the web-specific implementation of the OwlMeans panel system, designed for fullstack applications with focus on security and modern web user interfaces. It provides:
8
+
9
+ - **Material-UI Integration**: Complete Material Design component system with theming
10
+ - **Web Panel Components**: Comprehensive React components for building web admin panels
11
+ - **Authentication Integration**: Built-in authentication components and flows
12
+ - **Form Management**: Advanced form components with validation and error handling
13
+ - **File Upload**: File and media upload components with progress tracking
14
+ - **Layout System**: Flexible layout components for organizing panel content
15
+ - **Theme Customization**: Material-UI theme integration with customizable styling
16
+ - **Internationalization**: Built-in i18n support with browser language detection
17
+
18
+ This package follows the OwlMeans "quadra" pattern as the **web** implementation, complementing:
19
+ - **@owlmeans/client-panel**: Common panel declarations and base functionality *(base package)*
20
+ - **@owlmeans/native-panel**: React Native panel implementation
21
+ - **@owlmeans/web-panel**: Web browser panel implementation *(this package)*
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ npm install @owlmeans/web-panel
27
+ ```
28
+
29
+ ### Peer Dependencies
30
+
31
+ This package requires several peer dependencies for web development:
32
+
33
+ ```bash
34
+ npm install react react-dom @mui/material @emotion/react @emotion/styled react-hook-form @hookform/resolvers ajv
35
+ ```
36
+
37
+ ## Dependencies
38
+
39
+ This package builds upon the OwlMeans ecosystem and web technologies:
40
+ - `@owlmeans/client-panel`: Base panel functionality and context
41
+ - `@owlmeans/web-client`: Web client framework and rendering
42
+ - `@owlmeans/client-auth`: Authentication components and services
43
+ - `@owlmeans/client-flow`: Flow management integration
44
+ - `@owlmeans/web-flow`: Web-specific flow implementations
45
+ - Material-UI: React component library for Material Design
46
+ - React Hook Form: Form management and validation
47
+
48
+ ## Key Concepts
49
+
50
+ ### Material-UI Integration
51
+ Built on Material-UI (MUI) providing:
52
+ - **Material Design**: Modern Material Design 3 component system
53
+ - **Theme System**: Comprehensive theming with custom color schemes
54
+ - **Responsive Design**: Mobile-first responsive components
55
+ - **Accessibility**: Built-in accessibility support and ARIA compliance
56
+
57
+ ### Panel Architecture
58
+ Structured panel system with:
59
+ - **Panel Context**: Shared context for panel-wide settings and state
60
+ - **Authentication Guards**: Built-in authentication and authorization
61
+ - **Layout Management**: Flexible layout system for complex interfaces
62
+ - **Navigation Integration**: Integration with React Router and client routing
63
+
64
+ ### Form Management
65
+ Advanced form capabilities with:
66
+ - **React Hook Form**: Performance-optimized form management
67
+ - **AJV Validation**: Schema-based validation using JSON Schema
68
+ - **Error Handling**: Comprehensive error display and user feedback
69
+ - **File Uploads**: Integrated file and media upload components
70
+
71
+ ## API Reference
72
+
73
+ ### Main Functions
74
+
75
+ #### `render<C, T>(context, theme?, opts?): void`
76
+
77
+ Main rendering function for web panel applications.
78
+
79
+ ```typescript
80
+ function render<C extends ClientConfig, T extends ClientContext<C>>(
81
+ context: T,
82
+ theme?: Theme,
83
+ opts?: RenderOptions
84
+ ): void
85
+ ```
86
+
87
+ **Parameters:**
88
+ - `context`: Client context with configuration and services
89
+ - `theme`: Optional Material-UI theme customization
90
+ - `opts`: Optional rendering options
91
+
92
+ **Usage:**
93
+ ```typescript
94
+ import { render } from '@owlmeans/web-panel'
95
+ import { makeWebContext } from '@owlmeans/web-client'
96
+ import { createTheme } from '@mui/material/styles'
97
+
98
+ const context = makeWebContext(config)
99
+ const theme = createTheme({
100
+ palette: {
101
+ primary: { main: '#1976d2' },
102
+ secondary: { main: '#dc004e' }
103
+ }
104
+ })
105
+
106
+ render(context, theme, { rootId: 'app' })
107
+ ```
108
+
109
+ ### Core Components
110
+
111
+ #### `PanelApp`
112
+
113
+ Main panel application wrapper with Material-UI theming and context integration.
114
+
115
+ ```typescript
116
+ interface PanelAppProps {
117
+ context: AppContext<any> // Application context
118
+ provide?: ProvideFunction // Custom provider function
119
+ children?: React.ReactNode // Panel content
120
+ theme?: Theme // Material-UI theme
121
+ }
122
+
123
+ const PanelApp: FC<PanelAppProps> = (props) => { /* ... */ }
124
+ ```
125
+
126
+ **Features:**
127
+ - Material-UI theme provider integration
128
+ - CSS baseline normalization
129
+ - I18n context with browser language detection
130
+ - OwlMeans client app wrapper
131
+
132
+ **Usage:**
133
+ ```typescript
134
+ import { PanelApp } from '@owlmeans/web-panel'
135
+
136
+ <PanelApp context={context} theme={customTheme}>
137
+ <AdminInterface />
138
+ </PanelApp>
139
+ ```
140
+
141
+ ### Layout Components
142
+
143
+ #### Panel Layout System
144
+
145
+ Flexible layout components for organizing panel content.
146
+
147
+ ```typescript
148
+ import {
149
+ PanelLayout,
150
+ PanelHeader,
151
+ PanelSidebar,
152
+ PanelContent,
153
+ PanelFooter
154
+ } from '@owlmeans/web-panel'
155
+
156
+ <PanelLayout>
157
+ <PanelHeader title="Administration Panel">
158
+ <UserMenu />
159
+ </PanelHeader>
160
+
161
+ <PanelSidebar>
162
+ <NavigationMenu />
163
+ </PanelSidebar>
164
+
165
+ <PanelContent>
166
+ <MainContent />
167
+ </PanelContent>
168
+
169
+ <PanelFooter>
170
+ <StatusBar />
171
+ </PanelFooter>
172
+ </PanelLayout>
173
+ ```
174
+
175
+ ### Form Components
176
+
177
+ #### Advanced Form System
178
+
179
+ React Hook Form integration with Material-UI components and AJV validation.
180
+
181
+ ```typescript
182
+ import {
183
+ PanelForm,
184
+ FormField,
185
+ FormButton,
186
+ FormSelect,
187
+ FormCheckbox,
188
+ FormValidation
189
+ } from '@owlmeans/web-panel'
190
+
191
+ interface UserFormData {
192
+ name: string
193
+ email: string
194
+ role: string
195
+ active: boolean
196
+ }
197
+
198
+ const userSchema = {
199
+ type: 'object',
200
+ properties: {
201
+ name: { type: 'string', minLength: 2 },
202
+ email: { type: 'string', format: 'email' },
203
+ role: { type: 'string', enum: ['admin', 'user'] },
204
+ active: { type: 'boolean' }
205
+ },
206
+ required: ['name', 'email', 'role']
207
+ }
208
+
209
+ <PanelForm<UserFormData>
210
+ schema={userSchema}
211
+ onSubmit={handleSubmit}
212
+ defaultValues={defaultValues}
213
+ >
214
+ <FormField
215
+ name="name"
216
+ label="Full Name"
217
+ type="text"
218
+ required
219
+ />
220
+
221
+ <FormField
222
+ name="email"
223
+ label="Email Address"
224
+ type="email"
225
+ required
226
+ />
227
+
228
+ <FormSelect
229
+ name="role"
230
+ label="User Role"
231
+ options={[
232
+ { value: 'admin', label: 'Administrator' },
233
+ { value: 'user', label: 'Regular User' }
234
+ ]}
235
+ required
236
+ />
237
+
238
+ <FormCheckbox
239
+ name="active"
240
+ label="Active User"
241
+ />
242
+
243
+ <FormButton type="submit" variant="contained">
244
+ Save User
245
+ </FormButton>
246
+ </PanelForm>
247
+ ```
248
+
249
+ ### Button Components
250
+
251
+ Enhanced button components with loading states and Material-UI integration.
252
+
253
+ ```typescript
254
+ import { PanelButton, IconButton, FloatingActionButton } from '@owlmeans/web-panel'
255
+
256
+ <PanelButton
257
+ variant="contained"
258
+ color="primary"
259
+ startIcon={<SaveIcon />}
260
+ loading={isSaving}
261
+ onClick={handleSave}
262
+ >
263
+ Save Changes
264
+ </PanelButton>
265
+
266
+ <IconButton
267
+ color="secondary"
268
+ onClick={handleEdit}
269
+ tooltip="Edit Item"
270
+ >
271
+ <EditIcon />
272
+ </IconButton>
273
+
274
+ <FloatingActionButton
275
+ color="primary"
276
+ onClick={handleAdd}
277
+ position="bottom-right"
278
+ >
279
+ <AddIcon />
280
+ </FloatingActionButton>
281
+ ```
282
+
283
+ ### File Upload Components
284
+
285
+ Comprehensive file upload system with progress tracking and validation.
286
+
287
+ ```typescript
288
+ import {
289
+ FileUploader,
290
+ ImageUploader,
291
+ MultiFileUploader,
292
+ DropZone
293
+ } from '@owlmeans/web-panel'
294
+
295
+ <FileUploader
296
+ accept=".pdf,.doc,.docx"
297
+ maxSize={10 * 1024 * 1024} // 10MB
298
+ onUpload={handleFileUpload}
299
+ onProgress={handleProgress}
300
+ onError={handleError}
301
+ />
302
+
303
+ <ImageUploader
304
+ accept="image/*"
305
+ maxSize={5 * 1024 * 1024} // 5MB
306
+ cropAspectRatio={16/9}
307
+ onUpload={handleImageUpload}
308
+ preview={true}
309
+ />
310
+
311
+ <MultiFileUploader
312
+ maxFiles={5}
313
+ accept="*/*"
314
+ onUploadAll={handleMultipleUpload}
315
+ showProgress={true}
316
+ />
317
+
318
+ <DropZone
319
+ onDrop={handleFileDrop}
320
+ accept=".zip,.tar.gz"
321
+ multiple={false}
322
+ >
323
+ Drop files here or click to browse
324
+ </DropZone>
325
+ ```
326
+
327
+ ### Text and Display Components
328
+
329
+ Typography and content display components.
330
+
331
+ ```typescript
332
+ import {
333
+ PanelText,
334
+ PanelLink,
335
+ StatusIndicator,
336
+ InfoBlock
337
+ } from '@owlmeans/web-panel'
338
+
339
+ <PanelText variant="h4" color="primary" gutterBottom>
340
+ Panel Title
341
+ </PanelText>
342
+
343
+ <PanelLink href="/admin/users" external={false}>
344
+ Manage Users
345
+ </PanelLink>
346
+
347
+ <StatusIndicator
348
+ status="success"
349
+ message="Operation completed successfully"
350
+ />
351
+
352
+ <InfoBlock
353
+ title="Important Notice"
354
+ severity="warning"
355
+ actions={[
356
+ { label: 'Dismiss', onClick: handleDismiss },
357
+ { label: 'Learn More', onClick: openDetails }
358
+ ]}
359
+ >
360
+ This action cannot be undone.
361
+ </InfoBlock>
362
+ ```
363
+
364
+ ### Authentication Components
365
+
366
+ Built-in authentication UI components and flows.
367
+
368
+ ```typescript
369
+ import {
370
+ LoginForm,
371
+ LogoutButton,
372
+ UserProfile,
373
+ AuthGuard,
374
+ PermissionGuard
375
+ } from '@owlmeans/web-panel/auth'
376
+
377
+ <AuthGuard fallback={<LoginForm />}>
378
+ <PanelApp context={context}>
379
+ <PermissionGuard permissions={['admin']}>
380
+ <AdminPanel />
381
+ </PermissionGuard>
382
+ </PanelApp>
383
+ </AuthGuard>
384
+
385
+ <LoginForm
386
+ onSuccess={handleLoginSuccess}
387
+ onError={handleLoginError}
388
+ showRegister={true}
389
+ showForgotPassword={true}
390
+ />
391
+
392
+ <UserProfile
393
+ showAvatar={true}
394
+ showMenu={true}
395
+ menuActions={[
396
+ { label: 'Settings', onClick: openSettings },
397
+ { label: 'Logout', onClick: handleLogout }
398
+ ]}
399
+ />
400
+ ```
401
+
402
+ ## Usage Examples
403
+
404
+ ### Complete Panel Application
405
+
406
+ ```typescript
407
+ import React from 'react'
408
+ import { render } from '@owlmeans/web-panel'
409
+ import { makeWebContext } from '@owlmeans/web-client'
410
+ import { createTheme } from '@mui/material/styles'
411
+ import {
412
+ PanelApp,
413
+ PanelLayout,
414
+ PanelHeader,
415
+ PanelSidebar,
416
+ PanelContent,
417
+ AuthGuard
418
+ } from '@owlmeans/web-panel'
419
+
420
+ const config = {
421
+ service: 'admin-panel',
422
+ type: AppType.Frontend,
423
+ layer: Layer.Service
424
+ }
425
+
426
+ const theme = createTheme({
427
+ palette: {
428
+ mode: 'light',
429
+ primary: {
430
+ main: '#1976d2',
431
+ contrastText: '#ffffff'
432
+ },
433
+ secondary: {
434
+ main: '#dc004e'
435
+ },
436
+ background: {
437
+ default: '#f5f5f5',
438
+ paper: '#ffffff'
439
+ }
440
+ },
441
+ typography: {
442
+ fontFamily: 'Roboto, Arial, sans-serif',
443
+ h1: {
444
+ fontSize: '2.5rem',
445
+ fontWeight: 500
446
+ }
447
+ },
448
+ shape: {
449
+ borderRadius: 8
450
+ }
451
+ })
452
+
453
+ const AdminPanelApp: React.FC = () => {
454
+ const context = makeWebContext(config)
455
+
456
+ return (
457
+ <PanelApp context={context} theme={theme}>
458
+ <AuthGuard>
459
+ <PanelLayout>
460
+ <PanelHeader title="Administration Panel">
461
+ <UserProfile />
462
+ </PanelHeader>
463
+
464
+ <PanelSidebar>
465
+ <AdminNavigation />
466
+ </PanelSidebar>
467
+
468
+ <PanelContent>
469
+ <AdminRouter />
470
+ </PanelContent>
471
+ </PanelLayout>
472
+ </AuthGuard>
473
+ </PanelApp>
474
+ )
475
+ }
476
+
477
+ // Render the application
478
+ render(makeWebContext(config), theme)
479
+ ```
480
+
481
+ ### User Management Interface
482
+
483
+ ```typescript
484
+ import React, { useState, useEffect } from 'react'
485
+ import {
486
+ PanelForm,
487
+ FormField,
488
+ FormSelect,
489
+ FormButton,
490
+ PanelButton,
491
+ StatusIndicator,
492
+ InfoBlock
493
+ } from '@owlmeans/web-panel'
494
+ import { Grid, Card, CardContent, Typography } from '@mui/material'
495
+
496
+ interface User {
497
+ id: string
498
+ name: string
499
+ email: string
500
+ role: string
501
+ active: boolean
502
+ createdAt: Date
503
+ }
504
+
505
+ const UserManagement: React.FC = () => {
506
+ const [users, setUsers] = useState<User[]>([])
507
+ const [loading, setLoading] = useState(true)
508
+ const [editing, setEditing] = useState<User | null>(null)
509
+ const [error, setError] = useState<string | null>(null)
510
+
511
+ useEffect(() => {
512
+ loadUsers()
513
+ }, [])
514
+
515
+ const loadUsers = async () => {
516
+ try {
517
+ setLoading(true)
518
+ const response = await fetch('/api/users')
519
+ const userData = await response.json()
520
+ setUsers(userData)
521
+ } catch (err) {
522
+ setError('Failed to load users')
523
+ } finally {
524
+ setLoading(false)
525
+ }
526
+ }
527
+
528
+ const handleUserSave = async (userData: Partial<User>) => {
529
+ try {
530
+ const url = editing ? `/api/users/${editing.id}` : '/api/users'
531
+ const method = editing ? 'PUT' : 'POST'
532
+
533
+ const response = await fetch(url, {
534
+ method,
535
+ headers: { 'Content-Type': 'application/json' },
536
+ body: JSON.stringify(userData)
537
+ })
538
+
539
+ if (response.ok) {
540
+ await loadUsers()
541
+ setEditing(null)
542
+ } else {
543
+ setError('Failed to save user')
544
+ }
545
+ } catch (err) {
546
+ setError('Network error')
547
+ }
548
+ }
549
+
550
+ const handleUserDelete = async (userId: string) => {
551
+ if (!confirm('Are you sure you want to delete this user?')) return
552
+
553
+ try {
554
+ const response = await fetch(`/api/users/${userId}`, { method: 'DELETE' })
555
+ if (response.ok) {
556
+ await loadUsers()
557
+ } else {
558
+ setError('Failed to delete user')
559
+ }
560
+ } catch (err) {
561
+ setError('Network error')
562
+ }
563
+ }
564
+
565
+ const userSchema = {
566
+ type: 'object',
567
+ properties: {
568
+ name: { type: 'string', minLength: 2, maxLength: 100 },
569
+ email: { type: 'string', format: 'email' },
570
+ role: { type: 'string', enum: ['admin', 'user', 'moderator'] },
571
+ active: { type: 'boolean' }
572
+ },
573
+ required: ['name', 'email', 'role']
574
+ }
575
+
576
+ if (loading) {
577
+ return <StatusIndicator status="loading" message="Loading users..." />
578
+ }
579
+
580
+ return (
581
+ <Grid container spacing={3}>
582
+ <Grid item xs={12}>
583
+ <Typography variant="h4" gutterBottom>
584
+ User Management
585
+ </Typography>
586
+
587
+ {error && (
588
+ <InfoBlock severity="error" onClose={() => setError(null)}>
589
+ {error}
590
+ </InfoBlock>
591
+ )}
592
+ </Grid>
593
+
594
+ <Grid item xs={12} md={8}>
595
+ <Card>
596
+ <CardContent>
597
+ <Typography variant="h6" gutterBottom>
598
+ Users
599
+ </Typography>
600
+
601
+ <PanelButton
602
+ variant="contained"
603
+ color="primary"
604
+ onClick={() => setEditing({} as User)}
605
+ sx={{ mb: 2 }}
606
+ >
607
+ Add New User
608
+ </PanelButton>
609
+
610
+ {users.map(user => (
611
+ <Card key={user.id} variant="outlined" sx={{ mb: 1 }}>
612
+ <CardContent>
613
+ <Grid container alignItems="center" spacing={2}>
614
+ <Grid item xs>
615
+ <Typography variant="subtitle1">{user.name}</Typography>
616
+ <Typography variant="body2" color="textSecondary">
617
+ {user.email} • {user.role}
618
+ </Typography>
619
+ </Grid>
620
+ <Grid item>
621
+ <StatusIndicator
622
+ status={user.active ? 'success' : 'warning'}
623
+ message={user.active ? 'Active' : 'Inactive'}
624
+ />
625
+ </Grid>
626
+ <Grid item>
627
+ <PanelButton
628
+ size="small"
629
+ onClick={() => setEditing(user)}
630
+ >
631
+ Edit
632
+ </PanelButton>
633
+ <PanelButton
634
+ size="small"
635
+ color="error"
636
+ onClick={() => handleUserDelete(user.id)}
637
+ sx={{ ml: 1 }}
638
+ >
639
+ Delete
640
+ </PanelButton>
641
+ </Grid>
642
+ </Grid>
643
+ </CardContent>
644
+ </Card>
645
+ ))}
646
+ </CardContent>
647
+ </Card>
648
+ </Grid>
649
+
650
+ <Grid item xs={12} md={4}>
651
+ {editing && (
652
+ <Card>
653
+ <CardContent>
654
+ <Typography variant="h6" gutterBottom>
655
+ {editing.id ? 'Edit User' : 'Add User'}
656
+ </Typography>
657
+
658
+ <PanelForm
659
+ schema={userSchema}
660
+ defaultValues={editing}
661
+ onSubmit={handleUserSave}
662
+ >
663
+ <FormField
664
+ name="name"
665
+ label="Full Name"
666
+ required
667
+ fullWidth
668
+ margin="normal"
669
+ />
670
+
671
+ <FormField
672
+ name="email"
673
+ label="Email Address"
674
+ type="email"
675
+ required
676
+ fullWidth
677
+ margin="normal"
678
+ />
679
+
680
+ <FormSelect
681
+ name="role"
682
+ label="Role"
683
+ required
684
+ fullWidth
685
+ margin="normal"
686
+ options={[
687
+ { value: 'user', label: 'Regular User' },
688
+ { value: 'moderator', label: 'Moderator' },
689
+ { value: 'admin', label: 'Administrator' }
690
+ ]}
691
+ />
692
+
693
+ <FormField
694
+ name="active"
695
+ label="Active User"
696
+ type="checkbox"
697
+ margin="normal"
698
+ />
699
+
700
+ <Grid container spacing={2} sx={{ mt: 2 }}>
701
+ <Grid item>
702
+ <FormButton
703
+ type="submit"
704
+ variant="contained"
705
+ color="primary"
706
+ >
707
+ {editing.id ? 'Update' : 'Create'}
708
+ </FormButton>
709
+ </Grid>
710
+ <Grid item>
711
+ <PanelButton
712
+ variant="outlined"
713
+ onClick={() => setEditing(null)}
714
+ >
715
+ Cancel
716
+ </PanelButton>
717
+ </Grid>
718
+ </Grid>
719
+ </PanelForm>
720
+ </CardContent>
721
+ </Card>
722
+ )}
723
+ </Grid>
724
+ </Grid>
725
+ )
726
+ }
727
+
728
+ export default UserManagement
729
+ ```
730
+
731
+ ### File Upload Interface
732
+
733
+ ```typescript
734
+ import React, { useState } from 'react'
735
+ import {
736
+ FileUploader,
737
+ ImageUploader,
738
+ MultiFileUploader,
739
+ StatusIndicator,
740
+ PanelButton
741
+ } from '@owlmeans/web-panel'
742
+ import { Grid, Card, CardContent, Typography, LinearProgress } from '@mui/material'
743
+
744
+ const FileManagement: React.FC = () => {
745
+ const [uploadProgress, setUploadProgress] = useState<Record<string, number>>({})
746
+ const [uploadedFiles, setUploadedFiles] = useState<string[]>([])
747
+
748
+ const handleFileUpload = async (file: File, progressCallback: (progress: number) => void) => {
749
+ const formData = new FormData()
750
+ formData.append('file', file)
751
+
752
+ try {
753
+ const xhr = new XMLHttpRequest()
754
+
755
+ xhr.upload.addEventListener('progress', (e) => {
756
+ if (e.lengthComputable) {
757
+ const progress = (e.loaded / e.total) * 100
758
+ progressCallback(progress)
759
+ setUploadProgress(prev => ({ ...prev, [file.name]: progress }))
760
+ }
761
+ })
762
+
763
+ xhr.addEventListener('load', () => {
764
+ if (xhr.status === 200) {
765
+ setUploadedFiles(prev => [...prev, file.name])
766
+ setUploadProgress(prev => {
767
+ const updated = { ...prev }
768
+ delete updated[file.name]
769
+ return updated
770
+ })
771
+ }
772
+ })
773
+
774
+ xhr.open('POST', '/api/upload')
775
+ xhr.send(formData)
776
+ } catch (error) {
777
+ console.error('Upload failed:', error)
778
+ }
779
+ }
780
+
781
+ const handleImageUpload = async (file: File, cropData?: any) => {
782
+ console.log('Uploading image:', file.name, 'Crop data:', cropData)
783
+ // Implement image upload with crop data
784
+ }
785
+
786
+ const handleMultipleUpload = async (files: File[]) => {
787
+ for (const file of files) {
788
+ await handleFileUpload(file, () => {})
789
+ }
790
+ }
791
+
792
+ return (
793
+ <Grid container spacing={3}>
794
+ <Grid item xs={12}>
795
+ <Typography variant="h4" gutterBottom>
796
+ File Management
797
+ </Typography>
798
+ </Grid>
799
+
800
+ <Grid item xs={12} md={6}>
801
+ <Card>
802
+ <CardContent>
803
+ <Typography variant="h6" gutterBottom>
804
+ Document Upload
805
+ </Typography>
806
+
807
+ <FileUploader
808
+ accept=".pdf,.doc,.docx,.txt"
809
+ maxSize={10 * 1024 * 1024} // 10MB
810
+ onUpload={handleFileUpload}
811
+ multiple={false}
812
+ />
813
+ </CardContent>
814
+ </Card>
815
+ </Grid>
816
+
817
+ <Grid item xs={12} md={6}>
818
+ <Card>
819
+ <CardContent>
820
+ <Typography variant="h6" gutterBottom>
821
+ Image Upload
822
+ </Typography>
823
+
824
+ <ImageUploader
825
+ accept="image/*"
826
+ maxSize={5 * 1024 * 1024} // 5MB
827
+ cropAspectRatio={16/9}
828
+ onUpload={handleImageUpload}
829
+ preview={true}
830
+ cropperOptions={{
831
+ guides: false,
832
+ center: false,
833
+ highlight: false,
834
+ background: false,
835
+ autoCropArea: 1,
836
+ checkOrientation: false
837
+ }}
838
+ />
839
+ </CardContent>
840
+ </Card>
841
+ </Grid>
842
+
843
+ <Grid item xs={12}>
844
+ <Card>
845
+ <CardContent>
846
+ <Typography variant="h6" gutterBottom>
847
+ Multiple File Upload
848
+ </Typography>
849
+
850
+ <MultiFileUploader
851
+ maxFiles={5}
852
+ accept="*/*"
853
+ onUploadAll={handleMultipleUpload}
854
+ showProgress={true}
855
+ />
856
+
857
+ {Object.entries(uploadProgress).map(([fileName, progress]) => (
858
+ <div key={fileName}>
859
+ <Typography variant="body2" gutterBottom>
860
+ {fileName}
861
+ </Typography>
862
+ <LinearProgress
863
+ variant="determinate"
864
+ value={progress}
865
+ sx={{ mb: 1 }}
866
+ />
867
+ </div>
868
+ ))}
869
+ </CardContent>
870
+ </Card>
871
+ </Grid>
872
+
873
+ {uploadedFiles.length > 0 && (
874
+ <Grid item xs={12}>
875
+ <Card>
876
+ <CardContent>
877
+ <Typography variant="h6" gutterBottom>
878
+ Uploaded Files
879
+ </Typography>
880
+
881
+ {uploadedFiles.map(fileName => (
882
+ <StatusIndicator
883
+ key={fileName}
884
+ status="success"
885
+ message={`${fileName} uploaded successfully`}
886
+ />
887
+ ))}
888
+ </CardContent>
889
+ </Card>
890
+ </Grid>
891
+ )}
892
+ </Grid>
893
+ )
894
+ }
895
+
896
+ export default FileManagement
897
+ ```
898
+
899
+ ## Authentication Integration
900
+
901
+ ### Protected Routes and Components
902
+
903
+ ```typescript
904
+ import { AuthGuard, PermissionGuard } from '@owlmeans/web-panel/auth'
905
+ import { Navigate } from 'react-router-dom'
906
+
907
+ // Protect entire application
908
+ <AuthGuard fallback={<Navigate to="/login" />}>
909
+ <PanelApp context={context}>
910
+ <Router>
911
+ <Routes>
912
+ <Route path="/admin" element={
913
+ <PermissionGuard permissions={['admin']}>
914
+ <AdminPanel />
915
+ </PermissionGuard>
916
+ } />
917
+ <Route path="/users" element={
918
+ <PermissionGuard permissions={['user-management']}>
919
+ <UserManagement />
920
+ </PermissionGuard>
921
+ } />
922
+ </Routes>
923
+ </Router>
924
+ </PanelApp>
925
+ </AuthGuard>
926
+
927
+ // Conditional rendering based on permissions
928
+ const AdminActions: React.FC = () => (
929
+ <PermissionGuard permissions={['admin', 'moderator']}>
930
+ {(hasPermission) => (
931
+ <PanelButton
932
+ disabled={!hasPermission}
933
+ onClick={handleAdminAction}
934
+ >
935
+ Admin Action
936
+ </PanelButton>
937
+ )}
938
+ </PermissionGuard>
939
+ )
940
+ ```
941
+
942
+ ## Theme Customization
943
+
944
+ ### Custom Material-UI Theme
945
+
946
+ ```typescript
947
+ import { createTheme, ThemeProvider } from '@mui/material/styles'
948
+
949
+ const customTheme = createTheme({
950
+ palette: {
951
+ mode: 'light',
952
+ primary: {
953
+ main: '#1976d2',
954
+ light: '#42a5f5',
955
+ dark: '#1565c0',
956
+ contrastText: '#ffffff'
957
+ },
958
+ secondary: {
959
+ main: '#dc004e',
960
+ light: '#f06292',
961
+ dark: '#c2185b',
962
+ contrastText: '#ffffff'
963
+ },
964
+ background: {
965
+ default: '#f5f5f5',
966
+ paper: '#ffffff'
967
+ },
968
+ text: {
969
+ primary: '#212121',
970
+ secondary: '#757575'
971
+ }
972
+ },
973
+ typography: {
974
+ fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
975
+ h1: {
976
+ fontSize: '2.5rem',
977
+ fontWeight: 500,
978
+ lineHeight: 1.2
979
+ },
980
+ h2: {
981
+ fontSize: '2rem',
982
+ fontWeight: 500,
983
+ lineHeight: 1.3
984
+ },
985
+ body1: {
986
+ fontSize: '1rem',
987
+ lineHeight: 1.5
988
+ }
989
+ },
990
+ shape: {
991
+ borderRadius: 8
992
+ },
993
+ spacing: 8,
994
+ components: {
995
+ MuiCard: {
996
+ styleOverrides: {
997
+ root: {
998
+ boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
999
+ '&:hover': {
1000
+ boxShadow: '0 4px 16px rgba(0,0,0,0.15)'
1001
+ }
1002
+ }
1003
+ }
1004
+ },
1005
+ MuiButton: {
1006
+ styleOverrides: {
1007
+ root: {
1008
+ borderRadius: 8,
1009
+ textTransform: 'none',
1010
+ fontWeight: 500
1011
+ }
1012
+ }
1013
+ }
1014
+ }
1015
+ })
1016
+
1017
+ // Apply theme to panel app
1018
+ <PanelApp context={context} theme={customTheme}>
1019
+ <AdminInterface />
1020
+ </PanelApp>
1021
+ ```
1022
+
1023
+ ## Internationalization
1024
+
1025
+ ### Multi-language Support
1026
+
1027
+ ```typescript
1028
+ import { addI18nApp } from '@owlmeans/i18n'
1029
+
1030
+ // Add translations for panel
1031
+ addI18nApp('en', 'panel', {
1032
+ 'panel.title': 'Administration Panel',
1033
+ 'users.title': 'User Management',
1034
+ 'users.add': 'Add New User',
1035
+ 'users.edit': 'Edit User',
1036
+ 'users.delete': 'Delete User',
1037
+ 'form.save': 'Save',
1038
+ 'form.cancel': 'Cancel',
1039
+ 'status.loading': 'Loading...',
1040
+ 'status.error': 'An error occurred',
1041
+ 'status.success': 'Operation completed successfully'
1042
+ })
1043
+
1044
+ addI18nApp('es', 'panel', {
1045
+ 'panel.title': 'Panel de Administración',
1046
+ 'users.title': 'Gestión de Usuarios',
1047
+ 'users.add': 'Agregar Nuevo Usuario',
1048
+ 'users.edit': 'Editar Usuario',
1049
+ 'users.delete': 'Eliminar Usuario',
1050
+ 'form.save': 'Guardar',
1051
+ 'form.cancel': 'Cancelar',
1052
+ 'status.loading': 'Cargando...',
1053
+ 'status.error': 'Ocurrió un error',
1054
+ 'status.success': 'Operación completada exitosamente'
1055
+ })
1056
+
1057
+ // Use translations in components
1058
+ import { useTranslation } from '@owlmeans/client-i18n'
1059
+
1060
+ const UserPanel: React.FC = () => {
1061
+ const { t } = useTranslation()
1062
+
1063
+ return (
1064
+ <Typography variant="h4">
1065
+ {t('users.title')}
1066
+ </Typography>
1067
+ )
1068
+ }
1069
+ ```
1070
+
1071
+ ## Performance Optimization
1072
+
1073
+ ### Code Splitting and Lazy Loading
1074
+
1075
+ ```typescript
1076
+ import React, { lazy, Suspense } from 'react'
1077
+ import { StatusIndicator } from '@owlmeans/web-panel'
1078
+
1079
+ // Lazy load panel sections
1080
+ const UserManagement = lazy(() => import('./UserManagement'))
1081
+ const SystemSettings = lazy(() => import('./SystemSettings'))
1082
+ const Reports = lazy(() => import('./Reports'))
1083
+
1084
+ const AdminRouter: React.FC = () => (
1085
+ <Routes>
1086
+ <Route path="/users" element={
1087
+ <Suspense fallback={<StatusIndicator status="loading" message="Loading users..." />}>
1088
+ <UserManagement />
1089
+ </Suspense>
1090
+ } />
1091
+ <Route path="/settings" element={
1092
+ <Suspense fallback={<StatusIndicator status="loading" message="Loading settings..." />}>
1093
+ <SystemSettings />
1094
+ </Suspense>
1095
+ } />
1096
+ <Route path="/reports" element={
1097
+ <Suspense fallback={<StatusIndicator status="loading" message="Loading reports..." />}>
1098
+ <Reports />
1099
+ </Suspense>
1100
+ } />
1101
+ </Routes>
1102
+ )
1103
+ ```
1104
+
1105
+ ### Memoization and Optimization
1106
+
1107
+ ```typescript
1108
+ import React, { memo, useMemo, useCallback } from 'react'
1109
+
1110
+ const OptimizedUserList = memo<{ users: User[]; onUserSelect: (user: User) => void }>(({
1111
+ users,
1112
+ onUserSelect
1113
+ }) => {
1114
+ const sortedUsers = useMemo(() =>
1115
+ users.sort((a, b) => a.name.localeCompare(b.name)),
1116
+ [users]
1117
+ )
1118
+
1119
+ const handleUserClick = useCallback((user: User) => {
1120
+ onUserSelect(user)
1121
+ }, [onUserSelect])
1122
+
1123
+ return (
1124
+ <div>
1125
+ {sortedUsers.map(user => (
1126
+ <UserCard
1127
+ key={user.id}
1128
+ user={user}
1129
+ onClick={handleUserClick}
1130
+ />
1131
+ ))}
1132
+ </div>
1133
+ )
1134
+ })
1135
+ ```
1136
+
1137
+ ## Best Practices
1138
+
1139
+ 1. **Component Structure**: Use consistent component hierarchy and naming conventions
1140
+ 2. **Theme Management**: Leverage Material-UI theme system for consistent styling
1141
+ 3. **Form Validation**: Use AJV schemas for robust form validation
1142
+ 4. **Error Handling**: Provide comprehensive error feedback and recovery options
1143
+ 5. **Performance**: Implement code splitting and memoization for large applications
1144
+ 6. **Accessibility**: Ensure all components meet WCAG accessibility standards
1145
+ 7. **Internationalization**: Always use i18n for user-facing text
1146
+ 8. **Testing**: Write comprehensive tests for form validation and user interactions
1147
+
1148
+ ## Authentication Modules
1149
+
1150
+ The package provides authentication-specific modules and components:
1151
+
1152
+ ```typescript
1153
+ import { modules } from '@owlmeans/web-panel/auth/modules'
1154
+ import { AuthProvider, LoginForm } from '@owlmeans/web-panel/auth'
1155
+
1156
+ // Register authentication modules
1157
+ context.registerModules(modules)
1158
+
1159
+ // Use authentication components
1160
+ <AuthProvider context={context}>
1161
+ <LoginForm
1162
+ onSuccess={handleLogin}
1163
+ features={{
1164
+ showRegister: true,
1165
+ showForgotPassword: true,
1166
+ showRememberMe: true
1167
+ }}
1168
+ />
1169
+ </AuthProvider>
1170
+ ```
1171
+
1172
+ ## Related Packages
1173
+
1174
+ - **@owlmeans/client-panel**: Base panel functionality and context
1175
+ - **@owlmeans/native-panel**: React Native panel implementation
1176
+ - **@owlmeans/web-client**: Web client framework and rendering
1177
+ - **@owlmeans/client-auth**: Authentication components and services
1178
+ - **@owlmeans/client-flow**: Flow management integration
1179
+ - **@owlmeans/web-flow**: Web-specific flow implementations
1180
+
1181
+ ## TypeScript Support
1182
+
1183
+ This package is written in TypeScript and provides full type safety:
1184
+
1185
+ ```typescript
1186
+ import type {
1187
+ PanelAppProps,
1188
+ FormFieldProps,
1189
+ FileUploaderProps,
1190
+ AuthGuardProps
1191
+ } from '@owlmeans/web-panel'
1192
+
1193
+ const MyPanel: FC<PanelAppProps> = (props) => { /* ... */ }
1194
+ const MyForm: FC<{ onSubmit: (data: FormData) => void }> = ({ onSubmit }) => { /* ... */ }
1195
+ ```