@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.
Files changed (382) hide show
  1. package/README.md +128 -64
  2. package/dist/accordion/accordion.d.ts +14 -6
  3. package/dist/accordion/accordion.js +25 -17
  4. package/dist/accordion/llms.txt +22 -10
  5. package/dist/alert/alert.d.ts +2 -2
  6. package/dist/alert/alert.js +3 -2
  7. package/dist/alert/llms.txt +10 -9
  8. package/dist/app-shell/app-shell.d.ts +14 -14
  9. package/dist/app-shell/app-shell.js +22 -15
  10. package/dist/app-shell/llms.txt +16 -15
  11. package/dist/auth/auth-types.d.ts +6 -6
  12. package/dist/auth/auth.d.ts +2 -2
  13. package/dist/auth/auth.js +24 -15
  14. package/dist/auth/llms.txt +12 -11
  15. package/dist/autocomplete/autocomplete.d.ts +19 -6
  16. package/dist/autocomplete/autocomplete.js +32 -11
  17. package/dist/autocomplete/llms.txt +19 -5
  18. package/dist/avatar/avatar.d.ts +6 -6
  19. package/dist/avatar/avatar.js +6 -5
  20. package/dist/avatar/llms.txt +10 -10
  21. package/dist/avatar-group/avatar-group.d.ts +4 -4
  22. package/dist/avatar-group/avatar-group.js +4 -3
  23. package/dist/avatar-group/llms.txt +8 -8
  24. package/dist/backdrop/backdrop.d.ts +7 -26
  25. package/dist/backdrop/backdrop.js +32 -27
  26. package/dist/backdrop/llms.txt +27 -27
  27. package/dist/badge/badge.d.ts +3 -3
  28. package/dist/badge/badge.js +1 -1
  29. package/dist/badge/llms.txt +11 -11
  30. package/dist/bottom-sheet/bottom-sheet.d.ts +8 -3
  31. package/dist/bottom-sheet/bottom-sheet.js +5 -4
  32. package/dist/bottom-sheet/llms.txt +11 -8
  33. package/dist/breadcrumb/breadcrumb.d.ts +8 -2
  34. package/dist/breadcrumb/breadcrumb.js +11 -3
  35. package/dist/breadcrumb/llms.txt +10 -2
  36. package/dist/button/button.d.ts +3 -3
  37. package/dist/button/button.js +10 -9
  38. package/dist/button/llms.txt +27 -19
  39. package/dist/button-group/button-group.d.ts +18 -5
  40. package/dist/button-group/button-group.js +54 -6
  41. package/dist/button-group/llms.txt +27 -18
  42. package/dist/card/card.d.ts +8 -8
  43. package/dist/card/card.js +10 -9
  44. package/dist/card/llms.txt +20 -20
  45. package/dist/carousel/carousel.d.ts +6 -6
  46. package/dist/carousel/carousel.js +8 -5
  47. package/dist/carousel/llms.txt +10 -10
  48. package/dist/charts/chart-legend.d.ts +3 -3
  49. package/dist/charts/chart-legend.js +2 -1
  50. package/dist/charts/chart-tooltip.d.ts +3 -3
  51. package/dist/charts/chart-tooltip.js +1 -1
  52. package/dist/charts/chart.d.ts +4 -3
  53. package/dist/charts/chart.js +18 -10
  54. package/dist/charts/llms.txt +10 -7
  55. package/dist/charts-entry/public-api.js +2 -2
  56. package/dist/chat/chat.d.ts +17 -10
  57. package/dist/chat/chat.js +77 -23
  58. package/dist/chat/llms.txt +39 -15
  59. package/dist/chat-composer/chat-composer.d.ts +20 -7
  60. package/dist/chat-composer/chat-composer.js +29 -7
  61. package/dist/chat-composer/llms.txt +20 -11
  62. package/dist/chat-dock/chat-dock.d.ts +11 -4
  63. package/dist/chat-dock/chat-dock.js +10 -6
  64. package/dist/chat-dock/llms.txt +15 -14
  65. package/dist/chat-entry/public-api.js +1 -1
  66. package/dist/chat-message/chat-message.d.ts +12 -5
  67. package/dist/chat-message/chat-message.js +19 -8
  68. package/dist/chat-message/llms.txt +16 -15
  69. package/dist/chat-typing/chat-typing.d.ts +2 -2
  70. package/dist/chat-typing/chat-typing.js +4 -3
  71. package/dist/chat-typing/llms.txt +6 -6
  72. package/dist/checkbox/checkbox.d.ts +13 -6
  73. package/dist/checkbox/checkbox.js +31 -5
  74. package/dist/checkbox/llms.txt +26 -11
  75. package/dist/chip/chip.d.ts +4 -4
  76. package/dist/chip/chip.js +3 -2
  77. package/dist/chip/llms.txt +11 -11
  78. package/dist/chips-input/chips-input.d.ts +6 -4
  79. package/dist/chips-input/chips-input.js +47 -12
  80. package/dist/chips-input/llms.txt +18 -8
  81. package/dist/clock/clock.d.ts +11 -6
  82. package/dist/clock/clock.js +38 -8
  83. package/dist/clock/llms.txt +12 -8
  84. package/dist/color-picker/color-picker.d.ts +9 -5
  85. package/dist/color-picker/color-picker.js +37 -18
  86. package/dist/color-picker/llms.txt +8 -5
  87. package/dist/confirm/confirm-container.d.ts +3 -3
  88. package/dist/confirm/confirm-container.js +6 -5
  89. package/dist/confirm/confirm-store.d.ts +4 -4
  90. package/dist/confirm/confirm-store.js +11 -5
  91. package/dist/confirm/llms.txt +8 -7
  92. package/dist/context-menu/context-menu.d.ts +1 -1
  93. package/dist/context-menu/context-menu.js +37 -14
  94. package/dist/context-menu/llms.txt +10 -7
  95. package/dist/data-table/data-table-types.d.ts +5 -5
  96. package/dist/data-table/data-table.d.ts +37 -5
  97. package/dist/data-table/data-table.js +426 -119
  98. package/dist/data-table/export-csv.d.ts +3 -3
  99. package/dist/data-table/export-csv.js +8 -10
  100. package/dist/data-table/llms.txt +127 -79
  101. package/dist/data-view/data-view.d.ts +13 -5
  102. package/dist/data-view/data-view.js +68 -6
  103. package/dist/data-view/llms.txt +29 -10
  104. package/dist/date-range/date-range.d.ts +20 -8
  105. package/dist/date-range/date-range.js +86 -63
  106. package/dist/date-range/llms.txt +32 -18
  107. package/dist/datepicker/datepicker.d.ts +22 -8
  108. package/dist/datepicker/datepicker.js +103 -71
  109. package/dist/datepicker/llms.txt +36 -22
  110. package/dist/dialog/dialog.d.ts +4 -4
  111. package/dist/dialog/dialog.js +32 -11
  112. package/dist/dialog/llms.txt +13 -10
  113. package/dist/divider/divider.d.ts +7 -1
  114. package/dist/divider/divider.js +3 -2
  115. package/dist/divider/llms.txt +4 -3
  116. package/dist/drawer/drawer.d.ts +9 -4
  117. package/dist/drawer/drawer.js +5 -4
  118. package/dist/drawer/llms.txt +13 -10
  119. package/dist/empty/empty.d.ts +2 -2
  120. package/dist/empty/empty.js +1 -1
  121. package/dist/empty/llms.txt +9 -9
  122. package/dist/fab/fab.d.ts +1 -1
  123. package/dist/fab/fab.js +1 -1
  124. package/dist/fab/llms.txt +10 -6
  125. package/dist/fieldset/fieldset.d.ts +18 -4
  126. package/dist/fieldset/fieldset.js +12 -6
  127. package/dist/fieldset/llms.txt +26 -9
  128. package/dist/file-upload/file-upload.d.ts +8 -2
  129. package/dist/file-upload/file-upload.js +22 -11
  130. package/dist/file-upload/llms.txt +12 -9
  131. package/dist/form-field/form-field-context.d.ts +4 -4
  132. package/dist/form-field/form-field.d.ts +12 -4
  133. package/dist/form-field/form-field.js +27 -6
  134. package/dist/form-field/llms.txt +25 -11
  135. package/dist/galleria/galleria.d.ts +3 -3
  136. package/dist/galleria/galleria.js +9 -6
  137. package/dist/galleria/llms.txt +7 -7
  138. package/dist/grid/col.d.ts +4 -4
  139. package/dist/grid/col.js +2 -2
  140. package/dist/grid/flex.d.ts +3 -3
  141. package/dist/grid/flex.js +1 -1
  142. package/dist/grid/grid.d.ts +7 -7
  143. package/dist/grid/grid.js +3 -3
  144. package/dist/grid/layout.d.ts +2 -2
  145. package/dist/grid/layout.js +2 -2
  146. package/dist/grid/llms.txt +15 -15
  147. package/dist/grid-entry/public-api.js +1 -1
  148. package/dist/i18n/i18n-context.d.ts +6 -6
  149. package/dist/i18n/i18n-context.js +27 -5
  150. package/dist/icon/icon-registry.d.ts +3 -3
  151. package/dist/icon/icon-registry.js +3 -3
  152. package/dist/icon/icon.d.ts +4 -4
  153. package/dist/icon/icon.js +10 -7
  154. package/dist/icon/llms.txt +13 -13
  155. package/dist/icon-button/icon-button.d.ts +2 -2
  156. package/dist/icon-button/icon-button.js +1 -1
  157. package/dist/icon-button/llms.txt +9 -5
  158. package/dist/icons-entry/public-api.d.ts +2 -2
  159. package/dist/icons-entry/public-api.js +3 -3
  160. package/dist/image/image.js +5 -5
  161. package/dist/image/llms.txt +13 -13
  162. package/dist/input/input.d.ts +18 -5
  163. package/dist/input/input.js +22 -6
  164. package/dist/input/llms.txt +25 -11
  165. package/dist/input-mask/input-mask.d.ts +7 -2
  166. package/dist/input-mask/input-mask.js +17 -43
  167. package/dist/input-mask/llms.txt +8 -5
  168. package/dist/input-number/input-number.d.ts +11 -9
  169. package/dist/input-number/input-number.js +25 -21
  170. package/dist/input-number/llms.txt +17 -14
  171. package/dist/input-otp/input-otp.d.ts +18 -5
  172. package/dist/input-otp/input-otp.js +48 -24
  173. package/dist/input-otp/llms.txt +18 -7
  174. package/dist/internal/calendar-focus.d.ts +1 -1
  175. package/dist/internal/calendar-focus.js +3 -3
  176. package/dist/internal/cn.d.ts +1 -1
  177. package/dist/internal/mask.d.ts +14 -0
  178. package/dist/internal/mask.js +62 -0
  179. package/dist/internal/number-group.d.ts +22 -0
  180. package/dist/internal/number-group.js +53 -0
  181. package/dist/internal/option-key.d.ts +6 -0
  182. package/dist/internal/option-key.js +8 -0
  183. package/dist/internal/option-nav.d.ts +4 -4
  184. package/dist/internal/option-nav.js +5 -5
  185. package/dist/internal/overlay-container.js +1 -1
  186. package/dist/internal/overlay.d.ts +3 -3
  187. package/dist/internal/overlay.js +40 -10
  188. package/dist/internal/password-strength.d.ts +6 -0
  189. package/dist/internal/password-strength.js +74 -0
  190. package/dist/internal/roving.d.ts +2 -2
  191. package/dist/internal/roving.js +3 -3
  192. package/dist/internal/scroll-lock.d.ts +6 -0
  193. package/dist/internal/scroll-lock.js +35 -0
  194. package/dist/internal/slot-children.d.ts +13 -0
  195. package/dist/internal/slot-children.js +31 -0
  196. package/dist/internal/slot.d.ts +3 -3
  197. package/dist/internal/slot.js +2 -2
  198. package/dist/internal/step.d.ts +12 -0
  199. package/dist/internal/step.js +31 -0
  200. package/dist/internal/tween.d.ts +5 -5
  201. package/dist/internal/tween.js +7 -8
  202. package/dist/internal/types.d.ts +2 -2
  203. package/dist/internal/use-breakpoint.d.ts +2 -2
  204. package/dist/internal/use-breakpoint.js +4 -4
  205. package/dist/internal/use-controllable-state.d.ts +5 -0
  206. package/dist/internal/use-controllable-state.js +25 -4
  207. package/dist/internal/use-id.d.ts +2 -2
  208. package/dist/internal/use-id.js +2 -2
  209. package/dist/internal/use-modal-focus.d.ts +2 -1
  210. package/dist/internal/use-modal-focus.js +14 -3
  211. package/dist/knob/knob.d.ts +7 -4
  212. package/dist/knob/knob.js +27 -22
  213. package/dist/knob/llms.txt +18 -11
  214. package/dist/listbox/listbox.d.ts +8 -6
  215. package/dist/listbox/listbox.js +37 -17
  216. package/dist/listbox/llms.txt +12 -9
  217. package/dist/loader/llms.txt +56 -0
  218. package/dist/loader/loader.d.ts +49 -0
  219. package/dist/loader/loader.js +68 -0
  220. package/dist/map/llms.txt +30 -23
  221. package/dist/map/map-create-dialog.d.ts +4 -4
  222. package/dist/map/map-create-dialog.js +36 -28
  223. package/dist/map/map-hours-field.d.ts +4 -4
  224. package/dist/map/map-hours-field.js +8 -7
  225. package/dist/map/map-image-field.d.ts +2 -2
  226. package/dist/map/map-image-field.js +6 -5
  227. package/dist/map/map-legend.d.ts +4 -4
  228. package/dist/map/map-legend.js +3 -2
  229. package/dist/map/map-poi-card.d.ts +3 -3
  230. package/dist/map/map-poi-card.js +10 -9
  231. package/dist/map/map-search.d.ts +17 -6
  232. package/dist/map/map-search.js +70 -43
  233. package/dist/map/map.d.ts +25 -13
  234. package/dist/map/map.js +86 -57
  235. package/dist/map/ports.d.ts +9 -9
  236. package/dist/map/ports.js +6 -6
  237. package/dist/map-entry/public-api.js +2 -2
  238. package/dist/megamenu/llms.txt +18 -7
  239. package/dist/megamenu/megamenu.d.ts +12 -6
  240. package/dist/megamenu/megamenu.js +23 -14
  241. package/dist/mention/llms.txt +15 -15
  242. package/dist/mention/mention.d.ts +5 -5
  243. package/dist/mention/mention.js +2 -2
  244. package/dist/mention/mentions.d.ts +1 -1
  245. package/dist/mention/mentions.js +1 -1
  246. package/dist/menu/llms.txt +12 -12
  247. package/dist/menu/menu-item.d.ts +4 -4
  248. package/dist/menu/menu-keys.d.ts +2 -2
  249. package/dist/menu/menu-keys.js +5 -5
  250. package/dist/menu/menu-rows.js +1 -0
  251. package/dist/menu/menu.d.ts +2 -2
  252. package/dist/menu/menu.js +15 -8
  253. package/dist/menubar/llms.txt +19 -8
  254. package/dist/menubar/menubar.d.ts +11 -5
  255. package/dist/menubar/menubar.js +23 -11
  256. package/dist/meter-group/llms.txt +12 -12
  257. package/dist/meter-group/meter-group.d.ts +2 -2
  258. package/dist/meter-group/meter-group.js +2 -1
  259. package/dist/motion/motion-context.d.ts +22 -0
  260. package/dist/motion/motion-context.js +28 -0
  261. package/dist/order-list/llms.txt +24 -9
  262. package/dist/order-list/order-list.d.ts +12 -4
  263. package/dist/order-list/order-list.js +123 -25
  264. package/dist/paginator/llms.txt +8 -8
  265. package/dist/paginator/paginator.js +7 -4
  266. package/dist/panel/llms.txt +25 -13
  267. package/dist/panel/panel.d.ts +11 -3
  268. package/dist/panel/panel.js +12 -7
  269. package/dist/password/llms.txt +19 -7
  270. package/dist/password/password.d.ts +2 -2
  271. package/dist/password/password.js +27 -16
  272. package/dist/peek/llms.txt +11 -11
  273. package/dist/peek/peek.d.ts +6 -6
  274. package/dist/peek/peek.js +41 -19
  275. package/dist/pick-list/llms.txt +35 -12
  276. package/dist/pick-list/pick-list.d.ts +12 -4
  277. package/dist/pick-list/pick-list.js +128 -24
  278. package/dist/popover/llms.txt +13 -10
  279. package/dist/popover/popover.d.ts +6 -4
  280. package/dist/popover/popover.js +14 -7
  281. package/dist/progress/llms.txt +17 -17
  282. package/dist/progress/progress.d.ts +7 -7
  283. package/dist/progress/progress.js +7 -6
  284. package/dist/public-api.d.ts +16 -4
  285. package/dist/public-api.js +13 -7
  286. package/dist/radio-group/llms.txt +16 -6
  287. package/dist/radio-group/radio-group.d.ts +12 -3
  288. package/dist/radio-group/radio-group.js +23 -4
  289. package/dist/rating/llms.txt +20 -13
  290. package/dist/rating/rating-pointer.d.ts +16 -0
  291. package/dist/rating/rating-pointer.js +26 -0
  292. package/dist/rating/rating.d.ts +6 -6
  293. package/dist/rating/rating.js +77 -12
  294. package/dist/rich-text/lists.d.ts +2 -2
  295. package/dist/rich-text/lists.js +7 -7
  296. package/dist/rich-text/llms.txt +35 -12
  297. package/dist/rich-text/rich-text.d.ts +13 -14
  298. package/dist/rich-text/rich-text.js +311 -142
  299. package/dist/rich-text/sanitize.d.ts +11 -2
  300. package/dist/rich-text/sanitize.js +80 -32
  301. package/dist/rich-text/tables.d.ts +3 -3
  302. package/dist/rich-text/tables.js +3 -3
  303. package/dist/roadmap/llms.txt +23 -17
  304. package/dist/roadmap/roadmap.d.ts +6 -6
  305. package/dist/roadmap/roadmap.js +102 -25
  306. package/dist/roadmap-entry/public-api.js +2 -2
  307. package/dist/scroll-top/llms.txt +6 -6
  308. package/dist/scroll-top/scroll-top.d.ts +1 -1
  309. package/dist/scroll-top/scroll-top.js +2 -1
  310. package/dist/select/llms.txt +22 -12
  311. package/dist/select/select.d.ts +10 -8
  312. package/dist/select/select.js +87 -47
  313. package/dist/shared/types.d.ts +22 -1
  314. package/dist/shared/types.js +9 -1
  315. package/dist/sidenav/llms.txt +9 -9
  316. package/dist/sidenav/sidenav.d.ts +2 -3
  317. package/dist/sidenav/sidenav.js +5 -4
  318. package/dist/skeleton/llms.txt +3 -3
  319. package/dist/skeleton/skeleton.d.ts +1 -1
  320. package/dist/skeleton/skeleton.js +1 -1
  321. package/dist/slider/llms.txt +34 -12
  322. package/dist/slider/slider-drag.d.ts +26 -0
  323. package/dist/slider/slider-drag.js +79 -0
  324. package/dist/slider/slider.d.ts +8 -5
  325. package/dist/slider/slider.js +38 -8
  326. package/dist/speech/llms.txt +97 -0
  327. package/dist/speech/speech-button.d.ts +44 -0
  328. package/dist/speech/speech-button.js +86 -0
  329. package/dist/speech/speech-wave.d.ts +19 -0
  330. package/dist/speech/speech-wave.js +16 -0
  331. package/dist/speech/use-speech-recognition.d.ts +81 -0
  332. package/dist/speech/use-speech-recognition.js +179 -0
  333. package/dist/speed-dial/llms.txt +14 -8
  334. package/dist/speed-dial/speed-dial.d.ts +1 -1
  335. package/dist/speed-dial/speed-dial.js +3 -2
  336. package/dist/spinner/llms.txt +7 -7
  337. package/dist/spinner/spinner.d.ts +1 -1
  338. package/dist/spinner/spinner.js +2 -1
  339. package/dist/split-button/llms.txt +21 -15
  340. package/dist/split-button/split-button.d.ts +2 -2
  341. package/dist/split-button/split-button.js +13 -6
  342. package/dist/splitter/llms.txt +11 -11
  343. package/dist/splitter/splitter.d.ts +3 -3
  344. package/dist/splitter/splitter.js +25 -10
  345. package/dist/stepper/llms.txt +35 -13
  346. package/dist/stepper/stepper.d.ts +6 -6
  347. package/dist/stepper/stepper.js +60 -13
  348. package/dist/switch/llms.txt +15 -5
  349. package/dist/switch/switch.d.ts +10 -3
  350. package/dist/switch/switch.js +18 -4
  351. package/dist/switch-group/llms.txt +11 -8
  352. package/dist/switch-group/switch-group.d.ts +6 -4
  353. package/dist/switch-group/switch-group.js +9 -7
  354. package/dist/tabs/llms.txt +12 -9
  355. package/dist/tabs/tabs.d.ts +5 -5
  356. package/dist/tabs/tabs.js +36 -20
  357. package/dist/textarea/llms.txt +23 -12
  358. package/dist/textarea/textarea.d.ts +19 -6
  359. package/dist/textarea/textarea.js +22 -7
  360. package/dist/timeline/llms.txt +4 -4
  361. package/dist/timeline/timeline.d.ts +1 -1
  362. package/dist/timeline/timeline.js +1 -1
  363. package/dist/toast/llms.txt +50 -17
  364. package/dist/toast/toast-container.d.ts +9 -3
  365. package/dist/toast/toast-container.js +18 -9
  366. package/dist/toast/toast-store.d.ts +42 -2
  367. package/dist/toast/toast-store.js +36 -1
  368. package/dist/toolbar/llms.txt +7 -7
  369. package/dist/toolbar/toolbar.d.ts +3 -3
  370. package/dist/toolbar/toolbar.js +2 -2
  371. package/dist/tooltip/llms.txt +14 -12
  372. package/dist/tooltip/tooltip.d.ts +5 -4
  373. package/dist/tooltip/tooltip.js +100 -41
  374. package/dist/tree/llms.txt +25 -11
  375. package/dist/tree/tree-keys.d.ts +5 -5
  376. package/dist/tree/tree-keys.js +7 -7
  377. package/dist/tree/tree.d.ts +17 -5
  378. package/dist/tree/tree.js +62 -20
  379. package/dist/update/llms.txt +54 -0
  380. package/dist/update/update.d.ts +49 -0
  381. package/dist/update/update.js +82 -0
  382. 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 — bez bibliotek, bo to jedna reguła. */
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 — natywne pole pliku jest ukryte, więc bez tego klawiatura nie miałaby
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 (!disabled)
44
+ if (!locked)
37
45
  inputRef.current?.click();
38
46
  };
39
- /** `Enter` / spacja na strefie — spacja bez `preventDefault` przewinęłaby stronę. */
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 — inaczej `change` by nie poleciał.
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": disabled || undefined, "aria-invalid": showError || undefined, "data-invalid": showError ? '' : undefined, onClick: openPicker, onKeyDown: onZoneKeyDown, onDragOver: (event) => {
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 (!disabled)
68
+ if (!locked)
61
69
  setDragover(true);
62
70
  }, onDragLeave: () => setDragover(false), onDrop: (event) => {
63
71
  event.preventDefault();
64
72
  setDragover(false);
65
- if (!disabled)
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" }), _jsx("div", { className: "kpt-file-upload__text", dangerouslySetInnerHTML: { __html: t('fileUpload.hint') } }), 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) }), _jsx("button", { type: "button", className: "kpt-file-upload__remove", "aria-label": t('fileUpload.remove'), onClick: (event) => {
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
- }, children: _jsx(KptIcon, { name: "trash" }) })] }, `${index}-${file.name}`))) })) : null] }));
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">…</span>
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">…name, size, remove…</li>
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` — 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
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 carries markup
32
- `fileUpload.hint` holds a `<strong>`, so it is rendered with `dangerouslySetInnerHTML` — the text
33
- comes from the dictionary (ours or the app's), never from user input.
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 — see "Keyboard and states" above.
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]` — kontrolka bez własnego `id` nadaje je swojemu elementowi. */
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 — na nie wskaże `label[for]`. */
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 — dla kontrolek na elemencie, którego `label[for]` nie nazywa
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 — do `aria-describedby`. */
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 — `over`
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 — gdy niepusty, pole jest oznaczone jako nieprawidłowe. */
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 — stan błędu przekazuje się przez `error`.
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 — stan błędu przekazuje się przez `error`.
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 — wtedy `label[for]` wskazuje właśnie je.
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) — po pierwszym renderze projekcji, przed malowaniem,
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 — to jeden `querySelector`, nie warto tu optymalizować.
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
  }
@@ -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="…">E-mail<span class="kpt-form-field__required">*</span></label>
11
- <div class="kpt-form-field__control">…control…</div>
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 — 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
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 — `label[for]` and `input[id]` always match. Pass `controlId` to take over; a control
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`…) gets
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 — no placeholder required.
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` — the required state belongs on the control (`aria-required`), not on
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 — duży podgląd obrazu z paskiem miniatur i nawigacją.
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` — do pierwszego/ostatniego; gdy fokus stoi na miniaturze, idzie za
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 („Obraz 2 z 4: …”) — dopiero po działaniu użytkownika, nie przy starcie.
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 — duży podgląd obrazu z paskiem miniatur i nawigacją.
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` — do pierwszego/ostatniego; gdy fokus stoi na miniaturze, idzie za
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 („Obraz 2 z 4: …”) — dopiero po działaniu użytkownika, nie przy starcie.
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 [active, setActive] = useControllableState({
23
+ const [requested, setActive] = useControllableState({
23
24
  value: activeIndex,
24
25
  defaultValue: defaultActiveIndex,
25
26
  onChange: onActiveIndexChange,
26
27
  });
27
- // Ogłoszenie dopiero po działaniu użytkownika — przy starcie region ma milczeć.
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 — inaczej strzałka zmieniałaby obraz,
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();
@@ -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">…</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>
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="…" alt=""></button>…
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[]` — `{ src, thumbnail?, alt? }`
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` — “Image 3” — when there is none), with `alt=""` on the thumbnail image so the
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 — `galleria.position` (“Image 2 of 4”) plus the `alt` — only after the
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.
@@ -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 — baza mobile-first. */
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) — pozwala robić offsety. */
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` — rozpiętość mobile-first z nadpisaniami per breakpoint.
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` — 5.
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` — rozpiętość mobile-first z nadpisaniami per breakpoint.
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` — 5.
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.
@@ -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 — baza mobile-first. */
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 — zmienne dzieci reagują na szerokość tego kontenera. */
29
+ /** Tryb kontenerowy - zmienne dzieci reagują na szerokość tego kontenera. */
30
30
  container?: boolean;
31
31
  }
32
32
  /**
33
- * Kontener flexbox Koncept UI — te same zmienne i breakpointy co `KptGrid`.
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 — te same zmienne i breakpointy co `KptGrid`.
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
  *
@@ -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 — baza mobile-first. Domyślnie 12 (z CSS). */
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 — nadpisuje `gap` w poziomie. */
18
+ /** Odstęp między kolumnami - nadpisuje `gap` w poziomie. */
19
19
  gapX?: string;
20
- /** Odstęp między wierszami — nadpisuje `gap` w pionie. */
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 — `@container` nie potrafi
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 — CSS Grid sterowany custom properties z `@konce-pt/grid`.
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 — ale takim, który w trybie `asChild` niczego nie dokłada do DOM: przejmuje element,
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 — ustawia zmienną inline, a układ przelicza
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 — CSS Grid sterowany custom properties z `@konce-pt/grid`.
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 — ale takim, który w trybie `asChild` niczego nie dokłada do DOM: przejmuje element,
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 — ustawia zmienną inline, a układ przelicza
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';`).
@@ -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 — w trybie `asChild` — oddaje propsy jedynemu dziecku.
13
+ * Renderuje element układu albo - w trybie `asChild` - oddaje propsy jedynemu dziecku.
14
14
  *
15
- * To reactowy odpowiednik dyrektywy: `<KptCol asChild><li>…</li></KptCol>` nie dokłada żadnego
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;