@konce-pt/react 0.12.0 → 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 +122 -64
- package/dist/accordion/accordion.d.ts +14 -6
- package/dist/accordion/accordion.js +14 -7
- package/dist/accordion/llms.txt +22 -10
- package/dist/alert/alert.d.ts +2 -2
- package/dist/alert/alert.js +2 -2
- package/dist/alert/llms.txt +10 -10
- package/dist/app-shell/app-shell.d.ts +14 -14
- package/dist/app-shell/app-shell.js +11 -11
- package/dist/app-shell/llms.txt +13 -13
- package/dist/auth/auth-types.d.ts +6 -6
- package/dist/auth/auth.d.ts +2 -2
- package/dist/auth/auth.js +7 -7
- package/dist/auth/llms.txt +9 -9
- package/dist/autocomplete/autocomplete.d.ts +19 -6
- package/dist/autocomplete/autocomplete.js +23 -10
- package/dist/autocomplete/llms.txt +16 -5
- package/dist/avatar/avatar.d.ts +6 -6
- package/dist/avatar/avatar.js +5 -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 +3 -3
- package/dist/avatar-group/llms.txt +8 -8
- package/dist/backdrop/backdrop.d.ts +7 -7
- package/dist/backdrop/backdrop.js +16 -16
- 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 +4 -4
- package/dist/bottom-sheet/bottom-sheet.js +2 -2
- package/dist/bottom-sheet/llms.txt +9 -9
- package/dist/breadcrumb/breadcrumb.d.ts +2 -2
- package/dist/breadcrumb/breadcrumb.js +3 -3
- package/dist/breadcrumb/llms.txt +3 -3
- package/dist/button/button.d.ts +3 -3
- package/dist/button/button.js +8 -8
- package/dist/button/llms.txt +27 -19
- package/dist/button-group/button-group.d.ts +9 -9
- package/dist/button-group/button-group.js +30 -8
- package/dist/button-group/llms.txt +20 -14
- package/dist/card/card.d.ts +8 -8
- package/dist/card/card.js +6 -6
- package/dist/card/llms.txt +20 -20
- package/dist/carousel/carousel.d.ts +6 -6
- package/dist/carousel/carousel.js +4 -4
- package/dist/carousel/llms.txt +10 -10
- package/dist/charts/chart-legend.d.ts +3 -3
- package/dist/charts/chart-legend.js +1 -1
- package/dist/charts/chart-tooltip.d.ts +3 -3
- package/dist/charts/chart-tooltip.js +1 -1
- package/dist/charts/chart.d.ts +1 -1
- package/dist/charts/chart.js +8 -8
- package/dist/charts/llms.txt +6 -6
- package/dist/charts-entry/public-api.js +2 -2
- package/dist/chat/chat.d.ts +17 -10
- package/dist/chat/chat.js +42 -18
- package/dist/chat/llms.txt +32 -17
- package/dist/chat-composer/chat-composer.d.ts +17 -7
- package/dist/chat-composer/chat-composer.js +21 -8
- 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 +9 -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 +17 -7
- 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 +3 -3
- package/dist/chat-typing/llms.txt +6 -6
- package/dist/checkbox/checkbox.d.ts +13 -6
- package/dist/checkbox/checkbox.js +26 -7
- package/dist/checkbox/llms.txt +24 -12
- package/dist/chip/chip.d.ts +4 -4
- package/dist/chip/chip.js +2 -2
- package/dist/chip/llms.txt +11 -11
- package/dist/chips-input/chips-input.d.ts +4 -4
- package/dist/chips-input/chips-input.js +35 -9
- package/dist/chips-input/llms.txt +15 -8
- package/dist/clock/clock.d.ts +4 -4
- package/dist/clock/clock.js +7 -7
- package/dist/clock/llms.txt +8 -8
- package/dist/color-picker/color-picker.d.ts +6 -6
- package/dist/color-picker/color-picker.js +3 -3
- package/dist/color-picker/llms.txt +5 -5
- package/dist/confirm/confirm-container.d.ts +3 -3
- package/dist/confirm/confirm-container.js +5 -5
- package/dist/confirm/confirm-store.d.ts +4 -4
- package/dist/confirm/confirm-store.js +7 -7
- package/dist/confirm/llms.txt +6 -6
- package/dist/context-menu/context-menu.d.ts +1 -1
- package/dist/context-menu/context-menu.js +5 -5
- package/dist/context-menu/llms.txt +7 -7
- package/dist/data-table/data-table-types.d.ts +5 -5
- package/dist/data-table/data-table.d.ts +29 -8
- package/dist/data-table/data-table.js +340 -95
- package/dist/data-table/export-csv.d.ts +3 -3
- package/dist/data-table/export-csv.js +4 -4
- package/dist/data-table/llms.txt +127 -94
- package/dist/data-view/data-view.d.ts +13 -5
- package/dist/data-view/data-view.js +67 -6
- package/dist/data-view/llms.txt +29 -10
- package/dist/date-range/date-range.d.ts +9 -9
- package/dist/date-range/date-range.js +24 -24
- package/dist/date-range/llms.txt +20 -20
- package/dist/datepicker/datepicker.d.ts +10 -10
- package/dist/datepicker/datepicker.js +29 -29
- package/dist/datepicker/llms.txt +24 -24
- package/dist/dialog/dialog.d.ts +4 -4
- package/dist/dialog/dialog.js +4 -4
- package/dist/dialog/llms.txt +11 -11
- package/dist/divider/divider.d.ts +1 -1
- package/dist/divider/llms.txt +4 -4
- package/dist/drawer/drawer.d.ts +5 -5
- package/dist/drawer/drawer.js +2 -2
- package/dist/drawer/llms.txt +11 -11
- 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 +9 -6
- package/dist/fieldset/llms.txt +26 -9
- package/dist/file-upload/file-upload.d.ts +3 -3
- package/dist/file-upload/file-upload.js +7 -7
- package/dist/file-upload/llms.txt +7 -7
- 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 +26 -6
- package/dist/form-field/llms.txt +25 -11
- package/dist/galleria/galleria.d.ts +3 -3
- package/dist/galleria/galleria.js +5 -5
- 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 +3 -3
- package/dist/i18n/i18n-context.js +7 -7
- 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 +6 -6
- 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 +1 -1
- package/dist/image/llms.txt +13 -13
- package/dist/input/input.d.ts +18 -5
- package/dist/input/input.js +21 -6
- package/dist/input/llms.txt +25 -11
- package/dist/input-mask/input-mask.d.ts +1 -1
- package/dist/input-mask/input-mask.js +2 -2
- package/dist/input-mask/llms.txt +5 -5
- package/dist/input-number/input-number.d.ts +9 -9
- package/dist/input-number/input-number.js +11 -11
- package/dist/input-number/llms.txt +14 -14
- package/dist/input-otp/input-otp.d.ts +6 -6
- package/dist/input-otp/input-otp.js +10 -10
- package/dist/input-otp/llms.txt +9 -9
- 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 +2 -2
- package/dist/internal/mask.js +4 -4
- package/dist/internal/option-key.d.ts +2 -2
- package/dist/internal/option-key.js +2 -2
- 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 +8 -8
- package/dist/internal/password-strength.d.ts +2 -2
- package/dist/internal/password-strength.js +6 -6
- package/dist/internal/roving.d.ts +2 -2
- package/dist/internal/roving.js +3 -3
- package/dist/internal/scroll-lock.d.ts +1 -1
- package/dist/internal/scroll-lock.js +2 -2
- package/dist/internal/slot-children.d.ts +3 -3
- package/dist/internal/slot-children.js +4 -4
- package/dist/internal/slot.d.ts +3 -3
- package/dist/internal/slot.js +2 -2
- package/dist/internal/step.d.ts +3 -3
- package/dist/internal/step.js +4 -4
- package/dist/internal/tween.d.ts +5 -5
- package/dist/internal/tween.js +5 -5
- 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 +1 -1
- package/dist/internal/use-controllable-state.js +3 -3
- 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 +1 -1
- package/dist/internal/use-modal-focus.js +3 -3
- package/dist/knob/knob.d.ts +4 -4
- package/dist/knob/knob.js +14 -10
- package/dist/knob/llms.txt +17 -12
- package/dist/listbox/listbox.d.ts +6 -6
- package/dist/listbox/listbox.js +9 -9
- package/dist/listbox/llms.txt +10 -10
- 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 +25 -22
- package/dist/map/map-create-dialog.d.ts +4 -4
- package/dist/map/map-create-dialog.js +10 -10
- package/dist/map/map-hours-field.d.ts +4 -4
- package/dist/map/map-hours-field.js +7 -7
- package/dist/map/map-image-field.d.ts +2 -2
- package/dist/map/map-image-field.js +4 -4
- package/dist/map/map-legend.d.ts +4 -4
- package/dist/map/map-legend.js +2 -2
- package/dist/map/map-poi-card.d.ts +3 -3
- package/dist/map/map-poi-card.js +9 -9
- package/dist/map/map-search.d.ts +17 -6
- package/dist/map/map-search.js +21 -18
- package/dist/map/map.d.ts +21 -14
- package/dist/map/map.js +30 -29
- 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 +9 -9
- package/dist/megamenu/megamenu.d.ts +6 -6
- package/dist/megamenu/megamenu.js +10 -10
- 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.d.ts +2 -2
- package/dist/menu/menu.js +6 -6
- package/dist/menubar/llms.txt +10 -10
- package/dist/menubar/menubar.d.ts +5 -5
- package/dist/menubar/menubar.js +10 -10
- 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 +1 -1
- package/dist/motion/motion-context.d.ts +22 -0
- package/dist/motion/motion-context.js +28 -0
- package/dist/order-list/llms.txt +22 -10
- package/dist/order-list/order-list.d.ts +12 -4
- package/dist/order-list/order-list.js +104 -21
- package/dist/paginator/llms.txt +8 -8
- package/dist/paginator/paginator.js +1 -1
- package/dist/panel/llms.txt +25 -13
- package/dist/panel/panel.d.ts +11 -3
- package/dist/panel/panel.js +7 -4
- package/dist/password/llms.txt +16 -8
- package/dist/password/password.d.ts +2 -2
- package/dist/password/password.js +24 -3
- package/dist/peek/llms.txt +10 -10
- package/dist/peek/peek.d.ts +6 -6
- package/dist/peek/peek.js +7 -7
- package/dist/pick-list/llms.txt +33 -13
- package/dist/pick-list/pick-list.d.ts +12 -4
- package/dist/pick-list/pick-list.js +111 -23
- package/dist/popover/llms.txt +11 -11
- package/dist/popover/popover.d.ts +4 -4
- package/dist/popover/popover.js +5 -5
- package/dist/progress/llms.txt +17 -17
- package/dist/progress/progress.d.ts +7 -7
- package/dist/progress/progress.js +6 -6
- package/dist/public-api.d.ts +15 -3
- package/dist/public-api.js +13 -7
- package/dist/radio-group/llms.txt +13 -6
- package/dist/radio-group/radio-group.d.ts +11 -4
- package/dist/radio-group/radio-group.js +15 -7
- 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 +76 -12
- package/dist/rich-text/lists.d.ts +2 -2
- package/dist/rich-text/lists.js +7 -7
- package/dist/rich-text/llms.txt +26 -17
- package/dist/rich-text/rich-text.d.ts +12 -7
- package/dist/rich-text/rich-text.js +78 -54
- package/dist/rich-text/sanitize.d.ts +3 -3
- package/dist/rich-text/sanitize.js +12 -12
- package/dist/rich-text/tables.d.ts +3 -3
- package/dist/rich-text/tables.js +3 -3
- package/dist/roadmap/llms.txt +15 -15
- package/dist/roadmap/roadmap.d.ts +6 -6
- package/dist/roadmap/roadmap.js +19 -19
- 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 +1 -1
- package/dist/select/llms.txt +19 -12
- package/dist/select/select.d.ts +8 -8
- package/dist/select/select.js +47 -21
- package/dist/shared/types.d.ts +5 -5
- package/dist/shared/types.js +1 -1
- package/dist/sidenav/llms.txt +9 -9
- package/dist/sidenav/sidenav.d.ts +1 -1
- package/dist/sidenav/sidenav.js +1 -1
- 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 +32 -13
- package/dist/slider/slider-drag.d.ts +26 -0
- package/dist/slider/slider-drag.js +79 -0
- package/dist/slider/slider.d.ts +6 -5
- package/dist/slider/slider.js +27 -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 +1 -1
- package/dist/spinner/llms.txt +7 -7
- package/dist/spinner/spinner.d.ts +1 -1
- package/dist/spinner/spinner.js +1 -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 +4 -4
- package/dist/splitter/llms.txt +11 -11
- package/dist/splitter/splitter.d.ts +3 -3
- package/dist/splitter/splitter.js +5 -5
- package/dist/stepper/llms.txt +33 -14
- package/dist/stepper/stepper.d.ts +6 -6
- package/dist/stepper/stepper.js +53 -10
- package/dist/switch/llms.txt +12 -5
- package/dist/switch/switch.d.ts +10 -3
- package/dist/switch/switch.js +12 -5
- package/dist/switch-group/llms.txt +9 -9
- package/dist/switch-group/switch-group.d.ts +4 -4
- package/dist/switch-group/switch-group.js +4 -4
- package/dist/tabs/llms.txt +10 -10
- package/dist/tabs/tabs.d.ts +5 -5
- package/dist/tabs/tabs.js +8 -8
- package/dist/textarea/llms.txt +23 -12
- package/dist/textarea/textarea.d.ts +19 -6
- package/dist/textarea/textarea.js +21 -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 +47 -17
- package/dist/toast/toast-container.d.ts +9 -3
- package/dist/toast/toast-container.js +17 -9
- package/dist/toast/toast-store.d.ts +40 -4
- 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 +10 -10
- package/dist/tooltip/tooltip.d.ts +3 -3
- package/dist/tooltip/tooltip.js +18 -18
- package/dist/tree/llms.txt +25 -12
- package/dist/tree/tree-keys.d.ts +5 -5
- package/dist/tree/tree-keys.js +7 -7
- package/dist/tree/tree.d.ts +14 -7
- package/dist/tree/tree.js +53 -18
- 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 +15 -13
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { useEffect, useEffectEvent, useId, useLayoutEffect, useRef, useState, } from 'react';
|
|
4
|
+
import { flushSync } from 'react-dom';
|
|
5
|
+
import { isVisibleInScroller, layoutMotionAllowed, morphKeyed, playKeyedMotion, resolveLayoutMotion, revealInScroller, snapshotKeyed, stopKeyedMotion, } from '@konce-pt/motion';
|
|
4
6
|
import { cn } from "../internal/cn.js";
|
|
5
7
|
import { composeRefs } from "../internal/compose-refs.js";
|
|
6
8
|
import { useControllableState } from "../internal/use-controllable-state.js";
|
|
7
9
|
import { useKptMessages } from "../i18n/i18n-context.js";
|
|
8
10
|
import { KptIcon } from "../icon/icon.js";
|
|
9
11
|
import { nextMenuIndex } from "../menu/menu-keys.js";
|
|
12
|
+
import { useKptMotion } from "../motion/motion-context.js";
|
|
10
13
|
const EMPTY = [];
|
|
14
|
+
/** Klasy ruchu przenoszenia - reguły we wspólnym CSS komponentu. */
|
|
15
|
+
const MOTION_CLASSES = {
|
|
16
|
+
ghostClass: 'kpt-pick-list__ghost',
|
|
17
|
+
hiddenClass: 'kpt-pick-list__item--waiting',
|
|
18
|
+
movingClass: 'kpt-pick-list__item--moving',
|
|
19
|
+
};
|
|
20
|
+
/** Klasa View Transitions dla morfu. */
|
|
21
|
+
const MORPH_CLASS = 'kpt-pick-list-morph';
|
|
22
|
+
/** Przewijany pojemnik wiersza - lista panelu. */
|
|
23
|
+
function scrollerOf(element) {
|
|
24
|
+
return element.closest('.kpt-pick-list__items');
|
|
25
|
+
}
|
|
11
26
|
/**
|
|
12
|
-
* PickList
|
|
27
|
+
* PickList - transfer elementów między dwiema listami. Klik zaznacza, przyciski pośrodku
|
|
13
28
|
* przenoszą zaznaczone albo wszystko, dwuklik przerzuca pojedynczy element na drugą stronę.
|
|
14
|
-
* Z `dragdrop` dochodzi przeciąganie
|
|
29
|
+
* Z `dragdrop` dochodzi przeciąganie - porządkowanie wewnątrz panelu i przenoszenie na
|
|
15
30
|
* konkretną pozycję drugiego panelu.
|
|
16
31
|
*
|
|
17
32
|
* Każda lista to `listbox` z wielokrotnym wyborem i jednym przystankiem Tab (roving tabindex):
|
|
@@ -26,7 +41,7 @@ const EMPTY = [];
|
|
|
26
41
|
* renderItem={(item) => item.name}
|
|
27
42
|
* />
|
|
28
43
|
*/
|
|
29
|
-
export function KptPickList({ source, defaultSource = EMPTY, onSourceChange, target, defaultTarget = EMPTY, onTargetChange, sourceHeader, targetHeader, dragdrop = false, renderItem, locale, dictionary, className, ref, ...rest }) {
|
|
44
|
+
export function KptPickList({ source, defaultSource = EMPTY, onSourceChange, target, defaultTarget = EMPTY, onTargetChange, sourceHeader, targetHeader, dragdrop = false, layoutMotion, renderItem, locale, dictionary, className, ref, ...rest }) {
|
|
30
45
|
const { t } = useKptMessages({ locale, dictionary });
|
|
31
46
|
const [left, setLeft] = useControllableState({
|
|
32
47
|
value: source,
|
|
@@ -42,18 +57,80 @@ export function KptPickList({ source, defaultSource = EMPTY, onSourceChange, tar
|
|
|
42
57
|
// po obu stronach się przesuwają, a referencja zostaje ta sama.
|
|
43
58
|
const [selLeft, setSelLeft] = useState(new Set());
|
|
44
59
|
const [selRight, setSelRight] = useState(new Set());
|
|
45
|
-
/** Przeciągany element
|
|
60
|
+
/** Przeciągany element - strona i pozycja w jej tablicy. */
|
|
46
61
|
const [drag, setDrag] = useState(null);
|
|
47
|
-
/** Element pod kursorem
|
|
62
|
+
/** Element pod kursorem - rysuje wskaźnik miejsca upuszczenia. */
|
|
48
63
|
const [over, setOver] = useState(null);
|
|
49
|
-
/** Panel, nad którego pustym obszarem jest kursor
|
|
64
|
+
/** Panel, nad którego pustym obszarem jest kursor - upuszczenie tam dopina na koniec. */
|
|
50
65
|
const [listOver, setListOver] = useState(null);
|
|
51
|
-
/** Pozycja, która ostatnio miała fokus w każdej liście
|
|
66
|
+
/** Pozycja, która ostatnio miała fokus w każdej liście - ona jest przystankiem Tab. */
|
|
52
67
|
const [focusLeft, setFocusLeft] = useState(0);
|
|
53
68
|
const [focusRight, setFocusRight] = useState(0);
|
|
54
69
|
/** Pozycja, na którą po renderze trzeba przenieść fokus DOM (klawiatura). */
|
|
55
70
|
const [focusRequest, setFocusRequest] = useState(null);
|
|
56
71
|
const rootRef = useRef(null);
|
|
72
|
+
const motionConfig = useKptMotion();
|
|
73
|
+
// `view-transition-name` musi być poprawnym identyfikatorem CSS - `useId` daje dwukropki.
|
|
74
|
+
const morphPrefix = `kpt-pick-list-${useId().replaceAll(/[^a-zA-Z0-9-]/g, '')}`;
|
|
75
|
+
/** Który element danych pokazuje każdy wiersz - wiersze mają klucz po indeksie, więc go zmieniają. */
|
|
76
|
+
const keyOf = useRef(new WeakMap());
|
|
77
|
+
/** Stan sprzed zmiany, czekający na commit nowego układu. */
|
|
78
|
+
const pending = useRef(null);
|
|
79
|
+
/** Elementy, które przy ostatniej zmianie przeszły na drugą stronę - lista przewija się do nich. */
|
|
80
|
+
const crossed = useRef([]);
|
|
81
|
+
const stage = () => rootRef.current?.querySelector('.kpt-pick-list') ?? null;
|
|
82
|
+
const nodes = () => {
|
|
83
|
+
const root = stage();
|
|
84
|
+
if (!root)
|
|
85
|
+
return [];
|
|
86
|
+
return Array.from(root.querySelectorAll('.kpt-pick-list__items > .kpt-pick-list__item')).flatMap((element) => keyOf.current.has(element) ? [{ key: keyOf.current.get(element), element }] : []);
|
|
87
|
+
};
|
|
88
|
+
/** Przewija listę docelową do ostatniego przeniesionego elementu - ląduje tam, gdzie go widać. */
|
|
89
|
+
const revealCrossed = () => {
|
|
90
|
+
const last = crossed.current.at(-1);
|
|
91
|
+
if (last === undefined)
|
|
92
|
+
return;
|
|
93
|
+
const node = nodes().find((n) => n.key === last);
|
|
94
|
+
if (node)
|
|
95
|
+
revealInScroller(node.element, scrollerOf(node.element));
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Zmiana list z ruchem. Stan sprzed zmiany mierzymy, zanim React zmieni DOM - dlatego animujemy
|
|
99
|
+
* zmiany z interakcji (przyciski, dwuklik, Enter, przeciąganie), a listy podmienione z zewnątrz
|
|
100
|
+
* przełączają się od razu.
|
|
101
|
+
*/
|
|
102
|
+
const withMotion = (apply, origin) => {
|
|
103
|
+
const motion = resolveLayoutMotion(layoutMotion, motionConfig);
|
|
104
|
+
crossed.current = [];
|
|
105
|
+
const root = stage();
|
|
106
|
+
if (motion === 'none' || !root || !layoutMotionAllowed()) {
|
|
107
|
+
apply();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (motion === 'morph') {
|
|
111
|
+
morphKeyed(nodes(), nodes, morphPrefix, MORPH_CLASS, () => {
|
|
112
|
+
flushSync(apply);
|
|
113
|
+
revealCrossed();
|
|
114
|
+
}, (el) => isVisibleInScroller(el, scrollerOf(el)));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
pending.current = { first: snapshotKeyed(root, nodes(), scrollerOf), motion, origin };
|
|
118
|
+
stopKeyedMotion(root, MOTION_CLASSES);
|
|
119
|
+
apply();
|
|
120
|
+
};
|
|
121
|
+
// Nowy układ jest już w DOM (a `keyOf` zaktualizowany refami) - gramy loty od zapamiętanego stanu.
|
|
122
|
+
const playPending = useEffectEvent(() => {
|
|
123
|
+
const job = pending.current;
|
|
124
|
+
pending.current = null;
|
|
125
|
+
const root = stage();
|
|
126
|
+
if (!job || !root)
|
|
127
|
+
return;
|
|
128
|
+
revealCrossed();
|
|
129
|
+
playKeyedMotion(root, job.first, nodes(), { motion: job.motion, scrollerOf, ...MOTION_CLASSES }, job.origin);
|
|
130
|
+
});
|
|
131
|
+
useLayoutEffect(() => {
|
|
132
|
+
playPending();
|
|
133
|
+
}, [left, right]);
|
|
57
134
|
const listOf = (side) => (side === 'source' ? left : right);
|
|
58
135
|
const setListOf = (side) => (side === 'source' ? setLeft : setRight);
|
|
59
136
|
const selectionOf = (side) => (side === 'source' ? selLeft : selRight);
|
|
@@ -61,7 +138,7 @@ export function KptPickList({ source, defaultSource = EMPTY, onSourceChange, tar
|
|
|
61
138
|
const other = (side) => (side === 'source' ? 'target' : 'source');
|
|
62
139
|
const focusOf = (side) => (side === 'source' ? focusLeft : focusRight);
|
|
63
140
|
const setFocusOf = (side) => (side === 'source' ? setFocusLeft : setFocusRight);
|
|
64
|
-
/** Przystanek Tab listy
|
|
141
|
+
/** Przystanek Tab listy - ostatnio skupiona pozycja, przycięta do długości listy. */
|
|
65
142
|
const tabIndexOf = (side) => Math.min(focusOf(side), listOf(side).length - 1);
|
|
66
143
|
// Żądanie nie jest zerowane w efekcie (setState w efekcie = dodatkowy przebieg renderu): każde jest
|
|
67
144
|
// nowym obiektem, więc efekt rusza raz na żądanie, także o ten sam indeks.
|
|
@@ -95,7 +172,10 @@ export function KptPickList({ source, defaultSource = EMPTY, onSourceChange, tar
|
|
|
95
172
|
const text = t('pickList.moved', { count, list: headerOf(to) });
|
|
96
173
|
setAnnouncement((current) => (current === text ? text + '\u00a0' : text));
|
|
97
174
|
};
|
|
98
|
-
const move = (from, all) => {
|
|
175
|
+
const move = (from, all, origin) => {
|
|
176
|
+
withMotion(() => moveNow(from, all), origin);
|
|
177
|
+
};
|
|
178
|
+
const moveNow = (from, all) => {
|
|
99
179
|
const to = other(from);
|
|
100
180
|
const fromItems = listOf(from);
|
|
101
181
|
const selection = selectionOf(from);
|
|
@@ -104,6 +184,7 @@ export function KptPickList({ source, defaultSource = EMPTY, onSourceChange, tar
|
|
|
104
184
|
return;
|
|
105
185
|
setListOf(from)(fromItems.filter((item) => !moving.includes(item)));
|
|
106
186
|
setListOf(to)([...listOf(to), ...moving]);
|
|
187
|
+
crossed.current = moving;
|
|
107
188
|
setSelectionOf(from)(new Set());
|
|
108
189
|
announce(moving.length, to);
|
|
109
190
|
};
|
|
@@ -117,9 +198,11 @@ export function KptPickList({ source, defaultSource = EMPTY, onSourceChange, tar
|
|
|
117
198
|
toItems.splice(toIndex, 0, moved);
|
|
118
199
|
setListOf(fromSide)(fromItems);
|
|
119
200
|
setListOf(toSide)(toItems);
|
|
120
|
-
if (fromSide !== toSide)
|
|
201
|
+
if (fromSide !== toSide) {
|
|
202
|
+
crossed.current = [moved];
|
|
121
203
|
announce(1, toSide);
|
|
122
|
-
|
|
204
|
+
}
|
|
205
|
+
// Element opuszcza panel - jego zaznaczenie po tamtej stronie przestaje cokolwiek znaczyć.
|
|
123
206
|
const selection = selectionOf(fromSide);
|
|
124
207
|
if (selection.has(moved)) {
|
|
125
208
|
const next = new Set(selection);
|
|
@@ -128,12 +211,12 @@ export function KptPickList({ source, defaultSource = EMPTY, onSourceChange, tar
|
|
|
128
211
|
}
|
|
129
212
|
};
|
|
130
213
|
/** Dwuklik: przenosi wyłącznie klikniętą pozycję, niezależnie od zaznaczenia. */
|
|
131
|
-
const moveOne = (from, item) => {
|
|
214
|
+
const moveOne = (from, item, origin) => {
|
|
132
215
|
const index = listOf(from).indexOf(item);
|
|
133
216
|
if (index === -1)
|
|
134
217
|
return;
|
|
135
218
|
const to = other(from);
|
|
136
|
-
transfer(from, index, to, listOf(to).length);
|
|
219
|
+
withMotion(() => transfer(from, index, to, listOf(to).length), origin);
|
|
137
220
|
};
|
|
138
221
|
const onItemKeyDown = (side, index, item, event) => {
|
|
139
222
|
if (event.key === ' ') {
|
|
@@ -143,8 +226,8 @@ export function KptPickList({ source, defaultSource = EMPTY, onSourceChange, tar
|
|
|
143
226
|
}
|
|
144
227
|
if (event.key === 'Enter') {
|
|
145
228
|
event.preventDefault();
|
|
146
|
-
moveOne(side, item);
|
|
147
|
-
// Pozycja zniknęła z listy
|
|
229
|
+
moveOne(side, item, event.currentTarget);
|
|
230
|
+
// Pozycja zniknęła z listy - fokus zostaje w tym samym miejscu listy, na następnej.
|
|
148
231
|
focusItem(side, index);
|
|
149
232
|
return;
|
|
150
233
|
}
|
|
@@ -182,20 +265,21 @@ export function KptPickList({ source, defaultSource = EMPTY, onSourceChange, tar
|
|
|
182
265
|
clearDrag();
|
|
183
266
|
if (from === null)
|
|
184
267
|
return;
|
|
268
|
+
const origin = event.currentTarget;
|
|
185
269
|
if (from.side !== side) {
|
|
186
|
-
transfer(from.side, from.index, side, index);
|
|
270
|
+
withMotion(() => transfer(from.side, from.index, side, index), origin);
|
|
187
271
|
return;
|
|
188
272
|
}
|
|
189
273
|
if (from.index === index)
|
|
190
274
|
return;
|
|
191
|
-
// Indeks celu liczony na tablicy sprzed usunięcia
|
|
275
|
+
// Indeks celu liczony na tablicy sprzed usunięcia - element ląduje na pozycji tego,
|
|
192
276
|
// na który go upuszczono (ten sam wzór co przestawianie kolumn w KptDataTable).
|
|
193
277
|
const next = [...listOf(side)];
|
|
194
278
|
const [moved] = next.splice(from.index, 1);
|
|
195
279
|
if (moved === undefined)
|
|
196
280
|
return;
|
|
197
281
|
next.splice(index, 0, moved);
|
|
198
|
-
setListOf(side)(next);
|
|
282
|
+
withMotion(() => setListOf(side)(next), origin);
|
|
199
283
|
};
|
|
200
284
|
const onListDragOver = (side, event) => {
|
|
201
285
|
if (drag === null)
|
|
@@ -210,8 +294,9 @@ export function KptPickList({ source, defaultSource = EMPTY, onSourceChange, tar
|
|
|
210
294
|
clearDrag();
|
|
211
295
|
if (from === null)
|
|
212
296
|
return;
|
|
297
|
+
const origin = event.currentTarget;
|
|
213
298
|
if (from.side !== side) {
|
|
214
|
-
transfer(from.side, from.index, side, listOf(side).length);
|
|
299
|
+
withMotion(() => transfer(from.side, from.index, side, listOf(side).length), origin);
|
|
215
300
|
return;
|
|
216
301
|
}
|
|
217
302
|
const next = [...listOf(side)];
|
|
@@ -219,7 +304,7 @@ export function KptPickList({ source, defaultSource = EMPTY, onSourceChange, tar
|
|
|
219
304
|
if (moved === undefined)
|
|
220
305
|
return;
|
|
221
306
|
next.push(moved);
|
|
222
|
-
setListOf(side)(next);
|
|
307
|
+
withMotion(() => setListOf(side)(next), origin);
|
|
223
308
|
};
|
|
224
309
|
const column = (side) => {
|
|
225
310
|
const items = listOf(side);
|
|
@@ -227,8 +312,11 @@ export function KptPickList({ source, defaultSource = EMPTY, onSourceChange, tar
|
|
|
227
312
|
const header = headerOf(side);
|
|
228
313
|
return (_jsxs("div", { className: "kpt-pick-list__col", children: [_jsx("div", { className: "kpt-pick-list__header", children: header }), _jsx("ul", { className: cn('kpt-pick-list__items', listOver === side && 'is-dragover'), role: "listbox", "aria-multiselectable": "true", "aria-label": header, onDragOver: (event) => onListDragOver(side, event), onDragLeave: () => setListOver(null), onDrop: (event) => onListDrop(side, event), children: items.map((item, index) => {
|
|
229
314
|
const dragging = drag?.side === side && drag.index === index;
|
|
230
|
-
return (_jsx("li", {
|
|
315
|
+
return (_jsx("li", { ref: (element) => {
|
|
316
|
+
if (element)
|
|
317
|
+
keyOf.current.set(element, item);
|
|
318
|
+
}, className: cn('kpt-pick-list__item', selection.has(item) && 'is-selected', dragging && 'is-dragging', dragdrop && 'kpt-pick-list__item--draggable', over?.side === side && over.index === index && !dragging && 'kpt-pick-list__item--dragover'), role: "option", "aria-selected": selection.has(item), tabIndex: index === tabIndexOf(side) ? 0 : -1, onFocus: () => setFocusOf(side)(index), onKeyDown: (event) => onItemKeyDown(side, index, item, event), draggable: dragdrop || undefined, onClick: () => toggle(side, item), onDoubleClick: (event) => moveOne(side, item, event.currentTarget), onDragStart: (event) => onDragStart(side, index, event), onDragOver: (event) => onDragOver(side, index, event), onDragLeave: () => setOver(null), onDrop: (event) => onDrop(side, index, event), onDragEnd: clearDrag, children: renderItem(item, index) }, index));
|
|
231
319
|
}) })] }));
|
|
232
320
|
};
|
|
233
|
-
return (_jsxs("div", { ref: composeRefs(rootRef, ref), className: cn('kpt-pick-list-host', className), ...rest, children: [_jsxs("div", { className: "kpt-pick-list", children: [column('source'), _jsxs("div", { className: "kpt-pick-list__controls", children: [_jsxs("button", { type: "button", "aria-label": t('pickList.moveAllRight'), "aria-disabled": !left.length || undefined, onClick: () => move('source', true), children: [_jsx(KptIcon, { name: "chevron-right" }), _jsx(KptIcon, { name: "chevron-right" })] }), _jsx("button", { type: "button", "aria-label": t('pickList.moveRight'), "aria-disabled": !selLeft.size || undefined, onClick: () => move('source', false), children: _jsx(KptIcon, { name: "chevron-right" }) }), _jsx("button", { type: "button", "aria-label": t('pickList.moveLeft'), "aria-disabled": !selRight.size || undefined, onClick: () => move('target', false), children: _jsx(KptIcon, { name: "chevron-left" }) }), _jsxs("button", { type: "button", "aria-label": t('pickList.moveAllLeft'), "aria-disabled": !right.length || undefined, onClick: () => move('target', true), children: [_jsx(KptIcon, { name: "chevron-left" }), _jsx(KptIcon, { name: "chevron-left" })] })] }), column('target')] }), _jsx("p", { className: "kpt-visually-hidden", "aria-live": "polite", children: announcement })] }));
|
|
321
|
+
return (_jsxs("div", { ref: composeRefs(rootRef, ref), className: cn('kpt-pick-list-host', className), ...rest, children: [_jsxs("div", { className: "kpt-pick-list", children: [column('source'), _jsxs("div", { className: "kpt-pick-list__controls", children: [_jsxs("button", { type: "button", "aria-label": t('pickList.moveAllRight'), "aria-disabled": !left.length || undefined, onClick: (event) => move('source', true, event.currentTarget), children: [_jsx(KptIcon, { name: "chevron-right" }), _jsx(KptIcon, { name: "chevron-right" })] }), _jsx("button", { type: "button", "aria-label": t('pickList.moveRight'), "aria-disabled": !selLeft.size || undefined, onClick: (event) => move('source', false, event.currentTarget), children: _jsx(KptIcon, { name: "chevron-right" }) }), _jsx("button", { type: "button", "aria-label": t('pickList.moveLeft'), "aria-disabled": !selRight.size || undefined, onClick: (event) => move('target', false, event.currentTarget), children: _jsx(KptIcon, { name: "chevron-left" }) }), _jsxs("button", { type: "button", "aria-label": t('pickList.moveAllLeft'), "aria-disabled": !right.length || undefined, onClick: (event) => move('target', true, event.currentTarget), children: [_jsx(KptIcon, { name: "chevron-left" }), _jsx(KptIcon, { name: "chevron-left" })] })] }), column('target')] }), _jsx("p", { className: "kpt-visually-hidden", "aria-live": "polite", children: announcement })] }));
|
|
234
322
|
}
|
package/dist/popover/llms.txt
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
# KptPopover (@konce-pt/react)
|
|
2
2
|
|
|
3
|
-
Any content in a bubble pinned to its trigger
|
|
3
|
+
Any content in a bubble pinned to its trigger - richer than a tooltip.
|
|
4
4
|
Import: `import { KptPopover } from '@konce-pt/react';`
|
|
5
5
|
|
|
6
6
|
## DOM
|
|
7
7
|
<span class="kpt-popover-host">
|
|
8
|
-
<span class="kpt-popover__trigger"
|
|
8
|
+
<span class="kpt-popover__trigger">...trigger...</span>
|
|
9
9
|
</span>
|
|
10
10
|
<!-- while open, in a portal on document.body: -->
|
|
11
|
-
<div class="kpt-popover__panel" role="dialog"
|
|
11
|
+
<div class="kpt-popover__panel" role="dialog">...children...</div>
|
|
12
12
|
|
|
13
13
|
## Props
|
|
14
|
-
- `trigger`: ReactNode
|
|
15
|
-
- `children`: ReactNode
|
|
16
|
-
- `open` / `defaultOpen` / `onOpenChange`
|
|
17
|
-
- `placement`: 'bottom' (default) | 'top'
|
|
14
|
+
- `trigger`: ReactNode - the element that opens the bubble, rendered in place
|
|
15
|
+
- `children`: ReactNode - the panel content
|
|
16
|
+
- `open` / `defaultOpen` / `onOpenChange` - controlled or uncontrolled
|
|
17
|
+
- `placement`: 'bottom' (default) | 'top' - the preferred side; it flips when there is no room
|
|
18
18
|
- `className`, `ref` and every other `<span>` prop go to the host
|
|
19
19
|
|
|
20
20
|
## The panel is a portal
|
|
@@ -22,7 +22,7 @@ The Angular port stands on CDK Overlay. Here the panel renders into a portal on
|
|
|
22
22
|
with the same behaviour: positioned below the trigger, flipping above when there is no room, closed
|
|
23
23
|
by a click outside or by Escape, and following scroll and resize.
|
|
24
24
|
|
|
25
|
-
Clicking the trigger while the bubble is open closes it and does not reopen it
|
|
25
|
+
Clicking the trigger while the bubble is open closes it and does not reopen it - the transparent
|
|
26
26
|
backdrop takes that click, exactly as the CDK backdrop does.
|
|
27
27
|
|
|
28
28
|
## Examples
|
|
@@ -43,10 +43,10 @@ The panel is `role="dialog"` with an `id` the trigger points to.
|
|
|
43
43
|
|
|
44
44
|
## Focus and keyboard
|
|
45
45
|
The control inside the trigger slot gets `aria-haspopup="dialog"`, a live `aria-expanded` and, while
|
|
46
|
-
open, `aria-controls`
|
|
46
|
+
open, `aria-controls` - on the real `<button>`, not on the wrapper. Opening moves focus to the first
|
|
47
47
|
interactive element of the bubble; `Escape` or a click outside closes it, and focus returns to the
|
|
48
|
-
trigger when it was inside the bubble. Focus is not trapped
|
|
48
|
+
trigger when it was inside the bubble. Focus is not trapped - the popover is supporting content, not
|
|
49
49
|
a modal.
|
|
50
50
|
|
|
51
51
|
## Name and Escape
|
|
52
|
-
Give the panel `ariaLabel`
|
|
52
|
+
Give the panel `ariaLabel` - it is a `role="dialog"`. Escape closes only the top-most panel and does not reach an enclosing `<dialog>`, so a popover inside a dialog closes alone.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ComponentPropsWithRef, type ReactNode } from 'react';
|
|
2
2
|
export interface KptPopoverProps extends Omit<ComponentPropsWithRef<'span'>, 'content'> {
|
|
3
|
-
/** Element otwierający dymek
|
|
3
|
+
/** Element otwierający dymek - renderowany w miejscu popovera. */
|
|
4
4
|
trigger: ReactNode;
|
|
5
5
|
/** Treść panelu. */
|
|
6
6
|
children?: ReactNode;
|
|
@@ -9,11 +9,11 @@ export interface KptPopoverProps extends Omit<ComponentPropsWithRef<'span'>, 'co
|
|
|
9
9
|
onOpenChange?: (open: boolean) => void;
|
|
10
10
|
/** Preferowana strona dymka; gdy brakuje miejsca, przechodzi na drugą. */
|
|
11
11
|
placement?: 'bottom' | 'top';
|
|
12
|
-
/** Nazwa panelu (`role="dialog"`)
|
|
12
|
+
/** Nazwa panelu (`role="dialog"`) - okno bez nazwy czytnik ogłasza jako samo "okno dialogowe". */
|
|
13
13
|
ariaLabel?: string;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
* Popover
|
|
16
|
+
* Popover - dowolna treść w dymku przypiętym do wyzwalacza (bogatszy niż tooltip).
|
|
17
17
|
*
|
|
18
18
|
* Port Angulara stoi na CDK Overlay; tutaj panel renderuje się w portalu do `document.body`,
|
|
19
19
|
* z tym samym zachowaniem: pozycja pod wyzwalaczem (albo nad nim przy `placement="top"`)
|
|
@@ -25,7 +25,7 @@ export interface KptPopoverProps extends Omit<ComponentPropsWithRef<'span'>, 'co
|
|
|
25
25
|
*
|
|
26
26
|
* @example
|
|
27
27
|
* <KptPopover trigger={<KptButton variant="outline">Szczegóły</KptButton>}>
|
|
28
|
-
* <div>Bogata treść popovera
|
|
28
|
+
* <div>Bogata treść popovera...</div>
|
|
29
29
|
* </KptPopover>
|
|
30
30
|
*/
|
|
31
31
|
export declare function KptPopover({ trigger, children, open, defaultOpen, onOpenChange, placement, ariaLabel, className, ...rest }: Readonly<KptPopoverProps>): import("react").JSX.Element;
|
package/dist/popover/popover.js
CHANGED
|
@@ -5,10 +5,10 @@ import { cn } from "../internal/cn.js";
|
|
|
5
5
|
import { KptOverlay } from "../internal/overlay.js";
|
|
6
6
|
import { useControllableState } from "../internal/use-controllable-state.js";
|
|
7
7
|
import { useKptId } from "../internal/use-id.js";
|
|
8
|
-
/** Elementy, które same przyjmują fokus
|
|
8
|
+
/** Elementy, które same przyjmują fokus - pierwszy z nich dostaje fokus po otwarciu dymka. */
|
|
9
9
|
const FOCUSABLE = 'a[href], button:not(:disabled), input:not(:disabled), select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
10
10
|
/**
|
|
11
|
-
* Popover
|
|
11
|
+
* Popover - dowolna treść w dymku przypiętym do wyzwalacza (bogatszy niż tooltip).
|
|
12
12
|
*
|
|
13
13
|
* Port Angulara stoi na CDK Overlay; tutaj panel renderuje się w portalu do `document.body`,
|
|
14
14
|
* z tym samym zachowaniem: pozycja pod wyzwalaczem (albo nad nim przy `placement="top"`)
|
|
@@ -20,12 +20,12 @@ const FOCUSABLE = 'a[href], button:not(:disabled), input:not(:disabled), select,
|
|
|
20
20
|
*
|
|
21
21
|
* @example
|
|
22
22
|
* <KptPopover trigger={<KptButton variant="outline">Szczegóły</KptButton>}>
|
|
23
|
-
* <div>Bogata treść popovera
|
|
23
|
+
* <div>Bogata treść popovera...</div>
|
|
24
24
|
* </KptPopover>
|
|
25
25
|
*/
|
|
26
26
|
export function KptPopover({ trigger, children, open, defaultOpen = false, onOpenChange, placement = 'bottom', ariaLabel = '', className, ...rest }) {
|
|
27
27
|
const triggerRef = useRef(null);
|
|
28
|
-
/** Kotwica panelu
|
|
28
|
+
/** Kotwica panelu - w stanie, bo czyta ją render; ref zostaje dla handlerów. */
|
|
29
29
|
const [anchor, setAnchor] = useState(null);
|
|
30
30
|
const setTrigger = useCallback((element) => {
|
|
31
31
|
triggerRef.current = element;
|
|
@@ -51,7 +51,7 @@ export function KptPopover({ trigger, children, open, defaultOpen = false, onOpe
|
|
|
51
51
|
else
|
|
52
52
|
control.removeAttribute('aria-controls');
|
|
53
53
|
}, [isOpen, trigger, panelId]);
|
|
54
|
-
// Fokus do dymka klatkę później
|
|
54
|
+
// Fokus do dymka klatkę później - `KptOverlay` trzyma panel niewidoczny, dopóki go nie zmierzy.
|
|
55
55
|
useEffect(() => {
|
|
56
56
|
if (!isOpen)
|
|
57
57
|
return;
|
package/dist/progress/llms.txt
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# KptProgress (@konce-pt/react)
|
|
2
2
|
|
|
3
|
-
A progress indicator
|
|
3
|
+
A progress indicator - linear or circular, determinate (`min`-`max`) or indeterminate (`value` = null).
|
|
4
4
|
Import: `import { KptProgress } from '@konce-pt/react';`
|
|
5
5
|
|
|
6
6
|
## DOM
|
|
7
7
|
<!-- linear, with a label, a buffer and a value -->
|
|
8
8
|
<div class="kpt-progress-host" data-type="linear" data-size="md" data-variant="primary" data-label-position="top">
|
|
9
|
-
<span class="kpt-progress__label">Loading
|
|
9
|
+
<span class="kpt-progress__label">Loading...</span>
|
|
10
10
|
<div class="kpt-progress__linear" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="80">
|
|
11
11
|
<div class="kpt-progress__buffer" style="width: 92%"></div>
|
|
12
12
|
<div class="kpt-progress__bar" style="width: 80%"></div>
|
|
@@ -23,28 +23,28 @@ Import: `import { KptProgress } from '@konce-pt/react';`
|
|
|
23
23
|
<span class="kpt-progress__value" aria-hidden="true">75%</span>
|
|
24
24
|
</div>
|
|
25
25
|
|
|
26
|
-
The label, the track and the value are siblings straight under the host
|
|
26
|
+
The label, the track and the value are siblings straight under the host - there is no wrapper element.
|
|
27
27
|
`data-variant`, `data-type`, `data-size` and `data-label-position` all sit on the host, which is also
|
|
28
28
|
where the private `--_color` and `--_thickness` are resolved. This markup matches the Angular port
|
|
29
29
|
element for element, so both share one stylesheet.
|
|
30
30
|
|
|
31
31
|
## Props
|
|
32
|
-
- `value`: number | null (default null)
|
|
32
|
+
- `value`: number | null (default null) - a value on the `min`-`max` scale, or null for indeterminate
|
|
33
33
|
- `min`: number (default 0); `max`: number (default 100)
|
|
34
34
|
- `variant`: 'primary' | 'success' | 'danger' | 'warning' | 'info' (default 'primary')
|
|
35
35
|
- `type`: 'linear' | 'circular' (default 'linear')
|
|
36
|
-
- `size`: 'sm' | 'md' | 'lg' (default 'md')
|
|
37
|
-
- `diameter`: number (default 40)
|
|
38
|
-
- `bufferValue`: number | null (default null)
|
|
39
|
-
- `showValue`: boolean (default false)
|
|
36
|
+
- `size`: 'sm' | 'md' | 'lg' (default 'md') - track thickness, and arc width on the circular variant
|
|
37
|
+
- `diameter`: number (default 40) - the circular variant's size in pixels
|
|
38
|
+
- `bufferValue`: number | null (default null) - a second, dimmed bar behind the main one; linear only
|
|
39
|
+
- `showValue`: boolean (default false) - turns the value area on; `children` needs it too
|
|
40
40
|
- `valueFormat`: 'percent' | 'fraction' | 'none' (default 'percent')
|
|
41
|
-
- `label`: string
|
|
42
|
-
- `labelPosition`: 'top' | 'bottom' | 'end' (default 'top')
|
|
43
|
-
- `locale`, `dictionary`
|
|
41
|
+
- `label`: string - descriptive text next to the bar; it also becomes the `aria-label`
|
|
42
|
+
- `labelPosition`: 'top' | 'bottom' | 'end' (default 'top') - ignored by the circular variant
|
|
43
|
+
- `locale`, `dictionary` - per-instance dictionary overrides
|
|
44
44
|
- `className`, `ref` and every other `<div>` prop go to the host
|
|
45
45
|
|
|
46
46
|
## Value label
|
|
47
|
-
`showValue` opens the value area; `valueFormat` decides what goes in it
|
|
47
|
+
`showValue` opens the value area; `valueFormat` decides what goes in it - `percent` renders `80%`,
|
|
48
48
|
`fraction` renders `152 / 160` from `value` and `max`, `none` leaves it empty. Both strings come from
|
|
49
49
|
the `KptMessages` dictionary (`progress.percent`, `progress.fraction`), so a new locale can reshape them.
|
|
50
50
|
|
|
@@ -57,17 +57,17 @@ the accessible name.
|
|
|
57
57
|
|
|
58
58
|
## How the arc is drawn
|
|
59
59
|
The circle lives in a fixed `viewBox="0 0 40 40"` with `r=16`, so the circumference is computed from
|
|
60
|
-
that radius, not from `diameter`
|
|
60
|
+
that radius, not from `diameter` - the SVG scales, the maths does not change. The arc is the dash
|
|
61
61
|
offset: full circumference means empty, zero means complete. `size` only changes `stroke-width`, and
|
|
62
62
|
the widest step still fits inside the box, so no arc is ever clipped.
|
|
63
63
|
|
|
64
|
-
Values outside the range are clamped rather than rejected, `max`
|
|
65
|
-
buffer is never allowed behind the main bar
|
|
64
|
+
Values outside the range are clamped rather than rejected, `max` <= `min` collapses to zero, and the
|
|
65
|
+
buffer is never allowed behind the main bar - a computed percentage that briefly overshoots cannot
|
|
66
66
|
break the drawing.
|
|
67
67
|
|
|
68
68
|
## Examples
|
|
69
69
|
<KptProgress value={60} />
|
|
70
|
-
<KptProgress value={80} label="Loading
|
|
70
|
+
<KptProgress value={80} label="Loading..." showValue />
|
|
71
71
|
<KptProgress value={152} max={160} size="lg" showValue valueFormat="fraction" labelPosition="bottom" />
|
|
72
72
|
<KptProgress value={65} showValue labelPosition="end" />
|
|
73
73
|
<KptProgress value={38} bufferValue={62} />
|
|
@@ -91,5 +91,5 @@ leaves the value out, which is how a screen reader learns the progress is unknow
|
|
|
91
91
|
announcing the raw number as a percentage. The visible value is `aria-hidden`, so it is never read
|
|
92
92
|
twice. The accessible name comes from `label`, or from the dictionary when there is none.
|
|
93
93
|
|
|
94
|
-
Under `prefers-reduced-motion: reduce` the indeterminate animation slows down instead of stopping
|
|
94
|
+
Under `prefers-reduced-motion: reduce` the indeterminate animation slows down instead of stopping -
|
|
95
95
|
a frozen progress indicator reads as a hung application.
|
|
@@ -3,12 +3,12 @@ import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
|
|
|
3
3
|
export type KptProgressVariant = 'primary' | 'success' | 'danger' | 'warning' | 'info';
|
|
4
4
|
export type KptProgressType = 'linear' | 'circular';
|
|
5
5
|
export type KptProgressSize = 'sm' | 'md' | 'lg';
|
|
6
|
-
/** Postać etykiety wartości: procent,
|
|
6
|
+
/** Postać etykiety wartości: procent, "ile z ilu" albo brak. */
|
|
7
7
|
export type KptProgressValueFormat = 'percent' | 'fraction' | 'none';
|
|
8
8
|
/** Gdzie siada wiersz etykiety względem paska (tylko `type="linear"`). */
|
|
9
9
|
export type KptProgressLabelPosition = 'top' | 'bottom' | 'end';
|
|
10
10
|
export interface KptProgressProps extends ComponentPropsWithRef<'div'>, KptI18nOverrides {
|
|
11
|
-
/** Wartość w skali `min
|
|
11
|
+
/** Wartość w skali `min`-`max` albo `null` = postęp nieokreślony. */
|
|
12
12
|
value?: number | null;
|
|
13
13
|
min?: number;
|
|
14
14
|
max?: number;
|
|
@@ -18,26 +18,26 @@ export interface KptProgressProps extends ComponentPropsWithRef<'div'>, KptI18nO
|
|
|
18
18
|
size?: KptProgressSize;
|
|
19
19
|
/** Średnica wariantu kołowego w pikselach. */
|
|
20
20
|
diameter?: number;
|
|
21
|
-
/** Postęp buforowania
|
|
21
|
+
/** Postęp buforowania - drugi, przygaszony pasek pod głównym (tylko liniowy). */
|
|
22
22
|
bufferValue?: number | null;
|
|
23
|
-
/** Włącza obszar etykiety wartości
|
|
23
|
+
/** Włącza obszar etykiety wartości - razem z nim renderuje się `children`. */
|
|
24
24
|
showValue?: boolean;
|
|
25
25
|
valueFormat?: KptProgressValueFormat;
|
|
26
26
|
/** Tekst opisowy obok paska; służy też za `aria-label`. */
|
|
27
27
|
label?: string;
|
|
28
28
|
labelPosition?: KptProgressLabelPosition;
|
|
29
|
-
/** Zastępuje sformatowaną wartość
|
|
29
|
+
/** Zastępuje sformatowaną wartość - wymaga `showValue`. */
|
|
30
30
|
children?: ReactNode;
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* Wskaźnik postępu
|
|
33
|
+
* Wskaźnik postępu - liniowy lub kołowy, określony (`min`-`max`) albo nieokreślony (`value` = null).
|
|
34
34
|
*
|
|
35
35
|
* Etykietę wartości włącza `showValue`; `children` zastępuje sformatowaną wartość,
|
|
36
36
|
* więc w środku koła można pokazać cokolwiek.
|
|
37
37
|
*
|
|
38
38
|
* @example
|
|
39
39
|
* <KptProgress value={60} />
|
|
40
|
-
* <KptProgress value={80} label="Ładowanie
|
|
40
|
+
* <KptProgress value={80} label="Ładowanie..." showValue />
|
|
41
41
|
* <KptProgress value={152} max={160} showValue valueFormat="fraction" labelPosition="bottom" />
|
|
42
42
|
* <KptProgress value={38} bufferValue={62} />
|
|
43
43
|
* <KptProgress type="circular" value={75} variant="success" showValue />
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { cn } from "../internal/cn.js";
|
|
4
4
|
import { useKptMessages } from "../i18n/i18n-context.js";
|
|
5
|
-
/** Promień okręgu w viewBox 0 0 40 40
|
|
5
|
+
/** Promień okręgu w viewBox 0 0 40 40 - obwód liczymy z niego, nie ze średnicy w pikselach. */
|
|
6
6
|
const RADIUS = 16;
|
|
7
7
|
const CIRCUMFERENCE = 2 * Math.PI * RADIUS;
|
|
8
8
|
/**
|
|
9
|
-
* Wskaźnik postępu
|
|
9
|
+
* Wskaźnik postępu - liniowy lub kołowy, określony (`min`-`max`) albo nieokreślony (`value` = null).
|
|
10
10
|
*
|
|
11
11
|
* Etykietę wartości włącza `showValue`; `children` zastępuje sformatowaną wartość,
|
|
12
12
|
* więc w środku koła można pokazać cokolwiek.
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* <KptProgress value={60} />
|
|
16
|
-
* <KptProgress value={80} label="Ładowanie
|
|
16
|
+
* <KptProgress value={80} label="Ładowanie..." showValue />
|
|
17
17
|
* <KptProgress value={152} max={160} showValue valueFormat="fraction" labelPosition="bottom" />
|
|
18
18
|
* <KptProgress value={38} bufferValue={62} />
|
|
19
19
|
* <KptProgress type="circular" value={75} variant="success" showValue />
|
|
@@ -22,7 +22,7 @@ const CIRCUMFERENCE = 2 * Math.PI * RADIUS;
|
|
|
22
22
|
export function KptProgress({ value = null, min = 0, max = 100, variant = 'primary', type = 'linear', size = 'md', diameter = 40, bufferValue = null, showValue = false, valueFormat = 'percent', label, labelPosition = 'top', locale, dictionary, className, children, ...rest }) {
|
|
23
23
|
const { t } = useKptMessages({ locale, dictionary });
|
|
24
24
|
const indeterminate = value == null;
|
|
25
|
-
/** Ułamek 0
|
|
25
|
+
/** Ułamek 0-1. Odporny na `max` <= `min` i na wartości spoza zakresu. */
|
|
26
26
|
const toRatio = (v) => {
|
|
27
27
|
if (v == null)
|
|
28
28
|
return 0;
|
|
@@ -33,7 +33,7 @@ export function KptProgress({ value = null, min = 0, max = 100, variant = 'prima
|
|
|
33
33
|
};
|
|
34
34
|
const ratio = toRatio(value);
|
|
35
35
|
const percent = Math.round(ratio * 100);
|
|
36
|
-
// Bufor nigdy nie cofa się za pasek główny
|
|
36
|
+
// Bufor nigdy nie cofa się za pasek główny - inaczej wyglądałby jak błąd renderowania.
|
|
37
37
|
const bufferRatio = Math.max(ratio, toRatio(bufferValue));
|
|
38
38
|
const offset = CIRCUMFERENCE * (1 - ratio);
|
|
39
39
|
const fractionText = () => t('progress.fraction', { value: value ?? 0, max });
|
|
@@ -42,7 +42,7 @@ export function KptProgress({ value = null, min = 0, max = 100, variant = 'prima
|
|
|
42
42
|
valueText = valueFormat === 'fraction' ? fractionText() : t('progress.percent', { value: percent });
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
|
-
* Czytnik ekranu domyślnie odczytuje `aria-valuenow` jako procent, więc przy formacie
|
|
45
|
+
* Czytnik ekranu domyślnie odczytuje `aria-valuenow` jako procent, więc przy formacie "ile z ilu"
|
|
46
46
|
* podajemy mu ten sam napis, który widzi użytkownik.
|
|
47
47
|
*/
|
|
48
48
|
const ariaValueText = indeterminate || valueFormat !== 'fraction' ? undefined : fractionText();
|
package/dist/public-api.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export type { KptPanelProps } from './panel/panel.tsx';
|
|
|
13
13
|
export { KptStepper, KptStep, useKptStepper } from './stepper/stepper.tsx';
|
|
14
14
|
export type { KptStepProps, KptStepperContextValue, KptStepperProps } from './stepper/stepper.tsx';
|
|
15
15
|
export { KptFieldset } from './fieldset/fieldset.tsx';
|
|
16
|
-
export type { KptFieldsetProps } from './fieldset/fieldset.tsx';
|
|
16
|
+
export type { KptFieldsetProps, KptFieldsetVariant } from './fieldset/fieldset.tsx';
|
|
17
17
|
export { KptTimeline } from './timeline/timeline.tsx';
|
|
18
18
|
export type { KptTimelineItem, KptTimelineProps } from './timeline/timeline.tsx';
|
|
19
19
|
export { KptAlert } from './alert/alert.tsx';
|
|
@@ -26,6 +26,10 @@ export { KptProgress } from './progress/progress.tsx';
|
|
|
26
26
|
export type { KptProgressProps, KptProgressVariant, KptProgressType, KptProgressSize, KptProgressValueFormat, KptProgressLabelPosition, } from './progress/progress.tsx';
|
|
27
27
|
export { KptSpinner } from './spinner/spinner.tsx';
|
|
28
28
|
export type { KptSpinnerProps } from './spinner/spinner.tsx';
|
|
29
|
+
export { KptLoader } from './loader/loader.tsx';
|
|
30
|
+
export type { KptLoaderProps, KptLoaderColor, KptLoaderResult, KptLoaderStatus, KptLoaderVariant } from './loader/loader.tsx';
|
|
31
|
+
export { KptUpdate } from './update/update.tsx';
|
|
32
|
+
export type { KptUpdateProps, KptUpdateAction, KptUpdateStatus } from './update/update.tsx';
|
|
29
33
|
export { KptSkeleton } from './skeleton/skeleton.tsx';
|
|
30
34
|
export type { KptSkeletonProps, KptSkeletonVariant } from './skeleton/skeleton.tsx';
|
|
31
35
|
export { KptIcon } from './icon/icon.tsx';
|
|
@@ -89,8 +93,8 @@ export { kptConfirm, useKptConfirmRequest } from './confirm/confirm-store.ts';
|
|
|
89
93
|
export type { KptConfirmOptions, KptConfirmRequest } from './confirm/confirm-store.ts';
|
|
90
94
|
export { KptToastContainer } from './toast/toast-container.tsx';
|
|
91
95
|
export type { KptToastContainerProps } from './toast/toast-container.tsx';
|
|
92
|
-
export { kptToast, useKptToasts } from './toast/toast-store.ts';
|
|
93
|
-
export type { KptToast, KptToastAction, KptToastOptions } from './toast/toast-store.ts';
|
|
96
|
+
export { kptToast, useKptToasts, useKptToastsPaused, resolveKptToast, KPT_TOAST_FALLBACK_DURATION } from './toast/toast-store.ts';
|
|
97
|
+
export type { KptToast, KptToastAction, KptToastAppearance, KptToastConfig, KptToastOptions, KptToastPosition, } from './toast/toast-store.ts';
|
|
94
98
|
export { KptMenu } from './menu/menu.tsx';
|
|
95
99
|
export { KptMenubar } from './menubar/menubar.tsx';
|
|
96
100
|
export type { KptMenubarProps } from './menubar/menubar.tsx';
|
|
@@ -172,6 +176,14 @@ export type { KptPaginatorProps } from './paginator/paginator.tsx';
|
|
|
172
176
|
export { KptButton } from './button/button.tsx';
|
|
173
177
|
export { KptIconButton } from './icon-button/icon-button.tsx';
|
|
174
178
|
export type { KptIconButtonProps } from './icon-button/icon-button.tsx';
|
|
179
|
+
export { KptSpeechButton } from './speech/speech-button.tsx';
|
|
180
|
+
export type { KptSpeechButtonProps, KptSpeechColor, KptSpeechUnsupported } from './speech/speech-button.tsx';
|
|
181
|
+
export { KptSpeechWave } from './speech/speech-wave.tsx';
|
|
182
|
+
export type { KptSpeechWaveProps } from './speech/speech-wave.tsx';
|
|
183
|
+
export { useKptSpeechRecognition } from './speech/use-speech-recognition.ts';
|
|
184
|
+
export type { KptSpeechRecognition, KptSpeechRecognitionOptions, KptSpeechTargetRef, } from './speech/use-speech-recognition.ts';
|
|
185
|
+
export type { KptSpeechEndReason, KptSpeechErrorCode, KptSpeechInterimDisplay, KptSpeechMode, KptSpeechSnapshot, KptSpeechStatus, KptSpeechSupport, KptSpeechTarget, KptSpeechTargetInput, KptSpeechWaveMode, } from '@konce-pt/speech';
|
|
186
|
+
export { defaultSpeechLang, resolveSpeechTarget, speechSupport } from '@konce-pt/speech';
|
|
175
187
|
export { KptFab } from './fab/fab.tsx';
|
|
176
188
|
export type { KptFabProps } from './fab/fab.tsx';
|
|
177
189
|
export { KptSplitButton } from './split-button/split-button.tsx';
|