@konce-pt/react 0.12.0 → 0.15.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 +12 -7
- package/dist/dialog/dialog.js +4 -4
- package/dist/dialog/llms.txt +14 -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
|
@@ -9,9 +9,9 @@ import { KptIcon } from "../icon/icon.js";
|
|
|
9
9
|
import { kptIsPlainClick } from "../shared/types.js";
|
|
10
10
|
import { focusMenuEdge, handleMenuKeydown } from "../menu/menu-keys.js";
|
|
11
11
|
/**
|
|
12
|
-
* Mega-menu
|
|
13
|
-
* Struktura: pozycja górna
|
|
14
|
-
* Pozycja górna bez kolumn działa jak akcja
|
|
12
|
+
* Mega-menu - pozioma belka z szerokim, wielokolumnowym panelem.
|
|
13
|
+
* Struktura: pozycja górna -> `items` (kolumny) -> `items` kolumny (odnośniki).
|
|
14
|
+
* Pozycja górna bez kolumn działa jak akcja - wywołuje `onSelect` zamiast otwierać pusty panel.
|
|
15
15
|
*
|
|
16
16
|
* Panel kotwiczy się do CAŁEJ belki, nie do pojedynczego przycisku: jest szeroki, więc ma
|
|
17
17
|
* zaczynać się przy krawędzi menu, a nie przy przypadkowej pozycji, w którą kliknięto.
|
|
@@ -19,25 +19,25 @@ import { focusMenuEdge, handleMenuKeydown } from "../menu/menu-keys.js";
|
|
|
19
19
|
* Klawiatura jak w `KptMenubar`: belka to jeden przystanek Tab, strzałki w lewo/prawo
|
|
20
20
|
* i `Home`/`End` chodzą po pozycjach górnych, strzałka w dół (albo `Enter`/spacja) otwiera panel
|
|
21
21
|
* z fokusem na pierwszym odnośniku. W panelu strzałki w górę/dół przechodzą po wszystkich
|
|
22
|
-
* odnośnikach kolumna po kolumnie, w lewo/prawo
|
|
22
|
+
* odnośnikach kolumna po kolumnie, w lewo/prawo - do panelu sąsiedniej pozycji, a `Escape`
|
|
23
23
|
* zamyka panel i oddaje fokus belce.
|
|
24
24
|
*
|
|
25
25
|
* @example
|
|
26
26
|
* <KptMegamenu items={items} onSelect={onSelect} />
|
|
27
27
|
*/
|
|
28
28
|
export function KptMegamenu({ items = [], onSelect, onNavigate, ariaLabel, className, ...rest }) {
|
|
29
|
-
/** Pasek jako kotwica panelu
|
|
29
|
+
/** Pasek jako kotwica panelu - w stanie, bo czyta go render. */
|
|
30
30
|
const [bar, setBar] = useState(null);
|
|
31
31
|
const panelRef = useRef(null);
|
|
32
32
|
const buttonsRef = useRef([]);
|
|
33
33
|
const [openIndex, setOpenIndex] = useState(null);
|
|
34
|
-
// Ostatnio skupiona pozycja górna
|
|
34
|
+
// Ostatnio skupiona pozycja górna - ona jest przystankiem Tab belki.
|
|
35
35
|
const [focusIndex, setFocusIndex] = useState(0);
|
|
36
|
-
// Który odnośnik skupić po otwarciu
|
|
36
|
+
// Który odnośnik skupić po otwarciu - strzałka w górę otwiera "od końca".
|
|
37
37
|
const focusEdge = useRef('first');
|
|
38
38
|
const panelId = useKptId(undefined, 'kpt-megamenu');
|
|
39
39
|
const disabled = items.map((item) => !!item.disabled);
|
|
40
|
-
// Pozycja z `url` (bez kolumn, niewyłączona) to `<a href>`
|
|
40
|
+
// Pozycja z `url` (bez kolumn, niewyłączona) to `<a href>` - nawigację robi przeglądarka,
|
|
41
41
|
// więc działa nowa karta i podgląd adresu. `onSelect` i tak jest wołane.
|
|
42
42
|
const isLink = (item) => !!item.url && !item.items?.length && !item.disabled;
|
|
43
43
|
const tabStop = rovingStop(disabled, focusIndex);
|
|
@@ -102,7 +102,7 @@ export function KptMegamenu({ items = [], onSelect, onNavigate, ariaLabel, class
|
|
|
102
102
|
if (next === null)
|
|
103
103
|
return;
|
|
104
104
|
event.preventDefault();
|
|
105
|
-
// Przy otwartym panelu przejście w bok pokazuje panel sąsiada
|
|
105
|
+
// Przy otwartym panelu przejście w bok pokazuje panel sąsiada - jak w menu aplikacji.
|
|
106
106
|
if (openIndex === null)
|
|
107
107
|
focusTop(next);
|
|
108
108
|
else
|
|
@@ -125,7 +125,7 @@ export function KptMegamenu({ items = [], onSelect, onNavigate, ariaLabel, class
|
|
|
125
125
|
focusTop(top);
|
|
126
126
|
}
|
|
127
127
|
};
|
|
128
|
-
/** Zwykły klik w odnośnik
|
|
128
|
+
/** Zwykły klik w odnośnik -> `onNavigate` (Ctrl/Cmd/Shift, środkowy przycisk i `_blank` zostają natywne). */
|
|
129
129
|
const linkClick = (event, item) => {
|
|
130
130
|
if (item.url && onNavigate && kptIsPlainClick(event, event.currentTarget.target)) {
|
|
131
131
|
onNavigate({ item, url: item.url, event: event.nativeEvent });
|
package/dist/mention/llms.txt
CHANGED
|
@@ -14,19 +14,19 @@ Import: `import { KptMention, KptMentions } from '@konce-pt/react';`
|
|
|
14
14
|
<span class="kpt-mentions__text"> about the estimate.</span>
|
|
15
15
|
</span>
|
|
16
16
|
|
|
17
|
-
## KptMention
|
|
18
|
-
- `item`: `KptMentionItem`
|
|
19
|
-
- `id`, `label`, `kind`: string
|
|
20
|
-
- `prefix`: string (default '@'), `href`: string | null
|
|
21
|
-
- `placement`, `openDelay`
|
|
22
|
-
- `disabled`: boolean
|
|
23
|
-
- `children`: ReactNode
|
|
24
|
-
|
|
25
|
-
## KptMentions
|
|
26
|
-
- `text`: string
|
|
27
|
-
- `items`: `readonly KptMentionItem[]`
|
|
28
|
-
- `prefix`, `placement`
|
|
29
|
-
- `renderCard`: `(item, id, label) => ReactNode`
|
|
17
|
+
## KptMention - props
|
|
18
|
+
- `item`: `KptMentionItem` - the whole entry at once; the single props below win over it
|
|
19
|
+
- `id`, `label`, `kind`: string - `kind` lands in `data-kind`, so it can be styled per type
|
|
20
|
+
- `prefix`: string (default '@'), `href`: string | null - with `href` the mention is a link
|
|
21
|
+
- `placement`, `openDelay` - passed to `KptPeek`
|
|
22
|
+
- `disabled`: boolean - no card; the mention stays a plain highlighted word
|
|
23
|
+
- `children`: ReactNode - the card
|
|
24
|
+
|
|
25
|
+
## KptMentions - props
|
|
26
|
+
- `text`: string - the content with `@id` or `@[Name with spaces](id)`
|
|
27
|
+
- `items`: `readonly KptMentionItem[]` - entries the ids resolve against
|
|
28
|
+
- `prefix`, `placement` - passed to every mention
|
|
29
|
+
- `renderCard`: `(item, id, label) => ReactNode` - the card; without it mentions are plain words
|
|
30
30
|
|
|
31
31
|
## Example
|
|
32
32
|
<KptMentions
|
|
@@ -41,7 +41,7 @@ from `@konce-pt/mention` splits it into segments and the mention is an element t
|
|
|
41
41
|
itself. An application does not have to push user-written content through a sanitizer to get
|
|
42
42
|
mentions out of it.
|
|
43
43
|
|
|
44
|
-
An id that is not on the list still renders
|
|
44
|
+
An id that is not on the list still renders - the label falls back to the id, because a note has to
|
|
45
45
|
stay readable after someone leaves the team. Without `renderCard` the mention is a highlighted
|
|
46
46
|
word, not a button: there is nothing to open, so it does not pretend otherwise.
|
|
47
47
|
|
|
@@ -53,7 +53,7 @@ list, arrows and Enter (or Tab) insert the mention as
|
|
|
53
53
|
|
|
54
54
|
## Tokens
|
|
55
55
|
The mention is underlined with a **dotted** line: `--kpt-color-primary-border` at rest, darkening
|
|
56
|
-
to `--kpt-color-primary` on hover and while the card is open. Dotted, not solid
|
|
56
|
+
to `--kpt-color-primary` on hover and while the card is open. Dotted, not solid - a solid underline
|
|
57
57
|
would read as a link, and a mention usually leads nowhere, it opens a card. Text
|
|
58
58
|
`--kpt-color-primary`; a mention without a card `--kpt-color-text` + `--kpt-font-weight-medium` and
|
|
59
59
|
no line at all, since there is nothing to promise. Focus ring `--kpt-color-focus-ring`. The card
|
|
@@ -4,11 +4,11 @@ import { type KptPeekPlacement } from '../peek/peek.tsx';
|
|
|
4
4
|
export interface KptMentionProps extends Omit<ComponentPropsWithRef<'span'>, 'id' | 'prefix' | 'children'> {
|
|
5
5
|
/** Cała pozycja naraz. Pojedyncze propsy poniżej mają nad nią priorytet. */
|
|
6
6
|
item?: KptMentionItem | null;
|
|
7
|
-
/** Identyfikator zapisany w treści
|
|
7
|
+
/** Identyfikator zapisany w treści - nie zmienia się przy zmianie nazwy. */
|
|
8
8
|
id?: string;
|
|
9
9
|
/** Nazwa do pokazania; bez niej bierze się ją z `item`, a w ostateczności z `id`. */
|
|
10
10
|
label?: string;
|
|
11
|
-
/** Rodzaj (osoba, zadanie, dokument)
|
|
11
|
+
/** Rodzaj (osoba, zadanie, dokument) - ląduje w `data-kind`, więc da się go ostylować. */
|
|
12
12
|
kind?: string;
|
|
13
13
|
/** Znak przed nazwą. Pusty łańcuch zostawia samą nazwę. */
|
|
14
14
|
prefix?: string;
|
|
@@ -16,13 +16,13 @@ export interface KptMentionProps extends Omit<ComponentPropsWithRef<'span'>, 'id
|
|
|
16
16
|
href?: string | null;
|
|
17
17
|
placement?: KptPeekPlacement;
|
|
18
18
|
openDelay?: number;
|
|
19
|
-
/** Wyłączona wzmianka nie otwiera karty
|
|
19
|
+
/** Wyłączona wzmianka nie otwiera karty - zostaje samym napisem. */
|
|
20
20
|
disabled?: boolean;
|
|
21
21
|
/** Treść karty. Bez niej wzmianka też zostaje napisem: nie ma czego pokazać. */
|
|
22
22
|
children?: ReactNode;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
* Wzmianka w tekście
|
|
25
|
+
* Wzmianka w tekście - `@ktoś` albo `@coś` jako element, na który da się najechać i zobaczyć
|
|
26
26
|
* kartę podglądu z resztą powiązań. Treść karty daje aplikacja przez `children`: biblioteka nie
|
|
27
27
|
* wie, czym jest wzmiankowana rzecz, a osoba, zadanie i dokument wyglądają inaczej.
|
|
28
28
|
*
|
|
@@ -32,7 +32,7 @@ export interface KptMentionProps extends Omit<ComponentPropsWithRef<'span'>, 'id
|
|
|
32
32
|
*
|
|
33
33
|
* @example
|
|
34
34
|
* <KptMention id="anna.k" label="Anna Kowalska">
|
|
35
|
-
* <KptCard>Profil, projekty, kontakt
|
|
35
|
+
* <KptCard>Profil, projekty, kontakt...</KptCard>
|
|
36
36
|
* </KptMention>
|
|
37
37
|
*/
|
|
38
38
|
export declare function KptMention({ item, id, label, kind, prefix, href, placement, openDelay, disabled, children, className, ...rest }: Readonly<KptMentionProps>): import("react").JSX.Element;
|
package/dist/mention/mention.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { cn } from "../internal/cn.js";
|
|
3
3
|
import { KptPeek } from "../peek/peek.js";
|
|
4
4
|
/**
|
|
5
|
-
* Wzmianka w tekście
|
|
5
|
+
* Wzmianka w tekście - `@ktoś` albo `@coś` jako element, na który da się najechać i zobaczyć
|
|
6
6
|
* kartę podglądu z resztą powiązań. Treść karty daje aplikacja przez `children`: biblioteka nie
|
|
7
7
|
* wie, czym jest wzmiankowana rzecz, a osoba, zadanie i dokument wyglądają inaczej.
|
|
8
8
|
*
|
|
@@ -12,7 +12,7 @@ import { KptPeek } from "../peek/peek.js";
|
|
|
12
12
|
*
|
|
13
13
|
* @example
|
|
14
14
|
* <KptMention id="anna.k" label="Anna Kowalska">
|
|
15
|
-
* <KptCard>Profil, projekty, kontakt
|
|
15
|
+
* <KptCard>Profil, projekty, kontakt...</KptCard>
|
|
16
16
|
* </KptMention>
|
|
17
17
|
*/
|
|
18
18
|
export function KptMention({ item = null, id = '', label = '', kind = '', prefix = '@', href = null, placement = 'bottom', openDelay = 300, disabled = false, children, className, ...rest }) {
|
|
@@ -13,7 +13,7 @@ export interface KptMentionsProps<T = unknown> extends Omit<ComponentPropsWithRe
|
|
|
13
13
|
renderCard?: (item: KptMentionItem<T> | null, id: string, label: string) => ReactNode;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
* Akapit ze wzmiankami
|
|
16
|
+
* Akapit ze wzmiankami - tekst wchodzi jako zwykły napis, a `@wzmianki` wychodzą z niego jako
|
|
17
17
|
* elementy z kartą podglądu. Rozbiciem zajmuje się `parseMentionText()` z `@konce-pt/mention`
|
|
18
18
|
* (czysty TS z testami), więc oba porty czytają tę samą treść tak samo.
|
|
19
19
|
*
|
package/dist/mention/mentions.js
CHANGED
|
@@ -3,7 +3,7 @@ import { parseMentionText } from '@konce-pt/mention';
|
|
|
3
3
|
import { cn } from "../internal/cn.js";
|
|
4
4
|
import { KptMention } from "./mention.js";
|
|
5
5
|
/**
|
|
6
|
-
* Akapit ze wzmiankami
|
|
6
|
+
* Akapit ze wzmiankami - tekst wchodzi jako zwykły napis, a `@wzmianki` wychodzą z niego jako
|
|
7
7
|
* elementy z kartą podglądu. Rozbiciem zajmuje się `parseMentionText()` z `@konce-pt/mention`
|
|
8
8
|
* (czysty TS z testami), więc oba porty czytają tę samą treść tak samo.
|
|
9
9
|
*
|
package/dist/menu/llms.txt
CHANGED
|
@@ -4,29 +4,29 @@ A dropdown menu. Items come from `items`, the trigger from the `trigger` prop.
|
|
|
4
4
|
Import: `import { KptMenu, type KptMenuItem } from '@konce-pt/react';`
|
|
5
5
|
|
|
6
6
|
## DOM
|
|
7
|
-
<span class="kpt-menu-host"><span class="kpt-menu__trigger"
|
|
7
|
+
<span class="kpt-menu-host"><span class="kpt-menu__trigger">...trigger...</span></span>
|
|
8
8
|
<!-- while open, in a portal on document.body: -->
|
|
9
9
|
<div class="kpt-menu__panel" role="menu">
|
|
10
|
-
<div class="kpt-menu__header" role="presentation"
|
|
10
|
+
<div class="kpt-menu__header" role="presentation">...</div>
|
|
11
11
|
<div class="kpt-menu__separator" role="separator"></div>
|
|
12
|
-
<button class="kpt-menu__item" role="menuitem"
|
|
12
|
+
<button class="kpt-menu__item" role="menuitem">...</button>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
15
15
|
## Props
|
|
16
16
|
- `items`: `KptMenuItem<T>[]`
|
|
17
|
-
- `trigger`: ReactNode
|
|
18
|
-
- `onSelect(item)`
|
|
19
|
-
- `open` / `defaultOpen` / `onOpenChange`
|
|
17
|
+
- `trigger`: ReactNode - the element that opens the menu, rendered in place
|
|
18
|
+
- `onSelect(item)` - the picked item; headers, separators and disabled items never arrive here
|
|
19
|
+
- `open` / `defaultOpen` / `onOpenChange` - controlled or uncontrolled
|
|
20
20
|
- `className`, `ref` and every other `<span>` prop go to the host
|
|
21
21
|
|
|
22
22
|
## KptMenuItem
|
|
23
23
|
`label`, `value`, `icon`, `description` (a second line), `badge` + `badgeVariant`,
|
|
24
|
-
`avatar` (`{ src?, name?, icon? }`
|
|
24
|
+
`avatar` (`{ src?, name?, icon? }` - the header row of a user menu), `header` (a non-clickable
|
|
25
25
|
block instead of an item), `disabled`, `danger`, `separator`, plus `items` and `url` for the
|
|
26
26
|
menubar and megamenu that build on the same shape.
|
|
27
27
|
|
|
28
28
|
## The panel is a portal
|
|
29
|
-
It renders through the internal `KptOverlay`, so no overlay stylesheet is required
|
|
29
|
+
It renders through the internal `KptOverlay`, so no overlay stylesheet is required - unlike the
|
|
30
30
|
Angular port, which stands on CDK. Position, backdrop and Escape behave the same.
|
|
31
31
|
|
|
32
32
|
## Examples
|
|
@@ -46,11 +46,11 @@ Angular port, which stands on CDK. Position, backdrop and Escape behave the same
|
|
|
46
46
|
(the `danger` item), `--kpt-z-overlay`.
|
|
47
47
|
|
|
48
48
|
## Keyboard
|
|
49
|
-
-
|
|
49
|
+
- `ArrowDown` / `ArrowUp` on the trigger open the menu with focus on the first / last item; a click, `Enter`
|
|
50
50
|
or `Space` opens it on the first.
|
|
51
|
-
- Inside:
|
|
51
|
+
- Inside: `ArrowDown` / `ArrowUp` move between items and wrap around, `Home` / `End` jump to the ends;
|
|
52
52
|
disabled items, separators and headers are skipped.
|
|
53
|
-
- `Escape` and `Tab` close the menu, and so does picking an item
|
|
53
|
+
- `Escape` and `Tab` close the menu, and so does picking an item - focus returns to the trigger.
|
|
54
54
|
- Items carry `tabindex="-1"` (roving focus), so an open menu is one Tab stop, not one per item.
|
|
55
55
|
|
|
56
56
|
The logic lives in `menu-keys.ts`, shared with `KptSplitButton`; the other port has a twin file.
|
|
@@ -63,5 +63,5 @@ announcing them as actions.
|
|
|
63
63
|
The trigger itself gets `aria-haspopup="menu"`, a live `aria-expanded` and, while open,
|
|
64
64
|
`aria-controls` pointing at the panel. They are placed on the
|
|
65
65
|
interactive control INSIDE the slot (the projected `<button>`/`<a>`), never on the
|
|
66
|
-
`.kpt-menu__trigger` wrapper
|
|
66
|
+
`.kpt-menu__trigger` wrapper - giving that wrapper a role would create a nested control and a second
|
|
67
67
|
tab stop, and state attributes on a roleless element violate `aria-allowed-attr`.
|
package/dist/menu/menu-item.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { KptBadgeVariant } from '../badge/badge.tsx';
|
|
2
|
-
/** Awatar wiersza nagłówkowego
|
|
2
|
+
/** Awatar wiersza nagłówkowego - te same dane, które przyjmuje `KptAvatar`. */
|
|
3
3
|
export interface KptMenuItemAvatar {
|
|
4
4
|
src?: string;
|
|
5
5
|
name?: string;
|
|
6
6
|
icon?: string;
|
|
7
7
|
}
|
|
8
|
-
/** Pozycja menu
|
|
8
|
+
/** Pozycja menu - wspólny kształt dla `KptMenu` i `KptContextMenu`. */
|
|
9
9
|
export interface KptMenuItem<T = unknown> {
|
|
10
10
|
label?: string;
|
|
11
11
|
value?: T;
|
|
@@ -14,9 +14,9 @@ export interface KptMenuItem<T = unknown> {
|
|
|
14
14
|
description?: string;
|
|
15
15
|
/** Odznaka po prawej stronie pozycji (licznik lub krótka etykieta). */
|
|
16
16
|
badge?: string | number;
|
|
17
|
-
/** Wariant odznaki
|
|
17
|
+
/** Wariant odznaki - domyślnie `primary`. */
|
|
18
18
|
badgeVariant?: KptBadgeVariant;
|
|
19
|
-
/** Awatar po lewej
|
|
19
|
+
/** Awatar po lewej - typowo w wierszu nagłówka menu użytkownika. */
|
|
20
20
|
avatar?: KptMenuItemAvatar;
|
|
21
21
|
/**
|
|
22
22
|
* Wiersz nagłówkowy: nieklikalny blok tekstu zamiast pozycji menu. Mieści dane zalogowanego
|
package/dist/menu/menu-keys.d.ts
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
export declare function nextMenuIndex(count: number, current: number, key: string): number | null;
|
|
7
7
|
/** Aktywne pozycje panelu w kolejności DOM. */
|
|
8
8
|
export declare function menuItems(panel: HTMLElement): HTMLElement[];
|
|
9
|
-
/** Skupia pierwszą albo ostatnią aktywną pozycję
|
|
9
|
+
/** Skupia pierwszą albo ostatnią aktywną pozycję - po otwarciu menu z klawiatury lub myszy. */
|
|
10
10
|
export declare function focusMenuEdge(panel: HTMLElement, edge: 'first' | 'last'): void;
|
|
11
11
|
/**
|
|
12
12
|
* Obsługa klawisza w otwartym panelu. Zwraca `'close'`, gdy menu ma się zamknąć z powrotem
|
|
13
|
-
* fokusu na przycisk (Escape, Tab), `true`, gdy klawisz przesunął fokus, `false`
|
|
13
|
+
* fokusu na przycisk (Escape, Tab), `true`, gdy klawisz przesunął fokus, `false` - inny klawisz.
|
|
14
14
|
*/
|
|
15
15
|
export declare function handleMenuKeydown(panel: HTMLElement, event: KeyboardEvent): 'close' | boolean;
|
package/dist/menu/menu-keys.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Klawiatura panelu menu (wzorzec WAI-ARIA
|
|
3
|
-
* i `kpt-split-button`
|
|
4
|
-
* Port Angulara ma bliźniaczy plik `lib/menu/menu-keys.ts`
|
|
2
|
+
* Klawiatura panelu menu (wzorzec WAI-ARIA "menu button"), wspólna dla `kpt-menu`
|
|
3
|
+
* i `kpt-split-button` - oba mają ten sam panel z pozycjami `role="menuitem"`.
|
|
4
|
+
* Port Angulara ma bliźniaczy plik `lib/menu/menu-keys.ts` - zmiana zachowania w obu.
|
|
5
5
|
*/
|
|
6
6
|
/** Klawisze przesuwające fokus po pozycjach. */
|
|
7
7
|
const NAV_KEYS = new Set(['ArrowDown', 'ArrowUp', 'Home', 'End']);
|
|
@@ -28,14 +28,14 @@ export function nextMenuIndex(count, current, key) {
|
|
|
28
28
|
export function menuItems(panel) {
|
|
29
29
|
return [...panel.querySelectorAll('[role="menuitem"]:not(:disabled)')];
|
|
30
30
|
}
|
|
31
|
-
/** Skupia pierwszą albo ostatnią aktywną pozycję
|
|
31
|
+
/** Skupia pierwszą albo ostatnią aktywną pozycję - po otwarciu menu z klawiatury lub myszy. */
|
|
32
32
|
export function focusMenuEdge(panel, edge) {
|
|
33
33
|
const items = menuItems(panel);
|
|
34
34
|
(edge === 'first' ? items[0] : items[items.length - 1])?.focus();
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* Obsługa klawisza w otwartym panelu. Zwraca `'close'`, gdy menu ma się zamknąć z powrotem
|
|
38
|
-
* fokusu na przycisk (Escape, Tab), `true`, gdy klawisz przesunął fokus, `false`
|
|
38
|
+
* fokusu na przycisk (Escape, Tab), `true`, gdy klawisz przesunął fokus, `false` - inny klawisz.
|
|
39
39
|
*/
|
|
40
40
|
export function handleMenuKeydown(panel, event) {
|
|
41
41
|
if (event.key === 'Escape' || event.key === 'Tab') {
|
package/dist/menu/menu.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type ComponentPropsWithRef, type ReactNode } from 'react';
|
|
|
2
2
|
import type { KptMenuItem } from './menu-item.ts';
|
|
3
3
|
export interface KptMenuProps<T> extends Omit<ComponentPropsWithRef<'span'>, 'onSelect'> {
|
|
4
4
|
items?: readonly KptMenuItem<T>[];
|
|
5
|
-
/** Element otwierający menu
|
|
5
|
+
/** Element otwierający menu - renderowany w miejscu komponentu. */
|
|
6
6
|
trigger: ReactNode;
|
|
7
7
|
/** Wybrana pozycja; pozycje `header`, `separator` i wyłączone nigdy tu nie trafiają. */
|
|
8
8
|
onSelect?: (item: KptMenuItem<T>) => void;
|
|
@@ -13,7 +13,7 @@ export interface KptMenuProps<T> extends Omit<ComponentPropsWithRef<'span'>, 'on
|
|
|
13
13
|
/**
|
|
14
14
|
* Menu rozwijane (dropdown). Pozycje przez `items`, wyzwalacz przez prop `trigger`.
|
|
15
15
|
*
|
|
16
|
-
* Panel renderuje się w portalu (`KptOverlay`), więc nie potrzeba żadnych stylów overlay
|
|
16
|
+
* Panel renderuje się w portalu (`KptOverlay`), więc nie potrzeba żadnych stylów overlay -
|
|
17
17
|
* w odróżnieniu od portu Angulara, który stoi na CDK.
|
|
18
18
|
*
|
|
19
19
|
* @example
|
package/dist/menu/menu.js
CHANGED
|
@@ -10,7 +10,7 @@ import { MenuRows } from "./menu-rows.js";
|
|
|
10
10
|
/**
|
|
11
11
|
* Menu rozwijane (dropdown). Pozycje przez `items`, wyzwalacz przez prop `trigger`.
|
|
12
12
|
*
|
|
13
|
-
* Panel renderuje się w portalu (`KptOverlay`), więc nie potrzeba żadnych stylów overlay
|
|
13
|
+
* Panel renderuje się w portalu (`KptOverlay`), więc nie potrzeba żadnych stylów overlay -
|
|
14
14
|
* w odróżnieniu od portu Angulara, który stoi na CDK.
|
|
15
15
|
*
|
|
16
16
|
* @example
|
|
@@ -18,14 +18,14 @@ import { MenuRows } from "./menu-rows.js";
|
|
|
18
18
|
*/
|
|
19
19
|
export function KptMenu({ items = [], trigger, onSelect, open, defaultOpen = false, onOpenChange, className, ...rest }) {
|
|
20
20
|
const triggerRef = useRef(null);
|
|
21
|
-
/** Kotwica panelu
|
|
21
|
+
/** Kotwica panelu - w stanie, bo czyta ją render; ref zostaje dla handlerów. */
|
|
22
22
|
const [anchor, setAnchor] = useState(null);
|
|
23
23
|
const setTrigger = useCallback((element) => {
|
|
24
24
|
triggerRef.current = element;
|
|
25
25
|
setAnchor(element);
|
|
26
26
|
}, []);
|
|
27
27
|
const panelRef = useRef(null);
|
|
28
|
-
/** Którą pozycję skupić po otwarciu
|
|
28
|
+
/** Którą pozycję skupić po otwarciu - strzałka w górę na wyzwalaczu otwiera "od końca". */
|
|
29
29
|
const focusEdge = useRef('first');
|
|
30
30
|
const panelId = useKptId(undefined, 'kpt-menu');
|
|
31
31
|
const [isOpen, setOpen] = useControllableState({
|
|
@@ -36,7 +36,7 @@ export function KptMenu({ items = [], trigger, onSelect, open, defaultOpen = fal
|
|
|
36
36
|
const close = useCallback(() => setOpen(false), [setOpen]);
|
|
37
37
|
// ARIA idzie na kontrolkę wewnątrz slotu, nie na `.kpt-menu__trigger`. Trigger to zwykły
|
|
38
38
|
// `<span>` opakowujący dowolny węzeł z propa `trigger`: nadanie mu `role="button"` zrobiłoby
|
|
39
|
-
// zagnieżdżoną kontrolkę i drugi tab stop. `cloneElement` też odpada
|
|
39
|
+
// zagnieżdżoną kontrolkę i drugi tab stop. `cloneElement` też odpada - `trigger` bywa
|
|
40
40
|
// komponentem, który nie przekazuje nieznanych propsów dalej na DOM.
|
|
41
41
|
useEffect(() => {
|
|
42
42
|
const control = findControl();
|
|
@@ -60,11 +60,11 @@ export function KptMenu({ items = [], trigger, onSelect, open, defaultOpen = fal
|
|
|
60
60
|
});
|
|
61
61
|
return () => cancelAnimationFrame(frame);
|
|
62
62
|
}, [isOpen]);
|
|
63
|
-
/** Prawdziwa kontrolka w slocie
|
|
63
|
+
/** Prawdziwa kontrolka w slocie - tam idą ARIA i powrót fokusu. */
|
|
64
64
|
function findControl() {
|
|
65
65
|
return triggerRef.current?.querySelector('button, a, [role="button"]') ?? null;
|
|
66
66
|
}
|
|
67
|
-
/** Fokus wraca na kontrolkę
|
|
67
|
+
/** Fokus wraca na kontrolkę - inaczej po zniknięciu panelu spadłby na `<body>`. */
|
|
68
68
|
const closeAndRestoreFocus = () => {
|
|
69
69
|
close();
|
|
70
70
|
findControl()?.focus();
|
package/dist/menubar/llms.txt
CHANGED
|
@@ -8,21 +8,21 @@ Import: `import { KptMenubar } from '@konce-pt/react';`
|
|
|
8
8
|
<div class="kpt-menubar" role="menubar" aria-orientation="horizontal" aria-label="Editor menu">
|
|
9
9
|
<div class="kpt-menubar__group" role="none">
|
|
10
10
|
<button class="kpt-menubar__top is-open" role="menuitem" tabindex="0"
|
|
11
|
-
aria-haspopup="menu" aria-expanded="true" aria-controls="kpt-menubar-r1-menu-0">File
|
|
11
|
+
aria-haspopup="menu" aria-expanded="true" aria-controls="kpt-menubar-r1-menu-0">File ...caret...</button>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
14
14
|
</div>
|
|
15
15
|
<!-- while open, in a portal: -->
|
|
16
|
-
<div class="kpt-menubar__dropdown" role="menu" id="kpt-menubar-r1-menu-0" aria-label="File"
|
|
16
|
+
<div class="kpt-menubar__dropdown" role="menu" id="kpt-menubar-r1-menu-0" aria-label="File">...items and separators...</div>
|
|
17
17
|
|
|
18
18
|
## Props
|
|
19
|
-
- `items`: `KptMenuItem<T>[]`
|
|
20
|
-
- `onSelect(item)`
|
|
21
|
-
- `ariaLabel`: string
|
|
19
|
+
- `items`: `KptMenuItem<T>[]` - a top item's `items` become its dropdown
|
|
20
|
+
- `onSelect(item)` - an action item, or a pick from a dropdown
|
|
21
|
+
- `ariaLabel`: string - the bar's name for screen readers, e.g. "Editor menu"
|
|
22
22
|
- `className`, `ref` and every other `<div>` prop go to the host
|
|
23
23
|
|
|
24
24
|
## The dropdown is a portal
|
|
25
|
-
It renders outside the bar, so a parent with `overflow: hidden` cannot clip it
|
|
25
|
+
It renders outside the bar, so a parent with `overflow: hidden` cannot clip it - the same benefit
|
|
26
26
|
the Angular port gets from CDK Overlay, without CDK. Each dropdown is anchored to its own top
|
|
27
27
|
button, so it opens directly under the label it belongs to.
|
|
28
28
|
|
|
@@ -40,7 +40,7 @@ bar can mix menus and plain actions with no extra flag.
|
|
|
40
40
|
|
|
41
41
|
## Links (`url`)
|
|
42
42
|
An entry with `url` and no children (and not disabled) renders as a real `<a href>` with the same
|
|
43
|
-
look, so the browser handles navigation
|
|
43
|
+
look, so the browser handles navigation - opening in a new tab, the status-bar preview. `onSelect`
|
|
44
44
|
still fires before the browser follows the link.
|
|
45
45
|
|
|
46
46
|
## Tokens
|
|
@@ -51,7 +51,7 @@ still fires before the browser follows the link.
|
|
|
51
51
|
The bar is `role="menubar"` (`aria-orientation="horizontal"`, named by `ariaLabel`), top items and
|
|
52
52
|
dropdown rows are `role="menuitem"`, separators carry `role="separator"`. Top items with a dropdown
|
|
53
53
|
carry `aria-haspopup="menu"`, `aria-expanded` and, while open, `aria-controls`. The bar is a plain
|
|
54
|
-
`<div>`, not `<nav>`
|
|
54
|
+
`<div>`, not `<nav>` - wrap it in your own `<nav aria-label="...">` when it is the site navigation.
|
|
55
55
|
|
|
56
56
|
## Keyboard
|
|
57
57
|
The bar is a single `Tab` stop (roving `tabindex`), following the WAI-ARIA menubar pattern.
|
|
@@ -63,11 +63,11 @@ The bar is a single `Tab` stop (roving `tabindex`), following the WAI-ARIA menub
|
|
|
63
63
|
|
|
64
64
|
## Router
|
|
65
65
|
Links are plain `<a href>`, so without a router a click reloads the page. `onNavigate` fires on a plain
|
|
66
|
-
click (left button, no Ctrl
|
|
66
|
+
click (left button, no Ctrl/Cmd/Shift, no `target="_blank"`) with `{ item, url, event }`: call
|
|
67
67
|
`event.preventDefault()` and navigate with your router. Modified clicks stay native (a new tab, a new
|
|
68
68
|
window). The library depends on no router.
|
|
69
69
|
|
|
70
70
|
<KptMenubar items={items} onNavigate={({ event, url }) => { event.preventDefault(); navigate(url); }} />
|
|
71
71
|
|
|
72
72
|
## When to use it
|
|
73
|
-
The `menubar`/`menu` roles switch a screen reader into application mode: page navigation by headings and links stops, and arrow keys are expected. That fits an application menu (File, Edit, View) or a large product menu. For plain site navigation (a few links in a header) the WAI-ARIA APG recommends the disclosure pattern instead
|
|
73
|
+
The `menubar`/`menu` roles switch a screen reader into application mode: page navigation by headings and links stops, and arrow keys are expected. That fits an application menu (File, Edit, View) or a large product menu. For plain site navigation (a few links in a header) the WAI-ARIA APG recommends the disclosure pattern instead - a `<nav>` with buttons carrying `aria-expanded` and ordinary link lists - which you can build from `kpt-button` and lists. The menu does not render a third level: nested `items` of a submenu item are ignored.
|
|
@@ -6,21 +6,21 @@ export interface KptMenubarProps<T> extends Omit<ComponentPropsWithRef<'div'>, '
|
|
|
6
6
|
onSelect?: (item: KptMenuItem<T>) => void;
|
|
7
7
|
/**
|
|
8
8
|
* Zwykły klik w pozycję z `url`. Aplikacja z routerem woła `event.preventDefault()` i nawiguje
|
|
9
|
-
* sama
|
|
9
|
+
* sama - bez tego `<a href>` przeładowuje stronę.
|
|
10
10
|
*/
|
|
11
11
|
onNavigate?: (event: KptNavigateEvent<KptMenuItem<T>>) => void;
|
|
12
|
-
/** Nazwa belki dla czytników ekranu, np.
|
|
12
|
+
/** Nazwa belki dla czytników ekranu, np. "Menu edytora". */
|
|
13
13
|
ariaLabel?: string;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* Pozioma belka menu z rozwijanymi pod-menu. Pozycja bez `items` działa jak akcja lub link.
|
|
17
17
|
*
|
|
18
|
-
* Pod-menu renderuje się w portalu, więc rodzic z `overflow: hidden` go nie przycina
|
|
18
|
+
* Pod-menu renderuje się w portalu, więc rodzic z `overflow: hidden` go nie przycina - to ta sama
|
|
19
19
|
* korzyść, dla której port Angulara sięga po CDK Overlay, tylko bez CDK.
|
|
20
20
|
*
|
|
21
|
-
* Klawiatura według wzorca WAI-ARIA
|
|
21
|
+
* Klawiatura według wzorca WAI-ARIA "menubar": belka to jeden przystanek Tab, strzałki w lewo/prawo
|
|
22
22
|
* i `Home`/`End` chodzą po pozycjach górnych, strzałka w dół (albo `Enter`/spacja) otwiera
|
|
23
|
-
* pod-menu z fokusem na pierwszej pozycji, w górę
|
|
23
|
+
* pod-menu z fokusem na pierwszej pozycji, w górę - na ostatniej. W otwartym pod-menu strzałki
|
|
24
24
|
* w lewo/prawo przechodzą do sąsiedniego, a `Escape` zamyka je i oddaje fokus belce.
|
|
25
25
|
*
|
|
26
26
|
* @example
|
package/dist/menubar/menubar.js
CHANGED
|
@@ -11,12 +11,12 @@ import { focusMenuEdge, handleMenuKeydown } from "../menu/menu-keys.js";
|
|
|
11
11
|
/**
|
|
12
12
|
* Pozioma belka menu z rozwijanymi pod-menu. Pozycja bez `items` działa jak akcja lub link.
|
|
13
13
|
*
|
|
14
|
-
* Pod-menu renderuje się w portalu, więc rodzic z `overflow: hidden` go nie przycina
|
|
14
|
+
* Pod-menu renderuje się w portalu, więc rodzic z `overflow: hidden` go nie przycina - to ta sama
|
|
15
15
|
* korzyść, dla której port Angulara sięga po CDK Overlay, tylko bez CDK.
|
|
16
16
|
*
|
|
17
|
-
* Klawiatura według wzorca WAI-ARIA
|
|
17
|
+
* Klawiatura według wzorca WAI-ARIA "menubar": belka to jeden przystanek Tab, strzałki w lewo/prawo
|
|
18
18
|
* i `Home`/`End` chodzą po pozycjach górnych, strzałka w dół (albo `Enter`/spacja) otwiera
|
|
19
|
-
* pod-menu z fokusem na pierwszej pozycji, w górę
|
|
19
|
+
* pod-menu z fokusem na pierwszej pozycji, w górę - na ostatniej. W otwartym pod-menu strzałki
|
|
20
20
|
* w lewo/prawo przechodzą do sąsiedniego, a `Escape` zamyka je i oddaje fokus belce.
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
@@ -24,18 +24,18 @@ import { focusMenuEdge, handleMenuKeydown } from "../menu/menu-keys.js";
|
|
|
24
24
|
*/
|
|
25
25
|
export function KptMenubar({ items = [], onSelect, onNavigate, ariaLabel, className, ...rest }) {
|
|
26
26
|
const [openIndex, setOpenIndex] = useState(null);
|
|
27
|
-
/** Przycisk otwartego pod-menu
|
|
27
|
+
/** Przycisk otwartego pod-menu - w stanie, bo render podaje go nakładce jako kotwicę. */
|
|
28
28
|
const [anchorEl, setAnchorEl] = useState(null);
|
|
29
|
-
// Ostatnio skupiona pozycja górna
|
|
29
|
+
// Ostatnio skupiona pozycja górna - ona jest przystankiem Tab belki.
|
|
30
30
|
const [focusIndex, setFocusIndex] = useState(0);
|
|
31
31
|
const buttonsRef = useRef([]);
|
|
32
32
|
const panelRef = useRef(null);
|
|
33
|
-
// Którą pozycję pod-menu skupić po otwarciu
|
|
33
|
+
// Którą pozycję pod-menu skupić po otwarciu - strzałka w górę otwiera "od końca".
|
|
34
34
|
const focusEdge = useRef('first');
|
|
35
35
|
const baseId = useKptId(undefined, 'kpt-menubar');
|
|
36
36
|
const panelId = (index) => `${baseId}-menu-${index}`;
|
|
37
37
|
const disabled = items.map((item) => !!item.disabled);
|
|
38
|
-
// Pozycja z `url` (bez pod-menu, niewyłączona) to `<a href>`
|
|
38
|
+
// Pozycja z `url` (bez pod-menu, niewyłączona) to `<a href>` - nawigację robi przeglądarka,
|
|
39
39
|
// więc działa nowa karta i podgląd adresu. `onSelect` i tak jest wołane.
|
|
40
40
|
const isLink = (item) => !!item.url && !item.items?.length && !item.disabled;
|
|
41
41
|
const tabStop = rovingStop(disabled, focusIndex);
|
|
@@ -85,7 +85,7 @@ export function KptMenubar({ items = [], onSelect, onNavigate, ariaLabel, classN
|
|
|
85
85
|
return;
|
|
86
86
|
onSelect?.(item);
|
|
87
87
|
closeAll();
|
|
88
|
-
// Fokus wraca na pozycję górną
|
|
88
|
+
// Fokus wraca na pozycję górną - inaczej po zniknięciu pod-menu spadłby na `<body>`.
|
|
89
89
|
focusTop(index);
|
|
90
90
|
};
|
|
91
91
|
const onTopKeyDown = (event, index) => {
|
|
@@ -100,7 +100,7 @@ export function KptMenubar({ items = [], onSelect, onNavigate, ariaLabel, classN
|
|
|
100
100
|
if (next === null)
|
|
101
101
|
return;
|
|
102
102
|
event.preventDefault();
|
|
103
|
-
// Przy otwartym pod-menu przejście w bok otwiera pod-menu sąsiada
|
|
103
|
+
// Przy otwartym pod-menu przejście w bok otwiera pod-menu sąsiada - jak w menu aplikacji.
|
|
104
104
|
if (openIndex === null)
|
|
105
105
|
focusTop(next);
|
|
106
106
|
else
|
|
@@ -120,7 +120,7 @@ export function KptMenubar({ items = [], onSelect, onNavigate, ariaLabel, classN
|
|
|
120
120
|
focusTop(index);
|
|
121
121
|
}
|
|
122
122
|
};
|
|
123
|
-
/** Zwykły klik w odnośnik
|
|
123
|
+
/** Zwykły klik w odnośnik -> `onNavigate` (Ctrl/Cmd/Shift, środkowy przycisk i `_blank` zostają natywne). */
|
|
124
124
|
const linkClick = (event, item) => {
|
|
125
125
|
if (item.url && onNavigate && kptIsPlainClick(event, event.currentTarget.target)) {
|
|
126
126
|
onNavigate({ item, url: item.url, event: event.nativeEvent });
|
|
@@ -7,35 +7,35 @@ Import: `import { KptMeterGroup } from '@konce-pt/react';`
|
|
|
7
7
|
<div class="kpt-meter-group-host">
|
|
8
8
|
<div class="kpt-meter-group">
|
|
9
9
|
<div class="kpt-meter-group__track" role="meter" aria-label="Usage" aria-valuemin="0"
|
|
10
|
-
aria-valuenow="100" aria-valuemax="100" aria-valuetext="Documents 45,
|
|
11
|
-
<span class="kpt-meter-group__segment" style="width:45%" title="Documents"></span
|
|
10
|
+
aria-valuenow="100" aria-valuemax="100" aria-valuetext="Documents 45, ...">
|
|
11
|
+
<span class="kpt-meter-group__segment" style="width:45%" title="Documents"></span>...
|
|
12
12
|
</div>
|
|
13
13
|
<ul class="kpt-meter-group__legend">
|
|
14
14
|
<li class="kpt-meter-group__legend-item">
|
|
15
15
|
<span class="kpt-meter-group__dot"></span><span>Documents</span>
|
|
16
16
|
<span class="kpt-meter-group__val">45%</span>
|
|
17
|
-
</li
|
|
17
|
+
</li>...
|
|
18
18
|
</ul>
|
|
19
19
|
</div>
|
|
20
20
|
</div>
|
|
21
21
|
|
|
22
22
|
## Props
|
|
23
|
-
- `values`: `KptMeterItem[]`
|
|
24
|
-
- `max`: number
|
|
23
|
+
- `values`: `KptMeterItem[]` - `{ label, value, color? }`
|
|
24
|
+
- `max`: number - the reference total; without it the values' sum is 100%
|
|
25
25
|
- `showLegend`: boolean (default true)
|
|
26
|
-
- `label`: string
|
|
27
|
-
- `legendValue`: 'percent' | 'value' (default 'percent')
|
|
28
|
-
- `unit`: string
|
|
26
|
+
- `label`: string - the meter's name; empty = `meterGroup.label`
|
|
27
|
+
- `legendValue`: 'percent' | 'value' (default 'percent') - what the legend shows next to each label
|
|
28
|
+
- `unit`: string - appended to the values in the legend and in `aria-valuetext` (e.g. 'GB')
|
|
29
29
|
- `className`, `ref` and every other `<div>` prop go to the host
|
|
30
30
|
|
|
31
31
|
## Percentages come from the sum, not from 100
|
|
32
32
|
Without `max` the reference is the sum of the values, so `[45, 25, 15, 15]` and `[9, 5, 3, 3]`
|
|
33
|
-
draw the same picture. Pass `max` when the segments are meant to leave a gap
|
|
33
|
+
draw the same picture. Pass `max` when the segments are meant to leave a gap - a quota that is
|
|
34
34
|
not full yet. All-zero values fall back to a divisor of 1 instead of producing `NaN%`.
|
|
35
35
|
|
|
36
36
|
## Colours
|
|
37
37
|
`color` per item, otherwise the next one from the semantic palette
|
|
38
|
-
(`primary
|
|
38
|
+
(`primary -> info -> success -> warning -> danger`, cycled), so a group of any length stays readable
|
|
39
39
|
without picking colours by hand.
|
|
40
40
|
|
|
41
41
|
## Examples
|
|
@@ -48,7 +48,7 @@ The palette `--kpt-color-{primary,info,success,warning,danger}`, the track
|
|
|
48
48
|
|
|
49
49
|
## Accessibility
|
|
50
50
|
The track is `role="meter"` named by `label` (or `meterGroup.label`), with `aria-valuemin="0"`,
|
|
51
|
-
`aria-valuenow` set to the sum and `aria-valuemax` set to the real total
|
|
52
|
-
it. `aria-valuetext` spells out the split (
|
|
51
|
+
`aria-valuenow` set to the sum and `aria-valuemax` set to the real total - `max`, or the sum without
|
|
52
|
+
it. `aria-valuetext` spells out the split ("Photos 42 GB, Videos 28 GB, ..."), so the segments reach
|
|
53
53
|
the screen reader even with the legend hidden. Keep the legend visible anyway: it is the text
|
|
54
54
|
alternative to the colours.
|
|
@@ -11,11 +11,11 @@ export interface KptMeterGroupProps extends ComponentPropsWithRef<'div'>, KptI18
|
|
|
11
11
|
/** Suma odniesienia; domyślnie suma wartości, czyli segmenty wypełniają całość. */
|
|
12
12
|
max?: number;
|
|
13
13
|
showLegend?: boolean;
|
|
14
|
-
/** Nazwa paska dla czytników ekranu, np.
|
|
14
|
+
/** Nazwa paska dla czytników ekranu, np. "Miejsce na dysku"; domyślnie `meterGroup.label`. */
|
|
15
15
|
label?: string;
|
|
16
16
|
/** Co pokazuje legenda przy etykiecie: udział procentowy albo samą wartość (z `unit`). */
|
|
17
17
|
legendValue?: 'percent' | 'value';
|
|
18
|
-
/** Jednostka dopisywana do wartości
|
|
18
|
+
/** Jednostka dopisywana do wartości - w legendzie (`legendValue="value"`) i w `aria-valuetext`. */
|
|
19
19
|
unit?: string;
|
|
20
20
|
}
|
|
21
21
|
/**
|