@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.
- package/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/accordion/accordion.d.ts +45 -0
- package/dist/accordion/accordion.js +69 -0
- package/dist/alert/alert.d.ts +25 -0
- package/dist/alert/alert.js +31 -0
- package/dist/app-shell/app-shell.d.ts +94 -0
- package/dist/app-shell/app-shell.js +105 -0
- package/dist/auth/auth-types.d.ts +44 -0
- package/dist/auth/auth-types.js +2 -0
- package/dist/auth/auth.d.ts +76 -0
- package/dist/auth/auth.js +184 -0
- package/dist/autocomplete/autocomplete.d.ts +18 -0
- package/dist/autocomplete/autocomplete.js +72 -0
- package/dist/avatar/avatar.d.ts +33 -0
- package/dist/avatar/avatar.js +30 -0
- package/dist/avatar-group/avatar-group.d.ts +21 -0
- package/dist/avatar-group/avatar-group.js +15 -0
- package/dist/badge/badge.d.ts +25 -0
- package/dist/badge/badge.js +14 -0
- package/dist/bottom-sheet/bottom-sheet.d.ts +21 -0
- package/dist/bottom-sheet/bottom-sheet.js +22 -0
- package/dist/breadcrumb/breadcrumb.d.ts +19 -0
- package/dist/breadcrumb/breadcrumb.js +20 -0
- package/dist/button/button.d.ts +27 -0
- package/dist/button/button.js +49 -0
- package/dist/button-group/button-group.d.ts +25 -0
- package/dist/button-group/button-group.js +30 -0
- package/dist/card/card.d.ts +66 -0
- package/dist/card/card.js +96 -0
- package/dist/carousel/carousel.d.ts +20 -0
- package/dist/carousel/carousel.js +24 -0
- package/dist/charts/chart-legend.d.ts +23 -0
- package/dist/charts/chart-legend.js +9 -0
- package/dist/charts/chart-tooltip.d.ts +21 -0
- package/dist/charts/chart-tooltip.js +13 -0
- package/dist/charts/chart.d.ts +18 -0
- package/dist/charts/chart.js +231 -0
- package/dist/charts-entry/public-api.d.ts +4 -0
- package/dist/charts-entry/public-api.js +7 -0
- package/dist/checkbox/checkbox.d.ts +33 -0
- package/dist/checkbox/checkbox.js +29 -0
- package/dist/chip/chip.d.ts +22 -0
- package/dist/chip/chip.js +16 -0
- package/dist/chips-input/chips-input.d.ts +25 -0
- package/dist/chips-input/chips-input.js +54 -0
- package/dist/clock/clock.d.ts +17 -0
- package/dist/clock/clock.js +57 -0
- package/dist/color-picker/color-picker.d.ts +23 -0
- package/dist/color-picker/color-picker.js +28 -0
- package/dist/confirm/confirm-container.d.ts +13 -0
- package/dist/confirm/confirm-container.js +26 -0
- package/dist/confirm/confirm-store.d.ts +29 -0
- package/dist/confirm/confirm-store.js +52 -0
- package/dist/context-menu/context-menu.d.ts +21 -0
- package/dist/context-menu/context-menu.js +36 -0
- package/dist/data-table/data-table-types.d.ts +67 -0
- package/dist/data-table/data-table-types.js +1 -0
- package/dist/data-table/data-table.d.ts +62 -0
- package/dist/data-table/data-table.js +453 -0
- package/dist/data-table/export-csv.d.ts +7 -0
- package/dist/data-table/export-csv.js +19 -0
- package/dist/data-view/data-view.d.ts +21 -0
- package/dist/data-view/data-view.js +25 -0
- package/dist/date-range/date-range.d.ts +30 -0
- package/dist/date-range/date-range.js +155 -0
- package/dist/datepicker/datepicker.d.ts +39 -0
- package/dist/datepicker/datepicker.js +202 -0
- package/dist/dialog/dialog.d.ts +35 -0
- package/dist/dialog/dialog.js +59 -0
- package/dist/divider/divider.d.ts +16 -0
- package/dist/divider/divider.js +13 -0
- package/dist/drawer/drawer.d.ts +25 -0
- package/dist/drawer/drawer.js +25 -0
- package/dist/empty/empty.d.ts +18 -0
- package/dist/empty/empty.js +14 -0
- package/dist/fab/fab.d.ts +22 -0
- package/dist/fab/fab.js +17 -0
- package/dist/fieldset/fieldset.d.ts +22 -0
- package/dist/fieldset/fieldset.js +24 -0
- package/dist/file-upload/file-upload.d.ts +22 -0
- package/dist/file-upload/file-upload.js +50 -0
- package/dist/form-field/form-field-context.d.ts +23 -0
- package/dist/form-field/form-field-context.js +17 -0
- package/dist/form-field/form-field.d.ts +39 -0
- package/dist/form-field/form-field.js +41 -0
- package/dist/galleria/galleria.d.ts +22 -0
- package/dist/galleria/galleria.js +21 -0
- package/dist/grid/col.d.ts +39 -0
- package/dist/grid/col.js +32 -0
- package/dist/grid/flex.d.ts +45 -0
- package/dist/grid/flex.js +35 -0
- package/dist/grid/grid.d.ts +47 -0
- package/dist/grid/grid.js +38 -0
- package/dist/grid/layout.d.ts +18 -0
- package/dist/grid/layout.js +32 -0
- package/dist/grid-entry/public-api.d.ts +6 -0
- package/dist/grid-entry/public-api.js +8 -0
- package/dist/i18n/i18n-context.d.ts +45 -0
- package/dist/i18n/i18n-context.js +65 -0
- package/dist/icon/icon-registry.d.ts +16 -0
- package/dist/icon/icon-registry.js +43 -0
- package/dist/icon/icon.d.ts +17 -0
- package/dist/icon/icon.js +23 -0
- package/dist/icon-button/icon-button.d.ts +23 -0
- package/dist/icon-button/icon-button.js +14 -0
- package/dist/icons-entry/public-api.d.ts +12 -0
- package/dist/icons-entry/public-api.js +20 -0
- package/dist/image/image.d.ts +17 -0
- package/dist/image/image.js +16 -0
- package/dist/input/input.d.ts +41 -0
- package/dist/input/input.js +36 -0
- package/dist/input-mask/input-mask.d.ts +19 -0
- package/dist/input-mask/input-mask.js +65 -0
- package/dist/input-number/input-number.d.ts +28 -0
- package/dist/input-number/input-number.js +52 -0
- package/dist/input-otp/input-otp.d.ts +21 -0
- package/dist/input-otp/input-otp.js +59 -0
- package/dist/internal/cn.d.ts +9 -0
- package/dist/internal/cn.js +19 -0
- package/dist/internal/compose-refs.d.ts +6 -0
- package/dist/internal/compose-refs.js +16 -0
- package/dist/internal/overlay-container.d.ts +3 -0
- package/dist/internal/overlay-container.js +19 -0
- package/dist/internal/overlay.d.ts +26 -0
- package/dist/internal/overlay.js +64 -0
- package/dist/internal/slot.d.ts +23 -0
- package/dist/internal/slot.js +49 -0
- package/dist/internal/types.d.ts +25 -0
- package/dist/internal/types.js +1 -0
- package/dist/internal/use-breakpoint.d.ts +18 -0
- package/dist/internal/use-breakpoint.js +52 -0
- package/dist/internal/use-controllable-state.d.ts +11 -0
- package/dist/internal/use-controllable-state.js +18 -0
- package/dist/internal/use-id.d.ts +9 -0
- package/dist/internal/use-id.js +13 -0
- package/dist/knob/knob.d.ts +27 -0
- package/dist/knob/knob.js +86 -0
- package/dist/listbox/listbox.d.ts +28 -0
- package/dist/listbox/listbox.js +43 -0
- package/dist/map/map-create-dialog.d.ts +21 -0
- package/dist/map/map-create-dialog.js +196 -0
- package/dist/map/map-hours-field.d.ts +22 -0
- package/dist/map/map-hours-field.js +90 -0
- package/dist/map/map-image-field.d.ts +24 -0
- package/dist/map/map-image-field.js +61 -0
- package/dist/map/map-legend.d.ts +29 -0
- package/dist/map/map-legend.js +41 -0
- package/dist/map/map-poi-card.d.ts +42 -0
- package/dist/map/map-poi-card.js +152 -0
- package/dist/map/map-search.d.ts +37 -0
- package/dist/map/map-search.js +201 -0
- package/dist/map/map.d.ts +113 -0
- package/dist/map/map.js +425 -0
- package/dist/map/ports.d.ts +76 -0
- package/dist/map/ports.js +174 -0
- package/dist/map-entry/public-api.d.ts +20 -0
- package/dist/map-entry/public-api.js +19 -0
- package/dist/megamenu/megamenu.d.ts +17 -0
- package/dist/megamenu/megamenu.js +28 -0
- package/dist/menu/menu-item.d.ts +33 -0
- package/dist/menu/menu-item.js +1 -0
- package/dist/menu/menu-rows.d.ts +9 -0
- package/dist/menu/menu-rows.js +15 -0
- package/dist/menu/menu.d.ts +22 -0
- package/dist/menu/menu.js +31 -0
- package/dist/menubar/menubar.d.ts +16 -0
- package/dist/menubar/menubar.js +39 -0
- package/dist/meter-group/meter-group.d.ts +20 -0
- package/dist/meter-group/meter-group.js +24 -0
- package/dist/order-list/order-list.d.ts +18 -0
- package/dist/order-list/order-list.js +37 -0
- package/dist/paginator/paginator.d.ts +29 -0
- package/dist/paginator/paginator.js +45 -0
- package/dist/panel/panel.d.ts +31 -0
- package/dist/panel/panel.js +36 -0
- package/dist/password/password.d.ts +28 -0
- package/dist/password/password.js +37 -0
- package/dist/pick-list/pick-list.d.ts +28 -0
- package/dist/pick-list/pick-list.js +65 -0
- package/dist/popover/popover.d.ts +23 -0
- package/dist/popover/popover.js +27 -0
- package/dist/progress/progress.d.ts +19 -0
- package/dist/progress/progress.js +21 -0
- package/dist/public-api.d.ts +181 -0
- package/dist/public-api.js +105 -0
- package/dist/radio-group/radio-group.d.ts +24 -0
- package/dist/radio-group/radio-group.js +23 -0
- package/dist/rating/rating.d.ts +22 -0
- package/dist/rating/rating.js +30 -0
- package/dist/rich-text/lists.d.ts +17 -0
- package/dist/rich-text/lists.js +144 -0
- package/dist/rich-text/rich-text.d.ts +28 -0
- package/dist/rich-text/rich-text.js +654 -0
- package/dist/rich-text/sanitize.d.ts +10 -0
- package/dist/rich-text/sanitize.js +85 -0
- package/dist/rich-text/tables.d.ts +44 -0
- package/dist/rich-text/tables.js +268 -0
- package/dist/roadmap/roadmap.d.ts +37 -0
- package/dist/roadmap/roadmap.js +271 -0
- package/dist/roadmap-entry/public-api.d.ts +4 -0
- package/dist/roadmap-entry/public-api.js +7 -0
- package/dist/scroll-top/scroll-top.d.ts +16 -0
- package/dist/scroll-top/scroll-top.js +38 -0
- package/dist/select/select.d.ts +37 -0
- package/dist/select/select.js +117 -0
- package/dist/shared/types.d.ts +8 -0
- package/dist/shared/types.js +1 -0
- package/dist/sidenav/sidenav.d.ts +26 -0
- package/dist/sidenav/sidenav.js +41 -0
- package/dist/skeleton/skeleton.d.ts +20 -0
- package/dist/skeleton/skeleton.js +15 -0
- package/dist/slider/slider.d.ts +28 -0
- package/dist/slider/slider.js +30 -0
- package/dist/speed-dial/speed-dial.d.ts +20 -0
- package/dist/speed-dial/speed-dial.js +23 -0
- package/dist/spinner/spinner.d.ts +15 -0
- package/dist/spinner/spinner.js +14 -0
- package/dist/split-button/split-button.d.ts +28 -0
- package/dist/split-button/split-button.js +34 -0
- package/dist/splitter/splitter.d.ts +39 -0
- package/dist/splitter/splitter.js +80 -0
- package/dist/stepper/stepper.d.ts +51 -0
- package/dist/stepper/stepper.js +71 -0
- package/dist/switch/switch.d.ts +39 -0
- package/dist/switch/switch.js +30 -0
- package/dist/switch-group/switch-group.d.ts +29 -0
- package/dist/switch-group/switch-group.js +47 -0
- package/dist/tabs/tabs.d.ts +38 -0
- package/dist/tabs/tabs.js +74 -0
- package/dist/textarea/textarea.d.ts +28 -0
- package/dist/textarea/textarea.js +44 -0
- package/dist/timeline/timeline.d.ts +19 -0
- package/dist/timeline/timeline.js +12 -0
- package/dist/toast/toast-container.d.ts +12 -0
- package/dist/toast/toast-container.js +23 -0
- package/dist/toast/toast-store.d.ts +26 -0
- package/dist/toast/toast-store.js +51 -0
- package/dist/toolbar/toolbar.d.ts +29 -0
- package/dist/toolbar/toolbar.js +24 -0
- package/dist/tooltip/tooltip.d.ts +26 -0
- package/dist/tooltip/tooltip.js +113 -0
- package/dist/tree/tree.d.ts +31 -0
- package/dist/tree/tree.js +62 -0
- 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
|
+
}
|