@proyecto-viviana/ui 0.2.5 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/index.js +210 -557
  2. package/dist/index.js.map +7 -1
  3. package/dist/index.ssr.js +42 -399
  4. package/dist/index.ssr.js.map +7 -1
  5. package/dist/radio/index.d.ts +27 -12
  6. package/dist/radio/index.d.ts.map +1 -1
  7. package/package.json +11 -12
  8. package/src/alert/index.tsx +0 -48
  9. package/src/assets/favicon.png +0 -0
  10. package/src/assets/fire.gif +0 -0
  11. package/src/autocomplete/index.tsx +0 -313
  12. package/src/avatar/index.tsx +0 -75
  13. package/src/badge/index.tsx +0 -43
  14. package/src/breadcrumbs/index.tsx +0 -207
  15. package/src/button/Button.tsx +0 -74
  16. package/src/button/index.ts +0 -2
  17. package/src/button/types.ts +0 -24
  18. package/src/calendar/DateField.tsx +0 -200
  19. package/src/calendar/DatePicker.tsx +0 -298
  20. package/src/calendar/RangeCalendar.tsx +0 -236
  21. package/src/calendar/TimeField.tsx +0 -196
  22. package/src/calendar/index.tsx +0 -223
  23. package/src/checkbox/index.tsx +0 -257
  24. package/src/color/index.tsx +0 -687
  25. package/src/combobox/index.tsx +0 -383
  26. package/src/components.css +0 -1077
  27. package/src/custom/calendar-card/index.tsx +0 -66
  28. package/src/custom/chip/index.tsx +0 -46
  29. package/src/custom/conversation/index.tsx +0 -105
  30. package/src/custom/event-card/index.tsx +0 -132
  31. package/src/custom/header/index.tsx +0 -33
  32. package/src/custom/lateral-nav/index.tsx +0 -88
  33. package/src/custom/logo/index.tsx +0 -58
  34. package/src/custom/nav-header/index.tsx +0 -42
  35. package/src/custom/page-layout/index.tsx +0 -29
  36. package/src/custom/profile-card/index.tsx +0 -64
  37. package/src/custom/project-card/index.tsx +0 -59
  38. package/src/custom/timeline-item/index.tsx +0 -105
  39. package/src/dialog/Dialog.tsx +0 -260
  40. package/src/dialog/index.tsx +0 -3
  41. package/src/disclosure/index.tsx +0 -307
  42. package/src/gridlist/index.tsx +0 -403
  43. package/src/icon/icons/GitHubIcon.tsx +0 -20
  44. package/src/icon/index.tsx +0 -48
  45. package/src/index.ts +0 -322
  46. package/src/landmark/index.tsx +0 -231
  47. package/src/link/index.tsx +0 -130
  48. package/src/listbox/index.tsx +0 -231
  49. package/src/menu/index.tsx +0 -297
  50. package/src/meter/index.tsx +0 -163
  51. package/src/numberfield/index.tsx +0 -482
  52. package/src/popover/index.tsx +0 -260
  53. package/src/progress-bar/index.tsx +0 -169
  54. package/src/radio/index.tsx +0 -173
  55. package/src/searchfield/index.tsx +0 -453
  56. package/src/select/index.tsx +0 -349
  57. package/src/separator/index.tsx +0 -141
  58. package/src/slider/index.tsx +0 -382
  59. package/src/styles.css +0 -450
  60. package/src/switch/ToggleSwitch.tsx +0 -112
  61. package/src/switch/index.tsx +0 -90
  62. package/src/table/index.tsx +0 -531
  63. package/src/tabs/index.tsx +0 -273
  64. package/src/tag-group/index.tsx +0 -240
  65. package/src/test-utils/index.ts +0 -32
  66. package/src/textfield/index.tsx +0 -211
  67. package/src/theme.css +0 -101
  68. package/src/toast/index.tsx +0 -324
  69. package/src/toolbar/index.tsx +0 -108
  70. package/src/tooltip/index.tsx +0 -197
  71. package/src/tree/index.tsx +0 -494
@@ -1,531 +0,0 @@
1
- /**
2
- * Table component for proyecto-viviana-ui
3
- *
4
- * Styled table component built on top of solidaria-components.
5
- * Inspired by Spectrum 2's Table component patterns.
6
- */
7
-
8
- import { type JSX, splitProps, createContext, useContext, Show } from 'solid-js'
9
- import {
10
- Table as HeadlessTable,
11
- TableHeader as HeadlessTableHeader,
12
- TableColumn as HeadlessTableColumn,
13
- TableBody as HeadlessTableBody,
14
- TableRow as HeadlessTableRow,
15
- TableCell as HeadlessTableCell,
16
- TableSelectionCheckbox as HeadlessTableSelectionCheckbox,
17
- TableSelectAllCheckbox as HeadlessTableSelectAllCheckbox,
18
- type TableProps as HeadlessTableProps,
19
- type TableHeaderProps as HeadlessTableHeaderProps,
20
- type TableColumnProps as HeadlessTableColumnProps,
21
- type TableBodyProps as HeadlessTableBodyProps,
22
- type TableRowProps as HeadlessTableRowProps,
23
- type TableCellProps as HeadlessTableCellProps,
24
- type TableRenderProps,
25
- type TableColumnRenderProps,
26
- type TableRowRenderProps,
27
- type TableCellRenderProps,
28
- } from '@proyecto-viviana/solidaria-components'
29
- import type { Key, SortDescriptor, ColumnDefinition } from '@proyecto-viviana/solid-stately'
30
-
31
- // ============================================
32
- // SIZE CONTEXT
33
- // ============================================
34
-
35
- export type TableSize = 'sm' | 'md' | 'lg'
36
- export type TableVariant = 'default' | 'striped' | 'bordered'
37
-
38
- interface TableContextValue {
39
- size: TableSize
40
- variant: TableVariant
41
- }
42
-
43
- const TableSizeContext = createContext<TableContextValue>({ size: 'md', variant: 'default' })
44
-
45
- // ============================================
46
- // TYPES
47
- // ============================================
48
-
49
- export interface TableProps<T extends object>
50
- extends Omit<HeadlessTableProps<T>, 'class' | 'style' | 'children'> {
51
- /** The size of the table. */
52
- size?: TableSize
53
- /** The visual variant of the table. */
54
- variant?: TableVariant
55
- /** Additional CSS class name. */
56
- class?: string
57
- /** Title for the table. */
58
- title?: string
59
- /** Description for the table. */
60
- description?: string
61
- /** Children components (TableHeader, TableBody). */
62
- children?: JSX.Element | (() => JSX.Element)
63
- }
64
-
65
- export interface TableHeaderProps extends Omit<HeadlessTableHeaderProps, 'class' | 'style'> {
66
- /** Additional CSS class name. */
67
- class?: string
68
- }
69
-
70
- export interface TableColumnProps extends Omit<HeadlessTableColumnProps, 'class' | 'style'> {
71
- /** Additional CSS class name. */
72
- class?: string
73
- /** Text alignment for the column. */
74
- align?: 'left' | 'center' | 'right'
75
- /** Width of the column (CSS value). */
76
- width?: string
77
- }
78
-
79
- export interface TableBodyProps<T> extends Omit<HeadlessTableBodyProps<T>, 'class' | 'style'> {
80
- /** Additional CSS class name. */
81
- class?: string
82
- }
83
-
84
- export interface TableRowProps<T> extends Omit<HeadlessTableRowProps<T>, 'class' | 'style'> {
85
- /** Additional CSS class name. */
86
- class?: string
87
- }
88
-
89
- export interface TableCellProps extends Omit<HeadlessTableCellProps, 'class' | 'style'> {
90
- /** Additional CSS class name. */
91
- class?: string
92
- /** Text alignment for the cell. */
93
- align?: 'left' | 'center' | 'right'
94
- }
95
-
96
- // ============================================
97
- // STYLES
98
- // ============================================
99
-
100
- const sizeStyles = {
101
- sm: {
102
- table: 'text-sm',
103
- headerCell: 'px-3 py-2',
104
- cell: 'px-3 py-2',
105
- checkbox: 'w-4 h-4',
106
- },
107
- md: {
108
- table: 'text-base',
109
- headerCell: 'px-4 py-3',
110
- cell: 'px-4 py-3',
111
- checkbox: 'w-5 h-5',
112
- },
113
- lg: {
114
- table: 'text-lg',
115
- headerCell: 'px-5 py-4',
116
- cell: 'px-5 py-4',
117
- checkbox: 'w-6 h-6',
118
- },
119
- }
120
-
121
- const variantStyles = {
122
- default: {
123
- wrapper: 'rounded-lg border border-bg-300 overflow-hidden',
124
- header: 'bg-bg-300 border-b border-bg-400',
125
- row: '',
126
- rowHover: 'hover:bg-bg-200/50',
127
- rowSelected: 'bg-accent/10',
128
- },
129
- striped: {
130
- wrapper: 'rounded-lg border border-bg-300 overflow-hidden',
131
- header: 'bg-bg-300 border-b border-bg-400',
132
- row: 'even:bg-bg-200/30',
133
- rowHover: 'hover:bg-bg-200/50',
134
- rowSelected: 'bg-accent/10',
135
- },
136
- bordered: {
137
- wrapper: 'rounded-lg border-2 border-bg-400 overflow-hidden',
138
- header: 'bg-bg-300 border-b-2 border-bg-400',
139
- row: 'border-b border-bg-300 last:border-b-0',
140
- rowHover: 'hover:bg-bg-200/50',
141
- rowSelected: 'bg-accent/10',
142
- },
143
- }
144
-
145
- const alignStyles = {
146
- left: 'text-left',
147
- center: 'text-center',
148
- right: 'text-right',
149
- }
150
-
151
- // ============================================
152
- // TABLE COMPONENT
153
- // ============================================
154
-
155
- /**
156
- * A table displays data in rows and columns and enables a user to navigate its contents
157
- * via directional navigation keys, and optionally supports row selection and sorting.
158
- *
159
- * Built on solidaria-components Table for full accessibility support.
160
- *
161
- * @example
162
- * ```tsx
163
- * const columns = [
164
- * { key: 'name', name: 'Name' },
165
- * { key: 'role', name: 'Role' },
166
- * { key: 'status', name: 'Status' },
167
- * ]
168
- *
169
- * const rows = [
170
- * { id: '1', name: 'John', role: 'Developer', status: 'Active' },
171
- * { id: '2', name: 'Jane', role: 'Designer', status: 'Active' },
172
- * ]
173
- *
174
- * <Table items={rows} columns={columns} selectionMode="multiple">
175
- * {() => (
176
- * <>
177
- * <TableHeader>
178
- * {() => (
179
- * <For each={columns}>
180
- * {(col) => <TableColumn id={col.key}>{col.name}</TableColumn>}
181
- * </For>
182
- * )}
183
- * </TableHeader>
184
- * <TableBody>
185
- * {(row) => (
186
- * <TableRow id={row.id}>
187
- * {() => (
188
- * <>
189
- * <TableCell>{row.name}</TableCell>
190
- * <TableCell>{row.role}</TableCell>
191
- * <TableCell>{row.status}</TableCell>
192
- * </>
193
- * )}
194
- * </TableRow>
195
- * )}
196
- * </TableBody>
197
- * </>
198
- * )}
199
- * </Table>
200
- * ```
201
- */
202
- export function Table<T extends object>(props: TableProps<T>): JSX.Element {
203
- const [local, headlessProps] = splitProps(props, [
204
- 'size',
205
- 'variant',
206
- 'class',
207
- 'title',
208
- 'description',
209
- ])
210
-
211
- const size = () => local.size ?? 'md'
212
- const variant = () => local.variant ?? 'default'
213
- const styles = () => sizeStyles[size()]
214
- const variantStyle = () => variantStyles[variant()]
215
- const customClass = local.class ?? ''
216
-
217
- const getClassName = (renderProps: TableRenderProps): string => {
218
- const base = 'w-full bg-bg-400'
219
- const sizeClass = styles().table
220
-
221
- let stateClass = ''
222
- if (renderProps.isEmpty) {
223
- stateClass = ''
224
- }
225
-
226
- const focusClass = renderProps.isFocusVisible
227
- ? 'ring-2 ring-accent-300 ring-offset-2 ring-offset-bg-400'
228
- : ''
229
-
230
- return [base, sizeClass, stateClass, focusClass, customClass].filter(Boolean).join(' ')
231
- }
232
-
233
- const contextValue = () => ({ size: size(), variant: variant() })
234
-
235
- return (
236
- <TableSizeContext.Provider value={contextValue()}>
237
- <div class="flex flex-col gap-2">
238
- <Show when={local.title}>
239
- <h3 class="text-lg font-semibold text-primary-100">{local.title}</h3>
240
- </Show>
241
- <Show when={local.description}>
242
- <p class="text-sm text-primary-400">{local.description}</p>
243
- </Show>
244
- <div class={variantStyle().wrapper}>
245
- <HeadlessTable {...headlessProps} class={getClassName}>
246
- {props.children}
247
- </HeadlessTable>
248
- </div>
249
- </div>
250
- </TableSizeContext.Provider>
251
- )
252
- }
253
-
254
- // ============================================
255
- // TABLE HEADER COMPONENT
256
- // ============================================
257
-
258
- /**
259
- * A header row in a table containing column headers.
260
- */
261
- export function TableHeader(props: TableHeaderProps): JSX.Element {
262
- const [local, headlessProps] = splitProps(props, ['class'])
263
- const context = useContext(TableSizeContext)
264
- const variantStyle = variantStyles[context.variant]
265
- const customClass = local.class ?? ''
266
-
267
- const className = [variantStyle.header, customClass].filter(Boolean).join(' ')
268
-
269
- return (
270
- <HeadlessTableHeader {...headlessProps} class={className}>
271
- {props.children}
272
- </HeadlessTableHeader>
273
- )
274
- }
275
-
276
- // ============================================
277
- // TABLE COLUMN COMPONENT
278
- // ============================================
279
-
280
- /**
281
- * A column header in a table.
282
- */
283
- export function TableColumn(props: TableColumnProps): JSX.Element {
284
- const [local, headlessProps] = splitProps(props, ['class', 'align', 'width'])
285
- const context = useContext(TableSizeContext)
286
- const sizeStyle = sizeStyles[context.size]
287
- const customClass = local.class ?? ''
288
-
289
- const getClassName = (renderProps: TableColumnRenderProps): string => {
290
- const base = 'font-semibold text-primary-200 select-none'
291
- const sizeClass = sizeStyle.headerCell
292
- const alignClass = alignStyles[local.align ?? 'left']
293
-
294
- let sortClass = ''
295
- if (renderProps.isSortable) {
296
- sortClass = 'cursor-pointer'
297
- if (renderProps.isHovered) {
298
- sortClass += ' text-primary-100'
299
- }
300
- }
301
-
302
- const focusClass = renderProps.isFocusVisible
303
- ? 'ring-2 ring-inset ring-accent-300'
304
- : ''
305
-
306
- return [base, sizeClass, alignClass, sortClass, focusClass, customClass].filter(Boolean).join(' ')
307
- }
308
-
309
- const getStyle = (): JSX.CSSProperties | undefined => {
310
- if (local.width) {
311
- return { width: local.width }
312
- }
313
- return undefined
314
- }
315
-
316
- return (
317
- <HeadlessTableColumn {...headlessProps} class={getClassName} style={getStyle()}>
318
- {(renderProps: TableColumnRenderProps) => (
319
- <div class="flex items-center gap-2">
320
- <span class="flex-1">
321
- {typeof props.children === 'function'
322
- ? props.children(renderProps)
323
- : props.children}
324
- </span>
325
- <Show when={renderProps.isSortable && renderProps.sortDirection}>
326
- <SortIcon direction={renderProps.sortDirection!} class="w-4 h-4" />
327
- </Show>
328
- </div>
329
- )}
330
- </HeadlessTableColumn>
331
- )
332
- }
333
-
334
- // ============================================
335
- // TABLE BODY COMPONENT
336
- // ============================================
337
-
338
- /**
339
- * The body of a table containing data rows.
340
- */
341
- export function TableBody<T extends object>(props: TableBodyProps<T>): JSX.Element {
342
- const [local, headlessProps] = splitProps(props, ['class', 'renderEmptyState'])
343
- const customClass = local.class ?? ''
344
-
345
- const defaultEmptyState = () => (
346
- <tr>
347
- <td colSpan={100} class="py-8 text-center text-primary-400">
348
- <div class="flex flex-col items-center gap-2">
349
- <EmptyIcon class="w-12 h-12 text-primary-500" />
350
- <span>No data available</span>
351
- </div>
352
- </td>
353
- </tr>
354
- )
355
-
356
- return (
357
- <HeadlessTableBody
358
- {...headlessProps}
359
- class={customClass}
360
- renderEmptyState={local.renderEmptyState ?? defaultEmptyState}
361
- >
362
- {props.children}
363
- </HeadlessTableBody>
364
- )
365
- }
366
-
367
- // ============================================
368
- // TABLE ROW COMPONENT
369
- // ============================================
370
-
371
- /**
372
- * A row in a table.
373
- */
374
- export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element {
375
- const [local, headlessProps] = splitProps(props, ['class'])
376
- const context = useContext(TableSizeContext)
377
- const variantStyle = variantStyles[context.variant]
378
- const customClass = local.class ?? ''
379
-
380
- const getClassName = (renderProps: TableRowRenderProps): string => {
381
- const base = 'transition-colors duration-150 outline-none'
382
- const variantClass = variantStyle.row
383
-
384
- let stateClass = ''
385
- if (renderProps.isDisabled) {
386
- stateClass = 'opacity-50 cursor-not-allowed'
387
- } else if (renderProps.isSelected) {
388
- stateClass = variantStyle.rowSelected
389
- } else if (renderProps.isHovered) {
390
- stateClass = variantStyle.rowHover
391
- }
392
-
393
- const focusClass = renderProps.isFocusVisible
394
- ? 'ring-2 ring-inset ring-accent-300'
395
- : ''
396
-
397
- const pressedClass = renderProps.isPressed ? 'bg-bg-200/70' : ''
398
-
399
- return [base, variantClass, stateClass, focusClass, pressedClass, customClass]
400
- .filter(Boolean)
401
- .join(' ')
402
- }
403
-
404
- return (
405
- <HeadlessTableRow {...headlessProps} class={getClassName}>
406
- {props.children}
407
- </HeadlessTableRow>
408
- )
409
- }
410
-
411
- // ============================================
412
- // TABLE CELL COMPONENT
413
- // ============================================
414
-
415
- /**
416
- * A cell in a table row.
417
- */
418
- export function TableCell(props: TableCellProps): JSX.Element {
419
- const [local, headlessProps] = splitProps(props, ['class', 'align'])
420
- const context = useContext(TableSizeContext)
421
- const sizeStyle = sizeStyles[context.size]
422
- const customClass = local.class ?? ''
423
-
424
- const getClassName = (renderProps: TableCellRenderProps): string => {
425
- const base = 'text-primary-200'
426
- const sizeClass = sizeStyle.cell
427
- const alignClass = alignStyles[local.align ?? 'left']
428
-
429
- const focusClass = renderProps.isFocusVisible
430
- ? 'ring-2 ring-inset ring-accent-300'
431
- : ''
432
-
433
- return [base, sizeClass, alignClass, focusClass, customClass].filter(Boolean).join(' ')
434
- }
435
-
436
- return (
437
- <HeadlessTableCell {...headlessProps} class={getClassName}>
438
- {props.children}
439
- </HeadlessTableCell>
440
- )
441
- }
442
-
443
- // ============================================
444
- // TABLE SELECTION CHECKBOX COMPONENT
445
- // ============================================
446
-
447
- /**
448
- * A styled checkbox cell for row selection.
449
- */
450
- export function TableSelectionCheckbox(props: { rowKey: Key }): JSX.Element {
451
- const context = useContext(TableSizeContext)
452
- const sizeStyle = sizeStyles[context.size]
453
- const checkboxClass = `${sizeStyle.checkbox} rounded border-2 border-primary-500 bg-bg-400 text-accent cursor-pointer checked:bg-accent checked:border-accent focus:ring-2 focus:ring-accent-300 focus:ring-offset-1 focus:ring-offset-bg-400`
454
-
455
- return (
456
- <td class={`${sizeStyle.cell} w-px`}>
457
- <span class={checkboxClass}>
458
- <HeadlessTableSelectionCheckbox rowKey={props.rowKey} />
459
- </span>
460
- </td>
461
- )
462
- }
463
-
464
- /**
465
- * A styled checkbox for select-all functionality.
466
- */
467
- export function TableSelectAllCheckbox(): JSX.Element {
468
- const context = useContext(TableSizeContext)
469
- const sizeStyle = sizeStyles[context.size]
470
- const checkboxClass = `${sizeStyle.checkbox} rounded border-2 border-primary-500 bg-bg-400 text-accent cursor-pointer checked:bg-accent checked:border-accent focus:ring-2 focus:ring-accent-300 focus:ring-offset-1 focus:ring-offset-bg-400`
471
-
472
- return (
473
- <th class={`${sizeStyle.headerCell} w-px`}>
474
- <span class={checkboxClass}>
475
- <HeadlessTableSelectAllCheckbox />
476
- </span>
477
- </th>
478
- )
479
- }
480
-
481
- // ============================================
482
- // ICONS
483
- // ============================================
484
-
485
- function SortIcon(props: { direction: 'ascending' | 'descending'; class?: string }): JSX.Element {
486
- return (
487
- <svg
488
- class={props.class}
489
- fill="none"
490
- viewBox="0 0 24 24"
491
- stroke="currentColor"
492
- stroke-width="2"
493
- >
494
- {props.direction === 'ascending' ? (
495
- <path stroke-linecap="round" stroke-linejoin="round" d="M5 15l7-7 7 7" />
496
- ) : (
497
- <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />
498
- )}
499
- </svg>
500
- )
501
- }
502
-
503
- function EmptyIcon(props: { class?: string }): JSX.Element {
504
- return (
505
- <svg
506
- class={props.class}
507
- fill="none"
508
- viewBox="0 0 24 24"
509
- stroke="currentColor"
510
- stroke-width="1.5"
511
- >
512
- <path
513
- stroke-linecap="round"
514
- stroke-linejoin="round"
515
- d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"
516
- />
517
- </svg>
518
- )
519
- }
520
-
521
- // Attach sub-components for convenience
522
- Table.Header = TableHeader
523
- Table.Column = TableColumn
524
- Table.Body = TableBody
525
- Table.Row = TableRow
526
- Table.Cell = TableCell
527
- Table.SelectionCheckbox = TableSelectionCheckbox
528
- Table.SelectAllCheckbox = TableSelectAllCheckbox
529
-
530
- // Re-export types for convenience
531
- export type { Key, SortDescriptor, ColumnDefinition }