ywana-core8 0.1.82 → 0.1.84
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.
- package/dist/index.cjs +221 -88
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +59 -11
- package/dist/index.css.map +1 -1
- package/dist/index.modern.js +222 -89
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +221 -88
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/html/list.js +12 -12
- package/src/html/textfield.css +17 -4
- package/src/html/tree.css +42 -7
- package/src/html/tree.example.js +169 -7
- package/src/html/tree.js +216 -93
package/package.json
CHANGED
package/src/html/list.js
CHANGED
@@ -125,8 +125,8 @@ export const List = (props) => {
|
|
125
125
|
if (onSort) onSort(newConfig)
|
126
126
|
}, [sortable, sortConfig, onSort])
|
127
127
|
|
128
|
-
// Search component
|
129
|
-
const
|
128
|
+
// Search component JSX - memoized to prevent focus loss
|
129
|
+
const searchComponent = useMemo(() => (
|
130
130
|
searchable && (
|
131
131
|
<div className="list__search">
|
132
132
|
<TextField
|
@@ -140,7 +140,7 @@ export const List = (props) => {
|
|
140
140
|
/>
|
141
141
|
</div>
|
142
142
|
)
|
143
|
-
)
|
143
|
+
), [searchable, searchPlaceholder, searchTerm, handleSearch])
|
144
144
|
|
145
145
|
// Generate CSS classes
|
146
146
|
const cssClasses = [
|
@@ -178,12 +178,12 @@ export const List = (props) => {
|
|
178
178
|
if (empty || sortedItems.length === 0) {
|
179
179
|
return (
|
180
180
|
<div className={cssClasses} style={style} {...ariaAttributes} {...restProps}>
|
181
|
-
{searchPosition === 'top' &&
|
181
|
+
{searchPosition === 'top' && searchComponent}
|
182
182
|
<div className="list__empty">
|
183
183
|
<Icon icon={emptyIcon} size="large" />
|
184
184
|
<Text>{emptyMessage}</Text>
|
185
185
|
</div>
|
186
|
-
{searchPosition === 'bottom' &&
|
186
|
+
{searchPosition === 'bottom' && searchComponent}
|
187
187
|
{children}
|
188
188
|
</div>
|
189
189
|
)
|
@@ -204,7 +204,7 @@ export const List = (props) => {
|
|
204
204
|
/>
|
205
205
|
) : (
|
206
206
|
<div className={cssClasses} style={style} ref={listRef} {...ariaAttributes} {...restProps}>
|
207
|
-
{searchPosition === 'top' &&
|
207
|
+
{searchPosition === 'top' && searchComponent}
|
208
208
|
|
209
209
|
{sortable && sortBy && (
|
210
210
|
<div className="list__sort">
|
@@ -241,7 +241,7 @@ export const List = (props) => {
|
|
241
241
|
/>
|
242
242
|
))}
|
243
243
|
</ul>
|
244
|
-
{searchPosition === 'bottom' &&
|
244
|
+
{searchPosition === 'bottom' && searchComponent}
|
245
245
|
{children}
|
246
246
|
</div>
|
247
247
|
)
|
@@ -301,8 +301,8 @@ const GroupedList = (props) => {
|
|
301
301
|
})
|
302
302
|
}, [])
|
303
303
|
|
304
|
-
// Search component for grouped list
|
305
|
-
const
|
304
|
+
// Search component for grouped list - memoized to prevent focus loss
|
305
|
+
const groupedSearchComponent = useMemo(() => (
|
306
306
|
searchable && (
|
307
307
|
<div className="list__search">
|
308
308
|
<TextField
|
@@ -316,11 +316,11 @@ const GroupedList = (props) => {
|
|
316
316
|
/>
|
317
317
|
</div>
|
318
318
|
)
|
319
|
-
)
|
319
|
+
), [searchable, searchPlaceholder, searchTerm, onSearch])
|
320
320
|
|
321
321
|
return (
|
322
322
|
<div className={`${cssClasses} grouped`} style={style} {...ariaAttributes} {...restProps}>
|
323
|
-
{searchPosition === 'top' &&
|
323
|
+
{searchPosition === 'top' && groupedSearchComponent}
|
324
324
|
|
325
325
|
{groups.map(group => {
|
326
326
|
const isCollapsed = collapsedGroups.has(group.name)
|
@@ -377,7 +377,7 @@ const GroupedList = (props) => {
|
|
377
377
|
</Fragment>
|
378
378
|
)
|
379
379
|
})}
|
380
|
-
{searchPosition === 'bottom' &&
|
380
|
+
{searchPosition === 'bottom' && groupedSearchComponent}
|
381
381
|
{children}
|
382
382
|
</div>
|
383
383
|
)
|
package/src/html/textfield.css
CHANGED
@@ -41,13 +41,18 @@
|
|
41
41
|
|
42
42
|
.textfield>.icon {
|
43
43
|
position: absolute;
|
44
|
-
top:
|
44
|
+
top: 50%;
|
45
45
|
right: .2rem;
|
46
|
+
transform: translateY(-50%);
|
46
47
|
color: rgba(150,150,150,1);
|
48
|
+
display: flex;
|
49
|
+
align-items: center;
|
50
|
+
justify-content: center;
|
47
51
|
}
|
48
52
|
|
49
53
|
.textfield-outlined.no-label > .icon {
|
50
|
-
top:
|
54
|
+
top: 50%;
|
55
|
+
transform: translateY(-50%);
|
51
56
|
}
|
52
57
|
|
53
58
|
.textfield-date>.icon,
|
@@ -147,8 +152,12 @@ input:read-only ~ label,
|
|
147
152
|
|
148
153
|
.dropdown>.icon {
|
149
154
|
position: absolute;
|
150
|
-
top:
|
155
|
+
top: 50%;
|
151
156
|
right: .2rem;
|
157
|
+
transform: translateY(-50%);
|
158
|
+
display: flex;
|
159
|
+
align-items: center;
|
160
|
+
justify-content: center;
|
152
161
|
}
|
153
162
|
|
154
163
|
.dropdown>.decorator {
|
@@ -161,9 +170,13 @@ input:read-only ~ label,
|
|
161
170
|
.dropdown>.textfield>.icon,
|
162
171
|
.dropdown>.textfield-outlined>.icon {
|
163
172
|
position: absolute;
|
164
|
-
top:
|
173
|
+
top: 50%;
|
165
174
|
right: 2rem;
|
175
|
+
transform: translateY(-50%);
|
166
176
|
color: rgba(150,150,150,1);
|
177
|
+
display: flex;
|
178
|
+
align-items: center;
|
179
|
+
justify-content: center;
|
167
180
|
}
|
168
181
|
|
169
182
|
.dropdown>menu {
|
package/src/html/tree.css
CHANGED
@@ -14,13 +14,16 @@
|
|
14
14
|
align-items: center;
|
15
15
|
font: 1rem;
|
16
16
|
color: var(--text-color-light);
|
17
|
+
cursor: pointer;
|
18
|
+
width: 100%;
|
19
|
+
min-height: 2rem;
|
20
|
+
padding: 0.25rem 0;
|
17
21
|
}
|
18
22
|
|
19
23
|
.tree-item:hover {
|
20
|
-
cursor: pointer;
|
21
24
|
background-color: var(--background-color);
|
22
25
|
font-weight: 500;
|
23
|
-
}
|
26
|
+
}
|
24
27
|
|
25
28
|
.tree-item.final {
|
26
29
|
margin-left: 1rem;
|
@@ -35,6 +38,7 @@
|
|
35
38
|
|
36
39
|
.tree-item>i {
|
37
40
|
padding-left: .3rem;
|
41
|
+
pointer-events: none;
|
38
42
|
}
|
39
43
|
|
40
44
|
.tree-item>.label {
|
@@ -43,10 +47,10 @@
|
|
43
47
|
display: flex;
|
44
48
|
align-items: center;
|
45
49
|
justify-content: space-between;
|
50
|
+
pointer-events: none;
|
46
51
|
}
|
47
52
|
|
48
53
|
.tree-item>.label.clickable:hover {
|
49
|
-
cursor: pointer;
|
50
54
|
color: var(--accent-color);
|
51
55
|
}
|
52
56
|
|
@@ -56,11 +60,13 @@
|
|
56
60
|
overflow: hidden;
|
57
61
|
text-overflow: ellipsis;
|
58
62
|
white-space: nowrap;
|
63
|
+
pointer-events: none;
|
59
64
|
}
|
60
65
|
|
61
66
|
.tree-item>.actions {
|
62
67
|
padding: 0 .5rem;
|
63
68
|
color: var(--text-color-lighter);
|
69
|
+
pointer-events: auto;
|
64
70
|
}
|
65
71
|
|
66
72
|
.tree-item>.actions .rmwc-icon {
|
@@ -95,14 +101,42 @@
|
|
95
101
|
padding-left: 2rem;
|
96
102
|
}
|
97
103
|
|
98
|
-
/* Tree
|
99
|
-
.
|
100
|
-
|
104
|
+
/* Tree header */
|
105
|
+
.tree__header {
|
106
|
+
display: flex;
|
107
|
+
align-items: center;
|
108
|
+
justify-content: space-between;
|
109
|
+
padding: 0.5rem;
|
101
110
|
border-bottom: 1px solid var(--divider-color, #e0e0e0);
|
102
111
|
background-color: var(--background-color-light, #fafafa);
|
112
|
+
gap: 0.5rem;
|
103
113
|
margin-bottom: 0.5rem;
|
104
114
|
}
|
105
115
|
|
116
|
+
/* When only expand icon is present, align to right */
|
117
|
+
.tree__header:has(.tree__expand-control):not(:has(.tree__search)) {
|
118
|
+
justify-content: flex-end;
|
119
|
+
}
|
120
|
+
|
121
|
+
/* Alternative for browsers that don't support :has() */
|
122
|
+
.tree__header--expand-only {
|
123
|
+
justify-content: flex-end;
|
124
|
+
}
|
125
|
+
|
126
|
+
/* Tree search */
|
127
|
+
.tree__search {
|
128
|
+
flex: 1;
|
129
|
+
}
|
130
|
+
|
131
|
+
/* Tree expand control */
|
132
|
+
.tree__expand-control {
|
133
|
+
display: flex;
|
134
|
+
align-items: center;
|
135
|
+
justify-content: center;
|
136
|
+
min-width: 2rem;
|
137
|
+
height: 2rem;
|
138
|
+
}
|
139
|
+
|
106
140
|
/* Tree controls */
|
107
141
|
.tree__controls {
|
108
142
|
display: flex;
|
@@ -203,6 +237,7 @@
|
|
203
237
|
display: flex;
|
204
238
|
align-items: center;
|
205
239
|
margin-right: 0.5rem;
|
240
|
+
pointer-events: none;
|
206
241
|
}
|
207
242
|
|
208
243
|
/* TreeNode loading */
|
@@ -233,7 +268,7 @@
|
|
233
268
|
|
234
269
|
/* TreeNode children */
|
235
270
|
.tree-node__children {
|
236
|
-
margin-left:
|
271
|
+
margin-left: .8rem;
|
237
272
|
border-left: 1px solid var(--divider-color, #e0e0e0);
|
238
273
|
padding-left: 0.5rem;
|
239
274
|
}
|
package/src/html/tree.example.js
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
import React, { useState } from 'react'
|
2
2
|
import { Tree, TreeNode, TreeItem } from './tree'
|
3
3
|
import { Button } from './button'
|
4
|
-
import { Icon } from '
|
5
|
-
import { ExampleLayout, ExampleSection, ExampleSubsection, CodeSnippet } from './ExampleLayout'
|
4
|
+
import { Icon } from './icon'
|
5
|
+
import { ExampleLayout, ExampleSection, ExampleSubsection, CodeSnippet } from './ExampleLayout'
|
6
6
|
|
7
7
|
/**
|
8
8
|
* Ejemplos de los componentes Tree mejorados manteniendo 100% compatibilidad
|
@@ -209,7 +209,7 @@ export const TreeExamples = () => {
|
|
209
209
|
}}>
|
210
210
|
<Tree>
|
211
211
|
<TreeNode id="root" label="Root Folder" icon="folder" open={true}>
|
212
|
-
<TreeNode id="documents" label="Documents" icon="folder"
|
212
|
+
<TreeNode id="documents" label="Documents" icon="folder">
|
213
213
|
<TreeItem id="doc1" label="Document 1.pdf" icon="picture_as_pdf" onSelect={handleSelect} selected={selectedItem === 'doc1'} />
|
214
214
|
<TreeItem id="doc2" label="Document 2.docx" icon="description" onSelect={handleSelect} selected={selectedItem === 'doc2'} />
|
215
215
|
</TreeNode>
|
@@ -221,6 +221,27 @@ export const TreeExamples = () => {
|
|
221
221
|
</TreeNode>
|
222
222
|
</Tree>
|
223
223
|
</div>
|
224
|
+
<CodeSnippet
|
225
|
+
language="jsx"
|
226
|
+
code={`<Tree>
|
227
|
+
<TreeNode id="root" label="Root Folder" icon="folder" open={true}>
|
228
|
+
<TreeNode id="documents" label="Documents" icon="folder">
|
229
|
+
<TreeItem id="doc1" label="Document 1.pdf" icon="picture_as_pdf"
|
230
|
+
onSelect={handleSelect} selected={selectedItem === 'doc1'} />
|
231
|
+
<TreeItem id="doc2" label="Document 2.docx" icon="description"
|
232
|
+
onSelect={handleSelect} selected={selectedItem === 'doc2'} />
|
233
|
+
</TreeNode>
|
234
|
+
<TreeNode id="images" label="Images" icon="folder" open={true}>
|
235
|
+
<TreeItem id="img1" label="Photo 1.jpg" icon="image"
|
236
|
+
onSelect={handleSelect} selected={selectedItem === 'img1'} />
|
237
|
+
<TreeItem id="img2" label="Photo 2.png" icon="image"
|
238
|
+
onSelect={handleSelect} selected={selectedItem === 'img2'} />
|
239
|
+
</TreeNode>
|
240
|
+
<TreeItem id="readme" label="README.md" icon="description"
|
241
|
+
onSelect={handleSelect} selected={selectedItem === 'readme'} />
|
242
|
+
</TreeNode>
|
243
|
+
</Tree>`}
|
244
|
+
/>
|
224
245
|
</section>
|
225
246
|
|
226
247
|
{/* Tree con búsqueda */}
|
@@ -252,6 +273,24 @@ export const TreeExamples = () => {
|
|
252
273
|
</TreeNode>
|
253
274
|
</Tree>
|
254
275
|
</div>
|
276
|
+
<CodeSnippet
|
277
|
+
language="jsx"
|
278
|
+
code={`<Tree
|
279
|
+
searchable={true}
|
280
|
+
searchPlaceholder="Buscar archivos y carpetas..."
|
281
|
+
searchBy={['label']}
|
282
|
+
ariaLabel="Árbol de archivos con búsqueda"
|
283
|
+
>
|
284
|
+
<TreeNode id="projects" label="Projects" icon="work" open={true}>
|
285
|
+
<TreeNode id="project1" label="Website Project" icon="web">
|
286
|
+
<TreeItem id="index" label="index.html" icon="code"
|
287
|
+
onSelect={handleSelect} selected={selectedItem === 'index'} />
|
288
|
+
<TreeItem id="styles" label="styles.css" icon="palette"
|
289
|
+
onSelect={handleSelect} selected={selectedItem === 'styles'} />
|
290
|
+
</TreeNode>
|
291
|
+
</TreeNode>
|
292
|
+
</Tree>`}
|
293
|
+
/>
|
255
294
|
</section>
|
256
295
|
|
257
296
|
{/* Tree con checkboxes y selección múltiple */}
|
@@ -300,6 +339,31 @@ export const TreeExamples = () => {
|
|
300
339
|
</TreeNode>
|
301
340
|
</Tree>
|
302
341
|
</div>
|
342
|
+
<CodeSnippet
|
343
|
+
language="jsx"
|
344
|
+
code={`<Tree
|
345
|
+
multiSelect={true}
|
346
|
+
onMultiSelect={handleMultiSelect}
|
347
|
+
ariaLabel="Árbol con selección múltiple"
|
348
|
+
>
|
349
|
+
<TreeNode id="backup" label="Backup Files" icon="backup" open={true}>
|
350
|
+
<TreeItem
|
351
|
+
id="file1"
|
352
|
+
label="Config Backup"
|
353
|
+
icon="settings_backup_restore"
|
354
|
+
onSelect={handleSelect}
|
355
|
+
selected={selectedItems.includes('file1')}
|
356
|
+
/>
|
357
|
+
<TreeItem
|
358
|
+
id="file2"
|
359
|
+
label="Database Backup"
|
360
|
+
icon="storage"
|
361
|
+
onSelect={handleSelect}
|
362
|
+
selected={selectedItems.includes('file2')}
|
363
|
+
/>
|
364
|
+
</TreeNode>
|
365
|
+
</Tree>`}
|
366
|
+
/>
|
303
367
|
</section>
|
304
368
|
|
305
369
|
{/* Tree con badges y drag & drop */}
|
@@ -371,11 +435,90 @@ export const TreeExamples = () => {
|
|
371
435
|
</TreeNode>
|
372
436
|
</Tree>
|
373
437
|
</div>
|
438
|
+
<CodeSnippet
|
439
|
+
language="jsx"
|
440
|
+
code={`<Tree ariaLabel="Árbol con drag and drop">
|
441
|
+
<TreeNode
|
442
|
+
id="inbox"
|
443
|
+
label="Inbox"
|
444
|
+
icon="inbox"
|
445
|
+
open={true}
|
446
|
+
badge={5}
|
447
|
+
tooltip="5 unread messages"
|
448
|
+
draggable={true}
|
449
|
+
onDragStart={handleDragStart}
|
450
|
+
onDrop={handleDrop}
|
451
|
+
>
|
452
|
+
<TreeItem
|
453
|
+
id="msg1"
|
454
|
+
label="Important Message"
|
455
|
+
icon="priority_high"
|
456
|
+
badge="!"
|
457
|
+
tooltip="High priority message"
|
458
|
+
draggable={true}
|
459
|
+
onDragStart={handleDragStart}
|
460
|
+
onDrop={handleDrop}
|
461
|
+
/>
|
462
|
+
</TreeNode>
|
463
|
+
</Tree>`}
|
464
|
+
/>
|
465
|
+
</section>
|
466
|
+
|
467
|
+
{/* Tree con búsqueda y control de expansión */}
|
468
|
+
<section style={{ marginBottom: '2rem' }}>
|
469
|
+
<h3>Tree con Búsqueda y Control de Expansión</h3>
|
470
|
+
<div style={{
|
471
|
+
background: '#fff',
|
472
|
+
border: '1px solid #ddd',
|
473
|
+
borderRadius: '8px',
|
474
|
+
overflow: 'hidden',
|
475
|
+
maxHeight: '400px'
|
476
|
+
}}>
|
477
|
+
<Tree
|
478
|
+
searchable={true}
|
479
|
+
searchPlaceholder="Buscar en la estructura..."
|
480
|
+
searchBy={['label']}
|
481
|
+
showExpandIcon={true}
|
482
|
+
onExpandAll={() => console.log('Expand all')}
|
483
|
+
onCollapseAll={() => console.log('Collapse all')}
|
484
|
+
ariaLabel="Árbol con búsqueda y controles de expansión"
|
485
|
+
>
|
486
|
+
<TreeNode id="projects" label="Projects" icon="work" open={false}>
|
487
|
+
<TreeNode id="web-project" label="Web Project" icon="web" open={false}>
|
488
|
+
<TreeItem id="index-html" label="index.html" icon="code" onSelect={handleSelect} selected={selectedItem === 'index-html'} />
|
489
|
+
<TreeItem id="styles-css" label="styles.css" icon="palette" onSelect={handleSelect} selected={selectedItem === 'styles-css'} />
|
490
|
+
<TreeItem id="script-js" label="script.js" icon="javascript" onSelect={handleSelect} selected={selectedItem === 'script-js'} />
|
491
|
+
</TreeNode>
|
492
|
+
<TreeNode id="mobile-app" label="Mobile App" icon="phone_android" open={false}>
|
493
|
+
<TreeItem id="main-dart" label="main.dart" icon="code" onSelect={handleSelect} selected={selectedItem === 'main-dart'} />
|
494
|
+
<TreeItem id="pubspec" label="pubspec.yaml" icon="settings" onSelect={handleSelect} selected={selectedItem === 'pubspec'} />
|
495
|
+
</TreeNode>
|
496
|
+
</TreeNode>
|
497
|
+
</Tree>
|
498
|
+
</div>
|
499
|
+
<CodeSnippet
|
500
|
+
language="jsx"
|
501
|
+
code={`<Tree
|
502
|
+
searchable={true}
|
503
|
+
searchPlaceholder="Buscar en la estructura..."
|
504
|
+
searchBy={['label']}
|
505
|
+
showExpandIcon={true}
|
506
|
+
onExpandAll={() => console.log('Expand all')}
|
507
|
+
onCollapseAll={() => console.log('Collapse all')}
|
508
|
+
>
|
509
|
+
<TreeNode id="projects" label="Projects" icon="work">
|
510
|
+
<TreeNode id="web-project" label="Web Project" icon="web">
|
511
|
+
<TreeItem id="index-html" label="index.html" icon="code" />
|
512
|
+
<TreeItem id="styles-css" label="styles.css" icon="palette" />
|
513
|
+
</TreeNode>
|
514
|
+
</TreeNode>
|
515
|
+
</Tree>`}
|
516
|
+
/>
|
374
517
|
</section>
|
375
518
|
|
376
519
|
{/* Tree con controles de expansión */}
|
377
520
|
<section style={{ marginBottom: '2rem' }}>
|
378
|
-
<h3>Tree con
|
521
|
+
<h3>Tree con Control de Expansión</h3>
|
379
522
|
<div style={{
|
380
523
|
background: '#fff',
|
381
524
|
border: '1px solid #ddd',
|
@@ -383,9 +526,8 @@ export const TreeExamples = () => {
|
|
383
526
|
overflow: 'hidden',
|
384
527
|
maxHeight: '400px'
|
385
528
|
}}>
|
386
|
-
<Tree
|
387
|
-
|
388
|
-
collapseAll={true}
|
529
|
+
<Tree
|
530
|
+
showExpandIcon={true}
|
389
531
|
onExpandAll={() => console.log('Expand all')}
|
390
532
|
onCollapseAll={() => console.log('Collapse all')}
|
391
533
|
ariaLabel="Árbol con controles de expansión"
|
@@ -408,6 +550,26 @@ export const TreeExamples = () => {
|
|
408
550
|
</TreeNode>
|
409
551
|
</Tree>
|
410
552
|
</div>
|
553
|
+
<CodeSnippet
|
554
|
+
language="jsx"
|
555
|
+
code={`<Tree
|
556
|
+
showExpandIcon={true}
|
557
|
+
onExpandAll={() => console.log('Expand all')}
|
558
|
+
onCollapseAll={() => console.log('Collapse all')}
|
559
|
+
ariaLabel="Árbol con controles de expansión"
|
560
|
+
>
|
561
|
+
<TreeNode id="company" label="Company Structure" icon="business">
|
562
|
+
<TreeNode id="engineering" label="Engineering" icon="engineering">
|
563
|
+
<TreeNode id="frontend" label="Frontend Team" icon="web">
|
564
|
+
<TreeItem id="dev1" label="John Doe - Senior Developer"
|
565
|
+
icon="person" onSelect={handleSelect} />
|
566
|
+
<TreeItem id="dev2" label="Jane Smith - UI Designer"
|
567
|
+
icon="design_services" onSelect={handleSelect} />
|
568
|
+
</TreeNode>
|
569
|
+
</TreeNode>
|
570
|
+
</TreeNode>
|
571
|
+
</Tree>`}
|
572
|
+
/>
|
411
573
|
</section>
|
412
574
|
|
413
575
|
{/* Estados especiales */}
|