@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.
- package/README.md +381 -27
- package/dist/accordion/llms.txt +56 -0
- package/dist/alert/llms.txt +45 -0
- package/dist/app-shell/app-shell.d.ts +20 -0
- package/dist/app-shell/app-shell.js +24 -0
- package/dist/app-shell/llms.txt +59 -0
- package/dist/auth/auth.d.ts +1 -1
- package/dist/auth/llms.txt +65 -0
- package/dist/autocomplete/autocomplete.d.ts +1 -1
- package/dist/autocomplete/llms.txt +44 -0
- package/dist/avatar/llms.txt +42 -0
- package/dist/avatar-group/avatar-group.d.ts +1 -1
- package/dist/avatar-group/llms.txt +38 -0
- package/dist/badge/llms.txt +38 -0
- package/dist/bottom-sheet/llms.txt +43 -0
- package/dist/breadcrumb/breadcrumb.d.ts +1 -1
- package/dist/breadcrumb/llms.txt +35 -0
- package/dist/button/llms.txt +56 -0
- package/dist/button-group/button-group.d.ts +1 -1
- package/dist/button-group/llms.txt +40 -0
- package/dist/card/llms.txt +60 -0
- package/dist/carousel/carousel.d.ts +1 -1
- package/dist/carousel/llms.txt +47 -0
- package/dist/charts/chart-legend.d.ts +1 -1
- package/dist/charts/llms.txt +57 -0
- package/dist/checkbox/llms.txt +39 -0
- package/dist/chip/llms.txt +41 -0
- package/dist/chips-input/llms.txt +40 -0
- package/dist/clock/llms.txt +50 -0
- package/dist/color-picker/color-picker.d.ts +1 -1
- package/dist/color-picker/llms.txt +40 -0
- package/dist/confirm/llms.txt +44 -0
- package/dist/context-menu/context-menu.d.ts +1 -1
- package/dist/context-menu/llms.txt +39 -0
- package/dist/data-table/data-table-types.d.ts +1 -1
- package/dist/data-table/data-table.d.ts +2 -10
- package/dist/data-table/data-table.js +17 -9
- package/dist/data-table/llms.txt +79 -0
- package/dist/data-view/data-view.d.ts +1 -1
- package/dist/data-view/llms.txt +49 -0
- package/dist/date-range/llms.txt +54 -0
- package/dist/datepicker/llms.txt +74 -0
- package/dist/dialog/llms.txt +51 -0
- package/dist/divider/llms.txt +28 -0
- package/dist/drawer/llms.txt +47 -0
- package/dist/empty/llms.txt +35 -0
- package/dist/fab/llms.txt +37 -0
- package/dist/fieldset/llms.txt +43 -0
- package/dist/file-upload/llms.txt +48 -0
- package/dist/form-field/llms.txt +55 -0
- package/dist/galleria/galleria.d.ts +1 -1
- package/dist/galleria/llms.txt +46 -0
- package/dist/grid/llms.txt +110 -0
- package/dist/icon/icon-registry.d.ts +5 -2
- package/dist/icon/icon-registry.js +5 -3
- package/dist/icon/llms.txt +66 -0
- package/dist/icon-button/llms.txt +38 -0
- package/dist/icons-entry/public-api.d.ts +5 -1
- package/dist/icons-entry/public-api.js +7 -1
- package/dist/image/llms.txt +46 -0
- package/dist/input/llms.txt +54 -0
- package/dist/input-mask/llms.txt +37 -0
- package/dist/input-number/llms.txt +44 -0
- package/dist/input-otp/llms.txt +43 -0
- package/dist/internal/use-breakpoint.js +18 -10
- package/dist/knob/llms.txt +46 -0
- package/dist/listbox/listbox.d.ts +1 -1
- package/dist/listbox/llms.txt +39 -0
- package/dist/map/llms.txt +108 -0
- package/dist/megamenu/llms.txt +48 -0
- package/dist/megamenu/megamenu.d.ts +1 -1
- package/dist/menu/llms.txt +56 -0
- package/dist/menu/menu-item.d.ts +1 -1
- package/dist/menu/menu-rows.d.ts +1 -1
- package/dist/menu/menu.d.ts +1 -1
- package/dist/menu/menu.js +12 -1
- package/dist/menubar/llms.txt +45 -0
- package/dist/menubar/menubar.d.ts +1 -1
- package/dist/meter-group/llms.txt +47 -0
- package/dist/meter-group/meter-group.d.ts +1 -1
- package/dist/order-list/llms.txt +41 -0
- package/dist/paginator/llms.txt +48 -0
- package/dist/paginator/paginator.d.ts +1 -1
- package/dist/paginator/paginator.js +7 -1
- package/dist/panel/llms.txt +55 -0
- package/dist/password/llms.txt +45 -0
- package/dist/pick-list/llms.txt +52 -0
- package/dist/popover/llms.txt +42 -0
- package/dist/progress/llms.txt +47 -0
- package/dist/public-api.d.ts +2 -1
- package/dist/public-api.js +1 -1
- package/dist/radio-group/llms.txt +40 -0
- package/dist/radio-group/radio-group.d.ts +1 -1
- package/dist/rating/llms.txt +43 -0
- package/dist/rich-text/llms.txt +61 -0
- package/dist/rich-text/rich-text.d.ts +1 -1
- package/dist/roadmap/llms.txt +82 -0
- package/dist/scroll-top/llms.txt +41 -0
- package/dist/select/llms.txt +56 -0
- package/dist/select/select.d.ts +1 -1
- package/dist/sidenav/llms.txt +53 -0
- package/dist/skeleton/llms.txt +33 -0
- package/dist/slider/llms.txt +50 -0
- package/dist/speed-dial/llms.txt +46 -0
- package/dist/speed-dial/speed-dial.d.ts +1 -1
- package/dist/spinner/llms.txt +33 -0
- package/dist/split-button/llms.txt +54 -0
- package/dist/split-button/split-button.d.ts +1 -1
- package/dist/splitter/llms.txt +44 -0
- package/dist/stepper/llms.txt +64 -0
- package/dist/switch/llms.txt +42 -0
- package/dist/switch-group/llms.txt +43 -0
- package/dist/switch-group/switch-group.d.ts +1 -1
- package/dist/tabs/llms.txt +48 -0
- package/dist/textarea/llms.txt +40 -0
- package/dist/timeline/llms.txt +53 -0
- package/dist/timeline/timeline.d.ts +1 -1
- package/dist/toast/llms.txt +52 -0
- package/dist/toolbar/llms.txt +45 -0
- package/dist/tooltip/llms.txt +42 -0
- package/dist/tree/llms.txt +45 -0
- package/dist/tree/tree.d.ts +2 -2
- 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
|
|
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:
|
|
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
|
|
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;
|