@konce-pt/react 0.11.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -64
- package/dist/accordion/accordion.d.ts +14 -6
- package/dist/accordion/accordion.js +25 -17
- package/dist/accordion/llms.txt +22 -10
- package/dist/alert/alert.d.ts +2 -2
- package/dist/alert/alert.js +3 -2
- package/dist/alert/llms.txt +10 -9
- package/dist/app-shell/app-shell.d.ts +14 -14
- package/dist/app-shell/app-shell.js +22 -15
- package/dist/app-shell/llms.txt +16 -15
- package/dist/auth/auth-types.d.ts +6 -6
- package/dist/auth/auth.d.ts +2 -2
- package/dist/auth/auth.js +24 -15
- package/dist/auth/llms.txt +12 -11
- package/dist/autocomplete/autocomplete.d.ts +19 -6
- package/dist/autocomplete/autocomplete.js +32 -11
- package/dist/autocomplete/llms.txt +19 -5
- package/dist/avatar/avatar.d.ts +6 -6
- package/dist/avatar/avatar.js +6 -5
- package/dist/avatar/llms.txt +10 -10
- package/dist/avatar-group/avatar-group.d.ts +4 -4
- package/dist/avatar-group/avatar-group.js +4 -3
- package/dist/avatar-group/llms.txt +8 -8
- package/dist/backdrop/backdrop.d.ts +7 -26
- package/dist/backdrop/backdrop.js +32 -27
- package/dist/backdrop/llms.txt +27 -27
- package/dist/badge/badge.d.ts +3 -3
- package/dist/badge/badge.js +1 -1
- package/dist/badge/llms.txt +11 -11
- package/dist/bottom-sheet/bottom-sheet.d.ts +8 -3
- package/dist/bottom-sheet/bottom-sheet.js +5 -4
- package/dist/bottom-sheet/llms.txt +11 -8
- package/dist/breadcrumb/breadcrumb.d.ts +8 -2
- package/dist/breadcrumb/breadcrumb.js +11 -3
- package/dist/breadcrumb/llms.txt +10 -2
- package/dist/button/button.d.ts +3 -3
- package/dist/button/button.js +10 -9
- package/dist/button/llms.txt +27 -19
- package/dist/button-group/button-group.d.ts +18 -5
- package/dist/button-group/button-group.js +54 -6
- package/dist/button-group/llms.txt +27 -18
- package/dist/card/card.d.ts +8 -8
- package/dist/card/card.js +10 -9
- package/dist/card/llms.txt +20 -20
- package/dist/carousel/carousel.d.ts +6 -6
- package/dist/carousel/carousel.js +8 -5
- package/dist/carousel/llms.txt +10 -10
- package/dist/charts/chart-legend.d.ts +3 -3
- package/dist/charts/chart-legend.js +2 -1
- package/dist/charts/chart-tooltip.d.ts +3 -3
- package/dist/charts/chart-tooltip.js +1 -1
- package/dist/charts/chart.d.ts +4 -3
- package/dist/charts/chart.js +18 -10
- package/dist/charts/llms.txt +10 -7
- package/dist/charts-entry/public-api.js +2 -2
- package/dist/chat/chat.d.ts +17 -10
- package/dist/chat/chat.js +77 -23
- package/dist/chat/llms.txt +39 -15
- package/dist/chat-composer/chat-composer.d.ts +20 -7
- package/dist/chat-composer/chat-composer.js +29 -7
- package/dist/chat-composer/llms.txt +20 -11
- package/dist/chat-dock/chat-dock.d.ts +11 -4
- package/dist/chat-dock/chat-dock.js +10 -6
- package/dist/chat-dock/llms.txt +15 -14
- package/dist/chat-entry/public-api.js +1 -1
- package/dist/chat-message/chat-message.d.ts +12 -5
- package/dist/chat-message/chat-message.js +19 -8
- package/dist/chat-message/llms.txt +16 -15
- package/dist/chat-typing/chat-typing.d.ts +2 -2
- package/dist/chat-typing/chat-typing.js +4 -3
- package/dist/chat-typing/llms.txt +6 -6
- package/dist/checkbox/checkbox.d.ts +13 -6
- package/dist/checkbox/checkbox.js +31 -5
- package/dist/checkbox/llms.txt +26 -11
- package/dist/chip/chip.d.ts +4 -4
- package/dist/chip/chip.js +3 -2
- package/dist/chip/llms.txt +11 -11
- package/dist/chips-input/chips-input.d.ts +6 -4
- package/dist/chips-input/chips-input.js +47 -12
- package/dist/chips-input/llms.txt +18 -8
- package/dist/clock/clock.d.ts +11 -6
- package/dist/clock/clock.js +38 -8
- package/dist/clock/llms.txt +12 -8
- package/dist/color-picker/color-picker.d.ts +9 -5
- package/dist/color-picker/color-picker.js +37 -18
- package/dist/color-picker/llms.txt +8 -5
- package/dist/confirm/confirm-container.d.ts +3 -3
- package/dist/confirm/confirm-container.js +6 -5
- package/dist/confirm/confirm-store.d.ts +4 -4
- package/dist/confirm/confirm-store.js +11 -5
- package/dist/confirm/llms.txt +8 -7
- package/dist/context-menu/context-menu.d.ts +1 -1
- package/dist/context-menu/context-menu.js +37 -14
- package/dist/context-menu/llms.txt +10 -7
- package/dist/data-table/data-table-types.d.ts +5 -5
- package/dist/data-table/data-table.d.ts +37 -5
- package/dist/data-table/data-table.js +426 -119
- package/dist/data-table/export-csv.d.ts +3 -3
- package/dist/data-table/export-csv.js +8 -10
- package/dist/data-table/llms.txt +127 -79
- package/dist/data-view/data-view.d.ts +13 -5
- package/dist/data-view/data-view.js +68 -6
- package/dist/data-view/llms.txt +29 -10
- package/dist/date-range/date-range.d.ts +20 -8
- package/dist/date-range/date-range.js +86 -63
- package/dist/date-range/llms.txt +32 -18
- package/dist/datepicker/datepicker.d.ts +22 -8
- package/dist/datepicker/datepicker.js +103 -71
- package/dist/datepicker/llms.txt +36 -22
- package/dist/dialog/dialog.d.ts +4 -4
- package/dist/dialog/dialog.js +32 -11
- package/dist/dialog/llms.txt +13 -10
- package/dist/divider/divider.d.ts +7 -1
- package/dist/divider/divider.js +3 -2
- package/dist/divider/llms.txt +4 -3
- package/dist/drawer/drawer.d.ts +9 -4
- package/dist/drawer/drawer.js +5 -4
- package/dist/drawer/llms.txt +13 -10
- package/dist/empty/empty.d.ts +2 -2
- package/dist/empty/empty.js +1 -1
- package/dist/empty/llms.txt +9 -9
- package/dist/fab/fab.d.ts +1 -1
- package/dist/fab/fab.js +1 -1
- package/dist/fab/llms.txt +10 -6
- package/dist/fieldset/fieldset.d.ts +18 -4
- package/dist/fieldset/fieldset.js +12 -6
- package/dist/fieldset/llms.txt +26 -9
- package/dist/file-upload/file-upload.d.ts +8 -2
- package/dist/file-upload/file-upload.js +22 -11
- package/dist/file-upload/llms.txt +12 -9
- package/dist/form-field/form-field-context.d.ts +4 -4
- package/dist/form-field/form-field.d.ts +12 -4
- package/dist/form-field/form-field.js +27 -6
- package/dist/form-field/llms.txt +25 -11
- package/dist/galleria/galleria.d.ts +3 -3
- package/dist/galleria/galleria.js +9 -6
- package/dist/galleria/llms.txt +7 -7
- package/dist/grid/col.d.ts +4 -4
- package/dist/grid/col.js +2 -2
- package/dist/grid/flex.d.ts +3 -3
- package/dist/grid/flex.js +1 -1
- package/dist/grid/grid.d.ts +7 -7
- package/dist/grid/grid.js +3 -3
- package/dist/grid/layout.d.ts +2 -2
- package/dist/grid/layout.js +2 -2
- package/dist/grid/llms.txt +15 -15
- package/dist/grid-entry/public-api.js +1 -1
- package/dist/i18n/i18n-context.d.ts +6 -6
- package/dist/i18n/i18n-context.js +27 -5
- package/dist/icon/icon-registry.d.ts +3 -3
- package/dist/icon/icon-registry.js +3 -3
- package/dist/icon/icon.d.ts +4 -4
- package/dist/icon/icon.js +10 -7
- package/dist/icon/llms.txt +13 -13
- package/dist/icon-button/icon-button.d.ts +2 -2
- package/dist/icon-button/icon-button.js +1 -1
- package/dist/icon-button/llms.txt +9 -5
- package/dist/icons-entry/public-api.d.ts +2 -2
- package/dist/icons-entry/public-api.js +3 -3
- package/dist/image/image.js +5 -5
- package/dist/image/llms.txt +13 -13
- package/dist/input/input.d.ts +18 -5
- package/dist/input/input.js +22 -6
- package/dist/input/llms.txt +25 -11
- package/dist/input-mask/input-mask.d.ts +7 -2
- package/dist/input-mask/input-mask.js +17 -43
- package/dist/input-mask/llms.txt +8 -5
- package/dist/input-number/input-number.d.ts +11 -9
- package/dist/input-number/input-number.js +25 -21
- package/dist/input-number/llms.txt +17 -14
- package/dist/input-otp/input-otp.d.ts +18 -5
- package/dist/input-otp/input-otp.js +48 -24
- package/dist/input-otp/llms.txt +18 -7
- package/dist/internal/calendar-focus.d.ts +1 -1
- package/dist/internal/calendar-focus.js +3 -3
- package/dist/internal/cn.d.ts +1 -1
- package/dist/internal/mask.d.ts +14 -0
- package/dist/internal/mask.js +62 -0
- package/dist/internal/number-group.d.ts +22 -0
- package/dist/internal/number-group.js +53 -0
- package/dist/internal/option-key.d.ts +6 -0
- package/dist/internal/option-key.js +8 -0
- package/dist/internal/option-nav.d.ts +4 -4
- package/dist/internal/option-nav.js +5 -5
- package/dist/internal/overlay-container.js +1 -1
- package/dist/internal/overlay.d.ts +3 -3
- package/dist/internal/overlay.js +40 -10
- package/dist/internal/password-strength.d.ts +6 -0
- package/dist/internal/password-strength.js +74 -0
- package/dist/internal/roving.d.ts +2 -2
- package/dist/internal/roving.js +3 -3
- package/dist/internal/scroll-lock.d.ts +6 -0
- package/dist/internal/scroll-lock.js +35 -0
- package/dist/internal/slot-children.d.ts +13 -0
- package/dist/internal/slot-children.js +31 -0
- package/dist/internal/slot.d.ts +3 -3
- package/dist/internal/slot.js +2 -2
- package/dist/internal/step.d.ts +12 -0
- package/dist/internal/step.js +31 -0
- package/dist/internal/tween.d.ts +5 -5
- package/dist/internal/tween.js +7 -8
- package/dist/internal/types.d.ts +2 -2
- package/dist/internal/use-breakpoint.d.ts +2 -2
- package/dist/internal/use-breakpoint.js +4 -4
- package/dist/internal/use-controllable-state.d.ts +5 -0
- package/dist/internal/use-controllable-state.js +25 -4
- package/dist/internal/use-id.d.ts +2 -2
- package/dist/internal/use-id.js +2 -2
- package/dist/internal/use-modal-focus.d.ts +2 -1
- package/dist/internal/use-modal-focus.js +14 -3
- package/dist/knob/knob.d.ts +7 -4
- package/dist/knob/knob.js +27 -22
- package/dist/knob/llms.txt +18 -11
- package/dist/listbox/listbox.d.ts +8 -6
- package/dist/listbox/listbox.js +37 -17
- package/dist/listbox/llms.txt +12 -9
- package/dist/loader/llms.txt +56 -0
- package/dist/loader/loader.d.ts +49 -0
- package/dist/loader/loader.js +68 -0
- package/dist/map/llms.txt +30 -23
- package/dist/map/map-create-dialog.d.ts +4 -4
- package/dist/map/map-create-dialog.js +36 -28
- package/dist/map/map-hours-field.d.ts +4 -4
- package/dist/map/map-hours-field.js +8 -7
- package/dist/map/map-image-field.d.ts +2 -2
- package/dist/map/map-image-field.js +6 -5
- package/dist/map/map-legend.d.ts +4 -4
- package/dist/map/map-legend.js +3 -2
- package/dist/map/map-poi-card.d.ts +3 -3
- package/dist/map/map-poi-card.js +10 -9
- package/dist/map/map-search.d.ts +17 -6
- package/dist/map/map-search.js +70 -43
- package/dist/map/map.d.ts +25 -13
- package/dist/map/map.js +86 -57
- package/dist/map/ports.d.ts +9 -9
- package/dist/map/ports.js +6 -6
- package/dist/map-entry/public-api.js +2 -2
- package/dist/megamenu/llms.txt +18 -7
- package/dist/megamenu/megamenu.d.ts +12 -6
- package/dist/megamenu/megamenu.js +23 -14
- package/dist/mention/llms.txt +15 -15
- package/dist/mention/mention.d.ts +5 -5
- package/dist/mention/mention.js +2 -2
- package/dist/mention/mentions.d.ts +1 -1
- package/dist/mention/mentions.js +1 -1
- package/dist/menu/llms.txt +12 -12
- package/dist/menu/menu-item.d.ts +4 -4
- package/dist/menu/menu-keys.d.ts +2 -2
- package/dist/menu/menu-keys.js +5 -5
- package/dist/menu/menu-rows.js +1 -0
- package/dist/menu/menu.d.ts +2 -2
- package/dist/menu/menu.js +15 -8
- package/dist/menubar/llms.txt +19 -8
- package/dist/menubar/menubar.d.ts +11 -5
- package/dist/menubar/menubar.js +23 -11
- package/dist/meter-group/llms.txt +12 -12
- package/dist/meter-group/meter-group.d.ts +2 -2
- package/dist/meter-group/meter-group.js +2 -1
- package/dist/motion/motion-context.d.ts +22 -0
- package/dist/motion/motion-context.js +28 -0
- package/dist/order-list/llms.txt +24 -9
- package/dist/order-list/order-list.d.ts +12 -4
- package/dist/order-list/order-list.js +123 -25
- package/dist/paginator/llms.txt +8 -8
- package/dist/paginator/paginator.js +7 -4
- package/dist/panel/llms.txt +25 -13
- package/dist/panel/panel.d.ts +11 -3
- package/dist/panel/panel.js +12 -7
- package/dist/password/llms.txt +19 -7
- package/dist/password/password.d.ts +2 -2
- package/dist/password/password.js +27 -16
- package/dist/peek/llms.txt +11 -11
- package/dist/peek/peek.d.ts +6 -6
- package/dist/peek/peek.js +41 -19
- package/dist/pick-list/llms.txt +35 -12
- package/dist/pick-list/pick-list.d.ts +12 -4
- package/dist/pick-list/pick-list.js +128 -24
- package/dist/popover/llms.txt +13 -10
- package/dist/popover/popover.d.ts +6 -4
- package/dist/popover/popover.js +14 -7
- package/dist/progress/llms.txt +17 -17
- package/dist/progress/progress.d.ts +7 -7
- package/dist/progress/progress.js +7 -6
- package/dist/public-api.d.ts +16 -4
- package/dist/public-api.js +13 -7
- package/dist/radio-group/llms.txt +16 -6
- package/dist/radio-group/radio-group.d.ts +12 -3
- package/dist/radio-group/radio-group.js +23 -4
- package/dist/rating/llms.txt +20 -13
- package/dist/rating/rating-pointer.d.ts +16 -0
- package/dist/rating/rating-pointer.js +26 -0
- package/dist/rating/rating.d.ts +6 -6
- package/dist/rating/rating.js +77 -12
- package/dist/rich-text/lists.d.ts +2 -2
- package/dist/rich-text/lists.js +7 -7
- package/dist/rich-text/llms.txt +35 -12
- package/dist/rich-text/rich-text.d.ts +13 -14
- package/dist/rich-text/rich-text.js +311 -142
- package/dist/rich-text/sanitize.d.ts +11 -2
- package/dist/rich-text/sanitize.js +80 -32
- package/dist/rich-text/tables.d.ts +3 -3
- package/dist/rich-text/tables.js +3 -3
- package/dist/roadmap/llms.txt +23 -17
- package/dist/roadmap/roadmap.d.ts +6 -6
- package/dist/roadmap/roadmap.js +102 -25
- package/dist/roadmap-entry/public-api.js +2 -2
- package/dist/scroll-top/llms.txt +6 -6
- package/dist/scroll-top/scroll-top.d.ts +1 -1
- package/dist/scroll-top/scroll-top.js +2 -1
- package/dist/select/llms.txt +22 -12
- package/dist/select/select.d.ts +10 -8
- package/dist/select/select.js +87 -47
- package/dist/shared/types.d.ts +22 -1
- package/dist/shared/types.js +9 -1
- package/dist/sidenav/llms.txt +9 -9
- package/dist/sidenav/sidenav.d.ts +2 -3
- package/dist/sidenav/sidenav.js +5 -4
- package/dist/skeleton/llms.txt +3 -3
- package/dist/skeleton/skeleton.d.ts +1 -1
- package/dist/skeleton/skeleton.js +1 -1
- package/dist/slider/llms.txt +34 -12
- package/dist/slider/slider-drag.d.ts +26 -0
- package/dist/slider/slider-drag.js +79 -0
- package/dist/slider/slider.d.ts +8 -5
- package/dist/slider/slider.js +38 -8
- package/dist/speech/llms.txt +97 -0
- package/dist/speech/speech-button.d.ts +44 -0
- package/dist/speech/speech-button.js +86 -0
- package/dist/speech/speech-wave.d.ts +19 -0
- package/dist/speech/speech-wave.js +16 -0
- package/dist/speech/use-speech-recognition.d.ts +81 -0
- package/dist/speech/use-speech-recognition.js +179 -0
- package/dist/speed-dial/llms.txt +14 -8
- package/dist/speed-dial/speed-dial.d.ts +1 -1
- package/dist/speed-dial/speed-dial.js +3 -2
- package/dist/spinner/llms.txt +7 -7
- package/dist/spinner/spinner.d.ts +1 -1
- package/dist/spinner/spinner.js +2 -1
- package/dist/split-button/llms.txt +21 -15
- package/dist/split-button/split-button.d.ts +2 -2
- package/dist/split-button/split-button.js +13 -6
- package/dist/splitter/llms.txt +11 -11
- package/dist/splitter/splitter.d.ts +3 -3
- package/dist/splitter/splitter.js +25 -10
- package/dist/stepper/llms.txt +35 -13
- package/dist/stepper/stepper.d.ts +6 -6
- package/dist/stepper/stepper.js +60 -13
- package/dist/switch/llms.txt +15 -5
- package/dist/switch/switch.d.ts +10 -3
- package/dist/switch/switch.js +18 -4
- package/dist/switch-group/llms.txt +11 -8
- package/dist/switch-group/switch-group.d.ts +6 -4
- package/dist/switch-group/switch-group.js +9 -7
- package/dist/tabs/llms.txt +12 -9
- package/dist/tabs/tabs.d.ts +5 -5
- package/dist/tabs/tabs.js +36 -20
- package/dist/textarea/llms.txt +23 -12
- package/dist/textarea/textarea.d.ts +19 -6
- package/dist/textarea/textarea.js +22 -7
- package/dist/timeline/llms.txt +4 -4
- package/dist/timeline/timeline.d.ts +1 -1
- package/dist/timeline/timeline.js +1 -1
- package/dist/toast/llms.txt +50 -17
- package/dist/toast/toast-container.d.ts +9 -3
- package/dist/toast/toast-container.js +18 -9
- package/dist/toast/toast-store.d.ts +42 -2
- package/dist/toast/toast-store.js +36 -1
- package/dist/toolbar/llms.txt +7 -7
- package/dist/toolbar/toolbar.d.ts +3 -3
- package/dist/toolbar/toolbar.js +2 -2
- package/dist/tooltip/llms.txt +14 -12
- package/dist/tooltip/tooltip.d.ts +5 -4
- package/dist/tooltip/tooltip.js +100 -41
- package/dist/tree/llms.txt +25 -11
- package/dist/tree/tree-keys.d.ts +5 -5
- package/dist/tree/tree-keys.js +7 -7
- package/dist/tree/tree.d.ts +17 -5
- package/dist/tree/tree.js +62 -20
- package/dist/update/llms.txt +54 -0
- package/dist/update/update.d.ts +49 -0
- package/dist/update/update.js +82 -0
- package/package.json +18 -15
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useRef, useState } from 'react';
|
|
3
|
-
import { buildRangeGrid, clampVisibleMonths, datePart,
|
|
3
|
+
import { useEffect, useEffectEvent, useRef, useState, } from 'react';
|
|
4
|
+
import { buildRangeGrid, clampVisibleMonths, datePart, dayPeriodLabels, displayDate, formatTime, kptFirstDayOfWeek, orderWeekdays, initialFocusDate, moveFocusDate, pad, parseDate, parseTime, pickRangeDay, timePart, toIso, } from '@konce-pt/datetime';
|
|
4
5
|
import { monthNames, weekdayNames } from '@konce-pt/i18n';
|
|
5
6
|
import { cn } from "../internal/cn.js";
|
|
6
7
|
import { useControllableState } from "../internal/use-controllable-state.js";
|
|
@@ -18,43 +19,49 @@ const EMPTY_RANGE = { start: '', end: '' };
|
|
|
18
19
|
* `visibleMonths` pokazuje kilka miesięcy obok siebie, a zakres podświetla się ciągłym pasmem
|
|
19
20
|
* przez wszystkie panele.
|
|
20
21
|
*
|
|
21
|
-
* Klawiatura jak w `KptDatepicker`: `Enter`/`Spacja
|
|
22
|
-
* zakresu (albo dziś), strzałki, `Home`/`End` i `PageUp`/`PageDown` (z `Shift`
|
|
22
|
+
* Klawiatura jak w `KptDatepicker`: `Enter`/`Spacja`/`ArrowDown` otwierają panel z fokusem na początku
|
|
23
|
+
* zakresu (albo dziś), strzałki, `Home`/`End` i `PageUp`/`PageDown` (z `Shift` - rok) chodzą po
|
|
23
24
|
* dniach przez wszystkie panele, `Tab` krąży w panelu, `Escape` i wybór końca oddają fokus polu.
|
|
24
|
-
* Krańce i środek zakresu są w nazwie dnia (
|
|
25
|
+
* Krańce i środek zakresu są w nazwie dnia ("..., początek zakresu"), a wybór i przewinięcie miesiąca
|
|
26
|
+
* ogłasza region `polite`. Pole to `role="combobox"` z `aria-haspopup="dialog"`, więc niesie
|
|
27
|
+
* `aria-required`, `aria-readonly` i `aria-invalid`. Tydzień zaczyna się wg aktywnego języka.
|
|
25
28
|
*
|
|
26
29
|
* @example
|
|
27
30
|
* <KptDateRange value={period} onValueChange={setPeriod} visibleMonths={2} />
|
|
28
31
|
* <KptDateRange mode="datetime" hourFormat={12} value={span} onValueChange={setSpan} />
|
|
29
32
|
*/
|
|
30
|
-
export function KptDateRange({ value, defaultValue = EMPTY_RANGE, onValueChange, mode = 'date', visibleMonths = 1, hourFormat = 24, minuteStep = 1, placeholder, displayFormat = 'pl', minDate = null, maxDate = null, ariaLabel = null, id, disabled = false, invalid = false, touched, onTouch, locale, dictionary, className, ...rest }) {
|
|
33
|
+
export function KptDateRange({ value, defaultValue = EMPTY_RANGE, onValueChange, mode = 'date', visibleMonths = 1, hourFormat = 24, minuteStep = 1, placeholder, displayFormat = 'pl', firstDayOfWeek = null, open, onOpenChange, minDate = null, maxDate = null, ariaLabel = null, id, disabled = false, readOnly = false, required = false, invalid = false, touched, onTouch, locale, dictionary, className, ...rest }) {
|
|
31
34
|
const { t, locale: activeLocale } = useKptMessages({ locale, dictionary });
|
|
32
|
-
/** `div` z rolą nie dostaje nazwy z `label[for]`
|
|
35
|
+
/** `div` z rolą nie dostaje nazwy z `label[for]` - stąd `aria-labelledby` na etykietę wrappera. */
|
|
33
36
|
const field = useKptFieldA11y(id, 'kpt-date-range');
|
|
34
37
|
const [current, setCurrent] = useControllableState({ value, defaultValue, onChange: onValueChange });
|
|
35
|
-
const [isOpen, setOpen] =
|
|
38
|
+
const [isOpen, setOpen] = useControllableState({ value: open, defaultValue: false, onChange: onOpenChange });
|
|
36
39
|
const [anchor, setAnchor] = useState(null);
|
|
37
40
|
const triggerRef = useRef(null);
|
|
38
41
|
const panelRef = useRef(null);
|
|
39
42
|
const panelId = useKptId(undefined, 'kpt-date-range-panel');
|
|
40
|
-
/** Dzień z fokusem
|
|
43
|
+
/** Dzień z fokusem - jedyny przystanek Tab siatek dni (roving tabindex przez wszystkie panele). */
|
|
41
44
|
const [focusIso, setFocusIso] = useState('');
|
|
42
45
|
/** Komunikat regionu `polite` po wyborze początku i całego zakresu. */
|
|
43
46
|
const [announcement, setAnnouncement] = useState('');
|
|
44
|
-
/** Prośba o przeniesienie fokusu po najbliższym renderze (otwarcie, ruch klawiszem). */
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
+
/** Prośba o przeniesienie fokusu po najbliższym renderze (otwarcie, ruch klawiszem) - licznik w stanie. */
|
|
48
|
+
const [focusRequest, setFocusRequest] = useState(0);
|
|
49
|
+
const requestFocus = () => setFocusRequest((n) => n + 1);
|
|
50
|
+
/** "Dziś" liczone przy każdym otwarciu - panel otwarty po północy nie pokazuje wczorajszego dnia. */
|
|
51
|
+
const [today, setToday] = useState(() => new Date());
|
|
47
52
|
const todayIso = toIso(today);
|
|
53
|
+
const firstDay = firstDayOfWeek ?? kptFirstDayOfWeek(activeLocale);
|
|
54
|
+
const periods = dayPeriodLabels(activeLocale);
|
|
48
55
|
const showInvalid = invalid && (touched ?? true);
|
|
49
56
|
const [page, setPage] = useState(() => ({ y: today.getFullYear(), m: today.getMonth() }));
|
|
50
57
|
const [startTime, setStartTime] = useState('');
|
|
51
58
|
const [endTime, setEndTime] = useState('');
|
|
52
59
|
const [timeEnd, setTimeEnd] = useState('start');
|
|
53
|
-
// Część kalendarzowa zakresu w trybie datetime
|
|
60
|
+
// Część kalendarzowa zakresu w trybie datetime - wartość powstaje dopiero przy "Gotowe".
|
|
54
61
|
const [startDate, setStartDate] = useState('');
|
|
55
62
|
const [endDate, setEndDate] = useState('');
|
|
56
63
|
const months = monthNames(activeLocale);
|
|
57
|
-
const weekdays = weekdayNames(activeLocale);
|
|
64
|
+
const weekdays = orderWeekdays(weekdayNames(activeLocale), firstDay);
|
|
58
65
|
const panelCount = mode === 'time' ? 1 : clampVisibleMonths(visibleMonths);
|
|
59
66
|
const multi = panelCount > 1;
|
|
60
67
|
const dayFormat = new Intl.DateTimeFormat(activeLocale, { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' });
|
|
@@ -62,7 +69,7 @@ export function KptDateRange({ value, defaultValue = EMPTY_RANGE, onValueChange,
|
|
|
62
69
|
const date = parseDate(iso);
|
|
63
70
|
return date ? dayFormat.format(date) : iso;
|
|
64
71
|
};
|
|
65
|
-
/** Pełna nazwa dnia z rolą w zakresie
|
|
72
|
+
/** Pełna nazwa dnia z rolą w zakresie - kolor pasma nie jest jedynym nośnikiem informacji. */
|
|
66
73
|
const dayLabel = (cell) => {
|
|
67
74
|
const name = dayName(cell.iso);
|
|
68
75
|
if (cell.isStart)
|
|
@@ -75,49 +82,58 @@ export function KptDateRange({ value, defaultValue = EMPTY_RANGE, onValueChange,
|
|
|
75
82
|
};
|
|
76
83
|
const fmtTime = (hhmm) => {
|
|
77
84
|
const parsed = parseTime(hhmm);
|
|
78
|
-
return parsed ? formatTime(parsed.h, parsed.m, hourFormat) : '';
|
|
85
|
+
return parsed ? formatTime(parsed.h, parsed.m, hourFormat, periods) : '';
|
|
79
86
|
};
|
|
80
87
|
const display = (() => {
|
|
81
88
|
const { start, end } = current;
|
|
82
89
|
if (!start)
|
|
83
90
|
return '';
|
|
84
91
|
if (mode === 'time') {
|
|
85
|
-
return end ? `${fmtTime(start)}
|
|
92
|
+
return end ? `${fmtTime(start)} - ${fmtTime(end)}` : `${fmtTime(start)} - ...`;
|
|
86
93
|
}
|
|
87
94
|
if (mode === 'datetime') {
|
|
88
95
|
const one = (v) => {
|
|
89
|
-
const date =
|
|
96
|
+
const date = displayDate(datePart(v), displayFormat, activeLocale);
|
|
90
97
|
const time = fmtTime(timePart(v));
|
|
91
98
|
return time ? `${date} ${time}` : date;
|
|
92
99
|
};
|
|
93
|
-
return end ? `${one(start)}
|
|
100
|
+
return end ? `${one(start)} - ${one(end)}` : `${one(start)} - ...`;
|
|
94
101
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
: `${formatDate(start, displayFormat)} – …`;
|
|
102
|
+
const fmt = (iso) => displayDate(iso, displayFormat, activeLocale);
|
|
103
|
+
return end ? `${fmt(start)} - ${fmt(end)}` : `${fmt(start)} - ...`;
|
|
98
104
|
})();
|
|
105
|
+
// Panel otwiera też `open` z zewnątrz - stan początkowy liczymy przy każdym przejściu w stan
|
|
106
|
+
// otwarty, wzorcem "poprzednia wartość w stanie" (bez efektu i klatki ze starym widokiem).
|
|
107
|
+
const [wasOpen, setWasOpen] = useState(isOpen);
|
|
108
|
+
if (wasOpen !== isOpen) {
|
|
109
|
+
setWasOpen(isOpen);
|
|
110
|
+
if (isOpen)
|
|
111
|
+
prepareOpen();
|
|
112
|
+
}
|
|
113
|
+
function prepareOpen() {
|
|
114
|
+
const now = new Date();
|
|
115
|
+
setToday(now);
|
|
116
|
+
const { start, end } = current;
|
|
117
|
+
const focus = initialFocusDate(datePart(start), toIso(now), minDate, maxDate);
|
|
118
|
+
setFocusIso(focus);
|
|
119
|
+
setAnnouncement('');
|
|
120
|
+
setPage({ y: +focus.slice(0, 4), m: +focus.slice(5, 7) - 1 });
|
|
121
|
+
requestFocus();
|
|
122
|
+
if (mode === 'datetime') {
|
|
123
|
+
setStartDate(datePart(start));
|
|
124
|
+
setEndDate(datePart(end));
|
|
125
|
+
setStartTime(timePart(start) || '00:00');
|
|
126
|
+
setEndTime(timePart(end) || '00:00');
|
|
127
|
+
}
|
|
128
|
+
else if (mode === 'time') {
|
|
129
|
+
setStartTime(/^\d{2}:\d{2}$/.test(start) ? start : '00:00');
|
|
130
|
+
setEndTime(/^\d{2}:\d{2}$/.test(end) ? end : '00:00');
|
|
131
|
+
}
|
|
132
|
+
setTimeEnd('start');
|
|
133
|
+
}
|
|
99
134
|
const toggleOpen = () => {
|
|
100
|
-
if (disabled)
|
|
135
|
+
if (disabled || readOnly)
|
|
101
136
|
return;
|
|
102
|
-
if (!isOpen) {
|
|
103
|
-
const { start, end } = current;
|
|
104
|
-
const focus = initialFocusDate(datePart(start), todayIso, minDate, maxDate);
|
|
105
|
-
setFocusIso(focus);
|
|
106
|
-
setAnnouncement('');
|
|
107
|
-
setPage({ y: +focus.slice(0, 4), m: +focus.slice(5, 7) - 1 });
|
|
108
|
-
wantFocus.current = true;
|
|
109
|
-
if (mode === 'datetime') {
|
|
110
|
-
setStartDate(datePart(start));
|
|
111
|
-
setEndDate(datePart(end));
|
|
112
|
-
setStartTime(timePart(start) || '00:00');
|
|
113
|
-
setEndTime(timePart(end) || '00:00');
|
|
114
|
-
}
|
|
115
|
-
else if (mode === 'time') {
|
|
116
|
-
setStartTime(/^\d{2}:\d{2}$/.test(start) ? start : '00:00');
|
|
117
|
-
setEndTime(/^\d{2}:\d{2}$/.test(end) ? end : '00:00');
|
|
118
|
-
}
|
|
119
|
-
setTimeEnd('start');
|
|
120
|
-
}
|
|
121
137
|
setOpen(!isOpen);
|
|
122
138
|
};
|
|
123
139
|
const close = () => {
|
|
@@ -126,22 +142,20 @@ export function KptDateRange({ value, defaultValue = EMPTY_RANGE, onValueChange,
|
|
|
126
142
|
setOpen(false);
|
|
127
143
|
onTouch?.();
|
|
128
144
|
};
|
|
129
|
-
/** Zamknięcie z powrotem fokusu na pole
|
|
145
|
+
/** Zamknięcie z powrotem fokusu na pole - po wyborze z klawiatury, `Escape`. */
|
|
130
146
|
const closeAndFocus = () => {
|
|
131
147
|
close();
|
|
132
148
|
triggerRef.current?.focus();
|
|
133
149
|
};
|
|
134
|
-
// Fokus po renderze. Panel w nakładce jest niewidoczny do pierwszego pomiaru
|
|
150
|
+
// Fokus po renderze. Panel w nakładce jest niewidoczny do pierwszego pomiaru - stąd rAF.
|
|
151
|
+
const focusActive = useEffectEvent(() => focusCalendarActive(panelRef.current, focusIso));
|
|
135
152
|
useEffect(() => {
|
|
136
|
-
if (!isOpen ||
|
|
153
|
+
if (!isOpen || focusRequest === 0)
|
|
137
154
|
return;
|
|
138
|
-
const frame = requestAnimationFrame(() =>
|
|
139
|
-
wantFocus.current = false;
|
|
140
|
-
focusCalendarActive(panelRef.current, focusIso);
|
|
141
|
-
});
|
|
155
|
+
const frame = requestAnimationFrame(() => focusActive());
|
|
142
156
|
return () => cancelAnimationFrame(frame);
|
|
143
|
-
});
|
|
144
|
-
/** Przesuwa okno paneli tak, żeby miesiąc dnia `iso` był widoczny
|
|
157
|
+
}, [focusRequest, isOpen]);
|
|
158
|
+
/** Przesuwa okno paneli tak, żeby miesiąc dnia `iso` był widoczny - z najmniejszym skokiem. */
|
|
145
159
|
const revealMonth = (iso) => {
|
|
146
160
|
const target = +iso.slice(0, 4) * 12 + (+iso.slice(5, 7) - 1);
|
|
147
161
|
const first = page.y * 12 + page.m;
|
|
@@ -154,22 +168,27 @@ export function KptDateRange({ value, defaultValue = EMPTY_RANGE, onValueChange,
|
|
|
154
168
|
};
|
|
155
169
|
const onDayKeyDown = (event) => {
|
|
156
170
|
const rtl = !!panelRef.current && getComputedStyle(panelRef.current).direction === 'rtl';
|
|
157
|
-
const next = moveFocusDate(focusIso, event.key, { shift: event.shiftKey, rtl, minDate, maxDate });
|
|
171
|
+
const next = moveFocusDate(focusIso, event.key, { shift: event.shiftKey, rtl, minDate, maxDate, firstDay });
|
|
158
172
|
if (next === null)
|
|
159
173
|
return;
|
|
160
174
|
event.preventDefault();
|
|
161
175
|
setFocusIso(next);
|
|
162
176
|
revealMonth(next);
|
|
163
|
-
|
|
177
|
+
requestFocus();
|
|
164
178
|
};
|
|
165
|
-
/** Strzałki
|
|
179
|
+
/** Strzałki < >: fokus zostaje na strzałce, ale przystanek siatki idzie za stroną. */
|
|
166
180
|
const turnPage = (dir) => {
|
|
167
181
|
const first = page.y * 12 + page.m + dir;
|
|
168
182
|
setPage({ y: Math.floor(first / 12), m: ((first % 12) + 12) % 12 });
|
|
169
|
-
|
|
183
|
+
// Przewinięcie ogłasza widoczne miesiące (APG: `aria-live` na nagłówku).
|
|
184
|
+
setAnnouncement(Array.from({ length: panelCount }, (_, i) => {
|
|
185
|
+
const month = first + i;
|
|
186
|
+
return `${months[((month % 12) + 12) % 12]} ${Math.floor(month / 12)}`;
|
|
187
|
+
}).join(' - '));
|
|
188
|
+
const moved = moveFocusDate(focusIso, dir === 1 ? 'PageDown' : 'PageUp', { minDate, maxDate, firstDay });
|
|
170
189
|
if (moved) {
|
|
171
190
|
const target = +moved.slice(0, 4) * 12 + (+moved.slice(5, 7) - 1);
|
|
172
|
-
// Nowe okno zaczyna się od `first`
|
|
191
|
+
// Nowe okno zaczyna się od `first` - dzień spoza niego nie dostałby przystanku Tab.
|
|
173
192
|
if (target >= first && target < first + panelCount)
|
|
174
193
|
setFocusIso(moved);
|
|
175
194
|
}
|
|
@@ -194,6 +213,7 @@ export function KptDateRange({ value, defaultValue = EMPTY_RANGE, onValueChange,
|
|
|
194
213
|
hideOutside: multi,
|
|
195
214
|
minDate,
|
|
196
215
|
maxDate,
|
|
216
|
+
firstDay,
|
|
197
217
|
}),
|
|
198
218
|
};
|
|
199
219
|
});
|
|
@@ -204,12 +224,12 @@ export function KptDateRange({ value, defaultValue = EMPTY_RANGE, onValueChange,
|
|
|
204
224
|
setStartDate(next.start);
|
|
205
225
|
setEndDate(next.end);
|
|
206
226
|
announce(next.start, next.end);
|
|
207
|
-
return; // czas do wyboru
|
|
227
|
+
return; // czas do wyboru -> zamknięcie przez "Gotowe"
|
|
208
228
|
}
|
|
209
229
|
const next = pickRangeDay(current, iso);
|
|
210
230
|
setCurrent(next);
|
|
211
231
|
announce(next.start, next.end);
|
|
212
|
-
// Panel zostaje otwarty do czasu domknięcia zakresu
|
|
232
|
+
// Panel zostaje otwarty do czasu domknięcia zakresu - inaczej drugi klik nie miałby gdzie paść.
|
|
213
233
|
if (next.end)
|
|
214
234
|
closeAndFocus();
|
|
215
235
|
};
|
|
@@ -232,17 +252,20 @@ export function KptDateRange({ value, defaultValue = EMPTY_RANGE, onValueChange,
|
|
|
232
252
|
};
|
|
233
253
|
const clear = (event) => {
|
|
234
254
|
event.stopPropagation();
|
|
255
|
+
if (readOnly)
|
|
256
|
+
return;
|
|
235
257
|
setCurrent(EMPTY_RANGE);
|
|
236
258
|
setStartDate('');
|
|
237
259
|
setEndDate('');
|
|
260
|
+
onTouch?.();
|
|
238
261
|
};
|
|
239
262
|
const clockValue = timeEnd === 'start' ? startTime : endTime;
|
|
240
263
|
const setClockValue = timeEnd === 'start' ? setStartTime : setEndTime;
|
|
241
264
|
return (_jsxs("div", { className: cn('kpt-date-range-host', className), ...rest, children: [_jsxs("div", { ref: (el) => {
|
|
242
265
|
triggerRef.current = el;
|
|
243
266
|
setAnchor(el);
|
|
244
|
-
}, className: cn('kpt-date-range', isOpen && 'kpt-date-range--open', disabled && 'kpt-date-range--disabled', showInvalid && 'kpt-date-range--invalid'), role: "
|
|
245
|
-
if (disabled)
|
|
267
|
+
}, className: cn('kpt-date-range', isOpen && 'kpt-date-range--open', disabled && 'kpt-date-range--disabled', readOnly && 'kpt-date-range--readonly', showInvalid && 'kpt-date-range--invalid'), role: "combobox", tabIndex: 0, "aria-keyshortcuts": "Delete Backspace", "aria-required": required || undefined, "aria-readonly": readOnly || undefined, "aria-haspopup": "dialog", "aria-expanded": isOpen, "aria-controls": isOpen ? panelId : undefined, id: field.id, "aria-labelledby": ariaLabel ? undefined : field.labelledBy, "aria-describedby": field.describedBy, "aria-disabled": disabled || undefined, "aria-invalid": showInvalid || undefined, "aria-label": ariaLabel ?? undefined, onClick: toggleOpen, onKeyDown: (event) => {
|
|
268
|
+
if (disabled || readOnly)
|
|
246
269
|
return;
|
|
247
270
|
if (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown') {
|
|
248
271
|
event.preventDefault();
|
|
@@ -254,8 +277,8 @@ export function KptDateRange({ value, defaultValue = EMPTY_RANGE, onValueChange,
|
|
|
254
277
|
clear(event);
|
|
255
278
|
}
|
|
256
279
|
},
|
|
257
|
-
// Przy otwartym panelu fokus idzie do kalendarza
|
|
258
|
-
onBlur: () => !isOpen && onTouch?.(), children: [display ? (_jsx("span", { className: "kpt-date-range__value", children: display })) : (_jsx("span", { className: "kpt-date-range__placeholder", children: placeholder ?? t('dateRange.placeholder') })), _jsx("span", { className: "kpt-date-range__spacer" }), display ? (_jsx("button", { type: "button", className: "kpt-date-range__clear", tabIndex: -1, onClick: clear, "aria-label": t('common.clear'), children: _jsx(KptIcon, { name: "x" }) })) : null, _jsx(KptIcon, { className: "kpt-date-range__icon", name: "calendar" })] }), _jsx(KptOverlay, { open: isOpen, anchor: anchor, onClose: close, offset: 4, children: _jsxs("div", { ref: panelRef, id: panelId, role: "dialog", "aria-label": t('dateRange.dialog'), className: cn('kpt-calendar', mode === 'time' && 'kpt-calendar--clock', mode !== 'time' && 'kpt-calendar--range', multi && mode !== 'time' && 'kpt-calendar--multi'), onKeyDown: (event) => {
|
|
280
|
+
// Przy otwartym panelu fokus idzie do kalendarza - "dotknięcie" wyśle dopiero zamknięcie.
|
|
281
|
+
onBlur: () => !isOpen && onTouch?.(), children: [display ? (_jsx("span", { className: "kpt-date-range__value", children: display })) : (_jsx("span", { className: "kpt-date-range__placeholder", children: placeholder ?? t('dateRange.placeholder') })), _jsx("span", { className: "kpt-date-range__spacer" }), display && !readOnly ? (_jsx("button", { type: "button", className: "kpt-date-range__clear", tabIndex: -1, onClick: clear, "aria-label": t('common.clear'), children: _jsx(KptIcon, { name: "x" }) })) : null, _jsx(KptIcon, { className: "kpt-date-range__icon", name: "calendar" })] }), _jsx(KptOverlay, { open: isOpen, anchor: anchor, onClose: close, offset: 4, children: _jsxs("div", { ref: panelRef, id: panelId, role: "dialog", "aria-label": t('dateRange.dialog'), className: cn('kpt-calendar', mode === 'time' && 'kpt-calendar--clock', mode !== 'time' && 'kpt-calendar--range', multi && mode !== 'time' && 'kpt-calendar--multi'), onKeyDown: (event) => {
|
|
259
282
|
if (event.key === 'Escape') {
|
|
260
283
|
event.preventDefault();
|
|
261
284
|
event.stopPropagation();
|
|
@@ -265,7 +288,7 @@ export function KptDateRange({ value, defaultValue = EMPTY_RANGE, onValueChange,
|
|
|
265
288
|
trapTab(event.currentTarget, event.nativeEvent);
|
|
266
289
|
}
|
|
267
290
|
}, children: [_jsx("span", { className: "kpt-calendar__live", "aria-live": "polite", children: announcement }), mode === 'time' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "kpt-range-tabs", children: [_jsx("button", { type: "button", className: cn(timeEnd === 'start' && 'is-active'), onClick: () => setTimeEnd('start'), children: t('dateRange.from') }), _jsx("button", { type: "button", className: cn(timeEnd === 'end' && 'is-active'), onClick: () => setTimeEnd('end'), children: t('dateRange.to') })] }), _jsx(KptClock
|
|
268
|
-
// Klucz na edytowanym końcu wymusza remount przy przełączeniu Od/Koniec
|
|
291
|
+
// Klucz na edytowanym końcu wymusza remount przy przełączeniu Od/Koniec - tarcza ma
|
|
269
292
|
// wtedy wrócić do etapu godzin, tak jak dwie osobne instancje w porcie Angulara.
|
|
270
293
|
, { value: clockValue, onValueChange: setClockValue, hourFormat: hourFormat, minuteStep: minuteStep }, timeEnd), _jsx("div", { className: "kpt-calendar__footer", children: _jsx(KptButton, { size: "sm", onClick: commit, children: t('common.done') }) })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "kpt-calendar__panels", children: panels.map((panel, index) => (_jsxs("div", { className: "kpt-calendar__panel", children: [_jsxs("div", { className: "kpt-calendar__header", children: [index === 0 ? (_jsx("button", { type: "button", className: "kpt-calendar__nav", onClick: () => turnPage(-1), "aria-label": t('datepicker.prevMonth'), children: _jsx(KptIcon, { name: "chevron-left" }) })) : (_jsx("span", { className: "kpt-calendar__nav-slot" })), _jsx("span", { className: "kpt-calendar__title", children: panel.label }), index === panels.length - 1 ? (_jsx("button", { type: "button", className: "kpt-calendar__nav", onClick: () => turnPage(1), "aria-label": t('datepicker.nextMonth'), children: _jsx(KptIcon, { name: "chevron-right" }) })) : (_jsx("span", { className: "kpt-calendar__nav-slot" }))] }), _jsx("div", { className: "kpt-calendar__weekdays", children: weekdays.map((weekday) => (_jsx("span", { className: "kpt-calendar__weekday", children: weekday }, weekday))) }), _jsx("div", { className: "kpt-calendar__grid", onKeyDown: onDayKeyDown, children: panel.weeks.flat().map((cell) => cell.blank ? (_jsx("span", { className: "kpt-calendar__day kpt-calendar__day--blank" }, cell.iso)) : (_jsx("button", { type: "button", className: cn('kpt-calendar__day', !cell.inMonth && 'kpt-calendar__day--muted', cell.today && 'kpt-calendar__day--today', cell.inRange && 'kpt-calendar__day--range', cell.rangeStart && 'kpt-calendar__day--range-start', cell.rangeEnd && 'kpt-calendar__day--range-end', (cell.isStart || cell.isEnd) && 'kpt-calendar__day--selected'), "data-iso": cell.iso, tabIndex: cell.iso === focusIso ? 0 : -1, "aria-label": dayLabel(cell), "aria-current": cell.today ? 'date' : undefined, "aria-pressed": cell.isStart || cell.isEnd, disabled: cell.disabled, onClick: () => selectDay(cell.iso), children: cell.day }, cell.iso))) })] }, panel.key))) }), mode === 'datetime' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "kpt-range-tabs", children: [_jsx("button", { type: "button", className: cn(timeEnd === 'start' && 'is-active'), onClick: () => setTimeEnd('start'), children: t('dateRange.fromTime') }), _jsx("button", { type: "button", className: cn(timeEnd === 'end' && 'is-active'), onClick: () => setTimeEnd('end'), children: t('dateRange.toTime') })] }), _jsx(KptClock, { value: clockValue, onValueChange: setClockValue, hourFormat: hourFormat, minuteStep: minuteStep }, timeEnd), _jsx("div", { className: "kpt-calendar__footer", children: _jsx(KptButton, { size: "sm", onClick: commit, children: t('common.done') }) })] })) : null] }))] }) })] }));
|
|
271
294
|
}
|
package/dist/date-range/llms.txt
CHANGED
|
@@ -5,49 +5,49 @@ Import: `import { KptDateRange, type KptDateRangeValue } from '@konce-pt/react';
|
|
|
5
5
|
|
|
6
6
|
## DOM
|
|
7
7
|
<div class="kpt-date-range-host">
|
|
8
|
-
<div class="kpt-date-range" role="
|
|
9
|
-
<span class="kpt-date-range__value">08.09.2026
|
|
10
|
-
|
|
8
|
+
<div class="kpt-date-range" role="combobox" tabindex="0" aria-haspopup="dialog">
|
|
9
|
+
<span class="kpt-date-range__value">08.09.2026 - 14.09.2026</span>
|
|
10
|
+
...clear, icon...
|
|
11
11
|
</div>
|
|
12
12
|
</div>
|
|
13
|
-
<!-- in a portal: <div class="kpt-calendar kpt-calendar--range kpt-calendar--multi"
|
|
13
|
+
<!-- in a portal: <div class="kpt-calendar kpt-calendar--range kpt-calendar--multi">...</div> -->
|
|
14
14
|
|
|
15
15
|
## Props
|
|
16
|
-
- `value` / `defaultValue` / `onValueChange`
|
|
16
|
+
- `value` / `defaultValue` / `onValueChange` - `{ start, end }`: dates 'YYYY-MM-DD',
|
|
17
17
|
datetime 'YYYY-MM-DDTHH:mm', times 'HH:mm'
|
|
18
18
|
- `mode`: `'date'` (default) | `'datetime'` | `'time'`
|
|
19
|
-
- `visibleMonths`: number (default 1, clamped to 1
|
|
19
|
+
- `visibleMonths`: number (default 1, clamped to 1-3) - months side by side; ignored in 'time' mode
|
|
20
20
|
- `hourFormat`: 12 | 24 (default 24); `minuteStep`: number (default 1)
|
|
21
|
-
- `placeholder`
|
|
22
|
-
- `displayFormat`: `'pl'` (default) | `'iso'`
|
|
21
|
+
- `placeholder` - without one it falls back to `dateRange.placeholder`
|
|
22
|
+
- `displayFormat`: `'pl'` (default) | `'iso'` | `'locale'`
|
|
23
23
|
- `minDate`, `maxDate`: 'YYYY-MM-DD' bounds (inclusive); days outside are disabled
|
|
24
|
-
- `ariaLabel`
|
|
24
|
+
- `ariaLabel` - the accessible name when no `<label for>` describes the field
|
|
25
25
|
- `disabled`, `invalid`, `touched`
|
|
26
|
-
- `onTouch()`
|
|
26
|
+
- `onTouch()` - fires when the panel closes or focus leaves the closed trigger
|
|
27
27
|
- `className`, `ref` and every other `<div>` prop go to the host
|
|
28
28
|
|
|
29
29
|
## Two clicks, one band
|
|
30
30
|
The first click sets `start`, the second `end`, a third starts over; clicking before the start
|
|
31
31
|
normalizes the order rather than producing a reversed range (`pickRangeDay` in `@konce-pt/datetime`).
|
|
32
|
-
The panel stays open until the range closes
|
|
32
|
+
The panel stays open until the range closes - the second click needs somewhere to land.
|
|
33
33
|
|
|
34
34
|
With several panels the adjacent-month days become blank slots: otherwise the same date would be
|
|
35
35
|
clickable twice, and the band would paint in both places.
|
|
36
36
|
|
|
37
37
|
## Keyboard
|
|
38
38
|
As in the date picker: the trigger has `aria-haspopup="dialog"` and `aria-expanded`; `Enter`, `Space`
|
|
39
|
-
and
|
|
40
|
-
or today. The arrows, `Home`/`End` and `PageUp`/`PageDown` (with `Shift`
|
|
39
|
+
and `ArrowDown` open the panel (a `role="dialog"` named "Choose a date range") with focus on the range start,
|
|
40
|
+
or today. The arrows, `Home`/`End` and `PageUp`/`PageDown` (with `Shift` - a year) walk the days across
|
|
41
41
|
every panel, shifting the set of months when focus leaves it. `Tab` cycles inside the panel, `Escape`
|
|
42
42
|
closes it, and picking the end (or "Done") returns focus to the trigger. `Delete`/`Backspace` on the
|
|
43
43
|
trigger clears the range.
|
|
44
44
|
|
|
45
|
-
Each day is named with the full date and its role in the range ("
|
|
46
|
-
"
|
|
47
|
-
`aria-current="date"`. After the first pick a polite live region says "Start:
|
|
45
|
+
Each day is named with the full date and its role in the range ("..., start of range", "..., end of range",
|
|
46
|
+
"..., in range") - the band colour is not the only carrier. The ends have `aria-pressed`, today has
|
|
47
|
+
`aria-current="date"`. After the first pick a polite live region says "Start: ... Choose the end date.".
|
|
48
48
|
|
|
49
49
|
## The clock remounts when the end switches
|
|
50
|
-
`key={timeEnd}` on `KptClock`, so the dial returns to the hours stage after the From/To toggle
|
|
50
|
+
`key={timeEnd}` on `KptClock`, so the dial returns to the hours stage after the From/To toggle -
|
|
51
51
|
in Angular that came for free from two separate template branches.
|
|
52
52
|
|
|
53
53
|
## Examples
|
|
@@ -60,6 +60,20 @@ in Angular that came for free from two separate template branches.
|
|
|
60
60
|
Day and month names come from `Intl`; "From/To", the navigation, "Done" and the placeholder come
|
|
61
61
|
from the `dateRange`, `datepicker` and `common` namespaces.
|
|
62
62
|
|
|
63
|
+
## Week start, display format and field state
|
|
64
|
+
- The week starts by the active language (`Intl.Locale#getWeekInfo`, with a fallback list of regions):
|
|
65
|
+
en / en-US on Sunday, pl, de, en-GB on Monday. `firstDayOfWeek` (1 = Monday ... 7 = Sunday) overrides it;
|
|
66
|
+
the headers, the grid and `Home`/`End` follow it.
|
|
67
|
+
- `displayFormat`: `'pl'` (DD.MM.YYYY, default), `'iso'` (YYYY-MM-DD) or `'locale'` - order and separators
|
|
68
|
+
from `Intl` (en-US: MM/DD/YYYY). The placeholder follows the format and its letters follow the language
|
|
69
|
+
(EN `YYYY`, PL `RRRR`, the `datepicker.yearToken`/`monthToken`/`dayToken` keys). AM/PM come from `Intl`.
|
|
70
|
+
- The field is `role="combobox"` with `aria-haspopup="dialog"` (the APG select-only combobox), so it carries
|
|
71
|
+
`aria-required` (`required`), `aria-readonly` (`readOnly` - the value shows, the panel does not open,
|
|
72
|
+
there is no clear button) and `aria-invalid`.
|
|
73
|
+
- Turning the page with < > is announced (`aria-live="polite"`); the title buttons are named
|
|
74
|
+
"October, Choose month" - the visible text first (WCAG 2.5.3). Clearing the value counts as a touch.
|
|
75
|
+
- "Today" is computed on every open, so a panel opened after midnight marks the right day.
|
|
76
|
+
|
|
63
77
|
## Label and description
|
|
64
78
|
`id` goes to the focusable element, not the host; without one it comes from `KptFormField` or is
|
|
65
79
|
generated. A `div` with a role is not named by `label[for]`, so inside `KptFormField` it gets
|
|
@@ -71,7 +85,7 @@ The field `--kpt-form-field-*`; the calendar `--kpt-color-surface-raised`, the r
|
|
|
71
85
|
`--kpt-color-primary`.
|
|
72
86
|
|
|
73
87
|
## Accessibility
|
|
74
|
-
The trigger is `role="
|
|
88
|
+
The trigger is `role="combobox"` with `aria-haspopup="dialog"`, `aria-expanded` and `aria-controls`;
|
|
75
89
|
the panel is a named `role="dialog"`; the days are real buttons named with the date and their range
|
|
76
90
|
role, and the time ends are switched with a two-button toggle rather than a custom control. The
|
|
77
91
|
keyboard is described above.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ComponentPropsWithRef } from 'react';
|
|
2
|
-
import { type KptCalendarView, type KptDateSelectionMode } from '@konce-pt/datetime';
|
|
2
|
+
import { type KptCalendarView, type KptDateDisplayFormat, type KptDateSelectionMode, type KptFirstDayOfWeek } from '@konce-pt/datetime';
|
|
3
3
|
import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
|
|
4
4
|
export type { KptDateSelectionMode as KptDatepickerMode, KptCalendarView as KptDatepickerView };
|
|
5
5
|
export interface KptDatepickerProps extends Omit<ComponentPropsWithRef<'div'>, 'onChange' | 'defaultValue'>, KptI18nOverrides {
|
|
@@ -15,34 +15,48 @@ export interface KptDatepickerProps extends Omit<ComponentPropsWithRef<'div'>, '
|
|
|
15
15
|
placeholder?: string;
|
|
16
16
|
/** Prezentacja miesiąca w trybie 'month' i w etykietach: słownie czy liczbą. */
|
|
17
17
|
monthDisplay?: 'long' | 'number';
|
|
18
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Zapis daty: `'pl'` (DD.MM.RRRR, domyślnie), `'iso'` albo `'locale'` - kolejność i separatory
|
|
20
|
+
* z `Intl` dla aktywnego języka. Placeholder idzie za formatem, a jego litery za językiem.
|
|
21
|
+
*/
|
|
22
|
+
displayFormat?: KptDateDisplayFormat;
|
|
23
|
+
/** Pierwszy dzień tygodnia (1 = poniedziałek ... 7 = niedziela); `null` = wg aktywnego języka. */
|
|
24
|
+
firstDayOfWeek?: KptFirstDayOfWeek | null;
|
|
19
25
|
hourFormat?: 12 | 24;
|
|
20
26
|
minuteStep?: number;
|
|
21
|
-
/** Stan panelu
|
|
27
|
+
/** Stan panelu - pozwala otworzyć kalendarz z zewnątrz i wiedzieć, kiedy wybór się skończył. */
|
|
22
28
|
open?: boolean;
|
|
23
29
|
onOpenChange?: (open: boolean) => void;
|
|
24
30
|
/** Nazwa dostępna, gdy pola nie opisuje `<label for>`. */
|
|
25
31
|
ariaLabel?: string | null;
|
|
26
|
-
/** Id pola (nie hosta); bez niego generowane, w `KptFormField`
|
|
32
|
+
/** Id pola (nie hosta); bez niego generowane, w `KptFormField` - z wrappera. */
|
|
27
33
|
id?: string;
|
|
28
34
|
disabled?: boolean;
|
|
35
|
+
/** Tylko do odczytu - wartość widać, panel się nie otwiera (`aria-readonly`). */
|
|
36
|
+
readOnly?: boolean;
|
|
37
|
+
/** Pole wymagane - `aria-required`. */
|
|
38
|
+
required?: boolean;
|
|
29
39
|
invalid?: boolean;
|
|
30
40
|
touched?: boolean;
|
|
31
41
|
onTouch?: () => void;
|
|
32
42
|
}
|
|
33
43
|
/**
|
|
34
44
|
* Wybór daty i godziny z własnym kalendarzem. Panel jest stosem widoków
|
|
35
|
-
* dekady
|
|
45
|
+
* dekady -> lata -> miesiące -> dni: klik w komórkę schodzi poziom niżej, klik w tytuł wchodzi wyżej.
|
|
36
46
|
*
|
|
37
|
-
* Klawiatura według wzorca WAI-ARIA
|
|
47
|
+
* Klawiatura według wzorca WAI-ARIA "date picker dialog": `Enter`/`Spacja`/`ArrowDown` na polu otwierają
|
|
38
48
|
* kalendarz i przenoszą fokus na wybrany (albo dzisiejszy) dzień. W siatce dni strzałki chodzą
|
|
39
49
|
* o dzień i tydzień, `Home`/`End` na początek i koniec tygodnia, `PageUp`/`PageDown` o miesiąc
|
|
40
|
-
* (z `Shift`
|
|
50
|
+
* (z `Shift` - o rok); w siatkach miesięcy, lat i dekad strzałki chodzą po komórkach. `Tab` krąży
|
|
41
51
|
* w panelu, `Escape` zamyka go, a wybór i zamknięcie oddają fokus polu. `Delete`/`Backspace` na polu
|
|
42
52
|
* czyści wartość.
|
|
43
53
|
*
|
|
54
|
+
* Pole to `role="combobox"` z `aria-haspopup="dialog"`, więc niesie `aria-required`,
|
|
55
|
+
* `aria-readonly` i `aria-invalid`. Tydzień zaczyna się wg aktywnego języka, chyba że podano
|
|
56
|
+
* `firstDayOfWeek`; przewinięcie strony strzałką < > jest ogłaszane.
|
|
57
|
+
*
|
|
44
58
|
* @example
|
|
45
59
|
* <KptDatepicker value={date} onValueChange={setDate} startView="decade" minDate="1920-01-01" />
|
|
46
60
|
* <KptDatepicker selectionMode="datetime" hourFormat={12} value={at} onValueChange={setAt} />
|
|
47
61
|
*/
|
|
48
|
-
export declare function KptDatepicker({ value, defaultValue, onValueChange, selectionMode, startView, minDate, maxDate, placeholder, monthDisplay, displayFormat, hourFormat, minuteStep, open, onOpenChange, ariaLabel, id, disabled, invalid, touched, onTouch, locale, dictionary, className, ...rest }: Readonly<KptDatepickerProps>): import("react").JSX.Element;
|
|
62
|
+
export declare function KptDatepicker({ value, defaultValue, onValueChange, selectionMode, startView, minDate, maxDate, placeholder, monthDisplay, displayFormat, firstDayOfWeek, hourFormat, minuteStep, open, onOpenChange, ariaLabel, id, disabled, readOnly, required, invalid, touched, onTouch, locale, dictionary, className, ...rest }: Readonly<KptDatepickerProps>): import("react").JSX.Element;
|