@owlmeans/client-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 (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +791 -0
  3. package/build/.gitkeep +0 -0
  4. package/build/auth/i18n/en.json +56 -0
  5. package/build/auth/i18n.d.ts +2 -0
  6. package/build/auth/i18n.d.ts.map +1 -0
  7. package/build/auth/i18n.js +4 -0
  8. package/build/auth/i18n.js.map +1 -0
  9. package/build/auth/index.d.ts +2 -0
  10. package/build/auth/index.d.ts.map +1 -0
  11. package/build/auth/index.js +2 -0
  12. package/build/auth/index.js.map +1 -0
  13. package/build/auth/plugins/consts.d.ts +4 -0
  14. package/build/auth/plugins/consts.d.ts.map +1 -0
  15. package/build/auth/plugins/consts.js +13 -0
  16. package/build/auth/plugins/consts.js.map +1 -0
  17. package/build/auth/plugins/exports.d.ts +3 -0
  18. package/build/auth/plugins/exports.d.ts.map +1 -0
  19. package/build/auth/plugins/exports.js +3 -0
  20. package/build/auth/plugins/exports.js.map +1 -0
  21. package/build/auth/plugins/types.d.ts +6 -0
  22. package/build/auth/plugins/types.d.ts.map +1 -0
  23. package/build/auth/plugins/types.js +2 -0
  24. package/build/auth/plugins/types.js.map +1 -0
  25. package/build/components/consts.d.ts +6 -0
  26. package/build/components/consts.d.ts.map +1 -0
  27. package/build/components/consts.js +7 -0
  28. package/build/components/consts.js.map +1 -0
  29. package/build/components/context.d.ts +9 -0
  30. package/build/components/context.d.ts.map +1 -0
  31. package/build/components/context.js +30 -0
  32. package/build/components/context.js.map +1 -0
  33. package/build/components/form/context.d.ts +8 -0
  34. package/build/components/form/context.d.ts.map +1 -0
  35. package/build/components/form/context.js +26 -0
  36. package/build/components/form/context.js.map +1 -0
  37. package/build/components/form/helper.d.ts +4 -0
  38. package/build/components/form/helper.d.ts.map +1 -0
  39. package/build/components/form/helper.js +5 -0
  40. package/build/components/form/helper.js.map +1 -0
  41. package/build/components/form/index.d.ts +4 -0
  42. package/build/components/form/index.d.ts.map +1 -0
  43. package/build/components/form/index.js +4 -0
  44. package/build/components/form/index.js.map +1 -0
  45. package/build/components/form/types.d.ts +33 -0
  46. package/build/components/form/types.d.ts.map +1 -0
  47. package/build/components/form/types.js +2 -0
  48. package/build/components/form/types.js.map +1 -0
  49. package/build/components/index.d.ts +6 -0
  50. package/build/components/index.d.ts.map +1 -0
  51. package/build/components/index.js +5 -0
  52. package/build/components/index.js.map +1 -0
  53. package/build/components/layout/helper.d.ts +6 -0
  54. package/build/components/layout/helper.d.ts.map +1 -0
  55. package/build/components/layout/helper.js +17 -0
  56. package/build/components/layout/helper.js.map +1 -0
  57. package/build/components/layout/index.d.ts +2 -0
  58. package/build/components/layout/index.d.ts.map +1 -0
  59. package/build/components/layout/index.js +2 -0
  60. package/build/components/layout/index.js.map +1 -0
  61. package/build/components/types.d.ts +7 -0
  62. package/build/components/types.d.ts.map +1 -0
  63. package/build/components/types.js +2 -0
  64. package/build/components/types.js.map +1 -0
  65. package/build/helper/form.d.ts +3 -0
  66. package/build/helper/form.d.ts.map +1 -0
  67. package/build/helper/form.js +5 -0
  68. package/build/helper/form.js.map +1 -0
  69. package/build/helper/index.d.ts +2 -0
  70. package/build/helper/index.d.ts.map +1 -0
  71. package/build/helper/index.js +2 -0
  72. package/build/helper/index.js.map +1 -0
  73. package/build/index.d.ts +3 -0
  74. package/build/index.d.ts.map +1 -0
  75. package/build/index.js +3 -0
  76. package/build/index.js.map +1 -0
  77. package/package.json +74 -0
  78. package/src/auth/i18n/en.json +56 -0
  79. package/src/auth/i18n.ts +5 -0
  80. package/src/auth/index.ts +2 -0
  81. package/src/auth/plugins/consts.ts +15 -0
  82. package/src/auth/plugins/exports.ts +3 -0
  83. package/src/auth/plugins/types.ts +6 -0
  84. package/src/components/consts.ts +6 -0
  85. package/src/components/context.tsx +44 -0
  86. package/src/components/form/context.tsx +39 -0
  87. package/src/components/form/helper.ts +7 -0
  88. package/src/components/form/index.ts +4 -0
  89. package/src/components/form/types.ts +37 -0
  90. package/src/components/index.ts +6 -0
  91. package/src/components/layout/helper.ts +26 -0
  92. package/src/components/layout/index.ts +2 -0
  93. package/src/components/types.ts +7 -0
  94. package/src/helper/form.ts +7 -0
  95. package/src/helper/index.ts +2 -0
  96. package/src/index.ts +3 -0
  97. package/tsconfig.json +16 -0
  98. package/tsconfig.tsbuildinfo +1 -0
package/README.md ADDED
@@ -0,0 +1,791 @@
1
+ # @owlmeans/client-panel
2
+
3
+ React client panel library for OwlMeans Common applications. This package provides a comprehensive set of UI components and utilities for building administrative panels, forms, and user interfaces with integrated internationalization, validation, and layout management.
4
+
5
+ ## Overview
6
+
7
+ The `@owlmeans/client-panel` package extends the OwlMeans client ecosystem with pre-built UI components designed for panel applications. It provides:
8
+
9
+ - **Form Components**: Advanced form handling with validation and internationalization
10
+ - **Layout Components**: Flexible layout system for panel interfaces
11
+ - **Authentication Components**: Pre-built authentication UI components
12
+ - **Helper Utilities**: Form helpers, context providers, and utility functions
13
+ - **Internationalization**: Full i18n support with contextual translations
14
+ - **Validation Integration**: AJV schema validation with React Hook Form
15
+ - **Error Handling**: Comprehensive error display and management
16
+ - **Responsive Design**: Mobile-friendly responsive layout components
17
+
18
+ This package is part of the OwlMeans panel UI ecosystem:
19
+ - **@owlmeans/client-panel**: React panel components *(this package)*
20
+ - **@owlmeans/web-panel**: Web-specific panel implementations
21
+ - **@owlmeans/native-panel**: React Native panel components
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ npm install @owlmeans/client-panel react react-hook-form
27
+ ```
28
+
29
+ ## Core Concepts
30
+
31
+ ### Panel Architecture
32
+ The library follows a component-based architecture where panels are composed of reusable UI elements with consistent styling and behavior.
33
+
34
+ ### Form Management
35
+ Built on React Hook Form with AJV schema validation, providing type-safe forms with automatic validation and error handling.
36
+
37
+ ### Internationalization
38
+ Full integration with OwlMeans i18n system for translatable UI components with context-aware translations.
39
+
40
+ ### Authentication Integration
41
+ Optional authentication components that integrate with the OwlMeans authentication system.
42
+
43
+ ## API Reference
44
+
45
+ ### Components
46
+
47
+ #### Form Components
48
+
49
+ The form system provides comprehensive form handling with validation, internationalization, and error management.
50
+
51
+ ##### `<Form />`
52
+
53
+ Main form component with integrated validation and submission handling.
54
+
55
+ ```typescript
56
+ interface FormProps extends PropsWithChildren<I18nProps> {
57
+ name?: string // Form identifier for i18n
58
+ formRef?: MutableRefObject<FormRef<any> | null> // Form reference
59
+ defaults?: Record<string, any> // Default form values
60
+ validation?: AnySchema // AJV validation schema
61
+ decorate?: boolean // Apply form decoration
62
+ horizontal?: BlockScaling // Horizontal layout scaling
63
+ vertical?: BlockScaling // Vertical layout scaling
64
+ onSubmit?: FormOnSubmit<any> // Submit handler
65
+ }
66
+
67
+ const Form: FC<FormProps>
68
+ ```
69
+
70
+ **Usage:**
71
+ ```typescript
72
+ import { Form, useFormRef } from '@owlmeans/client-panel'
73
+
74
+ function UserForm() {
75
+ const formRef = useFormRef()
76
+
77
+ const handleSubmit = async (data, update) => {
78
+ try {
79
+ await api.saveUser(data)
80
+ console.log('User saved successfully')
81
+ } catch (error) {
82
+ formRef.current?.error(error)
83
+ }
84
+ }
85
+
86
+ return (
87
+ <Form
88
+ name="user-form"
89
+ formRef={formRef}
90
+ defaults={{ name: '', email: '' }}
91
+ validation={userSchema}
92
+ onSubmit={handleSubmit}
93
+ >
94
+ <input name="name" placeholder="Name" />
95
+ <input name="email" placeholder="Email" />
96
+ <button type="submit">Save User</button>
97
+ </Form>
98
+ )
99
+ }
100
+ ```
101
+
102
+ #### Layout Components
103
+
104
+ Layout components provide structured panel layouts with responsive design.
105
+
106
+ ##### Layout Helper
107
+
108
+ ```typescript
109
+ import { LayoutHelper } from '@owlmeans/client-panel'
110
+
111
+ // Layout utilities and components
112
+ ```
113
+
114
+ ### Hooks and Utilities
115
+
116
+ #### `useFormRef<T>(): MutableRefObject<FormRef<T> | null>`
117
+
118
+ Creates a reference for form component interaction.
119
+
120
+ ```typescript
121
+ import { useFormRef } from '@owlmeans/client-panel'
122
+
123
+ function FormComponent() {
124
+ const formRef = useFormRef<UserData>()
125
+
126
+ const resetForm = () => {
127
+ formRef.current?.form.reset()
128
+ }
129
+
130
+ const updateForm = (data: UserData) => {
131
+ formRef.current?.update(data)
132
+ }
133
+
134
+ return (
135
+ <div>
136
+ <Form formRef={formRef}>
137
+ {/* form fields */}
138
+ </Form>
139
+ <button onClick={resetForm}>Reset</button>
140
+ </div>
141
+ )
142
+ }
143
+ ```
144
+
145
+ #### `useFormI18n(): I18nFunction`
146
+
147
+ Provides internationalization for form components with contextual prefixes.
148
+
149
+ ```typescript
150
+ import { useFormI18n } from '@owlmeans/client-panel'
151
+
152
+ function FormField() {
153
+ const t = useFormI18n()
154
+
155
+ return (
156
+ <div>
157
+ <label>{t('name.label')}</label>
158
+ <input placeholder={t('name.placeholder')} />
159
+ </div>
160
+ )
161
+ }
162
+ ```
163
+
164
+ #### `useFormError(name: string, error?: FieldError): string | undefined`
165
+
166
+ Provides internationalized error messages for form fields.
167
+
168
+ ```typescript
169
+ import { useFormError } from '@owlmeans/client-panel'
170
+ import { useFormState } from 'react-hook-form'
171
+
172
+ function FormField({ name }) {
173
+ const { errors } = useFormState()
174
+ const errorMessage = useFormError(name, errors[name])
175
+
176
+ return (
177
+ <div>
178
+ <input name={name} />
179
+ {errorMessage && <span className="error">{errorMessage}</span>}
180
+ </div>
181
+ )
182
+ }
183
+ ```
184
+
185
+ #### `useClientFormContext(): TFormContext`
186
+
187
+ Accesses the current form context for configuration and state.
188
+
189
+ ```typescript
190
+ import { useClientFormContext } from '@owlmeans/client-panel'
191
+
192
+ function CustomFormField() {
193
+ const formContext = useClientFormContext()
194
+
195
+ return (
196
+ <div className={formContext.horizontal ? 'horizontal' : 'vertical'}>
197
+ {/* field content */}
198
+ </div>
199
+ )
200
+ }
201
+ ```
202
+
203
+ ### Types and Interfaces
204
+
205
+ #### `FormRef<T>`
206
+
207
+ Reference interface for form component control.
208
+
209
+ ```typescript
210
+ interface FormRef<T extends FieldValues = FieldValues> {
211
+ form: UseFormReturn<T> // React Hook Form instance
212
+ update: (data: T) => void // Update form data
213
+ loader: Toggleable // Loading state control
214
+ error: (error: unknown, target?: string) => void // Error handling
215
+ }
216
+ ```
217
+
218
+ #### `FormOnSubmit<T>`
219
+
220
+ Submit handler interface for form components.
221
+
222
+ ```typescript
223
+ interface FormOnSubmit<T> {
224
+ (data: T, update?: (data: T) => void): Promise<void> | void
225
+ }
226
+ ```
227
+
228
+ #### `TFormContext`
229
+
230
+ Form context interface for component communication.
231
+
232
+ ```typescript
233
+ interface TFormContext extends Omit<FormProps, 'defaults' | 'children'> {
234
+ loader: Toggleable // Loading state management
235
+ }
236
+ ```
237
+
238
+ #### `FormFieldProps`
239
+
240
+ Base properties for form field components.
241
+
242
+ ```typescript
243
+ interface FormFieldProps {
244
+ name: string // Field name
245
+ def?: any // Default value
246
+ }
247
+ ```
248
+
249
+ ### Helper Functions
250
+
251
+ #### `schemaToFormDefault(schema: AnySchema): Record<string, any>`
252
+
253
+ Extracts default values from AJV schema for form initialization.
254
+
255
+ ```typescript
256
+ import { schemaToFormDefault } from '@owlmeans/client-panel'
257
+
258
+ const userSchema = {
259
+ type: 'object',
260
+ properties: {
261
+ name: { type: 'string', default: 'John Doe' },
262
+ email: { type: 'string', default: '' },
263
+ age: { type: 'number', default: 18 }
264
+ }
265
+ }
266
+
267
+ const defaults = schemaToFormDefault(userSchema)
268
+ // Result: { name: 'John Doe', email: '', age: 18 }
269
+ ```
270
+
271
+ ### Constants
272
+
273
+ #### `BlockScaling`
274
+
275
+ Enumeration for layout scaling options.
276
+
277
+ ```typescript
278
+ enum BlockScaling {
279
+ // Layout scaling values
280
+ }
281
+ ```
282
+
283
+ ### Authentication Components
284
+
285
+ The package includes optional authentication components accessible via the `/auth` export:
286
+
287
+ ```typescript
288
+ import { AuthComponents } from '@owlmeans/client-panel/auth'
289
+ import { AuthPlugins } from '@owlmeans/client-panel/auth/plugins'
290
+ ```
291
+
292
+ These components provide:
293
+ - Pre-built authentication forms
294
+ - Login and registration components
295
+ - Authentication plugins and extensions
296
+ - Integration with OwlMeans authentication system
297
+
298
+ ## Usage Examples
299
+
300
+ ### Basic Form with Validation
301
+
302
+ ```typescript
303
+ import React from 'react'
304
+ import { Form, useFormRef, schemaToFormDefault } from '@owlmeans/client-panel'
305
+ import { useFormState } from 'react-hook-form'
306
+
307
+ interface UserData {
308
+ name: string
309
+ email: string
310
+ age: number
311
+ }
312
+
313
+ const userSchema = {
314
+ type: 'object',
315
+ properties: {
316
+ name: { type: 'string', minLength: 2, default: '' },
317
+ email: { type: 'string', format: 'email', default: '' },
318
+ age: { type: 'number', minimum: 18, default: 18 }
319
+ },
320
+ required: ['name', 'email']
321
+ }
322
+
323
+ function UserRegistrationForm() {
324
+ const formRef = useFormRef<UserData>()
325
+ const defaults = schemaToFormDefault(userSchema)
326
+
327
+ const handleSubmit = async (data: UserData, update) => {
328
+ try {
329
+ // Show loading state
330
+ formRef.current?.loader.on()
331
+
332
+ // Submit data
333
+ await api.createUser(data)
334
+
335
+ // Success - reset form
336
+ formRef.current?.form.reset()
337
+
338
+ console.log('User created successfully')
339
+ } catch (error) {
340
+ // Handle error
341
+ formRef.current?.error(error)
342
+ } finally {
343
+ // Hide loading state
344
+ formRef.current?.loader.off()
345
+ }
346
+ }
347
+
348
+ return (
349
+ <Form
350
+ name="user-registration"
351
+ formRef={formRef}
352
+ defaults={defaults}
353
+ validation={userSchema}
354
+ onSubmit={handleSubmit}
355
+ decorate={true}
356
+ >
357
+ <UserFormFields />
358
+ </Form>
359
+ )
360
+ }
361
+
362
+ function UserFormFields() {
363
+ const { errors } = useFormState<UserData>()
364
+ const t = useFormI18n()
365
+ const nameError = useFormError('name', errors.name)
366
+ const emailError = useFormError('email', errors.email)
367
+
368
+ return (
369
+ <div>
370
+ <div>
371
+ <label>{t('name.label')}</label>
372
+ <input
373
+ name="name"
374
+ placeholder={t('name.placeholder')}
375
+ className={errors.name ? 'error' : ''}
376
+ />
377
+ {nameError && <span className="error-text">{nameError}</span>}
378
+ </div>
379
+
380
+ <div>
381
+ <label>{t('email.label')}</label>
382
+ <input
383
+ name="email"
384
+ type="email"
385
+ placeholder={t('email.placeholder')}
386
+ className={errors.email ? 'error' : ''}
387
+ />
388
+ {emailError && <span className="error-text">{emailError}</span>}
389
+ </div>
390
+
391
+ <div>
392
+ <label>{t('age.label')}</label>
393
+ <input
394
+ name="age"
395
+ type="number"
396
+ min="18"
397
+ />
398
+ </div>
399
+
400
+ <button type="submit">{t('submit')}</button>
401
+ </div>
402
+ )
403
+ }
404
+ ```
405
+
406
+ ### Form with Dynamic Validation
407
+
408
+ ```typescript
409
+ import { Form, useFormRef } from '@owlmeans/client-panel'
410
+ import { useState } from 'react'
411
+
412
+ function DynamicForm() {
413
+ const formRef = useFormRef()
414
+ const [formType, setFormType] = useState<'basic' | 'advanced'>('basic')
415
+
416
+ const basicSchema = {
417
+ type: 'object',
418
+ properties: {
419
+ name: { type: 'string', minLength: 2 },
420
+ email: { type: 'string', format: 'email' }
421
+ },
422
+ required: ['name', 'email']
423
+ }
424
+
425
+ const advancedSchema = {
426
+ type: 'object',
427
+ properties: {
428
+ ...basicSchema.properties,
429
+ phone: { type: 'string', pattern: '^\\+?[1-9]\\d{1,14}$' },
430
+ company: { type: 'string', minLength: 2 }
431
+ },
432
+ required: [...basicSchema.required, 'phone', 'company']
433
+ }
434
+
435
+ const currentSchema = formType === 'basic' ? basicSchema : advancedSchema
436
+
437
+ const handleSubmit = async (data) => {
438
+ console.log('Form data:', data)
439
+ console.log('Form type:', formType)
440
+ }
441
+
442
+ return (
443
+ <div>
444
+ <div>
445
+ <button onClick={() => setFormType('basic')}>Basic Form</button>
446
+ <button onClick={() => setFormType('advanced')}>Advanced Form</button>
447
+ </div>
448
+
449
+ <Form
450
+ name={`${formType}-form`}
451
+ formRef={formRef}
452
+ validation={currentSchema}
453
+ onSubmit={handleSubmit}
454
+ >
455
+ <input name="name" placeholder="Name" />
456
+ <input name="email" placeholder="Email" />
457
+
458
+ {formType === 'advanced' && (
459
+ <>
460
+ <input name="phone" placeholder="Phone" />
461
+ <input name="company" placeholder="Company" />
462
+ </>
463
+ )}
464
+
465
+ <button type="submit">Submit {formType} Form</button>
466
+ </Form>
467
+ </div>
468
+ )
469
+ }
470
+ ```
471
+
472
+ ### Internationalized Form
473
+
474
+ ```typescript
475
+ import { Form, useFormI18n, useFormError } from '@owlmeans/client-panel'
476
+ import { addI18nApp } from '@owlmeans/i18n'
477
+
478
+ // Add translations
479
+ addI18nApp('en', 'user-form', {
480
+ 'name.label': 'Full Name',
481
+ 'name.placeholder': 'Enter your full name',
482
+ 'email.label': 'Email Address',
483
+ 'email.placeholder': 'Enter your email',
484
+ 'submit': 'Create Account',
485
+ 'name.errors.minLength': 'Name must be at least 2 characters',
486
+ 'email.errors.format': 'Please enter a valid email address'
487
+ })
488
+
489
+ addI18nApp('es', 'user-form', {
490
+ 'name.label': 'Nombre Completo',
491
+ 'name.placeholder': 'Ingrese su nombre completo',
492
+ 'email.label': 'Dirección de Correo',
493
+ 'email.placeholder': 'Ingrese su correo',
494
+ 'submit': 'Crear Cuenta',
495
+ 'name.errors.minLength': 'El nombre debe tener al menos 2 caracteres',
496
+ 'email.errors.format': 'Por favor ingrese un correo válido'
497
+ })
498
+
499
+ function InternationalizedForm() {
500
+ const formRef = useFormRef()
501
+
502
+ const handleSubmit = async (data) => {
503
+ console.log('Localized form data:', data)
504
+ }
505
+
506
+ return (
507
+ <Form
508
+ name="user-form"
509
+ formRef={formRef}
510
+ validation={userSchema}
511
+ onSubmit={handleSubmit}
512
+ i18n={{
513
+ resource: 'user-form',
514
+ ns: 'user-form'
515
+ }}
516
+ >
517
+ <LocalizedFormFields />
518
+ </Form>
519
+ )
520
+ }
521
+
522
+ function LocalizedFormFields() {
523
+ const { errors } = useFormState()
524
+ const t = useFormI18n()
525
+ const nameError = useFormError('name', errors.name)
526
+ const emailError = useFormError('email', errors.email)
527
+
528
+ return (
529
+ <div>
530
+ <div>
531
+ <label>{t('name.label')}</label>
532
+ <input
533
+ name="name"
534
+ placeholder={t('name.placeholder')}
535
+ />
536
+ {nameError && <div className="error">{nameError}</div>}
537
+ </div>
538
+
539
+ <div>
540
+ <label>{t('email.label')}</label>
541
+ <input
542
+ name="email"
543
+ placeholder={t('email.placeholder')}
544
+ />
545
+ {emailError && <div className="error">{emailError}</div>}
546
+ </div>
547
+
548
+ <button type="submit">{t('submit')}</button>
549
+ </div>
550
+ )
551
+ }
552
+ ```
553
+
554
+ ### Form with Custom Error Handling
555
+
556
+ ```typescript
557
+ import { Form, useFormRef } from '@owlmeans/client-panel'
558
+ import { OwlMeansError } from '@owlmeans/error'
559
+
560
+ function FormWithErrorHandling() {
561
+ const formRef = useFormRef()
562
+ const [serverErrors, setServerErrors] = useState({})
563
+
564
+ const handleSubmit = async (data) => {
565
+ try {
566
+ setServerErrors({})
567
+ formRef.current?.loader.on()
568
+
569
+ await api.submitData(data)
570
+
571
+ // Success
572
+ formRef.current?.form.reset()
573
+ } catch (error) {
574
+ if (error instanceof OwlMeansError) {
575
+ // Handle specific OwlMeans errors
576
+ if (error.code === 'VALIDATION_ERROR') {
577
+ setServerErrors(error.details || {})
578
+ } else {
579
+ formRef.current?.error(error, 'general')
580
+ }
581
+ } else {
582
+ // Handle generic errors
583
+ formRef.current?.error(error)
584
+ }
585
+ } finally {
586
+ formRef.current?.loader.off()
587
+ }
588
+ }
589
+
590
+ return (
591
+ <Form
592
+ name="error-handling-form"
593
+ formRef={formRef}
594
+ onSubmit={handleSubmit}
595
+ >
596
+ <div>
597
+ <input name="email" />
598
+ {serverErrors.email && (
599
+ <div className="server-error">{serverErrors.email}</div>
600
+ )}
601
+ </div>
602
+
603
+ <button type="submit">Submit</button>
604
+ </Form>
605
+ )
606
+ }
607
+ ```
608
+
609
+ ### Layout Components Usage
610
+
611
+ ```typescript
612
+ import { LayoutHelper } from '@owlmeans/client-panel'
613
+
614
+ function PanelLayout() {
615
+ return (
616
+ <LayoutHelper>
617
+ <div className="panel-container">
618
+ <header className="panel-header">
619
+ <h1>Admin Panel</h1>
620
+ </header>
621
+
622
+ <main className="panel-content">
623
+ <Form name="admin-form">
624
+ {/* form content */}
625
+ </Form>
626
+ </main>
627
+
628
+ <footer className="panel-footer">
629
+ <p>© 2024 My Company</p>
630
+ </footer>
631
+ </div>
632
+ </LayoutHelper>
633
+ )
634
+ }
635
+ ```
636
+
637
+ ### Authentication Panel Integration
638
+
639
+ ```typescript
640
+ import { AuthComponents } from '@owlmeans/client-panel/auth'
641
+ import { useContext } from '@owlmeans/client'
642
+
643
+ function AuthPanel() {
644
+ const context = useContext()
645
+ const authService = context.service('auth')
646
+
647
+ const [isAuthenticated, setIsAuthenticated] = useState(false)
648
+
649
+ useEffect(() => {
650
+ const checkAuth = async () => {
651
+ const token = await authService.authenticated()
652
+ setIsAuthenticated(token != null)
653
+ }
654
+
655
+ checkAuth()
656
+ }, [])
657
+
658
+ if (!isAuthenticated) {
659
+ return <AuthComponents.LoginForm />
660
+ }
661
+
662
+ return (
663
+ <div>
664
+ <h1>Authenticated Panel</h1>
665
+ {/* panel content */}
666
+ </div>
667
+ )
668
+ }
669
+ ```
670
+
671
+ ### Responsive Panel Design
672
+
673
+ ```typescript
674
+ import { Form } from '@owlmeans/client-panel'
675
+ import { useState, useEffect } from 'react'
676
+
677
+ function ResponsivePanel() {
678
+ const [isMobile, setIsMobile] = useState(false)
679
+
680
+ useEffect(() => {
681
+ const checkMobile = () => {
682
+ setIsMobile(window.innerWidth < 768)
683
+ }
684
+
685
+ checkMobile()
686
+ window.addEventListener('resize', checkMobile)
687
+
688
+ return () => window.removeEventListener('resize', checkMobile)
689
+ }, [])
690
+
691
+ return (
692
+ <Form
693
+ name="responsive-form"
694
+ horizontal={isMobile ? 'sm' : 'lg'}
695
+ vertical={isMobile ? 'sm' : 'md'}
696
+ >
697
+ <div className={isMobile ? 'mobile-layout' : 'desktop-layout'}>
698
+ {/* form fields */}
699
+ </div>
700
+ </Form>
701
+ )
702
+ }
703
+ ```
704
+
705
+ ## Integration with Other Packages
706
+
707
+ ### Client Integration
708
+ ```typescript
709
+ import { useContext } from '@owlmeans/client'
710
+ import { Form } from '@owlmeans/client-panel'
711
+
712
+ // Form components automatically integrate with client context
713
+ ```
714
+
715
+ ### Internationalization Integration
716
+ ```typescript
717
+ import { useI18n } from '@owlmeans/client-i18n'
718
+ import { Form, useFormI18n } from '@owlmeans/client-panel'
719
+
720
+ // Automatic i18n integration for form components
721
+ ```
722
+
723
+ ### Authentication Integration
724
+ ```typescript
725
+ import { AuthComponents } from '@owlmeans/client-panel/auth'
726
+ import { useContext } from '@owlmeans/client'
727
+
728
+ // Authentication panel components
729
+ ```
730
+
731
+ ### Module Integration
732
+ ```typescript
733
+ import { modules } from '@owlmeans/client-module'
734
+ import { Form } from '@owlmeans/client-panel'
735
+
736
+ // Forms can be used within module-based routing
737
+ ```
738
+
739
+ ## Error Handling
740
+
741
+ The package integrates with the OwlMeans error system:
742
+
743
+ ```typescript
744
+ import { OwlMeansError } from '@owlmeans/error'
745
+ import { Form, useFormRef } from '@owlmeans/client-panel'
746
+
747
+ const handleFormError = (error: unknown) => {
748
+ if (error instanceof OwlMeansError) {
749
+ // Handle specific error types
750
+ switch (error.code) {
751
+ case 'VALIDATION_ERROR':
752
+ // Handle validation errors
753
+ break
754
+ case 'AUTHENTICATION_ERROR':
755
+ // Handle auth errors
756
+ break
757
+ default:
758
+ // Handle other errors
759
+ break
760
+ }
761
+ }
762
+ }
763
+ ```
764
+
765
+ ## Best Practices
766
+
767
+ 1. **Form Validation**: Use AJV schemas for consistent validation
768
+ 2. **Internationalization**: Provide translations for all user-facing text
769
+ 3. **Error Handling**: Implement comprehensive error handling for forms
770
+ 4. **Responsive Design**: Use layout components for responsive interfaces
771
+ 5. **Accessibility**: Ensure forms are accessible with proper labels and ARIA attributes
772
+ 6. **Performance**: Use form refs to avoid unnecessary re-renders
773
+ 7. **Type Safety**: Use TypeScript interfaces for form data types
774
+
775
+ ## Dependencies
776
+
777
+ This package depends on:
778
+ - `@owlmeans/client` - React client library
779
+ - `@owlmeans/client-i18n` - Client internationalization
780
+ - `@owlmeans/client-module` - Client module system
781
+ - `@owlmeans/error` - Error handling system
782
+ - `react` - React library (peer dependency)
783
+ - `react-hook-form` - Form management (peer dependency)
784
+
785
+ ## Related Packages
786
+
787
+ - [`@owlmeans/client`](../client) - React client library
788
+ - [`@owlmeans/web-panel`](../web-panel) - Web-specific panel components
789
+ - [`@owlmeans/native-panel`](../native-panel) - React Native panel components
790
+ - [`@owlmeans/client-i18n`](../client-i18n) - Client internationalization
791
+ - [`@owlmeans/client-auth`](../client-auth) - Authentication integration