@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,6 +1,6 @@
1
1
  # KptChatTyping (@konce-pt/react/chat)
2
2
 
3
- The typing indicator — three dots and a line saying who is typing.
3
+ The typing indicator - three dots and a line saying who is typing.
4
4
  Import: `import { KptChatTyping } from '@konce-pt/react/chat';`
5
5
 
6
6
  ## DOM
@@ -11,13 +11,13 @@ Import: `import { KptChatTyping } from '@konce-pt/react/chat';`
11
11
  <span class="kpt-chat-typing__dot"></span>
12
12
  <span class="kpt-chat-typing__dot"></span>
13
13
  </span>
14
- <span class="kpt-chat-typing__label">Anna is typing…</span>
14
+ <span class="kpt-chat-typing__label">Anna is typing...</span>
15
15
  </div>
16
16
  </div>
17
17
 
18
18
  ## Props
19
- - `authors`: `KptChatAuthor[]` — an empty list renders nothing at all
20
- - `label`: string — your own wording instead of the dictionary's
19
+ - `authors`: `KptChatAuthor[]` - an empty list renders nothing at all
20
+ - `label`: string - your own wording instead of the dictionary's
21
21
  - `className`, `ref` and every other `<div>` prop go to the host
22
22
 
23
23
  ## One name, then a headcount
@@ -27,7 +27,7 @@ nobody reads it anyway.
27
27
  ## Examples
28
28
  <KptChatTyping authors={[anna]} />
29
29
  <KptChatTyping authors={typing} />
30
- <KptChatTyping label="The assistant is thinking…" />
30
+ <KptChatTyping label="The assistant is thinking..." />
31
31
 
32
32
  ## i18n
33
33
  `typing` (`{name}`) and `typingMany` (`{count}`) from the `chat` namespace.
@@ -37,5 +37,5 @@ The bubble `--kpt-color-surface-variant`, the dots `--kpt-color-text-muted`.
37
37
 
38
38
  ## Accessibility
39
39
  `role="status"` with `aria-live="polite"` announces the indicator without interrupting a message
40
- being read. Under `prefers-reduced-motion` the dots stop bouncing and pulse instead — they are the
40
+ being read. Under `prefers-reduced-motion` the dots stop bouncing and pulse instead - they are the
41
41
  only carrier of "someone is typing", so switching them off entirely would remove the message.
@@ -1,20 +1,27 @@
1
1
  import { type ComponentPropsWithRef, type ReactNode } from 'react';
2
2
  import type { KptHostProps } from '../internal/types.ts';
3
+ import { type KptToggleMotion } from '@konce-pt/motion';
3
4
  export interface KptCheckboxProps extends Omit<ComponentPropsWithRef<'input'>, 'type' | 'required'> {
5
+ /**
6
+ * Ruch przełączania: `spring` - pole wskakuje, a ptaszek rysuje się kreską; `fade` - spokojne przejście koloru i znaku; `none` - bez ruchu.
7
+ * Bez wartości bierze `toggle` z `KptMotionProvider` (domyślnie `spring`); `enabled={false}` i systemowe
8
+ * "ogranicz ruch" wyłączają go zawsze.
9
+ */
10
+ toggleMotion?: KptToggleMotion;
4
11
  /** Etykieta obok pola. Bogatszą treść podaj jako `children`. */
5
12
  label?: string;
6
13
  /** Oznacza pole jako wymagane atrybutem `aria-required`, a NIE natywnym `required`. */
7
14
  required?: boolean;
8
15
  /**
9
- * Stan pośredni („część zaznaczona”) — dla pola „zaznacz wszystko” nad listą. To właściwość DOM,
10
- * nie atrybut, więc ustawia ją komponent; czytnik ogłasza „częściowo zaznaczone”.
16
+ * Stan pośredni ("część zaznaczona") - dla pola "zaznacz wszystko" nad listą. To właściwość DOM,
17
+ * nie atrybut, więc ustawia ją komponent; czytnik ogłasza "częściowo zaznaczone".
11
18
  */
12
19
  indeterminate?: boolean;
13
20
  /** Pole jest nieprawidłowe. Widoczne dopiero, gdy `touched` też jest prawdziwe. */
14
21
  invalid?: boolean;
15
22
  /** Czy pole było dotknięte; pominięty = stan błędu pokazuje się od razu po `invalid`. */
16
23
  touched?: boolean;
17
- /** Wygodniejszy odpowiednik `onChange` — dostaje samo zaznaczenie. */
24
+ /** Wygodniejszy odpowiednik `onChange` - dostaje samo zaznaczenie. */
18
25
  onCheckedChange?: (checked: boolean) => void;
19
26
  /** Wywoływane na `blur`. */
20
27
  onTouch?: () => void;
@@ -24,15 +31,15 @@ export interface KptCheckboxProps extends Omit<ComponentPropsWithRef<'input'>, '
24
31
  }
25
32
  /**
26
33
  * Pole wyboru (checkbox). Cały układ niesie `<label>`, więc kliknięcie w etykietę przełącza pole
27
- * bez `htmlFor` — natywny `<input>` w środku odpowiada za semantykę i klawiaturę.
34
+ * bez `htmlFor` - natywny `<input>` w środku odpowiada za semantykę i klawiaturę.
28
35
  *
29
36
  * Działa kontrolowane (`checked` + `onCheckedChange`) i niekontrolowane (`defaultChecked`).
30
37
  *
31
38
  * `className` trafia na blok `.kpt-checkbox`, a pozostałe propsy (`name`, `value`, `ref`,
32
- * handlery) na natywny `<input>` — tam, gdzie oczekuje ich formularz.
39
+ * handlery) na natywny `<input>` - tam, gdzie oczekuje ich formularz.
33
40
  *
34
41
  * @example
35
42
  * <KptCheckbox name="terms" label="Akceptuję regulamin" />
36
43
  * <KptCheckbox checked={on} onCheckedChange={setOn} />
37
44
  */
38
- export declare function KptCheckbox({ label, required, invalid, touched, onCheckedChange, onTouch, hostProps, className, disabled, onChange, onBlur, children, 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedBy, id, indeterminate, ref, ...rest }: Readonly<KptCheckboxProps>): import("react").JSX.Element;
45
+ export declare function KptCheckbox({ label, required, invalid, touched, onCheckedChange, onTouch, hostProps, className, disabled, readOnly, onClick, onChange, onBlur, children, 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedBy, id, indeterminate, toggleMotion, ref, ...rest }: Readonly<KptCheckboxProps>): import("react").JSX.Element;
@@ -1,22 +1,25 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { useCallback, useEffect, useRef } from 'react';
3
4
  import { composeRefs } from "../internal/compose-refs.js";
4
5
  import { cn } from "../internal/cn.js";
5
6
  import { joinIds, useKptFieldA11y } from "../form-field/form-field-context.js";
7
+ import { playInvalidMotion, playPopMotion, resolveToggleMotion } from '@konce-pt/motion';
8
+ import { useKptMotion } from "../motion/motion-context.js";
6
9
  /**
7
10
  * Pole wyboru (checkbox). Cały układ niesie `<label>`, więc kliknięcie w etykietę przełącza pole
8
- * bez `htmlFor` — natywny `<input>` w środku odpowiada za semantykę i klawiaturę.
11
+ * bez `htmlFor` - natywny `<input>` w środku odpowiada za semantykę i klawiaturę.
9
12
  *
10
13
  * Działa kontrolowane (`checked` + `onCheckedChange`) i niekontrolowane (`defaultChecked`).
11
14
  *
12
15
  * `className` trafia na blok `.kpt-checkbox`, a pozostałe propsy (`name`, `value`, `ref`,
13
- * handlery) na natywny `<input>` — tam, gdzie oczekuje ich formularz.
16
+ * handlery) na natywny `<input>` - tam, gdzie oczekuje ich formularz.
14
17
  *
15
18
  * @example
16
19
  * <KptCheckbox name="terms" label="Akceptuję regulamin" />
17
20
  * <KptCheckbox checked={on} onCheckedChange={setOn} />
18
21
  */
19
- export function KptCheckbox({ label = '', required = false, invalid = false, touched, onCheckedChange, onTouch, hostProps, className, disabled = false, onChange, onBlur, children, 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedBy, id, indeterminate = false, ref, ...rest }) {
22
+ export function KptCheckbox({ label = '', required = false, invalid = false, touched, onCheckedChange, onTouch, hostProps, className, disabled = false, readOnly = false, onClick, onChange, onBlur, children, 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedBy, id, indeterminate = false, toggleMotion, ref, ...rest }) {
20
23
  const inputRef = useRef(null);
21
24
  useEffect(() => {
22
25
  if (inputRef.current)
@@ -25,13 +28,36 @@ export function KptCheckbox({ label = '', required = false, invalid = false, tou
25
28
  const field = useKptFieldA11y(id, 'kpt-checkbox');
26
29
  const { className: hostClassName, ...hostRest } = hostProps ?? {};
27
30
  const showInvalid = invalid && (touched ?? true);
31
+ const motion = resolveToggleMotion(toggleMotion, useKptMotion());
32
+ const markRef = useRef(null);
33
+ const wasInvalid = useRef(null);
34
+ // Sygnał błędu przy przejściu "poprawne -> błędne" (nie przy błędzie obecnym od startu): pierścień
35
+ // w kolorze błędu i krótkie potrząśnięcie. W błędnym `KptFormField` potrząsa już on - tu sam pierścień.
36
+ useEffect(() => {
37
+ const before = wasInvalid.current;
38
+ wasInvalid.current = showInvalid;
39
+ const el = markRef.current;
40
+ if (!showInvalid || before !== false || motion !== 'spring' || !el)
41
+ return;
42
+ playInvalidMotion(el, { shake: !el.closest('.kpt-form-field--invalid') });
43
+ }, [showInvalid, motion]);
28
44
  const handleChange = useCallback((event) => {
29
45
  onChange?.(event);
30
46
  onCheckedChange?.(event.target.checked);
31
- }, [onChange, onCheckedChange]);
47
+ // Wskoczenie po zmianie z ręki - z handlera, nie z CSS, bo reguła na `:checked` grałaby przy starcie.
48
+ const mark = event.currentTarget.nextElementSibling;
49
+ if (motion === 'spring' && mark instanceof HTMLElement)
50
+ playPopMotion(mark);
51
+ }, [onChange, onCheckedChange, motion]);
32
52
  const handleBlur = useCallback((event) => {
33
53
  onBlur?.(event);
34
54
  onTouch?.();
35
55
  }, [onBlur, onTouch]);
36
- return (_jsx("span", { className: cn('kpt-checkbox-host', hostClassName), ...hostRest, children: _jsxs("label", { className: cn('kpt-checkbox', disabled && 'kpt-checkbox--disabled', className), children: [_jsx("input", { type: "checkbox", className: "kpt-checkbox__input", ref: composeRefs(inputRef, ref), id: field.id, "aria-describedby": joinIds(ariaDescribedBy, field.describedBy), disabled: disabled, "aria-required": required || undefined, "aria-invalid": ariaInvalid ?? (showInvalid || undefined), onChange: handleChange, onBlur: handleBlur, ...rest }), _jsxs("span", { className: "kpt-checkbox__box", "aria-hidden": "true", children: [_jsx("svg", { viewBox: "0 0 16 16", className: "kpt-checkbox__check", children: _jsx("path", { d: "M13 4.5 6.5 11 3 7.5" }) }), _jsx("svg", { viewBox: "0 0 16 16", className: "kpt-checkbox__dash", children: _jsx("path", { d: "M4 8h8" }) })] }), label ? _jsx("span", { className: "kpt-checkbox__label", children: label }) : null, children] }) }));
56
+ return (_jsx("span", { className: cn('kpt-checkbox-host', hostClassName), ...hostRest, children: _jsxs("label", { className: cn('kpt-checkbox', disabled && 'kpt-checkbox--disabled', className), "data-motion": motion, children: [_jsx("input", { type: "checkbox", className: "kpt-checkbox__input", ref: composeRefs(inputRef, ref), id: field.id, "aria-describedby": joinIds(ariaDescribedBy, field.describedBy), disabled: disabled, "aria-required": required || undefined, "aria-readonly": readOnly || undefined,
57
+ // Natywne `readonly` nie działa na polach wyboru - klik (i Spacja) jest blokowany ręcznie.
58
+ onClick: (event) => {
59
+ if (readOnly)
60
+ event.preventDefault();
61
+ onClick?.(event);
62
+ }, "aria-invalid": ariaInvalid ?? (showInvalid || undefined), onChange: handleChange, onBlur: handleBlur, ...rest }), _jsxs("span", { ref: markRef, className: "kpt-checkbox__box", "aria-hidden": "true", children: [_jsx("svg", { viewBox: "0 0 16 16", className: "kpt-checkbox__check", children: _jsx("path", { d: "M13 4.5 6.5 11 3 7.5", pathLength: 1 }) }), _jsx("svg", { viewBox: "0 0 16 16", className: "kpt-checkbox__dash", children: _jsx("path", { d: "M4 8h8" }) })] }), label ? _jsx("span", { className: "kpt-checkbox__label", children: label }) : null, children] }) }));
37
63
  }
@@ -1,26 +1,27 @@
1
1
  # KptCheckbox (@konce-pt/react)
2
2
 
3
3
  A checkbox. The whole layout is a `<label>`, so clicking the text toggles the field with no
4
- `htmlFor` — the native `<input>` inside carries the semantics and the keyboard.
4
+ `htmlFor` - the native `<input>` inside carries the semantics and the keyboard.
5
5
  Import: `import { KptCheckbox } from '@konce-pt/react';`
6
6
 
7
7
  ## DOM
8
8
  <span class="kpt-checkbox-host">
9
9
  <label class="kpt-checkbox">
10
10
  <input type="checkbox" class="kpt-checkbox__input">
11
- <span class="kpt-checkbox__box" aria-hidden="true"><svg class="kpt-checkbox__check">…</svg></span>
11
+ <span class="kpt-checkbox__box" aria-hidden="true"><svg class="kpt-checkbox__check">...</svg></span>
12
12
  <span class="kpt-checkbox__label">I accept the terms</span>
13
13
  </label>
14
14
  </span>
15
15
 
16
16
  ## Props
17
- - `label`: string — the text next to the field; richer content goes in `children`
18
- - `checked` / `defaultChecked` — controlled or uncontrolled, like a native checkbox
19
- - `onCheckedChange(checked)` — the boolean alone; `onChange` still fires with the full event
20
- - `onTouch()` — fires on blur
21
- - `required`: boolean — set as `aria-required`, not as the native attribute
22
- - `invalid`, `touched` — the error state, gated the same way as in `KptInput`
23
- - `hostProps` — props for the `.kpt-checkbox-host` wrapper
17
+ - `label`: string - the text next to the field; richer content goes in `children`
18
+ - `checked` / `defaultChecked` - controlled or uncontrolled, like a native checkbox
19
+ - `onCheckedChange(checked)` - the boolean alone; `onChange` still fires with the full event
20
+ - `onTouch()` - fires on blur
21
+ - `required`: boolean - set as `aria-required`, not as the native attribute
22
+ - `invalid`, `touched` - the error state, gated the same way as in `KptInput`
23
+ - `toggleMotion`: 'spring' | 'fade' | 'none' (default from `KptMotionProvider`, else `spring`) - see "Toggle motion"
24
+ - `hostProps` - props for the `.kpt-checkbox-host` wrapper
24
25
  - `className` goes to the `.kpt-checkbox` block; `name`, `value`, `ref` and the handlers go to the
25
26
  native `<input>`, which is where a form expects them
26
27
 
@@ -30,7 +31,7 @@ Import: `import { KptCheckbox } from '@konce-pt/react';`
30
31
  <KptCheckbox label="Newsletter" invalid={!!err} touched={blurred} />
31
32
 
32
33
  ## Screen reader and keyboard
33
- `indeterminate`: boolean — the "some selected" state for a "select all" box (a dash in the box;
34
+ `indeterminate`: boolean - the "some selected" state for a "select all" box (a dash in the box;
34
35
  screen readers say "partially checked"). It is a DOM property, so the component sets it; the browser
35
36
  clears it on click, so set it to `false` in `onCheckedChange`.
36
37
 
@@ -40,11 +41,25 @@ generated. Inside `KptFormField` the wrapper's `label[for]` points at it and the
40
41
  added to `aria-describedby` (merged with your own). Without a wrapper, name it with `aria-label`.
41
42
  Inside `kpt-form-field` the box gets both names: the wrapper label and its own `label`.
42
43
 
44
+ ## Toggle motion
45
+ `toggleMotion`: `spring` - the box pops and the check mark draws itself as a stroke; `fade` - a calm colour and mark transition; `none` - no
46
+ motion. The bounce is started by the change handler, so a control that is checked on load does not
47
+ move. With no value it takes `toggle` from `KptMotionProvider` (default `spring`); `enabled: false` and the
48
+ system "reduce motion" setting always win.
49
+
50
+ With `spring` the error gets a signal too: when the field turns invalid (`invalid` and `touched`),
51
+ an error-coloured ring spreads from the box and fades, and the box shakes briefly. An error present on
52
+ load stays still, and a repeated submit with the field still invalid does not replay it. Inside an
53
+ invalid form field the field already shakes, so the checkbox adds only the ring.
54
+
43
55
  ## Tokens
44
56
  `--kpt-form-field-border`, `--kpt-color-primary` (the checked box), `--kpt-color-on-primary`
45
57
  (the tick), `--kpt-form-field-border-error`.
46
58
 
47
59
  ## Accessibility
48
- A native `<input type="checkbox">` inside a `<label>` — the label is the accessible name and the
60
+ A native `<input type="checkbox">` inside a `<label>` - the label is the accessible name and the
49
61
  whole row is clickable. The box and the tick are `aria-hidden`, being pure decoration over the real
50
62
  control.
63
+
64
+ ## Read-only and required
65
+ `readOnly` keeps the box focusable but blocks the click and Space (`aria-readonly`) - the native attribute does not work on checkboxes.
@@ -7,8 +7,8 @@ export type KptChipTextTransform = 'none' | 'capitalize' | 'uppercase' | 'lowerc
7
7
  export interface KptChipProps extends ComponentPropsWithRef<'span'>, KptI18nOverrides {
8
8
  variant?: KptChipVariant;
9
9
  /**
10
- * Wielkość liter etykiety. `capitalize` podnosi pierwszą literę każdego słowa — także po
11
- * dywizie („Agent-Ready"), bo CSS nie wie, gdzie kończy się wyraz złożony; przy takich
10
+ * Wielkość liter etykiety. `capitalize` podnosi pierwszą literę każdego słowa - także po
11
+ * dywizie ("Agent-Ready"), bo CSS nie wie, gdzie kończy się wyraz złożony; przy takich
12
12
  * napisach pewniejszy jest zapis wprost w treści.
13
13
  */
14
14
  textTransform?: KptChipTextTransform;
@@ -21,11 +21,11 @@ export interface KptChipProps extends ComponentPropsWithRef<'span'>, KptI18nOver
21
21
  hostProps?: KptHostProps<'span'>;
22
22
  }
23
23
  /**
24
- * Chip / tag — etykieta, opcjonalnie usuwalna.
24
+ * Chip / tag - etykieta, opcjonalnie usuwalna.
25
25
  *
26
26
  * @example
27
27
  * <KptChip>Angular</KptChip>
28
28
  * <KptChip variant="success" removable onRemove={remove}>UI</KptChip>
29
- * <KptChip textTransform="capitalize">nowość · zestaw startowy</KptChip>
29
+ * <KptChip textTransform="capitalize">nowość, zestaw startowy</KptChip>
30
30
  */
31
31
  export declare function KptChip({ variant, textTransform, removable, disabled, onRemove, locale, dictionary, hostProps, className, children, ...rest }: Readonly<KptChipProps>): import("react").JSX.Element;
package/dist/chip/chip.js CHANGED
@@ -1,15 +1,16 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { cn } from "../internal/cn.js";
3
4
  import { useKptId } from "../internal/use-id.js";
4
5
  import { KptIcon } from "../icon/icon.js";
5
6
  import { useKptMessages } from "../i18n/i18n-context.js";
6
7
  /**
7
- * Chip / tag — etykieta, opcjonalnie usuwalna.
8
+ * Chip / tag - etykieta, opcjonalnie usuwalna.
8
9
  *
9
10
  * @example
10
11
  * <KptChip>Angular</KptChip>
11
12
  * <KptChip variant="success" removable onRemove={remove}>UI</KptChip>
12
- * <KptChip textTransform="capitalize">nowość · zestaw startowy</KptChip>
13
+ * <KptChip textTransform="capitalize">nowość, zestaw startowy</KptChip>
13
14
  */
14
15
  export function KptChip({ variant = 'neutral', textTransform = 'none', removable = false, disabled = false, onRemove, locale, dictionary, hostProps, className, children, ...rest }) {
15
16
  const { t } = useKptMessages({ locale, dictionary });
@@ -1,6 +1,6 @@
1
1
  # KptChip (@konce-pt/react)
2
2
 
3
- A chip / tag — a label, optionally removable.
3
+ A chip / tag - a label, optionally removable.
4
4
  Import: `import { KptChip } from '@konce-pt/react';`
5
5
 
6
6
  ## DOM
@@ -8,23 +8,23 @@ Import: `import { KptChip } from '@konce-pt/react';`
8
8
  <span class="kpt-chip" data-variant="primary">
9
9
  <span class="kpt-chip__label" id="kpt-chip-r1-label">React</span>
10
10
  <button type="button" class="kpt-chip__remove" id="kpt-chip-r1-remove" aria-label="Remove"
11
- aria-labelledby="kpt-chip-r1-remove kpt-chip-r1-label">…icon…</button>
11
+ aria-labelledby="kpt-chip-r1-remove kpt-chip-r1-label">...icon...</button>
12
12
  </span>
13
13
  </span>
14
14
 
15
15
  ## Props
16
16
  - `variant`: 'neutral' | 'primary' | 'success' | 'danger' | 'warning' | 'info' (default 'neutral')
17
- - `textTransform`: 'none' | 'capitalize' | 'uppercase' | 'lowercase' (default 'none') — the label's letter case
18
- - `removable`: boolean — adds the remove button
17
+ - `textTransform`: 'none' | 'capitalize' | 'uppercase' | 'lowercase' (default 'none') - the label's letter case
18
+ - `removable`: boolean - adds the remove button
19
19
  - `disabled`: boolean
20
- - `onRemove()` — fired by the remove button
21
- - `locale`, `dictionary` — i18n overrides for this component only
22
- - `hostProps` — props for the `.kpt-chip-host` wrapper
20
+ - `onRemove()` - fired by the remove button
21
+ - `locale`, `dictionary` - i18n overrides for this component only
22
+ - `hostProps` - props for the `.kpt-chip-host` wrapper
23
23
  - `className`, `ref` and every other `<span>` prop go to the inner `.kpt-chip`
24
24
 
25
25
  ## Removing is your decision
26
26
  `onRemove` reports the intent; the chip does not remove itself from anything. Drop it from your own
27
- list — that keeps the chip usable both in a controlled collection and as a standalone label.
27
+ list - that keeps the chip usable both in a controlled collection and as a standalone label.
28
28
 
29
29
  ## i18n
30
30
  The remove button's label comes from `common.remove` in the dictionary.
@@ -33,12 +33,12 @@ The remove button's label comes from `common.remove` in the dictionary.
33
33
  <KptChip>React</KptChip>
34
34
  <KptChip variant="success" removable onRemove={() => drop(tag)}>UI</KptChip>
35
35
  <KptCard.Tags><KptChip variant="info">Daily</KptChip></KptCard.Tags>
36
- <KptChip textTransform="capitalize">new · starter kit</KptChip>
36
+ <KptChip textTransform="capitalize">new, starter kit</KptChip>
37
37
 
38
38
  ## Letter case
39
39
  `textTransform` lands as `data-text-transform` on `.kpt-chip` and sets `text-transform` there, so
40
40
  the label can stay in the application's own wording while the chip decides how it is displayed.
41
- `capitalize` raises the first letter of every word — **including after a hyphen**
41
+ `capitalize` raises the first letter of every word - **including after a hyphen**
42
42
  ("Agent-Ready"), because CSS does not know where a compound word ends. For labels with a hyphen,
43
43
  spelling it out in the content is the exact route.
44
44
 
@@ -48,6 +48,6 @@ spelling it out in the content is the exact route.
48
48
 
49
49
  ## Accessibility
50
50
  The label sits in `.kpt-chip__label`, and the remove button is named by `aria-labelledby` from
51
- itself plus that label — “Remove Angular” — so with several chips a screen reader user hears which
51
+ itself plus that label - "Remove Angular" - so with several chips a screen reader user hears which
52
52
  one goes. `Backspace` and `Delete` on the button work like a click. After removal focus falls back
53
53
  to the page; move it to the next chip yourself.
@@ -7,25 +7,27 @@ export interface KptChipsInputProps extends Omit<ComponentPropsWithRef<'div'>, '
7
7
  /** Placeholder; pominięty = `chipsInput.placeholder` ze słownika. */
8
8
  placeholder?: string;
9
9
  allowDuplicates?: boolean;
10
- /** Id elementu fokusowalnego (nie hosta); bez niego generowane, w `KptFormField` — z wrappera. */
10
+ /** Id elementu fokusowalnego (nie hosta); bez niego generowane, w `KptFormField` - z wrappera. */
11
11
  id?: string;
12
12
  /** Nazwa dostępna, gdy kontrolki nie opisuje etykieta (`<label for>` albo `KptFormField`). */
13
13
  ariaLabel?: string | null;
14
14
  /** Oznacza pole jako wymagane atrybutem `aria-required`. */
15
15
  required?: boolean;
16
16
  disabled?: boolean;
17
+ /** Tylko do odczytu - tagi widać, nie da się ich dodać ani usunąć. */
18
+ readOnly?: boolean;
17
19
  invalid?: boolean;
18
20
  touched?: boolean;
19
21
  onTouch?: () => void;
20
22
  }
21
23
  /**
22
- * Pole tagów — dodawanie Enterem albo przecinkiem, usuwanie Backspace lub ×.
24
+ * Pole tagów - dodawanie Enterem albo przecinkiem, usuwanie Backspace lub x.
23
25
  *
24
26
  * Tekst w trakcie pisania żyje w DOM, nie w stanie Reacta: wartością komponentu jest lista
25
27
  * zatwierdzonych tagów, a bufor wpisywania to prywatna sprawa pola. Dzięki temu każde naciśnięcie
26
28
  * klawisza nie przerysowuje listy chipów.
27
29
  *
28
30
  * @example
29
- * <KptChipsInput value={tags} onValueChange={setTags} placeholder="Dodaj tag…" />
31
+ * <KptChipsInput value={tags} onValueChange={setTags} placeholder="Dodaj tag..." />
30
32
  */
31
- export declare function KptChipsInput({ value, defaultValue, onValueChange, placeholder, allowDuplicates, id, ariaLabel, required, disabled, invalid, touched, onTouch, locale, dictionary, className, ...rest }: Readonly<KptChipsInputProps>): import("react").JSX.Element;
33
+ export declare function KptChipsInput({ value, defaultValue, onValueChange, placeholder, allowDuplicates, id, ariaLabel, required, disabled, readOnly, invalid, touched, onTouch, locale, dictionary, className, ...rest }: Readonly<KptChipsInputProps>): import("react").JSX.Element;
@@ -1,21 +1,24 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useRef, useState } from 'react';
3
+ import { useLayoutEffect, useRef, useState } from 'react';
4
+ import { prepareFlowMotion, resolveEnterMotion } from '@konce-pt/motion';
5
+ import { useKptMotion } from "../motion/motion-context.js";
3
6
  import { cn } from "../internal/cn.js";
4
7
  import { useControllableState } from "../internal/use-controllable-state.js";
5
8
  import { useKptMessages } from "../i18n/i18n-context.js";
6
9
  import { KptChip } from "../chip/chip.js";
7
10
  import { useKptFieldA11y } from "../form-field/form-field-context.js";
8
11
  /**
9
- * Pole tagów — dodawanie Enterem albo przecinkiem, usuwanie Backspace lub ×.
12
+ * Pole tagów - dodawanie Enterem albo przecinkiem, usuwanie Backspace lub x.
10
13
  *
11
14
  * Tekst w trakcie pisania żyje w DOM, nie w stanie Reacta: wartością komponentu jest lista
12
15
  * zatwierdzonych tagów, a bufor wpisywania to prywatna sprawa pola. Dzięki temu każde naciśnięcie
13
16
  * klawisza nie przerysowuje listy chipów.
14
17
  *
15
18
  * @example
16
- * <KptChipsInput value={tags} onValueChange={setTags} placeholder="Dodaj tag…" />
19
+ * <KptChipsInput value={tags} onValueChange={setTags} placeholder="Dodaj tag..." />
17
20
  */
18
- export function KptChipsInput({ value, defaultValue = [], onValueChange, placeholder, allowDuplicates = false, id, ariaLabel = null, required = false, disabled = false, invalid = false, touched, onTouch, locale, dictionary, className, ...rest }) {
21
+ export function KptChipsInput({ value, defaultValue = [], onValueChange, placeholder, allowDuplicates = false, id, ariaLabel = null, required = false, disabled = false, readOnly = false, invalid = false, touched, onTouch, locale, dictionary, className, ...rest }) {
19
22
  const { t } = useKptMessages({ locale, dictionary });
20
23
  const field = useKptFieldA11y(id, 'kpt-chips-input');
21
24
  const inputRef = useRef(null);
@@ -25,36 +28,68 @@ export function KptChipsInput({ value, defaultValue = [], onValueChange, placeho
25
28
  onChange: onValueChange,
26
29
  });
27
30
  const showInvalid = invalid && (touched ?? true);
31
+ /** Wejście i wyjście tagu idą za `enter` z `KptMotionProvider` (domyślnie `spring`). */
32
+ const motion = resolveEnterMotion(undefined, useKptMotion());
33
+ const boxRef = useRef(null);
34
+ /** Ruch przygotowany przed zmianą listy, odtwarzany po jej wyrenderowaniu. */
35
+ const pendingFlow = useRef(null);
36
+ /** Sam chip, nie `__item` - ten ma `display: contents` (semantyka listy) i nie ma pudełka do animacji. */
37
+ const flowItems = () => Array.from(boxRef.current?.querySelectorAll('.kpt-chips-input__item > *, .kpt-chips-input__field') ?? []);
38
+ // Przed malowaniem - inaczej mignęłaby klatka z nowym układem, zanim FLIP cofnie elementy.
39
+ useLayoutEffect(() => {
40
+ const play = pendingFlow.current;
41
+ pendingFlow.current = null;
42
+ play?.(flowItems());
43
+ });
44
+ /**
45
+ * Zmienia listę z ruchem: nowy tag wskakuje, usunięty gaśnie jako duch, a reszta i pole dosuwają
46
+ * się FLIP-em. Tagi są śledzone po indeksie, więc ruch liczy się z pozycji danych, nie węzłów -
47
+ * szczegóły w `prepareFlowMotion`. Stan zmienia się od razu; ruch tylko go ilustruje.
48
+ */
49
+ const change = (next, flow) => {
50
+ const box = boxRef.current;
51
+ if (motion !== 'none' && box)
52
+ pendingFlow.current = prepareFlowMotion(box, flowItems(), flow, motion);
53
+ setChips(next);
54
+ };
28
55
  /** Komunikat regionu `polite`: dodanie, usunięcie albo odrzucony duplikat. */
29
- const [announcement, setAnnouncement] = useState('');
56
+ const [announcement, setAnnouncementState] = useState('');
57
+ /**
58
+ * Ten sam komunikat dwa razy z rzędu (drugi odrzucony duplikat) nie zmieniłby treści regionu
59
+ * i czytnik by go nie ogłosił - doklejamy niewidoczną spację, żeby tekst się różnił.
60
+ */
61
+ const setAnnouncement = (message) => setAnnouncementState((current) => (current === message ? `${message}\u00A0` : message));
30
62
  const commit = (el) => {
31
63
  const text = el.value.trim();
32
- if (!text)
64
+ if (!text || readOnly)
33
65
  return;
34
66
  if (!allowDuplicates && chips.includes(text)) {
35
67
  // Duplikat zostaje w polu (do poprawy), a czytnik słyszy, dlaczego nic nie przybyło.
36
68
  setAnnouncement(t('chipsInput.duplicate', { value: text }));
37
69
  return;
38
70
  }
39
- setChips([...chips, text]);
71
+ change([...chips, text], { added: chips.length });
40
72
  setAnnouncement(t('chipsInput.added', { value: text }));
41
73
  el.value = '';
42
74
  };
43
75
  const removeAt = (index) => {
44
76
  const removed = chips[index];
45
- setChips(chips.filter((_, i) => i !== index));
77
+ change(chips.filter((_, i) => i !== index), { removed: index });
46
78
  if (removed !== undefined)
47
79
  setAnnouncement(t('chipsInput.removed', { value: removed }));
48
80
  onTouch?.();
49
81
  };
50
82
  const onKeyDown = (event) => {
51
83
  const el = event.currentTarget;
84
+ // W trakcie kompozycji IME (CJK) Enter zatwierdza znak, nie tag.
85
+ if (readOnly || event.nativeEvent.isComposing)
86
+ return;
52
87
  if (event.key === 'Enter' || event.key === ',') {
53
88
  event.preventDefault();
54
89
  commit(el);
55
90
  }
56
91
  else if (event.key === 'Backspace' && el.value === '' && chips.length) {
57
- // Backspace w pustym polu zjada ostatni chip — to samo, czego uczy każdy klient poczty.
92
+ // Backspace w pustym polu zjada ostatni chip - to samo, czego uczy każdy klient poczty.
58
93
  removeAt(chips.length - 1);
59
94
  }
60
95
  };
@@ -62,9 +97,9 @@ export function KptChipsInput({ value, defaultValue = [], onValueChange, placeho
62
97
  commit(event.currentTarget);
63
98
  onTouch?.();
64
99
  };
65
- return (_jsx("div", { className: cn('kpt-chips-input-host', className), ...rest, children: _jsxs("div", { className: cn('kpt-chips-input', disabled && 'kpt-chips-input--disabled', showInvalid && 'kpt-chips-input--invalid'), children: [_jsx("span", { className: "kpt-chips-input__list", role: "list", children: chips.map((chip, index) => (_jsx("span", { className: "kpt-chips-input__item", role: "listitem", children: _jsx(KptChip, { variant: "primary", removable: !disabled, onRemove: () => {
100
+ return (_jsx("div", { className: cn('kpt-chips-input-host', className), "data-motion": motion, ...rest, children: _jsxs("div", { ref: boxRef, className: cn('kpt-chips-input', disabled && 'kpt-chips-input--disabled', showInvalid && 'kpt-chips-input--invalid'), children: [_jsx("span", { className: "kpt-chips-input__list", role: "list", children: chips.map((chip, index) => (_jsx("span", { className: "kpt-chips-input__item", role: "listitem", children: _jsx(KptChip, { variant: "primary", removable: !disabled && !readOnly, onRemove: () => {
66
101
  removeAt(index);
67
- // Przycisk usuwania znika razem z tagiem — fokus wraca do pola, nie na <body>.
102
+ // Przycisk usuwania znika razem z tagiem - fokus wraca do pola, nie na <body>.
68
103
  inputRef.current?.focus();
69
- }, children: chip }) }, index))) }), _jsx("input", { ref: inputRef, className: "kpt-chips-input__field", id: field.id, "aria-label": ariaLabel ?? undefined, "aria-required": required || undefined, "aria-invalid": showInvalid || undefined, "aria-describedby": field.describedBy, type: "text", placeholder: chips.length ? '' : (placeholder ?? t('chipsInput.placeholder')), disabled: disabled, onKeyDown: onKeyDown, onBlur: onBlur }), _jsx("span", { className: "kpt-chips-input__live", "aria-live": "polite", children: announcement })] }) }));
104
+ }, children: chip }) }, index))) }), _jsx("input", { ref: inputRef, className: "kpt-chips-input__field", id: field.id, "aria-label": ariaLabel ?? undefined, "aria-required": required || undefined, "aria-invalid": showInvalid || undefined, "aria-describedby": field.describedBy, type: "text", placeholder: chips.length ? '' : (placeholder ?? t('chipsInput.placeholder')), disabled: disabled, readOnly: readOnly, onKeyDown: onKeyDown, onBlur: onBlur }), _jsx("span", { className: "kpt-chips-input__live", "aria-live": "polite", children: announcement })] }) }));
70
105
  }
@@ -1,22 +1,22 @@
1
1
  # KptChipsInput (@konce-pt/react)
2
2
 
3
- A tag field — add with Enter or a comma, remove with Backspace or ×.
3
+ A tag field - add with Enter or a comma, remove with Backspace or x.
4
4
  Import: `import { KptChipsInput } from '@konce-pt/react';`
5
5
 
6
6
  ## DOM
7
7
  <div class="kpt-chips-input-host">
8
8
  <div class="kpt-chips-input">
9
- …KptChip per tag…
9
+ ...KptChip per tag...
10
10
  <input class="kpt-chips-input__field" type="text">
11
11
  </div>
12
12
  </div>
13
13
 
14
14
  ## Props
15
- - `value` / `defaultValue` / `onValueChange` — `string[]`
16
- - `placeholder`: string — omitted falls back to `chipsInput.placeholder`
15
+ - `value` / `defaultValue` / `onValueChange` - `string[]`
16
+ - `placeholder`: string - omitted falls back to `chipsInput.placeholder`
17
17
  - `allowDuplicates`: boolean (default false)
18
18
  - `disabled`, `invalid`, `touched`, `onTouch()`
19
- - `locale`, `dictionary` — i18n overrides for this component only
19
+ - `locale`, `dictionary` - i18n overrides for this component only
20
20
 
21
21
  ## The buffer is not state
22
22
  The text being typed lives in the DOM, not in React state: the component's value is the list of
@@ -24,19 +24,19 @@ committed tags, and the typing buffer is the field's own business. Every keystro
24
24
  not re-render the chips.
25
25
 
26
26
  ## Keyboard
27
- Enter and a comma commit the tag. Backspace in an empty field eats the last chip — the behaviour
27
+ Enter and a comma commit the tag. Backspace in an empty field eats the last chip - the behaviour
28
28
  every mail client teaches. Blur commits whatever is left in the field, so a half-typed tag is not
29
29
  lost by clicking away.
30
30
 
31
31
  ## Examples
32
- <KptChipsInput value={tags} onValueChange={setTags} placeholder="Add a tag…" />
32
+ <KptChipsInput value={tags} onValueChange={setTags} placeholder="Add a tag..." />
33
33
  <KptChipsInput value={tags} onValueChange={setTags} allowDuplicates />
34
34
 
35
35
  ## Screen reader and keyboard
36
36
  The tags are a list (`role="list"`/`listitem`), so a screen reader hears how many there are. Adding,
37
37
  removing (also with `Backspace`) and a rejected duplicate are announced by a polite live region
38
38
  (`chipsInput.added`/`removed`/`duplicate`); a duplicate stays in the field to be corrected instead
39
- of vanishing. After removing a tag with its `×`, focus returns to the text field.
39
+ of vanishing. After removing a tag with its `x`, focus returns to the text field.
40
40
 
41
41
  ## Label and description
42
42
  `id` goes to the native field, not the host; without one it comes from `KptFormField` or is
@@ -44,9 +44,19 @@ generated. Inside `KptFormField` the wrapper's `label[for]` points at it and the
44
44
  added to `aria-describedby` (merged with your own). Without a wrapper, name it with `ariaLabel`.
45
45
  New: `id`, `ariaLabel`, `required` and `aria-invalid` on the text field.
46
46
 
47
+ ## Motion
48
+ An added tag pops in (grows from a smaller size and sharpens out of a blur); a removed one - by its "x"
49
+ or by `Backspace` - fades and shrinks in place while the following tags and the text field slide over on
50
+ a spring. The value changes at once; the motion only illustrates it. Follows `enter` from `KptMotionProvider`
51
+ (`spring` / `fade` - only fades, the neighbours slide without the spring / `none`); `enabled: false`
52
+ and the system "reduce motion" setting always win.
53
+
47
54
  ## Tokens
48
55
  `--kpt-form-field-{bg,border,border-focus,border-error,radius}` plus the chip tokens.
49
56
 
50
57
  ## Accessibility
51
58
  Each chip is a `KptChip` with a labelled remove button, and the field itself is a native input, so
52
59
  tags are reachable and removable from the keyboard alone.
60
+
61
+ ## Read-only and required
62
+ `readOnly` shows the tags without the remove buttons and ignores Enter, comma and Backspace. Enter during IME composition (CJK) confirms the character, not a tag. A repeated message (a second rejected duplicate) is announced again.
@@ -1,17 +1,22 @@
1
1
  import { type ComponentPropsWithRef } from 'react';
2
- export interface KptClockProps extends Omit<ComponentPropsWithRef<'div'>, 'onChange'> {
3
- /** Godzina jako 'HH:mm' — zawsze 24h, niezależnie od `hourFormat`. */
2
+ import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
3
+ export interface KptClockProps extends Omit<ComponentPropsWithRef<'div'>, 'onChange'>, KptI18nOverrides {
4
+ /** Godzina jako 'HH:mm' - zawsze 24h, niezależnie od `hourFormat`. */
4
5
  value?: string;
5
6
  onValueChange?: (value: string) => void;
6
7
  hourFormat?: 12 | 24;
7
8
  minuteStep?: number;
8
9
  }
9
10
  /**
10
- * Tarcza zegara — dwa etapy: godziny → minuty, klikiem albo przeciąganiem. W trybie 24h dochodzi
11
- * wewnętrzny pierścień 13–00; w 12h przełącznik AM/PM. Używana przez `KptDatepicker`
12
- * i `KptDateRange`.
11
+ * Tarcza zegara - dwa etapy: godziny -> minuty, klikiem albo przeciąganiem. W trybie 24h dochodzi
12
+ * wewnętrzny pierścień 13-00; w 12h przełącznik AM/PM z etykietami pory dnia z `Intl`. Używana
13
+ * przez `KptDatepicker` i `KptDateRange`.
14
+ *
15
+ * Klawiatura: segmenty godzin i minut to `role="spinbutton"` - `ArrowUp`/`ArrowDown` o jeden krok (minuty
16
+ * o `minuteStep`), `PageUp`/`PageDown` o pięć, `Home`/`End` do granic. Tak da się ustawić każdą
17
+ * minutę, także spoza znaczników tarczy co pięć.
13
18
  *
14
19
  * @example
15
20
  * <KptClock value={time} onValueChange={setTime} hourFormat={12} minuteStep={5} />
16
21
  */
17
- export declare function KptClock({ value, onValueChange, hourFormat, minuteStep, className, ...rest }: Readonly<KptClockProps>): import("react").JSX.Element;
22
+ export declare function KptClock({ value, onValueChange, hourFormat, minuteStep, locale, dictionary, className, ...rest }: Readonly<KptClockProps>): import("react").JSX.Element;