@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,22 @@
|
|
|
1
|
+
import type { ComponentPropsWithRef } from 'react';
|
|
2
|
+
import type { KptHostProps } from '../internal/types.ts';
|
|
3
|
+
export interface KptFabProps extends ComponentPropsWithRef<'button'> {
|
|
4
|
+
variant?: 'filled' | 'tonal';
|
|
5
|
+
size?: 'md' | 'mini';
|
|
6
|
+
/** Pigułka z tekstem obok ikony. */
|
|
7
|
+
extended?: boolean;
|
|
8
|
+
/** Propsy wrappera hosta (`.kpt-fab-host`). */
|
|
9
|
+
hostProps?: KptHostProps<'span'>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Floating Action Button — okrągły, wyniesiony przycisk akcji. `extended` robi z niego pigułkę
|
|
13
|
+
* z tekstem.
|
|
14
|
+
*
|
|
15
|
+
* W wariancie okrągłym `aria-label` jest niezbędny, bo przycisk nie ma tekstu; w `extended`
|
|
16
|
+
* etykietę niesie już treść, więc `aria-label` jest tam pomijany, żeby nie dublować nazwy.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* <KptFab aria-label="Dodaj"><KptIcon name="plus" /></KptFab>
|
|
20
|
+
* <KptFab extended><KptIcon name="plus" /> Nowy</KptFab>
|
|
21
|
+
*/
|
|
22
|
+
export declare function KptFab({ variant, size, extended, type, hostProps, className, 'aria-label': ariaLabel, ...rest }: Readonly<KptFabProps>): import("react").JSX.Element;
|
package/dist/fab/fab.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../internal/cn.js";
|
|
3
|
+
/**
|
|
4
|
+
* Floating Action Button — okrągły, wyniesiony przycisk akcji. `extended` robi z niego pigułkę
|
|
5
|
+
* z tekstem.
|
|
6
|
+
*
|
|
7
|
+
* W wariancie okrągłym `aria-label` jest niezbędny, bo przycisk nie ma tekstu; w `extended`
|
|
8
|
+
* etykietę niesie już treść, więc `aria-label` jest tam pomijany, żeby nie dublować nazwy.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* <KptFab aria-label="Dodaj"><KptIcon name="plus" /></KptFab>
|
|
12
|
+
* <KptFab extended><KptIcon name="plus" /> Nowy</KptFab>
|
|
13
|
+
*/
|
|
14
|
+
export function KptFab({ variant = 'filled', size = 'md', extended = false, type = 'button', hostProps, className, 'aria-label': ariaLabel, ...rest }) {
|
|
15
|
+
const { className: hostClassName, ...hostRest } = hostProps ?? {};
|
|
16
|
+
return (_jsx("span", { className: cn('kpt-fab-host', hostClassName), ...hostRest, children: _jsx("button", { className: cn('kpt-fab', extended && 'kpt-fab--extended', className), type: type, "data-variant": variant, "data-size": size, "aria-label": extended ? undefined : ariaLabel, ...rest }) }));
|
|
17
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ComponentPropsWithRef, ReactNode } from 'react';
|
|
2
|
+
export interface KptFieldsetProps extends ComponentPropsWithRef<'div'> {
|
|
3
|
+
legend?: string;
|
|
4
|
+
/** Legenda staje się przyciskiem zwijającym zawartość. */
|
|
5
|
+
toggleable?: boolean;
|
|
6
|
+
collapsed?: boolean;
|
|
7
|
+
defaultCollapsed?: boolean;
|
|
8
|
+
onCollapsedChange?: (collapsed: boolean) => void;
|
|
9
|
+
animated?: boolean;
|
|
10
|
+
animationDuration?: number;
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Grupa pól z legendą (`<fieldset>` + `<legend>`), opcjonalnie zwijana.
|
|
15
|
+
*
|
|
16
|
+
* Zwijanie idzie przez `grid-template-rows: 0fr → 1fr`, więc animuje się do naturalnej wysokości
|
|
17
|
+
* treści — bez mierzenia czegokolwiek w JS.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* <KptFieldset legend="Dane osobowe" toggleable>…</KptFieldset>
|
|
21
|
+
*/
|
|
22
|
+
export declare function KptFieldset({ legend, toggleable, collapsed, defaultCollapsed, onCollapsedChange, animated, animationDuration, className, style, children, ...rest }: Readonly<KptFieldsetProps>): import("react").JSX.Element;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../internal/cn.js";
|
|
3
|
+
import { useControllableState } from "../internal/use-controllable-state.js";
|
|
4
|
+
import { KptIcon } from "../icon/icon.js";
|
|
5
|
+
/**
|
|
6
|
+
* Grupa pól z legendą (`<fieldset>` + `<legend>`), opcjonalnie zwijana.
|
|
7
|
+
*
|
|
8
|
+
* Zwijanie idzie przez `grid-template-rows: 0fr → 1fr`, więc animuje się do naturalnej wysokości
|
|
9
|
+
* treści — bez mierzenia czegokolwiek w JS.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* <KptFieldset legend="Dane osobowe" toggleable>…</KptFieldset>
|
|
13
|
+
*/
|
|
14
|
+
export function KptFieldset({ legend = '', toggleable = false, collapsed, defaultCollapsed = false, onCollapsedChange, animated = true, animationDuration = 500, className, style, children, ...rest }) {
|
|
15
|
+
const [isCollapsed, setCollapsed] = useControllableState({
|
|
16
|
+
value: collapsed,
|
|
17
|
+
defaultValue: defaultCollapsed,
|
|
18
|
+
onChange: onCollapsedChange,
|
|
19
|
+
});
|
|
20
|
+
return (_jsx("div", { className: cn('kpt-fieldset-host', className), style: {
|
|
21
|
+
['--kpt-anim-duration']: `${animated ? animationDuration : 0}ms`,
|
|
22
|
+
...style,
|
|
23
|
+
}, ...rest, children: _jsxs("fieldset", { className: "kpt-fieldset", children: [_jsx("legend", { className: "kpt-fieldset__legend", children: toggleable ? (_jsxs("button", { type: "button", className: "kpt-fieldset__toggle", "aria-expanded": !isCollapsed, onClick: () => setCollapsed(!isCollapsed), children: [_jsx(KptIcon, { name: isCollapsed ? 'chevron-down' : 'chevron-up' }), _jsx("span", { children: legend })] })) : (_jsx("span", { children: legend })) }), _jsx("div", { className: cn('kpt-fieldset__collapse', !isCollapsed && 'is-open'), inert: isCollapsed, "aria-hidden": isCollapsed, children: _jsx("div", { className: "kpt-fieldset__collapse-inner", children: _jsx("div", { className: "kpt-fieldset__body", children: children }) }) })] }) }));
|
|
24
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ComponentPropsWithRef } from 'react';
|
|
2
|
+
import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
|
|
3
|
+
export interface KptFileUploadProps extends Omit<ComponentPropsWithRef<'div'>, 'onChange' | 'defaultValue'>, KptI18nOverrides {
|
|
4
|
+
value?: File[];
|
|
5
|
+
defaultValue?: File[];
|
|
6
|
+
onValueChange?: (files: File[]) => void;
|
|
7
|
+
/** Filtr natywnego okna wyboru, np. 'image/*'. */
|
|
8
|
+
accept?: string;
|
|
9
|
+
multiple?: boolean;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
invalid?: boolean;
|
|
12
|
+
touched?: boolean;
|
|
13
|
+
onTouch?: () => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Wgrywanie plików: strefa reagująca na kliknięcie i na upuszczenie, plus lista wybranych plików.
|
|
17
|
+
* Wartością jest tablica `File`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* <KptFileUpload value={files} onValueChange={setFiles} accept="image/*" multiple />
|
|
21
|
+
*/
|
|
22
|
+
export declare function KptFileUpload({ value, defaultValue, onValueChange, accept, multiple, disabled, invalid, touched, onTouch, locale, dictionary, className, ...rest }: Readonly<KptFileUploadProps>): import("react").JSX.Element;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useState } from 'react';
|
|
3
|
+
import { cn } from "../internal/cn.js";
|
|
4
|
+
import { useControllableState } from "../internal/use-controllable-state.js";
|
|
5
|
+
import { useKptMessages } from "../i18n/i18n-context.js";
|
|
6
|
+
import { KptIcon } from "../icon/icon.js";
|
|
7
|
+
const EMPTY = [];
|
|
8
|
+
/** Rozmiar pliku w KB albo MB — bez bibliotek, bo to jedna reguła. */
|
|
9
|
+
function formatSize(file) {
|
|
10
|
+
const kb = file.size / 1024;
|
|
11
|
+
return kb < 1024 ? `${kb.toFixed(0)} KB` : `${(kb / 1024).toFixed(1)} MB`;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Wgrywanie plików: strefa reagująca na kliknięcie i na upuszczenie, plus lista wybranych plików.
|
|
15
|
+
* Wartością jest tablica `File`.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* <KptFileUpload value={files} onValueChange={setFiles} accept="image/*" multiple />
|
|
19
|
+
*/
|
|
20
|
+
export function KptFileUpload({ value, defaultValue = EMPTY, onValueChange, accept = '', multiple = false, disabled = false, invalid = false, touched, onTouch, locale, dictionary, className, ...rest }) {
|
|
21
|
+
const { t } = useKptMessages({ locale, dictionary });
|
|
22
|
+
const inputRef = useRef(null);
|
|
23
|
+
const [current, setCurrent] = useControllableState({ value, defaultValue, onChange: onValueChange });
|
|
24
|
+
const [dragover, setDragover] = useState(false);
|
|
25
|
+
const addFiles = (list) => {
|
|
26
|
+
if (!list?.length)
|
|
27
|
+
return;
|
|
28
|
+
const added = Array.from(list);
|
|
29
|
+
setCurrent(multiple ? [...current, ...added] : added.slice(0, 1));
|
|
30
|
+
onTouch?.();
|
|
31
|
+
};
|
|
32
|
+
const onSelect = (event) => {
|
|
33
|
+
addFiles(event.target.files);
|
|
34
|
+
// Czyszczenie pola pozwala wybrać ten sam plik drugi raz — inaczej `change` by nie poleciał.
|
|
35
|
+
event.target.value = '';
|
|
36
|
+
};
|
|
37
|
+
return (_jsxs("div", { className: cn('kpt-file-upload-host', className), ...rest, children: [_jsxs("div", { className: cn('kpt-file-upload__zone', dragover && 'is-dragover', disabled && 'is-disabled'), onClick: () => !disabled && inputRef.current?.click(), onDragOver: (event) => {
|
|
38
|
+
event.preventDefault();
|
|
39
|
+
if (!disabled)
|
|
40
|
+
setDragover(true);
|
|
41
|
+
}, onDragLeave: () => setDragover(false), onDrop: (event) => {
|
|
42
|
+
event.preventDefault();
|
|
43
|
+
setDragover(false);
|
|
44
|
+
if (!disabled)
|
|
45
|
+
addFiles(event.dataTransfer?.files);
|
|
46
|
+
}, children: [_jsx("input", { ref: inputRef, type: "file", hidden: true, accept: accept, multiple: multiple, onChange: onSelect }), _jsx(KptIcon, { name: "upload", className: "kpt-file-upload__icon" }), _jsx("div", { className: "kpt-file-upload__text", dangerouslySetInnerHTML: { __html: t('fileUpload.hint') } }), accept ? _jsx("div", { className: "kpt-file-upload__hint", children: accept }) : null] }), current.length ? (_jsx("ul", { className: "kpt-file-upload__list", children: current.map((file) => (_jsxs("li", { className: "kpt-file-upload__file", children: [_jsx(KptIcon, { name: "photo" }), _jsx("span", { className: "kpt-file-upload__name", children: file.name }), _jsx("span", { className: "kpt-file-upload__size", children: formatSize(file) }), _jsx("button", { type: "button", className: "kpt-file-upload__remove", "aria-label": t('fileUpload.remove'), onClick: (event) => {
|
|
47
|
+
event.stopPropagation();
|
|
48
|
+
setCurrent(current.filter((item) => item !== file));
|
|
49
|
+
}, children: _jsx(KptIcon, { name: "trash" }) })] }, file.name))) })) : null] }));
|
|
50
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kontrakt między `KptFormField` a kontrolką w środku.
|
|
3
|
+
*
|
|
4
|
+
* Odpowiednik tokenu `KPT_FORM_FIELD_CONTROL` z portu Angulara. Wrapper sam odczytuje
|
|
5
|
+
* wypełnienie natywnego `input`/`textarea` z DOM; kontrolki bez natywnego pola (np. select
|
|
6
|
+
* zbudowany na liście) zgłaszają je przez `useKptFormFieldFilled`.
|
|
7
|
+
*/
|
|
8
|
+
export interface KptFormFieldContextValue {
|
|
9
|
+
/** Id, którym wrapper wiąże `label[for]` — kontrolka powinna nadać je swojemu elementowi. */
|
|
10
|
+
controlId: string;
|
|
11
|
+
/** Czy pole jest oznaczone jako nieprawidłowe (niepusty `error` na wrapperze). */
|
|
12
|
+
invalid: boolean;
|
|
13
|
+
/** Zgłasza wypełnienie kontrolki, gdy nie da się go odczytać z DOM. */
|
|
14
|
+
reportFilled: (filled: boolean) => void;
|
|
15
|
+
}
|
|
16
|
+
export declare const KptFormFieldContext: import("react").Context<KptFormFieldContextValue | null>;
|
|
17
|
+
/** Kontekst pola formularza albo `null`, gdy kontrolka stoi poza `KptFormField`. */
|
|
18
|
+
export declare function useKptFormFieldContext(): KptFormFieldContextValue | null;
|
|
19
|
+
/**
|
|
20
|
+
* Zgłasza wrapperowi wypełnienie kontrolki, która nie ma natywnego `input`/`textarea`.
|
|
21
|
+
* Steruje uniesieniem etykiety w wariantach float.
|
|
22
|
+
*/
|
|
23
|
+
export declare function useKptFormFieldFilled(filled: boolean): void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createContext, useContext, useEffect } from 'react';
|
|
2
|
+
export const KptFormFieldContext = createContext(null);
|
|
3
|
+
/** Kontekst pola formularza albo `null`, gdy kontrolka stoi poza `KptFormField`. */
|
|
4
|
+
export function useKptFormFieldContext() {
|
|
5
|
+
return useContext(KptFormFieldContext);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Zgłasza wrapperowi wypełnienie kontrolki, która nie ma natywnego `input`/`textarea`.
|
|
9
|
+
* Steruje uniesieniem etykiety w wariantach float.
|
|
10
|
+
*/
|
|
11
|
+
export function useKptFormFieldFilled(filled) {
|
|
12
|
+
const context = useKptFormFieldContext();
|
|
13
|
+
const reportFilled = context?.reportFilled;
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
reportFilled?.(filled);
|
|
16
|
+
}, [reportFilled, filled]);
|
|
17
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ComponentPropsWithRef, type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Wariant etykiety: `fixed` (statyczna nad kontrolką) albo Float Label — `over`
|
|
4
|
+
* (nad obramowaniem), `in` (u góry wewnątrz pola), `on` (na obramowaniu, notch).
|
|
5
|
+
*/
|
|
6
|
+
export type KptFormFieldLabelType = 'fixed' | 'over' | 'in' | 'on';
|
|
7
|
+
export interface KptFormFieldProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {
|
|
8
|
+
/** Tekst etykiety. */
|
|
9
|
+
label?: string;
|
|
10
|
+
/** Podpowiedź pod kontrolką (ukrywana, gdy jest błąd). */
|
|
11
|
+
hint?: string;
|
|
12
|
+
/** Komunikat błędu — gdy niepusty, pole jest oznaczone jako nieprawidłowe. */
|
|
13
|
+
error?: string | null;
|
|
14
|
+
/** Oznacz pole jako wymagane (gwiazdka przy etykiecie). */
|
|
15
|
+
required?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Id kontrolki dla powiązania `label[for]`. Puste = wrapper wygeneruje własne i poda je
|
|
18
|
+
* kontrolce przez kontekst, więc `<KptInput>` w środku nie wymaga żadnej konfiguracji.
|
|
19
|
+
*/
|
|
20
|
+
controlId?: string;
|
|
21
|
+
/** Wariant etykiety; uniesienie następuje przy focusie lub wypełnieniu pola. */
|
|
22
|
+
labelType?: KptFormFieldLabelType;
|
|
23
|
+
children?: ReactNode;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Wrapper pola formularza: etykieta, podpowiedź i komunikat błędu wokół dowolnej kontrolki.
|
|
27
|
+
* Prezentacyjny — stan błędu przekazuje się przez `error`.
|
|
28
|
+
*
|
|
29
|
+
* Wypełnienie (sterujące uniesieniem etykiety) wrapper odczytuje z natywnego `input`/`textarea`
|
|
30
|
+
* w środku, po zdarzeniach `input`/`change` oraz z wartości początkowej. Działa więc tak samo
|
|
31
|
+
* dla pola kontrolowanego i niekontrolowanego. Kontrolki bez natywnego pola zgłaszają
|
|
32
|
+
* wypełnienie hookiem `useKptFormFieldFilled`.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* <KptFormField label="E-mail" error={errors.email} hint="Adres firmowy">
|
|
36
|
+
* <KptInput type="email" name="email" />
|
|
37
|
+
* </KptFormField>
|
|
38
|
+
*/
|
|
39
|
+
export declare function KptFormField({ label, hint, error, required, controlId, labelType, className, children, ref, ...rest }: Readonly<KptFormFieldProps>): import("react").JSX.Element;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
|
|
3
|
+
import { cn } from "../internal/cn.js";
|
|
4
|
+
import { composeRefs } from "../internal/compose-refs.js";
|
|
5
|
+
import { useKptId } from "../internal/use-id.js";
|
|
6
|
+
import { KptFormFieldContext } from "./form-field-context.js";
|
|
7
|
+
/**
|
|
8
|
+
* Wrapper pola formularza: etykieta, podpowiedź i komunikat błędu wokół dowolnej kontrolki.
|
|
9
|
+
* Prezentacyjny — stan błędu przekazuje się przez `error`.
|
|
10
|
+
*
|
|
11
|
+
* Wypełnienie (sterujące uniesieniem etykiety) wrapper odczytuje z natywnego `input`/`textarea`
|
|
12
|
+
* w środku, po zdarzeniach `input`/`change` oraz z wartości początkowej. Działa więc tak samo
|
|
13
|
+
* dla pola kontrolowanego i niekontrolowanego. Kontrolki bez natywnego pola zgłaszają
|
|
14
|
+
* wypełnienie hookiem `useKptFormFieldFilled`.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* <KptFormField label="E-mail" error={errors.email} hint="Adres firmowy">
|
|
18
|
+
* <KptInput type="email" name="email" />
|
|
19
|
+
* </KptFormField>
|
|
20
|
+
*/
|
|
21
|
+
export function KptFormField({ label = '', hint = '', error = null, required = false, controlId = '', labelType = 'fixed', className, children, ref, ...rest }) {
|
|
22
|
+
const hostRef = useRef(null);
|
|
23
|
+
const [nativeFilled, setNativeFilled] = useState(false);
|
|
24
|
+
const [reportedFilled, setReportedFilled] = useState(null);
|
|
25
|
+
const generatedId = useKptId(undefined, 'kpt-form-field-control');
|
|
26
|
+
const id = controlId || generatedId;
|
|
27
|
+
/** Odczytuje wartość projektowanego `input`/`textarea` i aktualizuje stan wypełnienia. */
|
|
28
|
+
const updateFilled = useCallback(() => {
|
|
29
|
+
const el = hostRef.current?.querySelector('.kpt-form-field__control input, .kpt-form-field__control textarea');
|
|
30
|
+
setNativeFilled(!!el && el.value !== '');
|
|
31
|
+
}, []);
|
|
32
|
+
// Wartość początkowa (np. pole prefill) — po pierwszym renderze projekcji, przed malowaniem,
|
|
33
|
+
// żeby uniesiona etykieta nie przeskoczyła na oczach użytkownika.
|
|
34
|
+
useLayoutEffect(updateFilled, [updateFilled]);
|
|
35
|
+
// Kontrolowana wartość zmieniana z zewnątrz nie emituje zdarzenia `input`, więc odczyt
|
|
36
|
+
// powtarzamy po każdym renderze — to jeden `querySelector`, nie warto tu optymalizować.
|
|
37
|
+
useEffect(updateFilled);
|
|
38
|
+
const filled = reportedFilled ?? nativeFilled;
|
|
39
|
+
const context = useMemo(() => ({ controlId: id, invalid: !!error, reportFilled: setReportedFilled }), [id, error]);
|
|
40
|
+
return (_jsx(KptFormFieldContext.Provider, { value: context, children: _jsx("div", { className: cn('kpt-form-field-host', className), ref: composeRefs(hostRef, ref), onInput: updateFilled, onChange: updateFilled, ...rest, children: _jsxs("div", { className: cn('kpt-form-field', `kpt-form-field--${labelType}`, labelType !== 'fixed' && 'kpt-form-field--float', error && 'kpt-form-field--invalid'), children: [_jsxs("div", { className: cn('kpt-form-field__box', filled && 'is-filled'), children: [label ? (_jsxs("label", { className: "kpt-form-field__label", htmlFor: id || undefined, children: [label, required ? (_jsx("span", { className: "kpt-form-field__required", "aria-hidden": "true", children: "*" })) : null] })) : null, _jsx("div", { className: "kpt-form-field__control", children: children })] }), error ? (_jsx("p", { className: "kpt-form-field__message kpt-form-field__message--error", role: "alert", children: error })) : hint ? (_jsx("p", { className: "kpt-form-field__message kpt-form-field__message--hint", children: hint })) : null] }) }) }));
|
|
41
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ComponentPropsWithRef } from 'react';
|
|
2
|
+
import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
|
|
3
|
+
export interface KptGalleriaItem {
|
|
4
|
+
src: string;
|
|
5
|
+
/** Miniatura; bez niej pasek pokazuje pomniejszony obraz główny. */
|
|
6
|
+
thumbnail?: string;
|
|
7
|
+
alt?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface KptGalleriaProps extends Omit<ComponentPropsWithRef<'div'>, 'onChange'>, KptI18nOverrides {
|
|
10
|
+
items?: KptGalleriaItem[];
|
|
11
|
+
activeIndex?: number;
|
|
12
|
+
defaultActiveIndex?: number;
|
|
13
|
+
onActiveIndexChange?: (index: number) => void;
|
|
14
|
+
showThumbnails?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Galleria — duży podgląd obrazu z paskiem miniatur i nawigacją.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* <KptGalleria items={photos} activeIndex={index} onActiveIndexChange={setIndex} />
|
|
21
|
+
*/
|
|
22
|
+
export declare function KptGalleria({ items, activeIndex, defaultActiveIndex, onActiveIndexChange, showThumbnails, locale, dictionary, className, ...rest }: Readonly<KptGalleriaProps>): import("react").JSX.Element;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../internal/cn.js";
|
|
3
|
+
import { useControllableState } from "../internal/use-controllable-state.js";
|
|
4
|
+
import { useKptMessages } from "../i18n/i18n-context.js";
|
|
5
|
+
import { KptIcon } from "../icon/icon.js";
|
|
6
|
+
/**
|
|
7
|
+
* Galleria — duży podgląd obrazu z paskiem miniatur i nawigacją.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* <KptGalleria items={photos} activeIndex={index} onActiveIndexChange={setIndex} />
|
|
11
|
+
*/
|
|
12
|
+
export function KptGalleria({ items = [], activeIndex, defaultActiveIndex = 0, onActiveIndexChange, showThumbnails = true, locale, dictionary, className, ...rest }) {
|
|
13
|
+
const { t } = useKptMessages({ locale, dictionary });
|
|
14
|
+
const [active, setActive] = useControllableState({
|
|
15
|
+
value: activeIndex,
|
|
16
|
+
defaultValue: defaultActiveIndex,
|
|
17
|
+
onChange: onActiveIndexChange,
|
|
18
|
+
});
|
|
19
|
+
const current = items[active] ?? null;
|
|
20
|
+
return (_jsx("div", { className: cn('kpt-galleria-host', className), ...rest, children: _jsxs("div", { className: "kpt-galleria", children: [_jsxs("div", { className: "kpt-galleria__stage", children: [_jsx("button", { type: "button", className: "kpt-galleria__nav kpt-galleria__nav--prev", disabled: active === 0, "aria-label": t('common.previous'), onClick: () => setActive(Math.max(active - 1, 0)), children: _jsx(KptIcon, { name: "chevron-left" }) }), current ? _jsx("img", { className: "kpt-galleria__image", src: current.src, alt: current.alt || '' }) : null, _jsx("button", { type: "button", className: "kpt-galleria__nav kpt-galleria__nav--next", disabled: active >= items.length - 1, "aria-label": t('common.next'), onClick: () => setActive(Math.min(active + 1, items.length - 1)), children: _jsx(KptIcon, { name: "chevron-right" }) })] }), showThumbnails ? (_jsx("div", { className: "kpt-galleria__thumbs", children: items.map((item, index) => (_jsx("button", { type: "button", className: cn('kpt-galleria__thumb', index === active && 'is-active'), "aria-label": t('galleria.image', { index: index + 1 }), onClick: () => setActive(index), children: _jsx("img", { src: item.thumbnail || item.src, alt: item.alt || '' }) }, index))) })) : null] }) }));
|
|
21
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ComponentPropsWithRef } from 'react';
|
|
2
|
+
import type { AsChildProps } from '../internal/types.ts';
|
|
3
|
+
/** Rozpiętość kolumny: liczba, `'full'` (cała szerokość) albo dowolna wartość CSS. */
|
|
4
|
+
export type KptColSpan = number | string;
|
|
5
|
+
export interface KptColProps extends ComponentPropsWithRef<'div'>, AsChildProps {
|
|
6
|
+
/** Rozpiętość kolumny — baza mobile-first. */
|
|
7
|
+
span?: KptColSpan;
|
|
8
|
+
/** Rozpiętość od breakpointa SM (>= 640px). */
|
|
9
|
+
spanSm?: KptColSpan;
|
|
10
|
+
/** Rozpiętość od breakpointa MD (>= 768px). */
|
|
11
|
+
spanMd?: KptColSpan;
|
|
12
|
+
/** Rozpiętość od breakpointa LG (>= 1024px). */
|
|
13
|
+
spanLg?: KptColSpan;
|
|
14
|
+
/** Rozpiętość od breakpointa XL (>= 1280px). */
|
|
15
|
+
spanXl?: KptColSpan;
|
|
16
|
+
/** Rozpiętość od breakpointa 2XL (>= 1536px). */
|
|
17
|
+
span2xl?: KptColSpan;
|
|
18
|
+
/** Numer linii, od której zaczyna się kolumna (1-based) — pozwala robić offsety. */
|
|
19
|
+
start?: number | string;
|
|
20
|
+
/** Kolejność wizualna (`order`). Nie zmienia kolejności w DOM ani dla czytników ekranu. */
|
|
21
|
+
order?: number | string;
|
|
22
|
+
/** Wyrównanie w poprzek osi (`align-self`): `start`, `end`, `center`, `stretch`, `baseline`. */
|
|
23
|
+
self?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Kolumna siatki `KptGrid` — rozpiętość mobile-first z nadpisaniami per breakpoint.
|
|
27
|
+
*
|
|
28
|
+
* Wartość podana dla mniejszego breakpointa obowiązuje aż do następnego, który ją nadpisze:
|
|
29
|
+
* `span={12} spanLg={5}` daje 12 na mobile, tablecie i `md`, a dopiero od `lg` — 5.
|
|
30
|
+
*
|
|
31
|
+
* Ustawia wyłącznie custom properties inline; nie dodaje ani nie usuwa klas. Z `asChild`
|
|
32
|
+
* przejmuje Twój element, więc kolumną może być `<li>`, `<article>` czy komponent biblioteki.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* <KptGrid>
|
|
36
|
+
* <KptCol span={12} spanSm={6} spanMd={4}>Karta</KptCol>
|
|
37
|
+
* </KptGrid>
|
|
38
|
+
*/
|
|
39
|
+
export declare function KptCol({ span, spanSm, spanMd, spanLg, spanXl, span2xl, start, order, self, asChild, className, style, children, ...rest }: Readonly<KptColProps>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
package/dist/grid/col.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { layoutStyle, renderLayout } from "./layout.js";
|
|
2
|
+
/**
|
|
3
|
+
* Kolumna siatki `KptGrid` — rozpiętość mobile-first z nadpisaniami per breakpoint.
|
|
4
|
+
*
|
|
5
|
+
* Wartość podana dla mniejszego breakpointa obowiązuje aż do następnego, który ją nadpisze:
|
|
6
|
+
* `span={12} spanLg={5}` daje 12 na mobile, tablecie i `md`, a dopiero od `lg` — 5.
|
|
7
|
+
*
|
|
8
|
+
* Ustawia wyłącznie custom properties inline; nie dodaje ani nie usuwa klas. Z `asChild`
|
|
9
|
+
* przejmuje Twój element, więc kolumną może być `<li>`, `<article>` czy komponent biblioteki.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* <KptGrid>
|
|
13
|
+
* <KptCol span={12} spanSm={6} spanMd={4}>Karta</KptCol>
|
|
14
|
+
* </KptGrid>
|
|
15
|
+
*/
|
|
16
|
+
export function KptCol({ span, spanSm, spanMd, spanLg, spanXl, span2xl, start, order, self, asChild = false, className, style, children, ...rest }) {
|
|
17
|
+
return renderLayout(asChild, children, {
|
|
18
|
+
className,
|
|
19
|
+
style: layoutStyle({
|
|
20
|
+
'--kpt-col': span,
|
|
21
|
+
'--kpt-col-sm': spanSm,
|
|
22
|
+
'--kpt-col-md': spanMd,
|
|
23
|
+
'--kpt-col-lg': spanLg,
|
|
24
|
+
'--kpt-col-xl': spanXl,
|
|
25
|
+
'--kpt-col-2xl': span2xl,
|
|
26
|
+
'--kpt-col-start': start,
|
|
27
|
+
'--kpt-order': order,
|
|
28
|
+
'--kpt-self': self,
|
|
29
|
+
}, style),
|
|
30
|
+
...rest,
|
|
31
|
+
}, 'div');
|
|
32
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ComponentPropsWithRef } from 'react';
|
|
2
|
+
import type { AsChildProps } from '../internal/types.ts';
|
|
3
|
+
export type KptFlexDirection = 'row' | 'row-reverse' | 'column' | 'column-reverse';
|
|
4
|
+
export type KptFlexWrap = 'wrap' | 'nowrap' | 'wrap-reverse';
|
|
5
|
+
export type KptAlignment = 'start' | 'end' | 'center' | 'stretch' | 'baseline' | 'space-between' | 'space-around' | 'space-evenly';
|
|
6
|
+
export interface KptFlexProps extends ComponentPropsWithRef<'div'>, AsChildProps {
|
|
7
|
+
/** Kierunek osi głównej — baza mobile-first. */
|
|
8
|
+
direction?: KptFlexDirection;
|
|
9
|
+
/** Kierunek od breakpointa MD (>= 768px). */
|
|
10
|
+
directionMd?: KptFlexDirection;
|
|
11
|
+
/** Kierunek od breakpointa LG (>= 1024px). */
|
|
12
|
+
directionLg?: KptFlexDirection;
|
|
13
|
+
/** Zawijanie elementów. */
|
|
14
|
+
wrap?: KptFlexWrap;
|
|
15
|
+
/** Rozkład wzdłuż osi głównej (`justify-content`). */
|
|
16
|
+
justify?: KptAlignment;
|
|
17
|
+
/** Rozkład wzdłuż osi głównej od breakpointa MD. */
|
|
18
|
+
justifyMd?: KptAlignment;
|
|
19
|
+
/** Wyrównanie w poprzek osi (`align-items`). */
|
|
20
|
+
align?: KptAlignment;
|
|
21
|
+
/** Wyrównanie w poprzek osi od breakpointa MD. */
|
|
22
|
+
alignMd?: KptAlignment;
|
|
23
|
+
/** Odstęp w obu osiach. */
|
|
24
|
+
gap?: string;
|
|
25
|
+
/** Odstęp w poziomie. */
|
|
26
|
+
gapX?: string;
|
|
27
|
+
/** Odstęp w pionie. */
|
|
28
|
+
gapY?: string;
|
|
29
|
+
/** Tryb kontenerowy — zmienne dzieci reagują na szerokość tego kontenera. */
|
|
30
|
+
container?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Kontener flexbox Koncept UI — te same zmienne i breakpointy co `KptGrid`.
|
|
34
|
+
* Dla wartości bez odpowiednika w propsach (`grow`, `shrink`, `order` na dziecku)
|
|
35
|
+
* używa się klas utility: `kpt-grow-1`, `kpt-order-first`, `kpt-self-end`.
|
|
36
|
+
*
|
|
37
|
+
* Wymaga arkusza `@konce-pt/grid` (`import '@konce-pt/grid';`).
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* <KptFlex direction="column" directionMd="row" justify="space-between" gap="1rem">
|
|
41
|
+
* <span>Lewa</span>
|
|
42
|
+
* <span className="kpt-order-first kpt-order-md-none">Prawa</span>
|
|
43
|
+
* </KptFlex>
|
|
44
|
+
*/
|
|
45
|
+
export declare function KptFlex({ direction, directionMd, directionLg, wrap, justify, justifyMd, align, alignMd, gap, gapX, gapY, container, asChild, className, style, children, ...rest }: Readonly<KptFlexProps>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { cn } from "../internal/cn.js";
|
|
2
|
+
import { layoutStyle, renderLayout } from "./layout.js";
|
|
3
|
+
/**
|
|
4
|
+
* Kontener flexbox Koncept UI — te same zmienne i breakpointy co `KptGrid`.
|
|
5
|
+
* Dla wartości bez odpowiednika w propsach (`grow`, `shrink`, `order` na dziecku)
|
|
6
|
+
* używa się klas utility: `kpt-grow-1`, `kpt-order-first`, `kpt-self-end`.
|
|
7
|
+
*
|
|
8
|
+
* Wymaga arkusza `@konce-pt/grid` (`import '@konce-pt/grid';`).
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* <KptFlex direction="column" directionMd="row" justify="space-between" gap="1rem">
|
|
12
|
+
* <span>Lewa</span>
|
|
13
|
+
* <span className="kpt-order-first kpt-order-md-none">Prawa</span>
|
|
14
|
+
* </KptFlex>
|
|
15
|
+
*/
|
|
16
|
+
export function KptFlex({ direction, directionMd, directionLg, wrap, justify, justifyMd, align, alignMd, gap, gapX, gapY, container = false, asChild = false, className, style, children, ...rest }) {
|
|
17
|
+
return renderLayout(asChild, children, {
|
|
18
|
+
className: cn('kpt-flex', className),
|
|
19
|
+
'data-container': container ? '' : undefined,
|
|
20
|
+
style: layoutStyle({
|
|
21
|
+
'--kpt-flex-direction': direction,
|
|
22
|
+
'--kpt-flex-direction-md': directionMd,
|
|
23
|
+
'--kpt-flex-direction-lg': directionLg,
|
|
24
|
+
'--kpt-flex-wrap': wrap,
|
|
25
|
+
'--kpt-justify': justify,
|
|
26
|
+
'--kpt-justify-md': justifyMd,
|
|
27
|
+
'--kpt-align': align,
|
|
28
|
+
'--kpt-align-md': alignMd,
|
|
29
|
+
'--kpt-gap': gap,
|
|
30
|
+
'--kpt-gap-x': gapX,
|
|
31
|
+
'--kpt-gap-y': gapY,
|
|
32
|
+
}, style),
|
|
33
|
+
...rest,
|
|
34
|
+
}, 'div');
|
|
35
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ComponentPropsWithRef } from 'react';
|
|
2
|
+
import type { AsChildProps } from '../internal/types.ts';
|
|
3
|
+
export interface KptGridProps extends ComponentPropsWithRef<'div'>, AsChildProps {
|
|
4
|
+
/** Liczba kolumn — baza mobile-first. Domyślnie 12 (z CSS). */
|
|
5
|
+
columns?: number;
|
|
6
|
+
/** Liczba kolumn od breakpointa SM (>= 640px). */
|
|
7
|
+
columnsSm?: number;
|
|
8
|
+
/** Liczba kolumn od breakpointa MD (>= 768px). */
|
|
9
|
+
columnsMd?: number;
|
|
10
|
+
/** Liczba kolumn od breakpointa LG (>= 1024px). */
|
|
11
|
+
columnsLg?: number;
|
|
12
|
+
/** Liczba kolumn od breakpointa XL (>= 1280px). */
|
|
13
|
+
columnsXl?: number;
|
|
14
|
+
/** Liczba kolumn od breakpointa 2XL (>= 1536px). */
|
|
15
|
+
columns2xl?: number;
|
|
16
|
+
/** Odstęp w obu osiach, np. `'1.5rem'` albo `'var(--kpt-space-6)'`. */
|
|
17
|
+
gap?: string;
|
|
18
|
+
/** Odstęp między kolumnami — nadpisuje `gap` w poziomie. */
|
|
19
|
+
gapX?: string;
|
|
20
|
+
/** Odstęp między wierszami — nadpisuje `gap` w pionie. */
|
|
21
|
+
gapY?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Tryb kontenerowy: spany dzieci reagują na szerokość TEJ siatki, nie okna.
|
|
24
|
+
* Liczba kolumn i odstępy nadal idą za viewportem — `@container` nie potrafi
|
|
25
|
+
* odpytać elementu o jego własny kontener.
|
|
26
|
+
*/
|
|
27
|
+
container?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Siatka Koncept UI — CSS Grid sterowany custom properties z `@konce-pt/grid`.
|
|
31
|
+
*
|
|
32
|
+
* Odpowiednik dyrektywy `kptGrid` z portu Angulara. Dyrektyw w Reakcie nie ma, więc siatka jest
|
|
33
|
+
* komponentem — ale takim, który w trybie `asChild` niczego nie dokłada do DOM: przejmuje element,
|
|
34
|
+
* który i tak renderujesz (`<section>`, `<ul>`, `<main>`).
|
|
35
|
+
*
|
|
36
|
+
* Zmiana `columns` nie manipuluje klasami — ustawia zmienną inline, a układ przelicza
|
|
37
|
+
* natywny silnik CSS.
|
|
38
|
+
*
|
|
39
|
+
* Wymaga arkusza `@konce-pt/grid` (`import '@konce-pt/grid';`).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* <KptGrid columns={18} gap="1.5rem">
|
|
43
|
+
* <KptCol span={18} spanLg={5}>Sidebar</KptCol>
|
|
44
|
+
* <KptCol span={18} spanLg={13}>Treść</KptCol>
|
|
45
|
+
* </KptGrid>
|
|
46
|
+
*/
|
|
47
|
+
export declare function KptGrid({ columns, columnsSm, columnsMd, columnsLg, columnsXl, columns2xl, gap, gapX, gapY, container, asChild, className, style, children, ...rest }: Readonly<KptGridProps>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { cn } from "../internal/cn.js";
|
|
2
|
+
import { layoutStyle, renderLayout } from "./layout.js";
|
|
3
|
+
/**
|
|
4
|
+
* Siatka Koncept UI — CSS Grid sterowany custom properties z `@konce-pt/grid`.
|
|
5
|
+
*
|
|
6
|
+
* Odpowiednik dyrektywy `kptGrid` z portu Angulara. Dyrektyw w Reakcie nie ma, więc siatka jest
|
|
7
|
+
* komponentem — ale takim, który w trybie `asChild` niczego nie dokłada do DOM: przejmuje element,
|
|
8
|
+
* który i tak renderujesz (`<section>`, `<ul>`, `<main>`).
|
|
9
|
+
*
|
|
10
|
+
* Zmiana `columns` nie manipuluje klasami — ustawia zmienną inline, a układ przelicza
|
|
11
|
+
* natywny silnik CSS.
|
|
12
|
+
*
|
|
13
|
+
* Wymaga arkusza `@konce-pt/grid` (`import '@konce-pt/grid';`).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* <KptGrid columns={18} gap="1.5rem">
|
|
17
|
+
* <KptCol span={18} spanLg={5}>Sidebar</KptCol>
|
|
18
|
+
* <KptCol span={18} spanLg={13}>Treść</KptCol>
|
|
19
|
+
* </KptGrid>
|
|
20
|
+
*/
|
|
21
|
+
export function KptGrid({ columns, columnsSm, columnsMd, columnsLg, columnsXl, columns2xl, gap, gapX, gapY, container = false, asChild = false, className, style, children, ...rest }) {
|
|
22
|
+
return renderLayout(asChild, children, {
|
|
23
|
+
className: cn('kpt-grid', className),
|
|
24
|
+
'data-container': container ? '' : undefined,
|
|
25
|
+
style: layoutStyle({
|
|
26
|
+
'--kpt-grid-columns': columns,
|
|
27
|
+
'--kpt-grid-columns-sm': columnsSm,
|
|
28
|
+
'--kpt-grid-columns-md': columnsMd,
|
|
29
|
+
'--kpt-grid-columns-lg': columnsLg,
|
|
30
|
+
'--kpt-grid-columns-xl': columnsXl,
|
|
31
|
+
'--kpt-grid-columns-2xl': columns2xl,
|
|
32
|
+
'--kpt-gap': gap,
|
|
33
|
+
'--kpt-gap-x': gapX,
|
|
34
|
+
'--kpt-gap-y': gapY,
|
|
35
|
+
}, style),
|
|
36
|
+
...rest,
|
|
37
|
+
}, 'div');
|
|
38
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactElement, type ReactNode } from 'react';
|
|
2
|
+
/** Wartość custom property układu: liczba, dowolna wartość CSS albo brak. */
|
|
3
|
+
export type KptLayoutValue = number | string | undefined;
|
|
4
|
+
/**
|
|
5
|
+
* Składa custom properties układu w obiekt `style`, pomijając te bez wartości.
|
|
6
|
+
*
|
|
7
|
+
* Pominięcie jest istotne: `--kpt-col: undefined` nadpisałoby wartość z klasy utility albo
|
|
8
|
+
* z arkusza, a dyrektywy Angulara w takiej sytuacji nic nie ustawiają (`?? null`).
|
|
9
|
+
* Styl podany przez wołającego idzie na końcu, więc wygrywa.
|
|
10
|
+
*/
|
|
11
|
+
export declare function layoutStyle(vars: Readonly<Record<string, KptLayoutValue>>, style: CSSProperties | undefined): CSSProperties;
|
|
12
|
+
/**
|
|
13
|
+
* Renderuje element układu albo — w trybie `asChild` — oddaje propsy jedynemu dziecku.
|
|
14
|
+
*
|
|
15
|
+
* To reactowy odpowiednik dyrektywy: `<KptCol asChild><li>…</li></KptCol>` nie dokłada żadnego
|
|
16
|
+
* elementu do DOM, dokładnie jak `<li kptCol="6">` w Angularze.
|
|
17
|
+
*/
|
|
18
|
+
export declare function renderLayout(asChild: boolean, children: ReactNode, props: Record<string, unknown>, element: 'div' | 'span'): ReactElement;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cloneElement, isValidElement } from 'react';
|
|
3
|
+
import { mergeSlotProps } from "../internal/slot.js";
|
|
4
|
+
/**
|
|
5
|
+
* Składa custom properties układu w obiekt `style`, pomijając te bez wartości.
|
|
6
|
+
*
|
|
7
|
+
* Pominięcie jest istotne: `--kpt-col: undefined` nadpisałoby wartość z klasy utility albo
|
|
8
|
+
* z arkusza, a dyrektywy Angulara w takiej sytuacji nic nie ustawiają (`?? null`).
|
|
9
|
+
* Styl podany przez wołającego idzie na końcu, więc wygrywa.
|
|
10
|
+
*/
|
|
11
|
+
export function layoutStyle(vars, style) {
|
|
12
|
+
const result = {};
|
|
13
|
+
for (const [name, value] of Object.entries(vars)) {
|
|
14
|
+
if (value !== undefined && value !== null && value !== '')
|
|
15
|
+
result[name] = value;
|
|
16
|
+
}
|
|
17
|
+
return { ...result, ...style };
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Renderuje element układu albo — w trybie `asChild` — oddaje propsy jedynemu dziecku.
|
|
21
|
+
*
|
|
22
|
+
* To reactowy odpowiednik dyrektywy: `<KptCol asChild><li>…</li></KptCol>` nie dokłada żadnego
|
|
23
|
+
* elementu do DOM, dokładnie jak `<li kptCol="6">` w Angularze.
|
|
24
|
+
*/
|
|
25
|
+
export function renderLayout(asChild, children, props, element) {
|
|
26
|
+
if (asChild && isValidElement(children)) {
|
|
27
|
+
const child = children;
|
|
28
|
+
return cloneElement(child, mergeSlotProps(props, child.props));
|
|
29
|
+
}
|
|
30
|
+
const Tag = element;
|
|
31
|
+
return _jsx(Tag, { ...props, children: children });
|
|
32
|
+
}
|