@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
@@ -0,0 +1,81 @@
1
+ import { type RefObject } from 'react';
2
+ import { type KptSpeechEndReason, type KptSpeechErrorCode, type KptSpeechInterimDisplay, type KptSpeechMode, type KptSpeechSnapshot, type KptSpeechStatus, type KptSpeechSupport, type KptSpeechTargetInput, type KptSpeechWaveMode } from '@konce-pt/speech';
3
+ /** Cel dyktowania: element, `ref` do elementu, gotowy `KptSpeechTarget` albo funkcja. */
4
+ export type KptSpeechTargetRef = KptSpeechTargetInput | RefObject<HTMLElement | null>;
5
+ export interface KptSpeechRecognitionOptions {
6
+ /** Gdzie trafia tekst. Bez celu kontroler tylko zgłasza `onResult`. */
7
+ target?: KptSpeechTargetRef | null;
8
+ /** Język rozpoznawania (BCP 47); bez niego z `KptI18nProvider` i języka przeglądarki. */
9
+ lang?: string;
10
+ /** Słuchaj do "stop" (domyślnie) albo do końca jednej wypowiedzi. */
11
+ continuous?: boolean;
12
+ /** `insert` (w kursor, domyślnie), `append` albo `replace` (czyści cel w chwili startu). */
13
+ mode?: KptSpeechMode;
14
+ /** Pokaz tekstu tymczasowego; bez wartości - domyślny dla rodzaju celu. */
15
+ interim?: KptSpeechInterimDisplay;
16
+ /** Wielka litera na początku zdania. Domyślnie `true`. */
17
+ capitalize?: boolean;
18
+ /** Fala: `auto` (na żywo na desktopie, syntetyczna na telefonie), `live`, `synthetic`, `none`. */
19
+ wave?: KptSpeechWaveMode;
20
+ /** Słupki fali na żywo. Domyślnie 5. */
21
+ bars?: number;
22
+ /** Zatrzymaj po tylu ms bez nowego słowa; `0` - nigdy. */
23
+ silenceMs?: number;
24
+ /** Twardy limit długości dyktowania w ms; `0` - bez limitu. */
25
+ maxDuration?: number;
26
+ /** Rozpoznawanie wyłącznie w urządzeniu (Chrome 135+). */
27
+ processLocally?: boolean;
28
+ disabled?: boolean;
29
+ /**
30
+ * Czy kontroler w ogóle istnieje. `false` nie tworzy sesji ani nasłuchów strony - dla pól,
31
+ * w których mikrofon jest opcją (`speech` w `KptInput`). Domyślnie `true`.
32
+ */
33
+ enabled?: boolean;
34
+ onStart?: () => void;
35
+ onEnd?: (reason: KptSpeechEndReason) => void;
36
+ /** Stan transkryptu po każdej zmianie: zatwierdzony i tymczasowy osobno. */
37
+ onResult?: (snapshot: KptSpeechSnapshot) => void;
38
+ onError?: (code: KptSpeechErrorCode) => void;
39
+ }
40
+ export interface KptSpeechRecognition {
41
+ status: KptSpeechStatus;
42
+ /** Trwa nasłuch (także start i łagodne zatrzymywanie). */
43
+ listening: boolean;
44
+ /** Wsparcie przeglądarki - `null` do pierwszego renderu po stronie klienta (SSR). */
45
+ support: KptSpeechSupport | null;
46
+ /** Da się dyktować: przeglądarka rozpoznaje mowę, a usługa nie odmówiła (`network`). */
47
+ available: boolean;
48
+ /** Ostatni błąd albo `null`. */
49
+ error: KptSpeechErrorCode | null;
50
+ /** Powód końca ostatniego dyktowania; `null` przed pierwszym i w trakcie nasłuchu. */
51
+ lastEnd: KptSpeechEndReason | null;
52
+ /** Silnik słyszy mowę - napęd fali syntetycznej. */
53
+ speaking: boolean;
54
+ /** Poziomy fali na żywo (0..1), puste poza nasłuchem i w trybie syntetycznym. */
55
+ levels: readonly number[];
56
+ /** Rozstrzygnięty tryb fali. */
57
+ waveMode: Exclude<KptSpeechWaveMode, 'auto'>;
58
+ snapshot: KptSpeechSnapshot;
59
+ start: () => void;
60
+ /** Łagodny stop: ostatnie słowa jeszcze się zatwierdzą. */
61
+ stop: () => void;
62
+ /** Zatwierdź to, co widać, i skończ od razu - przed wysłaniem treści. */
63
+ flush: () => void;
64
+ /** Przerwij bez zatwierdzania tekstu tymczasowego. */
65
+ abort: () => void;
66
+ toggle: () => void;
67
+ }
68
+ /**
69
+ * Dyktowanie bez UI - sesja Web Speech API, wstawianie w cel i poziomy fali z `@konce-pt/speech`.
70
+ * `KptSpeechButton` używa go pod spodem; własny przycisk albo skrót klawiszowy dostaje to samo.
71
+ *
72
+ * Tekst tymczasowy widać w celu, ale do wartości (stanu kontrolowanego pola) trafia wyłącznie
73
+ * zatwierdzony - przez zwykłą edycję, którą `onChange` widzi jak wpisany tekst.
74
+ *
75
+ * @example
76
+ * const fieldRef = useRef<HTMLTextAreaElement>(null);
77
+ * const speech = useKptSpeechRecognition({ target: fieldRef });
78
+ * <KptSpeechButton speech={speech} />
79
+ * <KptButton onClick={() => { speech.flush(); send(); }}>Send</KptButton>
80
+ */
81
+ export declare function useKptSpeechRecognition(options?: KptSpeechRecognitionOptions): KptSpeechRecognition;
@@ -0,0 +1,179 @@
1
+ 'use client';
2
+ import { useEffect, useEffectEvent, useLayoutEffect, useRef, useState, useSyncExternalStore } from 'react';
3
+ import { browserSpeechEngine, createSpeechSession, defaultSpeechLang, mirrorSpeechLevels, onSpeechPageHidden, resolveSpeechTarget, resolveWaveMode, speechSupport, speechUnavailable, startSpeechMeter, } from '@konce-pt/speech';
4
+ import { useKptI18n } from "../i18n/i18n-context.js";
5
+ // Wsparcie przeglądarki nie zmienia się w trakcie życia strony - liczone raz, czytane przez
6
+ // `useSyncExternalStore`, żeby serwer i hydracja widziały "nieznane", a klient od razu prawdę.
7
+ let supportCache = null;
8
+ const readSupport = () => (supportCache ??= speechSupport());
9
+ const readServerSupport = () => null;
10
+ const subscribeNever = () => () => undefined;
11
+ const EMPTY_SNAPSHOT = { finalText: '', interimText: '' };
12
+ const NO_LEVELS = [];
13
+ function isRef(value) {
14
+ return typeof value === 'object' && value !== null && 'current' in value && !('begin' in value);
15
+ }
16
+ /**
17
+ * Dyktowanie bez UI - sesja Web Speech API, wstawianie w cel i poziomy fali z `@konce-pt/speech`.
18
+ * `KptSpeechButton` używa go pod spodem; własny przycisk albo skrót klawiszowy dostaje to samo.
19
+ *
20
+ * Tekst tymczasowy widać w celu, ale do wartości (stanu kontrolowanego pola) trafia wyłącznie
21
+ * zatwierdzony - przez zwykłą edycję, którą `onChange` widzi jak wpisany tekst.
22
+ *
23
+ * @example
24
+ * const fieldRef = useRef<HTMLTextAreaElement>(null);
25
+ * const speech = useKptSpeechRecognition({ target: fieldRef });
26
+ * <KptSpeechButton speech={speech} />
27
+ * <KptButton onClick={() => { speech.flush(); send(); }}>Send</KptButton>
28
+ */
29
+ export function useKptSpeechRecognition(options = {}) {
30
+ const { locale } = useKptI18n();
31
+ const support = useSyncExternalStore(subscribeNever, readSupport, readServerSupport);
32
+ const enabled = options.enabled ?? true;
33
+ const [status, setStatus] = useState('idle');
34
+ const [error, setError] = useState(null);
35
+ const [speaking, setSpeaking] = useState(false);
36
+ const [levels, setLevels] = useState(NO_LEVELS);
37
+ const [meterFailed, setMeterFailed] = useState(false);
38
+ const [unavailable, setUnavailable] = useState(false);
39
+ const [snapshot, setSnapshot] = useState(EMPTY_SNAPSHOT);
40
+ const [lastEnd, setLastEnd] = useState(null);
41
+ const sessionRef = useRef(null);
42
+ const targetRef = useRef(null);
43
+ const targetElementRef = useRef(null);
44
+ const meterRef = useRef(null);
45
+ const listening = status === 'starting' || status === 'listening' || status === 'stopping';
46
+ const available = enabled && !!support?.supported && !unavailable && !speechUnavailable();
47
+ const resolvedWave = support ? resolveWaveMode(options.wave ?? 'auto', support) : 'none';
48
+ const waveMode = resolvedWave === 'live' && meterFailed ? 'synthetic' : resolvedWave;
49
+ const emitStart = useEffectEvent(() => options.onStart?.());
50
+ const emitEnd = useEffectEvent((reason) => options.onEnd?.(reason));
51
+ const emitResult = useEffectEvent((next) => options.onResult?.(next));
52
+ const emitError = useEffectEvent((code) => options.onError?.(code));
53
+ // Escape w celu zatrzymuje dyktowanie - jak na samym przycisku.
54
+ const onTargetKeydown = useRef((event) => {
55
+ if (event.key !== 'Escape')
56
+ return;
57
+ const session = sessionRef.current;
58
+ if (!session || session.status === 'idle' || session.status === 'error')
59
+ return;
60
+ event.preventDefault();
61
+ session.stop();
62
+ });
63
+ // Sesja żyje tyle, co komponent. Słuchacze wołają zdarzenia efektu - zawsze z najnowszymi
64
+ // propsami, bez odtwarzania sesji przy każdym renderze.
65
+ useEffect(() => {
66
+ if (!enabled)
67
+ return;
68
+ const engine = browserSpeechEngine();
69
+ if (!engine)
70
+ return;
71
+ const releaseTarget = () => {
72
+ targetRef.current?.end();
73
+ targetRef.current = null;
74
+ targetElementRef.current?.removeEventListener('keydown', onTargetKeydown.current);
75
+ targetElementRef.current = null;
76
+ meterRef.current?.stop();
77
+ meterRef.current = null;
78
+ setLevels(NO_LEVELS);
79
+ setSpeaking(false);
80
+ };
81
+ const session = createSpeechSession({ engine }, { lang: 'en-US' }, {
82
+ status: (next) => {
83
+ setStatus(next);
84
+ if (next === 'starting')
85
+ emitStart();
86
+ },
87
+ interim: (text) => targetRef.current?.interim(text),
88
+ commit: (text) => targetRef.current?.commit(text),
89
+ snapshot: (next) => {
90
+ setSnapshot(next);
91
+ emitResult(next);
92
+ },
93
+ speech: (active) => setSpeaking(active),
94
+ error: (code) => {
95
+ setError(code);
96
+ if (speechUnavailable())
97
+ setUnavailable(true);
98
+ emitError(code);
99
+ },
100
+ end: (reason) => {
101
+ setLastEnd(reason);
102
+ releaseTarget();
103
+ emitEnd(reason);
104
+ },
105
+ });
106
+ sessionRef.current = session;
107
+ const offPageHidden = onSpeechPageHidden(() => session.stop());
108
+ return () => {
109
+ offPageHidden();
110
+ session.abort();
111
+ releaseTarget();
112
+ sessionRef.current = null;
113
+ };
114
+ }, [enabled]);
115
+ // Kontrolowane pole nadpisuje `value` stanem przy każdym renderze rodzica - a stan nie zna
116
+ // tekstu tymczasowego, więc React by go zmywał (przy fali na żywo co klatkę). Po każdym commicie,
117
+ // jeszcze przed malowaniem, cel przywraca tekst tymczasowy na swoje miejsce: nic nie mruga.
118
+ useLayoutEffect(() => {
119
+ targetRef.current?.refresh?.();
120
+ });
121
+ const start = () => {
122
+ const session = sessionRef.current;
123
+ if (!session || !support || !available || options.disabled)
124
+ return;
125
+ if (session.status !== 'idle' && session.status !== 'error')
126
+ return;
127
+ setError(null);
128
+ setLastEnd(null);
129
+ setMeterFailed(false);
130
+ setSnapshot(EMPTY_SNAPSHOT);
131
+ const raw = options.target;
132
+ const target = isRef(raw) ? raw.current : raw;
133
+ if (target) {
134
+ targetElementRef.current = target instanceof HTMLElement ? target : null;
135
+ targetElementRef.current?.addEventListener('keydown', onTargetKeydown.current);
136
+ const capitalize = options.capitalize ?? true;
137
+ targetRef.current = resolveSpeechTarget(target, options.interim ? { capitalize, interim: options.interim } : { capitalize });
138
+ targetRef.current.begin(options.mode ?? 'insert');
139
+ }
140
+ session.configure({
141
+ lang: options.lang ?? defaultSpeechLang(locale, globalThis.navigator?.language),
142
+ continuous: options.continuous ?? true,
143
+ processLocally: options.processLocally ?? false,
144
+ autoRestart: !support.ios,
145
+ silenceMs: options.silenceMs ?? 0,
146
+ maxDurationMs: options.maxDuration ?? 0,
147
+ });
148
+ // Miernik startuje jeszcze w geście kliknięcia - poza nim `AudioContext` jest zawieszony.
149
+ if (waveMode === 'live') {
150
+ meterRef.current = startSpeechMeter({
151
+ bars: options.bars ?? 5,
152
+ onLevels: (next) => setLevels(mirrorSpeechLevels(next)),
153
+ onFail: () => setMeterFailed(true),
154
+ });
155
+ }
156
+ session.start();
157
+ };
158
+ const stop = () => sessionRef.current?.stop();
159
+ const flush = () => sessionRef.current?.flush();
160
+ const abort = () => sessionRef.current?.abort();
161
+ const toggle = () => (listening ? stop() : start());
162
+ return {
163
+ status,
164
+ listening,
165
+ support,
166
+ available,
167
+ error,
168
+ lastEnd,
169
+ speaking,
170
+ levels,
171
+ waveMode,
172
+ snapshot,
173
+ start,
174
+ stop,
175
+ flush,
176
+ abort,
177
+ toggle,
178
+ };
179
+ }
@@ -1,25 +1,25 @@
1
1
  # KptSpeedDial (@konce-pt/react)
2
2
 
3
- A speed dial — a FAB that fans out a set of actions. Built on `KptFab`.
3
+ A speed dial - a FAB that fans out a set of actions. Built on `KptFab`.
4
4
  Import: `import { KptSpeedDial } from '@konce-pt/react';`
5
5
 
6
6
  ## DOM
7
7
  <div class="kpt-speed-dial-host">
8
8
  <div class="kpt-speed-dial is-open" data-direction="up">
9
9
  <div class="kpt-speed-dial__actions">
10
- <button class="kpt-speed-dial__action" aria-label="Upload file">…</button>…
10
+ <button class="kpt-speed-dial__action" aria-label="Upload file">...</button>...
11
11
  </div>
12
- <span class="kpt-fab-host"><button class="kpt-fab">…</button></span>
12
+ <span class="kpt-fab-host"><button class="kpt-fab">...</button></span>
13
13
  </div>
14
14
  <div class="kpt-speed-dial__backdrop"></div>
15
15
  </div>
16
16
 
17
17
  ## Props
18
- - `items`: `KptMenuItem<T>[]` — the actions (`label`, `icon`, `disabled`)
18
+ - `items`: `KptMenuItem<T>[]` - the actions (`label`, `icon`, `disabled`)
19
19
  - `direction`: `'up'` (default) | `'down'` | `'left'` | `'right'`
20
- - `icon`: string (default `'plus'`) — the SCSS rotates it 45° when open
21
- - `ariaLabel`: string — the closed-state label; without it `speedDial.actions`
22
- - `onSelect(item)` — fired on pick; a disabled item fires nothing
20
+ - `icon`: string (default `'plus'`) - the SCSS rotates it 45° when open
21
+ - `ariaLabel`: string - the closed-state label; without it `speedDial.actions`
22
+ - `onSelect(item)` - fired on pick; a disabled item fires nothing
23
23
  - `className`, `ref` and every other `<div>` prop go to the host
24
24
 
25
25
  ## The label follows the state
@@ -37,6 +37,12 @@ present would swallow clicks meant for the page underneath.
37
37
  ## i18n
38
38
  `speedDial.actions` and `common.close`; `locale` and `dictionary` override them per instance.
39
39
 
40
+ ## Motion
41
+ The actions fan out from the button in a cascade - the nearest first, on a spring, from the side of the
42
+ button - and fold back in reverse order; the trigger icon turns on a spring. The container hides
43
+ (`visibility`) only after the last action, so the closing cascade is not cut off. Pressed, it squeezes slightly and springs back on release (shared mixin `styles/_press.scss`). Pure CSS; durations follow `--kpt-motion-scale`, so `enabled: false` turns it off, and it drops out
44
+ under "reduce motion".
45
+
40
46
  ## Tokens
41
47
  The main button comes from `KptFab`; the actions use `--kpt-color-surface-raised` and
42
48
  `--kpt-elevation-2`.
@@ -44,7 +50,7 @@ The main button comes from `KptFab`; the actions use `--kpt-color-surface-raised
44
50
  ## Accessibility
45
51
  - The main button carries `aria-expanded` and `aria-controls` pointing at the actions container.
46
52
  - Closed actions are `visibility: hidden` (switched after the fade-out), so they are out of the Tab
47
- order and the accessibility tree — not just transparent.
53
+ order and the accessibility tree - not just transparent.
48
54
  - `Escape` anywhere in the dial closes it and returns focus to the main button.
49
55
  - Every action is a `<button>` labelled with its own `label`, so the fan works from the keyboard even
50
56
  when the actions show icons only.
@@ -12,7 +12,7 @@ export interface KptSpeedDialProps<T> extends Omit<ComponentPropsWithRef<'div'>,
12
12
  onSelect?: (item: KptMenuItem<T>) => void;
13
13
  }
14
14
  /**
15
- * Speed dial — FAB rozwijający zestaw akcji wachlarzem. Buduje na `KptFab`.
15
+ * Speed dial - FAB rozwijający zestaw akcji wachlarzem. Buduje na `KptFab`.
16
16
  *
17
17
  * @example
18
18
  * <KptSpeedDial items={actions} direction="up" onSelect={onAction} />
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { useRef, useState } from 'react';
3
4
  import { cn } from "../internal/cn.js";
@@ -6,7 +7,7 @@ import { useKptMessages } from "../i18n/i18n-context.js";
6
7
  import { KptFab } from "../fab/fab.js";
7
8
  import { KptIcon } from "../icon/icon.js";
8
9
  /**
9
- * Speed dial — FAB rozwijający zestaw akcji wachlarzem. Buduje na `KptFab`.
10
+ * Speed dial - FAB rozwijający zestaw akcji wachlarzem. Buduje na `KptFab`.
10
11
  *
11
12
  * @example
12
13
  * <KptSpeedDial items={actions} direction="up" onSelect={onAction} />
@@ -30,5 +31,5 @@ export function KptSpeedDial({ items = [], direction = 'up', icon = 'plus', aria
30
31
  onSelect?.(item);
31
32
  setOpen(false);
32
33
  };
33
- return (_jsxs("div", { ref: hostRef, className: cn('kpt-speed-dial-host', className), onKeyDown: onKeyDown, ...rest, children: [_jsxs("div", { className: cn('kpt-speed-dial', open && 'is-open'), "data-direction": direction, children: [_jsx("div", { className: "kpt-speed-dial__actions", id: actionsId, children: items.map((item, index) => (_jsxs("button", { type: "button", className: "kpt-speed-dial__action", disabled: item.disabled, "aria-label": item.label, onClick: () => pick(item), children: [item.icon ? _jsx(KptIcon, { name: item.icon }) : null, item.label ? _jsx("span", { className: "kpt-speed-dial__label", children: item.label }) : null] }, index))) }), _jsx(KptFab, { "aria-label": open ? t('common.close') : (ariaLabel ?? t('speedDial.actions')), "aria-expanded": open, "aria-controls": actionsId, onClick: () => setOpen(!open), children: _jsx("span", { className: "kpt-speed-dial__trigger-icon", children: _jsx(KptIcon, { name: icon }) }) })] }), open ? _jsx("div", { className: "kpt-speed-dial__backdrop", onClick: () => setOpen(false) }) : null] }));
34
+ return (_jsxs("div", { ref: hostRef, className: cn('kpt-speed-dial-host', className), onKeyDown: onKeyDown, ...rest, children: [_jsxs("div", { className: cn('kpt-speed-dial', open && 'is-open'), "data-direction": direction, children: [_jsx("div", { className: "kpt-speed-dial__actions", id: actionsId, children: items.map((item, index) => (_jsxs("button", { type: "button", className: "kpt-speed-dial__action", disabled: item.disabled, "aria-label": item.label, onClick: () => pick(item), children: [item.icon ? _jsx(KptIcon, { name: item.icon }) : null, item.label ? _jsx("span", { className: "kpt-speed-dial__label", children: item.label }) : null] }, index))) }), _jsx(KptFab, { "aria-label": open ? t('common.close') : (ariaLabel ?? t('speedDial.actions')), "aria-expanded": open, "aria-controls": actionsId, onClick: () => setOpen(!open), children: _jsx("span", { className: "kpt-speed-dial__trigger-icon", children: _jsx(KptIcon, { name: icon }) }) })] }), open ? (_jsx("div", { className: "kpt-speed-dial__backdrop", onClick: () => setOpen(false) })) : null] }));
34
35
  }
@@ -9,13 +9,13 @@ A loading indicator. Import: `import { KptSpinner } from '@konce-pt/react';`
9
9
  </span>
10
10
 
11
11
  ## Props
12
- - `size`: string (default '1.5rem') — a CSS length, applied to width and height
13
- - `label`: string — the accessibility label; omitted falls back to `spinner.label`
14
- - `locale`, `dictionary` — i18n overrides for this component only
12
+ - `size`: string (default '1.5rem') - a CSS length, applied to width and height
13
+ - `label`: string - the accessibility label; omitted falls back to `spinner.label`
14
+ - `locale`, `dictionary` - i18n overrides for this component only
15
15
  - `className`, `ref` and every other `<span>` prop go to the host
16
16
 
17
17
  ## The colour is inherited
18
- The host sets `color: var(--kpt-color-primary)`, and the ring is drawn in `currentColor` — so the
18
+ The host sets `color: var(--kpt-color-primary)`, and the ring is drawn in `currentColor` - so the
19
19
  spinner is primary by default, and anything that sets `color` on the host changes it. Pass
20
20
  `style={{ color: 'inherit' }}` (or a class) to take the colour of the text around it, e.g. inside a
21
21
  filled chip. There is no colour prop, on purpose.
@@ -23,15 +23,15 @@ filled chip. There is no colour prop, on purpose.
23
23
  ## Examples
24
24
  <KptSpinner />
25
25
  <KptSpinner size="2rem" label="Loading data" />
26
- <KptButton disabled><KptSpinner size="1em" /> Saving…</KptButton>
26
+ <KptButton disabled><KptSpinner size="1em" /> Saving...</KptButton>
27
27
 
28
28
  ## Tokens
29
- None of its own — the colour is `--kpt-color-primary` on the host (drawn in `currentColor`), the
29
+ None of its own - the colour is `--kpt-color-primary` on the host (drawn in `currentColor`), the
30
30
  size comes from the prop, the ring width is 8% of the size (at least 2px), the speed from
31
31
  `--kpt-motion-duration-*`.
32
32
 
33
33
  ## Accessibility
34
34
  The ring is `aria-hidden`; next to it sits a visually hidden `.kpt-spinner__label` with
35
- `role="status"`. Its text — `label`, or `spinner.label` — is written a frame after the spinner
35
+ `role="status"`. Its text - `label`, or `spinner.label` - is written a frame after the spinner
36
36
  appears, because a status region that is born already filled in is skipped by most screen readers.
37
37
  Under `prefers-reduced-motion` the rotation slows down instead of stopping.
@@ -10,7 +10,7 @@ export interface KptSpinnerProps extends Omit<ComponentPropsWithRef<'span'>, 'ch
10
10
  *
11
11
  * Pierścień jest dekoracją (`aria-hidden`); dla czytnika jest osobny, wizualnie ukryty region
12
12
  * `role="status"` z etykietą. Tekst trafia do regionu klatkę po pojawieniu się spinnera: region,
13
- * który powstaje od razu z treścią, większość czytników przemilcza — ogłaszają dopiero zmianę.
13
+ * który powstaje od razu z treścią, większość czytników przemilcza - ogłaszają dopiero zmianę.
14
14
  *
15
15
  * @example
16
16
  * <KptSpinner />
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { useEffect, useState } from 'react';
3
4
  import { cn } from "../internal/cn.js";
@@ -7,7 +8,7 @@ import { useKptMessages } from "../i18n/i18n-context.js";
7
8
  *
8
9
  * Pierścień jest dekoracją (`aria-hidden`); dla czytnika jest osobny, wizualnie ukryty region
9
10
  * `role="status"` z etykietą. Tekst trafia do regionu klatkę po pojawieniu się spinnera: region,
10
- * który powstaje od razu z treścią, większość czytników przemilcza — ogłaszają dopiero zmianę.
11
+ * który powstaje od razu z treścią, większość czytników przemilcza - ogłaszają dopiero zmianę.
11
12
  *
12
13
  * @example
13
14
  * <KptSpinner />
@@ -1,37 +1,37 @@
1
1
  # KptSplitButton (@konce-pt/react)
2
2
 
3
- A split button — a primary action plus a dropdown of further actions.
3
+ A split button - a primary action plus a dropdown of further actions.
4
4
  Import: `import { KptSplitButton } from '@konce-pt/react';`
5
5
 
6
6
  ## DOM
7
7
  <span class="kpt-split-button-host">
8
8
  <div class="kpt-split-button" data-variant="filled">
9
9
  <button class="kpt-split-button__main" type="button">Save</button>
10
- <button class="kpt-split-button__toggle" type="button" aria-label="More actions">…chevron…</button>
10
+ <button class="kpt-split-button__toggle" type="button" aria-label="More actions">...chevron...</button>
11
11
  </div>
12
12
  </span>
13
13
  <!-- while open, in a portal: -->
14
- <div class="kpt-split-button__panel" role="menu">…rows…</div>
14
+ <div class="kpt-split-button__panel" role="menu">...rows...</div>
15
15
 
16
16
  ## Props
17
- - `variant`: `KptSplitButtonVariant` = 'filled' | 'tonal' | 'outline' | 'text' (default 'filled') —
17
+ - `variant`: `KptSplitButtonVariant` = 'filled' | 'tonal' | 'outline' | 'text' (default 'filled') -
18
18
  the subset of `KptButtonVariant` that has a style; `outline` and `text` use the `--kpt-button-outline-*`
19
19
  and `--kpt-button-text-*` tokens, so they match `kpt-button` in the same row
20
- - `items`: `KptMenuItem<T>[]` — the same shape as `KptMenu`
21
- - `disabled`: boolean — disables both buttons
22
- - `onPrimaryClick()` — the main action
23
- - `onSelect(item)` — a pick from the menu
24
- - `open` / `defaultOpen` / `onOpenChange` — the panel state
25
- - `children` — the content of the main action
26
- - `locale`, `dictionary` — i18n overrides for this component only
20
+ - `items`: `KptMenuItem<T>[]` - the same shape as `KptMenu`
21
+ - `disabled`: boolean - disables both buttons
22
+ - `onPrimaryClick()` - the main action
23
+ - `onSelect(item)` - a pick from the menu
24
+ - `open` / `defaultOpen` / `onOpenChange` - the panel state
25
+ - `children` - the content of the main action
26
+ - `locale`, `dictionary` - i18n overrides for this component only
27
27
 
28
28
  ## The panel aligns to the right
29
29
  The toggle sits on the right-hand side of the control, so the panel is anchored by its RIGHT edge
30
30
  (`align="end"` on the overlay). Anchored to the left it would hang off the control instead of under
31
- it — the same reasoning the Angular port encodes in its CDK position list.
31
+ it - the same reasoning the Angular port encodes in its CDK position list.
32
32
 
33
33
  ## Shared rows
34
- The panel renders the same rows as `KptMenu` — icons, descriptions, badges, separators, headers and
34
+ The panel renders the same rows as `KptMenu` - icons, descriptions, badges, separators, headers and
35
35
  the `danger` modifier all behave identically, only the BEM block differs.
36
36
 
37
37
  ## i18n
@@ -39,9 +39,9 @@ The toggle's label comes from `splitButton.more` in the dictionary.
39
39
 
40
40
  ## Keyboard
41
41
  The toggle is a menu button: `aria-haspopup="menu"`, a live `aria-expanded`, `aria-controls` while
42
- open. `↓` / `↑` on it open the menu on the first / last item; inside, `↓` / `↑` wrap, `Home` / `End`
42
+ open. `ArrowDown` / `ArrowUp` on it open the menu on the first / last item; inside, `ArrowDown` / `ArrowUp` wrap, `Home` / `End`
43
43
  jump, `Escape` / `Tab` close, and closing or picking returns focus to the toggle. Same rules as the
44
- menu — see the `KptMenu` docs.
44
+ menu - see the `KptMenu` docs.
45
45
 
46
46
  ## Examples
47
47
  <KptSplitButton items={items} onPrimaryClick={save} onSelect={onItem}>Save</KptSplitButton>
@@ -53,6 +53,12 @@ menu — see the `KptMenu` docs.
53
53
  { label: 'Discard', value: 'discard', danger: true },
54
54
  ];
55
55
 
56
+ ## Motion
57
+ Pressing either part squeezes the whole pill (one part alone would come apart from the other inside
58
+ the clipped container); the arrow turns over when the menu opens and the menu slides out from under the
59
+ button. Pure CSS; durations follow `--kpt-motion-scale`, so `enabled: false` turns it off, and it drops out
60
+ under "reduce motion".
61
+
56
62
  ## Tokens
57
63
  The `--kpt-button-*` tokens of the chosen variant, plus `--kpt-color-surface-raised` and
58
64
  `--kpt-elevation-3` for the panel.
@@ -2,7 +2,7 @@ import { type ComponentPropsWithRef, type ReactNode } from 'react';
2
2
  import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
3
3
  import type { KptMenuItem } from '../menu/menu-item.ts';
4
4
  import type { KptButtonVariant } from '../button/button.tsx';
5
- /** Warianty, które mają styl — podzbiór `KptButtonVariant`. */
5
+ /** Warianty, które mają styl - podzbiór `KptButtonVariant`. */
6
6
  export type KptSplitButtonVariant = Extract<KptButtonVariant, 'filled' | 'tonal' | 'outline' | 'text'>;
7
7
  export interface KptSplitButtonProps<T> extends Omit<ComponentPropsWithRef<'span'>, 'onSelect'>, KptI18nOverrides {
8
8
  variant?: KptSplitButtonVariant;
@@ -19,7 +19,7 @@ export interface KptSplitButtonProps<T> extends Omit<ComponentPropsWithRef<'span
19
19
  children?: ReactNode;
20
20
  }
21
21
  /**
22
- * Przycisk dzielony — akcja główna plus rozwijane menu dodatkowych akcji.
22
+ * Przycisk dzielony - akcja główna plus rozwijane menu dodatkowych akcji.
23
23
  *
24
24
  * Panel wyrównuje się do PRAWEJ krawędzi przycisku, nie do lewej: rozwijacz siedzi po prawej
25
25
  * stronie kontrolki, więc menu otwierające się w lewo nie wychodzi poza nią.
@@ -1,5 +1,6 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useRef } from 'react';
3
+ import { useCallback, useEffect, useRef, useState } from 'react';
3
4
  import { cn } from "../internal/cn.js";
4
5
  import { KptOverlay } from "../internal/overlay.js";
5
6
  import { useControllableState } from "../internal/use-controllable-state.js";
@@ -9,7 +10,7 @@ import { KptIcon } from "../icon/icon.js";
9
10
  import { MenuRows } from "../menu/menu-rows.js";
10
11
  import { focusMenuEdge, handleMenuKeydown } from "../menu/menu-keys.js";
11
12
  /**
12
- * Przycisk dzielony — akcja główna plus rozwijane menu dodatkowych akcji.
13
+ * Przycisk dzielony - akcja główna plus rozwijane menu dodatkowych akcji.
13
14
  *
14
15
  * Panel wyrównuje się do PRAWEJ krawędzi przycisku, nie do lewej: rozwijacz siedzi po prawej
15
16
  * stronie kontrolki, więc menu otwierające się w lewo nie wychodzi poza nią.
@@ -20,8 +21,14 @@ import { focusMenuEdge, handleMenuKeydown } from "../menu/menu-keys.js";
20
21
  export function KptSplitButton({ variant = 'filled', items = [], disabled = false, onPrimaryClick, onSelect, open, defaultOpen = false, onOpenChange, locale, dictionary, className, children, ...rest }) {
21
22
  const { t } = useKptMessages({ locale, dictionary });
22
23
  const toggleRef = useRef(null);
24
+ /** Kotwica panelu - w stanie, bo czyta ją render; ref zostaje dla przywracania fokusu. */
25
+ const [toggleEl, setToggleEl] = useState(null);
26
+ const setToggle = useCallback((element) => {
27
+ toggleRef.current = element;
28
+ setToggleEl(element);
29
+ }, []);
23
30
  const panelRef = useRef(null);
24
- /** Którą pozycję skupić po otwarciu — strzałka w górę na przycisku otwiera „od końca”. */
31
+ /** Którą pozycję skupić po otwarciu - strzałka w górę na przycisku otwiera "od końca". */
25
32
  const focusEdge = useRef('first');
26
33
  const panelId = useKptId(undefined, 'kpt-split-button-menu');
27
34
  const [isOpen, setOpen] = useControllableState({
@@ -41,7 +48,7 @@ export function KptSplitButton({ variant = 'filled', items = [], disabled = fals
41
48
  });
42
49
  return () => cancelAnimationFrame(frame);
43
50
  }, [isOpen]);
44
- /** Fokus wraca na strzałkę — inaczej po zniknięciu panelu spadłby na `<body>`. */
51
+ /** Fokus wraca na strzałkę - inaczej po zniknięciu panelu spadłby na `<body>`. */
45
52
  const closeAndRestoreFocus = () => {
46
53
  close();
47
54
  toggleRef.current?.focus();
@@ -67,8 +74,8 @@ export function KptSplitButton({ variant = 'filled', items = [], disabled = fals
67
74
  onSelect?.(item);
68
75
  closeAndRestoreFocus();
69
76
  };
70
- return (_jsxs("span", { className: cn('kpt-split-button-host', className), ...rest, children: [_jsxs("div", { className: "kpt-split-button", "data-variant": variant, children: [_jsx("button", { className: "kpt-split-button__main", type: "button", disabled: disabled, onClick: onPrimaryClick, children: children }), _jsx("button", { ref: toggleRef, className: "kpt-split-button__toggle", type: "button", disabled: disabled, onClick: () => {
77
+ return (_jsxs("span", { className: cn('kpt-split-button-host', className), ...rest, children: [_jsxs("div", { className: "kpt-split-button", "data-variant": variant, children: [_jsx("button", { className: "kpt-split-button__main", type: "button", disabled: disabled, onClick: onPrimaryClick, children: children }), _jsx("button", { ref: setToggle, className: "kpt-split-button__toggle", type: "button", disabled: disabled, onClick: () => {
71
78
  focusEdge.current = 'first';
72
79
  setOpen(!isOpen);
73
- }, onKeyDown: onToggleKeyDown, "aria-haspopup": "menu", "aria-expanded": isOpen, "aria-controls": isOpen ? panelId : undefined, "aria-label": t('splitButton.more'), children: _jsx(KptIcon, { name: "chevron-down" }) })] }), _jsx(KptOverlay, { open: isOpen, anchor: toggleRef.current, onClose: close, align: "end", children: _jsx("div", { ref: panelRef, id: panelId, className: "kpt-split-button__panel", role: "menu", onKeyDown: onPanelKeyDown, children: _jsx(MenuRows, { items: items, block: "kpt-split-button", onPick: pick }) }) })] }));
80
+ }, onKeyDown: onToggleKeyDown, "aria-haspopup": "menu", "aria-expanded": isOpen, "aria-controls": isOpen ? panelId : undefined, "aria-label": t('splitButton.more'), children: _jsx(KptIcon, { name: "chevron-down" }) })] }), _jsx(KptOverlay, { open: isOpen, anchor: toggleEl, onClose: close, align: "end", children: _jsx("div", { ref: panelRef, id: panelId, className: "kpt-split-button__panel", role: "menu", tabIndex: -1, onKeyDown: onPanelKeyDown, children: _jsx(MenuRows, { items: items, block: "kpt-split-button", onPick: pick }) }) })] }));
74
81
  }
@@ -6,22 +6,22 @@ Import: `import { KptSplitter } from '@konce-pt/react';`
6
6
  ## DOM
7
7
  <div class="kpt-splitter-host">
8
8
  <div class="kpt-splitter" data-orientation="horizontal">
9
- <div class="kpt-splitter__pane" id="kpt-splitter-start-r1" style="flex-basis:40%">…</div>
9
+ <div class="kpt-splitter__pane" id="kpt-splitter-start-r1" style="flex-basis:40%">...</div>
10
10
  <div class="kpt-splitter__gutter" role="separator" tabindex="0" aria-orientation="vertical"
11
11
  aria-valuenow="40" aria-valuemin="10" aria-valuemax="90"
12
12
  aria-controls="kpt-splitter-start-r1" aria-label="Resize panes"></div>
13
- <div class="kpt-splitter__pane" style="flex-basis:60%">…</div>
13
+ <div class="kpt-splitter__pane" style="flex-basis:60%">...</div>
14
14
  </div>
15
15
  </div>
16
16
 
17
17
  ## Props
18
18
  - `orientation`: `'horizontal'` (default) | `'vertical'`
19
- - `startSize` / `defaultStartSize` / `onStartSizeChange` — the first pane's size in percent
20
- - `minSize`: number (percent, default 10) — neither pane goes below it
21
- - `ariaLabel`: string — the handle's name; empty = `splitter.resize` from the dictionary
22
- - `ariaLabel`: string — the handle's name; empty = `splitter.resize` from the dictionary
23
- - `ariaLabel`: string — the handle's name; empty = `splitter.resize` from the dictionary
24
- - `ariaLabel`: string — the handle's name; empty = `splitter.resize` from the dictionary
19
+ - `startSize` / `defaultStartSize` / `onStartSizeChange` - the first pane's size in percent
20
+ - `minSize`: number (percent, default 10) - neither pane goes below it
21
+ - `ariaLabel`: string - the handle's name; empty = `splitter.resize` from the dictionary
22
+ - `ariaLabel`: string - the handle's name; empty = `splitter.resize` from the dictionary
23
+ - `ariaLabel`: string - the handle's name; empty = `splitter.resize` from the dictionary
24
+ - `ariaLabel`: string - the handle's name; empty = `splitter.resize` from the dictionary
25
25
  - `className`, `ref` and every other `<div>` prop go to the host
26
26
 
27
27
  ## Panes
@@ -39,16 +39,16 @@ pointer outruns a 6px strip, and a handle-bound listener would drop the drag aft
39
39
  <KptSplitter.End>Right</KptSplitter.End>
40
40
  </KptSplitter>
41
41
 
42
- <KptSplitter orientation="vertical" defaultStartSize={30} minSize={20}>…</KptSplitter>
42
+ <KptSplitter orientation="vertical" defaultStartSize={30} minSize={20}>...</KptSplitter>
43
43
 
44
44
  ## Tokens
45
- The handle `--kpt-color-border` → `--kpt-color-primary` on hover and focus; the frame
45
+ The handle `--kpt-color-border` -> `--kpt-color-primary` on hover and focus; the frame
46
46
  `--kpt-color-border` with `--kpt-radius-md`.
47
47
 
48
48
  ## Accessibility
49
49
  The handle is a focusable `role="separator"` (the WAI-ARIA window splitter): `aria-valuenow`,
50
50
  `aria-valuemin`/`aria-valuemax` (from `minSize`), `aria-controls` pointing at the first pane, and a
51
51
  name from `ariaLabel` or `splitter.resize` in the dictionary. Arrow keys resize by 2%, `Home`/`End`
52
- jump to the minimum/maximum. `aria-orientation` describes the handle's line, not the layout —
52
+ jump to the minimum/maximum. `aria-orientation` describes the handle's line, not the layout -
53
53
  side-by-side panes have a vertical handle. The host takes `height: 100%`, so a height set on the
54
54
  parent reaches the panes.
@@ -15,7 +15,7 @@ export declare namespace KptSplitterEnd {
15
15
  }
16
16
  export interface KptSplitterProps extends Omit<ComponentPropsWithRef<'div'>, 'onChange'>, KptI18nOverrides {
17
17
  orientation?: KptSplitterOrientation;
18
- /** Rozmiar pierwszego panelu w procentach (0–100). */
18
+ /** Rozmiar pierwszego panelu w procentach (0-100). */
19
19
  startSize?: number;
20
20
  defaultStartSize?: number;
21
21
  onStartSizeChange?: (size: number) => void;
@@ -29,9 +29,9 @@ export interface KptSplitterProps extends Omit<ComponentPropsWithRef<'div'>, 'on
29
29
  * Dwa panele z przeciąganym uchwytem. `horizontal` stawia je obok siebie, `vertical` jeden pod
30
30
  * drugim.
31
31
  *
32
- * Uchwyt to `role="separator"` z wartością (wzorzec WAI-ARIA „window splitter”): strzałki
32
+ * Uchwyt to `role="separator"` z wartością (wzorzec WAI-ARIA "window splitter"): strzałki
33
33
  * przesuwają go o 2%, `Home`/`End` dosuwają do minimum i maksimum. `aria-orientation` opisuje
34
- * linię uchwytu, nie układ — przy panelach obok siebie linia jest pionowa.
34
+ * linię uchwytu, nie układ - przy panelach obok siebie linia jest pionowa.
35
35
  *
36
36
  * @example
37
37
  * <KptSplitter startSize={size} onStartSizeChange={setSize}>