@konce-pt/react 0.8.1 → 0.8.3

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 (123) hide show
  1. package/README.md +381 -27
  2. package/dist/accordion/llms.txt +56 -0
  3. package/dist/alert/llms.txt +45 -0
  4. package/dist/app-shell/app-shell.d.ts +20 -0
  5. package/dist/app-shell/app-shell.js +24 -0
  6. package/dist/app-shell/llms.txt +59 -0
  7. package/dist/auth/auth.d.ts +1 -1
  8. package/dist/auth/llms.txt +65 -0
  9. package/dist/autocomplete/autocomplete.d.ts +1 -1
  10. package/dist/autocomplete/llms.txt +44 -0
  11. package/dist/avatar/llms.txt +42 -0
  12. package/dist/avatar-group/avatar-group.d.ts +1 -1
  13. package/dist/avatar-group/llms.txt +38 -0
  14. package/dist/badge/llms.txt +38 -0
  15. package/dist/bottom-sheet/llms.txt +43 -0
  16. package/dist/breadcrumb/breadcrumb.d.ts +1 -1
  17. package/dist/breadcrumb/llms.txt +35 -0
  18. package/dist/button/llms.txt +56 -0
  19. package/dist/button-group/button-group.d.ts +1 -1
  20. package/dist/button-group/llms.txt +40 -0
  21. package/dist/card/llms.txt +60 -0
  22. package/dist/carousel/carousel.d.ts +1 -1
  23. package/dist/carousel/llms.txt +47 -0
  24. package/dist/charts/chart-legend.d.ts +1 -1
  25. package/dist/charts/llms.txt +57 -0
  26. package/dist/checkbox/llms.txt +39 -0
  27. package/dist/chip/llms.txt +41 -0
  28. package/dist/chips-input/llms.txt +40 -0
  29. package/dist/clock/llms.txt +50 -0
  30. package/dist/color-picker/color-picker.d.ts +1 -1
  31. package/dist/color-picker/llms.txt +40 -0
  32. package/dist/confirm/llms.txt +44 -0
  33. package/dist/context-menu/context-menu.d.ts +1 -1
  34. package/dist/context-menu/llms.txt +39 -0
  35. package/dist/data-table/data-table-types.d.ts +1 -1
  36. package/dist/data-table/data-table.d.ts +2 -10
  37. package/dist/data-table/data-table.js +17 -9
  38. package/dist/data-table/llms.txt +79 -0
  39. package/dist/data-view/data-view.d.ts +1 -1
  40. package/dist/data-view/llms.txt +49 -0
  41. package/dist/date-range/llms.txt +54 -0
  42. package/dist/datepicker/llms.txt +74 -0
  43. package/dist/dialog/llms.txt +51 -0
  44. package/dist/divider/llms.txt +28 -0
  45. package/dist/drawer/llms.txt +47 -0
  46. package/dist/empty/llms.txt +35 -0
  47. package/dist/fab/llms.txt +37 -0
  48. package/dist/fieldset/llms.txt +43 -0
  49. package/dist/file-upload/llms.txt +48 -0
  50. package/dist/form-field/llms.txt +55 -0
  51. package/dist/galleria/galleria.d.ts +1 -1
  52. package/dist/galleria/llms.txt +46 -0
  53. package/dist/grid/llms.txt +110 -0
  54. package/dist/icon/icon-registry.d.ts +5 -2
  55. package/dist/icon/icon-registry.js +5 -3
  56. package/dist/icon/llms.txt +66 -0
  57. package/dist/icon-button/llms.txt +38 -0
  58. package/dist/icons-entry/public-api.d.ts +5 -1
  59. package/dist/icons-entry/public-api.js +7 -1
  60. package/dist/image/llms.txt +46 -0
  61. package/dist/input/llms.txt +54 -0
  62. package/dist/input-mask/llms.txt +37 -0
  63. package/dist/input-number/llms.txt +44 -0
  64. package/dist/input-otp/llms.txt +43 -0
  65. package/dist/internal/use-breakpoint.js +18 -10
  66. package/dist/knob/llms.txt +46 -0
  67. package/dist/listbox/listbox.d.ts +1 -1
  68. package/dist/listbox/llms.txt +39 -0
  69. package/dist/map/llms.txt +108 -0
  70. package/dist/megamenu/llms.txt +48 -0
  71. package/dist/megamenu/megamenu.d.ts +1 -1
  72. package/dist/menu/llms.txt +56 -0
  73. package/dist/menu/menu-item.d.ts +1 -1
  74. package/dist/menu/menu-rows.d.ts +1 -1
  75. package/dist/menu/menu.d.ts +1 -1
  76. package/dist/menu/menu.js +12 -1
  77. package/dist/menubar/llms.txt +45 -0
  78. package/dist/menubar/menubar.d.ts +1 -1
  79. package/dist/meter-group/llms.txt +47 -0
  80. package/dist/meter-group/meter-group.d.ts +1 -1
  81. package/dist/order-list/llms.txt +41 -0
  82. package/dist/paginator/llms.txt +48 -0
  83. package/dist/paginator/paginator.d.ts +1 -1
  84. package/dist/paginator/paginator.js +7 -1
  85. package/dist/panel/llms.txt +55 -0
  86. package/dist/password/llms.txt +45 -0
  87. package/dist/pick-list/llms.txt +52 -0
  88. package/dist/popover/llms.txt +42 -0
  89. package/dist/progress/llms.txt +47 -0
  90. package/dist/public-api.d.ts +2 -1
  91. package/dist/public-api.js +1 -1
  92. package/dist/radio-group/llms.txt +40 -0
  93. package/dist/radio-group/radio-group.d.ts +1 -1
  94. package/dist/rating/llms.txt +43 -0
  95. package/dist/rich-text/llms.txt +61 -0
  96. package/dist/rich-text/rich-text.d.ts +1 -1
  97. package/dist/roadmap/llms.txt +82 -0
  98. package/dist/scroll-top/llms.txt +41 -0
  99. package/dist/select/llms.txt +56 -0
  100. package/dist/select/select.d.ts +1 -1
  101. package/dist/sidenav/llms.txt +53 -0
  102. package/dist/skeleton/llms.txt +33 -0
  103. package/dist/slider/llms.txt +50 -0
  104. package/dist/speed-dial/llms.txt +46 -0
  105. package/dist/speed-dial/speed-dial.d.ts +1 -1
  106. package/dist/spinner/llms.txt +33 -0
  107. package/dist/split-button/llms.txt +54 -0
  108. package/dist/split-button/split-button.d.ts +1 -1
  109. package/dist/splitter/llms.txt +44 -0
  110. package/dist/stepper/llms.txt +64 -0
  111. package/dist/switch/llms.txt +42 -0
  112. package/dist/switch-group/llms.txt +43 -0
  113. package/dist/switch-group/switch-group.d.ts +1 -1
  114. package/dist/tabs/llms.txt +48 -0
  115. package/dist/textarea/llms.txt +40 -0
  116. package/dist/timeline/llms.txt +53 -0
  117. package/dist/timeline/timeline.d.ts +1 -1
  118. package/dist/toast/llms.txt +52 -0
  119. package/dist/toolbar/llms.txt +45 -0
  120. package/dist/tooltip/llms.txt +42 -0
  121. package/dist/tree/llms.txt +45 -0
  122. package/dist/tree/tree.d.ts +2 -2
  123. package/package.json +11 -11
@@ -0,0 +1,54 @@
1
+ # KptSplitButton (@konce-pt/react)
2
+
3
+ A split button — a primary action plus a dropdown of further actions.
4
+ Import: `import { KptSplitButton } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <span class="kpt-split-button-host">
8
+ <div class="kpt-split-button" data-variant="filled">
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>
11
+ </div>
12
+ </span>
13
+ <!-- while open, in a portal: -->
14
+ <div class="kpt-split-button__panel" role="menu">…rows…</div>
15
+
16
+ ## Props
17
+ - `variant`: the same union as `KptButton` (default 'filled')
18
+ - `items`: `KptMenuItem<T>[]` — the same shape as `KptMenu`
19
+ - `disabled`: boolean — disables both buttons
20
+ - `onPrimaryClick()` — the main action
21
+ - `onSelect(item)` — a pick from the menu
22
+ - `open` / `defaultOpen` / `onOpenChange` — the panel state
23
+ - `children` — the content of the main action
24
+ - `locale`, `dictionary` — i18n overrides for this component only
25
+
26
+ ## The panel aligns to the right
27
+ The toggle sits on the right-hand side of the control, so the panel is anchored by its RIGHT edge
28
+ (`align="end"` on the overlay). Anchored to the left it would hang off the control instead of under
29
+ it — the same reasoning the Angular port encodes in its CDK position list.
30
+
31
+ ## Shared rows
32
+ The panel renders the same rows as `KptMenu` — icons, descriptions, badges, separators, headers and
33
+ the `danger` modifier all behave identically, only the BEM block differs.
34
+
35
+ ## i18n
36
+ The toggle's label comes from `splitButton.more` in the dictionary.
37
+
38
+ ## Examples
39
+ <KptSplitButton items={items} onPrimaryClick={save} onSelect={onItem}>Save</KptSplitButton>
40
+
41
+ const items: KptMenuItem[] = [
42
+ { label: 'Save as draft', value: 'draft' },
43
+ { label: 'Save and publish', value: 'publish' },
44
+ { separator: true },
45
+ { label: 'Discard', value: 'discard', danger: true },
46
+ ];
47
+
48
+ ## Tokens
49
+ The `--kpt-button-*` tokens of the chosen variant, plus `--kpt-color-surface-raised` and
50
+ `--kpt-elevation-3` for the panel.
51
+
52
+ ## Accessibility
53
+ Two native buttons; the toggle carries `aria-label`, the panel is `role="menu"` with
54
+ `role="menuitem"` rows.
@@ -4,7 +4,7 @@ import type { KptMenuItem } from '../menu/menu-item.ts';
4
4
  import type { KptButtonVariant } from '../button/button.tsx';
5
5
  export interface KptSplitButtonProps<T> extends Omit<ComponentPropsWithRef<'span'>, 'onSelect'>, KptI18nOverrides {
6
6
  variant?: KptButtonVariant;
7
- items?: KptMenuItem<T>[];
7
+ items?: readonly KptMenuItem<T>[];
8
8
  disabled?: boolean;
9
9
  /** Kliknięcie akcji głównej. */
10
10
  onPrimaryClick?: () => void;
@@ -0,0 +1,44 @@
1
+ # KptSplitter (@konce-pt/react)
2
+
3
+ Two panes with a draggable handle.
4
+ Import: `import { KptSplitter } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-splitter-host">
8
+ <div class="kpt-splitter" data-orientation="horizontal">
9
+ <div class="kpt-splitter__pane" style="flex-basis:40%">…</div>
10
+ <div class="kpt-splitter__gutter" role="separator" tabindex="0" aria-valuenow="40"></div>
11
+ <div class="kpt-splitter__pane" style="flex-basis:60%">…</div>
12
+ </div>
13
+ </div>
14
+
15
+ ## Props
16
+ - `orientation`: `'horizontal'` (default) | `'vertical'`
17
+ - `startSize` / `defaultStartSize` / `onStartSizeChange` — the first pane's size in percent
18
+ - `minSize`: number (percent, default 10) — neither pane goes below it
19
+ - `className`, `ref` and every other `<div>` prop go to the host
20
+
21
+ ## Panes
22
+ `<KptSplitter.Start>` and `<KptSplitter.End>` replace Angular's `[kptSplitStart]` / `[kptSplitEnd]`
23
+ slots. They render nothing themselves: the splitter reads their children and wraps them in
24
+ `__pane`, because it is the splitter that owns the size.
25
+
26
+ ## Dragging listens on the window
27
+ `pointermove` and `pointerup` are attached to `window`, not to the handle: on a quick drag the
28
+ pointer outruns a 6px strip, and a handle-bound listener would drop the drag after a few pixels.
29
+
30
+ ## Examples
31
+ <KptSplitter startSize={size} onStartSizeChange={setSize}>
32
+ <KptSplitter.Start>Left</KptSplitter.Start>
33
+ <KptSplitter.End>Right</KptSplitter.End>
34
+ </KptSplitter>
35
+
36
+ <KptSplitter orientation="vertical" defaultStartSize={30} minSize={20}>…</KptSplitter>
37
+
38
+ ## Tokens
39
+ The handle `--kpt-color-border` → `--kpt-color-primary` on hover and focus; the frame
40
+ `--kpt-color-border` with `--kpt-radius-md`.
41
+
42
+ ## Accessibility
43
+ The handle is `role="separator"` with `aria-orientation` and `aria-valuenow`, reachable with Tab;
44
+ the arrow keys resize by 2% a press, clamped by `minSize`.
@@ -0,0 +1,64 @@
1
+ # KptStepper + KptStep (@konce-pt/react)
2
+
3
+ A step wizard — a header of numbered steps plus the active step's content.
4
+ Import: `import { KptStepper, useKptStepper } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-stepper-host" style="--kpt-anim-duration:500ms; --kpt-anim-dir:1">
8
+ <ol class="kpt-stepper__header">
9
+ <li class="kpt-stepper__step is-done">
10
+ <button class="kpt-stepper__marker">✓</button>
11
+ <span class="kpt-stepper__label">Account</span>
12
+ <span class="kpt-stepper__connector"></span>
13
+ </li>
14
+ …
15
+ </ol>
16
+ <div class="kpt-stepper__body"><div class="kpt-stepper__panel">…</div></div>
17
+ </div>
18
+
19
+ ## KptStepper props
20
+ - `activeIndex` / `defaultActiveIndex` / `onActiveIndexChange`
21
+ - `animated`: boolean (default true), `animationDuration`: ms (default 500)
22
+ - `className`, `ref` and every other `<div>` prop go to the host
23
+
24
+ ## KptStepper.Step props
25
+ - `label`: string (required); `children` — the step's content
26
+
27
+ ## useKptStepper()
28
+ `{ activeIndex, count, next, prev, goTo }` — the replacement for Angular's `#s` + `s.next()`.
29
+ It reads a context the stepper provides around the panel, so it works only in a component
30
+ rendered inside a step (a hook cannot be called in the parent's body) and throws elsewhere.
31
+ `count` lets a step hide "Next" on the last one.
32
+
33
+ ## The step is a config carrier
34
+ `KptStep` renders `null`; `KptStepper` reads its props and decides what to show, so only the
35
+ active step's content is ever mounted — the same laziness as the `kpt-step` template in Angular.
36
+
37
+ ## The panel is keyed by index
38
+ `key={active}` forces a remount on every change, otherwise the enter animation would have nothing
39
+ to start from. The slide direction rides on `--kpt-anim-dir` (1 forward, -1 back), so jumping to
40
+ an earlier step animates from the other side.
41
+
42
+ ## Examples
43
+ <KptStepper>
44
+ <KptStepper.Step label="Account"><StepNav /></KptStepper.Step>
45
+ <KptStepper.Step label="Profile">…</KptStepper.Step>
46
+ </KptStepper>
47
+
48
+ function StepNav() {
49
+ const { activeIndex, count, next, prev } = useKptStepper();
50
+ return (
51
+ <>
52
+ {activeIndex > 0 && <KptButton size="sm" variant="text" onClick={prev}>Back</KptButton>}
53
+ {activeIndex < count - 1 && <KptButton size="sm" onClick={next}>Next</KptButton>}
54
+ </>
55
+ );
56
+ }
57
+
58
+ ## Tokens
59
+ The active and completed step: `--kpt-color-primary` (marker, connector); the rest
60
+ `--kpt-color-border-strong` and `--kpt-color-on-surface-muted`.
61
+
62
+ ## Accessibility
63
+ The header is an `<ol>` of real buttons — every step is reachable with the keyboard; the active
64
+ marker carries `aria-current="step"`.
@@ -0,0 +1,42 @@
1
+ # KptSwitch (@konce-pt/react)
2
+
3
+ A switch / toggle. Underneath it is a native `<input type="checkbox" role="switch">`, so the
4
+ keyboard and screen readers work with no extra handling.
5
+ Import: `import { KptSwitch } from '@konce-pt/react';`
6
+
7
+ ## DOM
8
+ <span class="kpt-switch-host">
9
+ <label class="kpt-switch">
10
+ <input type="checkbox" role="switch" class="kpt-switch__input">
11
+ <span class="kpt-switch__track" aria-hidden="true"><span class="kpt-switch__thumb"></span></span>
12
+ <span class="kpt-switch__label">Notifications</span>
13
+ <span class="kpt-switch__state kpt-switch__state--on">On</span>
14
+ </label>
15
+ </span>
16
+
17
+ ## Props
18
+ - `label`: string, `labelPosition`: 'start' | 'end' (default 'end')
19
+ - `onLabel`, `offLabel`: string — the state text, swapped on toggle
20
+ - `checked` / `defaultChecked`, `onCheckedChange(checked)`, `onTouch()`
21
+ - `required`, `invalid`, `touched` — as in `KptCheckbox`
22
+ - `hostProps` — props for the `.kpt-switch-host` wrapper
23
+ - `className` goes to the `.kpt-switch` block; the rest to the native `<input>`
24
+
25
+ ## The state text needs a controlled value
26
+ `onLabel` and `offLabel` read `checked`, so they only follow the switch in controlled mode.
27
+ Uncontrolled, the value belongs to the DOM and React never learns about a toggle, which would
28
+ freeze the state text on its initial value — use `checked` with `onCheckedChange` whenever you
29
+ show one.
30
+
31
+ ## Examples
32
+ <KptSwitch name="notifications" label="Notifications" />
33
+ <KptSwitch checked={on} onCheckedChange={setOn} onLabel="On" offLabel="Off" />
34
+ <KptSwitch checked={on} onCheckedChange={setOn} label="Dark mode" labelPosition="start" />
35
+
36
+ ## Tokens
37
+ `--kpt-color-primary` (the on track), `--kpt-color-muted` (the off track), `--kpt-color-surface`
38
+ (the thumb), `--kpt-motion-duration-fast`.
39
+
40
+ ## Accessibility
41
+ `role="switch"` on a native checkbox — a screen reader announces on/off instead of
42
+ checked/unchecked. The track and the thumb are `aria-hidden`.
@@ -0,0 +1,43 @@
1
+ # KptSwitchGroup (@konce-pt/react)
2
+
3
+ A group of switches — mutually exclusive by default, multi-select with `multiple`.
4
+ Import: `import { KptSwitchGroup } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-switch-group-host">
8
+ <div class="kpt-switch-group" role="group">
9
+ <span class="kpt-switch-host kpt-switch-group__item">…KptSwitch…</span>
10
+ …one per option…
11
+ </div>
12
+ </div>
13
+
14
+ ## Props
15
+ - `options`: `KptOption<T>[]` — `{ label, value, disabled? }`
16
+ - `value` / `defaultValue` / `onValueChange` — single select: the option's value or `null`;
17
+ with `multiple`: an array of the selected values
18
+ - `multiple`: boolean (default false)
19
+ - `orientation`: `'vertical'` (default) | `'horizontal'`
20
+ - `allowDeselect`: boolean (default true) — single select only; in `multiple` mode turning an
21
+ option off is always allowed
22
+ - `disabled`, `invalid`, `touched`, `onTouch()`
23
+ - `className`, `ref` and every other `<div>` prop go to the host
24
+
25
+ ## Single select comes out of the value, not out of the switches
26
+ Every entry is a `KptSwitch` whose `checked` is derived from the group value, so turning one on
27
+ turns the rest off by itself — there is no per-switch state to keep in sync.
28
+
29
+ That is also why `allowDeselect={false}` needs no code: the handler writes nothing, so React
30
+ re-applies the controlled `checked` and the switch snaps back on.
31
+
32
+ ## Examples
33
+ <KptSwitchGroup value={mode} onValueChange={setMode} options={options} />
34
+ <KptSwitchGroup multiple value={channels} onValueChange={setChannels} options={options} />
35
+ <KptSwitchGroup orientation="horizontal" value={mode} onValueChange={setMode} options={options} />
36
+
37
+ ## Tokens
38
+ Layout only: `--kpt-space-2` (vertical gap) and `--kpt-space-4` (horizontal). The look comes from
39
+ `KptSwitch` and its tokens.
40
+
41
+ ## Accessibility
42
+ `role="group"` with `aria-invalid` once the field is touched; every entry keeps the native
43
+ checkbox of `KptSwitch`, so keyboard and screen readers work with no extra handling.
@@ -1,7 +1,7 @@
1
1
  import type { ComponentPropsWithRef } from 'react';
2
2
  import type { KptOption } from '../shared/types.ts';
3
3
  export interface KptSwitchGroupProps<T> extends Omit<ComponentPropsWithRef<'div'>, 'onChange' | 'defaultValue'> {
4
- options?: KptOption<T>[];
4
+ options?: readonly KptOption<T>[];
5
5
  /** Pojedynczy wybór: wartość opcji albo `null`. Tryb `multiple`: tablica wartości. */
6
6
  value?: T | T[] | null;
7
7
  defaultValue?: T | T[] | null;
@@ -0,0 +1,48 @@
1
+ # KptTabs (@konce-pt/react)
2
+
3
+ Tabs — switching views, with the content rendered lazily.
4
+ Import: `import { KptTabs } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-tabs-host" style="--kpt-anim-duration: 500ms; --kpt-anim-dir: 1">
8
+ <div class="kpt-tabs__header" role="tablist">
9
+ <button class="kpt-tabs__tab is-active" role="tab" aria-selected="true">General</button>
10
+ <button class="kpt-tabs__tab" role="tab" aria-selected="false">Advanced</button>
11
+ <span class="kpt-tabs__ink" style="width: 95px; transform: translateX(85px)"></span>
12
+ </div>
13
+ <div class="kpt-tabs__body" role="tabpanel">
14
+ <div class="kpt-tabs__panel">…active tab content…</div>
15
+ </div>
16
+ </div>
17
+
18
+ ## Props
19
+ - `activeIndex` / `defaultActiveIndex` / `onActiveIndexChange` — controlled or uncontrolled
20
+ - `animated`: boolean (default true), `animationDuration`: number (ms, default 500)
21
+ - `children` — `<KptTabs.Tab>` elements
22
+
23
+ ## KptTabs.Tab
24
+ `label` (required), `disabled`, `children`. The tab component never renders itself — `KptTabs`
25
+ reads its props and decides what to show, exactly as the Angular version reads the `kpt-tab`
26
+ template. Only the active tab's content is in the DOM.
27
+
28
+ ## The underline is measured, not computed
29
+ `__ink` takes its width and offset from the active button in the DOM, not from the index: tabs have
30
+ different widths and the labels change with the language. The measurement runs after every render,
31
+ and the state is only replaced when the numbers actually change — otherwise each measurement would
32
+ schedule another render and the component would loop.
33
+
34
+ ## Examples
35
+ <KptTabs>
36
+ <KptTabs.Tab label="General">…</KptTabs.Tab>
37
+ <KptTabs.Tab label="Advanced">…</KptTabs.Tab>
38
+ </KptTabs>
39
+
40
+ <KptTabs activeIndex={tab} onActiveIndexChange={setTab} animated={false}>…</KptTabs>
41
+
42
+ ## Tokens
43
+ `--kpt-color-primary` (the active tab and the ink), `--kpt-color-on-surface-muted`,
44
+ `--kpt-color-border`, `--kpt-motion-easing-standard`.
45
+
46
+ ## Accessibility
47
+ The header is `role="tablist"` with `role="tab"` buttons carrying `aria-selected`; the body is
48
+ `role="tabpanel"`. A disabled tab is a disabled button, so the keyboard skips it.
@@ -0,0 +1,40 @@
1
+ # KptTextarea (@konce-pt/react)
2
+
3
+ A multi-line field, with optional auto-resize. It renders a native `<textarea>` inside a
4
+ `.kpt-textarea-host` wrapper. Import: `import { KptTextarea } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <span class="kpt-textarea-host">
8
+ <textarea class="kpt-textarea__field" rows="3"></textarea>
9
+ </span>
10
+
11
+ ## Props
12
+ - `autoResize`: boolean — matches the height to the content on every change
13
+ - `rows`: number (default 3) — the starting height
14
+ - `value` / `defaultValue` — controlled or uncontrolled, like a native textarea
15
+ - `onValueChange(value)`, `onTouch()` — the value alone, and the blur moment
16
+ - `required`: boolean — set as `aria-required`, not as the native attribute
17
+ - `invalid`, `touched` — the error state, gated the same way as in `KptInput`
18
+ - `hostProps` — props for the wrapper
19
+ - `className`, `ref`, `name`, `placeholder` and every other `<textarea>` prop go to the textarea
20
+
21
+ ## Auto-resize
22
+ The height is read straight from the DOM (`scrollHeight`), so it is right for a controlled field, an
23
+ uncontrolled one, and a prefilled initial value alike. The measurement resets the height to `auto`
24
+ first — without that a field can only ever grow, since `scrollHeight` never drops below the current
25
+ height.
26
+
27
+ ## Examples
28
+ <KptTextarea name="notes" placeholder="Notes…" autoResize />
29
+ <KptTextarea value={note} onValueChange={setNote} rows={6} />
30
+ <KptFormField label="Notes" error={err}>
31
+ <KptTextarea invalid={!!err} onTouch={markTouched} />
32
+ </KptFormField>
33
+
34
+ ## Tokens
35
+ `--kpt-form-field-{bg,text,placeholder,border,border-hover,border-focus,border-error,radius}` —
36
+ the same set as the text field, so both controls stay in step.
37
+
38
+ ## Accessibility
39
+ A native `<textarea>`. Inside `KptFormField` it takes its `id` from the wrapper, so `label[for]`
40
+ is wired with no configuration.
@@ -0,0 +1,53 @@
1
+ # KptTimeline (@konce-pt/react)
2
+
3
+ A timeline — a vertical list of events with markers.
4
+ Import: `import { KptTimeline } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-timeline-host">
8
+ <ol class="kpt-timeline">
9
+ <li class="kpt-timeline__item">
10
+ <div class="kpt-timeline__marker" data-variant="success">…icon…</div>
11
+ <div class="kpt-timeline__content">
12
+ <div class="kpt-timeline__header">
13
+ <span class="kpt-timeline__title">Order created</span>
14
+ <span class="kpt-timeline__time">10:02</span>
15
+ </div>
16
+ <p class="kpt-timeline__desc">…</p>
17
+ </div>
18
+ </li>
19
+ </ol>
20
+ </div>
21
+
22
+ ## Props
23
+ - `items`: `KptTimelineItem[]`
24
+ - `className`, `ref` and every other `<div>` prop go to the host
25
+
26
+ ### KptTimelineItem
27
+ - `title`: string (required)
28
+ - `description?`, `time?`: string; `icon?`: an icon name from the registry
29
+ - `variant?`: `'neutral' | 'primary' | 'success' | 'danger' | 'warning' | 'info'` (default `'primary'`)
30
+
31
+ ## The variant is an attribute, not a class
32
+ The marker carries `data-variant`, and the SCSS maps it to `--_color` — the same contract as every
33
+ other component in the library, so a new variant is a token, not a new class.
34
+
35
+ ## The connecting line is a pseudo-element
36
+ `::before` on every item but the last, so the line is drawn between markers without an extra node
37
+ and needs no knowledge of the list's length.
38
+
39
+ ## Examples
40
+ <KptTimeline items={events} />
41
+
42
+ const events: KptTimelineItem[] = [
43
+ { title: 'Order created', time: '10:02', variant: 'success', icon: 'check' },
44
+ { title: 'Shipped', time: '12:30', variant: 'info' },
45
+ ];
46
+
47
+ ## Tokens
48
+ The marker follows the variant (`--kpt-color-{variant}`), the line `--kpt-color-border`, the
49
+ description `--kpt-color-on-surface-muted`.
50
+
51
+ ## Accessibility
52
+ An ordered list (`<ol>`), so the sequence of events is conveyed by the markup itself; markers are
53
+ decorative and carry no text of their own.
@@ -8,7 +8,7 @@ export interface KptTimelineItem {
8
8
  variant?: 'neutral' | 'primary' | 'success' | 'danger' | 'warning' | 'info';
9
9
  }
10
10
  export interface KptTimelineProps extends ComponentPropsWithRef<'div'> {
11
- items?: KptTimelineItem[];
11
+ items?: readonly KptTimelineItem[];
12
12
  }
13
13
  /**
14
14
  * Oś czasu — pionowa lista zdarzeń z markerami.
@@ -0,0 +1,52 @@
1
+ # Toast (@konce-pt/react)
2
+
3
+ Notifications. `kptToast` raises them, `<KptToastContainer />` renders them.
4
+ Import: `import { kptToast, KptToastContainer } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-toast-container-host">
8
+ <div class="kpt-toast-container" aria-live="polite" aria-atomic="false">
9
+ <div class="kpt-toast" data-variant="success" role="status">
10
+ <span class="kpt-icon-host kpt-toast__icon">…</span>
11
+ <div class="kpt-toast__content">
12
+ <div class="kpt-toast__title">Saved</div>
13
+ <div class="kpt-toast__message">Your changes are stored.</div>
14
+ </div>
15
+ <button class="kpt-toast__close" type="button" aria-label="Close">…</button>
16
+ </div>
17
+ </div>
18
+ </div>
19
+
20
+ ## kptToast
21
+ - `show(message, options?)` — returns the toast id
22
+ - `info` / `success` / `warning` / `error` — the same, with the variant preset
23
+ - `dismiss(id)`, `clear()`
24
+ - options: `title`, `variant`, `duration` (ms, default 4000; `0` disables auto-dismiss)
25
+
26
+ ## A module singleton, not a provider
27
+ The store lives in the module, which is the closest equivalent of Angular's
28
+ `providedIn: 'root'`. `kptToast.error(...)` therefore works from anywhere — including outside the
29
+ React tree, in a data-layer error handler or an HTTP interceptor — with no provider wrapping the
30
+ application. `useKptToasts()` exposes the current list when you want to render them yourself.
31
+
32
+ ## Placement
33
+ Render `<KptToastContainer />` once, near the root of the application. Toasts raised before it
34
+ mounts are kept in the store and appear as soon as it does.
35
+
36
+ ## Examples
37
+ // once in the app
38
+ <KptToastContainer />
39
+
40
+ kptToast.success('Saved', { title: 'Saved' });
41
+ kptToast.error('Could not connect to the server.', { title: 'Error', duration: 0 });
42
+ const id = kptToast.info('Uploading…', { duration: 0 });
43
+ kptToast.dismiss(id);
44
+
45
+ ## Tokens
46
+ The semantic colour pairs of each variant (`--kpt-color-info` / `-success` / `-warning` /
47
+ `-danger` with their `-subtle` and `on-` counterparts), `--kpt-elevation-3`, `--kpt-z-overlay`.
48
+
49
+ ## Accessibility
50
+ The container is `aria-live="polite"` with `aria-atomic="false"`, and each toast is
51
+ `role="status"`, so a screen reader announces new ones without interrupting the current task.
52
+ The close button gets its label from `common.close`.
@@ -0,0 +1,45 @@
1
+ # KptToolbar (@konce-pt/react)
2
+
3
+ The top bar — a horizontal strip for application content (logo, actions).
4
+ Import: `import { KptToolbar, KptToolbarSpacer } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-toolbar kpt-toolbar--elevated">
8
+ …children…
9
+ <span kpttoolbarspacer=""></span>
10
+ …children…
11
+ </div>
12
+
13
+ ## Props
14
+ - `elevated`: boolean — adds a shadow under the bar
15
+ - `wrap`: boolean — lets the content wrap onto further rows when it runs out of room
16
+ - `className`, `ref` and every other `<div>` prop go to the bar itself
17
+
18
+ `wrap` is opt-in because wrapping changes what `<KptToolbarSpacer>` does: in a single-row bar it
19
+ pushes content apart, in a wrapping one it can shove the rest onto a new row.
20
+
21
+ ## KptToolbarSpacer
22
+ A flexible gap that pushes the bar's content apart. It carries the `kpttoolbarspacer` attribute the
23
+ shared SCSS targets (attribute names in CSS selectors are case-insensitive in HTML, so one rule
24
+ serves both ports).
25
+
26
+ ## Examples
27
+ <KptToolbar elevated>
28
+ <strong>Koncept UI</strong>
29
+ <KptToolbarSpacer />
30
+ <KptButton variant="text">Sign out</KptButton>
31
+ </KptToolbar>
32
+
33
+ <KptAppShell toolbar={<KptToolbar elevated>…</KptToolbar>} sidenav={…}>…</KptAppShell>
34
+
35
+ ## Responsiveness
36
+ Below the `sm` breakpoint the bar shrinks on its own — a lower height
37
+ (`--kpt-toolbar-height-compact`), narrower inline padding and a smaller gap. No props involved.
38
+
39
+ ## Tokens
40
+ `--kpt-toolbar-height` (3.5rem), `--kpt-toolbar-height-compact` (3rem), `--kpt-toolbar-bg`,
41
+ `--kpt-toolbar-fg`, `--kpt-toolbar-border`, `--kpt-elevation-1` for the elevated variant.
42
+
43
+ ## Accessibility
44
+ A plain container with no role of its own. Give it `role="banner"` or wrap it in a `<header>`
45
+ when it is the page's main bar.
@@ -0,0 +1,42 @@
1
+ # KptTooltip (@konce-pt/react)
2
+
3
+ A tooltip shown on hover and focus. Light — the element is appended to `body` and positioned
4
+ against the child. Import: `import { KptTooltip } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ The component renders NO wrapper of its own — it clones the child and attaches the handlers and a
8
+ ref to it, so the tree stays exactly as it would be without the tooltip. This is the port of the
9
+ `[kptTooltip]` directive, which likewise added nothing to the DOM.
10
+
11
+ <!-- while visible, appended to body: -->
12
+ <div class="kpt-tooltip" role="tooltip" style="position: fixed; …">Save changes</div>
13
+
14
+ ## Props
15
+ - `text`: string — the bubble content; empty text disables the tooltip
16
+ - `position`: 'top' | 'bottom' | 'left' | 'right' (default 'top')
17
+ - `onlyWhenTruncated`: boolean — show it only when the content does not fit
18
+ - `children` — exactly one element, the one that gets hover and focus
19
+
20
+ ## onlyWhenTruncated
21
+ The check runs at hover time, not at render, so the result is always current after a width or zoom
22
+ change, with no observers. It measures the host AND its direct children, because
23
+ `text-overflow: ellipsis` usually sits on an inner element — and such an element shrinks to the
24
+ available width instead of stretching its parent, so measuring the host alone would find nothing.
25
+
26
+ ## Styling
27
+ The bubble carries inline styles built from tokens rather than a class from the shared stylesheet,
28
+ exactly like the Angular directive — it is created outside React's tree, so there is nothing to
29
+ attach a stylesheet rule to reliably.
30
+
31
+ ## Examples
32
+ <KptTooltip text="Save changes" position="bottom"><KptButton>Save</KptButton></KptTooltip>
33
+ <KptTooltip text={name} onlyWhenTruncated><span className="ellipsis">{name}</span></KptTooltip>
34
+
35
+ ## Tokens
36
+ `--kpt-color-on-surface` (the background), `--kpt-color-surface` (the text), `--kpt-radius-sm`,
37
+ `--kpt-font-size-xs`, `--kpt-elevation-2`.
38
+
39
+ ## Accessibility
40
+ The bubble is `role="tooltip"` and appears on focus as well as hover, so it is reachable from the
41
+ keyboard. It is `pointer-events: none`, so it never steals a click. It does NOT replace an
42
+ accessible name — for an icon-only button give the button its own `aria-label`.
@@ -0,0 +1,45 @@
1
+ # KptTree (@konce-pt/react)
2
+
3
+ A hierarchical tree: expanding, selection, icons.
4
+ Import: `import { KptTree, type KptTreeNode } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-tree-host">
8
+ <ul class="kpt-tree" role="tree">
9
+ <li class="kpt-tree__node" role="treeitem" aria-expanded="true">
10
+ <div class="kpt-tree__row is-selected">
11
+ <button class="kpt-tree__toggle">…chevron…</button>
12
+ <span class="kpt-tree__icon">…</span>
13
+ <span class="kpt-tree__label">src</span>
14
+ </div>
15
+ <ul role="group">…</ul>
16
+ </li>
17
+ </ul>
18
+ </div>
19
+
20
+ ## Props
21
+ - `nodes`: `KptTreeNode<T>[]` — `{ label, value?, icon?, children?, expanded?, disabled? }`
22
+ - `selectable`: boolean — a row click selects instead of expanding
23
+ - `selected` / `defaultSelected` / `onSelectedChange` — the node object, or `null`
24
+ - `onNodeClick(node)`
25
+ - `className`, `ref` and every other `<div>` prop go to the host
26
+
27
+ ## Expansion is component state, not data
28
+ The Angular port flips `node.expanded` in place and bumps a version signal. In React that would be
29
+ a side effect on someone else's array during render, so the open branches live in a `Set` of node
30
+ references instead — and `expanded` in the data goes back to being what it should be: the initial
31
+ state, read once on mount.
32
+
33
+ ## Examples
34
+ <KptTree nodes={tree} />
35
+ <KptTree nodes={tree} selectable selected={node} onSelectedChange={setNode} />
36
+
37
+ ## i18n
38
+ The toggle is labelled from `tree.expand` / `tree.collapse`.
39
+
40
+ ## Tokens
41
+ The selected row `--kpt-color-primary`, the hover `--kpt-color-surface-variant`.
42
+
43
+ ## Accessibility
44
+ `role="tree"` / `role="treeitem"` with `aria-expanded` on branches only; the indentation is
45
+ `padding-inline-start`, so it follows the writing direction.
@@ -4,13 +4,13 @@ export interface KptTreeNode<T = unknown> {
4
4
  label: string;
5
5
  value?: T;
6
6
  icon?: string;
7
- children?: KptTreeNode<T>[];
7
+ children?: readonly KptTreeNode<T>[];
8
8
  /** Stan początkowy gałęzi; dalej rozwijaniem steruje już komponent. */
9
9
  expanded?: boolean;
10
10
  disabled?: boolean;
11
11
  }
12
12
  export interface KptTreeProps<T> extends Omit<ComponentPropsWithRef<'div'>, 'onSelect' | 'children'>, KptI18nOverrides {
13
- nodes?: KptTreeNode<T>[];
13
+ nodes?: readonly KptTreeNode<T>[];
14
14
  /** Klik w wiersz zaznacza gałąź zamiast ją rozwijać. */
15
15
  selectable?: boolean;
16
16
  selected?: KptTreeNode<T> | null;