@konce-pt/react 0.8.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.
Files changed (245) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +58 -0
  3. package/dist/accordion/accordion.d.ts +45 -0
  4. package/dist/accordion/accordion.js +69 -0
  5. package/dist/alert/alert.d.ts +25 -0
  6. package/dist/alert/alert.js +31 -0
  7. package/dist/app-shell/app-shell.d.ts +94 -0
  8. package/dist/app-shell/app-shell.js +105 -0
  9. package/dist/auth/auth-types.d.ts +44 -0
  10. package/dist/auth/auth-types.js +2 -0
  11. package/dist/auth/auth.d.ts +76 -0
  12. package/dist/auth/auth.js +184 -0
  13. package/dist/autocomplete/autocomplete.d.ts +18 -0
  14. package/dist/autocomplete/autocomplete.js +72 -0
  15. package/dist/avatar/avatar.d.ts +33 -0
  16. package/dist/avatar/avatar.js +30 -0
  17. package/dist/avatar-group/avatar-group.d.ts +21 -0
  18. package/dist/avatar-group/avatar-group.js +15 -0
  19. package/dist/badge/badge.d.ts +25 -0
  20. package/dist/badge/badge.js +14 -0
  21. package/dist/bottom-sheet/bottom-sheet.d.ts +21 -0
  22. package/dist/bottom-sheet/bottom-sheet.js +22 -0
  23. package/dist/breadcrumb/breadcrumb.d.ts +19 -0
  24. package/dist/breadcrumb/breadcrumb.js +20 -0
  25. package/dist/button/button.d.ts +27 -0
  26. package/dist/button/button.js +49 -0
  27. package/dist/button-group/button-group.d.ts +25 -0
  28. package/dist/button-group/button-group.js +30 -0
  29. package/dist/card/card.d.ts +66 -0
  30. package/dist/card/card.js +96 -0
  31. package/dist/carousel/carousel.d.ts +20 -0
  32. package/dist/carousel/carousel.js +24 -0
  33. package/dist/charts/chart-legend.d.ts +23 -0
  34. package/dist/charts/chart-legend.js +9 -0
  35. package/dist/charts/chart-tooltip.d.ts +21 -0
  36. package/dist/charts/chart-tooltip.js +13 -0
  37. package/dist/charts/chart.d.ts +18 -0
  38. package/dist/charts/chart.js +231 -0
  39. package/dist/charts-entry/public-api.d.ts +4 -0
  40. package/dist/charts-entry/public-api.js +7 -0
  41. package/dist/checkbox/checkbox.d.ts +33 -0
  42. package/dist/checkbox/checkbox.js +29 -0
  43. package/dist/chip/chip.d.ts +22 -0
  44. package/dist/chip/chip.js +16 -0
  45. package/dist/chips-input/chips-input.d.ts +25 -0
  46. package/dist/chips-input/chips-input.js +54 -0
  47. package/dist/clock/clock.d.ts +17 -0
  48. package/dist/clock/clock.js +57 -0
  49. package/dist/color-picker/color-picker.d.ts +23 -0
  50. package/dist/color-picker/color-picker.js +28 -0
  51. package/dist/confirm/confirm-container.d.ts +13 -0
  52. package/dist/confirm/confirm-container.js +26 -0
  53. package/dist/confirm/confirm-store.d.ts +29 -0
  54. package/dist/confirm/confirm-store.js +52 -0
  55. package/dist/context-menu/context-menu.d.ts +21 -0
  56. package/dist/context-menu/context-menu.js +36 -0
  57. package/dist/data-table/data-table-types.d.ts +67 -0
  58. package/dist/data-table/data-table-types.js +1 -0
  59. package/dist/data-table/data-table.d.ts +62 -0
  60. package/dist/data-table/data-table.js +453 -0
  61. package/dist/data-table/export-csv.d.ts +7 -0
  62. package/dist/data-table/export-csv.js +19 -0
  63. package/dist/data-view/data-view.d.ts +21 -0
  64. package/dist/data-view/data-view.js +25 -0
  65. package/dist/date-range/date-range.d.ts +30 -0
  66. package/dist/date-range/date-range.js +155 -0
  67. package/dist/datepicker/datepicker.d.ts +39 -0
  68. package/dist/datepicker/datepicker.js +202 -0
  69. package/dist/dialog/dialog.d.ts +35 -0
  70. package/dist/dialog/dialog.js +59 -0
  71. package/dist/divider/divider.d.ts +16 -0
  72. package/dist/divider/divider.js +13 -0
  73. package/dist/drawer/drawer.d.ts +25 -0
  74. package/dist/drawer/drawer.js +25 -0
  75. package/dist/empty/empty.d.ts +18 -0
  76. package/dist/empty/empty.js +14 -0
  77. package/dist/fab/fab.d.ts +22 -0
  78. package/dist/fab/fab.js +17 -0
  79. package/dist/fieldset/fieldset.d.ts +22 -0
  80. package/dist/fieldset/fieldset.js +24 -0
  81. package/dist/file-upload/file-upload.d.ts +22 -0
  82. package/dist/file-upload/file-upload.js +50 -0
  83. package/dist/form-field/form-field-context.d.ts +23 -0
  84. package/dist/form-field/form-field-context.js +17 -0
  85. package/dist/form-field/form-field.d.ts +39 -0
  86. package/dist/form-field/form-field.js +41 -0
  87. package/dist/galleria/galleria.d.ts +22 -0
  88. package/dist/galleria/galleria.js +21 -0
  89. package/dist/grid/col.d.ts +39 -0
  90. package/dist/grid/col.js +32 -0
  91. package/dist/grid/flex.d.ts +45 -0
  92. package/dist/grid/flex.js +35 -0
  93. package/dist/grid/grid.d.ts +47 -0
  94. package/dist/grid/grid.js +38 -0
  95. package/dist/grid/layout.d.ts +18 -0
  96. package/dist/grid/layout.js +32 -0
  97. package/dist/grid-entry/public-api.d.ts +6 -0
  98. package/dist/grid-entry/public-api.js +8 -0
  99. package/dist/i18n/i18n-context.d.ts +45 -0
  100. package/dist/i18n/i18n-context.js +65 -0
  101. package/dist/icon/icon-registry.d.ts +16 -0
  102. package/dist/icon/icon-registry.js +43 -0
  103. package/dist/icon/icon.d.ts +17 -0
  104. package/dist/icon/icon.js +23 -0
  105. package/dist/icon-button/icon-button.d.ts +23 -0
  106. package/dist/icon-button/icon-button.js +14 -0
  107. package/dist/icons-entry/public-api.d.ts +12 -0
  108. package/dist/icons-entry/public-api.js +20 -0
  109. package/dist/image/image.d.ts +17 -0
  110. package/dist/image/image.js +16 -0
  111. package/dist/input/input.d.ts +41 -0
  112. package/dist/input/input.js +36 -0
  113. package/dist/input-mask/input-mask.d.ts +19 -0
  114. package/dist/input-mask/input-mask.js +65 -0
  115. package/dist/input-number/input-number.d.ts +28 -0
  116. package/dist/input-number/input-number.js +52 -0
  117. package/dist/input-otp/input-otp.d.ts +21 -0
  118. package/dist/input-otp/input-otp.js +59 -0
  119. package/dist/internal/cn.d.ts +9 -0
  120. package/dist/internal/cn.js +19 -0
  121. package/dist/internal/compose-refs.d.ts +6 -0
  122. package/dist/internal/compose-refs.js +16 -0
  123. package/dist/internal/overlay-container.d.ts +3 -0
  124. package/dist/internal/overlay-container.js +19 -0
  125. package/dist/internal/overlay.d.ts +26 -0
  126. package/dist/internal/overlay.js +64 -0
  127. package/dist/internal/slot.d.ts +23 -0
  128. package/dist/internal/slot.js +49 -0
  129. package/dist/internal/types.d.ts +25 -0
  130. package/dist/internal/types.js +1 -0
  131. package/dist/internal/use-breakpoint.d.ts +18 -0
  132. package/dist/internal/use-breakpoint.js +52 -0
  133. package/dist/internal/use-controllable-state.d.ts +11 -0
  134. package/dist/internal/use-controllable-state.js +18 -0
  135. package/dist/internal/use-id.d.ts +9 -0
  136. package/dist/internal/use-id.js +13 -0
  137. package/dist/knob/knob.d.ts +27 -0
  138. package/dist/knob/knob.js +86 -0
  139. package/dist/listbox/listbox.d.ts +28 -0
  140. package/dist/listbox/listbox.js +43 -0
  141. package/dist/map/map-create-dialog.d.ts +21 -0
  142. package/dist/map/map-create-dialog.js +196 -0
  143. package/dist/map/map-hours-field.d.ts +22 -0
  144. package/dist/map/map-hours-field.js +90 -0
  145. package/dist/map/map-image-field.d.ts +24 -0
  146. package/dist/map/map-image-field.js +61 -0
  147. package/dist/map/map-legend.d.ts +29 -0
  148. package/dist/map/map-legend.js +41 -0
  149. package/dist/map/map-poi-card.d.ts +42 -0
  150. package/dist/map/map-poi-card.js +152 -0
  151. package/dist/map/map-search.d.ts +37 -0
  152. package/dist/map/map-search.js +201 -0
  153. package/dist/map/map.d.ts +113 -0
  154. package/dist/map/map.js +425 -0
  155. package/dist/map/ports.d.ts +76 -0
  156. package/dist/map/ports.js +174 -0
  157. package/dist/map-entry/public-api.d.ts +20 -0
  158. package/dist/map-entry/public-api.js +19 -0
  159. package/dist/megamenu/megamenu.d.ts +17 -0
  160. package/dist/megamenu/megamenu.js +28 -0
  161. package/dist/menu/menu-item.d.ts +33 -0
  162. package/dist/menu/menu-item.js +1 -0
  163. package/dist/menu/menu-rows.d.ts +9 -0
  164. package/dist/menu/menu-rows.js +15 -0
  165. package/dist/menu/menu.d.ts +22 -0
  166. package/dist/menu/menu.js +31 -0
  167. package/dist/menubar/menubar.d.ts +16 -0
  168. package/dist/menubar/menubar.js +39 -0
  169. package/dist/meter-group/meter-group.d.ts +20 -0
  170. package/dist/meter-group/meter-group.js +24 -0
  171. package/dist/order-list/order-list.d.ts +18 -0
  172. package/dist/order-list/order-list.js +37 -0
  173. package/dist/paginator/paginator.d.ts +29 -0
  174. package/dist/paginator/paginator.js +45 -0
  175. package/dist/panel/panel.d.ts +31 -0
  176. package/dist/panel/panel.js +36 -0
  177. package/dist/password/password.d.ts +28 -0
  178. package/dist/password/password.js +37 -0
  179. package/dist/pick-list/pick-list.d.ts +28 -0
  180. package/dist/pick-list/pick-list.js +65 -0
  181. package/dist/popover/popover.d.ts +23 -0
  182. package/dist/popover/popover.js +27 -0
  183. package/dist/progress/progress.d.ts +19 -0
  184. package/dist/progress/progress.js +21 -0
  185. package/dist/public-api.d.ts +181 -0
  186. package/dist/public-api.js +105 -0
  187. package/dist/radio-group/radio-group.d.ts +24 -0
  188. package/dist/radio-group/radio-group.js +23 -0
  189. package/dist/rating/rating.d.ts +22 -0
  190. package/dist/rating/rating.js +30 -0
  191. package/dist/rich-text/lists.d.ts +17 -0
  192. package/dist/rich-text/lists.js +144 -0
  193. package/dist/rich-text/rich-text.d.ts +28 -0
  194. package/dist/rich-text/rich-text.js +654 -0
  195. package/dist/rich-text/sanitize.d.ts +10 -0
  196. package/dist/rich-text/sanitize.js +85 -0
  197. package/dist/rich-text/tables.d.ts +44 -0
  198. package/dist/rich-text/tables.js +268 -0
  199. package/dist/roadmap/roadmap.d.ts +37 -0
  200. package/dist/roadmap/roadmap.js +271 -0
  201. package/dist/roadmap-entry/public-api.d.ts +4 -0
  202. package/dist/roadmap-entry/public-api.js +7 -0
  203. package/dist/scroll-top/scroll-top.d.ts +16 -0
  204. package/dist/scroll-top/scroll-top.js +38 -0
  205. package/dist/select/select.d.ts +37 -0
  206. package/dist/select/select.js +117 -0
  207. package/dist/shared/types.d.ts +8 -0
  208. package/dist/shared/types.js +1 -0
  209. package/dist/sidenav/sidenav.d.ts +26 -0
  210. package/dist/sidenav/sidenav.js +41 -0
  211. package/dist/skeleton/skeleton.d.ts +20 -0
  212. package/dist/skeleton/skeleton.js +15 -0
  213. package/dist/slider/slider.d.ts +28 -0
  214. package/dist/slider/slider.js +30 -0
  215. package/dist/speed-dial/speed-dial.d.ts +20 -0
  216. package/dist/speed-dial/speed-dial.js +23 -0
  217. package/dist/spinner/spinner.d.ts +15 -0
  218. package/dist/spinner/spinner.js +14 -0
  219. package/dist/split-button/split-button.d.ts +28 -0
  220. package/dist/split-button/split-button.js +34 -0
  221. package/dist/splitter/splitter.d.ts +39 -0
  222. package/dist/splitter/splitter.js +80 -0
  223. package/dist/stepper/stepper.d.ts +51 -0
  224. package/dist/stepper/stepper.js +71 -0
  225. package/dist/switch/switch.d.ts +39 -0
  226. package/dist/switch/switch.js +30 -0
  227. package/dist/switch-group/switch-group.d.ts +29 -0
  228. package/dist/switch-group/switch-group.js +47 -0
  229. package/dist/tabs/tabs.d.ts +38 -0
  230. package/dist/tabs/tabs.js +74 -0
  231. package/dist/textarea/textarea.d.ts +28 -0
  232. package/dist/textarea/textarea.js +44 -0
  233. package/dist/timeline/timeline.d.ts +19 -0
  234. package/dist/timeline/timeline.js +12 -0
  235. package/dist/toast/toast-container.d.ts +12 -0
  236. package/dist/toast/toast-container.js +23 -0
  237. package/dist/toast/toast-store.d.ts +26 -0
  238. package/dist/toast/toast-store.js +51 -0
  239. package/dist/toolbar/toolbar.d.ts +29 -0
  240. package/dist/toolbar/toolbar.js +24 -0
  241. package/dist/tooltip/tooltip.d.ts +26 -0
  242. package/dist/tooltip/tooltip.js +113 -0
  243. package/dist/tree/tree.d.ts +31 -0
  244. package/dist/tree/tree.js +62 -0
  245. package/package.json +91 -0
@@ -0,0 +1,28 @@
1
+ import type { ComponentPropsWithRef } from 'react';
2
+ /** Wartość suwaka: pojedyncza liczba albo para `[min, max]` w trybie `range`. */
3
+ export type KptSliderValue = number | [number, number];
4
+ export interface KptSliderProps extends Omit<ComponentPropsWithRef<'div'>, 'onChange' | 'defaultValue'> {
5
+ value?: KptSliderValue;
6
+ defaultValue?: KptSliderValue;
7
+ onValueChange?: (value: KptSliderValue) => void;
8
+ /** Tryb zakresu: dwa uchwyty, wartość jako para `[min, max]`. */
9
+ range?: boolean;
10
+ min?: number;
11
+ max?: number;
12
+ step?: number;
13
+ /** Pokazuje bieżącą wartość obok suwaka. */
14
+ showValue?: boolean;
15
+ disabled?: boolean;
16
+ onTouch?: () => void;
17
+ }
18
+ /**
19
+ * Suwak wartości. W trybie `range` udostępnia dwa uchwyty, a wartością jest para `[min, max]`.
20
+ *
21
+ * Oba uchwyty to natywne `<input type="range">` leżące na sobie — dzięki temu klawiatura,
22
+ * gesty dotykowe i czytniki ekranu działają bez ani jednej linii własnej obsługi.
23
+ *
24
+ * @example
25
+ * <KptSlider value={volume} onValueChange={setVolume} min={0} max={100} step={5} showValue />
26
+ * <KptSlider range value={range} onValueChange={setRange} showValue />
27
+ */
28
+ export declare function KptSlider({ value, defaultValue, onValueChange, range, min, max, step, showValue, disabled, onTouch, className, ...rest }: Readonly<KptSliderProps>): import("react").JSX.Element;
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { cn } from "../internal/cn.js";
3
+ import { useControllableState } from "../internal/use-controllable-state.js";
4
+ /**
5
+ * Suwak wartości. W trybie `range` udostępnia dwa uchwyty, a wartością jest para `[min, max]`.
6
+ *
7
+ * Oba uchwyty to natywne `<input type="range">` leżące na sobie — dzięki temu klawiatura,
8
+ * gesty dotykowe i czytniki ekranu działają bez ani jednej linii własnej obsługi.
9
+ *
10
+ * @example
11
+ * <KptSlider value={volume} onValueChange={setVolume} min={0} max={100} step={5} showValue />
12
+ * <KptSlider range value={range} onValueChange={setRange} showValue />
13
+ */
14
+ export function KptSlider({ value, defaultValue, onValueChange, range = false, min = 0, max = 100, step = 1, showValue = false, disabled = false, onTouch, className, ...rest }) {
15
+ const [current, setCurrent] = useControllableState({
16
+ value,
17
+ defaultValue: defaultValue ?? (range ? [min, max] : 0),
18
+ onChange: onValueChange,
19
+ });
20
+ const [low, high] = Array.isArray(current) ? [current[0], current[1]] : [min, current];
21
+ const single = Array.isArray(current) ? current[1] : current;
22
+ const pct = (val) => {
23
+ const span = max - min;
24
+ return span <= 0 ? 0 : ((val - min) / span) * 100;
25
+ };
26
+ // Uchwyty nie mogą się wyminąć — dolny nie przekracza górnego i odwrotnie.
27
+ const setLow = (next) => setCurrent([Math.min(next, high), high]);
28
+ const setHigh = (next) => setCurrent([low, Math.max(next, low)]);
29
+ return (_jsx("div", { className: cn('kpt-slider-host', className), ...rest, children: range ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "kpt-slider__range", children: [_jsx("div", { className: "kpt-slider__rail" }), _jsx("div", { className: "kpt-slider__fill", style: { left: `${pct(low)}%`, right: `${100 - pct(high)}%` } }), _jsx("input", { className: "kpt-slider__thumb kpt-slider__thumb--low", type: "range", min: min, max: max, step: step, value: low, disabled: disabled, "aria-label": "Minimum", onChange: (event) => setLow(Number(event.target.value)), onBlur: () => onTouch?.() }), _jsx("input", { className: "kpt-slider__thumb kpt-slider__thumb--high", type: "range", min: min, max: max, step: step, value: high, disabled: disabled, "aria-label": "Maksimum", onChange: (event) => setHigh(Number(event.target.value)), onBlur: () => onTouch?.() })] }), showValue ? (_jsxs("span", { className: "kpt-slider__value", children: [low, "\u2013", high] })) : null] })) : (_jsxs(_Fragment, { children: [_jsx("input", { className: "kpt-slider__input", type: "range", min: min, max: max, step: step, value: single, disabled: disabled, style: { ['--_pct']: `${pct(single)}%` }, onChange: (event) => setCurrent(Number(event.target.value)), onBlur: () => onTouch?.() }), showValue ? _jsx("span", { className: "kpt-slider__value", children: single }) : null] })) }));
30
+ }
@@ -0,0 +1,20 @@
1
+ import { type ComponentPropsWithRef } from 'react';
2
+ import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
3
+ import type { KptMenuItem } from '../menu/menu-item.ts';
4
+ export type KptSpeedDialDirection = 'up' | 'down' | 'left' | 'right';
5
+ export interface KptSpeedDialProps<T> extends Omit<ComponentPropsWithRef<'div'>, 'onSelect'>, KptI18nOverrides {
6
+ items?: KptMenuItem<T>[];
7
+ direction?: KptSpeedDialDirection;
8
+ /** Ikona głównego przycisku; SCSS obraca ją o 45° po otwarciu. */
9
+ icon?: string;
10
+ /** Etykieta a11y głównego przycisku w stanie zamkniętym. */
11
+ ariaLabel?: string;
12
+ onSelect?: (item: KptMenuItem<T>) => void;
13
+ }
14
+ /**
15
+ * Speed dial — FAB rozwijający zestaw akcji wachlarzem. Buduje na `KptFab`.
16
+ *
17
+ * @example
18
+ * <KptSpeedDial items={actions} direction="up" onSelect={onAction} />
19
+ */
20
+ export declare function KptSpeedDial<T>({ items, direction, icon, ariaLabel, onSelect, locale, dictionary, className, ...rest }: Readonly<KptSpeedDialProps<T>>): import("react").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { cn } from "../internal/cn.js";
4
+ import { useKptMessages } from "../i18n/i18n-context.js";
5
+ import { KptFab } from "../fab/fab.js";
6
+ import { KptIcon } from "../icon/icon.js";
7
+ /**
8
+ * Speed dial — FAB rozwijający zestaw akcji wachlarzem. Buduje na `KptFab`.
9
+ *
10
+ * @example
11
+ * <KptSpeedDial items={actions} direction="up" onSelect={onAction} />
12
+ */
13
+ export function KptSpeedDial({ items = [], direction = 'up', icon = 'plus', ariaLabel, onSelect, locale, dictionary, className, ...rest }) {
14
+ const { t } = useKptMessages({ locale, dictionary });
15
+ const [open, setOpen] = useState(false);
16
+ const pick = (item) => {
17
+ if (item.disabled)
18
+ return;
19
+ onSelect?.(item);
20
+ setOpen(false);
21
+ };
22
+ return (_jsxs("div", { className: cn('kpt-speed-dial-host', className), ...rest, children: [_jsxs("div", { className: cn('kpt-speed-dial', open && 'is-open'), "data-direction": direction, children: [_jsx("div", { className: "kpt-speed-dial__actions", children: items.map((item, index) => (_jsxs("button", { type: "button", className: "kpt-speed-dial__action", disabled: item.disabled, "aria-label": item.label, onClick: () => pick(item), children: [item.icon ? _jsx(KptIcon, { name: item.icon }) : null, item.label ? _jsx("span", { className: "kpt-speed-dial__label", children: item.label }) : null] }, index))) }), _jsx(KptFab, { "aria-label": open ? t('common.close') : (ariaLabel ?? t('speedDial.actions')), onClick: () => setOpen(!open), children: _jsx("span", { className: "kpt-speed-dial__trigger-icon", children: _jsx(KptIcon, { name: icon }) }) })] }), open ? _jsx("div", { className: "kpt-speed-dial__backdrop", onClick: () => setOpen(false) }) : null] }));
23
+ }
@@ -0,0 +1,15 @@
1
+ import type { ComponentPropsWithRef } from 'react';
2
+ import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
3
+ export interface KptSpinnerProps extends Omit<ComponentPropsWithRef<'span'>, 'children'>, KptI18nOverrides {
4
+ size?: string;
5
+ /** Etykieta dostępności; pominięta = `spinner.label` ze słownika. */
6
+ label?: string;
7
+ }
8
+ /**
9
+ * Wskaźnik ładowania. Kolor bierze z `currentColor`, więc dopasowuje się do treści wokół.
10
+ *
11
+ * @example
12
+ * <KptSpinner />
13
+ * <KptSpinner size="2rem" label="Wczytywanie danych" />
14
+ */
15
+ export declare function KptSpinner({ size, label, locale, dictionary, className, ...rest }: Readonly<KptSpinnerProps>): import("react").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "../internal/cn.js";
3
+ import { useKptMessages } from "../i18n/i18n-context.js";
4
+ /**
5
+ * Wskaźnik ładowania. Kolor bierze z `currentColor`, więc dopasowuje się do treści wokół.
6
+ *
7
+ * @example
8
+ * <KptSpinner />
9
+ * <KptSpinner size="2rem" label="Wczytywanie danych" />
10
+ */
11
+ export function KptSpinner({ size = '1.5rem', label, locale, dictionary, className, ...rest }) {
12
+ const { t } = useKptMessages({ locale, dictionary });
13
+ return (_jsx("span", { className: cn('kpt-spinner-host', className), ...rest, children: _jsx("span", { className: "kpt-spinner", role: "status", "aria-label": label ?? t('spinner.label'), style: { width: size, height: size } }) }));
14
+ }
@@ -0,0 +1,28 @@
1
+ import { type ComponentPropsWithRef, type ReactNode } from 'react';
2
+ import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
3
+ import type { KptMenuItem } from '../menu/menu-item.ts';
4
+ import type { KptButtonVariant } from '../button/button.tsx';
5
+ export interface KptSplitButtonProps<T> extends Omit<ComponentPropsWithRef<'span'>, 'onSelect'>, KptI18nOverrides {
6
+ variant?: KptButtonVariant;
7
+ items?: KptMenuItem<T>[];
8
+ disabled?: boolean;
9
+ /** Kliknięcie akcji głównej. */
10
+ onPrimaryClick?: () => void;
11
+ /** Wybór pozycji z menu. */
12
+ onSelect?: (item: KptMenuItem<T>) => void;
13
+ open?: boolean;
14
+ defaultOpen?: boolean;
15
+ onOpenChange?: (open: boolean) => void;
16
+ /** Treść akcji głównej. */
17
+ children?: ReactNode;
18
+ }
19
+ /**
20
+ * Przycisk dzielony — akcja główna plus rozwijane menu dodatkowych akcji.
21
+ *
22
+ * Panel wyrównuje się do PRAWEJ krawędzi przycisku, nie do lewej: rozwijacz siedzi po prawej
23
+ * stronie kontrolki, więc menu otwierające się w lewo nie wychodzi poza nią.
24
+ *
25
+ * @example
26
+ * <KptSplitButton items={items} onPrimaryClick={save} onSelect={onItem}>Zapisz</KptSplitButton>
27
+ */
28
+ export declare function KptSplitButton<T>({ variant, items, disabled, onPrimaryClick, onSelect, open, defaultOpen, onOpenChange, locale, dictionary, className, children, ...rest }: Readonly<KptSplitButtonProps<T>>): import("react").JSX.Element;
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useRef } from 'react';
3
+ import { cn } from "../internal/cn.js";
4
+ import { KptOverlay } from "../internal/overlay.js";
5
+ import { useControllableState } from "../internal/use-controllable-state.js";
6
+ import { useKptMessages } from "../i18n/i18n-context.js";
7
+ import { KptIcon } from "../icon/icon.js";
8
+ import { MenuRows } from "../menu/menu-rows.js";
9
+ /**
10
+ * Przycisk dzielony — akcja główna plus rozwijane menu dodatkowych akcji.
11
+ *
12
+ * Panel wyrównuje się do PRAWEJ krawędzi przycisku, nie do lewej: rozwijacz siedzi po prawej
13
+ * stronie kontrolki, więc menu otwierające się w lewo nie wychodzi poza nią.
14
+ *
15
+ * @example
16
+ * <KptSplitButton items={items} onPrimaryClick={save} onSelect={onItem}>Zapisz</KptSplitButton>
17
+ */
18
+ export function KptSplitButton({ variant = 'filled', items = [], disabled = false, onPrimaryClick, onSelect, open, defaultOpen = false, onOpenChange, locale, dictionary, className, children, ...rest }) {
19
+ const { t } = useKptMessages({ locale, dictionary });
20
+ const toggleRef = useRef(null);
21
+ const [isOpen, setOpen] = useControllableState({
22
+ value: open,
23
+ defaultValue: defaultOpen,
24
+ onChange: onOpenChange,
25
+ });
26
+ const close = useCallback(() => setOpen(false), [setOpen]);
27
+ const pick = (item) => {
28
+ if (item.disabled)
29
+ return;
30
+ onSelect?.(item);
31
+ close();
32
+ };
33
+ return (_jsxs("span", { className: cn('kpt-split-button-host', className), ...rest, children: [_jsxs("div", { className: "kpt-split-button", "data-variant": variant, children: [_jsx("button", { className: "kpt-split-button__main", type: "button", disabled: disabled, onClick: onPrimaryClick, children: children }), _jsx("button", { ref: toggleRef, className: "kpt-split-button__toggle", type: "button", disabled: disabled, onClick: () => setOpen(!isOpen), "aria-label": t('splitButton.more'), children: _jsx(KptIcon, { name: "chevron-down" }) })] }), _jsx(KptOverlay, { open: isOpen, anchor: toggleRef.current, onClose: close, align: "end", children: _jsx("div", { className: "kpt-split-button__panel", role: "menu", children: _jsx(MenuRows, { items: items, block: "kpt-split-button", onPick: pick }) }) })] }));
34
+ }
@@ -0,0 +1,39 @@
1
+ import { type ComponentPropsWithRef, type ReactNode } from 'react';
2
+ export type KptSplitterOrientation = 'horizontal' | 'vertical';
3
+ export interface KptSplitterPaneProps {
4
+ children?: ReactNode;
5
+ }
6
+ /** Panel splittera. Umieszczaj jako `<KptSplitter.Start>` i `<KptSplitter.End>`. */
7
+ export declare function KptSplitterStart(_props: Readonly<KptSplitterPaneProps>): ReactNode;
8
+ export declare namespace KptSplitterStart {
9
+ var kptSplitterSlot: "start";
10
+ }
11
+ export declare function KptSplitterEnd(_props: Readonly<KptSplitterPaneProps>): ReactNode;
12
+ export declare namespace KptSplitterEnd {
13
+ var kptSplitterSlot: "end";
14
+ }
15
+ export interface KptSplitterProps extends Omit<ComponentPropsWithRef<'div'>, 'onChange'> {
16
+ orientation?: KptSplitterOrientation;
17
+ /** Rozmiar pierwszego panelu w procentach (0–100). */
18
+ startSize?: number;
19
+ defaultStartSize?: number;
20
+ onStartSizeChange?: (size: number) => void;
21
+ /** Minimalny rozmiar panelu w procentach. */
22
+ minSize?: number;
23
+ children?: ReactNode;
24
+ }
25
+ /**
26
+ * Dwa panele z przeciąganym uchwytem. `horizontal` stawia je obok siebie, `vertical` jeden pod
27
+ * drugim.
28
+ *
29
+ * @example
30
+ * <KptSplitter startSize={size} onStartSizeChange={setSize}>
31
+ * <KptSplitter.Start>Lewy</KptSplitter.Start>
32
+ * <KptSplitter.End>Prawy</KptSplitter.End>
33
+ * </KptSplitter>
34
+ */
35
+ export declare function KptSplitter({ orientation, startSize, defaultStartSize, onStartSizeChange, minSize, className, children, ...rest }: Readonly<KptSplitterProps>): import("react").JSX.Element;
36
+ export declare namespace KptSplitter {
37
+ var Start: typeof KptSplitterStart;
38
+ var End: typeof KptSplitterEnd;
39
+ }
@@ -0,0 +1,80 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Children, isValidElement, useRef, } from 'react';
3
+ import { cn } from "../internal/cn.js";
4
+ import { useControllableState } from "../internal/use-controllable-state.js";
5
+ /** Panel splittera. Umieszczaj jako `<KptSplitter.Start>` i `<KptSplitter.End>`. */
6
+ export function KptSplitterStart(_props) {
7
+ // Panel jest nośnikiem treści: `KptSplitter` czyta jego dzieci i sam opakowuje je w `__pane`,
8
+ // bo to on trzyma rozmiar. Odpowiednik slotu `[kptSplitStart]` z Angulara.
9
+ return null;
10
+ }
11
+ KptSplitterStart.kptSplitterSlot = 'start';
12
+ export function KptSplitterEnd(_props) {
13
+ return null;
14
+ }
15
+ KptSplitterEnd.kptSplitterSlot = 'end';
16
+ /**
17
+ * Dwa panele z przeciąganym uchwytem. `horizontal` stawia je obok siebie, `vertical` jeden pod
18
+ * drugim.
19
+ *
20
+ * @example
21
+ * <KptSplitter startSize={size} onStartSizeChange={setSize}>
22
+ * <KptSplitter.Start>Lewy</KptSplitter.Start>
23
+ * <KptSplitter.End>Prawy</KptSplitter.End>
24
+ * </KptSplitter>
25
+ */
26
+ export function KptSplitter({ orientation = 'horizontal', startSize, defaultStartSize = 50, onStartSizeChange, minSize = 10, className, children, ...rest }) {
27
+ const containerRef = useRef(null);
28
+ const [size, setSize] = useControllableState({
29
+ value: startSize,
30
+ defaultValue: defaultStartSize,
31
+ onChange: onStartSizeChange,
32
+ });
33
+ let start = null;
34
+ let end = null;
35
+ Children.forEach(children, (child) => {
36
+ if (!isValidElement(child))
37
+ return;
38
+ const slot = child.type?.kptSplitterSlot;
39
+ const content = child.props.children;
40
+ if (slot === 'start')
41
+ start = content;
42
+ else if (slot === 'end')
43
+ end = content;
44
+ });
45
+ const clamp = (pct) => Math.min(100 - minSize, Math.max(minSize, Math.round(pct)));
46
+ const onPointerDown = (event) => {
47
+ event.preventDefault();
48
+ const container = containerRef.current;
49
+ if (!container)
50
+ return;
51
+ // Nasłuch na oknie, nie na uchwycie: przy szybkim ruchu kursor wyprzedza wąski pasek
52
+ // i bez tego przeciąganie urywałoby się po kilku pikselach.
53
+ const move = (e) => {
54
+ const rect = container.getBoundingClientRect();
55
+ setSize(clamp(orientation === 'horizontal'
56
+ ? ((e.clientX - rect.left) / rect.width) * 100
57
+ : ((e.clientY - rect.top) / rect.height) * 100));
58
+ };
59
+ const up = () => {
60
+ window.removeEventListener('pointermove', move);
61
+ window.removeEventListener('pointerup', up);
62
+ };
63
+ window.addEventListener('pointermove', move);
64
+ window.addEventListener('pointerup', up);
65
+ };
66
+ const onKeyDown = (event) => {
67
+ const dir = event.key === 'ArrowLeft' || event.key === 'ArrowUp'
68
+ ? -2
69
+ : event.key === 'ArrowRight' || event.key === 'ArrowDown'
70
+ ? 2
71
+ : 0;
72
+ if (!dir)
73
+ return;
74
+ event.preventDefault();
75
+ setSize(clamp(size + dir));
76
+ };
77
+ return (_jsx("div", { className: cn('kpt-splitter-host', className), ...rest, children: _jsxs("div", { ref: containerRef, className: "kpt-splitter", "data-orientation": orientation, children: [_jsx("div", { className: "kpt-splitter__pane", style: { flexBasis: `${size}%` }, children: start }), _jsx("div", { className: "kpt-splitter__gutter", role: "separator", tabIndex: 0, "aria-orientation": orientation, "aria-valuenow": size, onPointerDown: onPointerDown, onKeyDown: onKeyDown }), _jsx("div", { className: "kpt-splitter__pane", style: { flexBasis: `${100 - size}%` }, children: end })] }) }));
78
+ }
79
+ KptSplitter.Start = KptSplitterStart;
80
+ KptSplitter.End = KptSplitterEnd;
@@ -0,0 +1,51 @@
1
+ import { type ComponentPropsWithRef, type ReactNode } from 'react';
2
+ export interface KptStepperContextValue {
3
+ activeIndex: number;
4
+ /** Liczba kroków — pozwala treści kroku ukryć „Dalej" na ostatnim. */
5
+ count: number;
6
+ next: () => void;
7
+ prev: () => void;
8
+ goTo: (index: number) => void;
9
+ }
10
+ /**
11
+ * Sterowanie kreatorem z wnętrza kroku — odpowiednik `#s` + `s.next()` z portu Angulara.
12
+ * Poza `<KptStepper>` rzuca błąd, bo bez kreatora nie ma czym sterować.
13
+ *
14
+ * @example
15
+ * <KptButton onClick={useKptStepper().next}>Dalej</KptButton>
16
+ */
17
+ export declare function useKptStepper(): KptStepperContextValue;
18
+ export interface KptStepProps {
19
+ label: string;
20
+ children?: ReactNode;
21
+ }
22
+ /**
23
+ * Pojedynczy krok. Umieszczaj w `<KptStepper>`. Treść renderuje się leniwie — dopiero gdy krok
24
+ * jest aktywny, tak samo jak szablon `kpt-step` w porcie Angulara.
25
+ */
26
+ export declare function KptStep(_props: Readonly<KptStepProps>): ReactNode;
27
+ export declare namespace KptStep {
28
+ var kptStepperSlot: "step";
29
+ }
30
+ export interface KptStepperProps extends Omit<ComponentPropsWithRef<'div'>, 'onChange'> {
31
+ activeIndex?: number;
32
+ defaultActiveIndex?: number;
33
+ onActiveIndexChange?: (index: number) => void;
34
+ animated?: boolean;
35
+ animationDuration?: number;
36
+ children?: ReactNode;
37
+ }
38
+ /**
39
+ * Kreator kroków — nagłówek z numerowanymi krokami i treść aktywnego kroku.
40
+ * Treścią sterują `next()`/`prev()`/`goTo()` z hooka `useKptStepper()`.
41
+ *
42
+ * @example
43
+ * <KptStepper>
44
+ * <KptStepper.Step label="Konto">…</KptStepper.Step>
45
+ * <KptStepper.Step label="Profil">…</KptStepper.Step>
46
+ * </KptStepper>
47
+ */
48
+ export declare function KptStepper({ activeIndex, defaultActiveIndex, onActiveIndexChange, animated, animationDuration, className, style, children, ...rest }: Readonly<KptStepperProps>): import("react").JSX.Element;
49
+ export declare namespace KptStepper {
50
+ var Step: typeof KptStep;
51
+ }
@@ -0,0 +1,71 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Children, createContext, isValidElement, useContext, useState, } from 'react';
3
+ import { cn } from "../internal/cn.js";
4
+ import { useControllableState } from "../internal/use-controllable-state.js";
5
+ import { KptIcon } from "../icon/icon.js";
6
+ const StepperContext = createContext(null);
7
+ /**
8
+ * Sterowanie kreatorem z wnętrza kroku — odpowiednik `#s` + `s.next()` z portu Angulara.
9
+ * Poza `<KptStepper>` rzuca błąd, bo bez kreatora nie ma czym sterować.
10
+ *
11
+ * @example
12
+ * <KptButton onClick={useKptStepper().next}>Dalej</KptButton>
13
+ */
14
+ export function useKptStepper() {
15
+ const context = useContext(StepperContext);
16
+ if (!context)
17
+ throw new Error('useKptStepper: użyj wewnątrz <KptStepper>.');
18
+ return context;
19
+ }
20
+ /**
21
+ * Pojedynczy krok. Umieszczaj w `<KptStepper>`. Treść renderuje się leniwie — dopiero gdy krok
22
+ * jest aktywny, tak samo jak szablon `kpt-step` w porcie Angulara.
23
+ */
24
+ export function KptStep(_props) {
25
+ // Krok nigdy nie renderuje się sam: `KptStepper` czyta jego propsy i sam decyduje, co pokazać.
26
+ return null;
27
+ }
28
+ KptStep.kptStepperSlot = 'step';
29
+ /**
30
+ * Kreator kroków — nagłówek z numerowanymi krokami i treść aktywnego kroku.
31
+ * Treścią sterują `next()`/`prev()`/`goTo()` z hooka `useKptStepper()`.
32
+ *
33
+ * @example
34
+ * <KptStepper>
35
+ * <KptStepper.Step label="Konto">…</KptStepper.Step>
36
+ * <KptStepper.Step label="Profil">…</KptStepper.Step>
37
+ * </KptStepper>
38
+ */
39
+ export function KptStepper({ activeIndex, defaultActiveIndex = 0, onActiveIndexChange, animated = true, animationDuration = 500, className, style, children, ...rest }) {
40
+ const [active, setActive] = useControllableState({
41
+ value: activeIndex,
42
+ defaultValue: defaultActiveIndex,
43
+ onChange: onActiveIndexChange,
44
+ });
45
+ const [direction, setDirection] = useState(1);
46
+ const steps = [];
47
+ Children.forEach(children, (child) => {
48
+ if (!isValidElement(child) || child.type?.kptStepperSlot !== 'step')
49
+ return;
50
+ steps.push(child.props);
51
+ });
52
+ const goTo = (index) => {
53
+ const next = Math.max(0, Math.min(index, steps.length - 1));
54
+ // Kierunek karmi `--kpt-anim-dir`, więc panel wjeżdża z tej strony, z której się cofnąłeś.
55
+ setDirection(next >= active ? 1 : -1);
56
+ setActive(next);
57
+ };
58
+ const context = {
59
+ activeIndex: active,
60
+ count: steps.length,
61
+ next: () => goTo(active + 1),
62
+ prev: () => goTo(active - 1),
63
+ goTo,
64
+ };
65
+ return (_jsxs("div", { className: cn('kpt-stepper-host', className), style: {
66
+ ['--kpt-anim-duration']: `${animated ? animationDuration : 0}ms`,
67
+ ['--kpt-anim-dir']: direction,
68
+ ...style,
69
+ }, ...rest, children: [_jsx("ol", { className: "kpt-stepper__header", children: steps.map((step, index) => (_jsxs("li", { className: cn('kpt-stepper__step', index === active && 'is-active', index < active && 'is-done'), children: [_jsx("button", { type: "button", className: "kpt-stepper__marker", "aria-current": index === active ? 'step' : undefined, onClick: () => goTo(index), children: index < active ? _jsx(KptIcon, { name: "check" }) : index + 1 }), _jsx("span", { className: "kpt-stepper__label", children: step.label }), index < steps.length - 1 ? _jsx("span", { className: "kpt-stepper__connector" }) : null] }, index))) }), _jsx(StepperContext.Provider, { value: context, children: _jsx("div", { className: "kpt-stepper__body", children: steps[active] ? (_jsx("div", { className: "kpt-stepper__panel", children: steps[active].children }, active)) : null }) })] }));
70
+ }
71
+ KptStepper.Step = KptStep;
@@ -0,0 +1,39 @@
1
+ import { type ComponentPropsWithRef, type ReactNode } from 'react';
2
+ import type { KptHostProps } from '../internal/types.ts';
3
+ export interface KptSwitchProps extends Omit<ComponentPropsWithRef<'input'>, 'type' | 'required'> {
4
+ /** Etykieta obok przełącznika. */
5
+ label?: string;
6
+ /** Pozycja etykiety względem przełącznika. */
7
+ labelPosition?: 'start' | 'end';
8
+ /** Tekst stanu włączonego (wyświetlany, gdy zaznaczony). */
9
+ onLabel?: string;
10
+ /** Tekst stanu wyłączonego. */
11
+ offLabel?: string;
12
+ /** Oznacza pole jako wymagane atrybutem `aria-required`, a NIE natywnym `required`. */
13
+ required?: boolean;
14
+ /** Pole jest nieprawidłowe. Widoczne dopiero, gdy `touched` też jest prawdziwe. */
15
+ invalid?: boolean;
16
+ /** Czy pole było dotknięte; pominięty = stan błędu pokazuje się od razu po `invalid`. */
17
+ touched?: boolean;
18
+ /** Wygodniejszy odpowiednik `onChange` — dostaje samo zaznaczenie. */
19
+ onCheckedChange?: (checked: boolean) => void;
20
+ /** Wywoływane na `blur`. */
21
+ onTouch?: () => void;
22
+ /** Propsy wrappera hosta (`.kpt-switch-host`). */
23
+ hostProps?: KptHostProps<'span'>;
24
+ children?: ReactNode;
25
+ }
26
+ /**
27
+ * Przełącznik (switch/toggle). Pod spodem natywny `<input type="checkbox" role="switch">`,
28
+ * więc klawiatura i czytniki ekranu działają bez dodatkowej obsługi.
29
+ *
30
+ * Wariant z tekstem stanu: `onLabel`/`offLabel` — wyświetlany tekst zmienia się przy przełączaniu.
31
+ *
32
+ * Tekst stanu wymaga `checked` (tryb kontrolowany), bo w trybie niekontrolowanym wartość należy
33
+ * do DOM i React o niej nie wie; bez tego etykieta stanu zamarłaby na wartości początkowej.
34
+ *
35
+ * @example
36
+ * <KptSwitch name="notifications" label="Powiadomienia" />
37
+ * <KptSwitch checked={on} onCheckedChange={setOn} onLabel="Włączony" offLabel="Wyłączony" />
38
+ */
39
+ export declare function KptSwitch({ label, labelPosition, onLabel, offLabel, required, invalid, touched, onCheckedChange, onTouch, hostProps, className, disabled, checked, onChange, onBlur, children, 'aria-invalid': ariaInvalid, ...rest }: Readonly<KptSwitchProps>): import("react").JSX.Element;
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback } from 'react';
3
+ import { cn } from "../internal/cn.js";
4
+ /**
5
+ * Przełącznik (switch/toggle). Pod spodem natywny `<input type="checkbox" role="switch">`,
6
+ * więc klawiatura i czytniki ekranu działają bez dodatkowej obsługi.
7
+ *
8
+ * Wariant z tekstem stanu: `onLabel`/`offLabel` — wyświetlany tekst zmienia się przy przełączaniu.
9
+ *
10
+ * Tekst stanu wymaga `checked` (tryb kontrolowany), bo w trybie niekontrolowanym wartość należy
11
+ * do DOM i React o niej nie wie; bez tego etykieta stanu zamarłaby na wartości początkowej.
12
+ *
13
+ * @example
14
+ * <KptSwitch name="notifications" label="Powiadomienia" />
15
+ * <KptSwitch checked={on} onCheckedChange={setOn} onLabel="Włączony" offLabel="Wyłączony" />
16
+ */
17
+ export function KptSwitch({ label = '', labelPosition = 'end', onLabel = '', offLabel = '', required = false, invalid = false, touched, onCheckedChange, onTouch, hostProps, className, disabled = false, checked, onChange, onBlur, children, 'aria-invalid': ariaInvalid, ...rest }) {
18
+ const { className: hostClassName, ...hostRest } = hostProps ?? {};
19
+ const showInvalid = invalid && (touched ?? true);
20
+ const hasStateLabels = !!(onLabel || offLabel);
21
+ const handleChange = useCallback((event) => {
22
+ onChange?.(event);
23
+ onCheckedChange?.(event.target.checked);
24
+ }, [onChange, onCheckedChange]);
25
+ const handleBlur = useCallback((event) => {
26
+ onBlur?.(event);
27
+ onTouch?.();
28
+ }, [onBlur, onTouch]);
29
+ return (_jsx("span", { className: cn('kpt-switch-host', hostClassName), ...hostRest, children: _jsxs("label", { className: cn('kpt-switch', disabled && 'kpt-switch--disabled', className), children: [label && labelPosition === 'start' ? (_jsx("span", { className: "kpt-switch__label kpt-switch__label--start", children: label })) : null, _jsx("input", { type: "checkbox", role: "switch", className: "kpt-switch__input", checked: checked, disabled: disabled, "aria-required": required || undefined, "aria-invalid": ariaInvalid ?? (showInvalid || undefined), onChange: handleChange, onBlur: handleBlur, ...rest }), _jsx("span", { className: "kpt-switch__track", "aria-hidden": "true", children: _jsx("span", { className: "kpt-switch__thumb" }) }), label && labelPosition === 'end' ? _jsx("span", { className: "kpt-switch__label", children: label }) : null, hasStateLabels ? (_jsx("span", { className: cn('kpt-switch__state', checked && 'kpt-switch__state--on'), children: checked ? onLabel : offLabel })) : null, children] }) }));
30
+ }
@@ -0,0 +1,29 @@
1
+ import type { ComponentPropsWithRef } from 'react';
2
+ import type { KptOption } from '../shared/types.ts';
3
+ export interface KptSwitchGroupProps<T> extends Omit<ComponentPropsWithRef<'div'>, 'onChange' | 'defaultValue'> {
4
+ options?: KptOption<T>[];
5
+ /** Pojedynczy wybór: wartość opcji albo `null`. Tryb `multiple`: tablica wartości. */
6
+ value?: T | T[] | null;
7
+ defaultValue?: T | T[] | null;
8
+ onValueChange?: (value: T | T[] | null) => void;
9
+ /** Wielokrotny wybór — wartością staje się tablica `T[]`. */
10
+ multiple?: boolean;
11
+ orientation?: 'vertical' | 'horizontal';
12
+ /** Czy wyłączenie aktywnej opcji zeruje wartość. Dotyczy tylko trybu pojedynczego. */
13
+ allowDeselect?: boolean;
14
+ disabled?: boolean;
15
+ invalid?: boolean;
16
+ touched?: boolean;
17
+ onTouch?: () => void;
18
+ }
19
+ /**
20
+ * Grupa przełączników. Domyślnie wzajemnie wykluczających się — włączenie jednego wyłącza
21
+ * pozostałe; z `multiple` wartością jest tablica zaznaczonych opcji.
22
+ *
23
+ * Renderuje `KptSwitch`, więc dziedziczy jego wygląd, tokeny i obsługę klawiatury.
24
+ *
25
+ * @example
26
+ * <KptSwitchGroup options={plans} value={plan} onValueChange={setPlan} />
27
+ * <KptSwitchGroup multiple options={tags} value={selected} onValueChange={setSelected} />
28
+ */
29
+ export declare function KptSwitchGroup<T>({ options, value, defaultValue, onValueChange, multiple, orientation, allowDeselect, disabled, invalid, touched, onTouch, className, ...rest }: Readonly<KptSwitchGroupProps<T>>): import("react").JSX.Element;
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "../internal/cn.js";
3
+ import { useControllableState } from "../internal/use-controllable-state.js";
4
+ import { KptSwitch } from "../switch/switch.js";
5
+ /**
6
+ * Grupa przełączników. Domyślnie wzajemnie wykluczających się — włączenie jednego wyłącza
7
+ * pozostałe; z `multiple` wartością jest tablica zaznaczonych opcji.
8
+ *
9
+ * Renderuje `KptSwitch`, więc dziedziczy jego wygląd, tokeny i obsługę klawiatury.
10
+ *
11
+ * @example
12
+ * <KptSwitchGroup options={plans} value={plan} onValueChange={setPlan} />
13
+ * <KptSwitchGroup multiple options={tags} value={selected} onValueChange={setSelected} />
14
+ */
15
+ export function KptSwitchGroup({ options = [], value, defaultValue = null, onValueChange, multiple = false, orientation = 'vertical', allowDeselect = true, disabled = false, invalid = false, touched, onTouch, className, ...rest }) {
16
+ const [current, setCurrent] = useControllableState({
17
+ value,
18
+ defaultValue,
19
+ onChange: onValueChange,
20
+ });
21
+ const showInvalid = invalid && (touched ?? true);
22
+ // Wartość normalizujemy do tablicy tylko na potrzeby odczytu w trybie multiple —
23
+ // `null` i wartość pojedyncza są równie poprawnym wejściem.
24
+ const selected = Array.isArray(current) ? current : current == null ? [] : [current];
25
+ const isChecked = (optionValue) => multiple ? selected.includes(optionValue) : optionValue === current;
26
+ const toggle = (option, checked) => {
27
+ if (multiple) {
28
+ if (checked) {
29
+ if (!selected.includes(option.value))
30
+ setCurrent([...selected, option.value]);
31
+ }
32
+ else {
33
+ setCurrent(selected.filter((item) => item !== option.value));
34
+ }
35
+ return;
36
+ }
37
+ if (checked) {
38
+ setCurrent(option.value);
39
+ }
40
+ else if (allowDeselect) {
41
+ setCurrent(null);
42
+ }
43
+ // Bez `allowDeselect` nie robimy nic: `checked` jest wyliczane z wartości, a ta się nie
44
+ // zmieniła, więc przełącznik sam wraca do włączonego przy najbliższym renderze.
45
+ };
46
+ return (_jsx("div", { className: cn('kpt-switch-group-host', className), ...rest, children: _jsx("div", { className: cn('kpt-switch-group', orientation === 'horizontal' && 'kpt-switch-group--horizontal'), role: "group", "aria-invalid": showInvalid || undefined, children: options.map((option) => (_jsx(KptSwitch, { hostProps: { className: 'kpt-switch-group__item' }, checked: isChecked(option.value), label: option.label, disabled: disabled || option.disabled, onCheckedChange: (checked) => toggle(option, checked), onTouch: onTouch }, String(option.value)))) }) }));
47
+ }
@@ -0,0 +1,38 @@
1
+ import { type ComponentPropsWithRef, type ReactNode } from 'react';
2
+ export interface KptTabProps {
3
+ label: string;
4
+ disabled?: boolean;
5
+ children?: ReactNode;
6
+ }
7
+ /**
8
+ * Pojedyncza zakładka. Umieszczaj w `<KptTabs>`. Treść renderuje się leniwie — dopiero gdy
9
+ * zakładka jest aktywna, tak samo jak szablon `kpt-tab` w porcie Angulara.
10
+ */
11
+ export declare function KptTab(_props: Readonly<KptTabProps>): ReactNode;
12
+ export declare namespace KptTab {
13
+ var kptTabsSlot: "tab";
14
+ }
15
+ export interface KptTabsProps extends Omit<ComponentPropsWithRef<'div'>, 'onChange'> {
16
+ activeIndex?: number;
17
+ defaultActiveIndex?: number;
18
+ onActiveIndexChange?: (index: number) => void;
19
+ animated?: boolean;
20
+ animationDuration?: number;
21
+ children?: ReactNode;
22
+ }
23
+ /**
24
+ * Zakładki — przełączanie widoków, treść renderowana leniwie.
25
+ *
26
+ * Podkreślenie aktywnej zakładki (`__ink`) jest mierzone z DOM przycisku, nie liczone z indeksu:
27
+ * zakładki mają różne szerokości, a etykiety zmieniają się z językiem.
28
+ *
29
+ * @example
30
+ * <KptTabs>
31
+ * <KptTabs.Tab label="Ogólne">…</KptTabs.Tab>
32
+ * <KptTabs.Tab label="Zaawansowane">…</KptTabs.Tab>
33
+ * </KptTabs>
34
+ */
35
+ export declare function KptTabs({ activeIndex, defaultActiveIndex, onActiveIndexChange, animated, animationDuration, className, style, children, ...rest }: Readonly<KptTabsProps>): import("react").JSX.Element;
36
+ export declare namespace KptTabs {
37
+ var Tab: typeof KptTab;
38
+ }