@phpsoftbox/react-softbox 0.3.0 → 0.4.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.
- package/README.md +81 -1
- package/dist/components/Badge/Badge.d.ts +3 -1
- package/dist/components/Badge/Badge.js +7 -2
- package/dist/components/Badge/Badge.js.map +1 -1
- package/dist/components/Badge/Badge.module.css +18 -0
- package/dist/components/Input/ErrorTooltip/ErrorTooltip.d.ts +12 -0
- package/dist/components/Input/ErrorTooltip/ErrorTooltip.js +25 -0
- package/dist/components/Input/ErrorTooltip/ErrorTooltip.js.map +1 -0
- package/dist/components/Input/ErrorTooltip/ErrorTooltip.module.css +31 -0
- package/dist/components/Input/Field.js +8 -1
- package/dist/components/Input/Field.js.map +1 -1
- package/dist/components/Input/FloatLabel/FloatLabel.module.css +5 -3
- package/dist/components/Input/FormField/FormField.d.ts +2 -0
- package/dist/components/Input/FormField/FormField.js +12 -1
- package/dist/components/Input/FormField/FormField.js.map +1 -1
- package/dist/components/Input/FormField/FormField.module.css +1 -0
- package/dist/components/Input/Input.d.ts +2 -0
- package/dist/components/Input/Input.js +2 -0
- package/dist/components/Input/Input.js.map +1 -1
- package/dist/components/Input/Input.module.css +8 -1
- package/dist/components/Input/Select/Select.d.ts +52 -13
- package/dist/components/Input/Select/Select.js +103 -25
- package/dist/components/Input/Select/Select.js.map +1 -1
- package/dist/components/Input/Select/Select.module.css +65 -23
- package/dist/components/Modal/Modal.d.ts +2 -1
- package/dist/components/Modal/Modal.js +18 -1
- package/dist/components/Modal/Modal.js.map +1 -1
- package/dist/components/Table/Table.d.ts +26 -0
- package/dist/components/Table/Table.js +133 -91
- package/dist/components/Table/Table.js.map +1 -1
- package/dist/components/Table/Table.module.css +41 -1
- package/dist/components/Tabs/Tabs.js +7 -6
- package/dist/components/Tabs/Tabs.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.d.ts +33 -0
- package/dist/components/Tooltip/Tooltip.js +294 -0
- package/dist/components/Tooltip/Tooltip.js.map +1 -0
- package/dist/components/Tooltip/Tooltip.module.css +124 -0
- package/dist/foundations/index.css +1 -0
- package/dist/{components/Tabs/Tabs.module.css → foundations/tabs.css} +14 -11
- package/dist/foundations/tokens.css +6 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/docs/README.md +2 -0
- package/docs/feedback.md +3 -0
- package/docs/forms.md +55 -0
- package/docs/overlays.md +2 -2
- package/docs/table.md +137 -0
- package/docs/tabs.md +17 -0
- package/docs/tooltip.md +68 -0
- package/package.json +1 -1
package/docs/forms.md
CHANGED
|
@@ -20,6 +20,24 @@
|
|
|
20
20
|
</Input>
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
### Ошибка через Tooltip
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
<Input>
|
|
27
|
+
<Input.Label>Почта</Input.Label>
|
|
28
|
+
<Input.Control>
|
|
29
|
+
<Input.Field hasError placeholder="name@example.com" />
|
|
30
|
+
<Input.ErrorTooltip content="Некорректный email" />
|
|
31
|
+
</Input.Control>
|
|
32
|
+
</Input>
|
|
33
|
+
|
|
34
|
+
<Input>
|
|
35
|
+
<Input.Label>Телефон</Input.Label>
|
|
36
|
+
<Input.Field hasError placeholder="+7 (___) ___-__-__" />
|
|
37
|
+
<Input.ErrorTooltip target="input" content="Введите номер" placement="right" />
|
|
38
|
+
</Input>
|
|
39
|
+
```
|
|
40
|
+
|
|
23
41
|
## Textarea
|
|
24
42
|
|
|
25
43
|
```tsx
|
|
@@ -88,6 +106,28 @@ const options = [
|
|
|
88
106
|
</Input>
|
|
89
107
|
```
|
|
90
108
|
|
|
109
|
+
`value` и `options.value` могут быть `string` или `number`.
|
|
110
|
+
|
|
111
|
+
Для строгой типизации можно указать тип значения:
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
import type { SelectOption } from '@phpsoftbox/react-softbox';
|
|
115
|
+
|
|
116
|
+
type StatusValue = 10 | 20 | 30;
|
|
117
|
+
|
|
118
|
+
const statusOptions: SelectOption<StatusValue>[] = [
|
|
119
|
+
{ value: 10, label: 'Active' },
|
|
120
|
+
{ value: 20, label: 'Blocked' },
|
|
121
|
+
{ value: 30, label: 'Deleted' },
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
<Input.Select<StatusValue>
|
|
125
|
+
options={statusOptions}
|
|
126
|
+
value={status}
|
|
127
|
+
onChange={(value) => setStatus(value)}
|
|
128
|
+
/>;
|
|
129
|
+
```
|
|
130
|
+
|
|
91
131
|
### Поиск + multiple
|
|
92
132
|
|
|
93
133
|
```tsx
|
|
@@ -97,6 +137,21 @@ const options = [
|
|
|
97
137
|
</Input>
|
|
98
138
|
```
|
|
99
139
|
|
|
140
|
+
### Пустое значение и сброс
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
<Input>
|
|
144
|
+
<Input.Label>Статус</Input.Label>
|
|
145
|
+
<Input.Select
|
|
146
|
+
options={options}
|
|
147
|
+
allowEmptyValue
|
|
148
|
+
emptyOptionLabel="Не выбрано"
|
|
149
|
+
searchable
|
|
150
|
+
clearable
|
|
151
|
+
/>
|
|
152
|
+
</Input>
|
|
153
|
+
```
|
|
154
|
+
|
|
100
155
|
### Загрузка через axios
|
|
101
156
|
|
|
102
157
|
```tsx
|
package/docs/overlays.md
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
## Modal
|
|
4
4
|
|
|
5
5
|
```tsx
|
|
6
|
-
<Modal open={open} title="Заголовок" onClose={() => setOpen(false)}>
|
|
6
|
+
<Modal open={open} title="Заголовок" lockScroll onClose={() => setOpen(false)}>
|
|
7
7
|
Контент модалки
|
|
8
8
|
</Modal>
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Поддерживает `footer` для
|
|
11
|
+
Поддерживает `footer` для действий и `lockScroll` для блокировки скролла страницы (по умолчанию `true`).
|
|
12
12
|
|
|
13
13
|
## Drawer
|
|
14
14
|
|
package/docs/table.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Table
|
|
2
|
+
|
|
3
|
+
`Table` — табличный компонент с декларативными колонками, сортировкой и футером.
|
|
4
|
+
|
|
5
|
+
## Базовый пример
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
const columns = [
|
|
9
|
+
{ id: 'name', header: 'Название', accessor: 'name' },
|
|
10
|
+
{ id: 'status', header: 'Статус', accessor: 'status' },
|
|
11
|
+
{ id: 'amount', header: 'Сумма', accessor: (row) => `${row.amount} ₽`, align: 'right' },
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
<Table columns={columns} data={rows} />;
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Колонки из бэкенда
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
const backendColumns = [
|
|
21
|
+
{ id: 'client', title: 'Клиент', field: 'client', sortable: true },
|
|
22
|
+
{ id: 'project', title: 'Проект', field: 'project' },
|
|
23
|
+
{ id: 'amount', title: 'Сумма', field: 'amount', sortable: true, align: 'right' },
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
<Table columns={backendColumns} data={rows} />;
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`header`, `label`, `title`, `field` используются по цепочке как заголовок. `accessor` может быть ключом или функцией.
|
|
30
|
+
|
|
31
|
+
## Сортировка с обновлением query‑параметров
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
const [sort, setSort] = useState({ key: 'amount', direction: 'asc' });
|
|
35
|
+
|
|
36
|
+
<Table
|
|
37
|
+
columns={[
|
|
38
|
+
{ id: 'client', header: 'Клиент', accessor: 'client', sortable: true },
|
|
39
|
+
{ id: 'amount', header: 'Сумма', accessor: 'amount', sortable: true, align: 'right' },
|
|
40
|
+
]}
|
|
41
|
+
data={rows}
|
|
42
|
+
sort={{
|
|
43
|
+
key: sort.key,
|
|
44
|
+
direction: sort.direction,
|
|
45
|
+
param: 'sort',
|
|
46
|
+
orderParam: 'order',
|
|
47
|
+
onChange: (next, url) => {
|
|
48
|
+
setSort(next);
|
|
49
|
+
window.history.replaceState(null, '', url);
|
|
50
|
+
},
|
|
51
|
+
}}
|
|
52
|
+
/>;
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Футер
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
const columns = [
|
|
59
|
+
{ id: 'name', header: 'Товар', accessor: 'name', footer: 'Итого' },
|
|
60
|
+
{
|
|
61
|
+
id: 'amount',
|
|
62
|
+
header: 'Сумма',
|
|
63
|
+
accessor: 'amount',
|
|
64
|
+
align: 'right',
|
|
65
|
+
footer: (rows) => rows.reduce((sum, row) => sum + row.amount, 0),
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
<Table columns={columns} data={rows} showFooter />;
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Футер только в нужных колонках
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
const columns = [
|
|
76
|
+
{ id: 'a', header: 'A', accessor: 'a' },
|
|
77
|
+
{ id: 'b', header: 'B', accessor: 'b' },
|
|
78
|
+
{ id: 'c', header: 'C', accessor: 'c' },
|
|
79
|
+
{ id: 'd', header: 'D', accessor: 'd', footer: 'Итого' },
|
|
80
|
+
{ id: 'e', header: 'E', accessor: 'e', footer: (rows) => rows.reduce((sum, row) => sum + row.e, 0) },
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
<Table columns={columns} data={rows} showFooter />;
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Выбор строк + renderBulkAction
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
const [selected, setSelected] = useState<React.Key[]>([]);
|
|
90
|
+
|
|
91
|
+
<Table
|
|
92
|
+
columns={columns}
|
|
93
|
+
data={rows}
|
|
94
|
+
selection={{
|
|
95
|
+
selectedIds: selected,
|
|
96
|
+
onToggle: (id) => setSelected((prev) => prev.includes(id) ? prev.filter((key) => key !== id) : [...prev, id]),
|
|
97
|
+
onToggleAll: (ids) => setSelected((prev) => ids.length > 0 && ids.every((id) => prev.includes(id)) ? [] : ids),
|
|
98
|
+
}}
|
|
99
|
+
renderBulkAction={(ids) => (
|
|
100
|
+
<div>
|
|
101
|
+
Выбрано: {ids.length}
|
|
102
|
+
</div>
|
|
103
|
+
)}
|
|
104
|
+
/>;
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Bulk actions
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
<Table
|
|
111
|
+
columns={columns}
|
|
112
|
+
data={rows}
|
|
113
|
+
selection={{
|
|
114
|
+
selectedIds: selected,
|
|
115
|
+
onToggle: (id) => setSelected((prev) => prev.includes(id) ? prev.filter((key) => key !== id) : [...prev, id]),
|
|
116
|
+
}}
|
|
117
|
+
bulkActions={{
|
|
118
|
+
selectedIds: selected,
|
|
119
|
+
actions: [
|
|
120
|
+
{ id: 'remove', label: 'Удалить', onClick: (ids) => console.log(ids) },
|
|
121
|
+
],
|
|
122
|
+
disabled: false,
|
|
123
|
+
placement: 'both',
|
|
124
|
+
}}
|
|
125
|
+
/>;
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
По умолчанию `placement` = `both`.
|
|
129
|
+
|
|
130
|
+
## Полезные поля колонки
|
|
131
|
+
|
|
132
|
+
- `field` / `accessor` / `cell` — источник данных
|
|
133
|
+
- `sortable`, `sortKey` — сортировка для колонки
|
|
134
|
+
- `footer` — значение в футере (node или функция)
|
|
135
|
+
- `hideOn` — скрыть колонку на `sm`/`md`/`lg`
|
|
136
|
+
- `width` / `minWidth` — размеры колонки
|
|
137
|
+
- `align` — `left` | `center` | `right`
|
package/docs/tabs.md
CHANGED
|
@@ -32,3 +32,20 @@ const [activeId, setActiveId] = useState('overview');
|
|
|
32
32
|
|
|
33
33
|
- `badge` — дополнительная метка справа (например, `<Badge variant="info">3</Badge>`).
|
|
34
34
|
- `defaultActiveId` — активная вкладка по умолчанию (uncontrolled).
|
|
35
|
+
|
|
36
|
+
## CSS‑классы для ссылок
|
|
37
|
+
|
|
38
|
+
Можно использовать стили табов для ссылок:
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
<div className="tabs tabs-horizontal">
|
|
42
|
+
<div className="tabs-list">
|
|
43
|
+
<a className="tab tab-active" href="#overview">
|
|
44
|
+
<span className="tab-label">Обзор</span>
|
|
45
|
+
</a>
|
|
46
|
+
<a className="tab" href="#metrics">
|
|
47
|
+
<span className="tab-label">Метрики</span>
|
|
48
|
+
</a>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
```
|
package/docs/tooltip.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Tooltip
|
|
2
|
+
|
|
3
|
+
`Tooltip` — всплывающая подсказка для элементов интерфейса.
|
|
4
|
+
|
|
5
|
+
## Базовый пример
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<Tooltip content="Подсказка">
|
|
9
|
+
<Button>Наведи</Button>
|
|
10
|
+
</Tooltip>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Направление
|
|
14
|
+
|
|
15
|
+
`placement`: `auto` | `top` | `bottom` | `left` | `right`.
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
<Tooltip content="Справа" placement="right">
|
|
19
|
+
<span>Help</span>
|
|
20
|
+
</Tooltip>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Интерактивный контент
|
|
24
|
+
|
|
25
|
+
Если нужно, чтобы подсказка не исчезала при наведении мышью на сам tooltip (например, есть ссылки), включите `interactive`.
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
<Tooltip
|
|
29
|
+
interactive
|
|
30
|
+
content={
|
|
31
|
+
<>
|
|
32
|
+
<Tooltip.Header>Подробности</Tooltip.Header>
|
|
33
|
+
<Tooltip.Body>
|
|
34
|
+
Перейдите в <a href="/docs">документацию</a>.
|
|
35
|
+
</Tooltip.Body>
|
|
36
|
+
<Tooltip.Footer>Последнее обновление: сегодня</Tooltip.Footer>
|
|
37
|
+
</>
|
|
38
|
+
}
|
|
39
|
+
>
|
|
40
|
+
<Button>Подробнее</Button>
|
|
41
|
+
</Tooltip>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Варианты
|
|
45
|
+
|
|
46
|
+
`variant`: `default` | `info` | `success` | `warning` | `danger`.
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
<Tooltip content="Важно" variant="warning">
|
|
50
|
+
<span>!</span>
|
|
51
|
+
</Tooltip>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Header / Body / Footer
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
<Tooltip
|
|
58
|
+
content={
|
|
59
|
+
<>
|
|
60
|
+
<Tooltip.Header>Заголовок</Tooltip.Header>
|
|
61
|
+
<Tooltip.Body>Подробности и описание.</Tooltip.Body>
|
|
62
|
+
<Tooltip.Footer>Доп. инфо</Tooltip.Footer>
|
|
63
|
+
</>
|
|
64
|
+
}
|
|
65
|
+
>
|
|
66
|
+
<Button>Подробнее</Button>
|
|
67
|
+
</Tooltip>
|
|
68
|
+
```
|