@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,74 @@
1
+ # KptDatepicker (@konce-pt/react)
2
+
3
+ Picking a date and time with a custom calendar. The granularity comes from `selectionMode`.
4
+ Import: `import { KptDatepicker } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-datepicker-host">
8
+ <div class="kpt-datepicker" role="button" tabindex="0">
9
+ <span class="kpt-datepicker__value">06.09.2026</span>
10
+ <span class="kpt-datepicker__spacer"></span>
11
+ <button class="kpt-datepicker__clear">…</button>
12
+ <span class="kpt-icon-host kpt-datepicker__icon">…</span>
13
+ </div>
14
+ </div>
15
+ <!-- in a portal: <div class="kpt-calendar">…</div> -->
16
+
17
+ ## Props
18
+ - `value` / `defaultValue` / `onValueChange` — the value as a string; its format follows the mode:
19
+ 'YYYY-MM-DD' / 'YYYY-MM' / 'YYYY' / 'MM' / 'YYYY-MM-DDTHH:mm' / 'HH:mm'
20
+ - `selectionMode`: `'date'` (default) | `'monthYear'` | `'year'` | `'month'` | `'datetime'` | `'time'`
21
+ - `startView`: `'day' | 'month' | 'year' | 'decade' | null` — the level the panel opens at; `null`
22
+ means the level where the mode commits. It is never lowered below that level, so
23
+ `startView="day"` in 'year' mode is raised to 'year'.
24
+ - `minDate`, `maxDate`: 'YYYY-MM-DD' strings
25
+ - `monthDisplay`: `'long'` (default) | `'number'`; `displayFormat`: `'pl'` (default) | `'iso'`
26
+ - `hourFormat`: 12 | 24 (default 24) — the dial; the stored value is always 24h
27
+ - `minuteStep`: number (default 1) — minute snapping on the dial
28
+ - `open` / `onOpenChange` — the panel state, so it can be opened from outside
29
+ - `placeholder`, `ariaLabel`, `disabled`, `invalid`, `touched`, `onTouch()`
30
+ - `className`, `ref` and every other `<div>` prop go to the host
31
+
32
+ ## The view stack
33
+ The header is always `‹ title ›`: the arrows page the current level, the title goes one level up.
34
+
35
+ day ‹ [June] [1979] › arrows ±1 month; the chips → months / years
36
+ month ‹ [1979] › arrows ±1 year; the chip → years
37
+ year ‹ [1970 – 1979] › arrows ±10 years; the chip → decades
38
+ decade ‹ 1920 – 2039 › arrows ±120 years; the top of the stack
39
+
40
+ Clicking a cell above the committing level drills down; on that level it sets the value and closes
41
+ the panel. An arrow dims when the whole neighbouring page falls outside `minDate`/`maxDate`.
42
+
43
+ ## The logic lives in a package, the component only renders
44
+ Every grid, bound and format comes from `@konce-pt/datetime` — pure functions with their own tests.
45
+ The component holds nothing but React state: the page, the level, the time buffer.
46
+
47
+ ## The panel is set up on open, not on click
48
+ The state is initialised in an effect keyed on `open`, because the panel can also be opened from
49
+ outside through the `open` prop. The effect deliberately depends on `open` alone: a value changing
50
+ while the panel is open must not reset the view under the user's fingers.
51
+
52
+ ## Requires
53
+ `@konce-pt/styles/components` for the calendar styles. No CDK — the panel rides the internal
54
+ overlay primitive.
55
+
56
+ ## Examples
57
+ <KptDatepicker value={date} onValueChange={setDate} />
58
+ <KptDatepicker startView="decade" minDate="1920-01-01" maxDate="2029-12-31" value={birth} onValueChange={setBirth} />
59
+ <KptDatepicker selectionMode="monthYear" value={period} onValueChange={setPeriod} />
60
+ <KptDatepicker selectionMode="datetime" hourFormat={12} value={at} onValueChange={setAt} />
61
+ <KptDatepicker selectionMode="time" value={alarm} onValueChange={setAlarm} />
62
+
63
+ ## i18n
64
+ Weekday and month names come from `Intl` for the active locale, not from the dictionary. The
65
+ navigation labels and "Done" come from the `datepicker` and `common` namespaces; `locale` and
66
+ `dictionary` override them per instance.
67
+
68
+ ## Tokens
69
+ `--kpt-form-field-{bg,text,border,border-focus,border-error,radius}`; the panel
70
+ `--kpt-color-surface-raised`, the selection `--kpt-color-primary`.
71
+
72
+ ## Accessibility
73
+ The trigger is `role="button"` with `tabindex="0"` and Enter; every cell is a real `<button>` with
74
+ `aria-pressed`; `ariaLabel` names the field when no `<label for>` describes it.
@@ -0,0 +1,51 @@
1
+ # KptDialog (@konce-pt/react)
2
+
3
+ A modal window on a native `<dialog>` — the focus trap, Escape and the backdrop come from the
4
+ platform, not from our code. Import: `import { KptDialog } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <dialog class="kpt-dialog">
8
+ <div class="kpt-dialog__header">
9
+ <h2 class="kpt-dialog__title">Delete record?</h2>
10
+ <button class="kpt-dialog__close" type="button" aria-label="Close">…</button>
11
+ </div>
12
+ <div class="kpt-dialog__body">…children…</div>
13
+ <div kptdialogfooter="">…footer…</div>
14
+ </dialog>
15
+
16
+ ## Props
17
+ - `open`: boolean, `onOpenChange(open)` — the dialog is always controlled; the browser can close it
18
+ on its own (Escape, the `close` event), and the state has to follow
19
+ - `header`: string — the title; with no header there is no header row and no × button
20
+ - `dismissible`: boolean (default true) — allows Escape and shows ×
21
+ - `className`, `ref` and every other `<dialog>` prop go to the dialog
22
+
23
+ ## Sub-components
24
+ - `KptDialog.Footer` — lifted below the body; carries the `kptdialogfooter` attribute the shared
25
+ SCSS targets.
26
+
27
+ ## An overlay inside a modal
28
+ `showModal()` lifts the dialog into the browser's TOP LAYER, which sits above the whole document —
29
+ no `z-index` beats it. A `KptSelect` or `KptMenu` panel portalled to `document.body` would open
30
+ INVISIBLE, hidden behind the modal backdrop. While it is open, `KptDialog` therefore makes itself
31
+ the overlay container (through `KptOverlayContainerContext`), so those panels portal INSIDE the
32
+ `<dialog>`. The Angular port solves the same problem by moving the CDK overlay container into the
33
+ dialog; the mechanism differs, the result does not.
34
+
35
+ ## Examples
36
+ <KptDialog open={open} onOpenChange={setOpen} header="Delete record?">
37
+ This action cannot be undone.
38
+ <KptDialog.Footer>
39
+ <KptButton variant="text" onClick={() => setOpen(false)}>Cancel</KptButton>
40
+ <KptButton variant="danger" onClick={remove}>Delete</KptButton>
41
+ </KptDialog.Footer>
42
+ </KptDialog>
43
+
44
+ ## Tokens
45
+ `--kpt-color-surface-raised`, `--kpt-color-border`, `--kpt-radius-lg`, `--kpt-elevation-4`,
46
+ `--kpt-color-overlay-scrim` (the `::backdrop`).
47
+
48
+ ## Accessibility
49
+ A native `<dialog>` opened with `showModal()`: focus moves inside and is trapped, the rest of the
50
+ page becomes inert, and Escape closes it — all from the browser. With `dismissible={false}` the
51
+ `cancel` event is prevented, so Escape stops working; give the user another way out.
@@ -0,0 +1,28 @@
1
+ # KptDivider (@konce-pt/react)
2
+
3
+ A separator — a horizontal or vertical line. Colour from `--kpt-color-border`.
4
+ Import: `import { KptDivider } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-divider" role="separator" aria-orientation="horizontal" data-orientation="horizontal"></div>
8
+
9
+ ## Props
10
+ - `orientation`: 'horizontal' | 'vertical' (default 'horizontal')
11
+ - `inset`: boolean — an indent from the container edges
12
+ - `className`, `ref` and every other `<div>` prop go to the divider
13
+
14
+ ## Vertical needs a flex parent
15
+ The vertical variant stretches to the height of its container, so it only makes sense inside a
16
+ flex row — on its own it has nothing to measure against and collapses to nothing.
17
+
18
+ ## Examples
19
+ <KptDivider />
20
+ <KptDivider inset />
21
+ <div style={{ display: 'flex' }}>A<KptDivider orientation="vertical" />B</div>
22
+
23
+ ## Tokens
24
+ `--kpt-color-border`, `--kpt-space-*` for the inset.
25
+
26
+ ## Accessibility
27
+ `role="separator"` with `aria-orientation`, so a screen reader announces the break instead of
28
+ silently skipping a decorative line.
@@ -0,0 +1,47 @@
1
+ # KptDrawer (@konce-pt/react)
2
+
3
+ A slide-out panel (drawer / off-canvas), independent of the app shell.
4
+ Import: `import { KptDrawer } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-drawer-host">
8
+ <div class="kpt-drawer__backdrop is-open"></div>
9
+ <aside class="kpt-drawer__panel is-open" data-position="right" role="dialog" aria-modal="true" tabindex="-1">
10
+ <div class="kpt-drawer__header">
11
+ <span class="kpt-drawer__title">Filters</span>
12
+ <button class="kpt-drawer__close" type="button" aria-label="Close">…</button>
13
+ </div>
14
+ <div class="kpt-drawer__body">…children…</div>
15
+ </aside>
16
+ </div>
17
+
18
+ ## Props
19
+ - `open`: boolean, `onOpenChange(open)` — controlled
20
+ - `position`: 'left' | 'right' | 'top' | 'bottom' (default 'left')
21
+ - `header`: string
22
+ - `dismissible`: boolean (default true) — shows × and lets Escape close it
23
+ - `closeOnBackdrop`: boolean (default true)
24
+ - `className`, `ref` and every other `<div>` prop go to the host
25
+
26
+ ## Always in the DOM
27
+ The panel and the backdrop are always rendered; only the `is-open` class decides what is visible.
28
+ That is what makes the slide animatable — mounting the panel on open would give the transition
29
+ nothing to animate from.
30
+
31
+ ## Not a native modal
32
+ Unlike `KptDialog` this is a plain `<aside role="dialog" aria-modal="true">`, so the browser does
33
+ not trap focus and does not make the rest of the page inert. Escape works while the focus is inside
34
+ the panel. For a hard modal reach for `KptDialog`.
35
+
36
+ ## Examples
37
+ <KptDrawer open={open} onOpenChange={setOpen} position="right" header="Filters">
38
+ Panel content…
39
+ </KptDrawer>
40
+
41
+ ## Tokens
42
+ `--kpt-color-surface-raised`, `--kpt-color-border`, `--kpt-elevation-3`,
43
+ `--kpt-color-overlay-scrim`, `--kpt-motion-duration-base`, `--kpt-z-overlay`.
44
+
45
+ ## Accessibility
46
+ `role="dialog"` with `aria-modal="true"` and `tabindex="-1"`, so the panel can take focus. The close
47
+ button gets its label from `common.close` in the dictionary.
@@ -0,0 +1,35 @@
1
+ # KptEmpty (@konce-pt/react)
2
+
3
+ An empty state — an icon, a title, a description and optional actions.
4
+ Import: `import { KptEmpty } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-empty-host">
8
+ <div class="kpt-empty">
9
+ <div class="kpt-empty__icon">…icon…</div>
10
+ <p class="kpt-empty__title">No results</p>
11
+ <p class="kpt-empty__desc">Adjust your search criteria.</p>
12
+ <div class="kpt-empty__actions">…children…</div>
13
+ </div>
14
+ </div>
15
+
16
+ ## Props
17
+ - `icon`: string | null (default 'info-circle') — a registry icon name; `null` hides it
18
+ - `title`: string, `description`: string — each row disappears when its text is empty
19
+ - `children` — the actions under the description
20
+ - `className`, `ref` and every other `<div>` prop go to the host
21
+
22
+ ## Examples
23
+ <KptEmpty icon="search" title="No results" description="Adjust your search criteria.">
24
+ <KptButton variant="outline">Clear filters</KptButton>
25
+ </KptEmpty>
26
+
27
+ <KptEmpty icon={null} title="Nothing here yet" />
28
+
29
+ ## Tokens
30
+ `--kpt-color-on-surface-muted` (the description), `--kpt-space-*`.
31
+
32
+ ## Accessibility
33
+ A plain container with no role of its own — the title is a `<p>`, not a heading, so it does not
34
+ break the heading outline of the page. Where the empty state IS the heading of its section, render
35
+ your own `<h2>` in the children instead.
@@ -0,0 +1,37 @@
1
+ # KptFab (@konce-pt/react)
2
+
3
+ A floating action button — round and raised. `extended` turns it into a pill with text.
4
+ Import: `import { KptFab } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <span class="kpt-fab-host">
8
+ <button class="kpt-fab" type="button" data-variant="filled" data-size="md" aria-label="Add">…icon…</button>
9
+ </span>
10
+
11
+ ## Props
12
+ - `variant`: 'filled' | 'tonal' (default 'filled')
13
+ - `size`: 'md' | 'mini' (default 'md')
14
+ - `extended`: boolean — a pill with text next to the icon
15
+ - `hostProps` — props for the `.kpt-fab-host` wrapper
16
+ - `className`, `ref` and every other `<button>` prop go to the inner `<button>`
17
+
18
+ ## The label depends on the variant
19
+ In the round variant `aria-label` is essential — the button has no text. In `extended` the content
20
+ already is the label, so `aria-label` is dropped there rather than passed through: two names on one
21
+ control make a screen reader announce the wrong one.
22
+
23
+ ## Placement is yours
24
+ The component does not position itself. It is a button, not a layout — put it in a container that
25
+ pins it wherever the design wants (usually `position: fixed` in a corner).
26
+
27
+ ## Examples
28
+ <KptFab aria-label="Add"><KptIcon name="plus" /></KptFab>
29
+ <KptFab extended><KptIcon name="plus" /> New</KptFab>
30
+ <KptFab variant="tonal" size="mini" aria-label="Edit"><KptIcon name="copy" /></KptFab>
31
+
32
+ ## Tokens
33
+ `--kpt-color-primary` / `--kpt-color-on-primary` (filled), `--kpt-color-muted` /
34
+ `--kpt-color-on-muted` (tonal), `--kpt-elevation-3`, `--kpt-radius-full`.
35
+
36
+ ## Accessibility
37
+ A native `<button>`; in the round variant give it `aria-label`, in `extended` the text does the job.
@@ -0,0 +1,43 @@
1
+ # KptFieldset (@konce-pt/react)
2
+
3
+ A group of fields with a legend, optionally collapsible.
4
+ Import: `import { KptFieldset } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-fieldset-host" style="--kpt-anim-duration:500ms">
8
+ <fieldset class="kpt-fieldset">
9
+ <legend class="kpt-fieldset__legend">
10
+ <button class="kpt-fieldset__toggle" aria-expanded="true">…<span>Personal data</span></button>
11
+ </legend>
12
+ <div class="kpt-fieldset__collapse is-open">
13
+ <div class="kpt-fieldset__collapse-inner"><div class="kpt-fieldset__body">…</div></div>
14
+ </div>
15
+ </fieldset>
16
+ </div>
17
+
18
+ ## Props
19
+ - `legend`: string
20
+ - `toggleable`: boolean — turns the legend into a collapse button
21
+ - `collapsed` / `defaultCollapsed` / `onCollapsedChange`
22
+ - `animated`: boolean (default true), `animationDuration`: ms (default 500)
23
+ - `className`, `ref` and every other `<div>` prop go to the host
24
+
25
+ ## Collapsing without measuring
26
+ The transition runs on `grid-template-rows: 0fr → 1fr`, so it animates to the content's natural
27
+ height with no JS measurement and no height cached at mount — content that grows later still
28
+ collapses correctly.
29
+
30
+ ## The real fieldset stays
31
+ The markup is a native `<fieldset>` + `<legend>`, so the grouping is real for assistive tech;
32
+ the collapse only wraps the body, never the legend.
33
+
34
+ ## Examples
35
+ <KptFieldset legend="Personal data" toggleable>…</KptFieldset>
36
+ <KptFieldset legend="Advanced" toggleable collapsed={closed} onCollapsedChange={setClosed}>…</KptFieldset>
37
+
38
+ ## Tokens
39
+ Border `--kpt-color-border`, radius `--kpt-radius-md`, padding `--kpt-space-4`.
40
+
41
+ ## Accessibility
42
+ The toggle carries `aria-expanded`; the collapsed body gets `inert` and `aria-hidden`, so it is
43
+ out of the tab order and out of the accessibility tree.
@@ -0,0 +1,48 @@
1
+ # KptFileUpload (@konce-pt/react)
2
+
3
+ File upload: a zone that takes a click and a drop, plus the list of chosen files. The value is a
4
+ `File[]`.
5
+ Import: `import { KptFileUpload } from '@konce-pt/react';`
6
+
7
+ ## DOM
8
+ <div class="kpt-file-upload-host">
9
+ <div class="kpt-file-upload__zone is-dragover">
10
+ <input type="file" hidden>
11
+ <span class="kpt-icon-host kpt-file-upload__icon">…</span>
12
+ <div class="kpt-file-upload__text"><strong>Click</strong> or drag files here</div>
13
+ <div class="kpt-file-upload__hint">image/*</div>
14
+ </div>
15
+ <ul class="kpt-file-upload__list">
16
+ <li class="kpt-file-upload__file">…name, size, remove…</li>
17
+ </ul>
18
+ </div>
19
+
20
+ ## Props
21
+ - `value` / `defaultValue` / `onValueChange` — the `File[]`
22
+ - `accept`: string (e.g. `'image/*'`) — the native picker filter, also shown under the zone
23
+ - `multiple`: boolean — off, only the first file is kept
24
+ - `disabled`, `invalid`, `touched`, `onTouch()`
25
+ - `className`, `ref` and every other `<div>` prop go to the host
26
+
27
+ ## The input is cleared after every pick
28
+ `event.target.value = ''` after reading the files, otherwise picking the same file twice in a row
29
+ would fire no `change` and the second pick would be silently lost.
30
+
31
+ ## The hint carries markup
32
+ `fileUpload.hint` holds a `<strong>`, so it is rendered with `dangerouslySetInnerHTML` — the text
33
+ comes from the dictionary (ours or the app's), never from user input.
34
+
35
+ ## Examples
36
+ <KptFileUpload value={files} onValueChange={setFiles} accept="image/*" multiple />
37
+ <KptFileUpload value={files} onValueChange={setFiles} />
38
+
39
+ ## i18n
40
+ The zone hint and the remove label come from the `fileUpload` namespace; `locale` and `dictionary`
41
+ override them per instance.
42
+
43
+ ## Tokens
44
+ The zone `--kpt-form-field-border` (dashed), the dragover state `--kpt-color-primary`.
45
+
46
+ ## Accessibility
47
+ The remove button is labelled from the dictionary; the file input stays a real `<input type="file">`,
48
+ so the system picker and its keyboard path are untouched.
@@ -0,0 +1,55 @@
1
+ # KptFormField (@konce-pt/react)
2
+
3
+ A field container: label, hint, error message and the required flag around any control.
4
+ Import: `import { KptFormField } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-form-field-host">
8
+ <div class="kpt-form-field kpt-form-field--fixed">
9
+ <div class="kpt-form-field__box is-filled">
10
+ <label class="kpt-form-field__label" for="…">E-mail<span class="kpt-form-field__required">*</span></label>
11
+ <div class="kpt-form-field__control">…control…</div>
12
+ </div>
13
+ <p class="kpt-form-field__message kpt-form-field__message--hint">Company e-mail</p>
14
+ </div>
15
+ </div>
16
+
17
+ ## Props
18
+ - `label`: string — the label text
19
+ - `hint`: string — a hint under the control, hidden while there is an error
20
+ - `error`: string | null — when non-empty the field is marked invalid
21
+ - `required`: boolean — an asterisk next to the label
22
+ - `controlId`: string — empty means the wrapper generates one and hands it to the control
23
+ - `labelType`: 'fixed' | 'over' | 'in' | 'on' (default 'fixed')
24
+ - `className`, `ref` and every other `<div>` prop go to the host
25
+
26
+ ## Label wiring
27
+ The wrapper generates a control id and publishes it through context, so `<KptInput>` inside needs
28
+ no configuration — `label[for]` and `input[id]` always match. Pass `controlId` to take over.
29
+
30
+ ## Float labels
31
+ `labelType` other than `fixed` turns on the floating label with an animated transition: `over`
32
+ (above the border), `in` (top inside the field), `on` (on the border, notch). The label floats on
33
+ focus (CSS `:focus-within`) or when the field is filled — no placeholder required.
34
+
35
+ Filled state is read from the projected `input`/`textarea` on `input`/`change` and from the initial
36
+ value, so it works for controlled and uncontrolled fields alike. A control with no native field
37
+ reports it with `useKptFormFieldFilled(filled)`.
38
+
39
+ ## Examples
40
+ <KptFormField label="E-mail" hint="Company e-mail" error={err} required>
41
+ <KptInput type="email" name="email" placeholder="jan@firma.pl" />
42
+ </KptFormField>
43
+
44
+ <KptFormField label="Over Label" labelType="over">
45
+ <KptInput value={over} onValueChange={setOver} />
46
+ </KptFormField>
47
+
48
+ ## Tokens
49
+ `--kpt-form-field-{label,hint,error,border,border-focus,border-error,radius}` and
50
+ `--kpt-color-danger` for the required asterisk.
51
+
52
+ ## Accessibility
53
+ The error message carries `role="alert"`, so a screen reader announces it as it appears. The
54
+ asterisk is `aria-hidden` — the required state belongs on the control (`aria-required`), not on
55
+ decoration.
@@ -7,7 +7,7 @@ export interface KptGalleriaItem {
7
7
  alt?: string;
8
8
  }
9
9
  export interface KptGalleriaProps extends Omit<ComponentPropsWithRef<'div'>, 'onChange'>, KptI18nOverrides {
10
- items?: KptGalleriaItem[];
10
+ items?: readonly KptGalleriaItem[];
11
11
  activeIndex?: number;
12
12
  defaultActiveIndex?: number;
13
13
  onActiveIndexChange?: (index: number) => void;
@@ -0,0 +1,46 @@
1
+ # KptGalleria (@konce-pt/react)
2
+
3
+ A large image preview with a thumbnail strip and navigation.
4
+ Import: `import { KptGalleria, type KptGalleriaItem } from '@konce-pt/react';`
5
+
6
+ ## DOM
7
+ <div class="kpt-galleria-host">
8
+ <div class="kpt-galleria">
9
+ <div class="kpt-galleria__stage">
10
+ <button class="kpt-galleria__nav kpt-galleria__nav--prev">…</button>
11
+ <img class="kpt-galleria__image" src="…" alt="…">
12
+ <button class="kpt-galleria__nav kpt-galleria__nav--next">…</button>
13
+ </div>
14
+ <div class="kpt-galleria__thumbs">
15
+ <button class="kpt-galleria__thumb is-active"><img src="…"></button>…
16
+ </div>
17
+ </div>
18
+ </div>
19
+
20
+ ## Props
21
+ - `items`: `KptGalleriaItem[]` — `{ src, thumbnail?, alt? }`
22
+ - `activeIndex` / `defaultActiveIndex` / `onActiveIndexChange`
23
+ - `showThumbnails`: boolean (default true)
24
+ - `className`, `ref` and every other `<div>` prop go to the host
25
+
26
+ ## The thumbnail is optional
27
+ Without `thumbnail` the strip shows the scaled-down main image, so a gallery works with a single
28
+ URL per item; supply separate thumbnails when the originals are heavy.
29
+
30
+ ## An empty list renders the frame
31
+ `items[active]` falling outside the array renders no image rather than throwing, so a gallery whose
32
+ data is still loading shows the stage and the disabled arrows instead of crashing.
33
+
34
+ ## Examples
35
+ <KptGalleria items={photos} />
36
+ <KptGalleria items={photos} activeIndex={index} onActiveIndexChange={setIndex} showThumbnails={false} />
37
+
38
+ ## i18n
39
+ The arrows use `common.previous` / `common.next`, the thumbnails `galleria.image` (`{index}`).
40
+
41
+ ## Tokens
42
+ The stage `--kpt-color-muted`, the active thumbnail `--kpt-color-primary`.
43
+
44
+ ## Accessibility
45
+ Each thumbnail is a labelled button, and the arrows go dark at the ends; `alt` comes from the item,
46
+ so a photo without a description does not get a made-up one.
@@ -0,0 +1,110 @@
1
+ # KptGrid / KptCol / KptFlex (@konce-pt/react/grid)
2
+
3
+ React ergonomics over the `@konce-pt/grid` stylesheet. The components set nothing but inline custom
4
+ properties — they neither add nor remove classes, and the layout is computed by the native CSS
5
+ engine.
6
+
7
+ Import: `import { KptGrid, KptCol, KptFlex } from '@konce-pt/react/grid';`
8
+ Requires the stylesheet: `import '@konce-pt/grid';`
9
+
10
+ ## There are no directives in React
11
+ The Angular port ships `kptGrid` / `kptCol` / `kptFlex` as attribute directives, which add nothing
12
+ to the DOM. Here they are components, and `asChild` gives back the missing half: the props land on
13
+ the element you were rendering anyway, so a column can be an `<li>`, an `<article>` or another
14
+ component — no wrapper `<div>` in the middle of a grid.
15
+
16
+ ## Breakpoints (mobile-first)
17
+ `sm` >= 640px, `md` >= 768px, `lg` >= 1024px, `xl` >= 1280px, `2xl` >= 1536px.
18
+ A value applies from its breakpoint upward until the next one overrides it: `span={12} spanLg={5}`
19
+ gives 12 on mobile, `sm` and `md`, and 5 only from `lg` up.
20
+
21
+ ## KptGrid
22
+ Class `kpt-grid`. Renders a `<div>`, or the child with `asChild`.
23
+ - `columns`: number — the column count (12 by default, from CSS). Variants: `columnsSm`,
24
+ `columnsMd`, `columnsLg`, `columnsXl`, `columns2xl`
25
+ - `gap`: string — the gap on both axes, e.g. `'1.5rem'`, `'var(--kpt-space-6)'`
26
+ - `gapX`, `gapY`: string — the gap on one axis, overriding `gap`
27
+ - `container`: boolean — container query mode (see below)
28
+ - `className`, `style`, `ref` and every other `<div>` prop pass through; your `style` wins over the
29
+ generated variables
30
+
31
+ ## KptCol
32
+ No class of its own — only the variables.
33
+ - `span`: number | string — the span, the mobile-first base; `'full'` means the whole width
34
+ - `spanSm`, `spanMd`, `spanLg`, `spanXl`, `span2xl` — per-breakpoint overrides
35
+ - `start`: number — the grid line the column starts at (1-based); this is how offsets are done
36
+ - `order`: number — the visual order. It does not change the DOM: screen readers and keyboard
37
+ navigation follow the DOM, so do not use it to move interactive content around
38
+ - `self`: string — `align-self` (`start`, `end`, `center`, `stretch`, `baseline`)
39
+
40
+ ## KptFlex
41
+ Class `kpt-flex`. The same variables and breakpoints as the grid, in one dimension.
42
+ - `direction`: 'row' | 'row-reverse' | 'column' | 'column-reverse' (+ `directionMd`, `directionLg`)
43
+ - `wrap`: 'wrap' | 'nowrap' | 'wrap-reverse'
44
+ - `justify`, `align` (+ `justifyMd`, `alignMd`): `start` | `end` | `center` | `stretch` |
45
+ `baseline` | `space-between` | `space-around` | `space-evenly`
46
+ - `gap`, `gapX`, `gapY`: string
47
+ - `container`: boolean
48
+
49
+ Values with no matching prop are supplied with utility classes from `@konce-pt/grid`:
50
+ `kpt-grow-1`, `kpt-shrink-0`, `kpt-order-first`, `kpt-self-end`, `kpt-gap-6`.
51
+
52
+ ## An undefined prop sets nothing
53
+ A variable is written only when its prop has a value. Writing `--kpt-col: undefined` would override
54
+ what a utility class or the stylesheet already provides, so the components skip it entirely — the
55
+ same rule as the `?? null` in the Angular directives.
56
+
57
+ ## Container mode (`container`)
58
+ The children's spans react to the width of THIS grid instead of the window — a card in a narrow
59
+ sidebar lays itself out in a single column even though the viewport is wide.
60
+
61
+ A CSS limitation, not a package one: `@container` queries the nearest ancestor container, so an
62
+ element cannot query its own. What is responsive are the child's variables (span, start, order,
63
+ self); the column count and the gaps still follow the viewport.
64
+
65
+ ## Examples
66
+ <KptGrid>
67
+ <KptCol span={12} spanSm={6} spanMd={4}>Card</KptCol>
68
+ <KptCol span={12} spanSm={6} spanMd={4}>Card</KptCol>
69
+ <KptCol span={12} spanMd={4}>Card</KptCol>
70
+ </KptGrid>
71
+
72
+ {/* 18 columns with no SCSS recompilation */}
73
+ <KptGrid columns={18} gap="1.5rem">
74
+ <KptCol span={18} spanLg={5}>Sidebar</KptCol>
75
+ <KptCol span={18} spanLg={13}>Content</KptCol>
76
+ </KptGrid>
77
+
78
+ {/* an offset and a reordering on mobile */}
79
+ <KptGrid>
80
+ <KptCol span={6} start={4}>start 4, span 6</KptCol>
81
+ <KptCol span={12} spanMd={6} className="kpt-order-first kpt-order-md-none">second in the DOM</KptCol>
82
+ <KptCol span={12} spanMd={6}>first in the DOM</KptCol>
83
+ </KptGrid>
84
+
85
+ {/* no extra elements: the list items are the columns */}
86
+ <KptGrid asChild>
87
+ <ul>
88
+ <KptCol asChild span={12} spanMd={6}><li>First</li></KptCol>
89
+ <KptCol asChild span={12} spanMd={6}><li>Second</li></KptCol>
90
+ </ul>
91
+ </KptGrid>
92
+
93
+ {/* flexbox */}
94
+ <KptFlex direction="column" directionMd="row" justify="space-between" align="center" gap="1rem">
95
+ <span>Left</span>
96
+ <span>Right</span>
97
+ </KptFlex>
98
+
99
+ {/* a form layout (a CSS preset, no props on the children) */}
100
+ <form className="kpt-grid kpt-form-grid">
101
+ <KptFormField label="First name"><KptInput name="firstName" /></KptFormField>
102
+ <KptFormField label="Notes" className="kpt-col-md-12"><KptInput name="notes" /></KptFormField>
103
+ </form>
104
+
105
+ ## Custom properties
106
+ The grid: `--kpt-grid-columns`, `--kpt-gap`, `--kpt-gap-x`, `--kpt-gap-y`, `--kpt-justify`,
107
+ `--kpt-align`, `--kpt-content`, `--kpt-flex-direction`, `--kpt-flex-wrap`.
108
+ The child: `--kpt-col`, `--kpt-col-start`, `--kpt-order`, `--kpt-self`, `--kpt-flex`, `--kpt-grow`,
109
+ `--kpt-shrink`.
110
+ Each one has per-breakpoint variants: `--kpt-col` → `--kpt-col-md`.
@@ -1,11 +1,14 @@
1
+ import { type KptIconInput } from '@konce-pt/icons';
1
2
  /**
2
- * Rejestruje (lub nadpisuje) ikony: `{ nazwa: 'inner svg' }`.
3
+ * Rejestruje (lub nadpisuje) ikony. Przyjmuje listę definicji z subpathu Tablera
4
+ * (`[Rocket, LayoutDashboard]`), obiekt definicji (np. `import * as tabler`) albo
5
+ * mapę `{ nazwa: 'inner svg' }` — patrz [[KptIconInput]].
3
6
  *
4
7
  * Treść jest sanityzowana do allowlisty geometrii SVG — mimo to `registerKptIcons()` wolno
5
8
  * wołać wyłącznie z treścią kontrolowaną przez developera (build-time), nigdy bezpośrednio
6
9
  * z danych runtime/CMS/uploadu bez własnej walidacji domenowej wyżej w stosie.
7
10
  */
8
- export declare function registerKptIcons(next: Record<string, string>): void;
11
+ export declare function registerKptIcons(next: KptIconInput): void;
9
12
  /** Zwraca wewnętrzny SVG ikony lub `undefined`. */
10
13
  export declare function getKptIcon(name: string): string | undefined;
11
14
  /** Czy ikona o tej nazwie jest w rejestrze. */
@@ -1,4 +1,4 @@
1
- import { KPT_ICONS, sanitizeSvgFragment } from '@konce-pt/icons';
1
+ import { KPT_ICONS, sanitizeSvgFragment, toKptIconRecord } from '@konce-pt/icons';
2
2
  /*
3
3
  * Rejestr ikon dla `KptIcon`. Odpowiednik serwisu `KptIconRegistry` z portu Angulara,
4
4
  * ale jako moduł-singleton: ikony są globalne dla aplikacji, więc nie ma czego wstrzykiwać.
@@ -8,14 +8,16 @@ const icons = new Map(Object.entries(KPT_ICONS));
8
8
  const listeners = new Set();
9
9
  let version = 0;
10
10
  /**
11
- * Rejestruje (lub nadpisuje) ikony: `{ nazwa: 'inner svg' }`.
11
+ * Rejestruje (lub nadpisuje) ikony. Przyjmuje listę definicji z subpathu Tablera
12
+ * (`[Rocket, LayoutDashboard]`), obiekt definicji (np. `import * as tabler`) albo
13
+ * mapę `{ nazwa: 'inner svg' }` — patrz [[KptIconInput]].
12
14
  *
13
15
  * Treść jest sanityzowana do allowlisty geometrii SVG — mimo to `registerKptIcons()` wolno
14
16
  * wołać wyłącznie z treścią kontrolowaną przez developera (build-time), nigdy bezpośrednio
15
17
  * z danych runtime/CMS/uploadu bez własnej walidacji domenowej wyżej w stosie.
16
18
  */
17
19
  export function registerKptIcons(next) {
18
- for (const [name, svg] of Object.entries(next)) {
20
+ for (const [name, svg] of Object.entries(toKptIconRecord(next))) {
19
21
  icons.set(name, sanitizeSvgFragment(svg));
20
22
  }
21
23
  version += 1;