@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,3 +1,4 @@
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 { useControllableState } from "../internal/use-controllable-state.js";
@@ -16,11 +17,11 @@ const ICONS = {
16
17
  * go. `visible`/`onVisibleChange` pozwalają pokazać go ponownie z zewnątrz.
17
18
  *
18
19
  * Rola idzie za wagą komunikatu: `info` i `success` to `role="status"` (czytnik ogłosi je uprzejmie,
19
- * nie przerywając), `warning` i `danger` — `role="alert"` (natychmiast).
20
+ * nie przerywając), `warning` i `danger` - `role="alert"` (natychmiast).
20
21
  *
21
22
  * @example
22
23
  * <KptAlert variant="success" title="Zapisano">Zmiany zostały zapisane.</KptAlert>
23
- * <KptAlert variant="warning" dismissible onClosed={onClosed}>Uwaga…</KptAlert>
24
+ * <KptAlert variant="warning" dismissible onClosed={onClosed}>Uwaga...</KptAlert>
24
25
  */
25
26
  export function KptAlert({ variant = 'info', title = '', dismissible = false, onClosed, visible, defaultVisible = true, onVisibleChange, locale, dictionary, className, children, ...rest }) {
26
27
  const { t } = useKptMessages({ locale, dictionary });
@@ -6,22 +6,22 @@ Import: `import { KptAlert } from '@konce-pt/react';`
6
6
  ## DOM
7
7
  <div class="kpt-alert-host">
8
8
  <div class="kpt-alert" data-variant="success" role="status">
9
- <span class="kpt-icon-host kpt-alert__icon">…</span>
9
+ <span class="kpt-icon-host kpt-alert__icon">...</span>
10
10
  <div class="kpt-alert__content">
11
11
  <div class="kpt-alert__title">Saved</div>
12
- <div class="kpt-alert__message">…children…</div>
12
+ <div class="kpt-alert__message">...children...</div>
13
13
  </div>
14
- <button class="kpt-alert__close" type="button" aria-label="Close">…</button>
14
+ <button class="kpt-alert__close" type="button" aria-label="Close">...</button>
15
15
  </div>
16
16
  </div>
17
17
 
18
18
  ## Props
19
19
  - `variant`: 'info' | 'success' | 'warning' | 'danger' (default 'info')
20
20
  - `title`: string
21
- - `dismissible`: boolean — adds the close button
22
- - `visible` / `defaultVisible` / `onVisibleChange` — controlled or uncontrolled visibility
23
- - `onClosed()` — fires after the user dismisses it
24
- - `locale`, `dictionary` — i18n overrides for this component only
21
+ - `dismissible`: boolean - adds the close button
22
+ - `visible` / `defaultVisible` / `onVisibleChange` - controlled or uncontrolled visibility
23
+ - `onClosed()` - fires after the user dismisses it
24
+ - `locale`, `dictionary` - i18n overrides for this component only
25
25
  - `className`, `ref` and every other `<div>` prop go to the host
26
26
 
27
27
  ## Dismissal hides, it does not unmount
@@ -43,5 +43,6 @@ The semantic colour pairs of each variant (`--kpt-color-info` / `-success` / `-w
43
43
  ## Accessibility
44
44
  The role follows the weight of the message: `info` and `success` are `role="status"` (read
45
45
  politely, without interrupting), `warning` and `danger` are `role="alert"` (read at once). The icon
46
- is decorative; the × button is labelled from `common.close`. After closing, focus falls back to the
47
- page — move it yourself in the close handler when the alert was reached with the keyboard.
46
+ is decorative; the x button is labelled from `common.close`. After closing, focus falls back to the
47
+ page - move it yourself in the close handler when the alert was reached with the keyboard.
48
+ A live region announces **changes**: an alert rendered together with the page (or revealed by toggling `hidden`) is not announced reliably. To have it read, add it after the action (`@if` / conditional render) - the inserted element is announced.
@@ -3,13 +3,13 @@ import { type KptBreakpoint } from '../internal/use-breakpoint.ts';
3
3
  import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
4
4
  /**
5
5
  * Zachowanie panelu bocznego:
6
- * - `auto` — zależne od szerokości okna (domyślne),
7
- * - `side` — zawsze zadokowany, rozpycha treść,
8
- * - `over` — zawsze nakładka nad treścią.
6
+ * - `auto` - zależne od szerokości okna (domyślne),
7
+ * - `side` - zawsze zadokowany, rozpycha treść,
8
+ * - `over` - zawsze nakładka nad treścią.
9
9
  */
10
10
  export type KptSidenavMode = 'side' | 'over' | 'auto';
11
11
  export interface KptAppShellProps extends Omit<ComponentPropsWithRef<'div'>, 'children'>, KptI18nOverrides {
12
- /** Slot górnego paska — renderowany nad obszarem treści (zwykle `<KptToolbar>`). */
12
+ /** Slot górnego paska - renderowany nad obszarem treści (zwykle `<KptToolbar>`). */
13
13
  toolbar?: ReactNode;
14
14
  /** Slot panelu bocznego (zwykle `<KptSidenav>`). */
15
15
  sidenav?: ReactNode;
@@ -41,9 +41,9 @@ export interface KptAppShellProps extends Omit<ComponentPropsWithRef<'div'>, 'ch
41
41
  /** Etykieta dostępności panelu; puste = `appShell.navigation` ze słownika. */
42
42
  sidenavLabel?: string;
43
43
  }
44
- /** Kontrakt kontekstu shella — czytany przez `useKptAppShell()` i przełącznik panelu. */
44
+ /** Kontrakt kontekstu shella - czytany przez `useKptAppShell()` i przełącznik panelu. */
45
45
  export interface KptAppShellContextValue {
46
- /** Efektywny stan otwarcia — ten, który obowiązuje w bieżącym układzie. */
46
+ /** Efektywny stan otwarcia - ten, który obowiązuje w bieżącym układzie. */
47
47
  isSidenavOpen: boolean;
48
48
  /** Czy panel zachowuje się TERAZ jak nakładka nad treścią. */
49
49
  isOverlay: boolean;
@@ -59,23 +59,23 @@ export interface KptAppShellContextValue {
59
59
  * Domyślny tryb `auto` jest responsywny bez konfiguracji: od `sidenavBreakpoint` w górę panel
60
60
  * jest zadokowany, poniżej zachowuje się jak nakładka ze scrimem i startuje zamknięty.
61
61
  *
62
- * O układzie decyduje wyłącznie CSS — nic nie migocze przed hydracją i nic nie zależy od
62
+ * O układzie decyduje wyłącznie CSS - nic nie migocze przed hydracją i nic nie zależy od
63
63
  * `matchMedia`. JavaScript odpowiada tylko za to, KTÓRY stan przełącza przycisk.
64
64
  *
65
65
  * @example
66
66
  * <KptAppShell
67
- * toolbar={<KptToolbar>…</KptToolbar>}
68
- * sidenav={<KptSidenav>…</KptSidenav>}
67
+ * toolbar={<KptToolbar>...</KptToolbar>}
68
+ * sidenav={<KptSidenav>...</KptSidenav>}
69
69
  * >
70
70
  * <Routes />
71
71
  * </KptAppShell>
72
72
  */
73
73
  export declare function KptAppShell({ toolbar, sidenav, children, sidenavOpen, defaultSidenavOpen, onSidenavOpenChange, sidenavCompactOpen, defaultSidenavCompactOpen, onSidenavCompactOpenChange, sidenavMode, sidenavBreakpoint, sidenavRailBreakpoint, sidenavLabel, locale, dictionary, className, ...rest }: Readonly<KptAppShellProps>): import("react").JSX.Element;
74
- /** Dostęp do stanu shella. Poza `KptAppShell` rzuca — to zawsze błąd użycia. */
74
+ /** Dostęp do stanu shella. Poza `KptAppShell` rzuca - to zawsze błąd użycia. */
75
75
  export declare function useKptAppShell(): KptAppShellContextValue;
76
76
  /**
77
77
  * Propsy przycisku przełączającego panel boczny. Rozłóż je na natywnym `<button>`
78
- * (albo na `<KptButton>`, który przekazuje je do swojego wewnętrznego `<button>`) —
78
+ * (albo na `<KptButton>`, który przekazuje je do swojego wewnętrznego `<button>`) -
79
79
  * atrybuty ARIA muszą wylądować na elemencie z rolą, nie na opakowaniu.
80
80
  *
81
81
  * Trafia w stan właściwy dla bieżącego układu, więc jeden przycisk obsługuje desktop
@@ -93,11 +93,11 @@ export declare function useKptShellNavToggle(options?: {
93
93
  readonly onClick: () => void;
94
94
  };
95
95
  /**
96
- * Etykieta pozycji nawigacji. W szynie ikon (układ md–xl) shell chowa ją techniką
97
- * „visually hidden", więc pozycja zwęża się do samego znaku, a czytnik ekranu wciąż
96
+ * Etykieta pozycji nawigacji. W szynie ikon (układ md-xl) shell chowa ją techniką
97
+ * "visually hidden", więc pozycja zwęża się do samego znaku, a czytnik ekranu wciąż
98
98
  * odczytuje pełny tekst.
99
99
  *
100
- * Nosi atrybut `kptnavlabel` — to po nim celuje wspólny SCSS. Nazwy atrybutów w selektorach
100
+ * Nosi atrybut `kptnavlabel` - to po nim celuje wspólny SCSS. Nazwy atrybutów w selektorach
101
101
  * CSS są w HTML case-insensitive, więc jedna reguła obsługuje oba porty; zapis małymi literami
102
102
  * omija przy okazji ostrzeżenie React o nieznanym propie.
103
103
  *
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, } from 'react';
3
4
  import { cn } from "../internal/cn.js";
@@ -14,13 +15,13 @@ const KptAppShellContext = createContext(null);
14
15
  * Domyślny tryb `auto` jest responsywny bez konfiguracji: od `sidenavBreakpoint` w górę panel
15
16
  * jest zadokowany, poniżej zachowuje się jak nakładka ze scrimem i startuje zamknięty.
16
17
  *
17
- * O układzie decyduje wyłącznie CSS — nic nie migocze przed hydracją i nic nie zależy od
18
+ * O układzie decyduje wyłącznie CSS - nic nie migocze przed hydracją i nic nie zależy od
18
19
  * `matchMedia`. JavaScript odpowiada tylko za to, KTÓRY stan przełącza przycisk.
19
20
  *
20
21
  * @example
21
22
  * <KptAppShell
22
- * toolbar={<KptToolbar>…</KptToolbar>}
23
- * sidenav={<KptSidenav>…</KptSidenav>}
23
+ * toolbar={<KptToolbar>...</KptToolbar>}
24
+ * sidenav={<KptSidenav>...</KptSidenav>}
24
25
  * >
25
26
  * <Routes />
26
27
  * </KptAppShell>
@@ -58,9 +59,15 @@ export function KptAppShell({ toolbar, sidenav, children, sidenavOpen, defaultSi
58
59
  useEffect(() => {
59
60
  if (!isOverlay || !isSidenavOpen)
60
61
  return;
62
+ // Escape zamyka nakładkę nawigacji - ale nie wtedy, gdy zamyka nim coś otwartego nad shellem
63
+ // (okno, menu, popover): te wołają `preventDefault()` albo trzymają fokus w sobie.
61
64
  const onKeyDown = (event) => {
62
- if (event.key === 'Escape')
63
- closeSidenav();
65
+ if (event.key !== 'Escape' || event.defaultPrevented)
66
+ return;
67
+ const target = event.target instanceof Element ? event.target : null;
68
+ if (target?.closest('dialog[open], [popover], [role="menu"], [role="listbox"], [role="dialog"]'))
69
+ return;
70
+ closeSidenav();
64
71
  };
65
72
  document.addEventListener('keydown', onKeyDown);
66
73
  return () => document.removeEventListener('keydown', onKeyDown);
@@ -73,19 +80,19 @@ export function KptAppShell({ toolbar, sidenav, children, sidenavOpen, defaultSi
73
80
  openSidenav: () => setSidenavOpen(true),
74
81
  closeSidenav,
75
82
  }), [isSidenavOpen, isOverlay, sidenavId, setSidenavOpen, closeSidenav]);
76
- // Scrim blokuje wskaźnik, ale nie klawiaturę — treść pod nakładką nie może łapać fokusu.
83
+ // Scrim blokuje wskaźnik, ale nie klawiaturę - treść pod nakładką nie może łapać fokusu.
77
84
  const contentInert = isOverlay && isSidenavOpen;
78
85
  // Otwarta nakładka robi treść `inert`, więc fokus zostawiony w niej (albo na przycisku menu)
79
86
  // nie miałby dokąd pójść. Po otwarciu przenosimy go do panelu, po zamknięciu oddajemy tam,
80
- // skąd przyszedł — chyba że użytkownik zdążył go przenieść gdzie indziej. Stan `null` przed
87
+ // skąd przyszedł - chyba że użytkownik zdążył go przenieść gdzie indziej. Stan `null` przed
81
88
  // pierwszym renderem: nakładka otwarta już przy starcie nie zabiera fokusu.
82
- const asideRef = useRef(null);
89
+ const navRef = useRef(null);
83
90
  const overlayWasOpen = useRef(null);
84
91
  const returnFocusTo = useRef(null);
85
92
  useEffect(() => {
86
93
  const was = overlayWasOpen.current;
87
94
  overlayWasOpen.current = contentInert;
88
- const panel = asideRef.current;
95
+ const panel = navRef.current;
89
96
  if (was === null || was === contentInert || !panel)
90
97
  return;
91
98
  const active = document.activeElement;
@@ -99,9 +106,9 @@ export function KptAppShell({ toolbar, sidenav, children, sidenavOpen, defaultSi
99
106
  returnFocusTo.current.focus();
100
107
  returnFocusTo.current = null;
101
108
  }, [contentInert]);
102
- return (_jsx(KptAppShellContext.Provider, { value: context, children: _jsxs("div", { className: cn('kpt-app-shell', dockedOpen && 'kpt-app-shell--nav-open', compactOpen && 'kpt-app-shell--nav-compact-open', className), "data-sidenav-mode": sidenavMode, "data-sidenav-breakpoint": sidenavBreakpoint, "data-sidenav-rail": sidenavRailBreakpoint ?? undefined, ...rest, children: [toolbar, _jsxs("div", { className: "kpt-app-shell__body", children: [_jsx("aside", { ref: asideRef, className: "kpt-app-shell__sidenav", role: "navigation", tabIndex: -1, id: sidenavId, "aria-label": sidenavLabel || t('appShell.navigation'), children: sidenav }), _jsx("div", { className: "kpt-app-shell__scrim", "aria-hidden": "true", onClick: closeSidenav }), _jsx("main", { className: "kpt-app-shell__content", inert: contentInert, children: children })] })] }) }));
109
+ return (_jsx(KptAppShellContext.Provider, { value: context, children: _jsxs("div", { className: cn('kpt-app-shell', dockedOpen && 'kpt-app-shell--nav-open', compactOpen && 'kpt-app-shell--nav-compact-open', className), "data-sidenav-mode": sidenavMode, "data-sidenav-breakpoint": sidenavBreakpoint, "data-sidenav-rail": sidenavRailBreakpoint ?? undefined, ...rest, children: [toolbar, _jsxs("div", { className: "kpt-app-shell__body", children: [_jsx("nav", { ref: navRef, className: "kpt-app-shell__sidenav", tabIndex: -1, id: sidenavId, "aria-label": sidenavLabel || t('appShell.navigation'), children: sidenav }), _jsx("div", { className: "kpt-app-shell__scrim", "aria-hidden": "true", onClick: closeSidenav }), _jsx("main", { className: "kpt-app-shell__content", inert: contentInert, children: children })] })] }) }));
103
110
  }
104
- /** Dostęp do stanu shella. Poza `KptAppShell` rzuca — to zawsze błąd użycia. */
111
+ /** Dostęp do stanu shella. Poza `KptAppShell` rzuca - to zawsze błąd użycia. */
105
112
  export function useKptAppShell() {
106
113
  const context = useContext(KptAppShellContext);
107
114
  if (!context)
@@ -110,7 +117,7 @@ export function useKptAppShell() {
110
117
  }
111
118
  /**
112
119
  * Propsy przycisku przełączającego panel boczny. Rozłóż je na natywnym `<button>`
113
- * (albo na `<KptButton>`, który przekazuje je do swojego wewnętrznego `<button>`) —
120
+ * (albo na `<KptButton>`, który przekazuje je do swojego wewnętrznego `<button>`) -
114
121
  * atrybuty ARIA muszą wylądować na elemencie z rolą, nie na opakowaniu.
115
122
  *
116
123
  * Trafia w stan właściwy dla bieżącego układu, więc jeden przycisk obsługuje desktop
@@ -130,11 +137,11 @@ export function useKptShellNavToggle(options) {
130
137
  };
131
138
  }
132
139
  /**
133
- * Etykieta pozycji nawigacji. W szynie ikon (układ md–xl) shell chowa ją techniką
134
- * „visually hidden", więc pozycja zwęża się do samego znaku, a czytnik ekranu wciąż
140
+ * Etykieta pozycji nawigacji. W szynie ikon (układ md-xl) shell chowa ją techniką
141
+ * "visually hidden", więc pozycja zwęża się do samego znaku, a czytnik ekranu wciąż
135
142
  * odczytuje pełny tekst.
136
143
  *
137
- * Nosi atrybut `kptnavlabel` — to po nim celuje wspólny SCSS. Nazwy atrybutów w selektorach
144
+ * Nosi atrybut `kptnavlabel` - to po nim celuje wspólny SCSS. Nazwy atrybutów w selektorach
138
145
  * CSS są w HTML case-insensitive, więc jedna reguła obsługuje oba porty; zapis małymi literami
139
146
  * omija przy okazji ostrzeżenie React o nieznanym propie.
140
147
  *
@@ -6,27 +6,27 @@ Import: `import { KptAppShell, useKptShellNavToggle } from '@konce-pt/react';`
6
6
  ## DOM
7
7
  <div class="kpt-app-shell kpt-app-shell--nav-open"
8
8
  data-sidenav-mode="auto" data-sidenav-breakpoint="lg">
9
- …toolbar…
9
+ ...toolbar...
10
10
  <div class="kpt-app-shell__body">
11
- <aside class="kpt-app-shell__sidenav" role="navigation" tabindex="-1" id="…">…sidenav…</aside>
11
+ <nav class="kpt-app-shell__sidenav" tabindex="-1" id="...">...sidenav...</nav>
12
12
  <div class="kpt-app-shell__scrim" aria-hidden="true"></div>
13
- <main class="kpt-app-shell__content">…children…</main>
13
+ <main class="kpt-app-shell__content">...children...</main>
14
14
  </div>
15
15
  </div>
16
16
 
17
17
  ## Props
18
- - `toolbar`: ReactNode — the slot above the content area (usually `<KptToolbar>`)
19
- - `sidenav`: ReactNode — the side panel slot (usually `<KptSidenav>`)
20
- - `children`: ReactNode — the application content
21
- - `sidenavOpen` / `defaultSidenavOpen` / `onSidenavOpenChange` — the docked layout's open state
18
+ - `toolbar`: ReactNode - the slot above the content area (usually `<KptToolbar>`)
19
+ - `sidenav`: ReactNode - the side panel slot (usually `<KptSidenav>`)
20
+ - `children`: ReactNode - the application content
21
+ - `sidenavOpen` / `defaultSidenavOpen` / `onSidenavOpenChange` - the docked layout's open state
22
22
  (default open)
23
- - `sidenavCompactOpen` / `defaultSidenavCompactOpen` / `onSidenavCompactOpenChange` — the overlay's
23
+ - `sidenavCompactOpen` / `defaultSidenavCompactOpen` / `onSidenavCompactOpenChange` - the overlay's
24
24
  open state (default closed)
25
25
  - `sidenavMode`: 'auto' | 'side' | 'over' (default 'auto')
26
26
  - `sidenavBreakpoint`: 'sm' | 'md' | 'lg' | 'xl' | '2xl' (default 'lg')
27
27
  - `sidenavRailBreakpoint`: the same union or null (default null)
28
- - `sidenavLabel`: string — empty falls back to `appShell.navigation` from the dictionary
29
- - `locale`, `dictionary` — i18n overrides for this component only
28
+ - `sidenavLabel`: string - empty falls back to `appShell.navigation` from the dictionary
29
+ - `locale`, `dictionary` - i18n overrides for this component only
30
30
 
31
31
  ## Two open states, on purpose
32
32
  The docked layout and the overlay keep separate state. If they shared one, narrowing the window
@@ -38,7 +38,7 @@ would have to overwrite the consumer's state, and widening it back would have no
38
38
  <KptButton variant="text" {...toggle}>Menu</KptButton>
39
39
 
40
40
  It returns `aria-expanded`, `aria-controls`, `aria-label` and `onClick`. Spread them on a native
41
- `<button>` or on `<KptButton>` (which forwards them to its inner `<button>`) — ARIA attributes must
41
+ `<button>` or on `<KptButton>` (which forwards them to its inner `<button>`) - ARIA attributes must
42
42
  land on the element that carries the role, never on a wrapper.
43
43
 
44
44
  `useKptAppShell()` exposes the same state directly: `{ isSidenavOpen, isOverlay, sidenavId,
@@ -54,9 +54,10 @@ decides WHICH state the button flips. The scrim is always in the DOM; CSS contro
54
54
  `--kpt-color-overlay-scrim`, `--kpt-motion-duration-base`, `--kpt-motion-easing-standard`.
55
55
 
56
56
  ## Accessibility
57
- - The panel is an `<aside role="navigation">` with a label and an `id` for `aria-controls`.
57
+ - The panel is a `<nav>` with a label and an `id` for `aria-controls`.
58
58
  - A closed docked panel leaves the tab order through `visibility`, correct on the first frame.
59
- - While the overlay is open the content gets `inert`, and Escape closes the panel.
60
- - Opening the overlay moves focus into the panel (its first focusable element, or the `<aside>`
61
- itself); closing it returns focus to where it came from — usually the menu button — unless the user
59
+ - While the overlay is open the content gets `inert`, and Escape closes the panel - unless something
60
+ opened above the shell (a dialog, menu or popover) already handled it.
61
+ - Opening the overlay moves focus into the panel (its first focusable element, or the `<nav>`
62
+ itself); closing it returns focus to where it came from - usually the menu button - unless the user
62
63
  has already moved it elsewhere. An overlay that is open when the page loads does not take focus.
@@ -1,9 +1,9 @@
1
- /** Tryb ekranu — logowanie, rejestracja, odzyskiwanie hasła. */
1
+ /** Tryb ekranu - logowanie, rejestracja, odzyskiwanie hasła. */
2
2
  export type KptAuthMode = 'signIn' | 'signUp' | 'forgot';
3
3
  /**
4
4
  * Układ ekranu:
5
- * - `slider` — panel promo przesuwa się nad formularzami przy zmianie trybu,
6
- * - `split` — panel promo stoi w miejscu, zmienia się tylko formularz.
5
+ * - `slider` - panel promo przesuwa się nad formularzami przy zmianie trybu,
6
+ * - `split` - panel promo stoi w miejscu, zmienia się tylko formularz.
7
7
  */
8
8
  export type KptAuthLayout = 'slider' | 'split';
9
9
  /** Układ przycisków dostawców: pełnowymiarowa lista albo siatka ikon z podpisami. */
@@ -12,13 +12,13 @@ export type KptAuthProviderLayout = 'list' | 'grid';
12
12
  export interface KptAuthProvider {
13
13
  /** Identyfikator zwracany w `onProviderSelect`. */
14
14
  id: string;
15
- /** Widoczna etykieta — jednocześnie nazwa dostępna przycisku. */
15
+ /** Widoczna etykieta - jednocześnie nazwa dostępna przycisku. */
16
16
  label: string;
17
17
  /** Nazwa ikony z rejestru `KptIcon` (np. `brand-google` z pełnego zestawu Tabler). */
18
18
  icon?: string;
19
19
  /** Alternatywa dla `icon`: adres obrazka (wierne, wielokolorowe logo marki). */
20
20
  iconUrl?: string;
21
- /** Drugi wiersz opisu — tylko w układzie `list`. */
21
+ /** Drugi wiersz opisu - tylko w układzie `list`. */
22
22
  description?: string;
23
23
  }
24
24
  /** Wartość formularza logowania. */
@@ -38,7 +38,7 @@ export interface KptAuthSignUpValue {
38
38
  export interface KptAuthResetValue {
39
39
  email: string;
40
40
  }
41
- /** Rodzaj błędu pola — komunikat składamy z niego dopiero przy renderowaniu. */
41
+ /** Rodzaj błędu pola - komunikat składamy z niego dopiero przy renderowaniu. */
42
42
  export type KptAuthErrorKind = 'required' | 'email' | 'minLength' | 'mismatch';
43
43
  /** Minimalna długość hasła w rejestracji. */
44
44
  export declare const KPT_AUTH_MIN_PASSWORD = 8;
@@ -15,7 +15,7 @@ export interface KptAuthProps extends Omit<ComponentPropsWithRef<'div'>, 'onSubm
15
15
  showName?: boolean;
16
16
  requireTerms?: boolean;
17
17
  showRemember?: boolean;
18
- /** Operacja w toku — przyciski w stanie ładowania, dostawcy zablokowani. */
18
+ /** Operacja w toku - przyciski w stanie ładowania, dostawcy zablokowani. */
19
19
  busy?: boolean;
20
20
  error?: string | null;
21
21
  notice?: string | null;
@@ -36,7 +36,7 @@ export interface KptAuthProps extends Omit<ComponentPropsWithRef<'div'>, 'onSubm
36
36
  * Ekran uwierzytelniania: logowanie, rejestracja i odzyskiwanie hasła w jednym komponencie,
37
37
  * z panelem promocyjnym i listą dostawców zewnętrznych.
38
38
  *
39
- * Komponent jest prezentacyjny — nie woła API ani nie nawiguje. Wywołania backendu podpina
39
+ * Komponent jest prezentacyjny - nie woła API ani nie nawiguje. Wywołania backendu podpina
40
40
  * aplikacja pod `onSignIn` / `onSignUp` / `onResetPassword` / `onProviderSelect`, a stan
41
41
  * operacji podaje z powrotem przez `busy`, `error` i `notice`.
42
42
  *
package/dist/auth/auth.js CHANGED
@@ -1,6 +1,8 @@
1
+ 'use client';
1
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Children, Fragment, isValidElement, useId, useRef, useState, } from 'react';
3
+ import { Fragment, isValidElement, useId, useRef, useState, } from 'react';
3
4
  import { cn } from "../internal/cn.js";
5
+ import { slotChildren } from "../internal/slot-children.js";
4
6
  import { useControllableState } from "../internal/use-controllable-state.js";
5
7
  import { useKptMessages } from "../i18n/i18n-context.js";
6
8
  import { KptAlert } from "../alert/alert.js";
@@ -27,7 +29,7 @@ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
27
29
  * Ekran uwierzytelniania: logowanie, rejestracja i odzyskiwanie hasła w jednym komponencie,
28
30
  * z panelem promocyjnym i listą dostawców zewnętrznych.
29
31
  *
30
- * Komponent jest prezentacyjny — nie woła API ani nie nawiguje. Wywołania backendu podpina
32
+ * Komponent jest prezentacyjny - nie woła API ani nie nawiguje. Wywołania backendu podpina
31
33
  * aplikacja pod `onSignIn` / `onSignUp` / `onResetPassword` / `onProviderSelect`, a stan
32
34
  * operacji podaje z powrotem przez `busy`, `error` i `notice`.
33
35
  *
@@ -57,16 +59,16 @@ export function KptAuth({ mode, defaultMode = 'signIn', onModeChange, layout = '
57
59
  resetEmail: `${uid}-reset-email`,
58
60
  };
59
61
  const headingRef = useRef(null);
60
- // ── Sloty ──
62
+ // -- Sloty --
61
63
  const slots = {};
62
- Children.forEach(children, (child) => {
64
+ for (const child of slotChildren(children)) {
63
65
  if (!isValidElement(child))
64
- return;
66
+ continue;
65
67
  const name = child.type?.kptAuthSlot;
66
68
  if (name)
67
69
  slots[name] = child.props.children;
68
- });
69
- // ── Modele formularzy ──
70
+ }
71
+ // -- Modele formularzy --
70
72
  const [signInModel, setSignInModel] = useState({
71
73
  email: '',
72
74
  password: '',
@@ -83,9 +85,9 @@ export function KptAuth({ mode, defaultMode = 'signIn', onModeChange, layout = '
83
85
  const [touched, setTouched] = useState(new Set());
84
86
  const touch = (field) => setTouched((prev) => new Set(prev).add(field));
85
87
  /*
86
- * Walidacja jest bezwarunkowa i zwraca sam `kind` — komunikat składamy dopiero przy
88
+ * Walidacja jest bezwarunkowa i zwraca sam `kind` - komunikat składamy dopiero przy
87
89
  * renderowaniu, dzięki czemu zmiana języka w runtime przerysowuje błędy. Bramka
88
- * „nie strasz czerwienią świeżego pola" (`touched`) żyje w prezentacji, nie w walidatorze,
90
+ * "nie strasz czerwienią świeżego pola" (`touched`) żyje w prezentacji, nie w walidatorze,
89
91
  * więc `invalid` mówi prawdę także wtedy, gdy pola nikt jeszcze nie dotknął.
90
92
  */
91
93
  const signInErrors = {
@@ -100,7 +102,7 @@ export function KptAuth({ mode, defaultMode = 'signIn', onModeChange, layout = '
100
102
  : signUpModel.password.length < KPT_AUTH_MIN_PASSWORD
101
103
  ? 'minLength'
102
104
  : null,
103
- // Puste „powtórz hasło" nie jest jeszcze niezgodnością — dopiero wpisana, inna wartość.
105
+ // Puste "powtórz hasło" nie jest jeszcze niezgodnością - dopiero wpisana, inna wartość.
104
106
  confirm: signUpModel.confirm && signUpModel.confirm !== signUpModel.password ? 'mismatch' : null,
105
107
  terms: requireTerms && !signUpModel.terms ? 'required' : null,
106
108
  };
@@ -124,8 +126,9 @@ export function KptAuth({ mode, defaultMode = 'signIn', onModeChange, layout = '
124
126
  const errorFor = (form, field, kinds) => touched.has(`${form}.${field}`) ? message(kinds[field] ?? null) : null;
125
127
  const anyError = (kinds) => Object.values(kinds).some((kind) => kind !== null);
126
128
  const submitAll = (form, fields) => {
127
- // Submit dotyka całego formularza — inaczej pola, których użytkownik nie ruszył, nie
128
- // pokazałyby błędu i przycisk wyglądałby na zepsuty.
129
+ // Submit dotyka całego formularza - inaczej pola, których użytkownik nie ruszył, nie
130
+ // pokazałyby błędu. Dlatego przycisk wysyłki nie jest wyłączany przy błędach: pokazuje,
131
+ // czego brakuje, zamiast stać martwy (WCAG 3.3.1).
129
132
  setTouched((prev) => {
130
133
  const next = new Set(prev);
131
134
  for (const field of fields)
@@ -152,22 +155,28 @@ export function KptAuth({ mode, defaultMode = 'signIn', onModeChange, layout = '
152
155
  const promoBody = promoText === null ? t(`auth.promo.${promoMode}Text`) : promoText;
153
156
  return (_jsx("div", { className: cn('kpt-auth-host', className), "data-layout": layout, "data-mode": activeMode, style: { ['--kpt-anim-duration']: `${animated ? animationDuration : 0}ms`, ...style }, ...rest, children: _jsx("div", { className: "kpt-auth", children: _jsxs("div", { className: "kpt-auth__card", children: [_jsx("div", { className: "kpt-auth__form-side", children: _jsxs("div", { className: "kpt-auth__inner", "data-mode": activeMode, children: [_jsx("div", { className: "kpt-auth__brand", children: slots.brand }), _jsx("h2", { ref: headingRef, className: "kpt-auth__title", id: ids[activeMode], "data-mode": activeMode, tabIndex: -1, children: t(`auth.${activeMode}Title`) }), _jsx("p", { className: "kpt-auth__subtitle", children: t(`auth.${activeMode}Subtitle`) }), error ? _jsx(KptAlert, { variant: "danger", children: error }) : null, notice ? _jsx(KptAlert, { variant: "success", children: notice }) : null, activeMode === 'signIn' ? (_jsxs("form", { className: "kpt-auth__form", "aria-labelledby": ids.signIn, onSubmit: (event) => {
154
157
  event.preventDefault();
158
+ if (busy)
159
+ return;
155
160
  submitAll('signIn', ['email', 'password']);
156
161
  if (!anyError(signInErrors))
157
162
  onSignIn?.({ ...signInModel });
158
- }, children: [_jsx(KptFormField, { label: t('auth.email'), error: errorFor('signIn', 'email', signInErrors), required: true, controlId: ids.email, children: _jsx(KptInput, { type: "email", autoComplete: "email", id: ids.email, placeholder: t('auth.emailPlaceholder'), value: signInModel.email, onValueChange: (email) => setSignInModel({ ...signInModel, email }), onTouch: () => touch('signIn.email') }) }), _jsx(KptFormField, { label: t('auth.password'), error: errorFor('signIn', 'password', signInErrors), required: true, controlId: ids.password, children: _jsx(KptPassword, { autoComplete: "current-password", id: ids.password, value: signInModel.password, onValueChange: (password) => setSignInModel({ ...signInModel, password }), onTouch: () => touch('signIn.password') }) }), slots.fields, _jsxs("div", { className: "kpt-auth__row", children: [showRemember ? (_jsx(KptCheckbox, { label: t('auth.remember'), checked: signInModel.remember, onCheckedChange: (remember) => setSignInModel({ ...signInModel, remember }) })) : (_jsx("span", {})), _jsx("button", { type: "button", className: "kpt-auth__link", onClick: () => changeMode('forgot'), children: t('auth.forgotLink') })] }), _jsx(KptButton, { type: "submit", fullWidth: true, loading: busy, disabled: anyError(signInErrors), children: t('auth.signInSubmit') })] })) : null, activeMode === 'signUp' ? (_jsxs("form", { className: "kpt-auth__form", "aria-labelledby": ids.signUp, onSubmit: (event) => {
163
+ }, children: [_jsx(KptFormField, { label: t('auth.email'), error: errorFor('signIn', 'email', signInErrors), required: true, controlId: ids.email, children: _jsx(KptInput, { type: "email", autoComplete: "email", id: ids.email, placeholder: t('auth.emailPlaceholder'), value: signInModel.email, onValueChange: (email) => setSignInModel({ ...signInModel, email }), onTouch: () => touch('signIn.email') }) }), _jsx(KptFormField, { label: t('auth.password'), error: errorFor('signIn', 'password', signInErrors), required: true, controlId: ids.password, children: _jsx(KptPassword, { autoComplete: "current-password", id: ids.password, value: signInModel.password, onValueChange: (password) => setSignInModel({ ...signInModel, password }), onTouch: () => touch('signIn.password') }) }), slots.fields, _jsxs("div", { className: "kpt-auth__row", children: [showRemember ? (_jsx(KptCheckbox, { label: t('auth.remember'), checked: signInModel.remember, onCheckedChange: (remember) => setSignInModel({ ...signInModel, remember }) })) : (_jsx("span", {})), _jsx("button", { type: "button", className: "kpt-auth__link", onClick: () => changeMode('forgot'), children: t('auth.forgotLink') })] }), _jsx(KptButton, { type: "submit", fullWidth: true, loading: busy, children: t('auth.signInSubmit') })] })) : null, activeMode === 'signUp' ? (_jsxs("form", { className: "kpt-auth__form", "aria-labelledby": ids.signUp, onSubmit: (event) => {
159
164
  event.preventDefault();
165
+ if (busy)
166
+ return;
160
167
  submitAll('signUp', ['name', 'email', 'password', 'confirm', 'terms']);
161
168
  if (!anyError(signUpErrors)) {
162
169
  const { name, email, password, terms } = signUpModel;
163
170
  onSignUp?.({ name, email, password, terms });
164
171
  }
165
- }, children: [showName ? (_jsx(KptFormField, { label: t('auth.name'), error: errorFor('signUp', 'name', signUpErrors), required: true, controlId: ids.name, children: _jsx(KptInput, { autoComplete: "name", id: ids.name, value: signUpModel.name, onValueChange: (name) => setSignUpModel({ ...signUpModel, name }), onTouch: () => touch('signUp.name') }) })) : null, _jsx(KptFormField, { label: t('auth.email'), error: errorFor('signUp', 'email', signUpErrors), required: true, controlId: ids.regEmail, children: _jsx(KptInput, { type: "email", autoComplete: "email", id: ids.regEmail, placeholder: t('auth.emailPlaceholder'), value: signUpModel.email, onValueChange: (email) => setSignUpModel({ ...signUpModel, email }), onTouch: () => touch('signUp.email') }) }), _jsx(KptFormField, { label: t('auth.password'), error: errorFor('signUp', 'password', signUpErrors), hint: t('auth.passwordHint', { min: KPT_AUTH_MIN_PASSWORD }), required: true, controlId: ids.regPassword, children: _jsx(KptPassword, { autoComplete: "new-password", feedback: true, id: ids.regPassword, value: signUpModel.password, onValueChange: (password) => setSignUpModel({ ...signUpModel, password }), onTouch: () => touch('signUp.password') }) }), _jsx(KptFormField, { label: t('auth.confirmPassword'), error: errorFor('signUp', 'confirm', signUpErrors), required: true, controlId: ids.regConfirm, children: _jsx(KptPassword, { autoComplete: "new-password", id: ids.regConfirm, value: signUpModel.confirm, onValueChange: (confirm) => setSignUpModel({ ...signUpModel, confirm }), onTouch: () => touch('signUp.confirm') }) }), slots.fields, requireTerms ? (_jsx(KptFormField, { error: errorFor('signUp', 'terms', signUpErrors), children: _jsx(KptCheckbox, { label: t('auth.terms'), checked: signUpModel.terms, onCheckedChange: (terms) => setSignUpModel({ ...signUpModel, terms }), onTouch: () => touch('signUp.terms') }) })) : null, _jsx(KptButton, { type: "submit", fullWidth: true, loading: busy, disabled: anyError(signUpErrors), children: t('auth.signUpSubmit') })] })) : null, activeMode === 'forgot' ? (_jsxs("form", { className: "kpt-auth__form", "aria-labelledby": ids.forgot, onSubmit: (event) => {
172
+ }, children: [showName ? (_jsx(KptFormField, { label: t('auth.name'), error: errorFor('signUp', 'name', signUpErrors), required: true, controlId: ids.name, children: _jsx(KptInput, { autoComplete: "name", id: ids.name, value: signUpModel.name, onValueChange: (name) => setSignUpModel({ ...signUpModel, name }), onTouch: () => touch('signUp.name') }) })) : null, _jsx(KptFormField, { label: t('auth.email'), error: errorFor('signUp', 'email', signUpErrors), required: true, controlId: ids.regEmail, children: _jsx(KptInput, { type: "email", autoComplete: "email", id: ids.regEmail, placeholder: t('auth.emailPlaceholder'), value: signUpModel.email, onValueChange: (email) => setSignUpModel({ ...signUpModel, email }), onTouch: () => touch('signUp.email') }) }), _jsx(KptFormField, { label: t('auth.password'), error: errorFor('signUp', 'password', signUpErrors), hint: t('auth.passwordHint', { min: KPT_AUTH_MIN_PASSWORD }), required: true, controlId: ids.regPassword, children: _jsx(KptPassword, { autoComplete: "new-password", feedback: true, id: ids.regPassword, value: signUpModel.password, onValueChange: (password) => setSignUpModel({ ...signUpModel, password }), onTouch: () => touch('signUp.password') }) }), _jsx(KptFormField, { label: t('auth.confirmPassword'), error: errorFor('signUp', 'confirm', signUpErrors), required: true, controlId: ids.regConfirm, children: _jsx(KptPassword, { autoComplete: "new-password", id: ids.regConfirm, value: signUpModel.confirm, onValueChange: (confirm) => setSignUpModel({ ...signUpModel, confirm }), onTouch: () => touch('signUp.confirm') }) }), slots.fields, requireTerms ? (_jsx(KptFormField, { error: errorFor('signUp', 'terms', signUpErrors), children: _jsx(KptCheckbox, { label: t('auth.terms'), checked: signUpModel.terms, onCheckedChange: (terms) => setSignUpModel({ ...signUpModel, terms }), onTouch: () => touch('signUp.terms') }) })) : null, _jsx(KptButton, { type: "submit", fullWidth: true, loading: busy, children: t('auth.signUpSubmit') })] })) : null, activeMode === 'forgot' ? (_jsxs("form", { className: "kpt-auth__form", "aria-labelledby": ids.forgot, onSubmit: (event) => {
166
173
  event.preventDefault();
174
+ if (busy)
175
+ return;
167
176
  submitAll('forgot', ['email']);
168
177
  if (!anyError(resetErrors))
169
178
  onResetPassword?.({ ...resetModel });
170
- }, children: [_jsx(KptFormField, { label: t('auth.email'), error: errorFor('forgot', 'email', resetErrors), required: true, controlId: ids.resetEmail, children: _jsx(KptInput, { type: "email", autoComplete: "email", id: ids.resetEmail, placeholder: t('auth.emailPlaceholder'), value: resetModel.email, onValueChange: (email) => setResetModel({ email }), onTouch: () => touch('forgot.email') }) }), _jsx(KptButton, { type: "submit", fullWidth: true, loading: busy, disabled: anyError(resetErrors), children: t('auth.resetSubmit') }), _jsx("button", { type: "button", className: "kpt-auth__link kpt-auth__link--center", onClick: () => changeMode('signIn'), children: t('auth.backToSignIn') })] })) : null, activeMode !== 'forgot' ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "kpt-auth__sso", children: slots.sso }), providers.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "kpt-auth__separator", role: "separator", "aria-label": t('auth.orContinueWith'), children: _jsx("span", { className: "kpt-auth__separator-text", children: t('auth.orContinueWith') }) }), _jsx("div", { className: "kpt-auth__providers", "data-layout": providerLayout, children: providers.map((provider) => {
179
+ }, children: [_jsx(KptFormField, { label: t('auth.email'), error: errorFor('forgot', 'email', resetErrors), required: true, controlId: ids.resetEmail, children: _jsx(KptInput, { type: "email", autoComplete: "email", id: ids.resetEmail, placeholder: t('auth.emailPlaceholder'), value: resetModel.email, onValueChange: (email) => setResetModel({ email }), onTouch: () => touch('forgot.email') }) }), _jsx(KptButton, { type: "submit", fullWidth: true, loading: busy, children: t('auth.resetSubmit') }), _jsx("button", { type: "button", className: "kpt-auth__link kpt-auth__link--center", onClick: () => changeMode('signIn'), children: t('auth.backToSignIn') })] })) : null, activeMode !== 'forgot' ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "kpt-auth__sso", children: slots.sso }), providers.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "kpt-auth__separator", role: "separator", "aria-label": t('auth.orContinueWith'), children: _jsx("span", { className: "kpt-auth__separator-text", children: t('auth.orContinueWith') }) }), _jsx("div", { className: "kpt-auth__providers", "data-layout": providerLayout, children: providers.map((provider) => {
171
180
  const custom = renderProvider?.(provider, () => selectProvider(provider));
172
181
  // Fragment, nie `<span>`: lista dostawców to grid, więc dodatkowy
173
182
  // element stałby się jej dzieckiem i własny przycisk przestałby
@@ -4,35 +4,36 @@ An authentication screen: sign in, sign up and password recovery in one componen
4
4
  panel and a list of external providers.
5
5
  Import: `import { KptAuth, type KptAuthProvider } from '@konce-pt/react';`
6
6
 
7
- The component is **presentational** — it calls no API and does not navigate; the app does that in
7
+ The component is **presentational** - it calls no API and does not navigate; the app does that in
8
8
  the handlers.
9
9
 
10
10
  ## Props
11
- - `mode` / `defaultMode` / `onModeChange` — `'signIn' | 'signUp' | 'forgot'`
12
- - `layout`: `'slider'` (default) | `'split'` — the promo panel slides to the other side, or stays put
13
- - `providers`: `KptAuthProvider[]` — `{ id, label, icon?, iconUrl?, description? }`
11
+ - `mode` / `defaultMode` / `onModeChange` - `'signIn' | 'signUp' | 'forgot'`
12
+ - `layout`: `'slider'` (default) | `'split'` - the promo panel slides to the other side, or stays put
13
+ - `providers`: `KptAuthProvider[]` - `{ id, label, icon?, iconUrl?, description? }`
14
14
  - `providerLayout`: `'list'` (default) | `'grid'`
15
15
  - `showName`, `requireTerms`, `showRemember`: boolean (default true)
16
- - `busy`: boolean — the buttons show a loading state, providers are blocked
17
- - `error` / `notice`: string | null — a server message (a `danger` / `success` alert)
16
+ - `busy`: boolean - the buttons show a loading state, providers are blocked
17
+ - `error` / `notice`: string | null - a server message (a `danger` / `success` alert)
18
18
  - `promoTitle` / `promoText`: `null` = mode-dependent text from i18n, `''` = hidden
19
19
  - `animated` (true), `animationDuration` (320 ms)
20
20
  - `onSignIn`, `onSignUp`, `onResetPassword`, `onProviderSelect`
21
- - `renderProvider(provider, select)` — custom markup for one provider; return `null` for the rest
21
+ - `renderProvider(provider, select)` - custom markup for one provider; return `null` for the rest
22
22
 
23
23
  ## Slots
24
- `KptAuth.Brand`, `KptAuth.Promo`, `KptAuth.Sso`, `KptAuth.Fields`, `KptAuth.Footer` — the
24
+ `KptAuth.Brand`, `KptAuth.Promo`, `KptAuth.Sso`, `KptAuth.Fields`, `KptAuth.Footer` - the
25
25
  equivalents of the `[kptAuthBrand]`, `[kptAuthPromo]`, `[kptAuthSso]`, `[kptAuthFields]` and
26
26
  `[kptAuthFooter]` projections. **Fields from the `Fields` slot are not part of the component's
27
- model** — bind them to your own state and read them in the handler.
27
+ model** - bind them to your own state and read them in the handler.
28
28
 
29
29
  ## Validation without a form library
30
30
  Three independent forms, one per mode, validated on every render: e-mail required and valid,
31
31
  password required (sign up: at least 8 characters), the confirmation matching, consent required
32
32
  when `requireTerms`. The validator returns a `kind`, and the message is composed at render time,
33
33
  so **changing the language repaints the errors**. The "do not shout at an untouched field" gate
34
- lives in the presentation, so the submit button's disabled state tells the truth from the start;
35
- submitting marks the whole form as touched.
34
+ lives in the presentation. The submit button is **not** disabled while the form is invalid:
35
+ submitting marks the whole form as touched and shows what is missing (WCAG 3.3.1), and `onSignIn` /
36
+ `onSignUp` / `onResetPassword` fire only for a valid form.
36
37
 
37
38
  ## The heading takes focus after a mode change
38
39
  Without it a screen reader never announces the change, and focus stays on a button that has just
@@ -1,5 +1,7 @@
1
1
  import { type ComponentPropsWithRef } from 'react';
2
2
  import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
3
+ import type { KptSpeechMode } from '@konce-pt/speech';
4
+ import { type KptSpeechColor } from '../speech/speech-button.tsx';
3
5
  export interface KptAutocompleteProps extends Omit<ComponentPropsWithRef<'input'>, 'value' | 'defaultValue' | 'onChange'>, KptI18nOverrides {
4
6
  options?: readonly string[];
5
7
  value?: string;
@@ -8,16 +10,27 @@ export interface KptAutocompleteProps extends Omit<ComponentPropsWithRef<'input'
8
10
  invalid?: boolean;
9
11
  touched?: boolean;
10
12
  onTouch?: () => void;
13
+ /** Mikrofon w polu (Web Speech API). Bez wsparcia przeglądarki się nie pokazuje. */
14
+ speech?: boolean;
15
+ /** Język dyktowania (BCP 47); bez niego z `KptI18nProvider`. */
16
+ speechLang?: string;
17
+ /** Kolor "stop" i fali w trakcie nasłuchu; domyślnie kolor motywu. */
18
+ speechColor?: KptSpeechColor;
19
+ /**
20
+ * Domyślnie `replace`: podyktowana wartość zastępuje poprzednią, a nasłuch kończy się po jednej
21
+ * wypowiedzi - to pole wybiera jedną wartość, nie zbiera tekstu.
22
+ */
23
+ speechMode?: KptSpeechMode;
11
24
  }
12
25
  /**
13
- * Pole z podpowiedziami. Wartością jest wpisany tekst, nie wybrana opcja — podpowiedzi
26
+ * Pole z podpowiedziami. Wartością jest wpisany tekst, nie wybrana opcja - podpowiedzi
14
27
  * skracają pisanie, ale nie ograniczają wpisu, więc pole nadaje się też do wartości spoza listy.
15
28
  *
16
- * Wzorzec WAI-ARIA „combobox z listą”: fokus zostaje w polu, aktywną podpowiedź ogłasza
17
- * `aria-activedescendant`, a liczbę podpowiedzi (albo ich brak) — region `polite`. Dopasowanie
18
- * pomija wielkość liter i diakrytyki („lodz” znajduje „Łódź”).
29
+ * Wzorzec WAI-ARIA "combobox z listą": fokus zostaje w polu, aktywną podpowiedź ogłasza
30
+ * `aria-activedescendant`, a liczbę podpowiedzi (albo ich brak) - region `polite`. Dopasowanie
31
+ * pomija wielkość liter i diakrytyki ("lodz" znajduje "Łódź").
19
32
  *
20
33
  * @example
21
- * <KptAutocomplete options={cities} value={city} onValueChange={setCity} placeholder="Miasto…" />
34
+ * <KptAutocomplete options={cities} value={city} onValueChange={setCity} placeholder="Miasto..." />
22
35
  */
23
- export declare function KptAutocomplete({ options, value, defaultValue, onValueChange, invalid, touched, onTouch, disabled, className, onBlur, onFocus, onKeyDown, ref, id, 'aria-describedby': ariaDescribedBy, locale, dictionary, ...rest }: Readonly<KptAutocompleteProps>): import("react").JSX.Element;
36
+ export declare function KptAutocomplete({ options, value, defaultValue, onValueChange, invalid, touched, onTouch, disabled, readOnly, className, onBlur, onFocus, onKeyDown, ref, id, 'aria-describedby': ariaDescribedBy, locale, dictionary, speech, speechLang, speechColor, speechMode, ...rest }: Readonly<KptAutocompleteProps>): import("react").JSX.Element;