prime-ui-kit 0.13.1 → 0.14.0
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 +7 -6
- package/dist/chunks/{chunk-XNOJEX55.js → chunk-P6ZO37JM.js} +1 -1
- package/dist/chunks/{chunk-JV2KB5JZ.js → chunk-SYEX7OVT.js} +3572 -2865
- package/dist/chunks/{chunk-PK2GC77E.js → chunk-WXKRUVSE.js} +164 -140
- package/dist/color-picker.js +2 -2
- package/dist/components/banner/Banner.d.ts +5 -2
- package/dist/components/chart-frame/ChartFrame.d.ts +19 -6
- package/dist/components/chat/Chat.d.ts +2 -2
- package/dist/components/chat/ChatPinned.d.ts +2 -2
- package/dist/components/chat/MessageList.d.ts +1 -1
- package/dist/components/chat/chatContext.d.ts +1 -1
- package/dist/components/field-list/FieldList.d.ts +90 -0
- package/dist/components/index.d.ts +3 -1
- package/dist/components/input/Input.d.ts +2 -2
- package/dist/components/kanban/Kanban.d.ts +6 -3
- package/dist/components/page-content/PageContent.d.ts +55 -4
- package/dist/components/sparkline/Sparkline.d.ts +64 -15
- package/dist/components/sparkline/geometry.d.ts +26 -0
- package/dist/components/tooltip/Tooltip.d.ts +5 -2
- package/dist/hooks/usePosition.d.ts +15 -4
- package/dist/index.css +1 -1
- package/dist/index.js +4 -2
- package/dist/internal/ChartTooltip.d.ts +26 -0
- package/dist/internal/FieldAction.d.ts +6 -7
- package/dist/internal/fieldCell.d.ts +21 -0
- package/dist/internal/messageList.d.ts +2 -2
- package/dist/internal/palette.d.ts +7 -0
- package/dist/skill/SKILL.md +24 -14
- package/dist/skill/anti-slop.md +77 -4
- package/dist/skill/cheatsheet.md +24 -5
- package/dist/skill/checklist.md +19 -1
- package/dist/skill/choosing.md +10 -5
- package/dist/skill/components.md +4 -3
- package/dist/skill/composition.md +28 -15
- package/dist/skill/foundations.md +8 -6
- package/dist/skill/layouts.md +6 -6
- package/dist/skill/patterns/app-shell.module.css +1 -8
- package/dist/skill/patterns/app-shell.tsx +11 -9
- package/dist/skill/patterns/chat.tsx +23 -5
- package/dist/skill/patterns/dashboard.module.css +1 -31
- package/dist/skill/patterns/dashboard.tsx +150 -136
- package/dist/skill/patterns/detail-page.module.css +0 -3
- package/dist/skill/patterns/detail-page.tsx +4 -7
- package/dist/skill/patterns/form-drawer.tsx +2 -2
- package/dist/skill/patterns/kanban-board.tsx +4 -2
- package/dist/skill/patterns/list-page.tsx +2 -2
- package/dist/skill/patterns/media-library.module.css +0 -22
- package/dist/skill/patterns/media-library.tsx +17 -18
- package/dist/skill/patterns/record-editor.module.css +18 -0
- package/dist/skill/patterns/record-editor.tsx +356 -0
- package/dist/skill/patterns/screen-states.module.css +3 -17
- package/dist/skill/patterns/screen-states.tsx +70 -69
- package/dist/skill/patterns/settings-page.module.css +1 -21
- package/dist/skill/patterns/settings-page.tsx +58 -79
- package/dist/skill/reference/components/avatar/COMPONENT.md +4 -4
- package/dist/skill/reference/components/avatar/examples/presence.tsx +1 -1
- package/dist/skill/reference/components/avatar/examples/states.tsx +1 -1
- package/dist/skill/reference/components/banner/COMPONENT.md +6 -6
- package/dist/skill/reference/components/banner/examples/dismissible.tsx +22 -11
- package/dist/skill/reference/components/banner/examples/examples.module.css +3 -3
- package/dist/skill/reference/components/banner/examples/narrow.tsx +1 -1
- package/dist/skill/reference/components/breadcrumb/COMPONENT.md +1 -1
- package/dist/skill/reference/components/breadcrumb/examples/overflow.tsx +1 -1
- package/dist/skill/reference/components/card/COMPONENT.md +5 -4
- package/dist/skill/reference/components/card/examples/examples.module.css +0 -28
- package/dist/skill/reference/components/card/examples/kpi-media.tsx +13 -11
- package/dist/skill/reference/components/card/examples/narrow.tsx +1 -1
- package/dist/skill/reference/components/card/examples/panel-chart.tsx +45 -22
- package/dist/skill/reference/components/chart-frame/COMPONENT.md +10 -7
- package/dist/skill/reference/components/chart-frame/examples/tooltip.tsx +20 -24
- package/dist/skill/reference/components/chat/COMPONENT.md +3 -3
- package/dist/skill/reference/components/chat/examples/search.tsx +1 -1
- package/dist/skill/reference/components/chat-list/COMPONENT.md +1 -1
- package/dist/skill/reference/components/checkbox/examples/indicator.tsx +24 -2
- package/dist/skill/reference/components/color-picker/COMPONENT.md +2 -2
- package/dist/skill/reference/components/color-swatches/COMPONENT.md +1 -0
- package/dist/skill/reference/components/datepicker/COMPONENT.md +1 -0
- package/dist/skill/reference/components/dnd/COMPONENT.md +3 -3
- package/dist/skill/reference/components/field-list/COMPONENT.md +164 -0
- package/dist/skill/reference/components/field-list/examples/base-row.tsx +76 -0
- package/dist/skill/reference/components/field-list/examples/controlled.tsx +72 -0
- package/dist/skill/reference/components/field-list/examples/errors.tsx +85 -0
- package/dist/skill/reference/components/field-list/examples/examples.module.css +34 -0
- package/dist/skill/reference/components/field-list/examples/limits.tsx +55 -0
- package/dist/skill/reference/components/field-list/examples/locked.tsx +139 -0
- package/dist/skill/reference/components/field-list/examples/narrow.tsx +68 -0
- package/dist/skill/reference/components/field-list/examples/overview.tsx +66 -0
- package/dist/skill/reference/components/field-list/examples/reorder.tsx +42 -0
- package/dist/skill/reference/components/field-list/examples/sizes.tsx +42 -0
- package/dist/skill/reference/components/field-list/examples/states.tsx +51 -0
- package/dist/skill/reference/components/input/examples/examples.module.css +2 -7
- package/dist/skill/reference/components/kanban/COMPONENT.md +13 -9
- package/dist/skill/reference/components/kanban/examples/limits.tsx +2 -1
- package/dist/skill/reference/components/kanban/examples/variants.tsx +16 -8
- package/dist/skill/reference/components/list/COMPONENT.md +1 -1
- package/dist/skill/reference/components/media-viewer/COMPONENT.md +2 -2
- package/dist/skill/reference/components/message/COMPONENT.md +2 -2
- package/dist/skill/reference/components/notification/COMPONENT.md +1 -0
- package/dist/skill/reference/components/page-content/COMPONENT.md +70 -14
- package/dist/skill/reference/components/page-content/examples/grid.tsx +107 -0
- package/dist/skill/reference/components/page-content/examples/overview.tsx +2 -2
- package/dist/skill/reference/components/page-content/examples/sections.tsx +81 -0
- package/dist/skill/reference/components/page-toolbar/COMPONENT.md +1 -1
- package/dist/skill/reference/components/segmented-control/COMPONENT.md +1 -0
- package/dist/skill/reference/components/select/COMPONENT.md +4 -2
- package/dist/skill/reference/components/select/examples/icon-only.tsx +38 -0
- package/dist/skill/reference/components/sparkline/COMPONENT.md +83 -30
- package/dist/skill/reference/components/sparkline/examples/compact.tsx +1 -1
- package/dist/skill/reference/components/sparkline/examples/curve.tsx +28 -0
- package/dist/skill/reference/components/sparkline/examples/gaps.tsx +33 -0
- package/dist/skill/reference/components/sparkline/examples/overview.tsx +11 -2
- package/dist/skill/reference/components/sparkline/examples/period.tsx +7 -2
- package/dist/skill/reference/components/sparkline/examples/reference.tsx +37 -0
- package/dist/skill/reference/components/sparkline/examples/variants.tsx +2 -2
- package/dist/skill/reference/components/tabs/examples/examples.module.css +0 -6
- package/dist/skill/reference/components/tabs/examples/in-drawer.tsx +11 -13
- package/dist/skill/reference/components/timeline/examples/examples.module.css +0 -8
- package/dist/skill/reference/components/timeline/examples/narrow.tsx +2 -2
- package/dist/skill/reference/components/timeline/examples/sizes.tsx +3 -3
- package/dist/skill/reference/components/timeline/examples/variants.tsx +4 -4
- package/dist/skill/reference/components/tooltip/COMPONENT.md +6 -4
- package/dist/skill/reference/components/tooltip/examples/placement.tsx +2 -1
- package/dist/skill/reference/components/video-note/COMPONENT.md +1 -1
- package/dist/skill/reference/components/voice-player/COMPONENT.md +1 -1
- package/dist/skill/reference/layout/app-header/examples/in-app-shell.tsx +2 -2
- package/dist/skill/reference/layout/app-shell/COMPONENT.md +1 -1
- package/dist/skill/reference/layout/app-shell/examples/footer.tsx +2 -2
- package/dist/skill/reference/layout/app-shell/examples/overview.tsx +2 -2
- package/dist/skill/reference/layout/app-shell/examples/template.tsx +2 -2
- package/dist/skill/reference/layout/bottom-nav/examples/floating-action.tsx +2 -2
- package/dist/skill/reference/layout/bottom-nav/examples/floating.tsx +2 -2
- package/dist/skill/reference/layout/bottom-nav/examples/in-app-shell.tsx +2 -2
- package/dist/skill/responsive.md +5 -3
- package/dist/skill/ux.md +145 -0
- package/dist/tokens/semantic.d.ts +2 -0
- package/package.json +1 -1
- package/src/components/avatar/COMPONENT.md +4 -4
- package/src/components/avatar/examples/presence.tsx +1 -1
- package/src/components/avatar/examples/states.tsx +1 -1
- package/src/components/banner/COMPONENT.md +6 -6
- package/src/components/banner/examples/dismissible.tsx +22 -11
- package/src/components/banner/examples/examples.module.css +3 -3
- package/src/components/banner/examples/narrow.tsx +1 -1
- package/src/components/breadcrumb/COMPONENT.md +1 -1
- package/src/components/breadcrumb/examples/overflow.tsx +1 -1
- package/src/components/card/COMPONENT.md +5 -4
- package/src/components/card/examples/examples.module.css +0 -28
- package/src/components/card/examples/kpi-media.tsx +13 -11
- package/src/components/card/examples/narrow.tsx +1 -1
- package/src/components/card/examples/panel-chart.tsx +45 -22
- package/src/components/chart-frame/COMPONENT.md +10 -7
- package/src/components/chart-frame/examples/tooltip.tsx +20 -24
- package/src/components/chat/COMPONENT.md +3 -3
- package/src/components/chat/examples/search.tsx +1 -1
- package/src/components/chat-list/COMPONENT.md +1 -1
- package/src/components/checkbox/examples/indicator.tsx +24 -2
- package/src/components/color-picker/COMPONENT.md +2 -2
- package/src/components/color-swatches/COMPONENT.md +1 -0
- package/src/components/datepicker/COMPONENT.md +1 -0
- package/src/components/dnd/COMPONENT.md +3 -3
- package/src/components/field-list/COMPONENT.md +164 -0
- package/src/components/field-list/examples/base-row.tsx +76 -0
- package/src/components/field-list/examples/controlled.tsx +72 -0
- package/src/components/field-list/examples/errors.tsx +85 -0
- package/src/components/field-list/examples/examples.module.css +34 -0
- package/src/components/field-list/examples/limits.tsx +55 -0
- package/src/components/field-list/examples/locked.tsx +139 -0
- package/src/components/field-list/examples/narrow.tsx +68 -0
- package/src/components/field-list/examples/overview.tsx +66 -0
- package/src/components/field-list/examples/reorder.tsx +42 -0
- package/src/components/field-list/examples/sizes.tsx +42 -0
- package/src/components/field-list/examples/states.tsx +51 -0
- package/src/components/input/examples/examples.module.css +2 -7
- package/src/components/kanban/COMPONENT.md +13 -9
- package/src/components/kanban/examples/limits.tsx +2 -1
- package/src/components/kanban/examples/variants.tsx +16 -8
- package/src/components/list/COMPONENT.md +1 -1
- package/src/components/media-viewer/COMPONENT.md +2 -2
- package/src/components/message/COMPONENT.md +2 -2
- package/src/components/notification/COMPONENT.md +1 -0
- package/src/components/page-content/COMPONENT.md +70 -14
- package/src/components/page-content/examples/grid.tsx +107 -0
- package/src/components/page-content/examples/overview.tsx +2 -2
- package/src/components/page-content/examples/sections.tsx +81 -0
- package/src/components/page-toolbar/COMPONENT.md +1 -1
- package/src/components/segmented-control/COMPONENT.md +1 -0
- package/src/components/select/COMPONENT.md +4 -2
- package/src/components/select/examples/icon-only.tsx +38 -0
- package/src/components/sparkline/COMPONENT.md +83 -30
- package/src/components/sparkline/examples/compact.tsx +1 -1
- package/src/components/sparkline/examples/curve.tsx +28 -0
- package/src/components/sparkline/examples/gaps.tsx +33 -0
- package/src/components/sparkline/examples/overview.tsx +11 -2
- package/src/components/sparkline/examples/period.tsx +7 -2
- package/src/components/sparkline/examples/reference.tsx +37 -0
- package/src/components/sparkline/examples/variants.tsx +2 -2
- package/src/components/tabs/examples/examples.module.css +0 -6
- package/src/components/tabs/examples/in-drawer.tsx +11 -13
- package/src/components/timeline/examples/examples.module.css +0 -8
- package/src/components/timeline/examples/narrow.tsx +2 -2
- package/src/components/timeline/examples/sizes.tsx +3 -3
- package/src/components/timeline/examples/variants.tsx +4 -4
- package/src/components/tooltip/COMPONENT.md +6 -4
- package/src/components/tooltip/examples/placement.tsx +2 -1
- package/src/components/video-note/COMPONENT.md +1 -1
- package/src/components/voice-player/COMPONENT.md +1 -1
- package/src/layout/app-header/examples/in-app-shell.tsx +2 -2
- package/src/layout/app-shell/COMPONENT.md +1 -1
- package/src/layout/app-shell/examples/footer.tsx +2 -2
- package/src/layout/app-shell/examples/overview.tsx +2 -2
- package/src/layout/app-shell/examples/template.tsx +2 -2
- package/src/layout/bottom-nav/examples/floating-action.tsx +2 -2
- package/src/layout/bottom-nav/examples/floating.tsx +2 -2
- package/src/layout/bottom-nav/examples/in-app-shell.tsx +2 -2
- package/src/styles/theme-light.css +1 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** The parent owns the lines: it sums them under the list and puts the saved lines back on reset — `value`, `onValueChange`. */
|
|
2
|
+
import { Button, FieldList, type FieldListColumn, Input, Typography } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import styles from "./examples.module.css";
|
|
6
|
+
|
|
7
|
+
type Line = { id: string; service: string; amount: string };
|
|
8
|
+
|
|
9
|
+
const COLUMNS: FieldListColumn[] = [{ label: "Услуга" }, { label: "Сумма", width: "m" }];
|
|
10
|
+
|
|
11
|
+
const SAVED: Line[] = [
|
|
12
|
+
{ id: "license", service: "Лицензия на 12 месяцев", amount: "96 000" },
|
|
13
|
+
{ id: "migration", service: "Перенос данных", amount: "24 000" },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const RUB = new Intl.NumberFormat("ru-RU", {
|
|
17
|
+
style: "currency",
|
|
18
|
+
currency: "RUB",
|
|
19
|
+
maximumFractionDigits: 0,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
function totalOf(lines: Line[]) {
|
|
23
|
+
return lines.reduce((sum, line) => sum + (Number(line.amount.replace(/\s/g, "")) || 0), 0);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default function FieldListControlledExample() {
|
|
27
|
+
const [lines, setLines] = React.useState(SAVED);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div className={styles.stack}>
|
|
31
|
+
<FieldList
|
|
32
|
+
label="Состав сделки"
|
|
33
|
+
columns={COLUMNS}
|
|
34
|
+
value={lines}
|
|
35
|
+
onValueChange={setLines}
|
|
36
|
+
getId={(line) => line.id}
|
|
37
|
+
getLabel={(line) => line.service}
|
|
38
|
+
createItem={() => ({ id: crypto.randomUUID(), service: "", amount: "" })}
|
|
39
|
+
addLabel="Добавить услугу"
|
|
40
|
+
renderItem={(line, row) => (
|
|
41
|
+
<>
|
|
42
|
+
<Input.Root>
|
|
43
|
+
<Input.Wrapper>
|
|
44
|
+
<Input.Field
|
|
45
|
+
value={line.service}
|
|
46
|
+
onChange={(event) => row.update({ service: event.target.value })}
|
|
47
|
+
/>
|
|
48
|
+
</Input.Wrapper>
|
|
49
|
+
</Input.Root>
|
|
50
|
+
<Input.Root>
|
|
51
|
+
<Input.Wrapper>
|
|
52
|
+
<Input.Field
|
|
53
|
+
value={line.amount}
|
|
54
|
+
inputMode="decimal"
|
|
55
|
+
placeholder="0"
|
|
56
|
+
onChange={(event) => row.update({ amount: event.target.value })}
|
|
57
|
+
/>
|
|
58
|
+
<Input.InlineAffix side="end">₽</Input.InlineAffix>
|
|
59
|
+
</Input.Wrapper>
|
|
60
|
+
</Input.Root>
|
|
61
|
+
</>
|
|
62
|
+
)}
|
|
63
|
+
/>
|
|
64
|
+
<div className={styles.summary}>
|
|
65
|
+
<Typography variant="title-m">Итого {RUB.format(totalOf(lines))}</Typography>
|
|
66
|
+
<Button.Root variant="ghost" tone="neutral" onClick={() => setLines(SAVED)}>
|
|
67
|
+
Вернуть сохранённое
|
|
68
|
+
</Button.Root>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/** Contacts of a client checked on save: a field's problem shows under that field in its row, a problem of the whole list under the list, and focus goes to the first wrong field — `error`. */
|
|
2
|
+
import { Button, FieldList, type FieldListColumn, Input } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import styles from "./examples.module.css";
|
|
6
|
+
|
|
7
|
+
type Contact = { id: string; role: string; phone: string };
|
|
8
|
+
|
|
9
|
+
const COLUMNS: FieldListColumn[] = [{ label: "Должность" }, { label: "Телефон", width: "m" }];
|
|
10
|
+
|
|
11
|
+
const CONTACTS: Contact[] = [
|
|
12
|
+
{ id: "buyer", role: "Закупщик", phone: "+7 912 404-18-20" },
|
|
13
|
+
{ id: "lawyer", role: "Юрист", phone: "+7 912 40" },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const PHONE = /^\+7 \d{3} \d{3}-\d{2}-\d{2}$/;
|
|
17
|
+
|
|
18
|
+
function phoneError(phone: string) {
|
|
19
|
+
if (phone.trim() === "") return "Укажите телефон";
|
|
20
|
+
return PHONE.test(phone) ? undefined : "Формат: +7 912 404-18-20";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default function FieldListErrorsExample() {
|
|
24
|
+
const [contacts, setContacts] = React.useState(CONTACTS);
|
|
25
|
+
// Every save attempt validates the form; after it renders, focus goes to the first wrong field.
|
|
26
|
+
const [attempts, setAttempts] = React.useState(0);
|
|
27
|
+
const formRef = React.useRef<HTMLFormElement>(null);
|
|
28
|
+
const checked = attempts > 0;
|
|
29
|
+
React.useEffect(() => {
|
|
30
|
+
if (attempts === 0) return;
|
|
31
|
+
formRef.current?.querySelector<HTMLElement>("[aria-invalid='true']")?.focus();
|
|
32
|
+
}, [attempts]);
|
|
33
|
+
const listError = checked && contacts.length === 0 ? "Добавьте хотя бы один контакт" : undefined;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<form
|
|
37
|
+
ref={formRef}
|
|
38
|
+
noValidate
|
|
39
|
+
className={styles.form}
|
|
40
|
+
onSubmit={(event) => {
|
|
41
|
+
event.preventDefault();
|
|
42
|
+
setAttempts((count) => count + 1);
|
|
43
|
+
}}
|
|
44
|
+
>
|
|
45
|
+
<FieldList
|
|
46
|
+
label="Контакты клиента"
|
|
47
|
+
error={listError}
|
|
48
|
+
columns={COLUMNS}
|
|
49
|
+
value={contacts}
|
|
50
|
+
onValueChange={setContacts}
|
|
51
|
+
getId={(contact) => contact.id}
|
|
52
|
+
getLabel={(contact) => contact.role}
|
|
53
|
+
createItem={() => ({ id: crypto.randomUUID(), role: "", phone: "" })}
|
|
54
|
+
addLabel="Добавить контакт"
|
|
55
|
+
renderItem={(contact, row) => (
|
|
56
|
+
<>
|
|
57
|
+
<Input.Root
|
|
58
|
+
error={checked && contact.role.trim() === "" ? "Укажите должность" : undefined}
|
|
59
|
+
>
|
|
60
|
+
<Input.Wrapper>
|
|
61
|
+
<Input.Field
|
|
62
|
+
value={contact.role}
|
|
63
|
+
onChange={(event) => row.update({ role: event.target.value })}
|
|
64
|
+
/>
|
|
65
|
+
</Input.Wrapper>
|
|
66
|
+
</Input.Root>
|
|
67
|
+
<Input.Root error={checked ? phoneError(contact.phone) : undefined}>
|
|
68
|
+
<Input.Wrapper>
|
|
69
|
+
<Input.Field
|
|
70
|
+
type="tel"
|
|
71
|
+
value={contact.phone}
|
|
72
|
+
placeholder="+7 912 404-18-20"
|
|
73
|
+
onChange={(event) => row.update({ phone: event.target.value })}
|
|
74
|
+
/>
|
|
75
|
+
</Input.Wrapper>
|
|
76
|
+
</Input.Root>
|
|
77
|
+
</>
|
|
78
|
+
)}
|
|
79
|
+
/>
|
|
80
|
+
<Button.Root type="submit" className={styles.submit}>
|
|
81
|
+
Сохранить контакты
|
|
82
|
+
</Button.Root>
|
|
83
|
+
</form>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* Layout of the FieldList scenarios: semantic tokens only. */
|
|
2
|
+
|
|
3
|
+
/* A form: the list, then its submit button at the start, a group apart. */
|
|
4
|
+
.form {
|
|
5
|
+
display: grid;
|
|
6
|
+
gap: var(--prime-space-8);
|
|
7
|
+
width: 100%;
|
|
8
|
+
min-width: 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.submit {
|
|
12
|
+
justify-self: start;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* A 320 px column: the rows stack into blocks and every field shows its label. */
|
|
16
|
+
.narrow {
|
|
17
|
+
inline-size: min(100%, calc(var(--prime-space-20) * 4));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* The total of the lines and the reset beside it. */
|
|
21
|
+
.summary {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-wrap: wrap;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: space-between;
|
|
26
|
+
gap: var(--prime-space-3);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.stack {
|
|
30
|
+
display: grid;
|
|
31
|
+
gap: var(--prime-space-6);
|
|
32
|
+
width: 100%;
|
|
33
|
+
min-width: 0;
|
|
34
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** Recipients of invoice reminders, from one to three: the last row cannot be removed and the add button says why it is off once the list is full — `min`, `max`, `hint`. */
|
|
2
|
+
import { FieldList, type FieldListColumn, Input } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
type Recipient = { id: string; name: string; email: string };
|
|
6
|
+
|
|
7
|
+
const COLUMNS: FieldListColumn[] = [{ label: "Имя" }, { label: "Почта" }];
|
|
8
|
+
|
|
9
|
+
const RECIPIENTS: Recipient[] = [
|
|
10
|
+
{ id: "accounting", name: "Бухгалтерия", email: "buh@severstroy.ru" },
|
|
11
|
+
{ id: "director", name: "Ирина Котова", email: "kotova@severstroy.ru" },
|
|
12
|
+
{ id: "manager", name: "Олег Демин", email: "demin@severstroy.ru" },
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
export default function FieldListLimitsExample() {
|
|
16
|
+
const [recipients, setRecipients] = React.useState(RECIPIENTS);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<FieldList
|
|
20
|
+
label="Кому напоминать об оплате"
|
|
21
|
+
hint="Письмо уходит за три дня до срока."
|
|
22
|
+
columns={COLUMNS}
|
|
23
|
+
min={1}
|
|
24
|
+
max={3}
|
|
25
|
+
value={recipients}
|
|
26
|
+
onValueChange={setRecipients}
|
|
27
|
+
getId={(recipient) => recipient.id}
|
|
28
|
+
getLabel={(recipient) => recipient.name}
|
|
29
|
+
createItem={() => ({ id: crypto.randomUUID(), name: "", email: "" })}
|
|
30
|
+
addLabel="Добавить получателя"
|
|
31
|
+
renderItem={(recipient, row) => (
|
|
32
|
+
<>
|
|
33
|
+
<Input.Root>
|
|
34
|
+
<Input.Wrapper>
|
|
35
|
+
<Input.Field
|
|
36
|
+
value={recipient.name}
|
|
37
|
+
onChange={(event) => row.update({ name: event.target.value })}
|
|
38
|
+
/>
|
|
39
|
+
</Input.Wrapper>
|
|
40
|
+
</Input.Root>
|
|
41
|
+
<Input.Root>
|
|
42
|
+
<Input.Wrapper>
|
|
43
|
+
<Input.Field
|
|
44
|
+
type="email"
|
|
45
|
+
value={recipient.email}
|
|
46
|
+
placeholder="name@company.ru"
|
|
47
|
+
onChange={(event) => row.update({ email: event.target.value })}
|
|
48
|
+
/>
|
|
49
|
+
</Input.Wrapper>
|
|
50
|
+
</Input.Root>
|
|
51
|
+
</>
|
|
52
|
+
)}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/** Specs of a plan on one line each: an icon picker and a color swatch take compact columns, the first three specs are pinned with a lock and the rest reorder below them — `getLocked`, `width`, `reorderable`. */
|
|
2
|
+
import {
|
|
3
|
+
ColorPresets,
|
|
4
|
+
FieldList,
|
|
5
|
+
type FieldListColumn,
|
|
6
|
+
Icon,
|
|
7
|
+
type IconName,
|
|
8
|
+
Input,
|
|
9
|
+
Select,
|
|
10
|
+
} from "prime-ui-kit";
|
|
11
|
+
import * as React from "react";
|
|
12
|
+
|
|
13
|
+
type Spec = {
|
|
14
|
+
id: string;
|
|
15
|
+
icon: IconName;
|
|
16
|
+
name: string;
|
|
17
|
+
value: string;
|
|
18
|
+
color: string;
|
|
19
|
+
pinned?: boolean;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const COLUMNS: FieldListColumn[] = [
|
|
23
|
+
{ label: "Иконка", width: "compact" },
|
|
24
|
+
{ label: "Параметр" },
|
|
25
|
+
{ label: "Значение" },
|
|
26
|
+
{ label: "Цвет", width: "compact" },
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const ICONS: { name: IconName; label: string }[] = [
|
|
30
|
+
{ name: "object.users", label: "Пользователи" },
|
|
31
|
+
{ name: "object.storage", label: "Хранилище" },
|
|
32
|
+
{ name: "object.headset", label: "Поддержка" },
|
|
33
|
+
{ name: "object.chart", label: "Отчёты" },
|
|
34
|
+
{ name: "object.key", label: "Доступ" },
|
|
35
|
+
{ name: "object.globe", label: "Интеграции" },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const SPECS: Spec[] = [
|
|
39
|
+
{
|
|
40
|
+
id: "seats",
|
|
41
|
+
icon: "object.users",
|
|
42
|
+
name: "Сотрудники",
|
|
43
|
+
value: "до 50",
|
|
44
|
+
color: "#5068f5",
|
|
45
|
+
pinned: true,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: "storage",
|
|
49
|
+
icon: "object.storage",
|
|
50
|
+
name: "Хранилище",
|
|
51
|
+
value: "200 ГБ",
|
|
52
|
+
color: "#22c55e",
|
|
53
|
+
pinned: true,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "support",
|
|
57
|
+
icon: "object.headset",
|
|
58
|
+
name: "Поддержка",
|
|
59
|
+
value: "8/5",
|
|
60
|
+
color: "#f97316",
|
|
61
|
+
pinned: true,
|
|
62
|
+
},
|
|
63
|
+
{ id: "reports", icon: "object.chart", name: "Отчёты", value: "12 шаблонов", color: "#a855f7" },
|
|
64
|
+
{ id: "sso", icon: "object.key", name: "Вход через SSO", value: "SAML, OIDC", color: "#14b8a6" },
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
export default function FieldListLockedExample() {
|
|
68
|
+
const [specs, setSpecs] = React.useState(SPECS);
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<FieldList
|
|
72
|
+
label="Характеристики тарифа"
|
|
73
|
+
columns={COLUMNS}
|
|
74
|
+
reorderable
|
|
75
|
+
value={specs}
|
|
76
|
+
onValueChange={setSpecs}
|
|
77
|
+
getId={(spec) => spec.id}
|
|
78
|
+
getLabel={(spec) => spec.name}
|
|
79
|
+
getLocked={(spec) => spec.pinned ?? false}
|
|
80
|
+
createItem={(): Spec => ({
|
|
81
|
+
id: crypto.randomUUID(),
|
|
82
|
+
icon: "object.globe",
|
|
83
|
+
name: "",
|
|
84
|
+
value: "",
|
|
85
|
+
color: "#14b8a6",
|
|
86
|
+
})}
|
|
87
|
+
addLabel="Добавить характеристику"
|
|
88
|
+
renderItem={(spec, row) => (
|
|
89
|
+
<>
|
|
90
|
+
<Select.Root
|
|
91
|
+
value={spec.icon}
|
|
92
|
+
onValueChange={(icon) => row.update({ icon: icon as IconName })}
|
|
93
|
+
>
|
|
94
|
+
<Select.Trigger>
|
|
95
|
+
<Select.TriggerIcon>
|
|
96
|
+
<Icon name={spec.icon} />
|
|
97
|
+
</Select.TriggerIcon>
|
|
98
|
+
</Select.Trigger>
|
|
99
|
+
<Select.Content>
|
|
100
|
+
{ICONS.map((icon) => (
|
|
101
|
+
<Select.Item key={icon.name} value={icon.name}>
|
|
102
|
+
<Select.ItemIcon>
|
|
103
|
+
<Icon name={icon.name} />
|
|
104
|
+
</Select.ItemIcon>
|
|
105
|
+
{icon.label}
|
|
106
|
+
</Select.Item>
|
|
107
|
+
))}
|
|
108
|
+
</Select.Content>
|
|
109
|
+
</Select.Root>
|
|
110
|
+
<Input.Root>
|
|
111
|
+
<Input.Wrapper>
|
|
112
|
+
<Input.Field
|
|
113
|
+
value={spec.name}
|
|
114
|
+
onChange={(event) => row.update({ name: event.target.value })}
|
|
115
|
+
/>
|
|
116
|
+
</Input.Wrapper>
|
|
117
|
+
</Input.Root>
|
|
118
|
+
<Input.Root>
|
|
119
|
+
<Input.Wrapper>
|
|
120
|
+
<Input.Field
|
|
121
|
+
value={spec.value}
|
|
122
|
+
onChange={(event) => row.update({ value: event.target.value })}
|
|
123
|
+
/>
|
|
124
|
+
</Input.Wrapper>
|
|
125
|
+
</Input.Root>
|
|
126
|
+
<ColorPresets.Root
|
|
127
|
+
value={spec.color}
|
|
128
|
+
onValueChange={(color) => row.update({ color: color ?? spec.color })}
|
|
129
|
+
>
|
|
130
|
+
<ColorPresets.Trigger>
|
|
131
|
+
<ColorPresets.SwatchButton />
|
|
132
|
+
</ColorPresets.Trigger>
|
|
133
|
+
<ColorPresets.Content />
|
|
134
|
+
</ColorPresets.Root>
|
|
135
|
+
</>
|
|
136
|
+
)}
|
|
137
|
+
/>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/** The invoice lines in a 320 px column: the headings give way, each row stacks its fields with their own labels and rows stand a group apart — `columns`. */
|
|
2
|
+
import { FieldList, type FieldListColumn, Input } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import styles from "./examples.module.css";
|
|
6
|
+
|
|
7
|
+
type Line = { id: string; service: string; quantity: string; price: string };
|
|
8
|
+
|
|
9
|
+
const COLUMNS: FieldListColumn[] = [
|
|
10
|
+
{ label: "Услуга" },
|
|
11
|
+
{ label: "Кол-во", width: "s" },
|
|
12
|
+
{ label: "Цена", width: "m" },
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
const LINES: Line[] = [
|
|
16
|
+
{ id: "setup", service: "Внедрение CRM", quantity: "1", price: "180 000" },
|
|
17
|
+
{ id: "training", service: "Обучение менеджеров", quantity: "3", price: "15 000" },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
export default function FieldListNarrowExample() {
|
|
21
|
+
const [lines, setLines] = React.useState(LINES);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<div className={styles.narrow}>
|
|
25
|
+
<FieldList
|
|
26
|
+
label="Позиции счёта"
|
|
27
|
+
columns={COLUMNS}
|
|
28
|
+
value={lines}
|
|
29
|
+
onValueChange={setLines}
|
|
30
|
+
getId={(line) => line.id}
|
|
31
|
+
getLabel={(line) => line.service}
|
|
32
|
+
createItem={() => ({ id: crypto.randomUUID(), service: "", quantity: "1", price: "" })}
|
|
33
|
+
addLabel="Добавить позицию"
|
|
34
|
+
renderItem={(line, row) => (
|
|
35
|
+
<>
|
|
36
|
+
<Input.Root>
|
|
37
|
+
<Input.Wrapper>
|
|
38
|
+
<Input.Field
|
|
39
|
+
value={line.service}
|
|
40
|
+
onChange={(event) => row.update({ service: event.target.value })}
|
|
41
|
+
/>
|
|
42
|
+
</Input.Wrapper>
|
|
43
|
+
</Input.Root>
|
|
44
|
+
<Input.Root>
|
|
45
|
+
<Input.Wrapper>
|
|
46
|
+
<Input.Field
|
|
47
|
+
value={line.quantity}
|
|
48
|
+
inputMode="numeric"
|
|
49
|
+
onChange={(event) => row.update({ quantity: event.target.value })}
|
|
50
|
+
/>
|
|
51
|
+
</Input.Wrapper>
|
|
52
|
+
</Input.Root>
|
|
53
|
+
<Input.Root>
|
|
54
|
+
<Input.Wrapper>
|
|
55
|
+
<Input.Field
|
|
56
|
+
value={line.price}
|
|
57
|
+
inputMode="decimal"
|
|
58
|
+
onChange={(event) => row.update({ price: event.target.value })}
|
|
59
|
+
/>
|
|
60
|
+
<Input.InlineAffix side="end">₽</Input.InlineAffix>
|
|
61
|
+
</Input.Wrapper>
|
|
62
|
+
</Input.Root>
|
|
63
|
+
</>
|
|
64
|
+
)}
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** Lines of an invoice: the column headings stand once above the rows, each row has a remove button and the add button sits under them — `columns`, `renderItem`, `createItem`, `addLabel`. */
|
|
2
|
+
import { FieldList, type FieldListColumn, Input } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
type Line = { id: string; service: string; quantity: string; price: string };
|
|
6
|
+
|
|
7
|
+
const COLUMNS: FieldListColumn[] = [
|
|
8
|
+
{ label: "Услуга" },
|
|
9
|
+
{ label: "Кол-во", width: "s" },
|
|
10
|
+
{ label: "Цена", width: "m" },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const LINES: Line[] = [
|
|
14
|
+
{ id: "setup", service: "Внедрение CRM", quantity: "1", price: "180 000" },
|
|
15
|
+
{ id: "training", service: "Обучение менеджеров", quantity: "3", price: "15 000" },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
export default function FieldListOverviewExample() {
|
|
19
|
+
const [lines, setLines] = React.useState(LINES);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<FieldList
|
|
23
|
+
label="Позиции счёта"
|
|
24
|
+
columns={COLUMNS}
|
|
25
|
+
value={lines}
|
|
26
|
+
onValueChange={setLines}
|
|
27
|
+
getId={(line) => line.id}
|
|
28
|
+
getLabel={(line) => line.service}
|
|
29
|
+
createItem={() => ({ id: crypto.randomUUID(), service: "", quantity: "1", price: "" })}
|
|
30
|
+
addLabel="Добавить позицию"
|
|
31
|
+
renderItem={(line, row) => (
|
|
32
|
+
<>
|
|
33
|
+
<Input.Root>
|
|
34
|
+
<Input.Wrapper>
|
|
35
|
+
<Input.Field
|
|
36
|
+
value={line.service}
|
|
37
|
+
placeholder="Поддержка, 1 месяц"
|
|
38
|
+
onChange={(event) => row.update({ service: event.target.value })}
|
|
39
|
+
/>
|
|
40
|
+
</Input.Wrapper>
|
|
41
|
+
</Input.Root>
|
|
42
|
+
<Input.Root>
|
|
43
|
+
<Input.Wrapper>
|
|
44
|
+
<Input.Field
|
|
45
|
+
value={line.quantity}
|
|
46
|
+
inputMode="numeric"
|
|
47
|
+
onChange={(event) => row.update({ quantity: event.target.value })}
|
|
48
|
+
/>
|
|
49
|
+
</Input.Wrapper>
|
|
50
|
+
</Input.Root>
|
|
51
|
+
<Input.Root>
|
|
52
|
+
<Input.Wrapper>
|
|
53
|
+
<Input.Field
|
|
54
|
+
value={line.price}
|
|
55
|
+
inputMode="decimal"
|
|
56
|
+
placeholder="0"
|
|
57
|
+
onChange={(event) => row.update({ price: event.target.value })}
|
|
58
|
+
/>
|
|
59
|
+
<Input.InlineAffix side="end">₽</Input.InlineAffix>
|
|
60
|
+
</Input.Wrapper>
|
|
61
|
+
</Input.Root>
|
|
62
|
+
</>
|
|
63
|
+
)}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Selling points of a plan in the order of the pricing page: a one-column list has no headings and no numbers, a point moves by its handle or Alt+arrows — `reorderable`, `getLabel`. */
|
|
2
|
+
import { FieldList, type FieldListColumn, Input } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
type Point = { id: string; text: string };
|
|
6
|
+
|
|
7
|
+
const COLUMNS: FieldListColumn[] = [{ label: "Преимущество" }];
|
|
8
|
+
|
|
9
|
+
const POINTS: Point[] = [
|
|
10
|
+
{ id: "users", text: "До 50 сотрудников в одном пространстве" },
|
|
11
|
+
{ id: "storage", text: "200 ГБ для документов и вложений" },
|
|
12
|
+
{ id: "support", text: "Поддержка в рабочие часы, ответ за 2 часа" },
|
|
13
|
+
{ id: "api", text: "Доступ к API и вебхукам" },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export default function FieldListReorderExample() {
|
|
17
|
+
const [points, setPoints] = React.useState(POINTS);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<FieldList
|
|
21
|
+
label="Преимущества тарифа"
|
|
22
|
+
columns={COLUMNS}
|
|
23
|
+
reorderable
|
|
24
|
+
value={points}
|
|
25
|
+
onValueChange={setPoints}
|
|
26
|
+
getId={(point) => point.id}
|
|
27
|
+
getLabel={(point) => point.text}
|
|
28
|
+
createItem={() => ({ id: crypto.randomUUID(), text: "" })}
|
|
29
|
+
addLabel="Добавить преимущество"
|
|
30
|
+
renderItem={(point, row) => (
|
|
31
|
+
<Input.Root>
|
|
32
|
+
<Input.Wrapper>
|
|
33
|
+
<Input.Field
|
|
34
|
+
value={point.text}
|
|
35
|
+
onChange={(event) => row.update({ text: event.target.value })}
|
|
36
|
+
/>
|
|
37
|
+
</Input.Wrapper>
|
|
38
|
+
</Input.Root>
|
|
39
|
+
)}
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Every tier: the headings, the fields, the handle and the buttons follow the list's size — `size`. */
|
|
2
|
+
import { FieldList, type FieldListColumn, Input } from "prime-ui-kit";
|
|
3
|
+
|
|
4
|
+
type Contact = { id: string; name: string; phone: string };
|
|
5
|
+
|
|
6
|
+
const SIZES = ["xs", "s", "m", "l", "xl"] as const;
|
|
7
|
+
|
|
8
|
+
const COLUMNS: FieldListColumn[] = [{ label: "Контакт" }, { label: "Телефон", width: "m" }];
|
|
9
|
+
|
|
10
|
+
const CONTACTS: Contact[] = [{ id: "buyer", name: "Анна Лебедева", phone: "+7 912 404-18-20" }];
|
|
11
|
+
|
|
12
|
+
export default function FieldListSizesExample() {
|
|
13
|
+
return (
|
|
14
|
+
<>
|
|
15
|
+
{SIZES.map((size) => (
|
|
16
|
+
<FieldList
|
|
17
|
+
key={size}
|
|
18
|
+
size={size}
|
|
19
|
+
label={size}
|
|
20
|
+
columns={COLUMNS}
|
|
21
|
+
defaultValue={CONTACTS}
|
|
22
|
+
getId={(contact) => contact.id}
|
|
23
|
+
getLabel={(contact) => contact.name}
|
|
24
|
+
renderItem={(contact) => (
|
|
25
|
+
<>
|
|
26
|
+
<Input.Root>
|
|
27
|
+
<Input.Wrapper>
|
|
28
|
+
<Input.Field defaultValue={contact.name} />
|
|
29
|
+
</Input.Wrapper>
|
|
30
|
+
</Input.Root>
|
|
31
|
+
<Input.Root>
|
|
32
|
+
<Input.Wrapper>
|
|
33
|
+
<Input.Field type="tel" defaultValue={contact.phone} />
|
|
34
|
+
</Input.Wrapper>
|
|
35
|
+
</Input.Root>
|
|
36
|
+
</>
|
|
37
|
+
)}
|
|
38
|
+
/>
|
|
39
|
+
))}
|
|
40
|
+
</>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** The same list editable and disabled while the request saves it: fields, handles and buttons turn off together — `disabled`. */
|
|
2
|
+
import { FieldList, type FieldListColumn, Input } from "prime-ui-kit";
|
|
3
|
+
|
|
4
|
+
type Stage = { id: string; name: string; days: string };
|
|
5
|
+
|
|
6
|
+
const COLUMNS: FieldListColumn[] = [{ label: "Этап" }, { label: "Дней", width: "s" }];
|
|
7
|
+
|
|
8
|
+
const STAGES: Stage[] = [
|
|
9
|
+
{ id: "brief", name: "Бриф и смета", days: "3" },
|
|
10
|
+
{ id: "design", name: "Дизайн", days: "10" },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const STATES = [
|
|
14
|
+
{ label: "Этапы проекта", disabled: false },
|
|
15
|
+
{ label: "disabled", disabled: true },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
export default function FieldListStatesExample() {
|
|
19
|
+
return (
|
|
20
|
+
<>
|
|
21
|
+
{STATES.map((state) => (
|
|
22
|
+
<FieldList
|
|
23
|
+
key={state.label}
|
|
24
|
+
label={state.label}
|
|
25
|
+
disabled={state.disabled}
|
|
26
|
+
reorderable
|
|
27
|
+
columns={COLUMNS}
|
|
28
|
+
defaultValue={STAGES}
|
|
29
|
+
getId={(stage) => stage.id}
|
|
30
|
+
getLabel={(stage) => stage.name}
|
|
31
|
+
createItem={() => ({ id: crypto.randomUUID(), name: "", days: "" })}
|
|
32
|
+
addLabel="Добавить этап"
|
|
33
|
+
renderItem={(stage) => (
|
|
34
|
+
<>
|
|
35
|
+
<Input.Root>
|
|
36
|
+
<Input.Wrapper>
|
|
37
|
+
<Input.Field defaultValue={stage.name} />
|
|
38
|
+
</Input.Wrapper>
|
|
39
|
+
</Input.Root>
|
|
40
|
+
<Input.Root>
|
|
41
|
+
<Input.Wrapper>
|
|
42
|
+
<Input.Field defaultValue={stage.days} inputMode="numeric" />
|
|
43
|
+
</Input.Wrapper>
|
|
44
|
+
</Input.Root>
|
|
45
|
+
</>
|
|
46
|
+
)}
|
|
47
|
+
/>
|
|
48
|
+
))}
|
|
49
|
+
</>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
|
|
17
17
|
.formFields {
|
|
18
18
|
display: grid;
|
|
19
|
-
|
|
19
|
+
/* Two columns while each keeps 12rem, one column in a narrower form — from its own width. */
|
|
20
|
+
grid-template-columns: repeat(auto-fit, minmax(min(100%, calc(var(--prime-space-16) * 3)), 1fr));
|
|
20
21
|
align-items: start;
|
|
21
22
|
gap: var(--prime-space-5) var(--prime-space-4);
|
|
22
23
|
}
|
|
@@ -30,9 +31,3 @@
|
|
|
30
31
|
justify-content: flex-end;
|
|
31
32
|
gap: var(--prime-space-2);
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
-
@media (max-width: 639px) {
|
|
35
|
-
.formFields {
|
|
36
|
-
grid-template-columns: minmax(0, 1fr);
|
|
37
|
-
}
|
|
38
|
-
}
|