@konce-pt/react 0.11.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -64
- package/dist/accordion/accordion.d.ts +14 -6
- package/dist/accordion/accordion.js +25 -17
- package/dist/accordion/llms.txt +22 -10
- package/dist/alert/alert.d.ts +2 -2
- package/dist/alert/alert.js +3 -2
- package/dist/alert/llms.txt +10 -9
- package/dist/app-shell/app-shell.d.ts +14 -14
- package/dist/app-shell/app-shell.js +22 -15
- package/dist/app-shell/llms.txt +16 -15
- package/dist/auth/auth-types.d.ts +6 -6
- package/dist/auth/auth.d.ts +2 -2
- package/dist/auth/auth.js +24 -15
- package/dist/auth/llms.txt +12 -11
- package/dist/autocomplete/autocomplete.d.ts +19 -6
- package/dist/autocomplete/autocomplete.js +32 -11
- package/dist/autocomplete/llms.txt +19 -5
- package/dist/avatar/avatar.d.ts +6 -6
- package/dist/avatar/avatar.js +6 -5
- package/dist/avatar/llms.txt +10 -10
- package/dist/avatar-group/avatar-group.d.ts +4 -4
- package/dist/avatar-group/avatar-group.js +4 -3
- package/dist/avatar-group/llms.txt +8 -8
- package/dist/backdrop/backdrop.d.ts +7 -26
- package/dist/backdrop/backdrop.js +32 -27
- package/dist/backdrop/llms.txt +27 -27
- package/dist/badge/badge.d.ts +3 -3
- package/dist/badge/badge.js +1 -1
- package/dist/badge/llms.txt +11 -11
- package/dist/bottom-sheet/bottom-sheet.d.ts +8 -3
- package/dist/bottom-sheet/bottom-sheet.js +5 -4
- package/dist/bottom-sheet/llms.txt +11 -8
- package/dist/breadcrumb/breadcrumb.d.ts +8 -2
- package/dist/breadcrumb/breadcrumb.js +11 -3
- package/dist/breadcrumb/llms.txt +10 -2
- package/dist/button/button.d.ts +3 -3
- package/dist/button/button.js +10 -9
- package/dist/button/llms.txt +27 -19
- package/dist/button-group/button-group.d.ts +18 -5
- package/dist/button-group/button-group.js +54 -6
- package/dist/button-group/llms.txt +27 -18
- package/dist/card/card.d.ts +8 -8
- package/dist/card/card.js +10 -9
- package/dist/card/llms.txt +20 -20
- package/dist/carousel/carousel.d.ts +6 -6
- package/dist/carousel/carousel.js +8 -5
- package/dist/carousel/llms.txt +10 -10
- package/dist/charts/chart-legend.d.ts +3 -3
- package/dist/charts/chart-legend.js +2 -1
- package/dist/charts/chart-tooltip.d.ts +3 -3
- package/dist/charts/chart-tooltip.js +1 -1
- package/dist/charts/chart.d.ts +4 -3
- package/dist/charts/chart.js +18 -10
- package/dist/charts/llms.txt +10 -7
- package/dist/charts-entry/public-api.js +2 -2
- package/dist/chat/chat.d.ts +17 -10
- package/dist/chat/chat.js +77 -23
- package/dist/chat/llms.txt +39 -15
- package/dist/chat-composer/chat-composer.d.ts +20 -7
- package/dist/chat-composer/chat-composer.js +29 -7
- package/dist/chat-composer/llms.txt +20 -11
- package/dist/chat-dock/chat-dock.d.ts +11 -4
- package/dist/chat-dock/chat-dock.js +10 -6
- package/dist/chat-dock/llms.txt +15 -14
- package/dist/chat-entry/public-api.js +1 -1
- package/dist/chat-message/chat-message.d.ts +12 -5
- package/dist/chat-message/chat-message.js +19 -8
- package/dist/chat-message/llms.txt +16 -15
- package/dist/chat-typing/chat-typing.d.ts +2 -2
- package/dist/chat-typing/chat-typing.js +4 -3
- package/dist/chat-typing/llms.txt +6 -6
- package/dist/checkbox/checkbox.d.ts +13 -6
- package/dist/checkbox/checkbox.js +31 -5
- package/dist/checkbox/llms.txt +26 -11
- package/dist/chip/chip.d.ts +4 -4
- package/dist/chip/chip.js +3 -2
- package/dist/chip/llms.txt +11 -11
- package/dist/chips-input/chips-input.d.ts +6 -4
- package/dist/chips-input/chips-input.js +47 -12
- package/dist/chips-input/llms.txt +18 -8
- package/dist/clock/clock.d.ts +11 -6
- package/dist/clock/clock.js +38 -8
- package/dist/clock/llms.txt +12 -8
- package/dist/color-picker/color-picker.d.ts +9 -5
- package/dist/color-picker/color-picker.js +37 -18
- package/dist/color-picker/llms.txt +8 -5
- package/dist/confirm/confirm-container.d.ts +3 -3
- package/dist/confirm/confirm-container.js +6 -5
- package/dist/confirm/confirm-store.d.ts +4 -4
- package/dist/confirm/confirm-store.js +11 -5
- package/dist/confirm/llms.txt +8 -7
- package/dist/context-menu/context-menu.d.ts +1 -1
- package/dist/context-menu/context-menu.js +37 -14
- package/dist/context-menu/llms.txt +10 -7
- package/dist/data-table/data-table-types.d.ts +5 -5
- package/dist/data-table/data-table.d.ts +37 -5
- package/dist/data-table/data-table.js +426 -119
- package/dist/data-table/export-csv.d.ts +3 -3
- package/dist/data-table/export-csv.js +8 -10
- package/dist/data-table/llms.txt +127 -79
- package/dist/data-view/data-view.d.ts +13 -5
- package/dist/data-view/data-view.js +68 -6
- package/dist/data-view/llms.txt +29 -10
- package/dist/date-range/date-range.d.ts +20 -8
- package/dist/date-range/date-range.js +86 -63
- package/dist/date-range/llms.txt +32 -18
- package/dist/datepicker/datepicker.d.ts +22 -8
- package/dist/datepicker/datepicker.js +103 -71
- package/dist/datepicker/llms.txt +36 -22
- package/dist/dialog/dialog.d.ts +4 -4
- package/dist/dialog/dialog.js +32 -11
- package/dist/dialog/llms.txt +13 -10
- package/dist/divider/divider.d.ts +7 -1
- package/dist/divider/divider.js +3 -2
- package/dist/divider/llms.txt +4 -3
- package/dist/drawer/drawer.d.ts +9 -4
- package/dist/drawer/drawer.js +5 -4
- package/dist/drawer/llms.txt +13 -10
- package/dist/empty/empty.d.ts +2 -2
- package/dist/empty/empty.js +1 -1
- package/dist/empty/llms.txt +9 -9
- package/dist/fab/fab.d.ts +1 -1
- package/dist/fab/fab.js +1 -1
- package/dist/fab/llms.txt +10 -6
- package/dist/fieldset/fieldset.d.ts +18 -4
- package/dist/fieldset/fieldset.js +12 -6
- package/dist/fieldset/llms.txt +26 -9
- package/dist/file-upload/file-upload.d.ts +8 -2
- package/dist/file-upload/file-upload.js +22 -11
- package/dist/file-upload/llms.txt +12 -9
- package/dist/form-field/form-field-context.d.ts +4 -4
- package/dist/form-field/form-field.d.ts +12 -4
- package/dist/form-field/form-field.js +27 -6
- package/dist/form-field/llms.txt +25 -11
- package/dist/galleria/galleria.d.ts +3 -3
- package/dist/galleria/galleria.js +9 -6
- package/dist/galleria/llms.txt +7 -7
- package/dist/grid/col.d.ts +4 -4
- package/dist/grid/col.js +2 -2
- package/dist/grid/flex.d.ts +3 -3
- package/dist/grid/flex.js +1 -1
- package/dist/grid/grid.d.ts +7 -7
- package/dist/grid/grid.js +3 -3
- package/dist/grid/layout.d.ts +2 -2
- package/dist/grid/layout.js +2 -2
- package/dist/grid/llms.txt +15 -15
- package/dist/grid-entry/public-api.js +1 -1
- package/dist/i18n/i18n-context.d.ts +6 -6
- package/dist/i18n/i18n-context.js +27 -5
- package/dist/icon/icon-registry.d.ts +3 -3
- package/dist/icon/icon-registry.js +3 -3
- package/dist/icon/icon.d.ts +4 -4
- package/dist/icon/icon.js +10 -7
- package/dist/icon/llms.txt +13 -13
- package/dist/icon-button/icon-button.d.ts +2 -2
- package/dist/icon-button/icon-button.js +1 -1
- package/dist/icon-button/llms.txt +9 -5
- package/dist/icons-entry/public-api.d.ts +2 -2
- package/dist/icons-entry/public-api.js +3 -3
- package/dist/image/image.js +5 -5
- package/dist/image/llms.txt +13 -13
- package/dist/input/input.d.ts +18 -5
- package/dist/input/input.js +22 -6
- package/dist/input/llms.txt +25 -11
- package/dist/input-mask/input-mask.d.ts +7 -2
- package/dist/input-mask/input-mask.js +17 -43
- package/dist/input-mask/llms.txt +8 -5
- package/dist/input-number/input-number.d.ts +11 -9
- package/dist/input-number/input-number.js +25 -21
- package/dist/input-number/llms.txt +17 -14
- package/dist/input-otp/input-otp.d.ts +18 -5
- package/dist/input-otp/input-otp.js +48 -24
- package/dist/input-otp/llms.txt +18 -7
- package/dist/internal/calendar-focus.d.ts +1 -1
- package/dist/internal/calendar-focus.js +3 -3
- package/dist/internal/cn.d.ts +1 -1
- package/dist/internal/mask.d.ts +14 -0
- package/dist/internal/mask.js +62 -0
- package/dist/internal/number-group.d.ts +22 -0
- package/dist/internal/number-group.js +53 -0
- package/dist/internal/option-key.d.ts +6 -0
- package/dist/internal/option-key.js +8 -0
- package/dist/internal/option-nav.d.ts +4 -4
- package/dist/internal/option-nav.js +5 -5
- package/dist/internal/overlay-container.js +1 -1
- package/dist/internal/overlay.d.ts +3 -3
- package/dist/internal/overlay.js +40 -10
- package/dist/internal/password-strength.d.ts +6 -0
- package/dist/internal/password-strength.js +74 -0
- package/dist/internal/roving.d.ts +2 -2
- package/dist/internal/roving.js +3 -3
- package/dist/internal/scroll-lock.d.ts +6 -0
- package/dist/internal/scroll-lock.js +35 -0
- package/dist/internal/slot-children.d.ts +13 -0
- package/dist/internal/slot-children.js +31 -0
- package/dist/internal/slot.d.ts +3 -3
- package/dist/internal/slot.js +2 -2
- package/dist/internal/step.d.ts +12 -0
- package/dist/internal/step.js +31 -0
- package/dist/internal/tween.d.ts +5 -5
- package/dist/internal/tween.js +7 -8
- package/dist/internal/types.d.ts +2 -2
- package/dist/internal/use-breakpoint.d.ts +2 -2
- package/dist/internal/use-breakpoint.js +4 -4
- package/dist/internal/use-controllable-state.d.ts +5 -0
- package/dist/internal/use-controllable-state.js +25 -4
- package/dist/internal/use-id.d.ts +2 -2
- package/dist/internal/use-id.js +2 -2
- package/dist/internal/use-modal-focus.d.ts +2 -1
- package/dist/internal/use-modal-focus.js +14 -3
- package/dist/knob/knob.d.ts +7 -4
- package/dist/knob/knob.js +27 -22
- package/dist/knob/llms.txt +18 -11
- package/dist/listbox/listbox.d.ts +8 -6
- package/dist/listbox/listbox.js +37 -17
- package/dist/listbox/llms.txt +12 -9
- package/dist/loader/llms.txt +56 -0
- package/dist/loader/loader.d.ts +49 -0
- package/dist/loader/loader.js +68 -0
- package/dist/map/llms.txt +30 -23
- package/dist/map/map-create-dialog.d.ts +4 -4
- package/dist/map/map-create-dialog.js +36 -28
- package/dist/map/map-hours-field.d.ts +4 -4
- package/dist/map/map-hours-field.js +8 -7
- package/dist/map/map-image-field.d.ts +2 -2
- package/dist/map/map-image-field.js +6 -5
- package/dist/map/map-legend.d.ts +4 -4
- package/dist/map/map-legend.js +3 -2
- package/dist/map/map-poi-card.d.ts +3 -3
- package/dist/map/map-poi-card.js +10 -9
- package/dist/map/map-search.d.ts +17 -6
- package/dist/map/map-search.js +70 -43
- package/dist/map/map.d.ts +25 -13
- package/dist/map/map.js +86 -57
- package/dist/map/ports.d.ts +9 -9
- package/dist/map/ports.js +6 -6
- package/dist/map-entry/public-api.js +2 -2
- package/dist/megamenu/llms.txt +18 -7
- package/dist/megamenu/megamenu.d.ts +12 -6
- package/dist/megamenu/megamenu.js +23 -14
- package/dist/mention/llms.txt +15 -15
- package/dist/mention/mention.d.ts +5 -5
- package/dist/mention/mention.js +2 -2
- package/dist/mention/mentions.d.ts +1 -1
- package/dist/mention/mentions.js +1 -1
- package/dist/menu/llms.txt +12 -12
- package/dist/menu/menu-item.d.ts +4 -4
- package/dist/menu/menu-keys.d.ts +2 -2
- package/dist/menu/menu-keys.js +5 -5
- package/dist/menu/menu-rows.js +1 -0
- package/dist/menu/menu.d.ts +2 -2
- package/dist/menu/menu.js +15 -8
- package/dist/menubar/llms.txt +19 -8
- package/dist/menubar/menubar.d.ts +11 -5
- package/dist/menubar/menubar.js +23 -11
- package/dist/meter-group/llms.txt +12 -12
- package/dist/meter-group/meter-group.d.ts +2 -2
- package/dist/meter-group/meter-group.js +2 -1
- package/dist/motion/motion-context.d.ts +22 -0
- package/dist/motion/motion-context.js +28 -0
- package/dist/order-list/llms.txt +24 -9
- package/dist/order-list/order-list.d.ts +12 -4
- package/dist/order-list/order-list.js +123 -25
- package/dist/paginator/llms.txt +8 -8
- package/dist/paginator/paginator.js +7 -4
- package/dist/panel/llms.txt +25 -13
- package/dist/panel/panel.d.ts +11 -3
- package/dist/panel/panel.js +12 -7
- package/dist/password/llms.txt +19 -7
- package/dist/password/password.d.ts +2 -2
- package/dist/password/password.js +27 -16
- package/dist/peek/llms.txt +11 -11
- package/dist/peek/peek.d.ts +6 -6
- package/dist/peek/peek.js +41 -19
- package/dist/pick-list/llms.txt +35 -12
- package/dist/pick-list/pick-list.d.ts +12 -4
- package/dist/pick-list/pick-list.js +128 -24
- package/dist/popover/llms.txt +13 -10
- package/dist/popover/popover.d.ts +6 -4
- package/dist/popover/popover.js +14 -7
- package/dist/progress/llms.txt +17 -17
- package/dist/progress/progress.d.ts +7 -7
- package/dist/progress/progress.js +7 -6
- package/dist/public-api.d.ts +16 -4
- package/dist/public-api.js +13 -7
- package/dist/radio-group/llms.txt +16 -6
- package/dist/radio-group/radio-group.d.ts +12 -3
- package/dist/radio-group/radio-group.js +23 -4
- package/dist/rating/llms.txt +20 -13
- package/dist/rating/rating-pointer.d.ts +16 -0
- package/dist/rating/rating-pointer.js +26 -0
- package/dist/rating/rating.d.ts +6 -6
- package/dist/rating/rating.js +77 -12
- package/dist/rich-text/lists.d.ts +2 -2
- package/dist/rich-text/lists.js +7 -7
- package/dist/rich-text/llms.txt +35 -12
- package/dist/rich-text/rich-text.d.ts +13 -14
- package/dist/rich-text/rich-text.js +311 -142
- package/dist/rich-text/sanitize.d.ts +11 -2
- package/dist/rich-text/sanitize.js +80 -32
- package/dist/rich-text/tables.d.ts +3 -3
- package/dist/rich-text/tables.js +3 -3
- package/dist/roadmap/llms.txt +23 -17
- package/dist/roadmap/roadmap.d.ts +6 -6
- package/dist/roadmap/roadmap.js +102 -25
- package/dist/roadmap-entry/public-api.js +2 -2
- package/dist/scroll-top/llms.txt +6 -6
- package/dist/scroll-top/scroll-top.d.ts +1 -1
- package/dist/scroll-top/scroll-top.js +2 -1
- package/dist/select/llms.txt +22 -12
- package/dist/select/select.d.ts +10 -8
- package/dist/select/select.js +87 -47
- package/dist/shared/types.d.ts +22 -1
- package/dist/shared/types.js +9 -1
- package/dist/sidenav/llms.txt +9 -9
- package/dist/sidenav/sidenav.d.ts +2 -3
- package/dist/sidenav/sidenav.js +5 -4
- package/dist/skeleton/llms.txt +3 -3
- package/dist/skeleton/skeleton.d.ts +1 -1
- package/dist/skeleton/skeleton.js +1 -1
- package/dist/slider/llms.txt +34 -12
- package/dist/slider/slider-drag.d.ts +26 -0
- package/dist/slider/slider-drag.js +79 -0
- package/dist/slider/slider.d.ts +8 -5
- package/dist/slider/slider.js +38 -8
- package/dist/speech/llms.txt +97 -0
- package/dist/speech/speech-button.d.ts +44 -0
- package/dist/speech/speech-button.js +86 -0
- package/dist/speech/speech-wave.d.ts +19 -0
- package/dist/speech/speech-wave.js +16 -0
- package/dist/speech/use-speech-recognition.d.ts +81 -0
- package/dist/speech/use-speech-recognition.js +179 -0
- package/dist/speed-dial/llms.txt +14 -8
- package/dist/speed-dial/speed-dial.d.ts +1 -1
- package/dist/speed-dial/speed-dial.js +3 -2
- package/dist/spinner/llms.txt +7 -7
- package/dist/spinner/spinner.d.ts +1 -1
- package/dist/spinner/spinner.js +2 -1
- package/dist/split-button/llms.txt +21 -15
- package/dist/split-button/split-button.d.ts +2 -2
- package/dist/split-button/split-button.js +13 -6
- package/dist/splitter/llms.txt +11 -11
- package/dist/splitter/splitter.d.ts +3 -3
- package/dist/splitter/splitter.js +25 -10
- package/dist/stepper/llms.txt +35 -13
- package/dist/stepper/stepper.d.ts +6 -6
- package/dist/stepper/stepper.js +60 -13
- package/dist/switch/llms.txt +15 -5
- package/dist/switch/switch.d.ts +10 -3
- package/dist/switch/switch.js +18 -4
- package/dist/switch-group/llms.txt +11 -8
- package/dist/switch-group/switch-group.d.ts +6 -4
- package/dist/switch-group/switch-group.js +9 -7
- package/dist/tabs/llms.txt +12 -9
- package/dist/tabs/tabs.d.ts +5 -5
- package/dist/tabs/tabs.js +36 -20
- package/dist/textarea/llms.txt +23 -12
- package/dist/textarea/textarea.d.ts +19 -6
- package/dist/textarea/textarea.js +22 -7
- package/dist/timeline/llms.txt +4 -4
- package/dist/timeline/timeline.d.ts +1 -1
- package/dist/timeline/timeline.js +1 -1
- package/dist/toast/llms.txt +50 -17
- package/dist/toast/toast-container.d.ts +9 -3
- package/dist/toast/toast-container.js +18 -9
- package/dist/toast/toast-store.d.ts +42 -2
- package/dist/toast/toast-store.js +36 -1
- package/dist/toolbar/llms.txt +7 -7
- package/dist/toolbar/toolbar.d.ts +3 -3
- package/dist/toolbar/toolbar.js +2 -2
- package/dist/tooltip/llms.txt +14 -12
- package/dist/tooltip/tooltip.d.ts +5 -4
- package/dist/tooltip/tooltip.js +100 -41
- package/dist/tree/llms.txt +25 -11
- package/dist/tree/tree-keys.d.ts +5 -5
- package/dist/tree/tree-keys.js +7 -7
- package/dist/tree/tree.d.ts +17 -5
- package/dist/tree/tree.js +62 -20
- package/dist/update/llms.txt +54 -0
- package/dist/update/update.d.ts +49 -0
- package/dist/update/update.js +82 -0
- package/package.json +18 -15
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
+
import { isValidElement, useRef, } from 'react';
|
|
3
4
|
import { cn } from "../internal/cn.js";
|
|
5
|
+
import { slotChildren, warnUnslottedChild } from "../internal/slot-children.js";
|
|
4
6
|
import { useControllableState } from "../internal/use-controllable-state.js";
|
|
5
7
|
import { useKptId } from "../internal/use-id.js";
|
|
6
8
|
import { useKptMessages } from "../i18n/i18n-context.js";
|
|
@@ -19,9 +21,9 @@ KptSplitterEnd.kptSplitterSlot = 'end';
|
|
|
19
21
|
* Dwa panele z przeciąganym uchwytem. `horizontal` stawia je obok siebie, `vertical` jeden pod
|
|
20
22
|
* drugim.
|
|
21
23
|
*
|
|
22
|
-
* Uchwyt to `role="separator"` z wartością (wzorzec WAI-ARIA
|
|
24
|
+
* Uchwyt to `role="separator"` z wartością (wzorzec WAI-ARIA "window splitter"): strzałki
|
|
23
25
|
* przesuwają go o 2%, `Home`/`End` dosuwają do minimum i maksimum. `aria-orientation` opisuje
|
|
24
|
-
* linię uchwytu, nie układ
|
|
26
|
+
* linię uchwytu, nie układ - przy panelach obok siebie linia jest pionowa.
|
|
25
27
|
*
|
|
26
28
|
* @example
|
|
27
29
|
* <KptSplitter startSize={size} onStartSizeChange={setSize}>
|
|
@@ -40,16 +42,18 @@ export function KptSplitter({ orientation = 'horizontal', startSize, defaultStar
|
|
|
40
42
|
});
|
|
41
43
|
let start = null;
|
|
42
44
|
let end = null;
|
|
43
|
-
|
|
44
|
-
if (!isValidElement(child))
|
|
45
|
-
|
|
45
|
+
for (const child of slotChildren(children)) {
|
|
46
|
+
if (!isValidElement(child)) {
|
|
47
|
+
warnUnslottedChild('KptSplitter', child, '<KptSplitter.Start> / <KptSplitter.End>');
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
46
50
|
const slot = child.type?.kptSplitterSlot;
|
|
47
51
|
const content = child.props.children;
|
|
48
52
|
if (slot === 'start')
|
|
49
53
|
start = content;
|
|
50
54
|
else if (slot === 'end')
|
|
51
55
|
end = content;
|
|
52
|
-
}
|
|
56
|
+
}
|
|
53
57
|
const clamp = (pct) => Math.min(100 - minSize, Math.max(minSize, Math.round(pct)));
|
|
54
58
|
const onPointerDown = (event) => {
|
|
55
59
|
event.preventDefault();
|
|
@@ -58,18 +62,24 @@ export function KptSplitter({ orientation = 'horizontal', startSize, defaultStar
|
|
|
58
62
|
return;
|
|
59
63
|
// Nasłuch na oknie, nie na uchwycie: przy szybkim ruchu kursor wyprzedza wąski pasek
|
|
60
64
|
// i bez tego przeciąganie urywałoby się po kilku pikselach.
|
|
65
|
+
// W RTL panel "start" stoi po prawej (flex idzie za kierunkiem pisma), więc mierzymy od prawej.
|
|
66
|
+
const rtl = getComputedStyle(container).direction === 'rtl';
|
|
61
67
|
const move = (e) => {
|
|
62
68
|
const rect = container.getBoundingClientRect();
|
|
63
69
|
setSize(clamp(orientation === 'horizontal'
|
|
64
|
-
? ((e.clientX - rect.left) / rect.width) * 100
|
|
70
|
+
? ((rtl ? rect.right - e.clientX : e.clientX - rect.left) / rect.width) * 100
|
|
65
71
|
: ((e.clientY - rect.top) / rect.height) * 100));
|
|
66
72
|
};
|
|
73
|
+
// `pointercancel`: dotyk przerwany przez system nie wysyła `pointerup` - bez sprzątania
|
|
74
|
+
// `pointermove` dalej przesuwałby uchwyt.
|
|
67
75
|
const up = () => {
|
|
68
76
|
window.removeEventListener('pointermove', move);
|
|
69
77
|
window.removeEventListener('pointerup', up);
|
|
78
|
+
window.removeEventListener('pointercancel', up);
|
|
70
79
|
};
|
|
71
80
|
window.addEventListener('pointermove', move);
|
|
72
81
|
window.addEventListener('pointerup', up);
|
|
82
|
+
window.addEventListener('pointercancel', up);
|
|
73
83
|
};
|
|
74
84
|
const onKeyDown = (event) => {
|
|
75
85
|
if (event.key === 'Home' || event.key === 'End') {
|
|
@@ -85,9 +95,14 @@ export function KptSplitter({ orientation = 'horizontal', startSize, defaultStar
|
|
|
85
95
|
if (!dir)
|
|
86
96
|
return;
|
|
87
97
|
event.preventDefault();
|
|
88
|
-
|
|
98
|
+
// W RTL <- przesuwa uchwyt w lewo, czyli powiększa prawy panel "start" - odwrotnie niż w LTR.
|
|
99
|
+
const horizontal = event.key === 'ArrowLeft' || event.key === 'ArrowRight';
|
|
100
|
+
const rtl = horizontal && getComputedStyle(event.currentTarget).direction === 'rtl';
|
|
101
|
+
setSize(clamp(size + (rtl ? -dir : dir)));
|
|
89
102
|
};
|
|
90
|
-
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", id: startId, style: { flexBasis: `${size}%` }, children: start }), _jsx("div", { className: "kpt-splitter__gutter", role: "separator",
|
|
103
|
+
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", id: startId, style: { flexBasis: `${size}%` }, children: start }), _jsx("div", { className: "kpt-splitter__gutter", role: "separator",
|
|
104
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- separator okna (APG Window Splitter) to fokusowalny widżet ze strzałkami
|
|
105
|
+
tabIndex: 0, "aria-orientation": orientation === 'horizontal' ? 'vertical' : 'horizontal', "aria-valuenow": size, "aria-valuemin": minSize, "aria-valuemax": 100 - minSize, "aria-controls": startId, "aria-label": ariaLabel || t('splitter.resize'), onPointerDown: onPointerDown, onKeyDown: onKeyDown }), _jsx("div", { className: "kpt-splitter__pane", style: { flexBasis: `${100 - size}%` }, children: end })] }) }));
|
|
91
106
|
}
|
|
92
107
|
KptSplitter.Start = KptSplitterStart;
|
|
93
108
|
KptSplitter.End = KptSplitterEnd;
|
package/dist/stepper/llms.txt
CHANGED
|
@@ -1,38 +1,42 @@
|
|
|
1
1
|
# KptStepper + KptStep (@konce-pt/react)
|
|
2
2
|
|
|
3
|
-
A step wizard
|
|
3
|
+
A step wizard - a header of numbered steps plus the active step's content.
|
|
4
4
|
Import: `import { KptStepper, useKptStepper } from '@konce-pt/react';`
|
|
5
5
|
|
|
6
6
|
## DOM
|
|
7
7
|
<div class="kpt-stepper-host" style="--kpt-anim-duration:500ms; --kpt-anim-dir:1">
|
|
8
8
|
<ol class="kpt-stepper__header">
|
|
9
9
|
<li class="kpt-stepper__step is-done">
|
|
10
|
-
<button class="kpt-stepper__marker" aria-label="Step 1: Account, completed"
|
|
10
|
+
<button class="kpt-stepper__marker" aria-label="Step 1: Account, completed">
|
|
11
|
+
<span class="kpt-stepper__num">1</span><span class="kpt-icon-host kpt-stepper__check"><!-- check --></span>
|
|
12
|
+
</button>
|
|
11
13
|
<span class="kpt-stepper__label" aria-hidden="true">Account</span>
|
|
12
|
-
<span class="kpt-stepper__connector"></span>
|
|
14
|
+
<span class="kpt-stepper__connector" style="--kpt-stepper-line-delay:60ms; --kpt-stepper-line-dur:420ms"></span>
|
|
13
15
|
</li>
|
|
14
|
-
|
|
16
|
+
...
|
|
15
17
|
</ol>
|
|
16
|
-
<
|
|
18
|
+
<span class="kpt-stepper__comet" aria-hidden="true"></span>
|
|
19
|
+
<div class="kpt-stepper__body"><div class="kpt-stepper__panel">...</div></div>
|
|
17
20
|
</div>
|
|
18
21
|
|
|
19
22
|
## KptStepper props
|
|
20
23
|
- `activeIndex` / `defaultActiveIndex` / `onActiveIndexChange`
|
|
21
|
-
- `animated`: boolean (default true), `animationDuration`: ms (default 500)
|
|
24
|
+
- `animated`: boolean (default true), `animationDuration`: ms (default 500) - the pace of the whole motion:
|
|
25
|
+
the content enter, and the line (a segment takes 0.84x, a multi-step jump fits in 1.8x)
|
|
22
26
|
- `className`, `ref` and every other `<div>` prop go to the host
|
|
23
27
|
|
|
24
28
|
## KptStepper.Step props
|
|
25
|
-
- `label`: string (required); `children`
|
|
29
|
+
- `label`: string (required); `children` - the step's content
|
|
26
30
|
|
|
27
31
|
## useKptStepper()
|
|
28
|
-
`{ activeIndex, count, next, prev, goTo }`
|
|
32
|
+
`{ activeIndex, count, next, prev, goTo }` - the replacement for Angular's `#s` + `s.next()`.
|
|
29
33
|
It reads a context the stepper provides around the panel, so it works only in a component
|
|
30
34
|
rendered inside a step (a hook cannot be called in the parent's body) and throws elsewhere.
|
|
31
35
|
`count` lets a step hide "Next" on the last one.
|
|
32
36
|
|
|
33
37
|
## The step is a config carrier
|
|
34
38
|
`KptStep` renders `null`; `KptStepper` reads its props and decides what to show, so only the
|
|
35
|
-
active step's content is ever mounted
|
|
39
|
+
active step's content is ever mounted - the same laziness as the `kpt-step` template in Angular.
|
|
36
40
|
|
|
37
41
|
## The panel is keyed by index
|
|
38
42
|
`key={active}` forces a remount on every change, otherwise the enter animation would have nothing
|
|
@@ -42,7 +46,7 @@ an earlier step animates from the other side.
|
|
|
42
46
|
## Examples
|
|
43
47
|
<KptStepper>
|
|
44
48
|
<KptStepper.Step label="Account"><StepNav /></KptStepper.Step>
|
|
45
|
-
<KptStepper.Step label="Profile"
|
|
49
|
+
<KptStepper.Step label="Profile">...</KptStepper.Step>
|
|
46
50
|
</KptStepper>
|
|
47
51
|
|
|
48
52
|
function StepNav() {
|
|
@@ -55,14 +59,32 @@ an earlier step animates from the other side.
|
|
|
55
59
|
);
|
|
56
60
|
}
|
|
57
61
|
|
|
62
|
+
## Motion
|
|
63
|
+
Switching steps reads as colour flowing: the state changes at once (classes, `aria-current`,
|
|
64
|
+
the marker names), but the connector fills from grey to `--kpt-color-primary` with a glowing comet
|
|
65
|
+
running along it, and a marker turns "done" (fills from the centre, the check pops in) only when the
|
|
66
|
+
colour reaches it; the new active step sends out a ring and keeps a soft glow. A jump over several
|
|
67
|
+
steps runs the segments one after another within ~0.9 s; going back retracts them from the end.
|
|
68
|
+
The content of the new step slides in from the side of the move and sharpens out of a blur, the old
|
|
69
|
+
one leaves as a ghost the other way, and the body height changes smoothly.
|
|
70
|
+
|
|
71
|
+
The timings come from `stepperSchedule` in `@konce-pt/motion` (CSS variables
|
|
72
|
+
`--kpt-stepper-mark-delay`, `--kpt-stepper-line-delay`, `--kpt-stepper-line-dur` on the steps), the comet
|
|
73
|
+
and the ring from `playStepperLight`, the ghost from `preparePanelSwap`. Follows `animated` and `enter`
|
|
74
|
+
from `KptMotionProvider` (`none` - everything switches at once, `fade` - no comet and ring); `enabled: false` and the
|
|
75
|
+
system "reduce motion" setting always win.
|
|
76
|
+
|
|
58
77
|
## Tokens
|
|
59
78
|
The active and completed step: `--kpt-color-primary` (marker, connector); the rest
|
|
60
79
|
`--kpt-color-border-strong` and `--kpt-color-on-surface-muted`.
|
|
61
80
|
|
|
62
81
|
## Accessibility
|
|
63
82
|
The header is an `<ol>` of real buttons, so every step is reachable with the keyboard and the list
|
|
64
|
-
announces how many there are. Each marker is named from the dictionary
|
|
65
|
-
(
|
|
83
|
+
announces how many there are. Each marker is named from the dictionary - `stepper.step`
|
|
84
|
+
("Step 2: Delivery") or `stepper.stepDone` ("..., completed") - because the visible marker is only a
|
|
66
85
|
number or a check; the visible label is `aria-hidden` so it is not read twice. The active marker
|
|
67
|
-
carries `aria-current="step"`. After `next()` focus stays where it was
|
|
86
|
+
carries `aria-current="step"`. After `next()` focus stays where it was - move it into the new step
|
|
68
87
|
yourself when the step is long.
|
|
88
|
+
|
|
89
|
+
## Inactive content is destroyed
|
|
90
|
+
Switching renders the new panel from scratch (that is what the enter animation starts from), so local state inside the previous one - an unsent file upload, expanded sections, scroll position - is lost. Keep such state in your own model, outside the panel.
|
|
@@ -2,14 +2,14 @@ import { type ComponentPropsWithRef, type ReactNode } from 'react';
|
|
|
2
2
|
import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
|
|
3
3
|
export interface KptStepperContextValue {
|
|
4
4
|
activeIndex: number;
|
|
5
|
-
/** Liczba kroków
|
|
5
|
+
/** Liczba kroków - pozwala treści kroku ukryć "Dalej" na ostatnim. */
|
|
6
6
|
count: number;
|
|
7
7
|
next: () => void;
|
|
8
8
|
prev: () => void;
|
|
9
9
|
goTo: (index: number) => void;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
|
-
* Sterowanie kreatorem z wnętrza kroku
|
|
12
|
+
* Sterowanie kreatorem z wnętrza kroku - odpowiednik `#s` + `s.next()` z portu Angulara.
|
|
13
13
|
* Poza `<KptStepper>` rzuca błąd, bo bez kreatora nie ma czym sterować.
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
@@ -21,7 +21,7 @@ export interface KptStepProps {
|
|
|
21
21
|
children?: ReactNode;
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
|
-
* Pojedynczy krok. Umieszczaj w `<KptStepper>`. Treść renderuje się leniwie
|
|
24
|
+
* Pojedynczy krok. Umieszczaj w `<KptStepper>`. Treść renderuje się leniwie - dopiero gdy krok
|
|
25
25
|
* jest aktywny, tak samo jak szablon `kpt-step` w porcie Angulara.
|
|
26
26
|
*/
|
|
27
27
|
export declare function KptStep(_props: Readonly<KptStepProps>): ReactNode;
|
|
@@ -37,13 +37,13 @@ export interface KptStepperProps extends Omit<ComponentPropsWithRef<'div'>, 'onC
|
|
|
37
37
|
children?: ReactNode;
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
|
-
* Kreator kroków
|
|
40
|
+
* Kreator kroków - nagłówek z numerowanymi krokami i treść aktywnego kroku.
|
|
41
41
|
* Treścią sterują `next()`/`prev()`/`goTo()` z hooka `useKptStepper()`.
|
|
42
42
|
*
|
|
43
43
|
* @example
|
|
44
44
|
* <KptStepper>
|
|
45
|
-
* <KptStepper.Step label="Konto"
|
|
46
|
-
* <KptStepper.Step label="Profil"
|
|
45
|
+
* <KptStepper.Step label="Konto">...</KptStepper.Step>
|
|
46
|
+
* <KptStepper.Step label="Profil">...</KptStepper.Step>
|
|
47
47
|
* </KptStepper>
|
|
48
48
|
*/
|
|
49
49
|
export declare function KptStepper({ activeIndex, defaultActiveIndex, onActiveIndexChange, animated, animationDuration, locale, dictionary, className, style, children, ...rest }: Readonly<KptStepperProps>): import("react").JSX.Element;
|
package/dist/stepper/stepper.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
+
import { createContext, isValidElement, useContext, useLayoutEffect, useRef, useState, } from 'react';
|
|
3
4
|
import { cn } from "../internal/cn.js";
|
|
5
|
+
import { slotChildren, warnUnslottedChild } from "../internal/slot-children.js";
|
|
4
6
|
import { useControllableState } from "../internal/use-controllable-state.js";
|
|
5
7
|
import { useKptMessages } from "../i18n/i18n-context.js";
|
|
6
8
|
import { KptIcon } from "../icon/icon.js";
|
|
9
|
+
import { playStepperLight, preparePanelSwap, resolveEnterMotion, stepperSchedule, stepperScheduleOptions } from '@konce-pt/motion';
|
|
10
|
+
import { useKptMotion } from "../motion/motion-context.js";
|
|
7
11
|
const StepperContext = createContext(null);
|
|
8
12
|
/**
|
|
9
|
-
* Sterowanie kreatorem z wnętrza kroku
|
|
13
|
+
* Sterowanie kreatorem z wnętrza kroku - odpowiednik `#s` + `s.next()` z portu Angulara.
|
|
10
14
|
* Poza `<KptStepper>` rzuca błąd, bo bez kreatora nie ma czym sterować.
|
|
11
15
|
*
|
|
12
16
|
* @example
|
|
@@ -19,7 +23,7 @@ export function useKptStepper() {
|
|
|
19
23
|
return context;
|
|
20
24
|
}
|
|
21
25
|
/**
|
|
22
|
-
* Pojedynczy krok. Umieszczaj w `<KptStepper>`. Treść renderuje się leniwie
|
|
26
|
+
* Pojedynczy krok. Umieszczaj w `<KptStepper>`. Treść renderuje się leniwie - dopiero gdy krok
|
|
23
27
|
* jest aktywny, tak samo jak szablon `kpt-step` w porcie Angulara.
|
|
24
28
|
*/
|
|
25
29
|
export function KptStep(_props) {
|
|
@@ -28,13 +32,13 @@ export function KptStep(_props) {
|
|
|
28
32
|
}
|
|
29
33
|
KptStep.kptStepperSlot = 'step';
|
|
30
34
|
/**
|
|
31
|
-
* Kreator kroków
|
|
35
|
+
* Kreator kroków - nagłówek z numerowanymi krokami i treść aktywnego kroku.
|
|
32
36
|
* Treścią sterują `next()`/`prev()`/`goTo()` z hooka `useKptStepper()`.
|
|
33
37
|
*
|
|
34
38
|
* @example
|
|
35
39
|
* <KptStepper>
|
|
36
|
-
* <KptStepper.Step label="Konto"
|
|
37
|
-
* <KptStepper.Step label="Profil"
|
|
40
|
+
* <KptStepper.Step label="Konto">...</KptStepper.Step>
|
|
41
|
+
* <KptStepper.Step label="Profil">...</KptStepper.Step>
|
|
38
42
|
* </KptStepper>
|
|
39
43
|
*/
|
|
40
44
|
export function KptStepper({ activeIndex, defaultActiveIndex = 0, onActiveIndexChange, animated = true, animationDuration = 500, locale, dictionary, className, style, children, ...rest }) {
|
|
@@ -45,16 +49,56 @@ export function KptStepper({ activeIndex, defaultActiveIndex = 0, onActiveIndexC
|
|
|
45
49
|
onChange: onActiveIndexChange,
|
|
46
50
|
});
|
|
47
51
|
const [direction, setDirection] = useState(1);
|
|
52
|
+
/** Ruch przełączania idzie za `animated` i za `enter` z `KptMotionProvider` (`none` go wyłącza). */
|
|
53
|
+
const motionConfig = useKptMotion();
|
|
54
|
+
const motion = animated ? resolveEnterMotion(undefined, motionConfig) : 'none';
|
|
55
|
+
// Krok sprzed ostatniej zmiany - także przy zmianie z zewnątrz (`activeIndex`). Zapamiętany
|
|
56
|
+
// w stanie w trakcie renderu (wzorzec "informacja z poprzedniego renderu"), nie w efekcie.
|
|
57
|
+
const [transition, setTransition] = useState({ from: active, to: active });
|
|
58
|
+
if (transition.to !== active)
|
|
59
|
+
setTransition({ from: transition.to, to: active });
|
|
60
|
+
const rootRef = useRef(null);
|
|
61
|
+
const bodyRef = useRef(null);
|
|
62
|
+
/** Duch starej treści przygotowany przed zmianą kroku, odtwarzany po jej wyrenderowaniu. */
|
|
63
|
+
const pendingSwap = useRef(null);
|
|
48
64
|
const steps = [];
|
|
49
|
-
|
|
50
|
-
if (!isValidElement(child) || child.type?.kptStepperSlot !== 'step')
|
|
51
|
-
|
|
65
|
+
for (const child of slotChildren(children)) {
|
|
66
|
+
if (!isValidElement(child) || child.type?.kptStepperSlot !== 'step') {
|
|
67
|
+
warnUnslottedChild('KptStepper', child, '<KptStep>');
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
52
70
|
steps.push(child.props);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Kiedy widać zmianę każdego znacznika i odcinka linii (`stepperSchedule` z @konce-pt/motion):
|
|
74
|
+
* kolor płynie po linii i zapala znacznik dopiero, gdy do niego dotrze. Bez ruchu - same zera.
|
|
75
|
+
*/
|
|
76
|
+
// Tempo linii idzie za `animationDuration` - ten sam czas steruje całym ruchem, nie tylko treścią.
|
|
77
|
+
const schedule = stepperSchedule(steps.length, motion === 'none' ? active : transition.from, active, stepperScheduleOptions(animationDuration));
|
|
78
|
+
// Kometa po linii i fala w znaczniku, do którego dociera kolor; duch starej treści - przed malowaniem.
|
|
79
|
+
useLayoutEffect(() => {
|
|
80
|
+
const play = pendingSwap.current;
|
|
81
|
+
pendingSwap.current = null;
|
|
82
|
+
play?.();
|
|
53
83
|
});
|
|
84
|
+
useLayoutEffect(() => {
|
|
85
|
+
const root = rootRef.current;
|
|
86
|
+
if (!root || motion !== 'spring' || !schedule.direction)
|
|
87
|
+
return;
|
|
88
|
+
playStepperLight(schedule, root.querySelector('.kpt-stepper__comet'), Array.from(root.querySelectorAll('.kpt-stepper__connector')), Array.from(root.querySelectorAll('.kpt-stepper__marker')));
|
|
89
|
+
// Harmonogram liczy się z `transition` - gra raz na zmianę kroku, nie na każdy render.
|
|
90
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- schedule to pochodna transition i liczby kroków
|
|
91
|
+
}, [transition, motion]);
|
|
54
92
|
const goTo = (index) => {
|
|
55
93
|
const next = Math.max(0, Math.min(index, steps.length - 1));
|
|
94
|
+
if (next === active)
|
|
95
|
+
return;
|
|
56
96
|
// Kierunek karmi `--kpt-anim-dir`, więc panel wjeżdża z tej strony, z której się cofnąłeś.
|
|
57
|
-
|
|
97
|
+
const dir = next > active ? 1 : -1;
|
|
98
|
+
setDirection(dir);
|
|
99
|
+
// Stara treść wychodzi jako duch, a pojemnik płynnie zmienia wysokość - mierzone przed zmianą.
|
|
100
|
+
if (motion !== 'none' && bodyRef.current)
|
|
101
|
+
pendingSwap.current = preparePanelSwap(bodyRef.current, dir);
|
|
58
102
|
setActive(next);
|
|
59
103
|
};
|
|
60
104
|
const context = {
|
|
@@ -64,13 +108,16 @@ export function KptStepper({ activeIndex, defaultActiveIndex = 0, onActiveIndexC
|
|
|
64
108
|
prev: () => goTo(active - 1),
|
|
65
109
|
goTo,
|
|
66
110
|
};
|
|
67
|
-
return (_jsxs("div", { className: cn('kpt-stepper-host', className), style: {
|
|
111
|
+
return (_jsxs("div", { ref: rootRef, className: cn('kpt-stepper-host', className), style: {
|
|
68
112
|
['--kpt-anim-duration']: `${animated ? animationDuration : 0}ms`,
|
|
69
113
|
['--kpt-anim-dir']: direction,
|
|
70
114
|
...style,
|
|
71
|
-
}, ...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: [
|
|
115
|
+
}, ...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'), style: { ['--kpt-stepper-mark-delay']: `${schedule.markers[index] ?? 0}ms` }, children: [_jsxs("button", { type: "button", className: "kpt-stepper__marker", "aria-current": index === active ? 'step' : undefined, "aria-label": t(index < active ? 'stepper.stepDone' : 'stepper.step', {
|
|
72
116
|
index: index + 1,
|
|
73
117
|
label: step.label,
|
|
74
|
-
}), onClick: () => goTo(index), children: index
|
|
118
|
+
}), onClick: () => goTo(index), children: [_jsx("span", { className: "kpt-stepper__num", children: index + 1 }), _jsx(KptIcon, { className: "kpt-stepper__check", name: "check" })] }), _jsx("span", { className: "kpt-stepper__label", "aria-hidden": "true", children: step.label }), index < steps.length - 1 ? (_jsx("span", { className: "kpt-stepper__connector", style: {
|
|
119
|
+
['--kpt-stepper-line-delay']: `${schedule.lines[index]?.delay ?? 0}ms`,
|
|
120
|
+
['--kpt-stepper-line-dur']: `${schedule.lines[index]?.duration ?? 0}ms`,
|
|
121
|
+
} })) : null] }, index))) }), _jsx("span", { className: "kpt-stepper__comet", "aria-hidden": "true" }), _jsx(StepperContext.Provider, { value: context, children: _jsx("div", { className: "kpt-stepper__body", ref: bodyRef, children: steps[active] ? (_jsx("div", { className: "kpt-stepper__panel", children: steps[active].children }, active)) : null }) })] }));
|
|
75
122
|
}
|
|
76
123
|
KptStepper.Step = KptStep;
|
package/dist/switch/llms.txt
CHANGED
|
@@ -16,16 +16,17 @@ Import: `import { KptSwitch } from '@konce-pt/react';`
|
|
|
16
16
|
|
|
17
17
|
## Props
|
|
18
18
|
- `label`: string, `labelPosition`: 'start' | 'end' (default 'end')
|
|
19
|
-
- `onLabel`, `offLabel`: string
|
|
19
|
+
- `onLabel`, `offLabel`: string - the state text, swapped on toggle
|
|
20
20
|
- `checked` / `defaultChecked`, `onCheckedChange(checked)`, `onTouch()`
|
|
21
|
-
- `required`, `invalid`, `touched`
|
|
22
|
-
- `
|
|
21
|
+
- `required`, `invalid`, `touched` - as in `KptCheckbox`
|
|
22
|
+
- `toggleMotion`: 'spring' | 'fade' | 'none' (default from `KptMotionProvider`, else `spring`) - see "Toggle motion"
|
|
23
|
+
- `hostProps` - props for the `.kpt-switch-host` wrapper
|
|
23
24
|
- `className` goes to the `.kpt-switch` block; the rest to the native `<input>`
|
|
24
25
|
|
|
25
26
|
## The state text needs a controlled value
|
|
26
27
|
`onLabel` and `offLabel` read `checked`, so they only follow the switch in controlled mode.
|
|
27
28
|
Uncontrolled, the value belongs to the DOM and React never learns about a toggle, which would
|
|
28
|
-
freeze the state text on its initial value
|
|
29
|
+
freeze the state text on its initial value - use `checked` with `onCheckedChange` whenever you
|
|
29
30
|
show one.
|
|
30
31
|
|
|
31
32
|
## Examples
|
|
@@ -43,10 +44,19 @@ generated. Inside `KptFormField` the wrapper's `label[for]` points at it and the
|
|
|
43
44
|
added to `aria-describedby` (merged with your own). Without a wrapper, name it with `aria-label`.
|
|
44
45
|
Inside `kpt-form-field` the switch gets both names: the wrapper label and its own `label`.
|
|
45
46
|
|
|
47
|
+
## Toggle motion
|
|
48
|
+
`toggleMotion`: `spring` - the thumb travels on a spring and stretches while moving; `fade` - a calm colour and mark transition; `none` - no
|
|
49
|
+
motion. The bounce is started by the change handler, so a control that is checked on load does not
|
|
50
|
+
move. With no value it takes `toggle` from `KptMotionProvider` (default `spring`); `enabled: false` and the
|
|
51
|
+
system "reduce motion" setting always win.
|
|
52
|
+
|
|
46
53
|
## Tokens
|
|
47
54
|
`--kpt-color-primary` (the on track), `--kpt-color-muted` (the off track), `--kpt-color-surface`
|
|
48
55
|
(the thumb), `--kpt-motion-duration-fast`.
|
|
49
56
|
|
|
50
57
|
## Accessibility
|
|
51
|
-
`role="switch"` on a native checkbox
|
|
58
|
+
`role="switch"` on a native checkbox - a screen reader announces on/off instead of
|
|
52
59
|
checked/unchecked. The track and the thumb are `aria-hidden`.
|
|
60
|
+
|
|
61
|
+
## Read-only and required
|
|
62
|
+
`readOnly` keeps the switch focusable but blocks toggling (`aria-readonly`); `required` sets `aria-required`.
|
package/dist/switch/switch.d.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { type ComponentPropsWithRef, type ReactNode } from 'react';
|
|
2
2
|
import type { KptHostProps } from '../internal/types.ts';
|
|
3
|
+
import { type KptToggleMotion } from '@konce-pt/motion';
|
|
3
4
|
export interface KptSwitchProps extends Omit<ComponentPropsWithRef<'input'>, 'type' | 'required'> {
|
|
5
|
+
/**
|
|
6
|
+
* Ruch przełączania: `spring` - kciuk jedzie na sprężynie i rozciąga się w ruchu; `fade` - spokojne przejście koloru i znaku; `none` - bez ruchu.
|
|
7
|
+
* Bez wartości bierze `toggle` z `KptMotionProvider` (domyślnie `spring`); `enabled={false}` i systemowe
|
|
8
|
+
* "ogranicz ruch" wyłączają go zawsze.
|
|
9
|
+
*/
|
|
10
|
+
toggleMotion?: KptToggleMotion;
|
|
4
11
|
/** Etykieta obok przełącznika. */
|
|
5
12
|
label?: string;
|
|
6
13
|
/** Pozycja etykiety względem przełącznika. */
|
|
@@ -15,7 +22,7 @@ export interface KptSwitchProps extends Omit<ComponentPropsWithRef<'input'>, 'ty
|
|
|
15
22
|
invalid?: boolean;
|
|
16
23
|
/** Czy pole było dotknięte; pominięty = stan błędu pokazuje się od razu po `invalid`. */
|
|
17
24
|
touched?: boolean;
|
|
18
|
-
/** Wygodniejszy odpowiednik `onChange`
|
|
25
|
+
/** Wygodniejszy odpowiednik `onChange` - dostaje samo zaznaczenie. */
|
|
19
26
|
onCheckedChange?: (checked: boolean) => void;
|
|
20
27
|
/** Wywoływane na `blur`. */
|
|
21
28
|
onTouch?: () => void;
|
|
@@ -27,7 +34,7 @@ export interface KptSwitchProps extends Omit<ComponentPropsWithRef<'input'>, 'ty
|
|
|
27
34
|
* Przełącznik (switch/toggle). Pod spodem natywny `<input type="checkbox" role="switch">`,
|
|
28
35
|
* więc klawiatura i czytniki ekranu działają bez dodatkowej obsługi.
|
|
29
36
|
*
|
|
30
|
-
* Wariant z tekstem stanu: `onLabel`/`offLabel`
|
|
37
|
+
* Wariant z tekstem stanu: `onLabel`/`offLabel` - wyświetlany tekst zmienia się przy przełączaniu.
|
|
31
38
|
*
|
|
32
39
|
* Tekst stanu wymaga `checked` (tryb kontrolowany), bo w trybie niekontrolowanym wartość należy
|
|
33
40
|
* do DOM i React o niej nie wie; bez tego etykieta stanu zamarłaby na wartości początkowej.
|
|
@@ -36,4 +43,4 @@ export interface KptSwitchProps extends Omit<ComponentPropsWithRef<'input'>, 'ty
|
|
|
36
43
|
* <KptSwitch name="notifications" label="Powiadomienia" />
|
|
37
44
|
* <KptSwitch checked={on} onCheckedChange={setOn} onLabel="Włączony" offLabel="Wyłączony" />
|
|
38
45
|
*/
|
|
39
|
-
export declare function KptSwitch({ label, labelPosition, onLabel, offLabel, required, invalid, touched, onCheckedChange, onTouch, hostProps, className, disabled, checked, onChange, onBlur, children, 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedBy, id, ...rest }: Readonly<KptSwitchProps>): import("react").JSX.Element;
|
|
46
|
+
export declare function KptSwitch({ label, labelPosition, onLabel, offLabel, required, invalid, touched, onCheckedChange, onTouch, hostProps, className, disabled, readOnly, onClick, checked, onChange, onBlur, children, 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedBy, id, toggleMotion, ...rest }: Readonly<KptSwitchProps>): import("react").JSX.Element;
|
package/dist/switch/switch.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
import { useCallback } from 'react';
|
|
3
4
|
import { cn } from "../internal/cn.js";
|
|
4
5
|
import { joinIds, useKptFieldA11y } from "../form-field/form-field-context.js";
|
|
6
|
+
import { playPopMotion, resolveToggleMotion } from '@konce-pt/motion';
|
|
7
|
+
import { useKptMotion } from "../motion/motion-context.js";
|
|
5
8
|
/**
|
|
6
9
|
* Przełącznik (switch/toggle). Pod spodem natywny `<input type="checkbox" role="switch">`,
|
|
7
10
|
* więc klawiatura i czytniki ekranu działają bez dodatkowej obsługi.
|
|
8
11
|
*
|
|
9
|
-
* Wariant z tekstem stanu: `onLabel`/`offLabel`
|
|
12
|
+
* Wariant z tekstem stanu: `onLabel`/`offLabel` - wyświetlany tekst zmienia się przy przełączaniu.
|
|
10
13
|
*
|
|
11
14
|
* Tekst stanu wymaga `checked` (tryb kontrolowany), bo w trybie niekontrolowanym wartość należy
|
|
12
15
|
* do DOM i React o niej nie wie; bez tego etykieta stanu zamarłaby na wartości początkowej.
|
|
@@ -15,18 +18,29 @@ import { joinIds, useKptFieldA11y } from "../form-field/form-field-context.js";
|
|
|
15
18
|
* <KptSwitch name="notifications" label="Powiadomienia" />
|
|
16
19
|
* <KptSwitch checked={on} onCheckedChange={setOn} onLabel="Włączony" offLabel="Wyłączony" />
|
|
17
20
|
*/
|
|
18
|
-
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, 'aria-describedby': ariaDescribedBy, id, ...rest }) {
|
|
21
|
+
export function KptSwitch({ label = '', labelPosition = 'end', onLabel = '', offLabel = '', required = false, invalid = false, touched, onCheckedChange, onTouch, hostProps, className, disabled = false, readOnly = false, onClick, checked, onChange, onBlur, children, 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedBy, id, toggleMotion, ...rest }) {
|
|
19
22
|
const field = useKptFieldA11y(id, 'kpt-switch');
|
|
20
23
|
const { className: hostClassName, ...hostRest } = hostProps ?? {};
|
|
21
24
|
const showInvalid = invalid && (touched ?? true);
|
|
22
25
|
const hasStateLabels = !!(onLabel || offLabel);
|
|
26
|
+
const motion = resolveToggleMotion(toggleMotion, useKptMotion());
|
|
23
27
|
const handleChange = useCallback((event) => {
|
|
24
28
|
onChange?.(event);
|
|
25
29
|
onCheckedChange?.(event.target.checked);
|
|
26
|
-
|
|
30
|
+
// Kciuk rozciąga się w ruchu - z handlera, nie z CSS, bo reguła na `:checked` grałaby przy starcie.
|
|
31
|
+
const thumb = event.currentTarget.nextElementSibling?.firstElementChild;
|
|
32
|
+
if (motion === 'spring' && thumb instanceof HTMLElement)
|
|
33
|
+
playPopMotion(thumb, 'squash');
|
|
34
|
+
}, [onChange, onCheckedChange, motion]);
|
|
27
35
|
const handleBlur = useCallback((event) => {
|
|
28
36
|
onBlur?.(event);
|
|
29
37
|
onTouch?.();
|
|
30
38
|
}, [onBlur, onTouch]);
|
|
31
|
-
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", id: field.id, "aria-describedby": joinIds(ariaDescribedBy, field.describedBy), checked: checked, disabled: disabled, "aria-required": required || undefined, "aria-
|
|
39
|
+
return (_jsx("span", { className: cn('kpt-switch-host', hostClassName), ...hostRest, children: _jsxs("label", { className: cn('kpt-switch', disabled && 'kpt-switch--disabled', className), "data-motion": motion, 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", id: field.id, "aria-describedby": joinIds(ariaDescribedBy, field.describedBy), checked: checked, disabled: disabled, "aria-required": required || undefined, "aria-readonly": readOnly || undefined,
|
|
40
|
+
// Natywne `readonly` nie działa na polach wyboru - klik (i Spacja) jest blokowany ręcznie.
|
|
41
|
+
onClick: (event) => {
|
|
42
|
+
if (readOnly)
|
|
43
|
+
event.preventDefault();
|
|
44
|
+
onClick?.(event);
|
|
45
|
+
}, "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'), "aria-hidden": "true", children: checked ? onLabel : offLabel })) : null, children] }) }));
|
|
32
46
|
}
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
# KptSwitchGroup (@konce-pt/react)
|
|
2
2
|
|
|
3
|
-
A group of switches
|
|
3
|
+
A group of switches - mutually exclusive by default, multi-select with `multiple`.
|
|
4
4
|
Import: `import { KptSwitchGroup } from '@konce-pt/react';`
|
|
5
5
|
|
|
6
6
|
## DOM
|
|
7
7
|
<div class="kpt-switch-group-host">
|
|
8
8
|
<div class="kpt-switch-group" role="group">
|
|
9
|
-
<span class="kpt-switch-host kpt-switch-group__item"
|
|
10
|
-
|
|
9
|
+
<span class="kpt-switch-host kpt-switch-group__item">...KptSwitch...</span>
|
|
10
|
+
...one per option...
|
|
11
11
|
</div>
|
|
12
12
|
</div>
|
|
13
13
|
|
|
14
14
|
## Props
|
|
15
|
-
- `options`: `KptOption<T>[]`
|
|
16
|
-
- `value` / `defaultValue` / `onValueChange`
|
|
15
|
+
- `options`: `KptOption<T>[]` - `{ label, value, disabled? }`
|
|
16
|
+
- `value` / `defaultValue` / `onValueChange` - single select: the option's value or `null`;
|
|
17
17
|
with `multiple`: an array of the selected values
|
|
18
18
|
- `multiple`: boolean (default false)
|
|
19
19
|
- `orientation`: `'vertical'` (default) | `'horizontal'`
|
|
20
|
-
- `allowDeselect`: boolean (default true)
|
|
20
|
+
- `allowDeselect`: boolean (default true) - single select only; in `multiple` mode turning an
|
|
21
21
|
option off is always allowed
|
|
22
22
|
- `disabled`, `invalid`, `touched`, `onTouch()`
|
|
23
23
|
- `className`, `ref` and every other `<div>` prop go to the host
|
|
24
24
|
|
|
25
25
|
## Single select comes out of the value, not out of the switches
|
|
26
26
|
Every entry is a `KptSwitch` whose `checked` is derived from the group value, so turning one on
|
|
27
|
-
turns the rest off by itself
|
|
27
|
+
turns the rest off by itself - there is no per-switch state to keep in sync.
|
|
28
28
|
|
|
29
29
|
That is also why `allowDeselect={false}` needs no code: the handler writes nothing, so React
|
|
30
30
|
re-applies the controlled `checked` and the switch snaps back on.
|
|
@@ -37,7 +37,7 @@ re-applies the controlled `checked` and the switch snaps back on.
|
|
|
37
37
|
## Screen reader and keyboard
|
|
38
38
|
`aria-invalid` is not supported on `role="group"`, so the error state is carried by each switch. In
|
|
39
39
|
single mode the switches are mutually exclusive and nothing announces that turning one on turned
|
|
40
|
-
another off
|
|
40
|
+
another off - for a single choice prefer `KptRadioGroup`.
|
|
41
41
|
|
|
42
42
|
## Label and description
|
|
43
43
|
`id` goes to the focusable element, not the host; without one it comes from `KptFormField` or is
|
|
@@ -52,3 +52,6 @@ Layout only: `--kpt-space-2` (vertical gap) and `--kpt-space-4` (horizontal). Th
|
|
|
52
52
|
## Accessibility
|
|
53
53
|
`role="group"` with `aria-invalid` once the field is touched; every entry keeps the native
|
|
54
54
|
checkbox of `KptSwitch`, so keyboard and screen readers work with no extra handling.
|
|
55
|
+
|
|
56
|
+
## Read-only and required
|
|
57
|
+
`readOnly` is passed to every switch. With `allowDeselect=false` turning the active switch off puts it back on - before, the switch looked off while the group value said it was on.
|
|
@@ -6,22 +6,24 @@ export interface KptSwitchGroupProps<T> extends Omit<ComponentPropsWithRef<'div'
|
|
|
6
6
|
value?: T | T[] | null;
|
|
7
7
|
defaultValue?: T | T[] | null;
|
|
8
8
|
onValueChange?: (value: T | T[] | null) => void;
|
|
9
|
-
/** Wielokrotny wybór
|
|
9
|
+
/** Wielokrotny wybór - wartością staje się tablica `T[]`. */
|
|
10
10
|
multiple?: boolean;
|
|
11
11
|
orientation?: 'vertical' | 'horizontal';
|
|
12
12
|
/** Czy wyłączenie aktywnej opcji zeruje wartość. Dotyczy tylko trybu pojedynczego. */
|
|
13
13
|
allowDeselect?: boolean;
|
|
14
|
-
/** Id elementu fokusowalnego (nie hosta); bez niego generowane, w `KptFormField`
|
|
14
|
+
/** Id elementu fokusowalnego (nie hosta); bez niego generowane, w `KptFormField` - z wrappera. */
|
|
15
15
|
id?: string;
|
|
16
16
|
/** Nazwa dostępna, gdy kontrolki nie opisuje etykieta (`<label for>` albo `KptFormField`). */
|
|
17
17
|
ariaLabel?: string | null;
|
|
18
18
|
disabled?: boolean;
|
|
19
|
+
/** Tylko do odczytu - przełączniki widać, nie da się ich zmienić. */
|
|
20
|
+
readOnly?: boolean;
|
|
19
21
|
invalid?: boolean;
|
|
20
22
|
touched?: boolean;
|
|
21
23
|
onTouch?: () => void;
|
|
22
24
|
}
|
|
23
25
|
/**
|
|
24
|
-
* Grupa przełączników. Domyślnie wzajemnie wykluczających się
|
|
26
|
+
* Grupa przełączników. Domyślnie wzajemnie wykluczających się - włączenie jednego wyłącza
|
|
25
27
|
* pozostałe; z `multiple` wartością jest tablica zaznaczonych opcji.
|
|
26
28
|
*
|
|
27
29
|
* Renderuje `KptSwitch`, więc dziedziczy jego wygląd, tokeny i obsługę klawiatury.
|
|
@@ -30,4 +32,4 @@ export interface KptSwitchGroupProps<T> extends Omit<ComponentPropsWithRef<'div'
|
|
|
30
32
|
* <KptSwitchGroup options={plans} value={plan} onValueChange={setPlan} />
|
|
31
33
|
* <KptSwitchGroup multiple options={tags} value={selected} onValueChange={setSelected} />
|
|
32
34
|
*/
|
|
33
|
-
export declare function KptSwitchGroup<T>({ options, value, defaultValue, onValueChange, multiple, orientation, allowDeselect, id, ariaLabel, disabled, invalid, touched, onTouch, className, ...rest }: Readonly<KptSwitchGroupProps<T>>): import("react").JSX.Element;
|
|
35
|
+
export declare function KptSwitchGroup<T>({ options, value, defaultValue, onValueChange, multiple, orientation, allowDeselect, id, ariaLabel, disabled, readOnly, invalid, touched, onTouch, className, ...rest }: Readonly<KptSwitchGroupProps<T>>): import("react").JSX.Element;
|