@konce-pt/react 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/README.md +122 -64
  2. package/dist/accordion/accordion.d.ts +14 -6
  3. package/dist/accordion/accordion.js +14 -7
  4. package/dist/accordion/llms.txt +22 -10
  5. package/dist/alert/alert.d.ts +2 -2
  6. package/dist/alert/alert.js +2 -2
  7. package/dist/alert/llms.txt +10 -10
  8. package/dist/app-shell/app-shell.d.ts +14 -14
  9. package/dist/app-shell/app-shell.js +11 -11
  10. package/dist/app-shell/llms.txt +13 -13
  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 +7 -7
  14. package/dist/auth/llms.txt +9 -9
  15. package/dist/autocomplete/autocomplete.d.ts +19 -6
  16. package/dist/autocomplete/autocomplete.js +23 -10
  17. package/dist/autocomplete/llms.txt +16 -5
  18. package/dist/avatar/avatar.d.ts +6 -6
  19. package/dist/avatar/avatar.js +5 -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 +3 -3
  23. package/dist/avatar-group/llms.txt +8 -8
  24. package/dist/backdrop/backdrop.d.ts +7 -7
  25. package/dist/backdrop/backdrop.js +16 -16
  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 +4 -4
  31. package/dist/bottom-sheet/bottom-sheet.js +2 -2
  32. package/dist/bottom-sheet/llms.txt +9 -9
  33. package/dist/breadcrumb/breadcrumb.d.ts +2 -2
  34. package/dist/breadcrumb/breadcrumb.js +3 -3
  35. package/dist/breadcrumb/llms.txt +3 -3
  36. package/dist/button/button.d.ts +3 -3
  37. package/dist/button/button.js +8 -8
  38. package/dist/button/llms.txt +27 -19
  39. package/dist/button-group/button-group.d.ts +9 -9
  40. package/dist/button-group/button-group.js +30 -8
  41. package/dist/button-group/llms.txt +20 -14
  42. package/dist/card/card.d.ts +8 -8
  43. package/dist/card/card.js +6 -6
  44. package/dist/card/llms.txt +20 -20
  45. package/dist/carousel/carousel.d.ts +6 -6
  46. package/dist/carousel/carousel.js +4 -4
  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 +1 -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 +1 -1
  53. package/dist/charts/chart.js +8 -8
  54. package/dist/charts/llms.txt +6 -6
  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 +42 -18
  58. package/dist/chat/llms.txt +32 -17
  59. package/dist/chat-composer/chat-composer.d.ts +17 -7
  60. package/dist/chat-composer/chat-composer.js +21 -8
  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 +9 -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 +17 -7
  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 +3 -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 +26 -7
  74. package/dist/checkbox/llms.txt +24 -12
  75. package/dist/chip/chip.d.ts +4 -4
  76. package/dist/chip/chip.js +2 -2
  77. package/dist/chip/llms.txt +11 -11
  78. package/dist/chips-input/chips-input.d.ts +4 -4
  79. package/dist/chips-input/chips-input.js +35 -9
  80. package/dist/chips-input/llms.txt +15 -8
  81. package/dist/clock/clock.d.ts +4 -4
  82. package/dist/clock/clock.js +7 -7
  83. package/dist/clock/llms.txt +8 -8
  84. package/dist/color-picker/color-picker.d.ts +6 -6
  85. package/dist/color-picker/color-picker.js +3 -3
  86. package/dist/color-picker/llms.txt +5 -5
  87. package/dist/confirm/confirm-container.d.ts +3 -3
  88. package/dist/confirm/confirm-container.js +5 -5
  89. package/dist/confirm/confirm-store.d.ts +4 -4
  90. package/dist/confirm/confirm-store.js +7 -7
  91. package/dist/confirm/llms.txt +6 -6
  92. package/dist/context-menu/context-menu.d.ts +1 -1
  93. package/dist/context-menu/context-menu.js +5 -5
  94. package/dist/context-menu/llms.txt +7 -7
  95. package/dist/data-table/data-table-types.d.ts +5 -5
  96. package/dist/data-table/data-table.d.ts +29 -8
  97. package/dist/data-table/data-table.js +340 -95
  98. package/dist/data-table/export-csv.d.ts +3 -3
  99. package/dist/data-table/export-csv.js +4 -4
  100. package/dist/data-table/llms.txt +127 -94
  101. package/dist/data-view/data-view.d.ts +13 -5
  102. package/dist/data-view/data-view.js +67 -6
  103. package/dist/data-view/llms.txt +29 -10
  104. package/dist/date-range/date-range.d.ts +9 -9
  105. package/dist/date-range/date-range.js +24 -24
  106. package/dist/date-range/llms.txt +20 -20
  107. package/dist/datepicker/datepicker.d.ts +10 -10
  108. package/dist/datepicker/datepicker.js +29 -29
  109. package/dist/datepicker/llms.txt +24 -24
  110. package/dist/dialog/dialog.d.ts +4 -4
  111. package/dist/dialog/dialog.js +4 -4
  112. package/dist/dialog/llms.txt +11 -11
  113. package/dist/divider/divider.d.ts +1 -1
  114. package/dist/divider/llms.txt +4 -4
  115. package/dist/drawer/drawer.d.ts +5 -5
  116. package/dist/drawer/drawer.js +2 -2
  117. package/dist/drawer/llms.txt +11 -11
  118. package/dist/empty/empty.d.ts +2 -2
  119. package/dist/empty/empty.js +1 -1
  120. package/dist/empty/llms.txt +9 -9
  121. package/dist/fab/fab.d.ts +1 -1
  122. package/dist/fab/fab.js +1 -1
  123. package/dist/fab/llms.txt +10 -6
  124. package/dist/fieldset/fieldset.d.ts +18 -4
  125. package/dist/fieldset/fieldset.js +9 -6
  126. package/dist/fieldset/llms.txt +26 -9
  127. package/dist/file-upload/file-upload.d.ts +3 -3
  128. package/dist/file-upload/file-upload.js +7 -7
  129. package/dist/file-upload/llms.txt +7 -7
  130. package/dist/form-field/form-field-context.d.ts +4 -4
  131. package/dist/form-field/form-field.d.ts +12 -4
  132. package/dist/form-field/form-field.js +26 -6
  133. package/dist/form-field/llms.txt +25 -11
  134. package/dist/galleria/galleria.d.ts +3 -3
  135. package/dist/galleria/galleria.js +5 -5
  136. package/dist/galleria/llms.txt +7 -7
  137. package/dist/grid/col.d.ts +4 -4
  138. package/dist/grid/col.js +2 -2
  139. package/dist/grid/flex.d.ts +3 -3
  140. package/dist/grid/flex.js +1 -1
  141. package/dist/grid/grid.d.ts +7 -7
  142. package/dist/grid/grid.js +3 -3
  143. package/dist/grid/layout.d.ts +2 -2
  144. package/dist/grid/layout.js +2 -2
  145. package/dist/grid/llms.txt +15 -15
  146. package/dist/grid-entry/public-api.js +1 -1
  147. package/dist/i18n/i18n-context.d.ts +3 -3
  148. package/dist/i18n/i18n-context.js +7 -7
  149. package/dist/icon/icon-registry.d.ts +3 -3
  150. package/dist/icon/icon-registry.js +3 -3
  151. package/dist/icon/icon.d.ts +4 -4
  152. package/dist/icon/icon.js +6 -6
  153. package/dist/icon/llms.txt +13 -13
  154. package/dist/icon-button/icon-button.d.ts +2 -2
  155. package/dist/icon-button/icon-button.js +1 -1
  156. package/dist/icon-button/llms.txt +9 -5
  157. package/dist/icons-entry/public-api.d.ts +2 -2
  158. package/dist/icons-entry/public-api.js +3 -3
  159. package/dist/image/image.js +1 -1
  160. package/dist/image/llms.txt +13 -13
  161. package/dist/input/input.d.ts +18 -5
  162. package/dist/input/input.js +21 -6
  163. package/dist/input/llms.txt +25 -11
  164. package/dist/input-mask/input-mask.d.ts +1 -1
  165. package/dist/input-mask/input-mask.js +2 -2
  166. package/dist/input-mask/llms.txt +5 -5
  167. package/dist/input-number/input-number.d.ts +9 -9
  168. package/dist/input-number/input-number.js +11 -11
  169. package/dist/input-number/llms.txt +14 -14
  170. package/dist/input-otp/input-otp.d.ts +6 -6
  171. package/dist/input-otp/input-otp.js +10 -10
  172. package/dist/input-otp/llms.txt +9 -9
  173. package/dist/internal/calendar-focus.d.ts +1 -1
  174. package/dist/internal/calendar-focus.js +3 -3
  175. package/dist/internal/cn.d.ts +1 -1
  176. package/dist/internal/mask.d.ts +2 -2
  177. package/dist/internal/mask.js +4 -4
  178. package/dist/internal/option-key.d.ts +2 -2
  179. package/dist/internal/option-key.js +2 -2
  180. package/dist/internal/option-nav.d.ts +4 -4
  181. package/dist/internal/option-nav.js +5 -5
  182. package/dist/internal/overlay-container.js +1 -1
  183. package/dist/internal/overlay.d.ts +3 -3
  184. package/dist/internal/overlay.js +8 -8
  185. package/dist/internal/password-strength.d.ts +2 -2
  186. package/dist/internal/password-strength.js +6 -6
  187. package/dist/internal/roving.d.ts +2 -2
  188. package/dist/internal/roving.js +3 -3
  189. package/dist/internal/scroll-lock.d.ts +1 -1
  190. package/dist/internal/scroll-lock.js +2 -2
  191. package/dist/internal/slot-children.d.ts +3 -3
  192. package/dist/internal/slot-children.js +4 -4
  193. package/dist/internal/slot.d.ts +3 -3
  194. package/dist/internal/slot.js +2 -2
  195. package/dist/internal/step.d.ts +3 -3
  196. package/dist/internal/step.js +4 -4
  197. package/dist/internal/tween.d.ts +5 -5
  198. package/dist/internal/tween.js +5 -5
  199. package/dist/internal/types.d.ts +2 -2
  200. package/dist/internal/use-breakpoint.d.ts +2 -2
  201. package/dist/internal/use-breakpoint.js +4 -4
  202. package/dist/internal/use-controllable-state.d.ts +1 -1
  203. package/dist/internal/use-controllable-state.js +3 -3
  204. package/dist/internal/use-id.d.ts +2 -2
  205. package/dist/internal/use-id.js +2 -2
  206. package/dist/internal/use-modal-focus.d.ts +1 -1
  207. package/dist/internal/use-modal-focus.js +3 -3
  208. package/dist/knob/knob.d.ts +4 -4
  209. package/dist/knob/knob.js +14 -10
  210. package/dist/knob/llms.txt +17 -12
  211. package/dist/listbox/listbox.d.ts +6 -6
  212. package/dist/listbox/listbox.js +9 -9
  213. package/dist/listbox/llms.txt +10 -10
  214. package/dist/loader/llms.txt +56 -0
  215. package/dist/loader/loader.d.ts +49 -0
  216. package/dist/loader/loader.js +68 -0
  217. package/dist/map/llms.txt +25 -22
  218. package/dist/map/map-create-dialog.d.ts +4 -4
  219. package/dist/map/map-create-dialog.js +10 -10
  220. package/dist/map/map-hours-field.d.ts +4 -4
  221. package/dist/map/map-hours-field.js +7 -7
  222. package/dist/map/map-image-field.d.ts +2 -2
  223. package/dist/map/map-image-field.js +4 -4
  224. package/dist/map/map-legend.d.ts +4 -4
  225. package/dist/map/map-legend.js +2 -2
  226. package/dist/map/map-poi-card.d.ts +3 -3
  227. package/dist/map/map-poi-card.js +9 -9
  228. package/dist/map/map-search.d.ts +17 -6
  229. package/dist/map/map-search.js +21 -18
  230. package/dist/map/map.d.ts +21 -14
  231. package/dist/map/map.js +30 -29
  232. package/dist/map/ports.d.ts +9 -9
  233. package/dist/map/ports.js +6 -6
  234. package/dist/map-entry/public-api.js +2 -2
  235. package/dist/megamenu/llms.txt +9 -9
  236. package/dist/megamenu/megamenu.d.ts +6 -6
  237. package/dist/megamenu/megamenu.js +10 -10
  238. package/dist/mention/llms.txt +15 -15
  239. package/dist/mention/mention.d.ts +5 -5
  240. package/dist/mention/mention.js +2 -2
  241. package/dist/mention/mentions.d.ts +1 -1
  242. package/dist/mention/mentions.js +1 -1
  243. package/dist/menu/llms.txt +12 -12
  244. package/dist/menu/menu-item.d.ts +4 -4
  245. package/dist/menu/menu-keys.d.ts +2 -2
  246. package/dist/menu/menu-keys.js +5 -5
  247. package/dist/menu/menu.d.ts +2 -2
  248. package/dist/menu/menu.js +6 -6
  249. package/dist/menubar/llms.txt +10 -10
  250. package/dist/menubar/menubar.d.ts +5 -5
  251. package/dist/menubar/menubar.js +10 -10
  252. package/dist/meter-group/llms.txt +12 -12
  253. package/dist/meter-group/meter-group.d.ts +2 -2
  254. package/dist/meter-group/meter-group.js +1 -1
  255. package/dist/motion/motion-context.d.ts +22 -0
  256. package/dist/motion/motion-context.js +28 -0
  257. package/dist/order-list/llms.txt +22 -10
  258. package/dist/order-list/order-list.d.ts +12 -4
  259. package/dist/order-list/order-list.js +104 -21
  260. package/dist/paginator/llms.txt +8 -8
  261. package/dist/paginator/paginator.js +1 -1
  262. package/dist/panel/llms.txt +25 -13
  263. package/dist/panel/panel.d.ts +11 -3
  264. package/dist/panel/panel.js +7 -4
  265. package/dist/password/llms.txt +16 -8
  266. package/dist/password/password.d.ts +2 -2
  267. package/dist/password/password.js +24 -3
  268. package/dist/peek/llms.txt +10 -10
  269. package/dist/peek/peek.d.ts +6 -6
  270. package/dist/peek/peek.js +7 -7
  271. package/dist/pick-list/llms.txt +33 -13
  272. package/dist/pick-list/pick-list.d.ts +12 -4
  273. package/dist/pick-list/pick-list.js +111 -23
  274. package/dist/popover/llms.txt +11 -11
  275. package/dist/popover/popover.d.ts +4 -4
  276. package/dist/popover/popover.js +5 -5
  277. package/dist/progress/llms.txt +17 -17
  278. package/dist/progress/progress.d.ts +7 -7
  279. package/dist/progress/progress.js +6 -6
  280. package/dist/public-api.d.ts +15 -3
  281. package/dist/public-api.js +13 -7
  282. package/dist/radio-group/llms.txt +13 -6
  283. package/dist/radio-group/radio-group.d.ts +11 -4
  284. package/dist/radio-group/radio-group.js +15 -7
  285. package/dist/rating/llms.txt +20 -13
  286. package/dist/rating/rating-pointer.d.ts +16 -0
  287. package/dist/rating/rating-pointer.js +26 -0
  288. package/dist/rating/rating.d.ts +6 -6
  289. package/dist/rating/rating.js +76 -12
  290. package/dist/rich-text/lists.d.ts +2 -2
  291. package/dist/rich-text/lists.js +7 -7
  292. package/dist/rich-text/llms.txt +26 -17
  293. package/dist/rich-text/rich-text.d.ts +12 -7
  294. package/dist/rich-text/rich-text.js +78 -54
  295. package/dist/rich-text/sanitize.d.ts +3 -3
  296. package/dist/rich-text/sanitize.js +12 -12
  297. package/dist/rich-text/tables.d.ts +3 -3
  298. package/dist/rich-text/tables.js +3 -3
  299. package/dist/roadmap/llms.txt +15 -15
  300. package/dist/roadmap/roadmap.d.ts +6 -6
  301. package/dist/roadmap/roadmap.js +19 -19
  302. package/dist/roadmap-entry/public-api.js +2 -2
  303. package/dist/scroll-top/llms.txt +6 -6
  304. package/dist/scroll-top/scroll-top.d.ts +1 -1
  305. package/dist/scroll-top/scroll-top.js +1 -1
  306. package/dist/select/llms.txt +19 -12
  307. package/dist/select/select.d.ts +8 -8
  308. package/dist/select/select.js +47 -21
  309. package/dist/shared/types.d.ts +5 -5
  310. package/dist/shared/types.js +1 -1
  311. package/dist/sidenav/llms.txt +9 -9
  312. package/dist/sidenav/sidenav.d.ts +1 -1
  313. package/dist/sidenav/sidenav.js +1 -1
  314. package/dist/skeleton/llms.txt +3 -3
  315. package/dist/skeleton/skeleton.d.ts +1 -1
  316. package/dist/skeleton/skeleton.js +1 -1
  317. package/dist/slider/llms.txt +32 -13
  318. package/dist/slider/slider-drag.d.ts +26 -0
  319. package/dist/slider/slider-drag.js +79 -0
  320. package/dist/slider/slider.d.ts +6 -5
  321. package/dist/slider/slider.js +27 -8
  322. package/dist/speech/llms.txt +97 -0
  323. package/dist/speech/speech-button.d.ts +44 -0
  324. package/dist/speech/speech-button.js +86 -0
  325. package/dist/speech/speech-wave.d.ts +19 -0
  326. package/dist/speech/speech-wave.js +16 -0
  327. package/dist/speech/use-speech-recognition.d.ts +81 -0
  328. package/dist/speech/use-speech-recognition.js +179 -0
  329. package/dist/speed-dial/llms.txt +14 -8
  330. package/dist/speed-dial/speed-dial.d.ts +1 -1
  331. package/dist/speed-dial/speed-dial.js +1 -1
  332. package/dist/spinner/llms.txt +7 -7
  333. package/dist/spinner/spinner.d.ts +1 -1
  334. package/dist/spinner/spinner.js +1 -1
  335. package/dist/split-button/llms.txt +21 -15
  336. package/dist/split-button/split-button.d.ts +2 -2
  337. package/dist/split-button/split-button.js +4 -4
  338. package/dist/splitter/llms.txt +11 -11
  339. package/dist/splitter/splitter.d.ts +3 -3
  340. package/dist/splitter/splitter.js +5 -5
  341. package/dist/stepper/llms.txt +33 -14
  342. package/dist/stepper/stepper.d.ts +6 -6
  343. package/dist/stepper/stepper.js +53 -10
  344. package/dist/switch/llms.txt +12 -5
  345. package/dist/switch/switch.d.ts +10 -3
  346. package/dist/switch/switch.js +12 -5
  347. package/dist/switch-group/llms.txt +9 -9
  348. package/dist/switch-group/switch-group.d.ts +4 -4
  349. package/dist/switch-group/switch-group.js +4 -4
  350. package/dist/tabs/llms.txt +10 -10
  351. package/dist/tabs/tabs.d.ts +5 -5
  352. package/dist/tabs/tabs.js +8 -8
  353. package/dist/textarea/llms.txt +23 -12
  354. package/dist/textarea/textarea.d.ts +19 -6
  355. package/dist/textarea/textarea.js +21 -7
  356. package/dist/timeline/llms.txt +4 -4
  357. package/dist/timeline/timeline.d.ts +1 -1
  358. package/dist/timeline/timeline.js +1 -1
  359. package/dist/toast/llms.txt +47 -17
  360. package/dist/toast/toast-container.d.ts +9 -3
  361. package/dist/toast/toast-container.js +17 -9
  362. package/dist/toast/toast-store.d.ts +40 -4
  363. package/dist/toast/toast-store.js +36 -1
  364. package/dist/toolbar/llms.txt +7 -7
  365. package/dist/toolbar/toolbar.d.ts +3 -3
  366. package/dist/toolbar/toolbar.js +2 -2
  367. package/dist/tooltip/llms.txt +10 -10
  368. package/dist/tooltip/tooltip.d.ts +3 -3
  369. package/dist/tooltip/tooltip.js +18 -18
  370. package/dist/tree/llms.txt +25 -12
  371. package/dist/tree/tree-keys.d.ts +5 -5
  372. package/dist/tree/tree-keys.js +7 -7
  373. package/dist/tree/tree.d.ts +14 -7
  374. package/dist/tree/tree.js +53 -18
  375. package/dist/update/llms.txt +54 -0
  376. package/dist/update/update.d.ts +49 -0
  377. package/dist/update/update.js +82 -0
  378. package/package.json +15 -13
@@ -1,12 +1,15 @@
1
1
  'use client';
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- import { useCallback } from 'react';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useRef } from 'react';
4
4
  import { cn } from "../internal/cn.js";
5
+ import { composeRefs } from "../internal/compose-refs.js";
6
+ import { KptSpeechButton } from "../speech/speech-button.js";
7
+ import { useKptSpeechRecognition } from "../speech/use-speech-recognition.js";
5
8
  import { joinIds, useKptFieldA11y } from "../form-field/form-field-context.js";
6
9
  /**
7
10
  * Pole tekstowe Koncept UI. Renderuje natywny `<input>` w hoście `.kpt-input-host`.
8
11
  *
9
- * Działa kontrolowane (`value` + `onValueChange`) i niekontrolowane (`defaultValue`) —
12
+ * Działa kontrolowane (`value` + `onValueChange`) i niekontrolowane (`defaultValue`) -
10
13
  * w drugim trybie wartość należy do DOM, więc natywny `<form>`, `<form action>`, reset
11
14
  * formularza i React Hook Form (`register`) działają bez adaptera.
12
15
  *
@@ -17,10 +20,22 @@ import { joinIds, useKptFieldA11y } from "../form-field/form-field-context.js";
17
20
  * <KptInput name="email" type="email" defaultValue="" />
18
21
  * <KptInput value={email} onValueChange={setEmail} invalid={!ok} touched={blurred} />
19
22
  */
20
- export function KptInput({ type = 'text', required = false, invalid = false, touched, onValueChange, onTouch, hostProps, className, id, onChange, onBlur, 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedBy, ...rest }) {
23
+ export function KptInput({ type = 'text', required = false, invalid = false, touched, onValueChange, onTouch, hostProps, className, id, onChange, onBlur, ref, speech = false, speechLang, speechColor, speechMode = 'insert', 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedBy, ...rest }) {
21
24
  const { className: hostClassName, ...hostRest } = hostProps ?? {};
22
25
  const field = useKptFieldA11y(id, 'kpt-input');
23
- // Stan nieprawidłowy pokazujemy dopiero po dotknięciu pola — jak natywne `:user-invalid`.
26
+ const innerRef = useRef(null);
27
+ // Tekst zatwierdzony wchodzi przez zdarzenie `input` pola, więc `onChange` dostaje go jak wpisany;
28
+ // tymczasowy jest tylko na ekranie. Bez `speech` kontroler nie tworzy sesji.
29
+ const mic = useKptSpeechRecognition({
30
+ enabled: speech,
31
+ target: innerRef,
32
+ lang: speechLang,
33
+ mode: speechMode,
34
+ continuous: speechMode !== 'replace',
35
+ disabled: !!rest.disabled || !!rest.readOnly,
36
+ });
37
+ const speechState = speech && mic.available ? (mic.listening ? 'listening' : 'idle') : undefined;
38
+ // Stan nieprawidłowy pokazujemy dopiero po dotknięciu pola - jak natywne `:user-invalid`.
24
39
  // Bez `touched` nie ma czego bramkować, więc decyduje samo `invalid`.
25
40
  const showInvalid = invalid && (touched ?? true);
26
41
  const handleChange = useCallback((event) => {
@@ -31,5 +46,5 @@ export function KptInput({ type = 'text', required = false, invalid = false, tou
31
46
  onBlur?.(event);
32
47
  onTouch?.();
33
48
  }, [onBlur, onTouch]);
34
- return (_jsx("span", { className: cn('kpt-input-host', hostClassName), ...hostRest, children: _jsx("input", { className: cn('kpt-input__field', className), id: field.id, "aria-describedby": joinIds(ariaDescribedBy, field.describedBy), type: type, "aria-required": required || undefined, "aria-invalid": ariaInvalid ?? (showInvalid || undefined), onChange: handleChange, onBlur: handleBlur, ...rest }) }));
49
+ return (_jsxs("span", { className: cn('kpt-input-host', hostClassName), "data-speech": speechState, ...hostRest, children: [_jsx("input", { className: cn('kpt-input__field', className), id: field.id, "aria-describedby": joinIds(ariaDescribedBy, field.describedBy), type: type, "aria-required": required || undefined, "aria-invalid": ariaInvalid ?? (showInvalid || undefined), onChange: handleChange, onBlur: handleBlur, ref: composeRefs(innerRef, ref), ...rest }), speech ? (_jsx(KptSpeechButton, { listeningColor: speechColor, speech: mic, size: "sm", unsupported: "hide", disabled: !!rest.disabled || !!rest.readOnly, hostProps: { className: 'kpt-input__speech' } })) : null] }));
35
50
  }
@@ -5,28 +5,28 @@ Import: `import { KptInput } from '@konce-pt/react';`
5
5
 
6
6
  ## DOM
7
7
  <span class="kpt-input-host">
8
- <input class="kpt-input__field" id="…" type="text">
8
+ <input class="kpt-input__field" id="..." type="text">
9
9
  </span>
10
10
 
11
11
  ## Props
12
12
  - `type`: 'text' | 'email' | 'password' | 'number' | 'search' | 'tel' | 'url' | 'time' (default 'text')
13
- - `value` / `defaultValue` — controlled or uncontrolled, exactly like a native input
14
- - `onValueChange(value)` — the value alone; `onChange` still fires with the full event
15
- - `onTouch()` — fires on blur, the moment the field becomes touched
16
- - `required`: boolean — see the note below
17
- - `invalid`: boolean, `touched`: boolean — the error state
18
- - `hostProps` — props for the `.kpt-input-host` wrapper
13
+ - `value` / `defaultValue` - controlled or uncontrolled, exactly like a native input
14
+ - `onValueChange(value)` - the value alone; `onChange` still fires with the full event
15
+ - `onTouch()` - fires on blur, the moment the field becomes touched
16
+ - `required`: boolean - see the note below
17
+ - `invalid`: boolean, `touched`: boolean - the error state
18
+ - `hostProps` - props for the `.kpt-input-host` wrapper
19
19
  - `className`, `ref`, `name`, `placeholder`, `autoComplete` and every other `<input>` prop go to
20
20
  the inner `<input>`
21
21
 
22
22
  ## Controlled and uncontrolled
23
23
  Pass `value` and the field is controlled. Pass `defaultValue` (or nothing) and the value belongs
24
- to the DOM, so a native `<form>`, `<form action={…}>`, a form reset and React Hook Form's
25
- `register()` all work without an adapter — there is no internal mirror of the value to fight with.
24
+ to the DOM, so a native `<form>`, `<form action={...}>`, a form reset and React Hook Form's
25
+ `register()` all work without an adapter - there is no internal mirror of the value to fight with.
26
26
 
27
27
  ## The error state
28
28
  `aria-invalid="true"` is set when `invalid` is true. Pass `touched` as well to reproduce the
29
- Angular port's gate — the error then shows only after the field has been touched, like the native
29
+ Angular port's gate - the error then shows only after the field has been touched, like the native
30
30
  `:user-invalid`. With `touched` omitted there is nothing to gate on, so `invalid` decides alone;
31
31
  that is the common case in React, where the form library already knows when an error is ready.
32
32
  The style hangs off `aria-invalid`, never off a class.
@@ -55,5 +55,19 @@ added to `aria-describedby` (merged with your own). Without a wrapper, name it w
55
55
  `--kpt-form-field-{bg,text,placeholder,border,border-hover,border-focus,border-error,radius}`.
56
56
 
57
57
  ## Accessibility
58
- A native `<input>` — full keyboard and screen reader support. `aria-required` marks the field as
58
+ A native `<input>` - full keyboard and screen reader support. `aria-required` marks the field as
59
59
  required, `aria-invalid` marks it as erroneous, and the focus ring comes from `@konce-pt/styles`.
60
+
61
+ ## Dictation
62
+ - `speech`: boolean = false - a microphone at the end of the field (`KptSpeechButton`, Web Speech
63
+ API). Without browser support it is not shown and the field keeps its normal padding.
64
+ - `speechLang`: string - BCP 47 tag; without it from `KptI18nProvider`.
65
+ - `speechColor`: `'primary' | 'danger' | 'success' | 'warning' | 'info'` = `'primary'` - colour of "stop" and the wave while listening.
66
+ - `speechMode`: `'insert' | 'append' | 'replace'` = `'insert'`. `replace` clears the field the moment
67
+ the microphone is clicked (undoable with Ctrl+Z) and stops after one utterance - the search pattern.
68
+
69
+ Interim words are visible in the field but never reach your state; final text comes through
70
+ `onChange` / `onValueChange` like typed text.
71
+
72
+ <KptInput value={title} onValueChange={setTitle} speech />
73
+ <KptInput type="search" speech speechMode="replace" />
@@ -6,7 +6,7 @@ export interface KptInputMaskProps extends Omit<ComponentPropsWithRef<'input'>,
6
6
  /** Wzorzec maski; pozostałe znaki to literały (spacje, nawiasy, myślniki). */
7
7
  mask?: string;
8
8
  /**
9
- * Pole wymagane — `aria-required`, a nie natywne `required` (jak w `KptInput`): natywne
9
+ * Pole wymagane - `aria-required`, a nie natywne `required` (jak w `KptInput`): natywne
10
10
  * blokowałoby wysyłkę i uruchamiało walidację przeglądarki obok Twojej.
11
11
  */
12
12
  required?: boolean;
@@ -13,7 +13,7 @@ import { KPT_MASK_TOKENS, kptApplyMask, kptMaskCaret } from "../internal/mask.js
13
13
  */
14
14
  export function KptInputMask({ value, defaultValue = '', onValueChange, mask = '', placeholder, required = false, invalid = false, touched, onTouch, disabled = false, className, id, onBlur, 'aria-describedby': ariaDescribedBy, inputMode, ...rest }) {
15
15
  const field = useKptFieldA11y(id, 'kpt-input-mask');
16
- // Klawiatura ekranowa z maski: same tokeny `9` (telefon, kod pocztowy) → numeryczna.
16
+ // Klawiatura ekranowa z maski: same tokeny `9` (telefon, kod pocztowy) -> numeryczna.
17
17
  const tokens = [...mask].filter((char) => char in KPT_MASK_TOKENS);
18
18
  const autoInputMode = tokens.length && tokens.every((char) => char === '9') ? 'numeric' : 'text';
19
19
  const inputId = field.id;
@@ -25,7 +25,7 @@ export function KptInputMask({ value, defaultValue = '', onValueChange, mask = '
25
25
  const caret = el.selectionStart ?? raw.length;
26
26
  const formatted = kptApplyMask(raw, mask);
27
27
  setCurrent(formatted);
28
- // Gdy maska odrzuci znak, wartość się nie zmienia i React nie przerysuje pola —
28
+ // Gdy maska odrzuci znak, wartość się nie zmienia i React nie przerysuje pola -
29
29
  // wpisany znak zostałby na ekranie, więc DOM zrównujemy ręcznie.
30
30
  el.value = formatted;
31
31
  // Przepisanie `value` przenosi kursor na koniec; wraca za tyle samo znaczących znaków co przed zmianą.
@@ -9,9 +9,9 @@ Import: `import { KptInputMask } from '@konce-pt/react';`
9
9
  </span>
10
10
 
11
11
  ## Props
12
- - `value` / `defaultValue` / `onValueChange` — the formatted text
13
- - `mask`: string — `9` a digit, `a` a letter, `*` alphanumeric; everything else is a literal
14
- - `placeholder`: string — defaults to the mask itself, which doubles as a hint
12
+ - `value` / `defaultValue` / `onValueChange` - the formatted text
13
+ - `mask`: string - `9` a digit, `a` a letter, `*` alphanumeric; everything else is a literal
14
+ - `placeholder`: string - defaults to the mask itself, which doubles as a hint
15
15
  - `invalid`, `touched`, `onTouch()`
16
16
  - `className`, `ref` and every other `<input>` prop go to the input
17
17
 
@@ -22,7 +22,7 @@ digits therefore produce the same result, and deleting a literal cannot leave a
22
22
  pattern. Characters that match nothing are skipped rather than rejected, so stray letters around a
23
23
  number still format.
24
24
 
25
- Like the OTP field, the DOM is synced by hand when the mask drops a character — the value did not
25
+ Like the OTP field, the DOM is synced by hand when the mask drops a character - the value did not
26
26
  change, so React would not re-render and the character would linger on screen.
27
27
 
28
28
  ## Examples
@@ -32,7 +32,7 @@ change, so React would not re-render and the character would linger on screen.
32
32
  ## Screen reader and keyboard
33
33
  The on-screen keyboard follows the mask: only `9` tokens (phone, postal code) give
34
34
  `inputMode="numeric"`, otherwise `text`; pass `inputMode` to override it, and `autoComplete` (`tel`,
35
- `postal-code`…) so the browser can fill the field in.
35
+ `postal-code`...) so the browser can fill the field in.
36
36
 
37
37
  ## Label and description
38
38
  `id` goes to the native field, not the host; without one it comes from `KptFormField` or is
@@ -10,29 +10,29 @@ export interface KptInputNumberProps extends Omit<ComponentPropsWithRef<'div'>,
10
10
  placeholder?: string;
11
11
  /** Dopisek pokazywany za liczbą, np. ' szt.' albo 'ms'. */
12
12
  suffix?: string;
13
- /** Przyciski krokowania. `false` daje samo pole — wariant do zakresów „od–do". */
13
+ /** Przyciski krokowania. `false` daje samo pole - wariant do zakresów "od-do". */
14
14
  showButtons?: boolean;
15
- /** Id elementu fokusowalnego (nie hosta); bez niego generowane, w `KptFormField` — z wrappera. */
15
+ /** Id elementu fokusowalnego (nie hosta); bez niego generowane, w `KptFormField` - z wrappera. */
16
16
  id?: string;
17
17
  /** Nazwa dostępna, gdy kontrolki nie opisuje etykieta (`<label for>` albo `KptFormField`). */
18
18
  ariaLabel?: string | null;
19
19
  /** Oznacza pole jako wymagane atrybutem `aria-required`. */
20
20
  required?: boolean;
21
21
  disabled?: boolean;
22
- /** Tylko do odczytu — wartość widać i da się ją zaznaczyć, ale nie zmienić (także strzałkami). */
22
+ /** Tylko do odczytu - wartość widać i da się ją zaznaczyć, ale nie zmienić (także strzałkami). */
23
23
  readOnly?: boolean;
24
24
  invalid?: boolean;
25
25
  touched?: boolean;
26
26
  onTouch?: () => void;
27
27
  }
28
28
  /**
29
- * Pole liczbowe ze strzałkami krokowania. Wartość to `number | null` — puste pole ma znaczenie,
30
- * bo „brak wartości" to nie to samo co zero.
29
+ * Pole liczbowe ze strzałkami krokowania. Wartość to `number | null` - puste pole ma znaczenie,
30
+ * bo "brak wartości" to nie to samo co zero.
31
31
  *
32
- * Pole to `role="spinbutton"` (z `aria-valuemin`/`max`/`now`, a przy `suffix` — `aria-valuetext`):
33
- * `↑`/`↓` zmieniają wartość o `step`, `PageUp`/`PageDown` o dziesięć kroków. Wpisywana liczba nie
34
- * jest przycinana w trakcie pisania (inaczej „150” przy `max` 99 stawało się „99”, zanim user skończył) —
35
- * granice działają przy krokowaniu i na `blur`. Przyciski `−`/`+` stoją poza kolejnością Tab i nie
32
+ * Pole to `role="spinbutton"` (z `aria-valuemin`/`max`/`now`, a przy `suffix` - `aria-valuetext`):
33
+ * `ArrowUp`/`ArrowDown` zmieniają wartość o `step`, `PageUp`/`PageDown` o dziesięć kroków. Wpisywana liczba nie
34
+ * jest przycinana w trakcie pisania (inaczej "150" przy `max` 99 stawało się "99", zanim user skończył) -
35
+ * granice działają przy krokowaniu i na `blur`. Przyciski `-`/`+` stoją poza kolejnością Tab i nie
36
36
  * zabierają fokusu polu.
37
37
  *
38
38
  * @example
@@ -10,13 +10,13 @@ import { kptRoundTo } from "../internal/step.js";
10
10
  /** Liczba dziesiętna wpisana przez człowieka: bez `0x1A`, `1e3` i `Infinity`, które `Number()` też przyjmuje. */
11
11
  const DECIMAL = /^[-+]?(?:\d+\.?\d*|\.\d+)$/;
12
12
  /**
13
- * Pole liczbowe ze strzałkami krokowania. Wartość to `number | null` — puste pole ma znaczenie,
14
- * bo „brak wartości" to nie to samo co zero.
13
+ * Pole liczbowe ze strzałkami krokowania. Wartość to `number | null` - puste pole ma znaczenie,
14
+ * bo "brak wartości" to nie to samo co zero.
15
15
  *
16
- * Pole to `role="spinbutton"` (z `aria-valuemin`/`max`/`now`, a przy `suffix` — `aria-valuetext`):
17
- * `↑`/`↓` zmieniają wartość o `step`, `PageUp`/`PageDown` o dziesięć kroków. Wpisywana liczba nie
18
- * jest przycinana w trakcie pisania (inaczej „150” przy `max` 99 stawało się „99”, zanim user skończył) —
19
- * granice działają przy krokowaniu i na `blur`. Przyciski `−`/`+` stoją poza kolejnością Tab i nie
16
+ * Pole to `role="spinbutton"` (z `aria-valuemin`/`max`/`now`, a przy `suffix` - `aria-valuetext`):
17
+ * `ArrowUp`/`ArrowDown` zmieniają wartość o `step`, `PageUp`/`PageDown` o dziesięć kroków. Wpisywana liczba nie
18
+ * jest przycinana w trakcie pisania (inaczej "150" przy `max` 99 stawało się "99", zanim user skończył) -
19
+ * granice działają przy krokowaniu i na `blur`. Przyciski `-`/`+` stoją poza kolejnością Tab i nie
20
20
  * zabierają fokusu polu.
21
21
  *
22
22
  * @example
@@ -32,7 +32,7 @@ export function KptInputNumber({ value, defaultValue = null, onValueChange, min,
32
32
  onChange: onValueChange,
33
33
  });
34
34
  const showInvalid = invalid && (touched ?? true);
35
- /** Tekst w trakcie pisania — dopóki jest, pole pokazuje go zamiast sformatowanej wartości. */
35
+ /** Tekst w trakcie pisania - dopóki jest, pole pokazuje go zamiast sformatowanej wartości. */
36
36
  const [draft, setDraft] = useState(null);
37
37
  const clamp = useCallback((n) => {
38
38
  if (min !== undefined && n < min)
@@ -41,17 +41,17 @@ export function KptInputNumber({ value, defaultValue = null, onValueChange, min,
41
41
  return max;
42
42
  return n;
43
43
  }, [min, max]);
44
- // Zapis liczby wg aktywnego języka (PL: `12,5`), bez separatorów tysięcy — pole przyjmuje i kropkę,
44
+ // Zapis liczby wg aktywnego języka (PL: `12,5`), bez separatorów tysięcy - pole przyjmuje i kropkę,
45
45
  // i przecinek, a grupowanie cyfr rozjechałoby się z tym, co user wpisuje.
46
- // `latn`: cyfry łacińskie także w locale z własnymi (np. `ar`) — inaczej pole pokazywałoby zapis,
46
+ // `latn`: cyfry łacińskie także w locale z własnymi (np. `ar`) - inaczej pole pokazywałoby zapis,
47
47
  // którego parser niżej nie przeczyta.
48
48
  const format = new Intl.NumberFormat(activeLocale, { useGrouping: false, maximumFractionDigits: 20, numberingSystem: 'latn' });
49
49
  const display = current === null || current === undefined || Number.isNaN(current) ? '' : `${format.format(current)}${suffix}`;
50
50
  const canIncrement = max === undefined || (current ?? -Infinity) < max;
51
51
  const canDecrement = min === undefined || (current ?? Infinity) > min;
52
52
  const onInput = (event) => {
53
- // Przecinek jako separator dziesiętny i dopisek trafiają do pola razem z liczbą —
54
- // czyścimy je przed parsowaniem, żeby wpisywanie „12,5 zł" działało naturalnie.
53
+ // Przecinek jako separator dziesiętny i dopisek trafiają do pola razem z liczbą -
54
+ // czyścimy je przed parsowaniem, żeby wpisywanie "12,5 zł" działało naturalnie.
55
55
  setDraft(event.target.value);
56
56
  const raw = event.target.value.replace(suffix, '').replace(',', '.').trim();
57
57
  if (raw === '') {
@@ -5,20 +5,20 @@ A number field with stepper arrows. Import: `import { KptInputNumber } from '@ko
5
5
  ## DOM
6
6
  <div class="kpt-input-number-host">
7
7
  <div class="kpt-input-number">
8
- <button class="kpt-input-number__btn" aria-label="Decrease">…</button>
8
+ <button class="kpt-input-number__btn" aria-label="Decrease">...</button>
9
9
  <input class="kpt-input-number__input" type="text" inputmode="decimal" value="12 zł">
10
- <button class="kpt-input-number__btn" aria-label="Increase">…</button>
10
+ <button class="kpt-input-number__btn" aria-label="Increase">...</button>
11
11
  </div>
12
12
  </div>
13
13
 
14
14
  ## Props
15
- - `value` / `defaultValue` / `onValueChange` — `number | null`
15
+ - `value` / `defaultValue` / `onValueChange` - `number | null`
16
16
  - `min`, `max`, `step` (default 1)
17
- - `placeholder`, `suffix` — text shown after the number, e.g. ' szt.' or 'ms'
18
- - `showButtons`: boolean (default true) — `false` leaves the bare field
19
- - `disabled`, `readOnly`, `invalid`, `touched`, `onTouch()` — `readOnly` leaves the value selectable but
17
+ - `placeholder`, `suffix` - text shown after the number, e.g. ' szt.' or 'ms'
18
+ - `showButtons`: boolean (default true) - `false` leaves the bare field
19
+ - `disabled`, `readOnly`, `invalid`, `touched`, `onTouch()` - `readOnly` leaves the value selectable but
20
20
  blocks typing, the arrows and the buttons (`aria-readonly`)
21
- - `locale`, `dictionary` — i18n overrides for this component only
21
+ - `locale`, `dictionary` - i18n overrides for this component only
22
22
 
23
23
  ## Null is a value
24
24
  The value is `number | null`, not `number`: an empty field means "no value", which is not the same
@@ -27,8 +27,8 @@ nothing to step from.
27
27
 
28
28
  ## A text input, not a number input
29
29
  The field is `type="text"` with `inputmode="decimal"`, so the suffix can live inside it and a comma
30
- works as the decimal separator — typing "12,5 zł" parses correctly. A native `type="number"` would
31
- reject both. Values out of range are clamped on blur and when stepping — not while typing.
30
+ works as the decimal separator - typing "12,5 zł" parses correctly. A native `type="number"` would
31
+ reject both. Values out of range are clamped on blur and when stepping - not while typing.
32
32
 
33
33
  ## i18n
34
34
  The stepper labels come from `inputNumber.decrement` and `inputNumber.increment`.
@@ -39,16 +39,16 @@ The stepper labels come from `inputNumber.decrement` and `inputNumber.increment`
39
39
 
40
40
  ## Keyboard
41
41
  The field is `role="spinbutton"` with `aria-valuemin`/`aria-valuemax`/`aria-valuenow` (and
42
- `aria-valuetext` with the `suffix`, "5 pcs"). `↑`/`↓` change the value by `step`,
42
+ `aria-valuetext` with the `suffix`, "5 pcs"). `ArrowUp`/`ArrowDown` change the value by `step`,
43
43
  `PageUp`/`PageDown` by ten steps; stepping is rounded to the precision of `step` or of the current
44
44
  value, whichever is finer (`1.25` + 1 gives `2.25`, not `2`). Only a plain decimal is accepted while
45
- typing — `0x1A`, `1e3` and `Infinity` are ignored. A typed value is
46
- **not** clamped while typing ("150" with `max` 99 stays "150", so the form's `max()` can report it) —
47
- it is clamped on blur. The `−`/`+` buttons sit outside the Tab order and do not take focus from the
45
+ typing - `0x1A`, `1e3` and `Infinity` are ignored. A typed value is
46
+ **not** clamped while typing ("150" with `max` 99 stays "150", so the form's `max()` can report it) -
47
+ it is clamped on blur. The `-`/`+` buttons sit outside the Tab order and do not take focus from the
48
48
  field, so focus never drops to `<body>` when a button goes disabled at a limit.
49
49
 
50
50
  ## Screen reader and keyboard
51
- The value is shown in the active locale's notation (PL `12,5`), without thousands separators — the
51
+ The value is shown in the active locale's notation (PL `12,5`), without thousands separators - the
52
52
  field accepts both a dot and a comma, and digit grouping would clash with what the user types.
53
53
 
54
54
  ## Label and description
@@ -6,29 +6,29 @@ export interface KptInputOtpProps extends Omit<ComponentPropsWithRef<'div'>, 'on
6
6
  onValueChange?: (value: string) => void;
7
7
  length?: number;
8
8
  /**
9
- * Co ile komórek wstawić separator, licząc od lewej (`3` przy `length` 9 → `[][][]–[][][]–[][][]`).
10
- * `0` (domyślnie) — bez grup. Separator jest wyłącznie wizualny: wartość to same znaki.
9
+ * Co ile komórek wstawić separator, licząc od lewej (`3` przy `length` 9 -> `[][][]-[][][]-[][][]`).
10
+ * `0` (domyślnie) - bez grup. Separator jest wyłącznie wizualny: wartość to same znaki.
11
11
  */
12
12
  groupSize?: number;
13
13
  /** Znak między grupami komórek. */
14
14
  groupSeparator?: string;
15
15
  /** Dopuszcza wyłącznie cyfry i przełącza klawiaturę mobilną na numeryczną. */
16
16
  integerOnly?: boolean;
17
- /** Id pierwszej komórki (nie hosta) — klik w etykietę zaczyna wpisywanie od początku. */
17
+ /** Id pierwszej komórki (nie hosta) - klik w etykietę zaczyna wpisywanie od początku. */
18
18
  id?: string;
19
19
  /** Nazwa grupy komórek, gdy nie opisuje jej etykieta (`KptFormField`). */
20
20
  ariaLabel?: string | null;
21
21
  disabled?: boolean;
22
- /** Tylko do odczytu — kod widać, nie da się go zmienić. */
22
+ /** Tylko do odczytu - kod widać, nie da się go zmienić. */
23
23
  readOnly?: boolean;
24
- /** Pole wymagane — `aria-required` na komórkach. */
24
+ /** Pole wymagane - `aria-required` na komórkach. */
25
25
  required?: boolean;
26
26
  invalid?: boolean;
27
27
  touched?: boolean;
28
28
  onTouch?: () => void;
29
29
  }
30
30
  /**
31
- * Pole kodu jednorazowego (OTP/PIN) — N osobnych pól, automatyczne przejście do następnego
31
+ * Pole kodu jednorazowego (OTP/PIN) - N osobnych pól, automatyczne przejście do następnego
32
32
  * i wklejanie całego kodu naraz. Wartością są wpisane znaki **bez dziur** (`'13'`, nie `'1 3'`), więc
33
33
  * walidator długości i backend widzą tyle znaków, ile naprawdę wpisano.
34
34
  *
@@ -6,7 +6,7 @@ import { useControllableState } from "../internal/use-controllable-state.js";
6
6
  import { useKptFieldA11y } from "../form-field/form-field-context.js";
7
7
  import { useKptMessages } from "../i18n/i18n-context.js";
8
8
  /**
9
- * Pole kodu jednorazowego (OTP/PIN) — N osobnych pól, automatyczne przejście do następnego
9
+ * Pole kodu jednorazowego (OTP/PIN) - N osobnych pól, automatyczne przejście do następnego
10
10
  * i wklejanie całego kodu naraz. Wartością są wpisane znaki **bez dziur** (`'13'`, nie `'1 3'`), więc
11
11
  * walidator długości i backend widzą tyle znaków, ile naprawdę wpisano.
12
12
  *
@@ -14,7 +14,7 @@ import { useKptMessages } from "../i18n/i18n-context.js";
14
14
  * <KptInputOtp value={code} onValueChange={setCode} length={6} integerOnly />
15
15
  * <KptInputOtp value={code} onValueChange={setCode} length={9} groupSize={3} />
16
16
  */
17
- export function KptInputOtp({ value, defaultValue = '', onValueChange, length = 6, groupSize = 0, groupSeparator = '–', integerOnly = false, id, ariaLabel = null, disabled = false, readOnly = false, required = false, invalid = false, touched, onTouch, locale, dictionary, className, ...rest }) {
17
+ export function KptInputOtp({ value, defaultValue = '', onValueChange, length = 6, groupSize = 0, groupSeparator = '-', integerOnly = false, id, ariaLabel = null, disabled = false, readOnly = false, required = false, invalid = false, touched, onTouch, locale, dictionary, className, ...rest }) {
18
18
  const { t } = useKptMessages({ locale, dictionary });
19
19
  const field = useKptFieldA11y(id, 'kpt-input-otp');
20
20
  const [current, setCurrent] = useControllableState({ value, defaultValue, onChange: onValueChange });
@@ -22,8 +22,8 @@ export function KptInputOtp({ value, defaultValue = '', onValueChange, length =
22
22
  /*
23
23
  * Komórki trzymają układ osobno od wartości: wyczyszczenie środkowej zostawia w niej pustkę,
24
24
  * zamiast przesuwać resztę kodu w lewo, a wartość to same znaki. Zmiana wartości z zewnątrz
25
- * (inna niż złożenie bieżących komórek) układa znaki od początku — wzorzec „poprzednia
26
- * wartość w stanie”, bez efektu.
25
+ * (inna niż złożenie bieżących komórek) układa znaki od początku - wzorzec "poprzednia
26
+ * wartość w stanie", bez efektu.
27
27
  */
28
28
  const toCells = (text) => Array.from({ length }, (_, index) => text[index] ?? '');
29
29
  const [cells, setCells] = useState(() => toCells(current));
@@ -32,7 +32,7 @@ export function KptInputOtp({ value, defaultValue = '', onValueChange, length =
32
32
  setCells(toCells(current));
33
33
  const shown = inSync ? cells : toCells(current);
34
34
  const charAt = (index) => shown[index] ?? '';
35
- /** Zapis komórek i złożonej z nich wartości — jedno miejsce, żeby układ i model się nie rozjechały. */
35
+ /** Zapis komórek i złożonej z nich wartości - jedno miejsce, żeby układ i model się nie rozjechały. */
36
36
  const commitCells = (next) => {
37
37
  setCells(next);
38
38
  setCurrent(next.join(''));
@@ -42,7 +42,7 @@ export function KptInputOtp({ value, defaultValue = '', onValueChange, length =
42
42
  next[index] = char;
43
43
  commitCells(next);
44
44
  };
45
- /** Następna/poprzednia komórka — po polach, nie po rodzeństwie, bo między grupami stoi separator. */
45
+ /** Następna/poprzednia komórka - po polach, nie po rodzeństwie, bo między grupami stoi separator. */
46
46
  const focusSibling = (el, direction) => {
47
47
  const cells = [...(el.closest('.kpt-input-otp')?.querySelectorAll('input') ?? [])];
48
48
  cells[cells.indexOf(el) + direction]?.focus();
@@ -50,7 +50,7 @@ export function KptInputOtp({ value, defaultValue = '', onValueChange, length =
50
50
  /** Czy za komórką `index` kończy się grupa (a nie cały kod). */
51
51
  const group = Math.floor(groupSize);
52
52
  const separatorAfter = (index) => group >= 1 && (index + 1) % group === 0 && index < length - 1;
53
- /** Wpisuje `text` od komórki `start` (bez spacji i — przy `integerOnly` — bez nie-cyfr). */
53
+ /** Wpisuje `text` od komórki `start` (bez spacji i - przy `integerOnly` - bez nie-cyfr). */
54
54
  const fillFrom = (start, text, el) => {
55
55
  let chars = text.replace(/\s/g, '');
56
56
  if (integerOnly)
@@ -59,7 +59,7 @@ export function KptInputOtp({ value, defaultValue = '', onValueChange, length =
59
59
  for (let k = 0; k < chars.length && start + k < length; k += 1)
60
60
  arr[start + k] = chars[k];
61
61
  commitCells(arr);
62
- // Fokus na pierwszą pustą komórkę, a przy komplecie — na ostatnią.
62
+ // Fokus na pierwszą pustą komórkę, a przy komplecie - na ostatnią.
63
63
  const inputs = [...(el.closest('.kpt-input-otp')?.querySelectorAll('input') ?? [])];
64
64
  const empty = arr.findIndex((char) => char === '');
65
65
  inputs[empty >= 0 ? empty : inputs.length - 1]?.focus();
@@ -69,7 +69,7 @@ export function KptInputOtp({ value, defaultValue = '', onValueChange, length =
69
69
  if (readOnly)
70
70
  return;
71
71
  // Kilka znaków naraz to autouzupełnienie kodu z SMS (`one-time-code`) albo wklejenie przez
72
- // klawiaturę ekranową — rozkładamy je po komórkach od bieżącej. Dwa znaki w zajętej komórce
72
+ // klawiaturę ekranową - rozkładamy je po komórkach od bieżącej. Dwa znaki w zajętej komórce
73
73
  // to zwykłe nadpisanie: stary znak + nowy.
74
74
  if (el.value.length > 1 && !(el.value.length === 2 && charAt(index))) {
75
75
  const text = el.value;
@@ -102,7 +102,7 @@ export function KptInputOtp({ value, defaultValue = '', onValueChange, length =
102
102
  return;
103
103
  fillFrom(0, event.clipboardData.getData('text'), event.currentTarget);
104
104
  };
105
- /** „Dotknięcie” dopiero przy wyjściu fokusu z całej grupy, nie przy przejściu między komórkami. */
105
+ /** "Dotknięcie" dopiero przy wyjściu fokusu z całej grupy, nie przy przejściu między komórkami. */
106
106
  const onGroupBlur = (event) => {
107
107
  const next = event.relatedTarget;
108
108
  if (!next || !event.currentTarget.contains(next))
@@ -1,25 +1,25 @@
1
1
  # KptInputOtp (@konce-pt/react)
2
2
 
3
- A one-time code field (OTP / PIN) — N separate boxes, auto-advance and paste.
3
+ A one-time code field (OTP / PIN) - N separate boxes, auto-advance and paste.
4
4
  Import: `import { KptInputOtp } from '@konce-pt/react';`
5
5
 
6
6
  ## DOM
7
7
  <div class="kpt-input-otp-host">
8
8
  <div class="kpt-input-otp">
9
9
  <input class="kpt-input-otp__cell" type="text" inputmode="numeric" maxlength="1" value="1">
10
- …N cells…
10
+ ...N cells...
11
11
  </div>
12
12
  </div>
13
13
 
14
14
  ## Props
15
- - `value` / `defaultValue` / `onValueChange` — one string, the characters joined
15
+ - `value` / `defaultValue` / `onValueChange` - one string, the characters joined
16
16
  - `length`: number (default 6)
17
- - `integerOnly`: boolean — digits only, and a numeric keyboard on mobile
17
+ - `integerOnly`: boolean - digits only, and a numeric keyboard on mobile
18
18
  - `disabled`, `invalid`, `touched`, `onTouch()`
19
19
 
20
20
  ## One string, N boxes
21
21
  The value is a single string while the UI is N inputs, so a gap in the middle has to be
22
- expressible. Writing pads with spaces, replaces the character and trims trailing spaces — that way
22
+ expressible. Writing pads with spaces, replaces the character and trims trailing spaces - that way
23
23
  a code with a hole round-trips and a single character does not turn into one followed by blanks.
24
24
 
25
25
  The DOM of a cell is also synced by hand after a rejected character: the value did not change, so
@@ -28,7 +28,7 @@ React has nothing to re-render, and the typed character would otherwise stay on
28
28
  ## Keyboard and paste
29
29
  A character moves focus to the next cell; Backspace in an empty cell moves back; ArrowLeft and
30
30
  ArrowRight walk the cells; focus selects the content so typing overwrites. Pasting fills the whole
31
- code at once — with `integerOnly` everything non-numeric is stripped first, so a copied
31
+ code at once - with `integerOnly` everything non-numeric is stripped first, so a copied
32
32
  "123-456" still lands correctly.
33
33
 
34
34
  ## Examples
@@ -38,7 +38,7 @@ code at once — with `integerOnly` everything non-numeric is stripped first, so
38
38
  ## Screen reader and keyboard
39
39
  The first cell has `autocomplete="one-time-code"`, so phones offer the code from an SMS; a code that
40
40
  arrives in one cell at once (autofill, an on-screen keyboard paste) is spread over the cells like a
41
- paste. `touch` fires when focus leaves the whole group — not after a paste, and not when moving
41
+ paste. `touch` fires when focus leaves the whole group - not after a paste, and not when moving
42
42
  between cells.
43
43
 
44
44
  ## Label and description
@@ -61,8 +61,8 @@ keypad for a PIN instead of the full keyboard.
61
61
 
62
62
  ## Groups
63
63
  `groupSize` (default `0` = no groups) inserts a separator after every N boxes, counted from the
64
- left; `groupSeparator` sets the character (default `–`). With `length` 9 and `groupSize` 3 you get
65
- `[][][]–[][][]–[][][]`. The separator is purely visual (`aria-hidden`): the value is the bare characters
64
+ left; `groupSeparator` sets the character (default `-`). With `length` 9 and `groupSize` 3 you get
65
+ `[][][]-[][][]-[][][]`. The separator is purely visual (`aria-hidden`): the value is the bare characters
66
66
  (`"123456789"`), each box keeps its name "Character 4 of 9", and arrows/Backspace jump over it.
67
67
 
68
68
  <KptInputOtp value={code} onValueChange={setCode} length={9} groupSize={3} integerOnly />
@@ -1,7 +1,7 @@
1
1
  /** Zawija `Tab` / `Shift+Tab` w obrębie `panel`. */
2
2
  export declare function trapTab(panel: HTMLElement, event: KeyboardEvent): void;
3
3
  /**
4
- * Fokus na „aktywną” komórkę panelu: dzień `iso`, przystanek siatki komórek, a bez nich — pierwszy
4
+ * Fokus na "aktywną" komórkę panelu: dzień `iso`, przystanek siatki komórek, a bez nich - pierwszy
5
5
  * element panelu (zegar). Panel w nakładce jest niewidoczny do pierwszego pomiaru, więc wołający
6
6
  * odkłada to na `requestAnimationFrame`.
7
7
  */
@@ -1,9 +1,9 @@
1
1
  /*
2
- * Fokus w panelu kalendarza — wspólny dla `KptDatepicker` i `KptDateRange`. Panel stoi
2
+ * Fokus w panelu kalendarza - wspólny dla `KptDatepicker` i `KptDateRange`. Panel stoi
3
3
  * w nakładce na końcu strony, więc `Tab` z ostatniego elementu uciekłby poza niego; zawijamy go
4
4
  * w obrębie panelu, jak w oknie dialogowym.
5
5
  *
6
- * Bliźniak w porcie Angulara: `shared/calendar-focus.ts` — zmiana zachowania w obu.
6
+ * Bliźniak w porcie Angulara: `shared/calendar-focus.ts` - zmiana zachowania w obu.
7
7
  */
8
8
  const FOCUSABLE = 'button:not(:disabled):not([tabindex="-1"]), input:not(:disabled), [tabindex="0"]';
9
9
  /** Zawija `Tab` / `Shift+Tab` w obrębie `panel`. */
@@ -24,7 +24,7 @@ export function trapTab(panel, event) {
24
24
  }
25
25
  }
26
26
  /**
27
- * Fokus na „aktywną” komórkę panelu: dzień `iso`, przystanek siatki komórek, a bez nich — pierwszy
27
+ * Fokus na "aktywną" komórkę panelu: dzień `iso`, przystanek siatki komórek, a bez nich - pierwszy
28
28
  * element panelu (zegar). Panel w nakładce jest niewidoczny do pierwszego pomiaru, więc wołający
29
29
  * odkłada to na `requestAnimationFrame`.
30
30
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Sklejanie klas CSS. Odpowiednik `clsx` w kilkunastu linijkach — biblioteka
2
+ * Sklejanie klas CSS. Odpowiednik `clsx` w kilkunastu linijkach - biblioteka
3
3
  * zostaje bez zależności runtime, a konsument nie ryzykuje konfliktu wersji.
4
4
  *
5
5
  * Wartości fałszywe są pomijane, tablice spłaszczane, duplikaty usuwane
@@ -2,13 +2,13 @@
2
2
  export declare const KPT_MASK_TOKENS: Readonly<Record<string, RegExp>>;
3
3
  /**
4
4
  * Maska przepisuje wejście od zera: z tekstu bierze wyłącznie znaki pasujące do kolejnych
5
- * tokenów, a literały wstawia sama. Dzięki temu wklejenie „48123456789” i wpisanie „(48) 123…”
5
+ * tokenów, a literały wstawia sama. Dzięki temu wklejenie "48123456789" i wpisanie "(48) 123..."
6
6
  * dają ten sam wynik, a usunięcie literału nie zostawia dziury we wzorcu.
7
7
  */
8
8
  export declare function kptApplyMask(raw: string, mask: string): string;
9
9
  /**
10
10
  * Pozycja kursora po przeformatowaniu. Liczy znaczące znaki (te, które maska zabrała) przed
11
- * kursorem w surowym tekście i stawia kursor za tyloma samymi znakami w wyniku — poprawienie
11
+ * kursorem w surowym tekście i stawia kursor za tyloma samymi znakami w wyniku - poprawienie
12
12
  * cyfry w środku numeru nie przerzuca kursora na koniec pola.
13
13
  */
14
14
  export declare function kptMaskCaret(raw: string, caret: number, mask: string): number;
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Maska znakowa `kpt-input-mask`. Bliźniak w porcie Angulara (`shared/mask.ts`) — zmiana w obu.
2
+ * Maska znakowa `kpt-input-mask`. Bliźniak w porcie Angulara (`shared/mask.ts`) - zmiana w obu.
3
3
  */
4
4
  /** Tokeny maski: `9` = cyfra, `a` = litera (także `ą`, `ł`, `ß`), `*` = litera albo cyfra. */
5
5
  export const KPT_MASK_TOKENS = {
@@ -9,7 +9,7 @@ export const KPT_MASK_TOKENS = {
9
9
  };
10
10
  /**
11
11
  * Maska przepisuje wejście od zera: z tekstu bierze wyłącznie znaki pasujące do kolejnych
12
- * tokenów, a literały wstawia sama. Dzięki temu wklejenie „48123456789” i wpisanie „(48) 123…”
12
+ * tokenów, a literały wstawia sama. Dzięki temu wklejenie "48123456789" i wpisanie "(48) 123..."
13
13
  * dają ten sam wynik, a usunięcie literału nie zostawia dziury we wzorcu.
14
14
  */
15
15
  export function kptApplyMask(raw, mask) {
@@ -37,7 +37,7 @@ export function kptApplyMask(raw, mask) {
37
37
  }
38
38
  /**
39
39
  * Pozycja kursora po przeformatowaniu. Liczy znaczące znaki (te, które maska zabrała) przed
40
- * kursorem w surowym tekście i stawia kursor za tyloma samymi znakami w wyniku — poprawienie
40
+ * kursorem w surowym tekście i stawia kursor za tyloma samymi znakami w wyniku - poprawienie
41
41
  * cyfry w środku numeru nie przerzuca kursora na koniec pola.
42
42
  */
43
43
  export function kptMaskCaret(raw, caret, mask) {
@@ -45,7 +45,7 @@ export function kptMaskCaret(raw, caret, mask) {
45
45
  if (!mask)
46
46
  return Math.min(caret, formatted.length);
47
47
  const before = kptApplyMask(raw.slice(0, caret), mask);
48
- // Ile znaczących znaków jest przed kursorem — liczone na wyniku, więc literały się nie liczą.
48
+ // Ile znaczących znaków jest przed kursorem - liczone na wyniku, więc literały się nie liczą.
49
49
  let significant = 0;
50
50
  for (let i = 0; i < before.length; i += 1)
51
51
  if (KPT_MASK_TOKENS[mask[i]])
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Klucz Reacta dla opcji kontrolki generycznej: wartość prymitywna jako tekst, obiekt — pozycja.
3
- * `String(obiekt)` dawałby „[object Object]” dla każdej opcji, czyli zdublowane klucze i stan
2
+ * Klucz Reacta dla opcji kontrolki generycznej: wartość prymitywna jako tekst, obiekt - pozycja.
3
+ * `String(obiekt)` dawałby "[object Object]" dla każdej opcji, czyli zdublowane klucze i stan
4
4
  * przenoszony między opcjami przy zmianie listy.
5
5
  */
6
6
  export declare function optionKey(value: unknown, index: number): string;
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Klucz Reacta dla opcji kontrolki generycznej: wartość prymitywna jako tekst, obiekt — pozycja.
3
- * `String(obiekt)` dawałby „[object Object]” dla każdej opcji, czyli zdublowane klucze i stan
2
+ * Klucz Reacta dla opcji kontrolki generycznej: wartość prymitywna jako tekst, obiekt - pozycja.
3
+ * `String(obiekt)` dawałby "[object Object]" dla każdej opcji, czyli zdublowane klucze i stan
4
4
  * przenoszony między opcjami przy zmianie listy.
5
5
  */
6
6
  export function optionKey(value, index) {