prime-ui-kit 0.2.3 → 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.
- package/README.md +172 -34
- package/dist/components/accordion/Accordion.d.ts +70 -0
- package/dist/components/accordion/Accordion.d.ts.map +1 -0
- package/dist/components/avatar/Avatar.d.ts +58 -0
- package/dist/components/avatar/Avatar.d.ts.map +1 -0
- package/dist/components/badge/Badge.d.ts +51 -0
- package/dist/components/badge/Badge.d.ts.map +1 -0
- package/dist/components/banner/Banner.d.ts +78 -0
- package/dist/components/banner/Banner.d.ts.map +1 -0
- package/dist/components/breadcrumb/Breadcrumb.d.ts +47 -0
- package/dist/components/breadcrumb/Breadcrumb.d.ts.map +1 -0
- package/dist/components/button/Button.d.ts +57 -0
- package/dist/components/button/Button.d.ts.map +1 -0
- package/dist/components/button-group/ButtonGroup.d.ts +34 -0
- package/dist/components/button-group/ButtonGroup.d.ts.map +1 -0
- package/dist/components/card/Card.d.ts +234 -0
- package/dist/components/card/Card.d.ts.map +1 -0
- package/dist/components/checkbox/Checkbox.d.ts +42 -0
- package/dist/components/checkbox/Checkbox.d.ts.map +1 -0
- package/dist/components/code-block/CodeBlock.d.ts +17 -0
- package/dist/components/code-block/CodeBlock.d.ts.map +1 -0
- package/dist/components/color-picker/ColorPicker.d.ts +76 -0
- package/dist/components/color-picker/ColorPicker.d.ts.map +1 -0
- package/dist/components/color-picker/ColorPickerRac.d.ts +76 -0
- package/dist/components/color-picker/ColorPickerRac.d.ts.map +1 -0
- package/dist/components/command-menu/CommandMenu.d.ts +74 -0
- package/dist/components/command-menu/CommandMenu.d.ts.map +1 -0
- package/dist/components/data-table/DataTable.d.ts +78 -0
- package/dist/components/data-table/DataTable.d.ts.map +1 -0
- package/dist/components/datepicker/Datepicker.d.ts +104 -0
- package/dist/components/datepicker/Datepicker.d.ts.map +1 -0
- package/dist/components/digit-input/DigitInput.d.ts +21 -0
- package/dist/components/digit-input/DigitInput.d.ts.map +1 -0
- package/dist/components/divider/Divider.d.ts +26 -0
- package/dist/components/divider/Divider.d.ts.map +1 -0
- package/dist/components/drawer/Drawer.d.ts +71 -0
- package/dist/components/drawer/Drawer.d.ts.map +1 -0
- package/dist/components/dropdown/Dropdown.d.ts +147 -0
- package/dist/components/dropdown/Dropdown.d.ts.map +1 -0
- package/dist/components/dropdown/dropdownGeometry.d.ts +10 -0
- package/dist/components/dropdown/dropdownGeometry.d.ts.map +1 -0
- package/dist/components/dropdown/menuKeyboard.d.ts +4 -0
- package/dist/components/dropdown/menuKeyboard.d.ts.map +1 -0
- package/dist/components/dropdown/useDropdownPosition.d.ts +18 -0
- package/dist/components/dropdown/useDropdownPosition.d.ts.map +1 -0
- package/dist/components/example-frame/ExampleFrame.d.ts +53 -0
- package/dist/components/example-frame/ExampleFrame.d.ts.map +1 -0
- package/dist/components/file-upload/FileUpload.d.ts +176 -0
- package/dist/components/file-upload/FileUpload.d.ts.map +1 -0
- package/dist/components/hint/Hint.d.ts +27 -0
- package/dist/components/hint/Hint.d.ts.map +1 -0
- package/dist/components/index.css +6306 -5964
- package/dist/components/index.css.map +7 -1
- package/dist/components/index.d.ts +95 -2679
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +8750 -6666
- package/dist/components/index.js.map +7 -1
- package/dist/components/input/Input.d.ts +73 -0
- package/dist/components/input/Input.d.ts.map +1 -0
- package/dist/components/kbd/Kbd.d.ts +15 -0
- package/dist/components/kbd/Kbd.d.ts.map +1 -0
- package/dist/components/label/Label.d.ts +29 -0
- package/dist/components/label/Label.d.ts.map +1 -0
- package/dist/components/link-button/LinkButton.d.ts +18 -0
- package/dist/components/link-button/LinkButton.d.ts.map +1 -0
- package/dist/components/modal/Modal.d.ts +58 -0
- package/dist/components/modal/Modal.d.ts.map +1 -0
- package/dist/components/notification/Notification.d.ts +42 -0
- package/dist/components/notification/Notification.d.ts.map +1 -0
- package/dist/components/notification/NotificationStore.d.ts +18 -0
- package/dist/components/notification/NotificationStore.d.ts.map +1 -0
- package/dist/components/page-content/PageContent.d.ts +51 -0
- package/dist/components/page-content/PageContent.d.ts.map +1 -0
- package/dist/components/pagination/Pagination.d.ts +19 -0
- package/dist/components/pagination/Pagination.d.ts.map +1 -0
- package/dist/components/popover/Popover.d.ts +48 -0
- package/dist/components/popover/Popover.d.ts.map +1 -0
- package/dist/components/popover/popoverGeometry.d.ts +6 -0
- package/dist/components/popover/popoverGeometry.d.ts.map +1 -0
- package/dist/components/popover/usePopoverPosition.d.ts +18 -0
- package/dist/components/popover/usePopoverPosition.d.ts.map +1 -0
- package/dist/components/progress-bar/ProgressBar.d.ts +14 -0
- package/dist/components/progress-bar/ProgressBar.d.ts.map +1 -0
- package/dist/components/progress-circle/ProgressCircle.d.ts +33 -0
- package/dist/components/progress-circle/ProgressCircle.d.ts.map +1 -0
- package/dist/components/radio/Radio.d.ts +40 -0
- package/dist/components/radio/Radio.d.ts.map +1 -0
- package/dist/components/scroll-container/ScrollContainer.d.ts +42 -0
- package/dist/components/scroll-container/ScrollContainer.d.ts.map +1 -0
- package/dist/components/segmented-control/SegmentedControl.d.ts +40 -0
- package/dist/components/segmented-control/SegmentedControl.d.ts.map +1 -0
- package/dist/components/segmented-progress-bar/SegmentedProgressBar.d.ts +22 -0
- package/dist/components/segmented-progress-bar/SegmentedProgressBar.d.ts.map +1 -0
- package/dist/components/select/Select.d.ts +84 -0
- package/dist/components/select/Select.d.ts.map +1 -0
- package/dist/components/select/selectListbox.d.ts +13 -0
- package/dist/components/select/selectListbox.d.ts.map +1 -0
- package/dist/components/slider/Slider.d.ts +23 -0
- package/dist/components/slider/Slider.d.ts.map +1 -0
- package/dist/components/stepper/HorizontalStepper.d.ts +41 -0
- package/dist/components/stepper/HorizontalStepper.d.ts.map +1 -0
- package/dist/components/stepper/Stepper.d.ts +77 -0
- package/dist/components/stepper/Stepper.d.ts.map +1 -0
- package/dist/components/stepper/VerticalStepper.d.ts +41 -0
- package/dist/components/stepper/VerticalStepper.d.ts.map +1 -0
- package/dist/components/stepper/stepperAlignContext.d.ts +11 -0
- package/dist/components/stepper/stepperAlignContext.d.ts.map +1 -0
- package/dist/components/switch/Switch.d.ts +48 -0
- package/dist/components/switch/Switch.d.ts.map +1 -0
- package/dist/components/tabs/Tabs.d.ts +69 -0
- package/dist/components/tabs/Tabs.d.ts.map +1 -0
- package/dist/components/tag/Tag.d.ts +29 -0
- package/dist/components/tag/Tag.d.ts.map +1 -0
- package/dist/components/textarea/Textarea.d.ts +43 -0
- package/dist/components/textarea/Textarea.d.ts.map +1 -0
- package/dist/components/tooltip/Tooltip.d.ts +47 -0
- package/dist/components/tooltip/Tooltip.d.ts.map +1 -0
- package/dist/components/typography/Typography.d.ts +30 -0
- package/dist/components/typography/Typography.d.ts.map +1 -0
- package/dist/hooks/useControllableState.d.ts +8 -0
- package/dist/hooks/useControllableState.d.ts.map +1 -0
- package/dist/hooks/useEscapeKey.d.ts +7 -0
- package/dist/hooks/useEscapeKey.d.ts.map +1 -0
- package/dist/hooks/useFieldIds.d.ts +17 -0
- package/dist/hooks/useFieldIds.d.ts.map +1 -0
- package/dist/hooks/useFocusTrap.d.ts +16 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -0
- package/dist/hooks/useMergedRefs.d.ts +3 -0
- package/dist/hooks/useMergedRefs.d.ts.map +1 -0
- package/dist/hooks/useOutsideClick.d.ts +16 -0
- package/dist/hooks/useOutsideClick.d.ts.map +1 -0
- package/dist/hooks/useOverlayModal.d.ts +7 -0
- package/dist/hooks/useOverlayModal.d.ts.map +1 -0
- package/dist/hooks/usePosition.d.ts +41 -0
- package/dist/hooks/usePosition.d.ts.map +1 -0
- package/dist/hooks/useResponsiveMonths.d.ts +18 -0
- package/dist/hooks/useResponsiveMonths.d.ts.map +1 -0
- package/dist/hooks/useScrollLock.d.ts +8 -0
- package/dist/hooks/useScrollLock.d.ts.map +1 -0
- package/dist/icons/Icon.d.ts +13 -0
- package/dist/icons/Icon.d.ts.map +1 -0
- package/dist/icons/index.d.ts +40 -0
- package/dist/icons/index.d.ts.map +1 -0
- package/dist/index.css +6299 -7273
- package/dist/index.css.map +7 -1
- package/dist/index.d.ts +4 -8
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8784 -6676
- package/dist/index.js.map +7 -1
- package/dist/internal/ControlSizeContext.d.ts +17 -0
- package/dist/internal/ControlSizeContext.d.ts.map +1 -0
- package/dist/internal/DividerContentContext.d.ts +4 -0
- package/dist/internal/DividerContentContext.d.ts.map +1 -0
- package/dist/internal/OverlayPortalLayerContext.d.ts +13 -0
- package/dist/internal/OverlayPortalLayerContext.d.ts.map +1 -0
- package/dist/internal/Portal.d.ts +8 -0
- package/dist/internal/Portal.d.ts.map +1 -0
- package/dist/internal/context.d.ts +11 -0
- package/dist/internal/context.d.ts.map +1 -0
- package/dist/internal/cx.d.ts +2 -0
- package/dist/internal/cx.d.ts.map +1 -0
- package/dist/internal/data-attributes.d.ts +6 -0
- package/dist/internal/data-attributes.d.ts.map +1 -0
- package/dist/internal/highlightTsxHtml.d.ts +3 -0
- package/dist/internal/highlightTsxHtml.d.ts.map +1 -0
- package/dist/internal/layoutPxFromPrimitives.d.ts +13 -0
- package/dist/internal/layoutPxFromPrimitives.d.ts.map +1 -0
- package/dist/internal/mergeRefs.d.ts +4 -0
- package/dist/internal/mergeRefs.d.ts.map +1 -0
- package/dist/internal/runtimeUnits.d.ts +3 -0
- package/dist/internal/runtimeUnits.d.ts.map +1 -0
- package/dist/internal/scrollAncestors.d.ts +3 -0
- package/dist/internal/scrollAncestors.d.ts.map +1 -0
- package/dist/internal/slot.d.ts +19 -0
- package/dist/internal/slot.d.ts.map +1 -0
- package/dist/internal/states.d.ts +87 -0
- package/dist/internal/states.d.ts.map +1 -0
- package/dist/layout/app-shell/AppShell.d.ts +54 -0
- package/dist/layout/app-shell/AppShell.d.ts.map +1 -0
- package/dist/layout/index.d.ts +7 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/layout/sidebar/Sidebar.d.ts +241 -0
- package/dist/layout/sidebar/Sidebar.d.ts.map +1 -0
- package/dist/layout/sidebar/SidebarRoot.d.ts +51 -0
- package/dist/layout/sidebar/SidebarRoot.d.ts.map +1 -0
- package/dist/layout/sidebar/sidebar-context.d.ts +19 -0
- package/dist/layout/sidebar/sidebar-context.d.ts.map +1 -0
- package/dist/layout/sidebar/sidebarLayout.d.ts +12 -0
- package/dist/layout/sidebar/sidebarLayout.d.ts.map +1 -0
- package/dist/tokens/primitives.d.ts +390 -0
- package/dist/tokens/primitives.d.ts.map +1 -0
- package/dist/tokens/semantic.d.ts +732 -0
- package/dist/tokens/semantic.d.ts.map +1 -0
- package/dist/tokens/themes/dark.d.ts +143 -0
- package/dist/tokens/themes/dark.d.ts.map +1 -0
- package/dist/tokens/themes/light.d.ts +16 -0
- package/dist/tokens/themes/light.d.ts.map +1 -0
- package/package.json +14 -6
- package/src/components/accordion/COMPONENT.md +137 -0
- package/src/components/avatar/COMPONENT.md +100 -0
- package/src/components/badge/COMPONENT.md +78 -0
- package/src/components/banner/COMPONENT.md +118 -0
- package/src/components/breadcrumb/COMPONENT.md +94 -0
- package/src/components/button/COMPONENT.md +80 -0
- package/src/components/button-group/COMPONENT.md +83 -0
- package/src/components/card/COMPONENT.md +489 -0
- package/src/components/checkbox/COMPONENT.md +98 -0
- package/src/components/code-block/COMPONENT.md +58 -0
- package/src/components/color-picker/COMPONENT.md +149 -0
- package/src/components/command-menu/COMPONENT.md +167 -0
- package/src/components/data-table/COMPONENT.md +113 -0
- package/src/components/datepicker/COMPONENT.md +137 -0
- package/src/components/digit-input/COMPONENT.md +68 -0
- package/src/components/divider/COMPONENT.md +70 -0
- package/src/components/drawer/COMPONENT.md +149 -0
- package/src/components/dropdown/COMPONENT.md +192 -0
- package/src/components/file-upload/COMPONENT.md +200 -0
- package/src/components/hint/COMPONENT.md +67 -0
- package/src/components/input/COMPONENT.md +119 -0
- package/src/components/kbd/COMPONENT.md +59 -0
- package/src/components/label/COMPONENT.md +94 -0
- package/src/components/link-button/COMPONENT.md +60 -0
- package/src/components/modal/COMPONENT.md +105 -0
- package/src/components/notification/COMPONENT.md +120 -0
- package/src/components/pagination/COMPONENT.md +61 -0
- package/src/components/popover/COMPONENT.md +93 -0
- package/src/components/progress-bar/COMPONENT.md +59 -0
- package/src/components/progress-circle/COMPONENT.md +63 -0
- package/src/components/radio/COMPONENT.md +95 -0
- package/src/components/segmented-control/COMPONENT.md +86 -0
- package/src/components/segmented-progress-bar/COMPONENT.md +75 -0
- package/src/components/select/COMPONENT.md +175 -0
- package/src/components/slider/COMPONENT.md +62 -0
- package/src/components/stepper/COMPONENT.md +186 -0
- package/src/components/switch/COMPONENT.md +98 -0
- package/src/components/tabs/COMPONENT.md +114 -0
- package/src/components/tag/COMPONENT.md +67 -0
- package/src/components/textarea/COMPONENT.md +98 -0
- package/src/components/tooltip/COMPONENT.md +87 -0
- package/src/components/typography/COMPONENT.md +89 -0
- package/src/styles/theme-dark.css +43 -0
- package/src/styles/theme-light.css +43 -0
- package/src/styles/tokens.css +23 -4
- package/src/styles/tokens.test.ts +0 -27
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# ColorPicker
|
|
2
|
+
|
|
3
|
+
**Проектирование по умолчанию:** при проектировании экранов и примеров изначально выбирай **`m`** для `size` (где есть ось размера), если явно не оговорено иное.
|
|
4
|
+
|
|
5
|
+
## About
|
|
6
|
+
|
|
7
|
+
A composite color picker built on **react-aria-components**: it keeps a shared `Color` value across a 2D area, channel sliders, optional preset swatches, a standalone hex field, and a channel strip with an eyedropper control.
|
|
8
|
+
|
|
9
|
+
- **When to use:** brand, theme, or accent color selection with a visual preview; editor-style fill, stroke, or text color; chart or legend colors persisted as strings or `Color`; forms where the stored value must stay a CSS-parseable color.
|
|
10
|
+
- **When to use:** one shared `onChange` from many nested controls while the parent holds `value` / `parseColor` state.
|
|
11
|
+
- **When to use:** combining fixed presets (`SwatchPicker`) with free adjustment (area and sliders).
|
|
12
|
+
- **When not to use:** only a hex string is needed and no picker UI adds value — prefer a plain [Input](../input/COMPONENT.md) or another simple field.
|
|
13
|
+
- **When not to use:** the full control surface must stay inline in a tight layout — mount the panel in an overlay ([Popover](../popover/COMPONENT.md), [Modal](../modal/COMPONENT.md), or [Drawer](../drawer/COMPONENT.md)) instead.
|
|
14
|
+
- **When not to use:** every user must rely on the system eyedropper — without the EyeDropper API the control is non-functional decoration only.
|
|
15
|
+
|
|
16
|
+
## Composition
|
|
17
|
+
|
|
18
|
+
- **`ColorPicker.Root`** wraps everything that should share one color value (trigger + panel). Put **`ColorPicker.TriggerSwatch`** on the same root as the panel so the swatch reflects the live color.
|
|
19
|
+
- **Product layouts:** place the interactive surface (area, sliders, swatches, `HexInput`, `ChannelStrip`) inside **`Popover.Content`** (or modal/drawer), with a trigger such as [Button](../button/COMPONENT.md) + `TriggerSwatch`. `HexInput`-only flows still belong under a trigger if you want a compact field.
|
|
20
|
+
- **`ColorPicker.FormatProvider`** is required for **`FormatSelect`** and **`ChannelStrip`** (the strip calls into format context; without the provider it throws at runtime). `FormatSelect` renders nothing if mounted outside `FormatProvider`.
|
|
21
|
+
- **Typical panel order:** `FormatProvider` → optional `FormatSelect` → `Area` with `AreaThumb` → one or more `Slider` trees (`SliderMeta` optional, then `SliderTrack` → `Thumb`) → `ChannelStrip` (`pipetteIcon` required) → optional `SwatchPicker` with `SwatchPickerItem` children each wrapping `Swatch` → optional `HexInput` or RAC **`Field`** for custom channel inputs.
|
|
22
|
+
- **`EyeDropperButton`** is used inside `ChannelStrip` by default; it can also be composed separately under the same `Root` if needed.
|
|
23
|
+
- **`Output`** is the RAC slider value readout; the kit wires it inside **`SliderMeta`** (label + value row).
|
|
24
|
+
|
|
25
|
+
### Minimal example
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { Button, ColorPicker, Popover } from "prime-ui-kit";
|
|
29
|
+
|
|
30
|
+
export function MinimalColorField() {
|
|
31
|
+
return (
|
|
32
|
+
<ColorPicker.Root defaultValue="#3b82f6">
|
|
33
|
+
<Popover.Root>
|
|
34
|
+
<Popover.Trigger asChild>
|
|
35
|
+
<Button.Root mode="stroke" size="m" variant="neutral">
|
|
36
|
+
<ColorPicker.TriggerSwatch />
|
|
37
|
+
Color
|
|
38
|
+
</Button.Root>
|
|
39
|
+
</Popover.Trigger>
|
|
40
|
+
<Popover.Content align="start" insetGap="x3" insetPadding="x2" side="bottom">
|
|
41
|
+
<ColorPicker.FormatProvider>
|
|
42
|
+
<ColorPicker.FormatSelect />
|
|
43
|
+
<ColorPicker.Area colorSpace="hsl" xChannel="saturation" yChannel="lightness">
|
|
44
|
+
<ColorPicker.AreaThumb />
|
|
45
|
+
</ColorPicker.Area>
|
|
46
|
+
<ColorPicker.ChannelStrip pipetteIcon={<span aria-hidden />} />
|
|
47
|
+
</ColorPicker.FormatProvider>
|
|
48
|
+
</Popover.Content>
|
|
49
|
+
</Popover.Root>
|
|
50
|
+
</ColorPicker.Root>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Rules
|
|
56
|
+
|
|
57
|
+
- Use **controlled** mode with `value` and `onChange` when the parent owns color state; use **`defaultValue`** for uncontrolled usage. Value types follow RAC: `string | Color`; `onChange` receives a **`Color`** instance.
|
|
58
|
+
- Import **`Color`** for typing from **`react-aria-components`** (or use the kit re-export type **`ColorPickerColorValue`**). Use **`parseColor`** from **`prime-ui-kit`** to turn strings into `Color` for `useState` initial values.
|
|
59
|
+
- **`children`** on `Root` may be a render function; it receives **`ColorPickerRenderProps`** (`{ color }`) from RAC.
|
|
60
|
+
- There is **no** single `isDisabled` on `Root` — disable **`Area`**, **`Slider`**, **`SwatchPickerItem`**, or wrap groups in a disabled **`fieldset`** when appropriate.
|
|
61
|
+
- **`ChannelStrip`** must receive **`pipetteIcon`** (usually [Button.Icon](../button/COMPONENT.md) wrapping an icon). Pass **`aria-label`** on **`EyeDropperButton`** if you use it standalone (default label is Russian “Пипетка” in code).
|
|
62
|
+
- If **`window.EyeDropper`** is missing, the eyedropper renders as a disabled control with **`aria-hidden`** and **`tabIndex={-1}`** — do not rely on it as the only way to set a color.
|
|
63
|
+
- **`FormatProvider`** owns HSL / RGB / hex strip mode (`defaultFormat`: `"hsl"` \| `"rgb"` \| `"hex"`). **`FormatSelect`** only appears when inside that provider.
|
|
64
|
+
- **`HexInput`** and strip hex editing **revert** invalid input to the last committed color on **blur** or **Enter**. Channel cells in the strip **ignore** non-numeric input on commit (no color change).
|
|
65
|
+
- **`TriggerSwatch`** is **`aria-hidden`**; expose the purpose on the trigger (visible button text or `aria-label` on the control).
|
|
66
|
+
- **`SwatchPicker`** needs an accessible name (**`aria-label`** or an associated label).
|
|
67
|
+
- Sliders use a **fixed** visual size tier (`data-size="m"` on the kit `Slider`); only **`HexInput`** exposes the kit **`size`** axis (`s` \| `m` \| `l` \| `xl`).
|
|
68
|
+
- For **`SwatchPicker`** selection semantics and layout, follow RAC props (`value` / `defaultValue` / `onChange`, `layout`, etc.).
|
|
69
|
+
|
|
70
|
+
## API
|
|
71
|
+
|
|
72
|
+
### ColorPicker.Root
|
|
73
|
+
|
|
74
|
+
| Prop | Type | Default | Required | Description |
|
|
75
|
+
|------|------|---------|----------|-------------|
|
|
76
|
+
| value | `string \| Color` | — | No | Controlled color value |
|
|
77
|
+
| defaultValue | `string \| Color` | — | No | Initial color when uncontrolled |
|
|
78
|
+
| onChange | `(color: Color) => void` | — | No | Fires when any nested control changes the color |
|
|
79
|
+
| children | `ReactNode \| (props: ColorPickerRenderProps) => ReactNode` | — | Yes | Pickers, triggers, and panels sharing state |
|
|
80
|
+
| slot | `string \| null` | — | No | Slotted context name (RAC `SlotProps`) |
|
|
81
|
+
| className | `string \| (values) => string` | — | No | Root element classes (RAC render props) |
|
|
82
|
+
| …rest | RAC + DOM | — | No | Other **`ColorPickerRootProps`** / `AriaColorPickerProps` from react-aria-components |
|
|
83
|
+
|
|
84
|
+
### ColorPicker.FormatProvider
|
|
85
|
+
|
|
86
|
+
| Prop | Type | Default | Required | Description |
|
|
87
|
+
|------|------|---------|----------|-------------|
|
|
88
|
+
| children | `ReactNode` | — | Yes | subtree that may use `FormatSelect` and `ChannelStrip` |
|
|
89
|
+
| defaultFormat | `"hsl" \| "rgb" \| "hex"` | `"hsl"` | No | Initial format for the strip and format select |
|
|
90
|
+
|
|
91
|
+
### ColorPicker.FormatSelect
|
|
92
|
+
|
|
93
|
+
| Prop | Type | Default | Required | Description |
|
|
94
|
+
|------|------|---------|----------|-------------|
|
|
95
|
+
| className | `string` | — | No | Class on the wrapper around the kit [Select](../select/COMPONENT.md) |
|
|
96
|
+
|
|
97
|
+
Renders `null` when not under `FormatProvider`.
|
|
98
|
+
|
|
99
|
+
### ColorPicker.ChannelStrip
|
|
100
|
+
|
|
101
|
+
| Prop | Type | Default | Required | Description |
|
|
102
|
+
|------|------|---------|----------|-------------|
|
|
103
|
+
| pipetteIcon | `ReactNode` | — | Yes | Icon for the embedded eyedropper ([Button.Icon](../button/COMPONENT.md) + icon) |
|
|
104
|
+
| className | `string` | — | No | Class on the strip container |
|
|
105
|
+
|
|
106
|
+
### ColorPicker.HexInput
|
|
107
|
+
|
|
108
|
+
| Prop | Type | Default | Required | Description |
|
|
109
|
+
|------|------|---------|----------|-------------|
|
|
110
|
+
| size | `"s" \| "m" \| "l" \| "xl"` | `"m"` | No | Passed to kit [Input](../input/COMPONENT.md) |
|
|
111
|
+
| label | `ReactNode` | `"Hex"` | No | Field label |
|
|
112
|
+
| className | `string` | — | No | Class on `Input.Root` |
|
|
113
|
+
|
|
114
|
+
### ColorPicker.TriggerSwatch
|
|
115
|
+
|
|
116
|
+
| Prop | Type | Default | Required | Description |
|
|
117
|
+
|------|------|---------|----------|-------------|
|
|
118
|
+
| className | `string` | — | No | Class on the preview square |
|
|
119
|
+
|
|
120
|
+
### ColorPicker.SliderMeta
|
|
121
|
+
|
|
122
|
+
| Prop | Type | Default | Required | Description |
|
|
123
|
+
|------|------|---------|----------|-------------|
|
|
124
|
+
| label | `ReactNode` | — | Yes | Left label; current channel value on the right via `Output` |
|
|
125
|
+
|
|
126
|
+
### ColorPicker.EyeDropperButton
|
|
127
|
+
|
|
128
|
+
Same props as **`Button.Root`** from the kit except **`variant`**, **`mode`**, and **`size`** are fixed (`neutral`, `stroke`, `m`). Forwarded ref: **`HTMLButtonElement`**. Children are usually **`Button.Icon`**.
|
|
129
|
+
|
|
130
|
+
### ColorPicker.Area, AreaThumb, Slider, SliderTrack, Thumb, Output, Field, SwatchPicker, SwatchPickerItem, Swatch
|
|
131
|
+
|
|
132
|
+
Styled wrappers around the matching **react-aria-components** primitives. Use their RAC prop surfaces (e.g. **`Area`**: `colorSpace`, `xChannel`, `yChannel`, `isDisabled`; **`Slider`**: `channel`, optional `colorSpace`, `orientation`, `isDisabled`; **`SwatchPicker`** / **`SwatchPickerItem`**: selection and `color` on items; **`Field`**: RAC `ColorField` props). **`Swatch`** and **`SliderTrack`** add checkerboard layering for transparency in the kit styles.
|
|
133
|
+
|
|
134
|
+
### `parseColor(value: string): Color`
|
|
135
|
+
|
|
136
|
+
Parses a CSS color string into a **`Color`**. **Throws** if the string cannot be parsed (RAC / `@react-stately/color` behavior).
|
|
137
|
+
|
|
138
|
+
Exported types from this module include **`ColorPickerRootProps`**, **`ColorPickerHexInputProps`**, **`ColorPickerFormatProviderProps`**, **`ColorPickerTriggerSwatchProps`**, **`ColorValueFormat`**, **`ColorPickerRenderProps`**, and **`ColorPickerColorValue`** (alias of **`Color`**).
|
|
139
|
+
|
|
140
|
+
## Related
|
|
141
|
+
|
|
142
|
+
- [Popover](../popover/COMPONENT.md)
|
|
143
|
+
- [Button](../button/COMPONENT.md)
|
|
144
|
+
- [Input](../input/COMPONENT.md)
|
|
145
|
+
- [Select](../select/COMPONENT.md)
|
|
146
|
+
- [Modal](../modal/COMPONENT.md)
|
|
147
|
+
- [Drawer](../drawer/COMPONENT.md)
|
|
148
|
+
- [Label](../label/COMPONENT.md)
|
|
149
|
+
- [Typography](../typography/COMPONENT.md)
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# CommandMenu
|
|
2
|
+
|
|
3
|
+
**Проектирование по умолчанию:** при проектировании экранов и примеров изначально выбирай **`m`** для `size` (где есть ось размера), если явно не оговорено иное.
|
|
4
|
+
|
|
5
|
+
## About
|
|
6
|
+
|
|
7
|
+
A modal command palette: search field plus a filterable list of actions. Typing narrows visible options; users pick with pointer or keyboard while focus stays on the combobox input.
|
|
8
|
+
|
|
9
|
+
**When to use**
|
|
10
|
+
|
|
11
|
+
- **Dense navigation** — jump to sections, records, or actions without opening full menus (dashboards, CRM, admin).
|
|
12
|
+
- **Power-user flows** — one surface for “go to…” and “do…” when labels map cleanly to filter strings and `keywords`.
|
|
13
|
+
- **Keyboard-first desktops** — pair with your own global shortcut; arrow keys, Home, End, and Enter are handled from the search field.
|
|
14
|
+
- **Grouped actions** — optional section headings and optional tag row under the search for scope chips.
|
|
15
|
+
|
|
16
|
+
**When not to use**
|
|
17
|
+
|
|
18
|
+
- **Multi-select or bulk pick** — only one active option; no built-in multi-value selection.
|
|
19
|
+
- **Server-only search without a client list** — filtering is synchronous over registered items; huge lists need virtualization or a different pattern.
|
|
20
|
+
- **Non-modal pickers** — use [Dropdown](../dropdown/COMPONENT.md) or [Select](../select/COMPONENT.md) for inline single choice.
|
|
21
|
+
- **Built-in “no results” UX** — empty matches hide groups/items; you supply messaging or empty state markup yourself.
|
|
22
|
+
|
|
23
|
+
## Composition
|
|
24
|
+
|
|
25
|
+
- **`CommandMenu.Dialog`** wraps content in [Modal](../modal/COMPONENT.md) (`role="dialog"`) and mounts **`CommandMenuRootProvider`**: search string, active option, and item registry live here. Open state is controlled (`open` / `onOpenChange`) or uncontrolled (`defaultOpen`).
|
|
26
|
+
- **Recommended top order:** optional **`DialogTitle`** / **`DialogDescription`** (same typography shell as modal headings) → **`InputRow`** (optional slots **`leading`** / **`trailing`**) → **`Input`** → optional **`TagSection`** → **`TagSectionLabel`** / **`TagRow`** → **`List`** → optional **`Footer`** (optional **`FooterKeyBox`** for key hints).
|
|
27
|
+
- **`List`** is the **`listbox`** (`id` wired to the input’s **`aria-controls`**). **`Group`** wraps **`Item`** nodes; groups with no visible items get **`hidden`**. **`Item`** registers for filtering and keyboard activation; put **`ItemIcon`** and label text inside **`Item`**.
|
|
28
|
+
- **`Input`** may sit directly under **`Dialog`** without **`InputRow`** (valid markup); **`InputRow`** is the styled search row when you need leading/trailing slots or density.
|
|
29
|
+
|
|
30
|
+
### Minimal example
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import * as React from "react";
|
|
34
|
+
import { CommandMenu } from "prime-ui-kit";
|
|
35
|
+
|
|
36
|
+
export function Example() {
|
|
37
|
+
const [open, setOpen] = React.useState(false);
|
|
38
|
+
return (
|
|
39
|
+
<CommandMenu.Dialog open={open} onOpenChange={setOpen}>
|
|
40
|
+
<CommandMenu.InputRow>
|
|
41
|
+
<CommandMenu.Input placeholder="Search" aria-label="Search commands" />
|
|
42
|
+
</CommandMenu.InputRow>
|
|
43
|
+
<CommandMenu.List>
|
|
44
|
+
<CommandMenu.Item value="action" onSelect={() => setOpen(false)}>
|
|
45
|
+
Action
|
|
46
|
+
</CommandMenu.Item>
|
|
47
|
+
</CommandMenu.List>
|
|
48
|
+
</CommandMenu.Dialog>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Rules
|
|
54
|
+
|
|
55
|
+
- **Open state:** **`open`** + **`onOpenChange`** for controlled mode; **`defaultOpen`** (defaults to `false` via `Modal.Root`) for uncontrolled. Escape and overlay click close according to **`closeOnEscape`** and **`closeOnOverlayClick`** (both default `true`).
|
|
56
|
+
- **Search state:** **`Input`** is uncontrolled by default (internal `search` drives filtering). Pass **`value`** / **`onChange`** for controlled input; when **`value`** is set, internal state tracks it via an effect. **`type`** is always **`search`**; **`size`** is not a valid prop on **`Input`**.
|
|
57
|
+
- **Remount reset:** when the dialog content tree mounts, search and active item reset and the input is focused on the next animation frame—do not assume text persists across unmount.
|
|
58
|
+
- **Filtering:** matches run against normalized **`value`** and **`keywords`** together; **`disabled`** items are excluded from matches and keyboard order. **`Item`** **`value`** is required.
|
|
59
|
+
- **Selection:** Enter activates the active option; click and pointer move on an enabled, visible item updates the active option and can fire **`onSelect`**. **`Item`** renders **`type="button"`**; do not rely on **`type`** override.
|
|
60
|
+
- **Panel styling:** **`className`** and **`contentClassName`** merge onto the dialog panel; width/height helpers (e.g. `dialogContentWide`, `dialogContentNarrow`, `dialogContentTight`) live in the component CSS module—import those classes in your app if you need them.
|
|
61
|
+
- **Accessibility:** set **`aria-labelledby`** (and **`DialogTitle`** with a matching **`id`**) or an appropriate **`aria-label`** on the dialog surface; **`Input`** exposes **`role="combobox"`**, **`aria-controls`**, and **`aria-activedescendant`**; **`List`** is **`listbox`**, **`Item`** is **`option`** with **`aria-selected`**. Modal focus trap and scroll lock follow [Modal](../modal/COMPONENT.md) behavior.
|
|
62
|
+
- **FooterKeyBox** wraps [Badge](../badge/COMPONENT.md) (`size="s"`, `color="gray"`); **`tone="muted"`** maps to badge variant **`lighter`**, default maps to **`stroke`**.
|
|
63
|
+
|
|
64
|
+
## API
|
|
65
|
+
|
|
66
|
+
### CommandMenu.Dialog
|
|
67
|
+
|
|
68
|
+
| Prop | Type | Default | Required | Description |
|
|
69
|
+
|------|------|---------|----------|-------------|
|
|
70
|
+
| children | `React.ReactNode` | — | no | Palette markup (provider runs inside the panel) |
|
|
71
|
+
| open | `boolean` | — | no | Controlled open state |
|
|
72
|
+
| defaultOpen | `boolean` | `false` | no | Initial open when uncontrolled |
|
|
73
|
+
| onOpenChange | `(open: boolean) => void` | — | no | Open state change callback |
|
|
74
|
+
| closeOnEscape | `boolean` | `true` | no | Close when Escape is pressed |
|
|
75
|
+
| closeOnOverlayClick | `boolean` | `true` | no | Close when the overlay is clicked |
|
|
76
|
+
| overlayClassName | `string` | — | no | Overlay wrapper class |
|
|
77
|
+
| className | `string` | — | no | Panel class (merged with internal dialog layout) |
|
|
78
|
+
| contentClassName | `string` | — | no | Additional panel class merged before `className` |
|
|
79
|
+
| aria-labelledby | `string` | — | no | IDs of labelling element(s) |
|
|
80
|
+
| aria-describedby | `string` | — | no | IDs of description element(s) |
|
|
81
|
+
|
|
82
|
+
### CommandMenu.DialogTitle / CommandMenu.DialogDescription
|
|
83
|
+
|
|
84
|
+
| Part | Element | Notes |
|
|
85
|
+
|------|---------|--------|
|
|
86
|
+
| DialogTitle | `h2` | `React.HTMLAttributes<HTMLHeadingElement>` and `className`; same title class stack as modal shell |
|
|
87
|
+
| DialogDescription | `p` | `React.HTMLAttributes<HTMLParagraphElement>` and `className`; same description class stack as modal shell |
|
|
88
|
+
|
|
89
|
+
### CommandMenu.InputRow
|
|
90
|
+
|
|
91
|
+
| Prop | Type | Default | Required | Description |
|
|
92
|
+
|------|------|---------|----------|-------------|
|
|
93
|
+
| children | `React.ReactNode` | — | no | Typically **`Input`** |
|
|
94
|
+
| leading | `React.ReactNode` | — | no | Start slot |
|
|
95
|
+
| trailing | `React.ReactNode` | — | no | End slot |
|
|
96
|
+
| density | `"compact" \| "comfortable"` | `"compact"` | no | Search row vertical padding |
|
|
97
|
+
| className | `string` | — | no | Wrapper class |
|
|
98
|
+
| …rest | `React.HTMLAttributes<HTMLDivElement>` | — | no | Forwarded to the row `div` |
|
|
99
|
+
|
|
100
|
+
### CommandMenu.Input
|
|
101
|
+
|
|
102
|
+
| Prop | Type | Default | Required | Description |
|
|
103
|
+
|------|------|---------|----------|-------------|
|
|
104
|
+
| value | `string` (and other input value types) | — | no | Controlled value; when set, filters sync from this value |
|
|
105
|
+
| onChange | `React.ChangeEventHandler<HTMLInputElement>` | — | no | Standard change handler; internal state updates when uncontrolled |
|
|
106
|
+
| className | `string` | — | no | Input class |
|
|
107
|
+
| …rest | `Omit<React.InputHTMLAttributes<HTMLInputElement>, "size" \| "type">` | — | no | Other attributes except `size` and `type` (`type` is fixed to `search`) |
|
|
108
|
+
|
|
109
|
+
### CommandMenu.List
|
|
110
|
+
|
|
111
|
+
| Prop | Type | Default | Required | Description |
|
|
112
|
+
|------|------|---------|----------|-------------|
|
|
113
|
+
| children | `React.ReactNode` | — | no | Groups and/or items |
|
|
114
|
+
| className | `string` | — | no | List surface class |
|
|
115
|
+
| …rest | `React.HTMLAttributes<HTMLDivElement>` | — | no | Passed through to the scroll container root (`role="listbox"`, stable `id` for `aria-controls`) |
|
|
116
|
+
|
|
117
|
+
### CommandMenu.Group
|
|
118
|
+
|
|
119
|
+
| Prop | Type | Default | Required | Description |
|
|
120
|
+
|------|------|---------|----------|-------------|
|
|
121
|
+
| heading | `React.ReactNode` | — | no | Section label (string vs node pick different heading wrappers) |
|
|
122
|
+
| children | `React.ReactNode` | — | no | **`Item`** elements |
|
|
123
|
+
| className | `string` | — | no | Group container class |
|
|
124
|
+
| …rest | `React.HTMLAttributes<HTMLDivElement>` | — | no | Forwarded to the group `div`; container is **`hidden`** when no visible items belong to the group |
|
|
125
|
+
|
|
126
|
+
### CommandMenu.Item
|
|
127
|
+
|
|
128
|
+
| Prop | Type | Default | Required | Description |
|
|
129
|
+
|------|------|---------|----------|-------------|
|
|
130
|
+
| value | `string` | — | yes | Text participating in filter matching |
|
|
131
|
+
| keywords | `string` | `""` | no | Extra space for matching (not shown as the label) |
|
|
132
|
+
| size | `CommandMenuItemSize` (`"s"` \| `"m"`) | `"s"` | no | Row density / type scale |
|
|
133
|
+
| onSelect | `() => void` | — | no | Called when the item is chosen (click or keyboard activate) |
|
|
134
|
+
| disabled | `boolean` | — | no | Excluded from filtering, visibility, and activation |
|
|
135
|
+
| className | `string` | — | no | Button class |
|
|
136
|
+
| …rest | `Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "type" \| "onSelect">` | — | no | Other button props; `type` is always `button` |
|
|
137
|
+
|
|
138
|
+
### CommandMenu.ItemIcon
|
|
139
|
+
|
|
140
|
+
Polymorphic icon slot: `as` (element type, default `"span"`), `className`, and remaining props forwarded to the chosen component (see `CommandMenuItemIconProps`).
|
|
141
|
+
|
|
142
|
+
### CommandMenu.TagSection / TagSectionLabel / TagRow
|
|
143
|
+
|
|
144
|
+
`React.HTMLAttributes<HTMLDivElement>` with `className` and `children` for the optional block between search and list.
|
|
145
|
+
|
|
146
|
+
### CommandMenu.Footer
|
|
147
|
+
|
|
148
|
+
`React.HTMLAttributes<HTMLDivElement>` with `className` and `children`; base styles from the module (e.g. footer layout tokens). Optional module classes such as `footerMuted` apply via `className` when you import the stylesheet.
|
|
149
|
+
|
|
150
|
+
### CommandMenu.FooterKeyBox
|
|
151
|
+
|
|
152
|
+
| Prop | Type | Default | Required | Description |
|
|
153
|
+
|------|------|---------|----------|-------------|
|
|
154
|
+
| children | `React.ReactNode` | — | no | Key cap or icon (rendered inside `Badge.Icon`) |
|
|
155
|
+
| tone | `"default" \| "muted"` | `"default"` | no | Badge visual variant (`stroke` vs `lighter`) |
|
|
156
|
+
| className | `string` | — | no | Extra class on the badge root |
|
|
157
|
+
| …rest | `Omit<React.HTMLAttributes<HTMLDivElement>, "color">` | — | no | Additional attributes except `color` |
|
|
158
|
+
|
|
159
|
+
## Related
|
|
160
|
+
|
|
161
|
+
- [Modal](../modal/COMPONENT.md) — dialog shell, focus trap, portal
|
|
162
|
+
- [Badge](../badge/COMPONENT.md) — used inside **`FooterKeyBox`**
|
|
163
|
+
- [Button](../button/COMPONENT.md), [LinkButton](../link-button/COMPONENT.md) — triggers and links outside the palette
|
|
164
|
+
- [Tag](../tag/COMPONENT.md) — common companion for **`TagRow`**
|
|
165
|
+
- [Kbd](../kbd/COMPONENT.md) — shortcut hints in **`InputRow`** trailing slot
|
|
166
|
+
- [Typography](../typography/COMPONENT.md) — titles, hints, footer copy
|
|
167
|
+
- [Dropdown](../dropdown/COMPONENT.md), [Select](../select/COMPONENT.md) — non-modal single-choice lists
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# DataTable
|
|
2
|
+
|
|
3
|
+
**Проектирование по умолчанию:** при проектировании экранов и примеров изначально выбирай **`m`** для `size` (где есть ось размера), если явно не оговорено иное.
|
|
4
|
+
|
|
5
|
+
## About
|
|
6
|
+
|
|
7
|
+
`DataTable.Root` renders a semantic `<table>` inside a scroll viewport, with optional client-side sorting, classic pagination or infinite-scroll slicing, sticky header and sticky first column, and a footer with row counts (and pagination or infinite-scroll hints).
|
|
8
|
+
|
|
9
|
+
- **Use** when you need sortable tabular data with built-in pagination or “load more while scrolling” without building table chrome from scratch.
|
|
10
|
+
- **Use** when row hover / column hover highlights or zebra striping should stay consistent with kit tokens via `size` and `ControlSizeProvider`.
|
|
11
|
+
- **Use** when the first column must stay visible during horizontal scroll (`stickyFirstColumn`).
|
|
12
|
+
- **Do not use** when you need arbitrary column pinning, resizable columns, or spreadsheet-style keyboard grid navigation — the table does not implement those.
|
|
13
|
+
- **Do not use** when sorting or filtering must run on the server only without mirroring logic in the parent — sorting is applied in memory to the `rows` you pass; supply pre-sorted data or control `sort` yourself and replace `rows` accordingly.
|
|
14
|
+
- **Do not use** when you need a loading overlay on top of already rendered rows — `loading` only affects the body when there are zero rows to display.
|
|
15
|
+
|
|
16
|
+
## Composition
|
|
17
|
+
|
|
18
|
+
- **Public API** — a single compound entry: `DataTable` with `Root` (`DataTableRoot`). There are no other exported subcomponents.
|
|
19
|
+
- **Structure** — `ControlSizeProvider` wraps a root `div` (data attributes for size, dividers, header visibility, stickiness, table width mode, hover highlights, zebra). Inside: `ScrollContainer` viewport → `<table>`, optional `<thead>` (`<th>` per column), `<tbody>` with rows, and an `aria-hidden` sentinel at the bottom when `infiniteScroll` is on (for `IntersectionObserver` or scroll fallback).
|
|
20
|
+
- **Footer** — always shows a “shown range / total” line; if not `infiniteScroll` and `showPagination` and there is more than one page, it renders `Pagination.Root`; in infinite mode it may show a short status when more rows can be revealed or loaded.
|
|
21
|
+
|
|
22
|
+
### Minimal example
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { DataTable, type DataTableColumn } from "prime-ui-kit";
|
|
26
|
+
|
|
27
|
+
type Row = { id: string };
|
|
28
|
+
|
|
29
|
+
const columns: DataTableColumn<Row>[] = [{ id: "id", header: "ID", accessor: "id" }];
|
|
30
|
+
const rows: Row[] = [{ id: "1" }];
|
|
31
|
+
|
|
32
|
+
export function Example() {
|
|
33
|
+
return <DataTable.Root columns={columns} rows={rows} />;
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Rules
|
|
38
|
+
|
|
39
|
+
- Pass **`columns`** with unique **`id`** and **`header`** for every column; **`accessor`** (key or function), **`cell`**, **`sortable`**, and the rest are optional.
|
|
40
|
+
- **Sort** — controlled: `sort` + `onSortChange`. Uncontrolled initial order: `defaultSort` (default `null`). Clicking a sortable header cycles **asc → desc → none** for that column; changing sort sets the page to **1** in paginated mode.
|
|
41
|
+
- **Page** — controlled: `page` + `onPageChange`. Uncontrolled: `defaultPage` (default `1`). Page index is clamped when row count changes. Toggling **`infiniteScroll`** resets the visible slice; leaving infinite mode resets page to **1** via internal effect.
|
|
42
|
+
- **Infinite scroll** — set `infiniteScroll`. The visible slice grows by **`infiniteBatchSize`** up to the current **`rows.length`** first; when the slice shows all local rows and **`hasMore`**, **`onLoadMore`** runs when the sentinel intersects (or on near-bottom scroll if `IntersectionObserver` is missing). **`initialVisibleRows`** defaults to **`pageSize`** when omitted.
|
|
43
|
+
- **`loading`** — shows **`loadingText`** in a single spanning row only when there are no displayed rows yet; it does not dim existing rows.
|
|
44
|
+
- **Empty** — when not loading and there are no rows, **`emptyText`** is shown in a spanning row.
|
|
45
|
+
- **Row keys** — provide **`getRowKey`** for stable identity; otherwise React **`key`** falls back to the row **index** (fragile if row order changes).
|
|
46
|
+
- **Localization** — default **`loadingText`**, **`emptyText`**, footer range text, and infinite-scroll hints are **Russian** in the implementation; override with props where needed.
|
|
47
|
+
- **Accessibility** — sortable headers use an inner control pattern inside **`th`** with **`scope="col"`**; sort icons are **`aria-hidden`**. Cells with **`onCellClick`** get **`role="button"`**, **`tabIndex={0}`**, and **Enter / Space**. There is no **`grid`** role or arrow-key cell navigation.
|
|
48
|
+
|
|
49
|
+
## API
|
|
50
|
+
|
|
51
|
+
### DataTable.Root
|
|
52
|
+
|
|
53
|
+
| Prop | Type | Default | Required | Description |
|
|
54
|
+
| --- | --- | --- | --- | --- |
|
|
55
|
+
| columns | `DataTableColumn<Row>[]` | — | Yes | Column definitions |
|
|
56
|
+
| rows | `Row[]` | — | Yes | Data rows (sorted in memory when `sort` applies) |
|
|
57
|
+
| size | `DataTableSize` | `"m"` | No | Row density; forwarded to nested `Pagination` unless `paginationSize` is set |
|
|
58
|
+
| className | `string` | — | No | Class on the outer wrapper |
|
|
59
|
+
| showHeader | `boolean` | `true` | No | Render `<thead>` |
|
|
60
|
+
| stickyHeader | `boolean` | `false` | No | Sticky header row |
|
|
61
|
+
| stickyFirstColumn | `boolean` | `false` | No | Sticky first column (and corner cell when header is sticky) |
|
|
62
|
+
| getRowKey | `(row: Row, index: number) => React.Key` | — | No | Stable row key; default is index |
|
|
63
|
+
| onRowClick | `(row: Row, index: number, event: React.MouseEvent<HTMLTableRowElement>) => void` | — | No | Row click handler |
|
|
64
|
+
| loading | `boolean` | `false` | No | Loading state when no rows are displayed |
|
|
65
|
+
| loadingText | `React.ReactNode` | `"Загрузка данных…"` | No | Message in loading state |
|
|
66
|
+
| emptyText | `React.ReactNode` | `"Нет данных для отображения."` | No | Message when there are no rows |
|
|
67
|
+
| dividerStyle | `DataTableDividerStyle` | `"standard"` | No | Cell border style: `standard`, `dashed`, `dotted`, `none` |
|
|
68
|
+
| sort | `DataTableSortState` | — | No | Controlled sort (`null` or `{ columnId, order }`) |
|
|
69
|
+
| defaultSort | `DataTableSortState` | `null` | No | Initial sort when uncontrolled |
|
|
70
|
+
| onSortChange | `(sort: DataTableSortState) => void` | — | No | Sort change callback |
|
|
71
|
+
| page | `number` | — | No | Controlled current page (1-based) |
|
|
72
|
+
| defaultPage | `number` | `1` | No | Initial page when uncontrolled |
|
|
73
|
+
| onPageChange | `(page: number) => void` | — | No | Page change callback |
|
|
74
|
+
| pageSize | `number` | `10` | No | Rows per page in pagination mode; also default for `initialVisibleRows` in infinite mode |
|
|
75
|
+
| showPagination | `boolean` | `true` | No | Show `Pagination` when not in infinite mode and `totalPages > 1` |
|
|
76
|
+
| siblingCount | `number` | `1` | No | Page window size passed to `Pagination.Root` |
|
|
77
|
+
| paginationSize | `DataTableSize` | — | No | Pagination size; defaults to root `size` |
|
|
78
|
+
| infiniteScroll | `boolean` | `false` | No | Scroll viewport with growing slice / `onLoadMore` |
|
|
79
|
+
| initialVisibleRows | `number` | `pageSize` | No | Initial number of rows shown in infinite mode |
|
|
80
|
+
| infiniteBatchSize | `number` | `20` | No | Rows added per reach-end step before `onLoadMore` |
|
|
81
|
+
| hasMore | `boolean` | `false` | No | Server has more data after current `rows` |
|
|
82
|
+
| loadingMore | `boolean` | `false` | No | While an async `onLoadMore` is in progress |
|
|
83
|
+
| onLoadMore | `() => void \| Promise<void>` | — | No | Fetch next chunk when local slice is exhausted |
|
|
84
|
+
| scrollHeight | `number \| string` | `360` | No | Max height of the scroll viewport in infinite mode |
|
|
85
|
+
| fillWidth | `boolean` | `true` | No | When `true`, table is full container width; extra space is distributed by the browser’s automatic table layout (`table-layout: auto`) from cell content and `width` / `minWidth` / `maxWidth`. When `false`, table width follows content (`max-content`) |
|
|
86
|
+
| highlightRowOnHover | `boolean` | `true` | No | Row hover highlight |
|
|
87
|
+
| highlightColumnOnHover | `boolean` | `false` | No | Column hover highlight (header + cells) |
|
|
88
|
+
| striped | `boolean` | `false` | No | Alternating row backgrounds |
|
|
89
|
+
|
|
90
|
+
### `DataTableColumn<Row>`
|
|
91
|
+
|
|
92
|
+
| Field | Type | Default | Required | Description |
|
|
93
|
+
| --- | --- | --- | --- | --- |
|
|
94
|
+
| id | `string` | — | Yes | Column id (used for sort state and DOM data attributes) |
|
|
95
|
+
| header | `React.ReactNode` | — | Yes | Header content |
|
|
96
|
+
| accessor | `keyof Row \| ((row: Row) => unknown)` | — | No | Value for default cell text and sort (unless `sortAccessor` / `sortComparator` override) |
|
|
97
|
+
| cell | `(row: Row) => React.ReactNode` | — | No | Custom cell render |
|
|
98
|
+
| sortable | `boolean` | `false` | No | Header toggles sort on click |
|
|
99
|
+
| sortAccessor | `(row: Row) => unknown` | — | No | Value used for sorting (and default sort comparison) instead of `accessor` |
|
|
100
|
+
| sortComparator | `(a: Row, b: Row, order: DataTableOrder) => number` | — | No | Custom comparator; when set, default primitive compare is not used |
|
|
101
|
+
| align | `DataTableCellAlign` | `"start"` | No | `start`, `center`, or `end` |
|
|
102
|
+
| width | `string` | — | No | Column width on `th` / `td` (CSS `width`) |
|
|
103
|
+
| minWidth | `string` | — | No | Minimum column width on `th` / `td` |
|
|
104
|
+
| maxWidth | `string` | — | No | Maximum column width on `th` / `td` |
|
|
105
|
+
| onHeaderClick | `(event: React.MouseEvent<HTMLTableCellElement>) => void` | — | No | Fires on header click before sort handling |
|
|
106
|
+
| onCellClick | `(row: Row, event: React.MouseEvent<HTMLTableCellElement> \| React.KeyboardEvent<HTMLTableCellElement>) => void` | — | No | Makes the cell focusable and keyboard-activable |
|
|
107
|
+
|
|
108
|
+
Exported types: `DataTableSortState`, `DataTableOrder`, `DataTableSize`, `DataTableCellAlign`, `DataTableDividerStyle`, `DataTableRootProps`, `DataTableColumn`.
|
|
109
|
+
|
|
110
|
+
## Related
|
|
111
|
+
|
|
112
|
+
- [Pagination](../pagination/COMPONENT.md) — used under the table for page navigation.
|
|
113
|
+
- [LinkButton](../link-button/COMPONENT.md), [Badge](../badge/COMPONENT.md), [Tag](../tag/COMPONENT.md) — common cell content; they pick up size from the table’s `ControlSizeProvider` unless overridden.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Datepicker
|
|
2
|
+
|
|
3
|
+
**Проектирование по умолчанию:** при проектировании экранов и примеров изначально выбирай **`m`** для `size` (где есть ось размера), если явно не оговорено иное.
|
|
4
|
+
|
|
5
|
+
## About
|
|
6
|
+
|
|
7
|
+
Composite pieces for picking a calendar date or range: a size-aware shell, a day grid built on react-day-picker with kit styling, optional quick presets, optional time inputs, and a caption-sized text wrapper. Pass `locale` and formatting from **date-fns** (or compatible) so labels match your UI language.
|
|
8
|
+
|
|
9
|
+
- **When to use** — booking, scheduling, or any task where users choose one day or a from–to range from a calendar grid.
|
|
10
|
+
- **When to use** — filters and reports that pair the grid with quick presets and optional time fields in the same shell.
|
|
11
|
+
- **When to use** — forms that need a short caption (`Datepicker.Value`) tied to picker scale and tone.
|
|
12
|
+
- **When not to use** — free-text or partial dates (use a plain or masked [Input](../input/COMPONENT.md) instead).
|
|
13
|
+
- **When not to use** — always-visible full calendars as default page chrome; open the shell from a trigger in [Popover](../popover/COMPONENT.md), [Modal](../modal/COMPONENT.md), or [Drawer](../drawer/COMPONENT.md).
|
|
14
|
+
- **When not to use** — month- or year-only picking without days (use a slimmer control or native inputs).
|
|
15
|
+
|
|
16
|
+
## Composition
|
|
17
|
+
|
|
18
|
+
- **`Datepicker.Shell`** — Root wrapper: sets `DatepickerSize` context, owns `requestedMonth` / `requestMonth` for syncing the grid month when presets fire. Optional **`presets`** renders a bottom row after **`children`**.
|
|
19
|
+
- **`Datepicker.Calendar`** — Must live under `Shell` (directly or nested) so `size` context resolves. Forwards **react-day-picker** `DayPicker` props; kit adds `responsiveMonths`, `responsiveBreakpoints`, and `size`.
|
|
20
|
+
- **`Datepicker.Presets`** — Optional; usually passed as `Shell`’s `presets` prop. Calls `requestMonth` when a preset is chosen so the visible month follows the selection.
|
|
21
|
+
- **`Datepicker.Time`** — Optional; place as a child of `Shell` (e.g. under or beside `Calendar`). Single mode merges time into one `Date`; range mode uses `from` / `to` and separate change handlers.
|
|
22
|
+
- **`Datepicker.Value`** — Optional caption: `Typography.Root` with picker-scale typography; default `tone` is `muted`.
|
|
23
|
+
|
|
24
|
+
### Minimal example
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { enUS } from "date-fns/locale";
|
|
28
|
+
import { Datepicker } from "prime-ui-kit";
|
|
29
|
+
|
|
30
|
+
export function DatepickerMinimal() {
|
|
31
|
+
return (
|
|
32
|
+
<Datepicker.Shell>
|
|
33
|
+
<Datepicker.Calendar locale={enUS} mode="single" />
|
|
34
|
+
</Datepicker.Shell>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Rules
|
|
40
|
+
|
|
41
|
+
- Prefer **`Datepicker.Shell` inside [Popover](../popover/COMPONENT.md) `Content`** (often with `insetPadding="none"` on `Content`) opened from a trigger that shows the current value; the calendar is large and focus-heavy for inline page defaults.
|
|
42
|
+
- **Controlled vs uncontrolled** — Drive selection with **`selected`** and **`onSelect`** from react-day-picker (and optional **`month`** / **`onMonthChange`**) when the parent must own state; otherwise rely on day-picker internal state where types allow.
|
|
43
|
+
- **`responsiveMonths`** — When `true`, **`numberOfMonths` is ignored**; the kit measures the calendar viewport and switches between one and two columns using **`responsiveBreakpoints.twoColumns`** (default **500** px).
|
|
44
|
+
- **Presets** — Use **`mode="single"`** or **`mode="range"`** per instance; do not mix range presets with single calendar mode in one `Presets`. The **`title`** prop exists on the type but **is not rendered** in the component.
|
|
45
|
+
- **Time fields** — **`Datepicker.Time`** disables `input type="time"` until the anchor date exists (`value` in single mode; `from` / `to` in range mode). Default labels are Russian (**«Время»**, **«Начало»**, **«Конец»**); override via **`labels`**.
|
|
46
|
+
- **Accessibility** — Day grid roles and keyboard navigation come from react-day-picker; month nav uses [Button](../button/COMPONENT.md) with English **`aria-label`** strings in the kit—replace via **`components`** / **`classNames`** on `Calendar` if your product language differs. Ensure the popover trigger has an accessible name. Time row uses **`useId`**-scoped labels on [Input](../input/COMPONENT.md).
|
|
47
|
+
- **Styling and layout** — The module imports **`react-day-picker/style.css`**. **`responsiveMonths`** depends on container width; in tight flex layouts without **`min-width: 0`**, width can clip—check popover and grid CSS.
|
|
48
|
+
- **Time zones** — Behavior follows local `Date` instances and how the browser shows **`type="time"`**; UTC shifts are the app’s responsibility.
|
|
49
|
+
|
|
50
|
+
## API
|
|
51
|
+
|
|
52
|
+
### Datepicker.Calendar
|
|
53
|
+
|
|
54
|
+
| Prop | Type | Default | Required | Description |
|
|
55
|
+
|------|------|---------|----------|-------------|
|
|
56
|
+
| size | `"s" \| "m" \| "l" \| "xl"` | from `Shell` context, else `m` | No | Cell typography, nav buttons, and control scale. |
|
|
57
|
+
| responsiveMonths | `boolean` | `false` | No | If `true`, `numberOfMonths` is ignored; column count follows viewport width. |
|
|
58
|
+
| responsiveBreakpoints | `{ twoColumns: number }` | `{ twoColumns: 500 }` | No | Pixel width at which the layout uses two month columns. |
|
|
59
|
+
| weekStartsOn | `0`–`6` | `1` | No | First weekday column (0 = Sunday). |
|
|
60
|
+
| navLayout | `DayPicker` nav layout | `"after"` | No | Month navigation placement (react-day-picker). |
|
|
61
|
+
| month | `Date` | — | No | Displayed month (controlled when set). |
|
|
62
|
+
| onMonthChange | `(d: Date) => void` | — | No | Month changes; also notifies `Shell` month context. |
|
|
63
|
+
| numberOfMonths | `number` | `1` | No | Fixed month count when `responsiveMonths` is not `true`. |
|
|
64
|
+
| classNames, components, style | `DayPicker` props | — | No | Merged with kit defaults; custom `components` extend kit chevron and month caption. |
|
|
65
|
+
| mode, selected, onSelect, disabled, locale, … | `DayPickerProps` | — | Varies | Other react-day-picker props are forwarded to `DayPicker`. |
|
|
66
|
+
|
|
67
|
+
### Datepicker.Shell
|
|
68
|
+
|
|
69
|
+
| Prop | Type | Default | Required | Description |
|
|
70
|
+
|------|------|---------|----------|-------------|
|
|
71
|
+
| size | `"s" \| "m" \| "l" \| "xl"` | `m` | No | Size context for `Calendar`, `Presets`, `Time`, and `Value`. |
|
|
72
|
+
| presets | `ReactNode` | — | No | Bottom bar (commonly `Datepicker.Presets`). |
|
|
73
|
+
| children | `ReactNode` | — | Yes | Main panel content (`Calendar`, `Time`, `Value`, etc.). |
|
|
74
|
+
| className | `string` | — | No | Root element class. |
|
|
75
|
+
|
|
76
|
+
### Datepicker.Presets
|
|
77
|
+
|
|
78
|
+
| Prop | Type | Default | Required | Description |
|
|
79
|
+
|------|------|---------|----------|-------------|
|
|
80
|
+
| mode | `"single" \| "range"` | — | Yes | Selects preset shape and `onSelect` signature. |
|
|
81
|
+
| presets | `DatepickerPresetSingle[]` or `DatepickerPresetRange[]` | — | Yes | Quick actions; single items use `{ label, date }`, range items use `{ label, range }`. |
|
|
82
|
+
| onSelect | `(date: Date \| undefined) => void` or `(range: DateRange \| undefined) => void` | — | Yes | Invoked when a preset button is pressed; updates shell month from the preset anchor. |
|
|
83
|
+
| size | `"s" \| "m" \| "l" \| "xl"` | from context | No | [ButtonGroup](../button-group/COMPONENT.md) segment size. |
|
|
84
|
+
| className | `string` | — | No | Block wrapper class. |
|
|
85
|
+
| title | `string` | — | No | Present in types only; not rendered. |
|
|
86
|
+
|
|
87
|
+
### Datepicker.Time
|
|
88
|
+
|
|
89
|
+
**Single** (default — `mode` omitted or `"single"`)
|
|
90
|
+
|
|
91
|
+
| Prop | Type | Default | Required | Description |
|
|
92
|
+
|------|------|---------|----------|-------------|
|
|
93
|
+
| value | `Date \| undefined` | — | Yes | Anchor date; time field disabled when unset. |
|
|
94
|
+
| onChange | `(next: Date) => void` | — | Yes | Called with date merged from `HH:mm` input. |
|
|
95
|
+
| labels | `{ time?: string }` | — | No | Overrides default time label. |
|
|
96
|
+
| size | `"s" \| "m" \| "l" \| "xl"` | from context | No | Input size. |
|
|
97
|
+
|
|
98
|
+
**Range** (`mode="range"`)
|
|
99
|
+
|
|
100
|
+
| Prop | Type | Default | Required | Description |
|
|
101
|
+
|------|------|---------|----------|-------------|
|
|
102
|
+
| mode | `"range"` | — | Yes | Enables two time fields. |
|
|
103
|
+
| from | `Date \| undefined` | — | Yes | Start date; start time disabled when unset. |
|
|
104
|
+
| to | `Date \| undefined` | — | Yes | End date; end time disabled when unset. |
|
|
105
|
+
| onFromChange | `(next: Date) => void` | — | Yes | Merges time into `from`. |
|
|
106
|
+
| onToChange | `(next: Date) => void` | — | Yes | Merges time into `to`. |
|
|
107
|
+
| labels | `{ from?: string; to?: string }` | — | No | Overrides default range labels. |
|
|
108
|
+
| size | `"s" \| "m" \| "l" \| "xl"` | from context | No | Input size. |
|
|
109
|
+
|
|
110
|
+
### Datepicker.Value
|
|
111
|
+
|
|
112
|
+
| Prop | Type | Default | Required | Description |
|
|
113
|
+
|------|------|---------|----------|-------------|
|
|
114
|
+
| size | `"s" \| "m" \| "l" \| "xl"` | from context | No | Масштаб пикера; внутри маппится на [Typography](../typography/COMPONENT.md) `variant`. |
|
|
115
|
+
| tone | `Typography` tone | `muted` | No | Передаётся в `Typography.Root`. |
|
|
116
|
+
| as, weight, tracking, italic, children, className, … | `Omit<TypographyRootProps, "variant">` | — | No | Как у `Typography.Root`, но кегль задаётся через `size` пикера (см. выше). |
|
|
117
|
+
|
|
118
|
+
### Utilities
|
|
119
|
+
|
|
120
|
+
| Name | Signature | Description |
|
|
121
|
+
|------|-----------|-------------|
|
|
122
|
+
| `formatTimeInputValue` | `(date?: Date) => string` | `HH:mm` for `input type="time"` `value`. |
|
|
123
|
+
| `mergeTimeIntoDate` | `(date: Date, timeHHmm: string) => Date` | New `Date` with hours and minutes from the string. |
|
|
124
|
+
|
|
125
|
+
### Exported types
|
|
126
|
+
|
|
127
|
+
`DatepickerCalendarProps`, `DatepickerShellProps`, `DatepickerPresetsProps`, `DatepickerTimeProps`, `DatepickerTimeSingleProps`, `DatepickerTimeRangeProps`, `DatepickerValueProps`, `DatepickerSize`, `DatepickerPresetSingle`, `DatepickerPresetRange`, and **`DateRange`** (re-exported from react-day-picker) are exported from the package alongside the component and utilities.
|
|
128
|
+
|
|
129
|
+
## Related
|
|
130
|
+
|
|
131
|
+
- [Popover](../popover/COMPONENT.md)
|
|
132
|
+
- [Button](../button/COMPONENT.md)
|
|
133
|
+
- [ButtonGroup](../button-group/COMPONENT.md)
|
|
134
|
+
- [Input](../input/COMPONENT.md)
|
|
135
|
+
- [Typography](../typography/COMPONENT.md)
|
|
136
|
+
- [Modal](../modal/COMPONENT.md)
|
|
137
|
+
- [Drawer](../drawer/COMPONENT.md)
|