@konce-pt/react 0.8.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 (245) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +58 -0
  3. package/dist/accordion/accordion.d.ts +45 -0
  4. package/dist/accordion/accordion.js +69 -0
  5. package/dist/alert/alert.d.ts +25 -0
  6. package/dist/alert/alert.js +31 -0
  7. package/dist/app-shell/app-shell.d.ts +94 -0
  8. package/dist/app-shell/app-shell.js +105 -0
  9. package/dist/auth/auth-types.d.ts +44 -0
  10. package/dist/auth/auth-types.js +2 -0
  11. package/dist/auth/auth.d.ts +76 -0
  12. package/dist/auth/auth.js +184 -0
  13. package/dist/autocomplete/autocomplete.d.ts +18 -0
  14. package/dist/autocomplete/autocomplete.js +72 -0
  15. package/dist/avatar/avatar.d.ts +33 -0
  16. package/dist/avatar/avatar.js +30 -0
  17. package/dist/avatar-group/avatar-group.d.ts +21 -0
  18. package/dist/avatar-group/avatar-group.js +15 -0
  19. package/dist/badge/badge.d.ts +25 -0
  20. package/dist/badge/badge.js +14 -0
  21. package/dist/bottom-sheet/bottom-sheet.d.ts +21 -0
  22. package/dist/bottom-sheet/bottom-sheet.js +22 -0
  23. package/dist/breadcrumb/breadcrumb.d.ts +19 -0
  24. package/dist/breadcrumb/breadcrumb.js +20 -0
  25. package/dist/button/button.d.ts +27 -0
  26. package/dist/button/button.js +49 -0
  27. package/dist/button-group/button-group.d.ts +25 -0
  28. package/dist/button-group/button-group.js +30 -0
  29. package/dist/card/card.d.ts +66 -0
  30. package/dist/card/card.js +96 -0
  31. package/dist/carousel/carousel.d.ts +20 -0
  32. package/dist/carousel/carousel.js +24 -0
  33. package/dist/charts/chart-legend.d.ts +23 -0
  34. package/dist/charts/chart-legend.js +9 -0
  35. package/dist/charts/chart-tooltip.d.ts +21 -0
  36. package/dist/charts/chart-tooltip.js +13 -0
  37. package/dist/charts/chart.d.ts +18 -0
  38. package/dist/charts/chart.js +231 -0
  39. package/dist/charts-entry/public-api.d.ts +4 -0
  40. package/dist/charts-entry/public-api.js +7 -0
  41. package/dist/checkbox/checkbox.d.ts +33 -0
  42. package/dist/checkbox/checkbox.js +29 -0
  43. package/dist/chip/chip.d.ts +22 -0
  44. package/dist/chip/chip.js +16 -0
  45. package/dist/chips-input/chips-input.d.ts +25 -0
  46. package/dist/chips-input/chips-input.js +54 -0
  47. package/dist/clock/clock.d.ts +17 -0
  48. package/dist/clock/clock.js +57 -0
  49. package/dist/color-picker/color-picker.d.ts +23 -0
  50. package/dist/color-picker/color-picker.js +28 -0
  51. package/dist/confirm/confirm-container.d.ts +13 -0
  52. package/dist/confirm/confirm-container.js +26 -0
  53. package/dist/confirm/confirm-store.d.ts +29 -0
  54. package/dist/confirm/confirm-store.js +52 -0
  55. package/dist/context-menu/context-menu.d.ts +21 -0
  56. package/dist/context-menu/context-menu.js +36 -0
  57. package/dist/data-table/data-table-types.d.ts +67 -0
  58. package/dist/data-table/data-table-types.js +1 -0
  59. package/dist/data-table/data-table.d.ts +62 -0
  60. package/dist/data-table/data-table.js +453 -0
  61. package/dist/data-table/export-csv.d.ts +7 -0
  62. package/dist/data-table/export-csv.js +19 -0
  63. package/dist/data-view/data-view.d.ts +21 -0
  64. package/dist/data-view/data-view.js +25 -0
  65. package/dist/date-range/date-range.d.ts +30 -0
  66. package/dist/date-range/date-range.js +155 -0
  67. package/dist/datepicker/datepicker.d.ts +39 -0
  68. package/dist/datepicker/datepicker.js +202 -0
  69. package/dist/dialog/dialog.d.ts +35 -0
  70. package/dist/dialog/dialog.js +59 -0
  71. package/dist/divider/divider.d.ts +16 -0
  72. package/dist/divider/divider.js +13 -0
  73. package/dist/drawer/drawer.d.ts +25 -0
  74. package/dist/drawer/drawer.js +25 -0
  75. package/dist/empty/empty.d.ts +18 -0
  76. package/dist/empty/empty.js +14 -0
  77. package/dist/fab/fab.d.ts +22 -0
  78. package/dist/fab/fab.js +17 -0
  79. package/dist/fieldset/fieldset.d.ts +22 -0
  80. package/dist/fieldset/fieldset.js +24 -0
  81. package/dist/file-upload/file-upload.d.ts +22 -0
  82. package/dist/file-upload/file-upload.js +50 -0
  83. package/dist/form-field/form-field-context.d.ts +23 -0
  84. package/dist/form-field/form-field-context.js +17 -0
  85. package/dist/form-field/form-field.d.ts +39 -0
  86. package/dist/form-field/form-field.js +41 -0
  87. package/dist/galleria/galleria.d.ts +22 -0
  88. package/dist/galleria/galleria.js +21 -0
  89. package/dist/grid/col.d.ts +39 -0
  90. package/dist/grid/col.js +32 -0
  91. package/dist/grid/flex.d.ts +45 -0
  92. package/dist/grid/flex.js +35 -0
  93. package/dist/grid/grid.d.ts +47 -0
  94. package/dist/grid/grid.js +38 -0
  95. package/dist/grid/layout.d.ts +18 -0
  96. package/dist/grid/layout.js +32 -0
  97. package/dist/grid-entry/public-api.d.ts +6 -0
  98. package/dist/grid-entry/public-api.js +8 -0
  99. package/dist/i18n/i18n-context.d.ts +45 -0
  100. package/dist/i18n/i18n-context.js +65 -0
  101. package/dist/icon/icon-registry.d.ts +16 -0
  102. package/dist/icon/icon-registry.js +43 -0
  103. package/dist/icon/icon.d.ts +17 -0
  104. package/dist/icon/icon.js +23 -0
  105. package/dist/icon-button/icon-button.d.ts +23 -0
  106. package/dist/icon-button/icon-button.js +14 -0
  107. package/dist/icons-entry/public-api.d.ts +12 -0
  108. package/dist/icons-entry/public-api.js +20 -0
  109. package/dist/image/image.d.ts +17 -0
  110. package/dist/image/image.js +16 -0
  111. package/dist/input/input.d.ts +41 -0
  112. package/dist/input/input.js +36 -0
  113. package/dist/input-mask/input-mask.d.ts +19 -0
  114. package/dist/input-mask/input-mask.js +65 -0
  115. package/dist/input-number/input-number.d.ts +28 -0
  116. package/dist/input-number/input-number.js +52 -0
  117. package/dist/input-otp/input-otp.d.ts +21 -0
  118. package/dist/input-otp/input-otp.js +59 -0
  119. package/dist/internal/cn.d.ts +9 -0
  120. package/dist/internal/cn.js +19 -0
  121. package/dist/internal/compose-refs.d.ts +6 -0
  122. package/dist/internal/compose-refs.js +16 -0
  123. package/dist/internal/overlay-container.d.ts +3 -0
  124. package/dist/internal/overlay-container.js +19 -0
  125. package/dist/internal/overlay.d.ts +26 -0
  126. package/dist/internal/overlay.js +64 -0
  127. package/dist/internal/slot.d.ts +23 -0
  128. package/dist/internal/slot.js +49 -0
  129. package/dist/internal/types.d.ts +25 -0
  130. package/dist/internal/types.js +1 -0
  131. package/dist/internal/use-breakpoint.d.ts +18 -0
  132. package/dist/internal/use-breakpoint.js +52 -0
  133. package/dist/internal/use-controllable-state.d.ts +11 -0
  134. package/dist/internal/use-controllable-state.js +18 -0
  135. package/dist/internal/use-id.d.ts +9 -0
  136. package/dist/internal/use-id.js +13 -0
  137. package/dist/knob/knob.d.ts +27 -0
  138. package/dist/knob/knob.js +86 -0
  139. package/dist/listbox/listbox.d.ts +28 -0
  140. package/dist/listbox/listbox.js +43 -0
  141. package/dist/map/map-create-dialog.d.ts +21 -0
  142. package/dist/map/map-create-dialog.js +196 -0
  143. package/dist/map/map-hours-field.d.ts +22 -0
  144. package/dist/map/map-hours-field.js +90 -0
  145. package/dist/map/map-image-field.d.ts +24 -0
  146. package/dist/map/map-image-field.js +61 -0
  147. package/dist/map/map-legend.d.ts +29 -0
  148. package/dist/map/map-legend.js +41 -0
  149. package/dist/map/map-poi-card.d.ts +42 -0
  150. package/dist/map/map-poi-card.js +152 -0
  151. package/dist/map/map-search.d.ts +37 -0
  152. package/dist/map/map-search.js +201 -0
  153. package/dist/map/map.d.ts +113 -0
  154. package/dist/map/map.js +425 -0
  155. package/dist/map/ports.d.ts +76 -0
  156. package/dist/map/ports.js +174 -0
  157. package/dist/map-entry/public-api.d.ts +20 -0
  158. package/dist/map-entry/public-api.js +19 -0
  159. package/dist/megamenu/megamenu.d.ts +17 -0
  160. package/dist/megamenu/megamenu.js +28 -0
  161. package/dist/menu/menu-item.d.ts +33 -0
  162. package/dist/menu/menu-item.js +1 -0
  163. package/dist/menu/menu-rows.d.ts +9 -0
  164. package/dist/menu/menu-rows.js +15 -0
  165. package/dist/menu/menu.d.ts +22 -0
  166. package/dist/menu/menu.js +31 -0
  167. package/dist/menubar/menubar.d.ts +16 -0
  168. package/dist/menubar/menubar.js +39 -0
  169. package/dist/meter-group/meter-group.d.ts +20 -0
  170. package/dist/meter-group/meter-group.js +24 -0
  171. package/dist/order-list/order-list.d.ts +18 -0
  172. package/dist/order-list/order-list.js +37 -0
  173. package/dist/paginator/paginator.d.ts +29 -0
  174. package/dist/paginator/paginator.js +45 -0
  175. package/dist/panel/panel.d.ts +31 -0
  176. package/dist/panel/panel.js +36 -0
  177. package/dist/password/password.d.ts +28 -0
  178. package/dist/password/password.js +37 -0
  179. package/dist/pick-list/pick-list.d.ts +28 -0
  180. package/dist/pick-list/pick-list.js +65 -0
  181. package/dist/popover/popover.d.ts +23 -0
  182. package/dist/popover/popover.js +27 -0
  183. package/dist/progress/progress.d.ts +19 -0
  184. package/dist/progress/progress.js +21 -0
  185. package/dist/public-api.d.ts +181 -0
  186. package/dist/public-api.js +105 -0
  187. package/dist/radio-group/radio-group.d.ts +24 -0
  188. package/dist/radio-group/radio-group.js +23 -0
  189. package/dist/rating/rating.d.ts +22 -0
  190. package/dist/rating/rating.js +30 -0
  191. package/dist/rich-text/lists.d.ts +17 -0
  192. package/dist/rich-text/lists.js +144 -0
  193. package/dist/rich-text/rich-text.d.ts +28 -0
  194. package/dist/rich-text/rich-text.js +654 -0
  195. package/dist/rich-text/sanitize.d.ts +10 -0
  196. package/dist/rich-text/sanitize.js +85 -0
  197. package/dist/rich-text/tables.d.ts +44 -0
  198. package/dist/rich-text/tables.js +268 -0
  199. package/dist/roadmap/roadmap.d.ts +37 -0
  200. package/dist/roadmap/roadmap.js +271 -0
  201. package/dist/roadmap-entry/public-api.d.ts +4 -0
  202. package/dist/roadmap-entry/public-api.js +7 -0
  203. package/dist/scroll-top/scroll-top.d.ts +16 -0
  204. package/dist/scroll-top/scroll-top.js +38 -0
  205. package/dist/select/select.d.ts +37 -0
  206. package/dist/select/select.js +117 -0
  207. package/dist/shared/types.d.ts +8 -0
  208. package/dist/shared/types.js +1 -0
  209. package/dist/sidenav/sidenav.d.ts +26 -0
  210. package/dist/sidenav/sidenav.js +41 -0
  211. package/dist/skeleton/skeleton.d.ts +20 -0
  212. package/dist/skeleton/skeleton.js +15 -0
  213. package/dist/slider/slider.d.ts +28 -0
  214. package/dist/slider/slider.js +30 -0
  215. package/dist/speed-dial/speed-dial.d.ts +20 -0
  216. package/dist/speed-dial/speed-dial.js +23 -0
  217. package/dist/spinner/spinner.d.ts +15 -0
  218. package/dist/spinner/spinner.js +14 -0
  219. package/dist/split-button/split-button.d.ts +28 -0
  220. package/dist/split-button/split-button.js +34 -0
  221. package/dist/splitter/splitter.d.ts +39 -0
  222. package/dist/splitter/splitter.js +80 -0
  223. package/dist/stepper/stepper.d.ts +51 -0
  224. package/dist/stepper/stepper.js +71 -0
  225. package/dist/switch/switch.d.ts +39 -0
  226. package/dist/switch/switch.js +30 -0
  227. package/dist/switch-group/switch-group.d.ts +29 -0
  228. package/dist/switch-group/switch-group.js +47 -0
  229. package/dist/tabs/tabs.d.ts +38 -0
  230. package/dist/tabs/tabs.js +74 -0
  231. package/dist/textarea/textarea.d.ts +28 -0
  232. package/dist/textarea/textarea.js +44 -0
  233. package/dist/timeline/timeline.d.ts +19 -0
  234. package/dist/timeline/timeline.js +12 -0
  235. package/dist/toast/toast-container.d.ts +12 -0
  236. package/dist/toast/toast-container.js +23 -0
  237. package/dist/toast/toast-store.d.ts +26 -0
  238. package/dist/toast/toast-store.js +51 -0
  239. package/dist/toolbar/toolbar.d.ts +29 -0
  240. package/dist/toolbar/toolbar.js +24 -0
  241. package/dist/tooltip/tooltip.d.ts +26 -0
  242. package/dist/tooltip/tooltip.js +113 -0
  243. package/dist/tree/tree.d.ts +31 -0
  244. package/dist/tree/tree.js +62 -0
  245. package/package.json +91 -0
@@ -0,0 +1,24 @@
1
+ import type { ComponentPropsWithRef } from 'react';
2
+ import type { KptOption } from '../shared/types.ts';
3
+ export interface KptRadioGroupProps<T> extends Omit<ComponentPropsWithRef<'div'>, 'onChange' | 'defaultValue'> {
4
+ options?: KptOption<T>[];
5
+ value?: T;
6
+ defaultValue?: T;
7
+ onValueChange?: (value: T) => void;
8
+ /** Nazwa grupy w formularzu; pominięta = generowana. */
9
+ name?: string;
10
+ disabled?: boolean;
11
+ invalid?: boolean;
12
+ touched?: boolean;
13
+ onTouch?: () => void;
14
+ }
15
+ /**
16
+ * Grupa przycisków opcji (radio). Opcje przez `options`.
17
+ *
18
+ * Wszystkie pola dzielą jedną nazwę `name` — to ona, a nie kod komponentu, sprawia, że
19
+ * przeglądarka traktuje je jako jedną grupę i pozwala chodzić po niej strzałkami.
20
+ *
21
+ * @example
22
+ * <KptRadioGroup options={plans} value={plan} onValueChange={setPlan} />
23
+ */
24
+ export declare function KptRadioGroup<T>({ options, value, defaultValue, onValueChange, name, disabled, invalid, touched, onTouch, className, ...rest }: Readonly<KptRadioGroupProps<T>>): import("react").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../internal/cn.js";
3
+ import { useControllableState } from "../internal/use-controllable-state.js";
4
+ import { useKptId } from "../internal/use-id.js";
5
+ /**
6
+ * Grupa przycisków opcji (radio). Opcje przez `options`.
7
+ *
8
+ * Wszystkie pola dzielą jedną nazwę `name` — to ona, a nie kod komponentu, sprawia, że
9
+ * przeglądarka traktuje je jako jedną grupę i pozwala chodzić po niej strzałkami.
10
+ *
11
+ * @example
12
+ * <KptRadioGroup options={plans} value={plan} onValueChange={setPlan} />
13
+ */
14
+ export function KptRadioGroup({ options = [], value, defaultValue, onValueChange, name, disabled = false, invalid = false, touched, onTouch, className, ...rest }) {
15
+ const groupName = useKptId(name, 'kpt-radio');
16
+ const [current, setCurrent] = useControllableState({
17
+ value,
18
+ defaultValue,
19
+ onChange: onValueChange,
20
+ });
21
+ const showInvalid = invalid && (touched ?? true);
22
+ return (_jsx("div", { className: cn('kpt-radio-group-host', className), ...rest, children: _jsx("div", { className: "kpt-radio-group", role: "radiogroup", "aria-invalid": showInvalid || undefined, children: options.map((option) => (_jsxs("label", { className: cn('kpt-radio', (disabled || option.disabled) && 'kpt-radio--disabled'), children: [_jsx("input", { type: "radio", className: "kpt-radio__input", name: groupName, checked: option.value === current, disabled: disabled || option.disabled, onChange: () => setCurrent(option.value), onBlur: () => onTouch?.() }), _jsx("span", { className: "kpt-radio__dot", "aria-hidden": "true" }), _jsx("span", { className: "kpt-radio__label", children: option.label })] }, String(option.value)))) }) }));
23
+ }
@@ -0,0 +1,22 @@
1
+ import { type ComponentPropsWithRef } from 'react';
2
+ import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
3
+ export interface KptRatingProps extends Omit<ComponentPropsWithRef<'div'>, 'onChange' | 'defaultValue'>, KptI18nOverrides {
4
+ value?: number;
5
+ defaultValue?: number;
6
+ onValueChange?: (value: number) => void;
7
+ /** Liczba gwiazdek. */
8
+ count?: number;
9
+ /** Ocena tylko do odczytu — bez klikania i bez podglądu pod kursorem. */
10
+ readOnly?: boolean;
11
+ disabled?: boolean;
12
+ onTouch?: () => void;
13
+ }
14
+ /**
15
+ * Ocena gwiazdkami. Kliknięcie zapalonej gwiazdki zeruje ocenę, więc wystawioną można cofnąć
16
+ * bez osobnego przycisku „wyczyść".
17
+ *
18
+ * @example
19
+ * <KptRating value={score} onValueChange={setScore} count={5} />
20
+ * <KptRating value={4} readOnly />
21
+ */
22
+ export declare function KptRating({ value, defaultValue, onValueChange, count, readOnly, disabled, onTouch, locale, dictionary, className, ...rest }: Readonly<KptRatingProps>): import("react").JSX.Element;
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { cn } from "../internal/cn.js";
4
+ import { useControllableState } from "../internal/use-controllable-state.js";
5
+ import { useKptMessages } from "../i18n/i18n-context.js";
6
+ import { KptIcon } from "../icon/icon.js";
7
+ /**
8
+ * Ocena gwiazdkami. Kliknięcie zapalonej gwiazdki zeruje ocenę, więc wystawioną można cofnąć
9
+ * bez osobnego przycisku „wyczyść".
10
+ *
11
+ * @example
12
+ * <KptRating value={score} onValueChange={setScore} count={5} />
13
+ * <KptRating value={4} readOnly />
14
+ */
15
+ export function KptRating({ value, defaultValue = 0, onValueChange, count = 5, readOnly = false, disabled = false, onTouch, locale, dictionary, className, ...rest }) {
16
+ const { t } = useKptMessages({ locale, dictionary });
17
+ const [current, setCurrent] = useControllableState({ value, defaultValue, onChange: onValueChange });
18
+ const [hover, setHover] = useState(0);
19
+ const locked = readOnly || disabled;
20
+ // Podgląd pod kursorem wygrywa z oceną, ale tylko dopóki kursor jest nad gwiazdkami —
21
+ // po `mouseleave` wraca 0 i zapalona zostaje sama wartość.
22
+ const shown = hover || current;
23
+ const pick = (star) => {
24
+ if (locked)
25
+ return;
26
+ setCurrent(current === star ? 0 : star);
27
+ onTouch?.();
28
+ };
29
+ return (_jsx("div", { className: cn('kpt-rating-host', className), ...rest, children: _jsx("div", { className: "kpt-rating", role: "slider", "aria-valuenow": current, "aria-valuemax": count, children: Array.from({ length: count }, (_, index) => index + 1).map((star) => (_jsx("button", { type: "button", className: cn('kpt-rating__star', star <= shown && 'is-filled'), disabled: locked, onClick: () => pick(star), onMouseEnter: () => setHover(star), onMouseLeave: () => setHover(0), "aria-label": t('rating.star', { value: star, max: count }), children: _jsx(KptIcon, { name: "star" }) }, star))) }) }));
30
+ }
@@ -0,0 +1,17 @@
1
+ /** Najbliższy punkt listy zawierający węzeł, ale tylko wewnątrz edytora. */
2
+ export declare function closestItem(editor: HTMLElement | null, node: Node | null): HTMLLIElement | null;
3
+ /** Poziom punktu w obrębie edytora (1 = najwyższy). */
4
+ export declare function level(editor: HTMLElement | null, li: HTMLLIElement): number;
5
+ export declare function canIndentItem(editor: HTMLElement | null, li: HTMLLIElement, maxLevel: number): boolean;
6
+ export declare function canOutdentItem(li: HTMLLIElement): boolean;
7
+ /**
8
+ * Punkty listy objęte zaznaczeniem. Przy wielu punktach operujemy na ich wspólnym poziomie
9
+ * zagnieżdżenia — inaczej podpunkt dostałby wcięcie dwa razy: raz sam, raz z rodzicem.
10
+ */
11
+ export declare function selectedItems(editor: HTMLElement | null): HTMLLIElement[];
12
+ /**
13
+ * Przesuwa zaznaczone punkty o poziom. Zwraca `true`, gdy DOM faktycznie się zmienił — od tego
14
+ * zależy, czy Tab dostanie `preventDefault()`, a więc czy edytor nie stanie się pułapką
15
+ * klawiaturową (WCAG 2.1.2).
16
+ */
17
+ export declare function shiftItems(editor: HTMLElement | null, dir: 'indent' | 'outdent', maxLevel: number): boolean;
@@ -0,0 +1,144 @@
1
+ /*
2
+ * Wcięcia list. `execCommand('indent')` daje w Chrome nieprawidłowe `ul > ul` (albo `blockquote`
3
+ * z marginesem, który i tak zdjąłby sanitizer), więc zagnieżdżanie robimy własnym kodem DOM.
4
+ * Plik nie zna Reacta — to czyste operacje na węzłach.
5
+ */
6
+ /** Najbliższy punkt listy zawierający węzeł, ale tylko wewnątrz edytora. */
7
+ export function closestItem(editor, node) {
8
+ const el = node instanceof Element ? node : (node?.parentElement ?? null);
9
+ const li = el?.closest('li') ?? null;
10
+ return li instanceof HTMLLIElement && editor?.contains(li) ? li : null;
11
+ }
12
+ /** Poziom punktu w obrębie edytora (1 = najwyższy). */
13
+ export function level(editor, li) {
14
+ let depth = 1;
15
+ let parent = li.parentElement?.closest('li') ?? null;
16
+ while (parent && editor?.contains(parent)) {
17
+ depth++;
18
+ parent = parent.parentElement?.closest('li') ?? null;
19
+ }
20
+ return depth;
21
+ }
22
+ /** Najgłębszy poziom w poddrzewie punktu — wcięcie przenosi podpunkty razem z rodzicem. */
23
+ function deepest(editor, li) {
24
+ let max = level(editor, li);
25
+ for (const nested of li.querySelectorAll('li')) {
26
+ max = Math.max(max, level(editor, nested));
27
+ }
28
+ return max;
29
+ }
30
+ export function canIndentItem(editor, li, maxLevel) {
31
+ return li.previousElementSibling instanceof HTMLLIElement && deepest(editor, li) < maxLevel;
32
+ }
33
+ export function canOutdentItem(li) {
34
+ return li.parentElement?.parentElement instanceof HTMLLIElement;
35
+ }
36
+ /**
37
+ * Punkty listy objęte zaznaczeniem. Przy wielu punktach operujemy na ich wspólnym poziomie
38
+ * zagnieżdżenia — inaczej podpunkt dostałby wcięcie dwa razy: raz sam, raz z rodzicem.
39
+ */
40
+ export function selectedItems(editor) {
41
+ const selection = window.getSelection();
42
+ if (!editor || !selection || selection.rangeCount === 0)
43
+ return [];
44
+ const range = selection.getRangeAt(0);
45
+ if (!editor.contains(range.commonAncestorContainer))
46
+ return [];
47
+ const start = closestItem(editor, range.startContainer);
48
+ const end = closestItem(editor, range.endContainer);
49
+ if (!start)
50
+ return [];
51
+ if (!end || start === end)
52
+ return [start];
53
+ // Podnieś głębszy koniec, aż oba będą rodzeństwem w tej samej liście.
54
+ let a = start;
55
+ let b = end;
56
+ while (a && b && a.parentElement !== b.parentElement) {
57
+ if (level(editor, a) >= level(editor, b))
58
+ a = closestItem(editor, a.parentElement);
59
+ else
60
+ b = closestItem(editor, b.parentElement);
61
+ }
62
+ if (!a || !b || !a.parentElement)
63
+ return [start];
64
+ const siblings = [...a.parentElement.children].filter((el) => el instanceof HTMLLIElement);
65
+ const from = siblings.indexOf(a);
66
+ const to = siblings.indexOf(b);
67
+ if (from < 0 || to < 0)
68
+ return [start];
69
+ return siblings.slice(Math.min(from, to), Math.max(from, to) + 1);
70
+ }
71
+ /** Zagnieżdża punkt w podliście poprzedniego punktu — poprawne `li > ul > li`. */
72
+ function indentItem(editor, li, maxLevel) {
73
+ if (!canIndentItem(editor, li, maxLevel))
74
+ return false;
75
+ const prev = li.previousElementSibling;
76
+ let sub = prev.lastElementChild;
77
+ if (!(sub instanceof HTMLUListElement || sub instanceof HTMLOListElement)) {
78
+ // Ta sama numeracja co poziom wyżej.
79
+ sub = document.createElement(li.parentElement?.tagName ?? 'UL');
80
+ prev.append(sub);
81
+ }
82
+ sub.append(li);
83
+ return true;
84
+ }
85
+ /** Wyciąga punkt poziom wyżej; rodzeństwo po nim trafia do jego podlisty, więc kolejność zostaje. */
86
+ function outdentItem(li) {
87
+ const list = li.parentElement;
88
+ const host = list?.parentElement;
89
+ if (!list || !(host instanceof HTMLLIElement))
90
+ return false;
91
+ const children = [...list.children];
92
+ const after = children.slice(children.indexOf(li) + 1);
93
+ if (after.length > 0) {
94
+ let own = li.lastElementChild;
95
+ if (!(own instanceof HTMLUListElement || own instanceof HTMLOListElement)) {
96
+ own = document.createElement(list.tagName);
97
+ li.append(own);
98
+ }
99
+ own.append(...after);
100
+ }
101
+ host.after(li);
102
+ if (list.children.length === 0)
103
+ list.remove();
104
+ return true;
105
+ }
106
+ /**
107
+ * Przesuwa zaznaczone punkty o poziom. Zwraca `true`, gdy DOM faktycznie się zmienił — od tego
108
+ * zależy, czy Tab dostanie `preventDefault()`, a więc czy edytor nie stanie się pułapką
109
+ * klawiaturową (WCAG 2.1.2).
110
+ */
111
+ export function shiftItems(editor, dir, maxLevel) {
112
+ const items = selectedItems(editor);
113
+ if (items.length === 0)
114
+ return false;
115
+ // Migawka granic kursora: przy usunięciu węzła spec DOM przestawia *żywy* Range na starego
116
+ // rodzica, więc zapamiętanie samego zakresu wyprowadziłoby kursor poza przenoszony punkt.
117
+ const selection = window.getSelection();
118
+ const range = selection && selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
119
+ const caret = range
120
+ ? { sc: range.startContainer, so: range.startOffset, ec: range.endContainer, eo: range.endOffset }
121
+ : null;
122
+ // Outdent od końca — inaczej `host.after()` odwróciłby kolejność przenoszonych punktów.
123
+ const order = dir === 'outdent' ? [...items].reverse() : items;
124
+ let changed = false;
125
+ for (const li of order) {
126
+ const done = dir === 'indent' ? indentItem(editor, li, maxLevel) : outdentItem(li);
127
+ changed = done || changed;
128
+ }
129
+ if (!changed)
130
+ return false;
131
+ if (caret && selection && caret.sc.isConnected && caret.ec.isConnected) {
132
+ try {
133
+ const restored = document.createRange();
134
+ restored.setStart(caret.sc, caret.so);
135
+ restored.setEnd(caret.ec, caret.eo);
136
+ selection.removeAllRanges();
137
+ selection.addRange(restored);
138
+ }
139
+ catch {
140
+ /* offset przestał pasować po przeniesieniu rodzeństwa — zostaw kursor tam, gdzie jest */
141
+ }
142
+ }
143
+ return true;
144
+ }
@@ -0,0 +1,28 @@
1
+ import { type ComponentPropsWithRef } from 'react';
2
+ import { type KptI18nOverrides } from '../i18n/i18n-context.tsx';
3
+ export type KptRichTool = 'copy' | 'paste' | 'pasteText' | 'heading' | 'bold' | 'italic' | 'underline' | 'strike' | 'ul' | 'ol' | 'indent' | 'outdent' | 'foreColor' | 'backColor' | 'alignLeft' | 'alignCenter' | 'alignRight' | 'alignJustify' | 'link' | 'table' | 'clear' | 'html';
4
+ /** Pasek: płaska lista narzędzi albo grupy — sekcje rozdzielone separatorem. */
5
+ export type KptRichToolbar = KptRichTool[] | KptRichTool[][];
6
+ export interface KptRichTextProps extends Omit<ComponentPropsWithRef<'div'>, 'onChange' | 'children'>, KptI18nOverrides {
7
+ /** Wartość jako HTML. */
8
+ value?: string;
9
+ defaultValue?: string;
10
+ onValueChange?: (value: string) => void;
11
+ toolbar?: KptRichToolbar;
12
+ placeholder?: string;
13
+ /** Maksymalna głębokość zagnieżdżenia list (Tab, „Dodaj wcięcie"). */
14
+ maxListLevel?: number;
15
+ disabled?: boolean;
16
+ invalid?: boolean;
17
+ touched?: boolean;
18
+ onTouch?: () => void;
19
+ }
20
+ /**
21
+ * Lekki edytor tekstu sformatowanego na `contenteditable`, z konfigurowalnym paskiem sekcji
22
+ * i edycją tabel. Wartością jest HTML.
23
+ *
24
+ * @example
25
+ * <KptRichText value={html} onValueChange={setHtml} />
26
+ * <KptRichText value={html} onValueChange={setHtml} toolbar={[['bold', 'italic'], ['link']]} />
27
+ */
28
+ export declare function KptRichText({ value, defaultValue, onValueChange, toolbar, placeholder, maxListLevel, disabled, invalid, touched, onTouch, locale, dictionary, className, ...rest }: Readonly<KptRichTextProps>): import("react").JSX.Element;