ywana-core8 0.1.83 → 0.1.85

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 (76) hide show
  1. package/__previewjs__/Wrapper.tsx +8 -5
  2. package/build-doc.sh +10 -0
  3. package/dist/index.cjs +627 -194
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.css +353 -105
  6. package/dist/index.css.map +1 -1
  7. package/dist/index.modern.js +628 -196
  8. package/dist/index.modern.js.map +1 -1
  9. package/dist/index.umd.js +629 -196
  10. package/dist/index.umd.js.map +1 -1
  11. package/doc/README.md +196 -0
  12. package/doc/craco.config.js +31 -0
  13. package/doc/generate-examples.cjs +310 -0
  14. package/doc/package-lock.json +17298 -0
  15. package/doc/package.json +33 -0
  16. package/doc/public/index.html +22 -0
  17. package/doc/src/App.css +171 -0
  18. package/doc/src/App.js +214 -0
  19. package/doc/src/components/ExamplePage.js +104 -0
  20. package/doc/src/components/WelcomePage.js +84 -0
  21. package/doc/src/examples/button.example.js +47 -0
  22. package/doc/src/examples/input.example.js +91 -0
  23. package/doc/src/index.css +237 -0
  24. package/doc/src/index.js +11 -0
  25. package/package.json +9 -2
  26. package/preview.config.js +38 -0
  27. package/src/html/accordion.example.js +2 -2
  28. package/src/html/actions-cell.css +108 -0
  29. package/src/html/actions-cell.example.js +587 -0
  30. package/src/html/actions-cell.js +260 -0
  31. package/src/html/checkbox.example.js +2 -2
  32. package/src/html/chip.example.js +2 -2
  33. package/src/html/color.example.js +2 -2
  34. package/src/html/form.example.js +2 -2
  35. package/src/html/header2.example.js +2 -2
  36. package/src/html/index.js +1 -0
  37. package/src/html/menu.css +9 -2
  38. package/src/html/menu.js +14 -2
  39. package/src/html/progress.example.js +2 -2
  40. package/src/html/property.example.js +2 -2
  41. package/src/html/radio.example.js +2 -2
  42. package/src/html/switch.example.js +2 -2
  43. package/src/html/tab.example.js +2 -2
  44. package/src/html/table.css +47 -1
  45. package/src/html/table.example.js +1012 -0
  46. package/src/html/table.js +12 -7
  47. package/src/html/table2-actions-test.js +138 -0
  48. package/src/html/table2.css +40 -3
  49. package/src/html/table2.example.js +330 -0
  50. package/src/html/table2.js +56 -13
  51. package/src/html/textfield.css +17 -4
  52. package/src/html/tokenfield.example.js +2 -2
  53. package/src/html/tree.css +42 -7
  54. package/src/html/tree.example.js +169 -7
  55. package/src/html/tree.js +216 -93
  56. package/src/widgets/calendar/Calendar.js +1 -1
  57. /package/{ACCORDION_EVALUATION.md → doc/evalulations/ACCORDION_EVALUATION.md} +0 -0
  58. /package/{CHECKBOX_EVALUATION.md → doc/evalulations/CHECKBOX_EVALUATION.md} +0 -0
  59. /package/{CHIP_EVALUATION.md → doc/evalulations/CHIP_EVALUATION.md} +0 -0
  60. /package/{COLOR_EVALUATION.md → doc/evalulations/COLOR_EVALUATION.md} +0 -0
  61. /package/{COMPONENTS_EVALUATION.md → doc/evalulations/COMPONENTS_EVALUATION.md} +0 -0
  62. /package/{FORM_EVALUATION.md → doc/evalulations/FORM_EVALUATION.md} +0 -0
  63. /package/{HEADER_EVALUATION.md → doc/evalulations/HEADER_EVALUATION.md} +0 -0
  64. /package/{ICON_EVALUATION.md → doc/evalulations/ICON_EVALUATION.md} +0 -0
  65. /package/{LIST_EVALUATION.md → doc/evalulations/LIST_EVALUATION.md} +0 -0
  66. /package/{PROGRESS_EVALUATION.md → doc/evalulations/PROGRESS_EVALUATION.md} +0 -0
  67. /package/{RADIO_EVALUATION.md → doc/evalulations/RADIO_EVALUATION.md} +0 -0
  68. /package/{RADIO_VISUAL_FIX.md → doc/evalulations/RADIO_VISUAL_FIX.md} +0 -0
  69. /package/{SECTION_IMPROVEMENTS.md → doc/evalulations/SECTION_IMPROVEMENTS.md} +0 -0
  70. /package/{SWITCH_EVALUATION.md → doc/evalulations/SWITCH_EVALUATION.md} +0 -0
  71. /package/{SWITCH_VISUAL_FIX.md → doc/evalulations/SWITCH_VISUAL_FIX.md} +0 -0
  72. /package/{TAB_EVALUATION.md → doc/evalulations/TAB_EVALUATION.md} +0 -0
  73. /package/{TEXTFIELD_EVALUATION.md → doc/evalulations/TEXTFIELD_EVALUATION.md} +0 -0
  74. /package/{TOOLTIP_FIX.md → doc/evalulations/TOOLTIP_FIX.md} +0 -0
  75. /package/{TREE_EVALUATION.md → doc/evalulations/TREE_EVALUATION.md} +0 -0
  76. /package/src/incubator/{PDFViewer.js → pdfViewer.js} +0 -0
@@ -0,0 +1,1012 @@
1
+ import React, { useState, useCallback } from 'react'
2
+ import { DataTable } from './table'
3
+ import { Button } from './button'
4
+ import { Icon } from './icon'
5
+ import { ActionsCell } from './actions-cell'
6
+ import { FORMATS } from '../domain/ContentType'
7
+ import { ExampleLayout, ExampleSection, ExampleSubsection, CodeSnippet } from './ExampleLayout'
8
+
9
+ /**
10
+ * DataTable Examples - Original table.js component
11
+ *
12
+ * Este archivo muestra ejemplos del componente DataTable original (table.js)
13
+ * para comparar con DataTable2 y demostrar compatibilidad.
14
+ */
15
+ export const TableExamples = () => {
16
+ const [isLoading, setIsLoading] = useState(false)
17
+
18
+ // Datos de ejemplo
19
+ const [rows, setRows] = useState([
20
+ {
21
+ id: 1,
22
+ checked: false,
23
+ name: "John Smith",
24
+ email: "john.smith@example.com",
25
+ department: "Engineering",
26
+ salary: 75000,
27
+ status: "active",
28
+ description: "Senior Software Engineer",
29
+ color: "#4CAF50",
30
+ date: "2023-01-15",
31
+ num: 25.50,
32
+ category: "A"
33
+ },
34
+ {
35
+ id: 2,
36
+ checked: false,
37
+ name: "Ann Martin",
38
+ email: "ann.martin@example.com",
39
+ department: "Design",
40
+ salary: 68000,
41
+ status: "active",
42
+ description: "UX Designer",
43
+ color: "#2196F3",
44
+ date: "2023-02-20",
45
+ num: 1234.75,
46
+ category: "B"
47
+ },
48
+ {
49
+ id: 3,
50
+ checked: false,
51
+ name: "Zack McCracken",
52
+ email: "zack.mccracken@example.com",
53
+ department: "Marketing",
54
+ salary: 62000,
55
+ status: "inactive",
56
+ description: "Marketing Specialist",
57
+ color: "#FF9800",
58
+ date: "2023-03-10",
59
+ num: 567.25,
60
+ category: "C"
61
+ },
62
+ {
63
+ id: 4,
64
+ checked: false,
65
+ name: "Martin Freeman",
66
+ email: "martin.freeman@example.com",
67
+ department: "Engineering",
68
+ salary: 82000,
69
+ status: "active",
70
+ description: "Tech Lead",
71
+ color: "#9C27B0",
72
+ date: "2023-04-05",
73
+ num: 890.10,
74
+ category: "A"
75
+ },
76
+ {
77
+ id: 5,
78
+ checked: false,
79
+ name: "Sarah Connor",
80
+ email: "sarah.connor@example.com",
81
+ department: "Operations",
82
+ salary: 71000,
83
+ status: "active",
84
+ description: "Operations Manager",
85
+ color: "#F44336",
86
+ date: "2023-05-12",
87
+ num: 365.90,
88
+ category: "B"
89
+ }
90
+ ])
91
+
92
+ // Columnas básicas
93
+ const basicColumns = [
94
+ { id: "index", label: "#", type: "INDEX" },
95
+ { id: "checked", onChange: handleCheck },
96
+ { id: "name", label: "Name", type: "String", sortable: true, filterable: true, resizable: true },
97
+ { id: "email", label: "Email", type: "String", sortable: true, filterable: true },
98
+ { id: "department", label: "Department", type: "String", sortable: true, filterable: true },
99
+ { id: "status", label: "Status", type: "String", sortable: true }
100
+ ]
101
+
102
+ // Columnas con formatos
103
+ const formattedColumns = [
104
+ { id: "index", label: "#", type: "INDEX" },
105
+ { id: "name", label: "Name", type: "String", sortable: true },
106
+ { id: "salary", label: "Salary", type: "Number", format: FORMATS.CURRENCY, sortable: true },
107
+ { id: "color", label: "Color", type: "String", format: FORMATS.COLOR },
108
+ { id: "date", label: "Date", type: "String", format: FORMATS.DATE, sortable: true },
109
+ { id: "num", label: "Number", type: "Number", maxDecimals: 2, sortable: true }
110
+ ]
111
+
112
+ // Columnas editables
113
+ const editableColumns = [
114
+ { id: "index", label: "#", type: "INDEX" },
115
+ { id: "checked", onChange: handleCheck },
116
+ { id: "name", label: "Name", type: "String", sortable: true, onChange: handleCellEdit },
117
+ { id: "email", label: "Email", type: "String", sortable: true, onChange: handleCellEdit },
118
+ { id: "department", label: "Department", type: "String", sortable: true, onChange: handleCellEdit, options: [
119
+ { label: "Engineering", value: "Engineering" },
120
+ { label: "Design", value: "Design" },
121
+ { label: "Marketing", value: "Marketing" },
122
+ { label: "Operations", value: "Operations" }
123
+ ]},
124
+ { id: "status", label: "Status", type: "String", sortable: true, onChange: handleCellEdit, options: [
125
+ { label: "Active", value: "active" },
126
+ { label: "Inactive", value: "inactive" }
127
+ ]}
128
+ ]
129
+
130
+ // Columnas con filtros
131
+ const filterableColumns = [
132
+ { id: "index", label: "#", type: "INDEX" },
133
+ { id: "name", label: "Name", type: "String", sortable: true, filterable: true },
134
+ { id: "department", label: "Department", type: "String", sortable: true, filterable: true, options: [
135
+ { label: "Engineering", value: "Engineering" },
136
+ { label: "Design", value: "Design" },
137
+ { label: "Marketing", value: "Marketing" },
138
+ { label: "Operations", value: "Operations" }
139
+ ]},
140
+ { id: "status", label: "Status", type: "String", sortable: true, filterable: true, options: [
141
+ { label: "Active", value: "active" },
142
+ { label: "Inactive", value: "inactive" }
143
+ ]},
144
+ { id: "salary", label: "Salary", type: "Number", format: FORMATS.CURRENCY, sortable: true, filterable: true }
145
+ ]
146
+
147
+ // Columnas con acciones simples
148
+ const simpleActionsColumns = [
149
+ { id: "index", label: "#", type: "INDEX" },
150
+ { id: "name", label: "Name", type: "String", sortable: true },
151
+ { id: "email", label: "Email", type: "String", sortable: true },
152
+ { id: "department", label: "Department", type: "String", sortable: true },
153
+ { id: "actions", label: "Actions", type: "String" }
154
+ ]
155
+
156
+ // Columnas con ActionsCell
157
+ const actionsCellColumns = [
158
+ { id: "index", label: "#", type: "INDEX" },
159
+ { id: "name", label: "Name", type: "String", sortable: true },
160
+ { id: "email", label: "Email", type: "String", sortable: true },
161
+ { id: "department", label: "Department", type: "String", sortable: true },
162
+ { id: "status", label: "Status", type: "String", sortable: true },
163
+ { id: "actions", label: "Actions", type: "String" }
164
+ ]
165
+
166
+ // Event handlers
167
+ function handleRowSelection(row, event) {
168
+ console.log('Row selected:', row)
169
+ const next = rows.map(r => r.id === row.id ? { ...r, selected: !r.selected } : r)
170
+ setRows(next)
171
+ }
172
+
173
+ function handleCheck(rowID, columnID, value) {
174
+ console.log('Check changed:', rowID, columnID, value)
175
+ const next = rows.map(r => r.id === rowID ? { ...r, checked: value } : r)
176
+ setRows(next)
177
+ }
178
+
179
+ function handleCheckAll(ids, checked) {
180
+ console.log('Check all:', ids, checked)
181
+ const next = rows.map(row => ({ ...row, checked }))
182
+ setRows(next)
183
+ }
184
+
185
+ function handleCellEdit(rowID, columnID, value) {
186
+ console.log('Cell edited:', rowID, columnID, value)
187
+ const next = rows.map(r => r.id === rowID ? { ...r, [columnID]: value } : r)
188
+ setRows(next)
189
+ }
190
+
191
+ function handleSort(columnId, direction) {
192
+ console.log('Sort:', columnId, direction)
193
+ }
194
+
195
+ function handleClearFilters() {
196
+ console.log('Clear filters')
197
+ }
198
+
199
+ // Funciones para acciones
200
+ function handleView(row) {
201
+ alert(`Ver detalles de: ${row.name}`)
202
+ }
203
+
204
+ function handleEdit(row) {
205
+ alert(`Editar: ${row.name}`)
206
+ }
207
+
208
+ function handleDelete(row) {
209
+ if (confirm(`¿Eliminar a ${row.name}?`)) {
210
+ const newRows = rows.filter(r => r.id !== row.id)
211
+ setRows(newRows)
212
+ alert(`${row.name} eliminado`)
213
+ }
214
+ }
215
+
216
+ function handleEmail(row) {
217
+ alert(`Enviar email a: ${row.email}`)
218
+ }
219
+
220
+ function handlePromote(row) {
221
+ alert(`Promover a: ${row.name}`)
222
+ }
223
+
224
+ function handleArchive(row) {
225
+ alert(`Archivar a: ${row.name}`)
226
+ }
227
+
228
+ const simulateLoading = () => {
229
+ setIsLoading(true)
230
+ setTimeout(() => setIsLoading(false), 3000)
231
+ }
232
+
233
+ // Datos con acciones simples
234
+ const rowsWithSimpleActions = rows.map(row => ({
235
+ ...row,
236
+ actions: [
237
+ <Icon key="view" icon="visibility" size="small" clickable action={() => handleView(row)} title="Ver" />,
238
+ <Icon key="edit" icon="edit" size="small" clickable action={() => handleEdit(row)} title="Editar" />,
239
+ <Icon key="delete" icon="delete" size="small" clickable action={() => handleDelete(row)} title="Eliminar" />
240
+ ]
241
+ }))
242
+
243
+ // Datos con ActionsCell
244
+ const rowsWithActionsCell = rows.map(row => ({
245
+ ...row,
246
+ actions: [
247
+ <ActionsCell
248
+ key="actions-cell"
249
+ actions={
250
+ <div style={{ display: 'flex', gap: '4px' }}>
251
+ <Icon icon="visibility" size="small" clickable action={() => handleView(row)} title="Ver" />
252
+ <Icon icon="edit" size="small" clickable action={() => handleEdit(row)} title="Editar" />
253
+ <Icon icon="email" size="small" clickable action={() => handleEmail(row)} title="Enviar Email" />
254
+ <Icon icon="trending_up" size="small" clickable action={() => handlePromote(row)} title="Promover" />
255
+ <Icon icon="archive" size="small" clickable action={() => handleArchive(row)} title="Archivar" />
256
+ <Icon icon="delete" size="small" clickable action={() => handleDelete(row)} title="Eliminar" />
257
+ </div>
258
+ }
259
+ maxWidth={120}
260
+ menuAlign="right"
261
+ />
262
+ ]
263
+ }))
264
+
265
+ // Definir secciones para el menú lateral
266
+ const sections = [
267
+ {
268
+ id: 'overview',
269
+ title: 'Introducción',
270
+ icon: 'info'
271
+ },
272
+ {
273
+ id: 'basic-examples',
274
+ title: 'Ejemplos Básicos',
275
+ icon: 'table_chart',
276
+ subsections: [
277
+ { id: 'simple-table', title: 'Tabla Simple' },
278
+ { id: 'sortable-table', title: 'Tabla Ordenable' },
279
+ { id: 'outlined-table', title: 'Tabla con Bordes' }
280
+ ]
281
+ },
282
+ {
283
+ id: 'formatted-data',
284
+ title: 'Datos Formateados',
285
+ icon: 'format_paint',
286
+ subsections: [
287
+ { id: 'currency-format', title: 'Formato de Moneda' },
288
+ { id: 'date-format', title: 'Formato de Fecha' },
289
+ { id: 'color-format', title: 'Formato de Color' }
290
+ ]
291
+ },
292
+ {
293
+ id: 'interactive-features',
294
+ title: 'Funciones Interactivas',
295
+ icon: 'touch_app',
296
+ subsections: [
297
+ { id: 'selection-table', title: 'Selección de Filas' },
298
+ { id: 'editable-table', title: 'Tabla Editable' },
299
+ { id: 'checkbox-table', title: 'Checkboxes' }
300
+ ]
301
+ },
302
+ {
303
+ id: 'action-columns',
304
+ title: 'Columnas de Acciones',
305
+ icon: 'build',
306
+ subsections: [
307
+ { id: 'simple-actions', title: 'Acciones Simples' },
308
+ { id: 'actions-cell-component', title: 'Componente ActionsCell' }
309
+ ]
310
+ },
311
+ {
312
+ id: 'advanced-features',
313
+ title: 'Funciones Avanzadas',
314
+ icon: 'tune',
315
+ subsections: [
316
+ { id: 'filterable-table', title: 'Tabla con Filtros' },
317
+ { id: 'multisort-table', title: 'Ordenamiento Múltiple' },
318
+ { id: 'expandable-rows', title: 'Filas Expandibles' }
319
+ ]
320
+ },
321
+ {
322
+ id: 'api-reference',
323
+ title: 'Referencia API',
324
+ icon: 'code'
325
+ }
326
+ ]
327
+
328
+ return (
329
+ <ExampleLayout title="DataTable Examples (Original)" sections={sections}>
330
+ <ExampleSection id="overview" title="DataTable - Componente Original" icon="table_chart">
331
+ <div style={{
332
+ background: '#f8f9fa',
333
+ padding: '1.5rem',
334
+ borderRadius: '8px',
335
+ border: '1px solid #e9ecef',
336
+ marginBottom: '2rem'
337
+ }}>
338
+ <h3 style={{ margin: '0 0 1rem 0', color: '#495057' }}>
339
+ 📊 DataTable - Componente Original
340
+ </h3>
341
+ <p style={{ margin: '0 0 1rem 0', lineHeight: '1.6', color: '#6c757d' }}>
342
+ Este es el componente <strong>DataTable original</strong> (table.js) que ha sido la base
343
+ para el desarrollo de DataTable2. Aquí puedes ver todas sus funcionalidades y comparar
344
+ con la versión mejorada.
345
+ </p>
346
+
347
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '1rem', marginTop: '1.5rem' }}>
348
+ <div style={{ background: 'white', padding: '1rem', borderRadius: '6px', border: '1px solid #dee2e6' }}>
349
+ <h4 style={{ margin: '0 0 0.5rem 0', color: '#28a745' }}>✅ Características</h4>
350
+ <ul style={{ margin: 0, paddingLeft: '1.2rem', color: '#6c757d' }}>
351
+ <li>Ordenamiento simple y múltiple</li>
352
+ <li>Selección de filas</li>
353
+ <li>Edición inline</li>
354
+ <li>Filtros por columna</li>
355
+ <li>Formatos de datos</li>
356
+ <li>Filas expandibles</li>
357
+ </ul>
358
+ </div>
359
+
360
+ <div style={{ background: 'white', padding: '1rem', borderRadius: '6px', border: '1px solid #dee2e6' }}>
361
+ <h4 style={{ margin: '0 0 0.5rem 0', color: '#17a2b8' }}>🔧 Casos de Uso</h4>
362
+ <ul style={{ margin: 0, paddingLeft: '1.2rem', color: '#6c757d' }}>
363
+ <li>Listados de datos básicos</li>
364
+ <li>Formularios con tablas</li>
365
+ <li>Dashboards simples</li>
366
+ <li>Administración de contenido</li>
367
+ </ul>
368
+ </div>
369
+ </div>
370
+ </div>
371
+ </ExampleSection>
372
+
373
+ <ExampleSection id="basic-examples" title="Ejemplos Básicos" icon="table_chart">
374
+ <ExampleSubsection id="simple-table" title="Tabla Simple">
375
+ <div style={{
376
+ background: '#fff',
377
+ padding: '1rem',
378
+ border: '1px solid #ddd',
379
+ borderRadius: '8px',
380
+ marginBottom: '1rem'
381
+ }}>
382
+ <DataTable
383
+ columns={basicColumns}
384
+ rows={rows}
385
+ onRowSelection={handleRowSelection}
386
+ />
387
+ </div>
388
+
389
+ <CodeSnippet
390
+ title="Código de Tabla Simple"
391
+ code={`const columns = [
392
+ { id: "index", label: "#", type: "INDEX" },
393
+ { id: "checked", onChange: handleCheck },
394
+ { id: "name", label: "Name", type: "String", sortable: true, filterable: true },
395
+ { id: "email", label: "Email", type: "String", sortable: true },
396
+ { id: "department", label: "Department", type: "String", sortable: true },
397
+ { id: "status", label: "Status", type: "String", sortable: true }
398
+ ]
399
+
400
+ <DataTable
401
+ columns={columns}
402
+ rows={rows}
403
+ onRowSelection={handleRowSelection}
404
+ />`}
405
+ />
406
+ </ExampleSubsection>
407
+
408
+ <ExampleSubsection id="sortable-table" title="Tabla Ordenable">
409
+ <div style={{
410
+ background: '#fff',
411
+ padding: '1rem',
412
+ border: '1px solid #ddd',
413
+ borderRadius: '8px',
414
+ marginBottom: '1rem'
415
+ }}>
416
+ <DataTable
417
+ columns={basicColumns}
418
+ rows={rows}
419
+ onRowSelection={handleRowSelection}
420
+ onSort={handleSort}
421
+ />
422
+ </div>
423
+
424
+ <CodeSnippet
425
+ title="Código de Tabla Ordenable"
426
+ code={`// Las columnas con sortable: true permiten ordenamiento
427
+ const columns = [
428
+ { id: "name", label: "Name", type: "String", sortable: true },
429
+ { id: "email", label: "Email", type: "String", sortable: true },
430
+ { id: "department", label: "Department", type: "String", sortable: true }
431
+ ]
432
+
433
+ <DataTable
434
+ columns={columns}
435
+ rows={rows}
436
+ onRowSelection={handleRowSelection}
437
+ onSort={handleSort} // ← Callback para manejar ordenamiento
438
+ />`}
439
+ />
440
+ </ExampleSubsection>
441
+
442
+ <ExampleSubsection id="outlined-table" title="Tabla con Bordes">
443
+ <div style={{
444
+ background: '#fff',
445
+ padding: '1rem',
446
+ border: '1px solid #ddd',
447
+ borderRadius: '8px',
448
+ marginBottom: '1rem'
449
+ }}>
450
+ <DataTable
451
+ columns={basicColumns}
452
+ rows={rows}
453
+ onRowSelection={handleRowSelection}
454
+ outlined={true}
455
+ />
456
+ </div>
457
+
458
+ <CodeSnippet
459
+ title="Código de Tabla con Bordes"
460
+ code={`<DataTable
461
+ columns={columns}
462
+ rows={rows}
463
+ onRowSelection={handleRowSelection}
464
+ outlined={true} // ← Agrega bordes a la tabla
465
+ />`}
466
+ />
467
+ </ExampleSubsection>
468
+ </ExampleSection>
469
+
470
+ <ExampleSection id="formatted-data" title="Datos Formateados" icon="format_paint">
471
+ <ExampleSubsection id="currency-format" title="Formato de Moneda">
472
+ <div style={{
473
+ background: '#fff',
474
+ padding: '1rem',
475
+ border: '1px solid #ddd',
476
+ borderRadius: '8px',
477
+ marginBottom: '1rem'
478
+ }}>
479
+ <DataTable
480
+ columns={formattedColumns}
481
+ rows={rows}
482
+ onRowSelection={handleRowSelection}
483
+ outlined={true}
484
+ />
485
+ </div>
486
+
487
+ <CodeSnippet
488
+ title="Código con Formatos"
489
+ code={`import { FORMATS } from '../domain/ContentType'
490
+
491
+ const columns = [
492
+ { id: "salary", label: "Salary", type: "Number", format: FORMATS.CURRENCY },
493
+ { id: "color", label: "Color", type: "String", format: FORMATS.COLOR },
494
+ { id: "date", label: "Date", type: "String", format: FORMATS.DATE },
495
+ { id: "num", label: "Number", type: "Number", maxDecimals: 2 }
496
+ ]`}
497
+ />
498
+ </ExampleSubsection>
499
+ </ExampleSection>
500
+
501
+ <ExampleSection id="interactive-features" title="Funciones Interactivas" icon="touch_app">
502
+ <ExampleSubsection id="selection-table" title="Selección de Filas">
503
+ <div style={{
504
+ background: '#fff',
505
+ padding: '1rem',
506
+ border: '1px solid #ddd',
507
+ borderRadius: '8px',
508
+ marginBottom: '1rem'
509
+ }}>
510
+ <DataTable
511
+ columns={basicColumns}
512
+ rows={rows}
513
+ onRowSelection={handleRowSelection}
514
+ outlined={true}
515
+ />
516
+ </div>
517
+
518
+ <CodeSnippet
519
+ title="Código de Selección de Filas"
520
+ code={`function handleRowSelection(row, event) {
521
+ console.log('Row selected:', row)
522
+ const next = rows.map(r => r.id === row.id ? { ...r, selected: !r.selected } : r)
523
+ setRows(next)
524
+ }
525
+
526
+ <DataTable
527
+ columns={columns}
528
+ rows={rows}
529
+ onRowSelection={handleRowSelection} // ← Callback para selección
530
+ />`}
531
+ />
532
+ </ExampleSubsection>
533
+
534
+ <ExampleSubsection id="editable-table" title="Tabla Editable">
535
+ <div style={{
536
+ background: '#fff',
537
+ padding: '1rem',
538
+ border: '1px solid #ddd',
539
+ borderRadius: '8px',
540
+ marginBottom: '1rem'
541
+ }}>
542
+ <DataTable
543
+ columns={editableColumns}
544
+ rows={rows}
545
+ onRowSelection={handleRowSelection}
546
+ editable={true}
547
+ outlined={true}
548
+ />
549
+ </div>
550
+
551
+ <CodeSnippet
552
+ title="Código de Tabla Editable"
553
+ code={`const editableColumns = [
554
+ {
555
+ id: "name",
556
+ label: "Name",
557
+ type: "String",
558
+ sortable: true,
559
+ onChange: handleCellEdit // ← Callback para edición
560
+ },
561
+ {
562
+ id: "department",
563
+ label: "Department",
564
+ type: "String",
565
+ onChange: handleCellEdit,
566
+ options: [ // ← Opciones para dropdown
567
+ { label: "Engineering", value: "Engineering" },
568
+ { label: "Design", value: "Design" }
569
+ ]
570
+ }
571
+ ]
572
+
573
+ <DataTable
574
+ columns={editableColumns}
575
+ rows={rows}
576
+ editable={true} // ← Habilita edición
577
+ onRowSelection={handleRowSelection}
578
+ />`}
579
+ />
580
+ </ExampleSubsection>
581
+
582
+ <ExampleSubsection id="checkbox-table" title="Checkboxes">
583
+ <div style={{
584
+ background: '#fff',
585
+ padding: '1rem',
586
+ border: '1px solid #ddd',
587
+ borderRadius: '8px',
588
+ marginBottom: '1rem'
589
+ }}>
590
+ <DataTable
591
+ columns={basicColumns}
592
+ rows={rows}
593
+ onRowSelection={handleRowSelection}
594
+ onCheckAll={handleCheckAll}
595
+ outlined={true}
596
+ />
597
+ </div>
598
+
599
+ <CodeSnippet
600
+ title="Código con Checkboxes"
601
+ code={`const columns = [
602
+ { id: "checked", onChange: handleCheck }, // ← Columna de checkbox
603
+ { id: "name", label: "Name", type: "String" }
604
+ ]
605
+
606
+ function handleCheck(rowID, columnID, value) {
607
+ const next = rows.map(r => r.id === rowID ? { ...r, checked: value } : r)
608
+ setRows(next)
609
+ }
610
+
611
+ function handleCheckAll(ids, checked) {
612
+ const next = rows.map(row => ({ ...row, checked }))
613
+ setRows(next)
614
+ }
615
+
616
+ <DataTable
617
+ columns={columns}
618
+ rows={rows}
619
+ onCheckAll={handleCheckAll} // ← Callback para "seleccionar todo"
620
+ />`}
621
+ />
622
+ </ExampleSubsection>
623
+ </ExampleSection>
624
+
625
+ <ExampleSection id="action-columns" title="Columnas de Acciones" icon="build">
626
+ <ExampleSubsection id="simple-actions" title="Acciones Simples">
627
+ <div style={{
628
+ background: '#fff',
629
+ padding: '1rem',
630
+ border: '1px solid #ddd',
631
+ borderRadius: '8px',
632
+ marginBottom: '1rem'
633
+ }}>
634
+ <DataTable
635
+ columns={simpleActionsColumns}
636
+ rows={rowsWithSimpleActions}
637
+ onRowSelection={handleRowSelection}
638
+ outlined={true}
639
+ />
640
+ </div>
641
+
642
+ <CodeSnippet
643
+ title="Código con Acciones Simples"
644
+ code={`// Agregar columna de acciones
645
+ const columns = [
646
+ { id: "name", label: "Name", type: "String" },
647
+ { id: "email", label: "Email", type: "String" },
648
+ { id: "actions", label: "Actions", type: "String" } // ← Columna de acciones
649
+ ]
650
+
651
+ // Funciones para manejar acciones
652
+ function handleView(row) {
653
+ alert(\`Ver detalles de: \${row.name}\`)
654
+ }
655
+
656
+ function handleEdit(row) {
657
+ alert(\`Editar: \${row.name}\`)
658
+ }
659
+
660
+ function handleDelete(row) {
661
+ if (confirm(\`¿Eliminar a \${row.name}?\`)) {
662
+ // Lógica para eliminar
663
+ }
664
+ }
665
+
666
+ // Agregar acciones a las filas
667
+ const rowsWithActions = rows.map(row => ({
668
+ ...row,
669
+ actions: [
670
+ <Icon key="view" icon="visibility" size="small" clickable
671
+ action={() => handleView(row)} title="Ver" />,
672
+ <Icon key="edit" icon="edit" size="small" clickable
673
+ action={() => handleEdit(row)} title="Editar" />,
674
+ <Icon key="delete" icon="delete" size="small" clickable
675
+ action={() => handleDelete(row)} title="Eliminar" />
676
+ ]
677
+ }))
678
+
679
+ <DataTable
680
+ columns={columns}
681
+ rows={rowsWithActions}
682
+ onRowSelection={handleRowSelection}
683
+ />`}
684
+ />
685
+ </ExampleSubsection>
686
+
687
+ <ExampleSubsection id="actions-cell-component" title="Componente ActionsCell">
688
+ <div style={{
689
+ background: '#fff',
690
+ padding: '1rem',
691
+ border: '1px solid #ddd',
692
+ borderRadius: '8px',
693
+ marginBottom: '1rem'
694
+ }}>
695
+ <DataTable
696
+ columns={actionsCellColumns}
697
+ rows={rowsWithActionsCell}
698
+ onRowSelection={handleRowSelection}
699
+ outlined={true}
700
+ />
701
+ </div>
702
+
703
+ <CodeSnippet
704
+ title="Código con ActionsCell"
705
+ code={`import { ActionsCell } from './actions-cell'
706
+
707
+ // Agregar ActionsCell a las filas
708
+ const rowsWithActionsCell = rows.map(row => ({
709
+ ...row,
710
+ actions: [
711
+ <ActionsCell
712
+ key="actions-cell"
713
+ actions={
714
+ <div style={{ display: 'flex', gap: '4px' }}>
715
+ <Icon icon="visibility" size="small" clickable
716
+ action={() => handleView(row)} title="Ver" />
717
+ <Icon icon="edit" size="small" clickable
718
+ action={() => handleEdit(row)} title="Editar" />
719
+ <Icon icon="email" size="small" clickable
720
+ action={() => handleEmail(row)} title="Email" />
721
+ <Icon icon="trending_up" size="small" clickable
722
+ action={() => handlePromote(row)} title="Promover" />
723
+ <Icon icon="archive" size="small" clickable
724
+ action={() => handleArchive(row)} title="Archivar" />
725
+ <Icon icon="delete" size="small" clickable
726
+ action={() => handleDelete(row)} title="Eliminar" />
727
+ </div>
728
+ }
729
+ maxWidth={120} // ← Ancho máximo antes de convertir a menú
730
+ menuAlign="right" // ← Menú se abre hacia la izquierda
731
+ />
732
+ ]
733
+ }))
734
+
735
+ <DataTable
736
+ columns={columns}
737
+ rows={rowsWithActionsCell}
738
+ onRowSelection={handleRowSelection}
739
+ />`}
740
+ />
741
+
742
+ <div style={{
743
+ background: '#e3f2fd',
744
+ padding: '1rem',
745
+ borderRadius: '6px',
746
+ border: '1px solid #bbdefb',
747
+ marginTop: '1rem'
748
+ }}>
749
+ <h4 style={{ margin: '0 0 0.5rem 0', color: '#1976d2' }}>
750
+ 💡 Ventajas de ActionsCell
751
+ </h4>
752
+ <ul style={{ margin: 0, paddingLeft: '1.2rem', color: '#1565c0' }}>
753
+ <li><strong>Overflow Automático:</strong> Se convierte en menú cuando las acciones no caben</li>
754
+ <li><strong>Responsive:</strong> Se adapta automáticamente al ancho disponible</li>
755
+ <li><strong>Reutilizable:</strong> Funciona en tablas, headers, listas, etc.</li>
756
+ <li><strong>Configurable:</strong> Personalizable con maxWidth y menuAlign (right = hacia izquierda)</li>
757
+ </ul>
758
+ </div>
759
+ </ExampleSubsection>
760
+ </ExampleSection>
761
+
762
+ <ExampleSection id="advanced-features" title="Funciones Avanzadas" icon="tune">
763
+ <ExampleSubsection id="filterable-table" title="Tabla con Filtros">
764
+ <div style={{
765
+ background: '#fff',
766
+ padding: '1rem',
767
+ border: '1px solid #ddd',
768
+ borderRadius: '8px',
769
+ marginBottom: '1rem'
770
+ }}>
771
+ <DataTable
772
+ columns={filterableColumns}
773
+ rows={rows}
774
+ onRowSelection={handleRowSelection}
775
+ filterable={true}
776
+ onClearFilters={handleClearFilters}
777
+ outlined={true}
778
+ />
779
+ </div>
780
+
781
+ <CodeSnippet
782
+ title="Código con Filtros"
783
+ code={`const filterableColumns = [
784
+ {
785
+ id: "name",
786
+ label: "Name",
787
+ type: "String",
788
+ sortable: true,
789
+ filterable: true // ← Habilita filtro
790
+ },
791
+ {
792
+ id: "department",
793
+ label: "Department",
794
+ type: "String",
795
+ filterable: true,
796
+ options: [ // ← Opciones para filtro dropdown
797
+ { label: "Engineering", value: "Engineering" },
798
+ { label: "Design", value: "Design" }
799
+ ]
800
+ }
801
+ ]
802
+
803
+ <DataTable
804
+ columns={filterableColumns}
805
+ rows={rows}
806
+ filterable={true} // ← Habilita fila de filtros
807
+ onClearFilters={handleClearFilters}
808
+ />`}
809
+ />
810
+ </ExampleSubsection>
811
+
812
+ <ExampleSubsection id="multisort-table" title="Ordenamiento Múltiple">
813
+ <div style={{
814
+ background: '#fff',
815
+ padding: '1rem',
816
+ border: '1px solid #ddd',
817
+ borderRadius: '8px',
818
+ marginBottom: '1rem'
819
+ }}>
820
+ <DataTable
821
+ columns={basicColumns}
822
+ rows={rows}
823
+ onRowSelection={handleRowSelection}
824
+ multisort={true}
825
+ outlined={true}
826
+ />
827
+ </div>
828
+
829
+ <CodeSnippet
830
+ title="Código con Ordenamiento Múltiple"
831
+ code={`<DataTable
832
+ columns={columns}
833
+ rows={rows}
834
+ multisort={true} // ← Permite ordenar por múltiples columnas
835
+ onRowSelection={handleRowSelection}
836
+ />`}
837
+ />
838
+ </ExampleSubsection>
839
+
840
+ <ExampleSubsection id="expandable-rows" title="Filas Expandibles">
841
+ <div style={{
842
+ background: '#fff',
843
+ padding: '1rem',
844
+ border: '1px solid #ddd',
845
+ borderRadius: '8px',
846
+ marginBottom: '1rem'
847
+ }}>
848
+ <DataTable
849
+ columns={basicColumns}
850
+ rows={rows.map(row => ({
851
+ ...row,
852
+ info: `Información adicional para ${row.name}: ${row.description}`
853
+ }))}
854
+ onRowSelection={handleRowSelection}
855
+ expanded={false}
856
+ outlined={true}
857
+ />
858
+ </div>
859
+
860
+ <CodeSnippet
861
+ title="Código con Filas Expandibles"
862
+ code={`// Agregar propiedad 'info' a las filas
863
+ const rowsWithInfo = rows.map(row => ({
864
+ ...row,
865
+ info: \`Información adicional para \${row.name}: \${row.description}\`
866
+ }))
867
+
868
+ <DataTable
869
+ columns={columns}
870
+ rows={rowsWithInfo}
871
+ expanded={false} // ← false = cerradas por defecto, true = abiertas
872
+ onRowSelection={handleRowSelection}
873
+ />`}
874
+ />
875
+ </ExampleSubsection>
876
+ </ExampleSection>
877
+
878
+ <ExampleSection id="api-reference" title="Referencia API" icon="code">
879
+ <div style={{
880
+ background: '#f8f9fa',
881
+ padding: '1.5rem',
882
+ borderRadius: '8px',
883
+ border: '1px solid #e9ecef',
884
+ marginBottom: '2rem'
885
+ }}>
886
+ <h3 style={{ margin: '0 0 1rem 0', color: '#495057' }}>
887
+ 📖 Props del Componente DataTable
888
+ </h3>
889
+
890
+ <div style={{ display: 'grid', gap: '1rem' }}>
891
+ <div style={{ background: 'white', padding: '1rem', borderRadius: '6px', border: '1px solid #dee2e6' }}>
892
+ <h4 style={{ margin: '0 0 0.5rem 0', color: '#007bff' }}>Props Principales</h4>
893
+ <table style={{ width: '100%', borderCollapse: 'collapse' }}>
894
+ <thead>
895
+ <tr style={{ borderBottom: '1px solid #dee2e6' }}>
896
+ <th style={{ textAlign: 'left', padding: '0.5rem', color: '#495057' }}>Prop</th>
897
+ <th style={{ textAlign: 'left', padding: '0.5rem', color: '#495057' }}>Tipo</th>
898
+ <th style={{ textAlign: 'left', padding: '0.5rem', color: '#495057' }}>Descripción</th>
899
+ </tr>
900
+ </thead>
901
+ <tbody>
902
+ <tr>
903
+ <td style={{ padding: '0.5rem', fontFamily: 'monospace', color: '#e83e8c' }}>columns</td>
904
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Array</td>
905
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Definición de columnas</td>
906
+ </tr>
907
+ <tr>
908
+ <td style={{ padding: '0.5rem', fontFamily: 'monospace', color: '#e83e8c' }}>rows</td>
909
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Array</td>
910
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Datos de las filas</td>
911
+ </tr>
912
+ <tr>
913
+ <td style={{ padding: '0.5rem', fontFamily: 'monospace', color: '#e83e8c' }}>onRowSelection</td>
914
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Function</td>
915
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Callback al seleccionar fila</td>
916
+ </tr>
917
+ <tr>
918
+ <td style={{ padding: '0.5rem', fontFamily: 'monospace', color: '#e83e8c' }}>onSort</td>
919
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Function</td>
920
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Callback para ordenamiento</td>
921
+ </tr>
922
+ <tr>
923
+ <td style={{ padding: '0.5rem', fontFamily: 'monospace', color: '#e83e8c' }}>onCheckAll</td>
924
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Function</td>
925
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Callback para seleccionar todo</td>
926
+ </tr>
927
+ <tr>
928
+ <td style={{ padding: '0.5rem', fontFamily: 'monospace', color: '#e83e8c' }}>editable</td>
929
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Boolean</td>
930
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Habilita edición inline</td>
931
+ </tr>
932
+ <tr>
933
+ <td style={{ padding: '0.5rem', fontFamily: 'monospace', color: '#e83e8c' }}>outlined</td>
934
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Boolean</td>
935
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Agrega bordes a la tabla</td>
936
+ </tr>
937
+ <tr>
938
+ <td style={{ padding: '0.5rem', fontFamily: 'monospace', color: '#e83e8c' }}>multisort</td>
939
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Boolean</td>
940
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Permite ordenamiento múltiple</td>
941
+ </tr>
942
+ <tr>
943
+ <td style={{ padding: '0.5rem', fontFamily: 'monospace', color: '#e83e8c' }}>filterable</td>
944
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Boolean</td>
945
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Muestra fila de filtros</td>
946
+ </tr>
947
+ <tr>
948
+ <td style={{ padding: '0.5rem', fontFamily: 'monospace', color: '#e83e8c' }}>expanded</td>
949
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Boolean</td>
950
+ <td style={{ padding: '0.5rem', color: '#6c757d' }}>Estado inicial de filas expandibles</td>
951
+ </tr>
952
+ </tbody>
953
+ </table>
954
+ </div>
955
+
956
+ <div style={{ background: 'white', padding: '1rem', borderRadius: '6px', border: '1px solid #dee2e6' }}>
957
+ <h4 style={{ margin: '0 0 0.5rem 0', color: '#28a745' }}>Estructura de Columnas</h4>
958
+ <CodeSnippet
959
+ title="Ejemplo de Definición de Columna"
960
+ code={`{
961
+ id: "name", // Identificador único
962
+ label: "Name", // Texto del encabezado
963
+ type: "String", // Tipo de dato (String, Number, Boolean, etc.)
964
+ sortable: true, // Permite ordenamiento
965
+ filterable: true, // Permite filtrado
966
+ resizable: true, // Permite redimensionar
967
+ editable: true, // Permite edición (si la tabla es editable)
968
+ format: FORMATS.DATE, // Formato especial (opcional)
969
+ onChange: handleEdit, // Callback para edición (opcional)
970
+ options: [ // Opciones para dropdown (opcional)
971
+ { label: "Option 1", value: "opt1" },
972
+ { label: "Option 2", value: "opt2" }
973
+ ]
974
+ }`}
975
+ />
976
+ </div>
977
+
978
+ <div style={{ background: 'white', padding: '1rem', borderRadius: '6px', border: '1px solid #dee2e6' }}>
979
+ <h4 style={{ margin: '0 0 0.5rem 0', color: '#dc3545' }}>Tipos de Datos Soportados</h4>
980
+ <ul style={{ margin: 0, paddingLeft: '1.2rem', color: '#6c757d' }}>
981
+ <li><code>INDEX</code> - Número de fila automático</li>
982
+ <li><code>String</code> - Texto simple</li>
983
+ <li><code>Number</code> - Números con formato</li>
984
+ <li><code>Boolean</code> - Checkbox</li>
985
+ <li><code>DATETIME</code> - Fecha y hora</li>
986
+ <li><code>ICON</code> - Iconos de Material Design</li>
987
+ <li><code>Image</code> - Imágenes</li>
988
+ <li><code>ENTITY</code> - Objetos complejos</li>
989
+ </ul>
990
+ </div>
991
+
992
+ <div style={{ background: 'white', padding: '1rem', borderRadius: '6px', border: '1px solid #dee2e6' }}>
993
+ <h4 style={{ margin: '0 0 0.5rem 0', color: '#6f42c1' }}>Formatos Disponibles</h4>
994
+ <ul style={{ margin: 0, paddingLeft: '1.2rem', color: '#6c757d' }}>
995
+ <li><code>FORMATS.CURRENCY</code> - Formato de moneda</li>
996
+ <li><code>FORMATS.PERCENT</code> - Formato de porcentaje</li>
997
+ <li><code>FORMATS.DATE</code> - Formato de fecha</li>
998
+ <li><code>FORMATS.TIME</code> - Formato de hora</li>
999
+ <li><code>FORMATS.DATETIME</code> - Formato de fecha y hora</li>
1000
+ <li><code>FORMATS.COLOR</code> - Selector de color</li>
1001
+ <li><code>FORMATS.URL</code> - Enlaces</li>
1002
+ <li><code>FORMATS.IMG</code> - Imágenes</li>
1003
+ </ul>
1004
+ </div>
1005
+ </div>
1006
+ </div>
1007
+ </ExampleSection>
1008
+ </ExampleLayout>
1009
+ )
1010
+ }
1011
+
1012
+ export default TableExamples