uifolio 0.5.4 → 0.5.5
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/README.md +1 -1
- package/package.json +1 -1
- package/src/components/ui/table.tsx +49 -23
package/README.md
CHANGED
|
@@ -90,7 +90,7 @@ only marks the installation as complete when that is relevant.
|
|
|
90
90
|
| ResizablePanels | `src/components/ui/resizable.tsx` | horizontal/vertical groups, handles, min-size, keyboard |
|
|
91
91
|
| OtpInput | `src/components/ui/otp-input.tsx` | 4 fields, paste, rotate + success check |
|
|
92
92
|
| ColorPicker | `src/components/ui/color-picker.tsx` | advanced panel, saturation/lightness, hue, alpha, eyedropper, RGB channels, presets, HEX/RGB/HSL/RGBA |
|
|
93
|
-
| Table | `src/components/ui/table.tsx` | typed
|
|
93
|
+
| Table | `src/components/ui/table.tsx` | shadcn-style typed table, uniform `px-4` cells and a wider gap before Actions, select-all checkbox, row actions |
|
|
94
94
|
|
|
95
95
|
Copyable helpers (the CLI follows them automatically): `src/lib/utils.ts`,
|
|
96
96
|
`src/lib/video.ts`, `src/lib/vtt.ts`, `src/lib/date.ts`, `src/lib/uploader.ts`, `src/lib/color.ts`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uifolio",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.5",
|
|
4
4
|
"description": "CLI that copies React components (calendar, video/audio players, OTP, editor, upload) and their helpers into your project, with Tailwind CSS 4 tokens.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import type
|
|
3
|
+
import { useEffect, useRef, type ReactNode } from 'react'
|
|
4
4
|
import { cn } from '@/lib/utils'
|
|
5
5
|
import { useControllableValue } from '@/lib/use-controllable'
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ export interface TableColumn<T> {
|
|
|
8
8
|
/** Stable identifier, also used as the React key of the column. */
|
|
9
9
|
key: string
|
|
10
10
|
header: ReactNode
|
|
11
|
-
cell: (row: T) => ReactNode
|
|
11
|
+
cell: (row: T, index: number) => ReactNode
|
|
12
12
|
/** Applied to the header and body cells: width, nowrap… */
|
|
13
13
|
className?: string
|
|
14
14
|
align?: 'left' | 'center' | 'right'
|
|
@@ -36,9 +36,10 @@ function alignClass(align: TableColumn<unknown>['align']): string {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
* Data table with a shadcn-like API: typed columns, optional
|
|
40
|
-
* dedicated actions column. Every cell on the left shares the
|
|
41
|
-
* padding; the actions column keeps a wider `pl-10` gap with the
|
|
39
|
+
* Data table with a shadcn-like API: typed columns, an optional select-all
|
|
40
|
+
* checkbox, and a dedicated actions column. Every cell on the left shares the
|
|
41
|
+
* same `px-4` padding; the actions column keeps a wider `pl-10` gap with the
|
|
42
|
+
* last column.
|
|
42
43
|
*/
|
|
43
44
|
export function Table<T>({
|
|
44
45
|
columns,
|
|
@@ -59,6 +60,17 @@ export function Table<T>({
|
|
|
59
60
|
defaultSelectedKeys,
|
|
60
61
|
onSelectionChange,
|
|
61
62
|
)
|
|
63
|
+
const selectAllRef = useRef<HTMLInputElement>(null)
|
|
64
|
+
|
|
65
|
+
const keys = rows.map((row) => String(rowKey(row)))
|
|
66
|
+
const allSelected = keys.length > 0 && keys.every((key) => selection.includes(key))
|
|
67
|
+
const someSelected = keys.some((key) => selection.includes(key))
|
|
68
|
+
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (selectAllRef.current) {
|
|
71
|
+
selectAllRef.current.indeterminate = someSelected && !allSelected
|
|
72
|
+
}
|
|
73
|
+
}, [someSelected, allSelected])
|
|
62
74
|
|
|
63
75
|
const toggle = (key: string, checked: boolean) => {
|
|
64
76
|
setSelection((current) =>
|
|
@@ -70,13 +82,29 @@ export function Table<T>({
|
|
|
70
82
|
)
|
|
71
83
|
}
|
|
72
84
|
|
|
73
|
-
const
|
|
85
|
+
const toggleAll = (checked: boolean) => {
|
|
86
|
+
setSelection(checked ? keys : [])
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const columnsCount = columns.length + (selectable ? 1 : 0) + (actions ? 1 : 0)
|
|
74
90
|
|
|
75
91
|
return (
|
|
76
92
|
<div className={cn('w-full overflow-x-auto rounded-sm border bg-card', className)}>
|
|
77
93
|
<table className="w-full min-w-[860px] border-collapse text-left text-xs">
|
|
78
94
|
<thead>
|
|
79
95
|
<tr className="border-b bg-muted/50">
|
|
96
|
+
{selectable && (
|
|
97
|
+
<th scope="col" className="w-10 px-4 py-3.5">
|
|
98
|
+
<input
|
|
99
|
+
ref={selectAllRef}
|
|
100
|
+
type="checkbox"
|
|
101
|
+
checked={allSelected}
|
|
102
|
+
onChange={(event) => toggleAll(event.target.checked)}
|
|
103
|
+
aria-label="Select all rows"
|
|
104
|
+
className="size-4 cursor-pointer rounded-sm border-border accent-primary"
|
|
105
|
+
/>
|
|
106
|
+
</th>
|
|
107
|
+
)}
|
|
80
108
|
{columns.map((column) => (
|
|
81
109
|
<th
|
|
82
110
|
key={column.key}
|
|
@@ -108,7 +136,7 @@ export function Table<T>({
|
|
|
108
136
|
</td>
|
|
109
137
|
</tr>
|
|
110
138
|
) : (
|
|
111
|
-
rows.map((row) => {
|
|
139
|
+
rows.map((row, rowIndex) => {
|
|
112
140
|
const key = String(rowKey(row))
|
|
113
141
|
const selected = selection.includes(key)
|
|
114
142
|
|
|
@@ -122,7 +150,19 @@ export function Table<T>({
|
|
|
122
150
|
selected ? 'bg-primary/5' : 'hover:bg-muted/30',
|
|
123
151
|
)}
|
|
124
152
|
>
|
|
125
|
-
{
|
|
153
|
+
{selectable && (
|
|
154
|
+
<td className="w-10 px-4 py-3.5 align-middle">
|
|
155
|
+
<input
|
|
156
|
+
type="checkbox"
|
|
157
|
+
checked={selected}
|
|
158
|
+
onChange={(event) => toggle(key, event.target.checked)}
|
|
159
|
+
onClick={(event) => event.stopPropagation()}
|
|
160
|
+
aria-label={`Select row ${key}`}
|
|
161
|
+
className="size-4 cursor-pointer rounded-sm border-border accent-primary"
|
|
162
|
+
/>
|
|
163
|
+
</td>
|
|
164
|
+
)}
|
|
165
|
+
{columns.map((column) => (
|
|
126
166
|
<td
|
|
127
167
|
key={column.key}
|
|
128
168
|
className={cn(
|
|
@@ -131,21 +171,7 @@ export function Table<T>({
|
|
|
131
171
|
column.className,
|
|
132
172
|
)}
|
|
133
173
|
>
|
|
134
|
-
{
|
|
135
|
-
<div className="flex items-center gap-3">
|
|
136
|
-
<input
|
|
137
|
-
type="checkbox"
|
|
138
|
-
checked={selected}
|
|
139
|
-
onChange={(event) => toggle(key, event.target.checked)}
|
|
140
|
-
onClick={(event) => event.stopPropagation()}
|
|
141
|
-
aria-label={`Select row ${key}`}
|
|
142
|
-
className="size-4 shrink-0 cursor-pointer rounded-sm border-border accent-primary"
|
|
143
|
-
/>
|
|
144
|
-
{column.cell(row)}
|
|
145
|
-
</div>
|
|
146
|
-
) : (
|
|
147
|
-
column.cell(row)
|
|
148
|
-
)}
|
|
174
|
+
{column.cell(row, rowIndex)}
|
|
149
175
|
</td>
|
|
150
176
|
))}
|
|
151
177
|
{actions && (
|