@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,11 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
import { useRef, useState } from 'react';
|
|
3
4
|
import { cn } from "../internal/cn.js";
|
|
4
5
|
import { useControllableState } from "../internal/use-controllable-state.js";
|
|
5
6
|
import { useKptMessages } from "../i18n/i18n-context.js";
|
|
6
7
|
import { KptIcon } from "../icon/icon.js";
|
|
8
|
+
import { useKptFieldA11y } from "../form-field/form-field-context.js";
|
|
7
9
|
const EMPTY = [];
|
|
8
|
-
/** Rozmiar pliku w KB albo MB
|
|
10
|
+
/** Rozmiar pliku w KB albo MB - bez bibliotek, bo to jedna reguła. */
|
|
9
11
|
function formatSize(file) {
|
|
10
12
|
const kb = file.size / 1024;
|
|
11
13
|
return kb < 1024 ? `${kb.toFixed(0)} KB` : `${(kb / 1024).toFixed(1)} MB`;
|
|
@@ -19,24 +21,30 @@ function fileIcon(file) {
|
|
|
19
21
|
* Wartością jest tablica `File`.
|
|
20
22
|
*
|
|
21
23
|
* Strefa to `role="button"` z jednym przystankiem Tab: `Enter` i spacja otwierają okno wyboru,
|
|
22
|
-
* tak jak kliknięcie
|
|
24
|
+
* tak jak kliknięcie - natywne pole pliku jest ukryte, więc bez tego klawiatura nie miałaby
|
|
23
25
|
* jak wybrać pliku. `disabled` wyjmuje strefę z kolejności Tab. Stan błędu: `invalid`
|
|
24
26
|
* i `touched` (pominięty `touched` = błąd widać od razu, jak w `KptInput`).
|
|
25
27
|
*
|
|
26
28
|
* @example
|
|
27
29
|
* <KptFileUpload value={files} onValueChange={setFiles} accept="image/*" multiple />
|
|
28
30
|
*/
|
|
29
|
-
export function KptFileUpload({ value, defaultValue = EMPTY, onValueChange, accept = '', multiple = false, disabled = false, invalid = false, touched, onTouch, locale, dictionary, className, ...rest }) {
|
|
31
|
+
export function KptFileUpload({ value, defaultValue = EMPTY, onValueChange, accept = '', multiple = false, disabled = false, readOnly = false, id, ariaLabel = null, invalid = false, touched, onTouch, locale, dictionary, className, ...rest }) {
|
|
30
32
|
const { t } = useKptMessages({ locale, dictionary });
|
|
31
33
|
const inputRef = useRef(null);
|
|
34
|
+
const zoneRef = useRef(null);
|
|
35
|
+
/** `div` z rolą nie dostaje nazwy z `label[for]` - stąd `aria-labelledby` na etykietę wrappera. */
|
|
36
|
+
const field = useKptFieldA11y(id, 'kpt-file-upload');
|
|
37
|
+
// Podpowiedź rozcięta w miejscu `{action}` - pogrubienie robi JSX, nie HTML ze słownika.
|
|
38
|
+
const [hintBefore = '', hintAfter = ''] = t('fileUpload.hint').split('{action}');
|
|
39
|
+
const locked = disabled || readOnly;
|
|
32
40
|
const [current, setCurrent] = useControllableState({ value, defaultValue, onChange: onValueChange });
|
|
33
41
|
const [dragover, setDragover] = useState(false);
|
|
34
42
|
const showError = invalid && (touched ?? true);
|
|
35
43
|
const openPicker = () => {
|
|
36
|
-
if (!
|
|
44
|
+
if (!locked)
|
|
37
45
|
inputRef.current?.click();
|
|
38
46
|
};
|
|
39
|
-
/** `Enter` / spacja na strefie
|
|
47
|
+
/** `Enter` / spacja na strefie - spacja bez `preventDefault` przewinęłaby stronę. */
|
|
40
48
|
const onZoneKeyDown = (event) => {
|
|
41
49
|
if (event.key !== 'Enter' && event.key !== ' ')
|
|
42
50
|
return;
|
|
@@ -52,20 +60,23 @@ export function KptFileUpload({ value, defaultValue = EMPTY, onValueChange, acce
|
|
|
52
60
|
};
|
|
53
61
|
const onSelect = (event) => {
|
|
54
62
|
addFiles(event.target.files);
|
|
55
|
-
// Czyszczenie pola pozwala wybrać ten sam plik drugi raz
|
|
63
|
+
// Czyszczenie pola pozwala wybrać ten sam plik drugi raz - inaczej `change` by nie poleciał.
|
|
56
64
|
event.target.value = '';
|
|
57
65
|
};
|
|
58
|
-
return (_jsxs("div", { className: cn('kpt-file-upload-host', className), ...rest, children: [_jsxs("div", { className: cn('kpt-file-upload__zone', dragover && 'is-dragover', disabled && 'is-disabled'), role: "button", tabIndex: disabled ? -1 : 0, "aria-disabled":
|
|
66
|
+
return (_jsxs("div", { className: cn('kpt-file-upload-host', className), ...rest, children: [_jsxs("div", { className: cn('kpt-file-upload__zone', dragover && 'is-dragover', disabled && 'is-disabled'), ref: zoneRef, role: "button", id: field.id, tabIndex: disabled ? -1 : 0, "aria-disabled": locked || undefined, "aria-label": ariaLabel ?? undefined, "aria-labelledby": ariaLabel ? undefined : field.labelledBy, "aria-describedby": field.describedBy, "data-invalid": showError ? '' : undefined, onClick: openPicker, onKeyDown: onZoneKeyDown, onDragOver: (event) => {
|
|
59
67
|
event.preventDefault();
|
|
60
|
-
if (!
|
|
68
|
+
if (!locked)
|
|
61
69
|
setDragover(true);
|
|
62
70
|
}, onDragLeave: () => setDragover(false), onDrop: (event) => {
|
|
63
71
|
event.preventDefault();
|
|
64
72
|
setDragover(false);
|
|
65
|
-
if (!
|
|
73
|
+
if (!locked)
|
|
66
74
|
addFiles(event.dataTransfer?.files);
|
|
67
|
-
}, children: [_jsx("input", { ref: inputRef, type: "file", hidden: true, accept: accept, multiple: multiple, onChange: onSelect }), _jsx(KptIcon, { name: "upload", className: "kpt-file-upload__icon" }),
|
|
75
|
+
}, children: [_jsx("input", { ref: inputRef, type: "file", hidden: true, accept: accept, multiple: multiple, onChange: onSelect }), _jsx(KptIcon, { name: "upload", className: "kpt-file-upload__icon" }), _jsxs("div", { className: "kpt-file-upload__text", children: [hintBefore, _jsx("strong", { children: t('fileUpload.hintAction') }), hintAfter] }), accept ? _jsx("div", { className: "kpt-file-upload__hint", children: accept }) : null] }), current.length ? (_jsx("ul", { className: "kpt-file-upload__list", children: current.map((file, index) => (_jsxs("li", { className: "kpt-file-upload__file", children: [_jsx(KptIcon, { name: fileIcon(file) }), _jsx("span", { className: "kpt-file-upload__name", children: file.name }), _jsx("span", { className: "kpt-file-upload__size", children: formatSize(file) }), readOnly ? null : (_jsx("button", { type: "button", className: "kpt-file-upload__remove", "aria-label": `${t('fileUpload.remove')}: ${file.name}`, onClick: (event) => {
|
|
68
76
|
event.stopPropagation();
|
|
69
77
|
setCurrent(current.filter((item) => item !== file));
|
|
70
|
-
|
|
78
|
+
onTouch?.();
|
|
79
|
+
// Przycisk znika razem z pozycją - fokus wraca na strefę, a nie spada na <body>.
|
|
80
|
+
zoneRef.current?.focus();
|
|
81
|
+
}, children: _jsx(KptIcon, { name: "trash" }) }))] }, `${index}-${file.name}`))) })) : null] }));
|
|
71
82
|
}
|
|
@@ -8,19 +8,19 @@ Import: `import { KptFileUpload } from '@konce-pt/react';`
|
|
|
8
8
|
<div class="kpt-file-upload-host">
|
|
9
9
|
<div class="kpt-file-upload__zone is-dragover" role="button" tabindex="0">
|
|
10
10
|
<input type="file" hidden>
|
|
11
|
-
<span class="kpt-icon-host kpt-file-upload__icon"
|
|
11
|
+
<span class="kpt-icon-host kpt-file-upload__icon">...</span>
|
|
12
12
|
<div class="kpt-file-upload__text"><strong>Click</strong> or drag files here</div>
|
|
13
13
|
<div class="kpt-file-upload__hint">image/*</div>
|
|
14
14
|
</div>
|
|
15
15
|
<ul class="kpt-file-upload__list">
|
|
16
|
-
<li class="kpt-file-upload__file"
|
|
16
|
+
<li class="kpt-file-upload__file">...name, size, remove...</li>
|
|
17
17
|
</ul>
|
|
18
18
|
</div>
|
|
19
19
|
|
|
20
20
|
## Props
|
|
21
|
-
- `value` / `defaultValue` / `onValueChange`
|
|
22
|
-
- `accept`: string (e.g. `'image/*'`)
|
|
23
|
-
- `multiple`: boolean
|
|
21
|
+
- `value` / `defaultValue` / `onValueChange` - the `File[]`
|
|
22
|
+
- `accept`: string (e.g. `'image/*'`) - the native picker filter, also shown under the zone
|
|
23
|
+
- `multiple`: boolean - off, only the first file is kept
|
|
24
24
|
- `disabled`, `invalid`, `touched`, `onTouch()`
|
|
25
25
|
- `className`, `ref` and every other `<div>` prop go to the host
|
|
26
26
|
|
|
@@ -28,9 +28,9 @@ Import: `import { KptFileUpload } from '@konce-pt/react';`
|
|
|
28
28
|
`event.target.value = ''` after reading the files, otherwise picking the same file twice in a row
|
|
29
29
|
would fire no `change` and the second pick would be silently lost.
|
|
30
30
|
|
|
31
|
-
## The hint
|
|
32
|
-
`fileUpload.hint` holds
|
|
33
|
-
|
|
31
|
+
## The hint is plain text
|
|
32
|
+
`fileUpload.hint` holds an `{action}` placeholder that is replaced by `fileUpload.hintAction` in
|
|
33
|
+
`<strong>`. Dictionaries carry no HTML, so a translation from a CMS cannot inject markup.
|
|
34
34
|
|
|
35
35
|
## Examples
|
|
36
36
|
<KptFileUpload value={files} onValueChange={setFiles} accept="image/*" multiple />
|
|
@@ -56,4 +56,7 @@ focus ring `--kpt-color-focus-ring`.
|
|
|
56
56
|
|
|
57
57
|
## Accessibility
|
|
58
58
|
The remove button is labelled from the dictionary. The zone itself is the keyboard path to the
|
|
59
|
-
system picker
|
|
59
|
+
system picker - see "Keyboard and states" above.
|
|
60
|
+
|
|
61
|
+
## Read-only and required
|
|
62
|
+
`readOnly` shows the list without the remove buttons and does not open the picker nor accept a drop. The zone takes `id` and `ariaLabel` and is linked to `kpt-form-field` (label and description); `button` accepts neither `aria-invalid` nor `aria-required`, so the error is the linked message. The hint is plain text: `fileUpload.hint` with `{action}` and `fileUpload.hintAction` (bold) - dictionaries no longer carry HTML. The remove button names the file.
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
* zbudowany na liście) zgłaszają je przez `useKptFormFieldFilled`.
|
|
7
7
|
*/
|
|
8
8
|
export interface KptFormFieldContextValue {
|
|
9
|
-
/** Id, którym wrapper wiąże `label[for]`
|
|
9
|
+
/** Id, którym wrapper wiąże `label[for]` - kontrolka bez własnego `id` nadaje je swojemu elementowi. */
|
|
10
10
|
controlId: string;
|
|
11
11
|
/** Id elementu etykiety albo `undefined`, gdy wrapper jej nie pokazuje. */
|
|
12
12
|
labelId: string | undefined;
|
|
13
13
|
/** Id widocznego komunikatu (błąd albo podpowiedź) albo `undefined`. */
|
|
14
14
|
describedBy: string | undefined;
|
|
15
|
-
/** Kontrolka z własnym `id` zgłasza je wrapperowi
|
|
15
|
+
/** Kontrolka z własnym `id` zgłasza je wrapperowi - na nie wskaże `label[for]`. */
|
|
16
16
|
reportControlId: (id: string | null) => void;
|
|
17
17
|
/** Czy pole jest oznaczone jako nieprawidłowe (niepusty `error` na wrapperze). */
|
|
18
18
|
invalid: boolean;
|
|
@@ -32,11 +32,11 @@ export interface KptFieldA11y {
|
|
|
32
32
|
/** Id elementu fokusowalnego: własne `id`, potem `controlId` wrappera, potem wygenerowane. */
|
|
33
33
|
id: string;
|
|
34
34
|
/**
|
|
35
|
-
* Id etykiety wrappera
|
|
35
|
+
* Id etykiety wrappera - dla kontrolek na elemencie, którego `label[for]` nie nazywa
|
|
36
36
|
* (`div` z rolą, `contenteditable`). Natywne `input`/`textarea` nazywa już samo `htmlFor`.
|
|
37
37
|
*/
|
|
38
38
|
labelledBy: string | undefined;
|
|
39
|
-
/** Id podpowiedzi albo błędu wrappera
|
|
39
|
+
/** Id podpowiedzi albo błędu wrappera - do `aria-describedby`. */
|
|
40
40
|
describedBy: string | undefined;
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ComponentPropsWithRef, type ReactNode } from 'react';
|
|
2
|
+
import { type KptEnterMotion } from '@konce-pt/motion';
|
|
2
3
|
/**
|
|
3
|
-
* Wariant etykiety: `fixed` (statyczna nad kontrolką) albo Float Label
|
|
4
|
+
* Wariant etykiety: `fixed` (statyczna nad kontrolką) albo Float Label - `over`
|
|
4
5
|
* (nad obramowaniem), `in` (u góry wewnątrz pola), `on` (na obramowaniu, notch).
|
|
5
6
|
*/
|
|
6
7
|
export type KptFormFieldLabelType = 'fixed' | 'over' | 'in' | 'on';
|
|
@@ -9,7 +10,7 @@ export interface KptFormFieldProps extends Omit<ComponentPropsWithRef<'div'>, 'c
|
|
|
9
10
|
label?: string;
|
|
10
11
|
/** Podpowiedź pod kontrolką (ukrywana, gdy jest błąd). */
|
|
11
12
|
hint?: string;
|
|
12
|
-
/** Komunikat błędu
|
|
13
|
+
/** Komunikat błędu - gdy niepusty, pole jest oznaczone jako nieprawidłowe. */
|
|
13
14
|
error?: string | null;
|
|
14
15
|
/** Oznacz pole jako wymagane (gwiazdka przy etykiecie). */
|
|
15
16
|
required?: boolean;
|
|
@@ -20,11 +21,18 @@ export interface KptFormFieldProps extends Omit<ComponentPropsWithRef<'div'>, 'c
|
|
|
20
21
|
controlId?: string;
|
|
21
22
|
/** Wariant etykiety; uniesienie następuje przy focusie lub wypełnieniu pola. */
|
|
22
23
|
labelType?: KptFormFieldLabelType;
|
|
24
|
+
/**
|
|
25
|
+
* Ruch: `spring` - komunikat wjeżdża z rozmycia, pole potrząsa się, gdy staje się błędne, etykieta
|
|
26
|
+
* float unosi się na sprężynie; `fade` - komunikat się przenika; `none` - bez ruchu. Bez wartości
|
|
27
|
+
* bierze `enter` z `KptMotionProvider` (domyślnie `spring`); `enabled={false}` i systemowe
|
|
28
|
+
* "ogranicz ruch" wyłączają go zawsze.
|
|
29
|
+
*/
|
|
30
|
+
enterMotion?: KptEnterMotion;
|
|
23
31
|
children?: ReactNode;
|
|
24
32
|
}
|
|
25
33
|
/**
|
|
26
34
|
* Wrapper pola formularza: etykieta, podpowiedź i komunikat błędu wokół dowolnej kontrolki.
|
|
27
|
-
* Prezentacyjny
|
|
35
|
+
* Prezentacyjny - stan błędu przekazuje się przez `error`.
|
|
28
36
|
*
|
|
29
37
|
* Wypełnienie (sterujące uniesieniem etykiety) wrapper odczytuje z natywnego `input`/`textarea`
|
|
30
38
|
* w środku, po zdarzeniach `input`/`change` oraz z wartości początkowej. Działa więc tak samo
|
|
@@ -36,4 +44,4 @@ export interface KptFormFieldProps extends Omit<ComponentPropsWithRef<'div'>, 'c
|
|
|
36
44
|
* <KptInput type="email" name="email" />
|
|
37
45
|
* </KptFormField>
|
|
38
46
|
*/
|
|
39
|
-
export declare function KptFormField({ label, hint, error, required, controlId, labelType, className, children, ref, ...rest }: Readonly<KptFormFieldProps>): import("react").JSX.Element;
|
|
47
|
+
export declare function KptFormField({ label, hint, error, required, controlId, labelType, enterMotion, className, children, ref, ...rest }: Readonly<KptFormFieldProps>): import("react").JSX.Element;
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
|
|
3
4
|
import { cn } from "../internal/cn.js";
|
|
4
5
|
import { composeRefs } from "../internal/compose-refs.js";
|
|
5
6
|
import { useKptId } from "../internal/use-id.js";
|
|
6
7
|
import { KptFormFieldContext } from "./form-field-context.js";
|
|
8
|
+
import { playShakeMotion, resolveEnterMotion } from '@konce-pt/motion';
|
|
9
|
+
import { useKptMotion } from "../motion/motion-context.js";
|
|
7
10
|
/**
|
|
8
11
|
* Wrapper pola formularza: etykieta, podpowiedź i komunikat błędu wokół dowolnej kontrolki.
|
|
9
|
-
* Prezentacyjny
|
|
12
|
+
* Prezentacyjny - stan błędu przekazuje się przez `error`.
|
|
10
13
|
*
|
|
11
14
|
* Wypełnienie (sterujące uniesieniem etykiety) wrapper odczytuje z natywnego `input`/`textarea`
|
|
12
15
|
* w środku, po zdarzeniach `input`/`change` oraz z wartości początkowej. Działa więc tak samo
|
|
@@ -18,14 +21,32 @@ import { KptFormFieldContext } from "./form-field-context.js";
|
|
|
18
21
|
* <KptInput type="email" name="email" />
|
|
19
22
|
* </KptFormField>
|
|
20
23
|
*/
|
|
21
|
-
export function KptFormField({ label = '', hint = '', error = null, required = false, controlId = '', labelType = 'fixed', className, children, ref, ...rest }) {
|
|
24
|
+
export function KptFormField({ label = '', hint = '', error = null, required = false, controlId = '', labelType = 'fixed', enterMotion, className, children, ref, ...rest }) {
|
|
22
25
|
const hostRef = useRef(null);
|
|
26
|
+
const motion = resolveEnterMotion(enterMotion, useKptMotion());
|
|
27
|
+
const rootRef = useRef(null);
|
|
28
|
+
const controlRef = useRef(null);
|
|
29
|
+
const wasInvalid = useRef(null);
|
|
30
|
+
// Wejścia komunikatów dopiero po pierwszym renderze - błędy obecne od startu stoją. Atrybut idzie
|
|
31
|
+
// wprost na element: React nim nie zarządza, więc go nie nadpisze (klasę nadpisałby przy zmianie `error`).
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (rootRef.current)
|
|
34
|
+
rootRef.current.dataset['live'] = '';
|
|
35
|
+
}, []);
|
|
36
|
+
// Potrząśnięcie tylko przy przejściu "poprawne -> błędne", nie przy każdej zmianie treści błędu.
|
|
37
|
+
const invalid = !!error;
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const before = wasInvalid.current;
|
|
40
|
+
wasInvalid.current = invalid;
|
|
41
|
+
if (before === false && invalid && motion === 'spring' && controlRef.current)
|
|
42
|
+
playShakeMotion(controlRef.current);
|
|
43
|
+
}, [invalid, motion]);
|
|
23
44
|
const [nativeFilled, setNativeFilled] = useState(false);
|
|
24
45
|
const [reportedFilled, setReportedFilled] = useState(null);
|
|
25
46
|
const generatedId = useKptId(undefined, 'kpt-form-field-control');
|
|
26
47
|
const baseId = useKptId(undefined, 'kpt-form-field');
|
|
27
48
|
const id = controlId || generatedId;
|
|
28
|
-
// Kontrolka z własnym `id` zgłasza je przez kontekst
|
|
49
|
+
// Kontrolka z własnym `id` zgłasza je przez kontekst - wtedy `label[for]` wskazuje właśnie je.
|
|
29
50
|
const [reportedId, setReportedId] = useState(null);
|
|
30
51
|
const labelFor = controlId || reportedId || generatedId;
|
|
31
52
|
const labelId = label ? `${baseId}-label` : undefined;
|
|
@@ -36,11 +57,11 @@ export function KptFormField({ label = '', hint = '', error = null, required = f
|
|
|
36
57
|
const el = hostRef.current?.querySelector('.kpt-form-field__control input, .kpt-form-field__control textarea');
|
|
37
58
|
setNativeFilled(!!el && el.value !== '');
|
|
38
59
|
}, []);
|
|
39
|
-
// Wartość początkowa (np. pole prefill)
|
|
60
|
+
// Wartość początkowa (np. pole prefill) - po pierwszym renderze projekcji, przed malowaniem,
|
|
40
61
|
// żeby uniesiona etykieta nie przeskoczyła na oczach użytkownika.
|
|
41
62
|
useLayoutEffect(updateFilled, [updateFilled]);
|
|
42
63
|
// Kontrolowana wartość zmieniana z zewnątrz nie emituje zdarzenia `input`, więc odczyt
|
|
43
|
-
// powtarzamy po każdym renderze
|
|
64
|
+
// powtarzamy po każdym renderze - to jeden `querySelector`, nie warto tu optymalizować.
|
|
44
65
|
useEffect(updateFilled);
|
|
45
66
|
const filled = reportedFilled ?? nativeFilled;
|
|
46
67
|
const context = useMemo(() => ({
|
|
@@ -51,5 +72,5 @@ export function KptFormField({ label = '', hint = '', error = null, required = f
|
|
|
51
72
|
reportFilled: setReportedFilled,
|
|
52
73
|
reportControlId: setReportedId,
|
|
53
74
|
}), [id, labelId, describedBy, error]);
|
|
54
|
-
return (_jsx(KptFormFieldContext.Provider, { value: context, children: _jsx("div", { className: cn('kpt-form-field-host', className), ref: composeRefs(hostRef, ref), onInput: updateFilled, onChange: updateFilled, ...rest, children: _jsxs("div", { className: cn('kpt-form-field', `kpt-form-field--${labelType}`, labelType !== 'fixed' && 'kpt-form-field--float', error && 'kpt-form-field--invalid'), children: [_jsxs("div", { className: cn('kpt-form-field__box', filled && 'is-filled'), children: [label ? (_jsxs("label", { className: "kpt-form-field__label", id: labelId, htmlFor: labelFor, children: [label, required ? (_jsx("span", { className: "kpt-form-field__required", "aria-hidden": "true", children: "*" })) : null] })) : null, _jsx("div", { className: "kpt-form-field__control", children: children })] }), error ? (_jsx("p", { className: "kpt-form-field__message kpt-form-field__message--error", role: "alert", id: messageId, children: error })) : hint ? (_jsx("p", { className: "kpt-form-field__message kpt-form-field__message--hint", id: messageId, children: hint })) : null] }) }) }));
|
|
75
|
+
return (_jsx(KptFormFieldContext.Provider, { value: context, children: _jsx("div", { className: cn('kpt-form-field-host', className), ref: composeRefs(hostRef, ref), onInput: updateFilled, onChange: updateFilled, ...rest, children: _jsxs("div", { ref: rootRef, "data-motion": motion, className: cn('kpt-form-field', `kpt-form-field--${labelType}`, labelType !== 'fixed' && 'kpt-form-field--float', error && 'kpt-form-field--invalid'), children: [_jsxs("div", { className: cn('kpt-form-field__box', filled && 'is-filled'), children: [label ? (_jsxs("label", { className: "kpt-form-field__label", id: labelId, htmlFor: labelFor, children: [label, required ? (_jsx("span", { className: "kpt-form-field__required", "aria-hidden": "true", children: "*" })) : null] })) : null, _jsx("div", { ref: controlRef, className: "kpt-form-field__control", children: children })] }), error ? (_jsx("p", { className: "kpt-form-field__message kpt-form-field__message--error", role: "alert", id: messageId, children: error }, error)) : hint ? (_jsx("p", { className: "kpt-form-field__message kpt-form-field__message--hint", id: messageId, children: hint })) : null] }) }) }));
|
|
55
76
|
}
|
package/dist/form-field/llms.txt
CHANGED
|
@@ -7,30 +7,31 @@ Import: `import { KptFormField } from '@konce-pt/react';`
|
|
|
7
7
|
<div class="kpt-form-field-host">
|
|
8
8
|
<div class="kpt-form-field kpt-form-field--fixed">
|
|
9
9
|
<div class="kpt-form-field__box is-filled">
|
|
10
|
-
<label class="kpt-form-field__label" for="
|
|
11
|
-
<div class="kpt-form-field__control"
|
|
10
|
+
<label class="kpt-form-field__label" for="...">E-mail<span class="kpt-form-field__required">*</span></label>
|
|
11
|
+
<div class="kpt-form-field__control">...control...</div>
|
|
12
12
|
</div>
|
|
13
13
|
<p class="kpt-form-field__message kpt-form-field__message--hint">Company e-mail</p>
|
|
14
14
|
</div>
|
|
15
15
|
</div>
|
|
16
16
|
|
|
17
17
|
## Props
|
|
18
|
-
- `label`: string
|
|
19
|
-
- `hint`: string
|
|
20
|
-
- `error`: string | null
|
|
21
|
-
- `required`: boolean
|
|
22
|
-
- `controlId`: string
|
|
18
|
+
- `label`: string - the label text
|
|
19
|
+
- `hint`: string - a hint under the control, hidden while there is an error
|
|
20
|
+
- `error`: string | null - when non-empty the field is marked invalid
|
|
21
|
+
- `required`: boolean - an asterisk next to the label
|
|
22
|
+
- `controlId`: string - empty means the wrapper generates one and hands it to the control
|
|
23
23
|
- `labelType`: 'fixed' | 'over' | 'in' | 'on' (default 'fixed')
|
|
24
|
+
- `enterMotion`: 'spring' | 'fade' | 'none' - how the message and the error appear (default from `KptMotionProvider`, else `spring`)
|
|
24
25
|
- `className`, `ref` and every other `<div>` prop go to the host
|
|
25
26
|
|
|
26
27
|
## Label wiring
|
|
27
28
|
The wrapper generates a control id and publishes it through context, so `<KptInput>` inside needs
|
|
28
|
-
no configuration
|
|
29
|
+
no configuration - `label[for]` and `input[id]` always match. Pass `controlId` to take over; a control
|
|
29
30
|
with its own `id` reports it, and the label follows.
|
|
30
31
|
|
|
31
32
|
The context also carries the label's id and the id of the visible hint or error. Every library
|
|
32
33
|
control uses them through `useKptFieldA11y`: the hint or error lands in `aria-describedby`, and a
|
|
33
|
-
control on a `div` with a role (`KptSelect`, `KptDatepicker`, `KptRadioGroup`, `KptRichText
|
|
34
|
+
control on a `div` with a role (`KptSelect`, `KptDatepicker`, `KptRadioGroup`, `KptRichText`...) gets
|
|
34
35
|
`aria-labelledby` pointing at the label, because `label[for]` does not name it. A custom control:
|
|
35
36
|
|
|
36
37
|
const field = useKptFieldA11y(id, 'my-control');
|
|
@@ -39,7 +40,7 @@ control on a `div` with a role (`KptSelect`, `KptDatepicker`, `KptRadioGroup`, `
|
|
|
39
40
|
## Float labels
|
|
40
41
|
`labelType` other than `fixed` turns on the floating label with an animated transition: `over`
|
|
41
42
|
(above the border), `in` (top inside the field), `on` (on the border, notch). The label floats on
|
|
42
|
-
focus (CSS `:focus-within`) or when the field is filled
|
|
43
|
+
focus (CSS `:focus-within`) or when the field is filled - no placeholder required.
|
|
43
44
|
|
|
44
45
|
Filled state is read from the projected `input`/`textarea` on `input`/`change` and from the initial
|
|
45
46
|
value, so it works for controlled and uncontrolled fields alike. A control with no native field
|
|
@@ -54,11 +55,24 @@ reports it with `useKptFormFieldFilled(filled)`.
|
|
|
54
55
|
<KptInput value={over} onValueChange={setOver} />
|
|
55
56
|
</KptFormField>
|
|
56
57
|
|
|
58
|
+
## Motion
|
|
59
|
+
`enterMotion` (`spring | fade | none`):
|
|
60
|
+
- the message under the field enters on every change - hint -> error, error A -> error B - sliding in
|
|
61
|
+
from above and sharpening out of a blur (`fade`: only fades); each new error is a new element, so it
|
|
62
|
+
is also announced again;
|
|
63
|
+
- `spring` only: the control shakes briefly when the field turns invalid - not when the error text
|
|
64
|
+
changes and not for an error present on load; the floating label rises on a spring.
|
|
65
|
+
|
|
66
|
+
Messages present on the first render do not animate. With no value it takes `enter` from `KptMotionProvider`
|
|
67
|
+
(default `spring`); `enabled: false` and the system "reduce motion" setting always win. Every form
|
|
68
|
+
control's surface (border, focus ring, background) changes smoothly on hover, focus and error - a shared
|
|
69
|
+
rule, independent of this input.
|
|
70
|
+
|
|
57
71
|
## Tokens
|
|
58
72
|
`--kpt-form-field-{label,hint,error,border,border-focus,border-error,radius}` and
|
|
59
73
|
`--kpt-color-danger` for the required asterisk.
|
|
60
74
|
|
|
61
75
|
## Accessibility
|
|
62
76
|
The error message carries `role="alert"`, so a screen reader announces it as it appears. The
|
|
63
|
-
asterisk is `aria-hidden`
|
|
77
|
+
asterisk is `aria-hidden` - the required state belongs on the control (`aria-required`), not on
|
|
64
78
|
decoration.
|
|
@@ -14,12 +14,12 @@ export interface KptGalleriaProps extends Omit<ComponentPropsWithRef<'div'>, 'on
|
|
|
14
14
|
showThumbnails?: boolean;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
* Galleria
|
|
17
|
+
* Galleria - duży podgląd obrazu z paskiem miniatur i nawigacją.
|
|
18
18
|
*
|
|
19
19
|
* Klawiatura: na całej galerii strzałki w lewo/prawo przechodzą do sąsiedniego obrazu (w RTL
|
|
20
|
-
* odwrotnie), `Home`/`End`
|
|
20
|
+
* odwrotnie), `Home`/`End` - do pierwszego/ostatniego; gdy fokus stoi na miniaturze, idzie za
|
|
21
21
|
* aktywną. Miniatura ma nazwę z `alt` obrazu i `aria-current` na aktywnej, a zmiana obrazu jest
|
|
22
|
-
* ogłaszana uprzejmie (
|
|
22
|
+
* ogłaszana uprzejmie ("Obraz 2 z 4: ...") - dopiero po działaniu użytkownika, nie przy starcie.
|
|
23
23
|
*
|
|
24
24
|
* @example
|
|
25
25
|
* <KptGalleria items={photos} activeIndex={index} onActiveIndexChange={setIndex} />
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
import { useRef, useState } from 'react';
|
|
3
4
|
import { cn } from "../internal/cn.js";
|
|
@@ -7,24 +8,26 @@ import { KptIcon } from "../icon/icon.js";
|
|
|
7
8
|
/** Klawisze przechodzące między obrazami: kierunek względem bieżącego albo skrajny indeks. */
|
|
8
9
|
const NAV_KEYS = new Set(['ArrowLeft', 'ArrowRight', 'Home', 'End']);
|
|
9
10
|
/**
|
|
10
|
-
* Galleria
|
|
11
|
+
* Galleria - duży podgląd obrazu z paskiem miniatur i nawigacją.
|
|
11
12
|
*
|
|
12
13
|
* Klawiatura: na całej galerii strzałki w lewo/prawo przechodzą do sąsiedniego obrazu (w RTL
|
|
13
|
-
* odwrotnie), `Home`/`End`
|
|
14
|
+
* odwrotnie), `Home`/`End` - do pierwszego/ostatniego; gdy fokus stoi na miniaturze, idzie za
|
|
14
15
|
* aktywną. Miniatura ma nazwę z `alt` obrazu i `aria-current` na aktywnej, a zmiana obrazu jest
|
|
15
|
-
* ogłaszana uprzejmie (
|
|
16
|
+
* ogłaszana uprzejmie ("Obraz 2 z 4: ...") - dopiero po działaniu użytkownika, nie przy starcie.
|
|
16
17
|
*
|
|
17
18
|
* @example
|
|
18
19
|
* <KptGalleria items={photos} activeIndex={index} onActiveIndexChange={setIndex} />
|
|
19
20
|
*/
|
|
20
21
|
export function KptGalleria({ items = [], activeIndex, defaultActiveIndex = 0, onActiveIndexChange, showThumbnails = true, locale, dictionary, className, ...rest }) {
|
|
21
22
|
const { t } = useKptMessages({ locale, dictionary });
|
|
22
|
-
const [
|
|
23
|
+
const [requested, setActive] = useControllableState({
|
|
23
24
|
value: activeIndex,
|
|
24
25
|
defaultValue: defaultActiveIndex,
|
|
25
26
|
onChange: onActiveIndexChange,
|
|
26
27
|
});
|
|
27
|
-
//
|
|
28
|
+
// Indeks przycięty do listy: po skróceniu `items` (filtr) widok nie zostaje pusty.
|
|
29
|
+
const active = Math.min(Math.max(requested, 0), Math.max(items.length - 1, 0));
|
|
30
|
+
// Ogłoszenie dopiero po działaniu użytkownika - przy starcie region ma milczeć.
|
|
28
31
|
const [userMoved, setUserMoved] = useState(false);
|
|
29
32
|
const thumbsRef = useRef([]);
|
|
30
33
|
const rootRef = useRef(null);
|
|
@@ -47,7 +50,7 @@ export function KptGalleria({ items = [], activeIndex, defaultActiveIndex = 0, o
|
|
|
47
50
|
const target = event.key === 'Home' ? 0 : event.key === 'End' ? last : active + (rtl ? -step : step);
|
|
48
51
|
const focusOnThumb = thumbsRef.current.some((thumb) => thumb === document.activeElement);
|
|
49
52
|
const next = select(target);
|
|
50
|
-
// Fokus na miniaturze idzie za aktywnym obrazem
|
|
53
|
+
// Fokus na miniaturze idzie za aktywnym obrazem - inaczej strzałka zmieniałaby obraz,
|
|
51
54
|
// a fokus zostawał na poprzedniej miniaturze.
|
|
52
55
|
if (focusOnThumb)
|
|
53
56
|
thumbsRef.current[next]?.focus();
|
package/dist/galleria/llms.txt
CHANGED
|
@@ -7,19 +7,19 @@ Import: `import { KptGalleria, type KptGalleriaItem } from '@konce-pt/react';`
|
|
|
7
7
|
<div class="kpt-galleria-host">
|
|
8
8
|
<div class="kpt-galleria">
|
|
9
9
|
<div class="kpt-galleria__stage">
|
|
10
|
-
<button class="kpt-galleria__nav kpt-galleria__nav--prev" aria-disabled="true" aria-label="Previous"
|
|
11
|
-
<img class="kpt-galleria__image" src="
|
|
12
|
-
<button class="kpt-galleria__nav kpt-galleria__nav--next" aria-label="Next"
|
|
10
|
+
<button class="kpt-galleria__nav kpt-galleria__nav--prev" aria-disabled="true" aria-label="Previous">...</button>
|
|
11
|
+
<img class="kpt-galleria__image" src="..." alt="Mountain lake">
|
|
12
|
+
<button class="kpt-galleria__nav kpt-galleria__nav--next" aria-label="Next">...</button>
|
|
13
13
|
</div>
|
|
14
14
|
<div class="kpt-galleria__thumbs">
|
|
15
|
-
<button class="kpt-galleria__thumb is-active" aria-current="true" aria-label="Mountain lake"><img src="
|
|
15
|
+
<button class="kpt-galleria__thumb is-active" aria-current="true" aria-label="Mountain lake"><img src="..." alt=""></button>...
|
|
16
16
|
</div>
|
|
17
17
|
<span class="kpt-galleria__live" aria-live="polite">Image 2 of 4: Pine forest</span>
|
|
18
18
|
</div>
|
|
19
19
|
</div>
|
|
20
20
|
|
|
21
21
|
## Props
|
|
22
|
-
- `items`: `KptGalleriaItem[]`
|
|
22
|
+
- `items`: `KptGalleriaItem[]` - `{ src, thumbnail?, alt? }`
|
|
23
23
|
- `activeIndex` / `defaultActiveIndex` / `onActiveIndexChange`
|
|
24
24
|
- `showThumbnails`: boolean (default true)
|
|
25
25
|
- `className`, `ref` and every other `<div>` prop go to the host
|
|
@@ -48,8 +48,8 @@ The stage `--kpt-color-muted`; the active thumbnail `--kpt-color-primary`; the a
|
|
|
48
48
|
|
|
49
49
|
## Accessibility
|
|
50
50
|
The large image carries its `alt`. Each thumbnail is a button named by the item's `alt` (or
|
|
51
|
-
`galleria.image`
|
|
51
|
+
`galleria.image` - "Image 3" - when there is none), with `alt=""` on the thumbnail image so the
|
|
52
52
|
name is not read twice; the active one carries `aria-current`. The arrows use `aria-disabled` at
|
|
53
53
|
the ends instead of `disabled`, so they keep the focus. A change of image is announced politely
|
|
54
|
-
through a hidden live region
|
|
54
|
+
through a hidden live region - `galleria.position` ("Image 2 of 4") plus the `alt` - only after the
|
|
55
55
|
user acts, never on first render.
|
package/dist/grid/col.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { AsChildProps } from '../internal/types.ts';
|
|
|
3
3
|
/** Rozpiętość kolumny: liczba, `'full'` (cała szerokość) albo dowolna wartość CSS. */
|
|
4
4
|
export type KptColSpan = number | string;
|
|
5
5
|
export interface KptColProps extends ComponentPropsWithRef<'div'>, AsChildProps {
|
|
6
|
-
/** Rozpiętość kolumny
|
|
6
|
+
/** Rozpiętość kolumny - baza mobile-first. */
|
|
7
7
|
span?: KptColSpan;
|
|
8
8
|
/** Rozpiętość od breakpointa SM (>= 640px). */
|
|
9
9
|
spanSm?: KptColSpan;
|
|
@@ -15,7 +15,7 @@ export interface KptColProps extends ComponentPropsWithRef<'div'>, AsChildProps
|
|
|
15
15
|
spanXl?: KptColSpan;
|
|
16
16
|
/** Rozpiętość od breakpointa 2XL (>= 1536px). */
|
|
17
17
|
span2xl?: KptColSpan;
|
|
18
|
-
/** Numer linii, od której zaczyna się kolumna (1-based)
|
|
18
|
+
/** Numer linii, od której zaczyna się kolumna (1-based) - pozwala robić offsety. */
|
|
19
19
|
start?: number | string;
|
|
20
20
|
/** Kolejność wizualna (`order`). Nie zmienia kolejności w DOM ani dla czytników ekranu. */
|
|
21
21
|
order?: number | string;
|
|
@@ -23,10 +23,10 @@ export interface KptColProps extends ComponentPropsWithRef<'div'>, AsChildProps
|
|
|
23
23
|
self?: string;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
* Kolumna siatki `KptGrid`
|
|
26
|
+
* Kolumna siatki `KptGrid` - rozpiętość mobile-first z nadpisaniami per breakpoint.
|
|
27
27
|
*
|
|
28
28
|
* Wartość podana dla mniejszego breakpointa obowiązuje aż do następnego, który ją nadpisze:
|
|
29
|
-
* `span={12} spanLg={5}` daje 12 na mobile, tablecie i `md`, a dopiero od `lg`
|
|
29
|
+
* `span={12} spanLg={5}` daje 12 na mobile, tablecie i `md`, a dopiero od `lg` - 5.
|
|
30
30
|
*
|
|
31
31
|
* Ustawia wyłącznie custom properties inline; nie dodaje ani nie usuwa klas. Z `asChild`
|
|
32
32
|
* przejmuje Twój element, więc kolumną może być `<li>`, `<article>` czy komponent biblioteki.
|
package/dist/grid/col.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { layoutStyle, renderLayout } from "./layout.js";
|
|
2
2
|
/**
|
|
3
|
-
* Kolumna siatki `KptGrid`
|
|
3
|
+
* Kolumna siatki `KptGrid` - rozpiętość mobile-first z nadpisaniami per breakpoint.
|
|
4
4
|
*
|
|
5
5
|
* Wartość podana dla mniejszego breakpointa obowiązuje aż do następnego, który ją nadpisze:
|
|
6
|
-
* `span={12} spanLg={5}` daje 12 na mobile, tablecie i `md`, a dopiero od `lg`
|
|
6
|
+
* `span={12} spanLg={5}` daje 12 na mobile, tablecie i `md`, a dopiero od `lg` - 5.
|
|
7
7
|
*
|
|
8
8
|
* Ustawia wyłącznie custom properties inline; nie dodaje ani nie usuwa klas. Z `asChild`
|
|
9
9
|
* przejmuje Twój element, więc kolumną może być `<li>`, `<article>` czy komponent biblioteki.
|
package/dist/grid/flex.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export type KptFlexDirection = 'row' | 'row-reverse' | 'column' | 'column-revers
|
|
|
4
4
|
export type KptFlexWrap = 'wrap' | 'nowrap' | 'wrap-reverse';
|
|
5
5
|
export type KptAlignment = 'start' | 'end' | 'center' | 'stretch' | 'baseline' | 'space-between' | 'space-around' | 'space-evenly';
|
|
6
6
|
export interface KptFlexProps extends ComponentPropsWithRef<'div'>, AsChildProps {
|
|
7
|
-
/** Kierunek osi głównej
|
|
7
|
+
/** Kierunek osi głównej - baza mobile-first. */
|
|
8
8
|
direction?: KptFlexDirection;
|
|
9
9
|
/** Kierunek od breakpointa MD (>= 768px). */
|
|
10
10
|
directionMd?: KptFlexDirection;
|
|
@@ -26,11 +26,11 @@ export interface KptFlexProps extends ComponentPropsWithRef<'div'>, AsChildProps
|
|
|
26
26
|
gapX?: string;
|
|
27
27
|
/** Odstęp w pionie. */
|
|
28
28
|
gapY?: string;
|
|
29
|
-
/** Tryb kontenerowy
|
|
29
|
+
/** Tryb kontenerowy - zmienne dzieci reagują na szerokość tego kontenera. */
|
|
30
30
|
container?: boolean;
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* Kontener flexbox Koncept UI
|
|
33
|
+
* Kontener flexbox Koncept UI - te same zmienne i breakpointy co `KptGrid`.
|
|
34
34
|
* Dla wartości bez odpowiednika w propsach (`grow`, `shrink`, `order` na dziecku)
|
|
35
35
|
* używa się klas utility: `kpt-grow-1`, `kpt-order-first`, `kpt-self-end`.
|
|
36
36
|
*
|
package/dist/grid/flex.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { cn } from "../internal/cn.js";
|
|
2
2
|
import { layoutStyle, renderLayout } from "./layout.js";
|
|
3
3
|
/**
|
|
4
|
-
* Kontener flexbox Koncept UI
|
|
4
|
+
* Kontener flexbox Koncept UI - te same zmienne i breakpointy co `KptGrid`.
|
|
5
5
|
* Dla wartości bez odpowiednika w propsach (`grow`, `shrink`, `order` na dziecku)
|
|
6
6
|
* używa się klas utility: `kpt-grow-1`, `kpt-order-first`, `kpt-self-end`.
|
|
7
7
|
*
|
package/dist/grid/grid.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentPropsWithRef } from 'react';
|
|
2
2
|
import type { AsChildProps } from '../internal/types.ts';
|
|
3
3
|
export interface KptGridProps extends ComponentPropsWithRef<'div'>, AsChildProps {
|
|
4
|
-
/** Liczba kolumn
|
|
4
|
+
/** Liczba kolumn - baza mobile-first. Domyślnie 12 (z CSS). */
|
|
5
5
|
columns?: number;
|
|
6
6
|
/** Liczba kolumn od breakpointa SM (>= 640px). */
|
|
7
7
|
columnsSm?: number;
|
|
@@ -15,25 +15,25 @@ export interface KptGridProps extends ComponentPropsWithRef<'div'>, AsChildProps
|
|
|
15
15
|
columns2xl?: number;
|
|
16
16
|
/** Odstęp w obu osiach, np. `'1.5rem'` albo `'var(--kpt-space-6)'`. */
|
|
17
17
|
gap?: string;
|
|
18
|
-
/** Odstęp między kolumnami
|
|
18
|
+
/** Odstęp między kolumnami - nadpisuje `gap` w poziomie. */
|
|
19
19
|
gapX?: string;
|
|
20
|
-
/** Odstęp między wierszami
|
|
20
|
+
/** Odstęp między wierszami - nadpisuje `gap` w pionie. */
|
|
21
21
|
gapY?: string;
|
|
22
22
|
/**
|
|
23
23
|
* Tryb kontenerowy: spany dzieci reagują na szerokość TEJ siatki, nie okna.
|
|
24
|
-
* Liczba kolumn i odstępy nadal idą za viewportem
|
|
24
|
+
* Liczba kolumn i odstępy nadal idą za viewportem - `@container` nie potrafi
|
|
25
25
|
* odpytać elementu o jego własny kontener.
|
|
26
26
|
*/
|
|
27
27
|
container?: boolean;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
* Siatka Koncept UI
|
|
30
|
+
* Siatka Koncept UI - CSS Grid sterowany custom properties z `@konce-pt/grid`.
|
|
31
31
|
*
|
|
32
32
|
* Odpowiednik dyrektywy `kptGrid` z portu Angulara. Dyrektyw w Reakcie nie ma, więc siatka jest
|
|
33
|
-
* komponentem
|
|
33
|
+
* komponentem - ale takim, który w trybie `asChild` niczego nie dokłada do DOM: przejmuje element,
|
|
34
34
|
* który i tak renderujesz (`<section>`, `<ul>`, `<main>`).
|
|
35
35
|
*
|
|
36
|
-
* Zmiana `columns` nie manipuluje klasami
|
|
36
|
+
* Zmiana `columns` nie manipuluje klasami - ustawia zmienną inline, a układ przelicza
|
|
37
37
|
* natywny silnik CSS.
|
|
38
38
|
*
|
|
39
39
|
* Wymaga arkusza `@konce-pt/grid` (`import '@konce-pt/grid';`).
|
package/dist/grid/grid.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { cn } from "../internal/cn.js";
|
|
2
2
|
import { layoutStyle, renderLayout } from "./layout.js";
|
|
3
3
|
/**
|
|
4
|
-
* Siatka Koncept UI
|
|
4
|
+
* Siatka Koncept UI - CSS Grid sterowany custom properties z `@konce-pt/grid`.
|
|
5
5
|
*
|
|
6
6
|
* Odpowiednik dyrektywy `kptGrid` z portu Angulara. Dyrektyw w Reakcie nie ma, więc siatka jest
|
|
7
|
-
* komponentem
|
|
7
|
+
* komponentem - ale takim, który w trybie `asChild` niczego nie dokłada do DOM: przejmuje element,
|
|
8
8
|
* który i tak renderujesz (`<section>`, `<ul>`, `<main>`).
|
|
9
9
|
*
|
|
10
|
-
* Zmiana `columns` nie manipuluje klasami
|
|
10
|
+
* Zmiana `columns` nie manipuluje klasami - ustawia zmienną inline, a układ przelicza
|
|
11
11
|
* natywny silnik CSS.
|
|
12
12
|
*
|
|
13
13
|
* Wymaga arkusza `@konce-pt/grid` (`import '@konce-pt/grid';`).
|
package/dist/grid/layout.d.ts
CHANGED
|
@@ -10,9 +10,9 @@ export type KptLayoutValue = number | string | undefined;
|
|
|
10
10
|
*/
|
|
11
11
|
export declare function layoutStyle(vars: Readonly<Record<string, KptLayoutValue>>, style: CSSProperties | undefined): CSSProperties;
|
|
12
12
|
/**
|
|
13
|
-
* Renderuje element układu albo
|
|
13
|
+
* Renderuje element układu albo - w trybie `asChild` - oddaje propsy jedynemu dziecku.
|
|
14
14
|
*
|
|
15
|
-
* To reactowy odpowiednik dyrektywy: `<KptCol asChild><li
|
|
15
|
+
* To reactowy odpowiednik dyrektywy: `<KptCol asChild><li>...</li></KptCol>` nie dokłada żadnego
|
|
16
16
|
* elementu do DOM, dokładnie jak `<li kptCol="6">` w Angularze.
|
|
17
17
|
*/
|
|
18
18
|
export declare function renderLayout(asChild: boolean, children: ReactNode, props: Record<string, unknown>, element: 'div' | 'span'): ReactElement;
|