@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,48 @@
|
|
|
1
|
+
# KptMegamenu (@konce-pt/react)
|
|
2
|
+
|
|
3
|
+
A mega menu — a horizontal bar with a wide, multi-column panel.
|
|
4
|
+
Import: `import { KptMegamenu } from '@konce-pt/react';`
|
|
5
|
+
|
|
6
|
+
## DOM
|
|
7
|
+
<div class="kpt-megamenu-host">
|
|
8
|
+
<nav class="kpt-megamenu" role="menubar">
|
|
9
|
+
<button class="kpt-megamenu__top is-open" role="menuitem">Products …caret…</button>
|
|
10
|
+
</nav>
|
|
11
|
+
</div>
|
|
12
|
+
<!-- while open, in a portal: -->
|
|
13
|
+
<div class="kpt-megamenu__panel" role="menu">
|
|
14
|
+
<div class="kpt-megamenu__column">
|
|
15
|
+
<div class="kpt-megamenu__col-title">Components</div>
|
|
16
|
+
<button class="kpt-megamenu__link">Forms</button>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
## Props
|
|
21
|
+
- `items`: `KptMenuItem<T>[]` — three levels: top item → `items` (columns) → column `items` (links)
|
|
22
|
+
- `onSelect(link)` — a picked link from a column
|
|
23
|
+
- `className`, `ref` and every other `<div>` prop go to the host
|
|
24
|
+
|
|
25
|
+
## The panel is anchored to the whole bar
|
|
26
|
+
Not to the clicked button: the panel is wide, so it should start at the edge of the menu rather
|
|
27
|
+
than at whichever item happened to be pressed. Switching to another top item swaps the columns
|
|
28
|
+
without closing the panel, so browsing across sections costs one click each.
|
|
29
|
+
|
|
30
|
+
## Examples
|
|
31
|
+
<KptMegamenu items={items} onSelect={onSelect} />
|
|
32
|
+
|
|
33
|
+
// top → columns → links
|
|
34
|
+
const items: KptMenuItem[] = [{
|
|
35
|
+
label: 'Products',
|
|
36
|
+
items: [
|
|
37
|
+
{ label: 'Components', items: [{ label: 'Forms' }, { label: 'Tables' }] },
|
|
38
|
+
{ label: 'Templates', items: [{ label: 'Dashboard' }] },
|
|
39
|
+
],
|
|
40
|
+
}];
|
|
41
|
+
|
|
42
|
+
## Tokens
|
|
43
|
+
`--kpt-color-surface-raised`, `--kpt-color-border`, `--kpt-elevation-3`,
|
|
44
|
+
`--kpt-color-on-surface-muted` (the column titles).
|
|
45
|
+
|
|
46
|
+
## Accessibility
|
|
47
|
+
The bar is `role="menubar"` with `role="menuitem"` buttons; the panel is `role="menu"`. Column
|
|
48
|
+
titles are plain text, not headings, so they do not disturb the page outline.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ComponentPropsWithRef } from 'react';
|
|
2
2
|
import type { KptMenuItem } from '../menu/menu-item.ts';
|
|
3
3
|
export interface KptMegamenuProps<T> extends Omit<ComponentPropsWithRef<'div'>, 'onSelect'> {
|
|
4
|
-
items?: KptMenuItem<T>[];
|
|
4
|
+
items?: readonly KptMenuItem<T>[];
|
|
5
5
|
onSelect?: (item: KptMenuItem<T>) => void;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# KptMenu (@konce-pt/react)
|
|
2
|
+
|
|
3
|
+
A dropdown menu. Items come from `items`, the trigger from the `trigger` prop.
|
|
4
|
+
Import: `import { KptMenu, type KptMenuItem } from '@konce-pt/react';`
|
|
5
|
+
|
|
6
|
+
## DOM
|
|
7
|
+
<span class="kpt-menu-host"><span class="kpt-menu__trigger">…trigger…</span></span>
|
|
8
|
+
<!-- while open, in a portal on document.body: -->
|
|
9
|
+
<div class="kpt-menu__panel" role="menu">
|
|
10
|
+
<div class="kpt-menu__header" role="presentation">…</div>
|
|
11
|
+
<div class="kpt-menu__separator" role="separator"></div>
|
|
12
|
+
<button class="kpt-menu__item" role="menuitem">…</button>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
## Props
|
|
16
|
+
- `items`: `KptMenuItem<T>[]`
|
|
17
|
+
- `trigger`: ReactNode — the element that opens the menu, rendered in place
|
|
18
|
+
- `onSelect(item)` — the picked item; headers, separators and disabled items never arrive here
|
|
19
|
+
- `open` / `defaultOpen` / `onOpenChange` — controlled or uncontrolled
|
|
20
|
+
- `className`, `ref` and every other `<span>` prop go to the host
|
|
21
|
+
|
|
22
|
+
## KptMenuItem
|
|
23
|
+
`label`, `value`, `icon`, `description` (a second line), `badge` + `badgeVariant`,
|
|
24
|
+
`avatar` (`{ src?, name?, icon? }` — the header row of a user menu), `header` (a non-clickable
|
|
25
|
+
block instead of an item), `disabled`, `danger`, `separator`, plus `items` and `url` for the
|
|
26
|
+
menubar and megamenu that build on the same shape.
|
|
27
|
+
|
|
28
|
+
## The panel is a portal
|
|
29
|
+
It renders through the internal `KptOverlay`, so no overlay stylesheet is required — unlike the
|
|
30
|
+
Angular port, which stands on CDK. Position, backdrop and Escape behave the same.
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
<KptMenu items={items} onSelect={onSelect} trigger={<KptButton variant="outline">Options</KptButton>} />
|
|
34
|
+
|
|
35
|
+
const items: KptMenuItem[] = [
|
|
36
|
+
{ header: true, avatar: { src: '/u/admin.jpg' }, label: 'Admin', description: 'admin@konce.pt' },
|
|
37
|
+
{ separator: true },
|
|
38
|
+
{ label: 'Edit', value: 'edit', icon: 'copy' },
|
|
39
|
+
{ label: 'Notifications', value: 'notif', icon: 'bell', badge: 4, badgeVariant: 'success' },
|
|
40
|
+
{ separator: true },
|
|
41
|
+
{ label: 'Delete', value: 'del', icon: 'x', danger: true },
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
## Tokens
|
|
45
|
+
`--kpt-color-surface-raised`, `--kpt-color-border`, `--kpt-elevation-3`, `--kpt-color-danger`
|
|
46
|
+
(the `danger` item), `--kpt-z-overlay`.
|
|
47
|
+
|
|
48
|
+
## Accessibility
|
|
49
|
+
The panel is `role="menu"`, items are native buttons with `role="menuitem"`, separators carry
|
|
50
|
+
`role="separator"` and header rows `role="presentation"`, so a screen reader skips them instead of
|
|
51
|
+
announcing them as actions.
|
|
52
|
+
|
|
53
|
+
The trigger itself gets `aria-haspopup="menu"` and a live `aria-expanded`. They are placed on the
|
|
54
|
+
interactive control INSIDE the slot (the projected `<button>`/`<a>`), never on the
|
|
55
|
+
`.kpt-menu__trigger` wrapper — giving that wrapper a role would create a nested control and a second
|
|
56
|
+
tab stop, and state attributes on a roleless element violate `aria-allowed-attr`.
|
package/dist/menu/menu-item.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export interface KptMenuItem<T = unknown> {
|
|
|
27
27
|
danger?: boolean;
|
|
28
28
|
separator?: boolean;
|
|
29
29
|
/** Pozycje podrzędne (menubar / megamenu). */
|
|
30
|
-
items?: KptMenuItem<T>[];
|
|
30
|
+
items?: readonly KptMenuItem<T>[];
|
|
31
31
|
/** Adres odnośnika (menubar / megamenu). */
|
|
32
32
|
url?: string;
|
|
33
33
|
}
|
package/dist/menu/menu-rows.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import type { KptMenuItem } from './menu-item.ts';
|
|
3
3
|
export interface MenuRowsProps<T> {
|
|
4
|
-
items: KptMenuItem<T>[];
|
|
4
|
+
items: readonly KptMenuItem<T>[];
|
|
5
5
|
/** Prefiks bloku BEM: `kpt-menu` albo `kpt-context-menu`. */
|
|
6
6
|
block: string;
|
|
7
7
|
onPick: (item: KptMenuItem<T>) => void;
|
package/dist/menu/menu.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ComponentPropsWithRef, type ReactNode } from 'react';
|
|
2
2
|
import type { KptMenuItem } from './menu-item.ts';
|
|
3
3
|
export interface KptMenuProps<T> extends Omit<ComponentPropsWithRef<'span'>, 'onSelect'> {
|
|
4
|
-
items?: KptMenuItem<T>[];
|
|
4
|
+
items?: readonly KptMenuItem<T>[];
|
|
5
5
|
/** Element otwierający menu — renderowany w miejscu komponentu. */
|
|
6
6
|
trigger: ReactNode;
|
|
7
7
|
/** Wybrana pozycja; pozycje `header`, `separator` i wyłączone nigdy tu nie trafiają. */
|
package/dist/menu/menu.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useRef } from 'react';
|
|
2
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
3
3
|
import { cn } from "../internal/cn.js";
|
|
4
4
|
import { KptOverlay } from "../internal/overlay.js";
|
|
5
5
|
import { useControllableState } from "../internal/use-controllable-state.js";
|
|
@@ -21,6 +21,17 @@ export function KptMenu({ items = [], trigger, onSelect, open, defaultOpen = fal
|
|
|
21
21
|
onChange: onOpenChange,
|
|
22
22
|
});
|
|
23
23
|
const close = useCallback(() => setOpen(false), [setOpen]);
|
|
24
|
+
// ARIA idzie na kontrolkę wewnątrz slotu, nie na `.kpt-menu__trigger`. Trigger to zwykły
|
|
25
|
+
// `<span>` opakowujący dowolny węzeł z propa `trigger`: nadanie mu `role="button"` zrobiłoby
|
|
26
|
+
// zagnieżdżoną kontrolkę i drugi tab stop. `cloneElement` też odpada — `trigger` bywa
|
|
27
|
+
// komponentem, który nie przekazuje nieznanych propsów dalej na DOM.
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const control = triggerRef.current?.querySelector('button, a, [role="button"]');
|
|
30
|
+
if (!control)
|
|
31
|
+
return;
|
|
32
|
+
control.setAttribute('aria-haspopup', 'menu');
|
|
33
|
+
control.setAttribute('aria-expanded', String(isOpen));
|
|
34
|
+
}, [isOpen, trigger]);
|
|
24
35
|
const pick = (item) => {
|
|
25
36
|
if (item.disabled)
|
|
26
37
|
return;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# KptMenubar (@konce-pt/react)
|
|
2
|
+
|
|
3
|
+
A horizontal menu bar with dropdowns. An item without `items` acts as an action or a link.
|
|
4
|
+
Import: `import { KptMenubar } from '@konce-pt/react';`
|
|
5
|
+
|
|
6
|
+
## DOM
|
|
7
|
+
<div class="kpt-menubar-host">
|
|
8
|
+
<nav class="kpt-menubar" role="menubar">
|
|
9
|
+
<div class="kpt-menubar__group">
|
|
10
|
+
<button class="kpt-menubar__top is-open" role="menuitem">File …caret…</button>
|
|
11
|
+
</div>
|
|
12
|
+
</nav>
|
|
13
|
+
</div>
|
|
14
|
+
<!-- while open, in a portal: -->
|
|
15
|
+
<div class="kpt-menubar__dropdown" role="menu">…items and separators…</div>
|
|
16
|
+
|
|
17
|
+
## Props
|
|
18
|
+
- `items`: `KptMenuItem<T>[]` — a top item's `items` become its dropdown
|
|
19
|
+
- `onSelect(item)` — an action item, or a pick from a dropdown
|
|
20
|
+
- `className`, `ref` and every other `<div>` prop go to the host
|
|
21
|
+
|
|
22
|
+
## The dropdown is a portal
|
|
23
|
+
It renders outside the bar, so a parent with `overflow: hidden` cannot clip it — the same benefit
|
|
24
|
+
the Angular port gets from CDK Overlay, without CDK. Each dropdown is anchored to its own top
|
|
25
|
+
button, so it opens directly under the label it belongs to.
|
|
26
|
+
|
|
27
|
+
## Top items do double duty
|
|
28
|
+
With `items` a top item toggles its dropdown; without them it fires `onSelect` straight away, so a
|
|
29
|
+
bar can mix menus and plain actions with no extra flag.
|
|
30
|
+
|
|
31
|
+
## Examples
|
|
32
|
+
<KptMenubar items={items} onSelect={onSelect} />
|
|
33
|
+
|
|
34
|
+
const items: KptMenuItem[] = [
|
|
35
|
+
{ label: 'File', items: [{ label: 'New' }, { separator: true }, { label: 'Close', danger: true }] },
|
|
36
|
+
{ label: 'Help' },
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
## Tokens
|
|
40
|
+
`--kpt-color-surface`, `--kpt-color-muted` (the open top item), `--kpt-color-surface-raised` and
|
|
41
|
+
`--kpt-elevation-3` for the dropdown, `--kpt-color-danger`.
|
|
42
|
+
|
|
43
|
+
## Accessibility
|
|
44
|
+
The bar is `role="menubar"`, top items and dropdown rows are `role="menuitem"`, separators carry
|
|
45
|
+
`role="separator"`.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ComponentPropsWithRef } from 'react';
|
|
2
2
|
import type { KptMenuItem } from '../menu/menu-item.ts';
|
|
3
3
|
export interface KptMenubarProps<T> extends Omit<ComponentPropsWithRef<'div'>, 'onSelect'> {
|
|
4
|
-
items?: KptMenuItem<T>[];
|
|
4
|
+
items?: readonly KptMenuItem<T>[];
|
|
5
5
|
onSelect?: (item: KptMenuItem<T>) => void;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# KptMeterGroup (@konce-pt/react)
|
|
2
|
+
|
|
3
|
+
A multi-segment meter with an optional legend.
|
|
4
|
+
Import: `import { KptMeterGroup } from '@konce-pt/react';`
|
|
5
|
+
|
|
6
|
+
## DOM
|
|
7
|
+
<div class="kpt-meter-group-host">
|
|
8
|
+
<div class="kpt-meter-group">
|
|
9
|
+
<div class="kpt-meter-group__track" role="meter" aria-valuenow="100">
|
|
10
|
+
<span class="kpt-meter-group__segment" style="width:45%" title="Documents"></span>…
|
|
11
|
+
</div>
|
|
12
|
+
<ul class="kpt-meter-group__legend">
|
|
13
|
+
<li class="kpt-meter-group__legend-item">
|
|
14
|
+
<span class="kpt-meter-group__dot"></span><span>Documents</span>
|
|
15
|
+
<span class="kpt-meter-group__val">45%</span>
|
|
16
|
+
</li>…
|
|
17
|
+
</ul>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
## Props
|
|
22
|
+
- `values`: `KptMeterItem[]` — `{ label, value, color? }`
|
|
23
|
+
- `max`: number — the reference total; without it the values' sum is 100%
|
|
24
|
+
- `showLegend`: boolean (default true)
|
|
25
|
+
- `className`, `ref` and every other `<div>` prop go to the host
|
|
26
|
+
|
|
27
|
+
## Percentages come from the sum, not from 100
|
|
28
|
+
Without `max` the reference is the sum of the values, so `[45, 25, 15, 15]` and `[9, 5, 3, 3]`
|
|
29
|
+
draw the same picture. Pass `max` when the segments are meant to leave a gap — a quota that is
|
|
30
|
+
not full yet. All-zero values fall back to a divisor of 1 instead of producing `NaN%`.
|
|
31
|
+
|
|
32
|
+
## Colours
|
|
33
|
+
`color` per item, otherwise the next one from the semantic palette
|
|
34
|
+
(`primary → info → success → warning → danger`, cycled), so a group of any length stays readable
|
|
35
|
+
without picking colours by hand.
|
|
36
|
+
|
|
37
|
+
## Examples
|
|
38
|
+
<KptMeterGroup values={[{ label: 'Used', value: 70 }, { label: 'Free', value: 30 }]} />
|
|
39
|
+
<KptMeterGroup values={values} max={200} showLegend={false} />
|
|
40
|
+
|
|
41
|
+
## Tokens
|
|
42
|
+
The palette `--kpt-color-{primary,info,success,warning,danger}`, the track
|
|
43
|
+
`--kpt-color-surface-sunken`.
|
|
44
|
+
|
|
45
|
+
## Accessibility
|
|
46
|
+
The track is `role="meter"` with `aria-valuenow`; every segment carries a native `title`, and the
|
|
47
|
+
legend repeats the same values as text.
|
|
@@ -6,7 +6,7 @@ export interface KptMeterItem {
|
|
|
6
6
|
color?: string;
|
|
7
7
|
}
|
|
8
8
|
export interface KptMeterGroupProps extends ComponentPropsWithRef<'div'> {
|
|
9
|
-
values?: KptMeterItem[];
|
|
9
|
+
values?: readonly KptMeterItem[];
|
|
10
10
|
/** Suma odniesienia; domyślnie suma wartości, czyli segmenty wypełniają całość. */
|
|
11
11
|
max?: number;
|
|
12
12
|
showLegend?: boolean;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# KptOrderList (@konce-pt/react)
|
|
2
|
+
|
|
3
|
+
A list with manual reordering. Click selects an item, the buttons move it up and down.
|
|
4
|
+
Import: `import { KptOrderList } from '@konce-pt/react';`
|
|
5
|
+
|
|
6
|
+
## DOM
|
|
7
|
+
<div class="kpt-order-list-host">
|
|
8
|
+
<div class="kpt-order-list">
|
|
9
|
+
<div class="kpt-order-list__controls">…up, down…</div>
|
|
10
|
+
<div class="kpt-order-list__panel">
|
|
11
|
+
<div class="kpt-order-list__header">Order</div>
|
|
12
|
+
<ul class="kpt-order-list__items">
|
|
13
|
+
<li class="kpt-order-list__item is-selected">…</li>…
|
|
14
|
+
</ul>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
## Props
|
|
20
|
+
- `items` / `defaultItems` / `onItemsChange` — the list; the callback receives the new order
|
|
21
|
+
- `header`: string
|
|
22
|
+
- `renderItem(item, index)` — required; the equivalent of `<ng-template let-item>`
|
|
23
|
+
- `className`, `ref` and every other `<div>` prop go to the host
|
|
24
|
+
|
|
25
|
+
## The selection follows the item
|
|
26
|
+
After a move the selection jumps to the new index, so pressing the button again moves the same
|
|
27
|
+
entry — with the selection pinned to a position, the second press would move its neighbour.
|
|
28
|
+
|
|
29
|
+
## Examples
|
|
30
|
+
<KptOrderList items={tasks} onItemsChange={setTasks} header="Order" renderItem={(item) => item} />
|
|
31
|
+
<KptOrderList defaultItems={steps} renderItem={(step) => step.name} />
|
|
32
|
+
|
|
33
|
+
## i18n
|
|
34
|
+
The buttons use `orderList.up` and `orderList.down`.
|
|
35
|
+
|
|
36
|
+
## Tokens
|
|
37
|
+
The selection `--kpt-color-primary`, the buttons `--kpt-color-surface-raised`.
|
|
38
|
+
|
|
39
|
+
## Accessibility
|
|
40
|
+
Both buttons are labelled from the dictionary and go disabled while nothing is selected, so the
|
|
41
|
+
control never looks broken.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# KptPaginator (@konce-pt/react)
|
|
2
|
+
|
|
3
|
+
Page-size selector, item range and navigation.
|
|
4
|
+
Import: `import { KptPaginator } from '@konce-pt/react';`
|
|
5
|
+
|
|
6
|
+
## DOM
|
|
7
|
+
<div class="kpt-paginator">
|
|
8
|
+
<div class="kpt-paginator__size"><label>Rows: <select class="kpt-paginator__select">…</select></label></div>
|
|
9
|
+
<span class="kpt-paginator__range">1–10 of 120</span>
|
|
10
|
+
<div class="kpt-paginator__nav">…two KptButton…</div>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
## Props
|
|
14
|
+
- `length`: number — the total number of items (required)
|
|
15
|
+
- `pageIndex` / `defaultPageIndex` / `onPageIndexChange` — the 0-based page
|
|
16
|
+
- `pageSize` / `defaultPageSize` / `onPageSizeChange` — the page size (default 10)
|
|
17
|
+
- `pageSizeOptions`: readonly number[] (default [5, 10, 20, 50])
|
|
18
|
+
|
|
19
|
+
The select always offers the current `pageSize` even when it is absent from this list: without
|
|
20
|
+
that, `pageSize={8}` against the defaults left no matching option, so the control displayed the
|
|
21
|
+
first entry while the table paged by eight.
|
|
22
|
+
- `prevIcon`, `nextIcon`: ReactNode — the navigation button content
|
|
23
|
+
- `locale`, `dictionary` — i18n overrides for this component only
|
|
24
|
+
- `className`, `ref` and every other `<div>` prop go to the paginator root
|
|
25
|
+
|
|
26
|
+
## Behaviour
|
|
27
|
+
Works controlled and uncontrolled. Changing the page size returns to the first page. The index is
|
|
28
|
+
clamped whenever `length` or `pageSize` shrinks it out of range, so the component never shows an
|
|
29
|
+
empty page after the data changes underneath it.
|
|
30
|
+
|
|
31
|
+
## i18n
|
|
32
|
+
Labels come from the dictionary: `paginator.rowsPerPage`, `paginator.prevPage`,
|
|
33
|
+
`paginator.nextPage` and `paginator.range` with `{start}`, `{end}` and `{total}` interpolation.
|
|
34
|
+
|
|
35
|
+
## Icons
|
|
36
|
+
The default arrows are `KptIcon` with `chevron-left` / `chevron-right` from the built-in set, so
|
|
37
|
+
they work without registering the full Tabler set. Pass `prevIcon` / `nextIcon` to swap in your own.
|
|
38
|
+
|
|
39
|
+
## Examples
|
|
40
|
+
<KptPaginator length={120} pageIndex={page} onPageIndexChange={setPage} />
|
|
41
|
+
<KptPaginator length={total} defaultPageSize={20} pageSizeOptions={[20, 50, 100]} />
|
|
42
|
+
|
|
43
|
+
## Tokens
|
|
44
|
+
`--kpt-form-field-{bg,text,border,border-focus}` for the select, plus the button tokens.
|
|
45
|
+
|
|
46
|
+
## Accessibility
|
|
47
|
+
The navigation buttons carry `aria-label` from the dictionary and go `disabled` at the ends of the
|
|
48
|
+
range, so the keyboard never lands on a dead control.
|
|
@@ -12,7 +12,7 @@ export interface KptPaginatorProps extends Omit<ComponentPropsWithRef<'div'>, 'c
|
|
|
12
12
|
defaultPageIndex?: number;
|
|
13
13
|
onPageIndexChange?: (pageIndex: number) => void;
|
|
14
14
|
/** Dostępne rozmiary strony. */
|
|
15
|
-
pageSizeOptions?: number[];
|
|
15
|
+
pageSizeOptions?: readonly number[];
|
|
16
16
|
/** Treść przycisków nawigacji; domyślnie strzałki z wbudowanego zestawu ikon. */
|
|
17
17
|
prevIcon?: ReactNode;
|
|
18
18
|
nextIcon?: ReactNode;
|
|
@@ -41,5 +41,11 @@ export function KptPaginator({ length, pageSize, defaultPageSize = 10, onPageSiz
|
|
|
41
41
|
setSize(Number(event.target.value));
|
|
42
42
|
setIndex(0);
|
|
43
43
|
};
|
|
44
|
-
|
|
44
|
+
// Opcje selecta uzupełnione o bieżący rozmiar. Bez tego `pageSize` spoza listy nie ma
|
|
45
|
+
// odpowiadającej opcji: React ostrzega o `value` bez dopasowania, a select pokazuje
|
|
46
|
+
// pierwszą pozycję, choć stronicowanie idzie po zupełnie innej liczbie.
|
|
47
|
+
const sizeOptions = pageSizeOptions.includes(size)
|
|
48
|
+
? pageSizeOptions
|
|
49
|
+
: [...pageSizeOptions, size].sort((a, b) => a - b);
|
|
50
|
+
return (_jsxs("div", { className: cn('kpt-paginator', className), ...rest, children: [_jsx("div", { className: "kpt-paginator__size", children: _jsxs("label", { children: [t('paginator.rowsPerPage'), _jsx("select", { className: "kpt-paginator__select", value: size, onChange: onSizeChange, children: sizeOptions.map((option) => (_jsx("option", { value: option, children: option }, option))) })] }) }), _jsx("span", { className: "kpt-paginator__range", children: t('paginator.range', { start: rangeStart, end: rangeEnd, total: length }) }), _jsxs("div", { className: "kpt-paginator__nav", children: [_jsx(KptButton, { variant: "outline", size: "sm", disabled: !canPrev, onClick: () => setIndex(index - 1), "aria-label": t('paginator.prevPage'), children: prevIcon }), _jsx(KptButton, { variant: "outline", size: "sm", disabled: !canNext, onClick: () => setIndex(index + 1), "aria-label": t('paginator.nextPage'), children: nextIcon })] })] }));
|
|
45
51
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# KptPanel (@konce-pt/react)
|
|
2
|
+
|
|
3
|
+
A panel with a header and optional collapsing.
|
|
4
|
+
Import: `import { KptPanel } from '@konce-pt/react';`
|
|
5
|
+
|
|
6
|
+
## DOM
|
|
7
|
+
<div class="kpt-panel-host" style="--kpt-anim-duration: 500ms">
|
|
8
|
+
<div class="kpt-panel">
|
|
9
|
+
<div class="kpt-panel__header">
|
|
10
|
+
<span class="kpt-panel__title">Settings</span>
|
|
11
|
+
<span class="kpt-panel__actions">…actions…</span>
|
|
12
|
+
<button class="kpt-panel__toggle" aria-expanded="true" aria-label="Collapse / expand">…</button>
|
|
13
|
+
</div>
|
|
14
|
+
<div class="kpt-panel__collapse is-open">
|
|
15
|
+
<div class="kpt-panel__collapse-inner">
|
|
16
|
+
<div class="kpt-panel__body">…children…</div>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
## Props
|
|
23
|
+
- `header`: string
|
|
24
|
+
- `toggleable`: boolean — adds the collapse button to the header
|
|
25
|
+
- `collapsed` / `defaultCollapsed` / `onCollapsedChange` — controlled or uncontrolled
|
|
26
|
+
- `animated`: boolean (default true), `animationDuration`: number (ms, default 500)
|
|
27
|
+
- `locale`, `dictionary` — i18n overrides for this component only
|
|
28
|
+
- `className`, `ref` and every other `<div>` prop go to the host
|
|
29
|
+
|
|
30
|
+
## Sub-components
|
|
31
|
+
- `KptPanel.Actions` — lifted into the header, next to the title, before the collapse button.
|
|
32
|
+
|
|
33
|
+
## Collapsed content stays mounted
|
|
34
|
+
It gets `inert` and `aria-hidden` rather than being removed, so the height is animatable while
|
|
35
|
+
nothing inside can take focus or be read out. That is also why a collapsed panel keeps the state of
|
|
36
|
+
whatever lives in it — a half-filled form inside survives a collapse.
|
|
37
|
+
|
|
38
|
+
## i18n
|
|
39
|
+
The toggle's label comes from `panel.toggle` in the dictionary.
|
|
40
|
+
|
|
41
|
+
## Examples
|
|
42
|
+
<KptPanel header="Settings" toggleable>Panel content…</KptPanel>
|
|
43
|
+
|
|
44
|
+
<KptPanel header="Filters" toggleable collapsed={collapsed} onCollapsedChange={setCollapsed}>
|
|
45
|
+
<KptPanel.Actions><KptIconButton aria-label="Reset"><KptIcon name="x" /></KptIconButton></KptPanel.Actions>
|
|
46
|
+
…
|
|
47
|
+
</KptPanel>
|
|
48
|
+
|
|
49
|
+
## Tokens
|
|
50
|
+
`--kpt-color-surface`, `--kpt-color-border`, `--kpt-radius-lg`, `--kpt-motion-easing-standard`.
|
|
51
|
+
|
|
52
|
+
## Accessibility
|
|
53
|
+
The toggle is a native button with `aria-expanded` and a label from the dictionary. The header
|
|
54
|
+
title is a `<span>`, not a heading — give the panel your own heading when it needs one in the
|
|
55
|
+
document outline.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# KptPassword (@konce-pt/react)
|
|
2
|
+
|
|
3
|
+
A password field with a reveal toggle and an optional strength meter.
|
|
4
|
+
Import: `import { KptPassword } from '@konce-pt/react';`
|
|
5
|
+
|
|
6
|
+
## DOM
|
|
7
|
+
<div class="kpt-password-host">
|
|
8
|
+
<div class="kpt-password">
|
|
9
|
+
<input class="kpt-password__input" type="password" autocomplete="current-password">
|
|
10
|
+
<button class="kpt-password__toggle" type="button" aria-label="Show password">…</button>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="kpt-password__meter" data-score="3">
|
|
13
|
+
<div class="kpt-password__bars"><span class="kpt-password__bar is-on"></span>…</div>
|
|
14
|
+
<span class="kpt-password__hint">Good</span>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
## Props
|
|
19
|
+
- `value` / `defaultValue` / `onValueChange`
|
|
20
|
+
- `feedback`: boolean — shows the strength meter once something is typed
|
|
21
|
+
- `autoComplete`: string | null (default 'current-password')
|
|
22
|
+
- `placeholder`, `id`, `disabled`, `invalid`, `touched`, `onTouch()`
|
|
23
|
+
- `locale`, `dictionary` — i18n overrides for this component only
|
|
24
|
+
|
|
25
|
+
## autoComplete is not a detail
|
|
26
|
+
Sign-up and password reset need `autoComplete="new-password"`. With the default, a password manager
|
|
27
|
+
fills in the OLD password instead of offering a new one, and the user ends up saving the wrong
|
|
28
|
+
thing.
|
|
29
|
+
|
|
30
|
+
## How the score is computed
|
|
31
|
+
Four independent criteria, one point each: at least 8 characters, both letter cases, a digit, a
|
|
32
|
+
non-alphanumeric character. The label comes from `password.strength` — the only array-valued key in
|
|
33
|
+
the dictionary — indexed by the score, so a translation controls the wording without touching code.
|
|
34
|
+
|
|
35
|
+
## Examples
|
|
36
|
+
<KptPassword value={pass} onValueChange={setPass} feedback />
|
|
37
|
+
<KptPassword value={pass} onValueChange={setPass} autoComplete="new-password" feedback />
|
|
38
|
+
|
|
39
|
+
## Tokens
|
|
40
|
+
`--kpt-form-field-*` for the field, `--kpt-color-danger` / `-warning` / `-success` for the meter
|
|
41
|
+
bars by score.
|
|
42
|
+
|
|
43
|
+
## Accessibility
|
|
44
|
+
The toggle's label swaps between `password.show` and `password.hide`, so a screen reader knows what
|
|
45
|
+
pressing it will do rather than just that a button exists.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# KptPickList (@konce-pt/react)
|
|
2
|
+
|
|
3
|
+
Transfers items between two lists. Click to select, the middle buttons move the selection or
|
|
4
|
+
everything.
|
|
5
|
+
Import: `import { KptPickList } from '@konce-pt/react';`
|
|
6
|
+
|
|
7
|
+
## DOM
|
|
8
|
+
<div class="kpt-pick-list-host">
|
|
9
|
+
<div class="kpt-pick-list">
|
|
10
|
+
<div class="kpt-pick-list__col">
|
|
11
|
+
<div class="kpt-pick-list__header">Available</div>
|
|
12
|
+
<ul class="kpt-pick-list__items">
|
|
13
|
+
<li class="kpt-pick-list__item is-selected">…</li>…
|
|
14
|
+
</ul>
|
|
15
|
+
</div>
|
|
16
|
+
<div class="kpt-pick-list__controls">…four buttons…</div>
|
|
17
|
+
<div class="kpt-pick-list__col">…</div>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
## Props
|
|
22
|
+
- `source` / `defaultSource` / `onSourceChange` — the left list
|
|
23
|
+
- `target` / `defaultTarget` / `onTargetChange` — the right list
|
|
24
|
+
- `sourceHeader`, `targetHeader` — without them `pickList.available` / `pickList.selected`
|
|
25
|
+
- `renderItem(item, index)` — required; the equivalent of `<ng-template let-item>`
|
|
26
|
+
- `className`, `ref` and every other `<div>` prop go to the host
|
|
27
|
+
|
|
28
|
+
## The selection is kept by reference
|
|
29
|
+
Selected items live in a `Set` of references, not of indexes: after a move the indexes on both
|
|
30
|
+
sides shift, while a reference stays the same. That is also why a moved item never carries its
|
|
31
|
+
selection over — the selection is cleared on every move.
|
|
32
|
+
|
|
33
|
+
## Two lists, two controlled values
|
|
34
|
+
Both sides are independent controllable values, so the component works uncontrolled (`default*`),
|
|
35
|
+
half-controlled, or fully controlled by the form.
|
|
36
|
+
|
|
37
|
+
## Examples
|
|
38
|
+
<KptPickList
|
|
39
|
+
source={available} onSourceChange={setAvailable}
|
|
40
|
+
target={selected} onTargetChange={setSelected}
|
|
41
|
+
renderItem={(item) => item.name}
|
|
42
|
+
/>
|
|
43
|
+
|
|
44
|
+
## i18n
|
|
45
|
+
The headers and the four move buttons come from the `pickList` namespace.
|
|
46
|
+
|
|
47
|
+
## Tokens
|
|
48
|
+
The selection `--kpt-color-primary`, the headers `--kpt-color-surface-variant`.
|
|
49
|
+
|
|
50
|
+
## Accessibility
|
|
51
|
+
Every move button is labelled from the dictionary, so "move all right" is distinguishable from
|
|
52
|
+
"move right" without seeing the double chevron.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# KptPopover (@konce-pt/react)
|
|
2
|
+
|
|
3
|
+
Any content in a bubble pinned to its trigger — richer than a tooltip.
|
|
4
|
+
Import: `import { KptPopover } from '@konce-pt/react';`
|
|
5
|
+
|
|
6
|
+
## DOM
|
|
7
|
+
<span class="kpt-popover-host">
|
|
8
|
+
<span class="kpt-popover__trigger">…trigger…</span>
|
|
9
|
+
</span>
|
|
10
|
+
<!-- while open, in a portal on document.body: -->
|
|
11
|
+
<div class="kpt-popover__panel" role="dialog">…children…</div>
|
|
12
|
+
|
|
13
|
+
## Props
|
|
14
|
+
- `trigger`: ReactNode — the element that opens the bubble, rendered in place
|
|
15
|
+
- `children`: ReactNode — the panel content
|
|
16
|
+
- `open` / `defaultOpen` / `onOpenChange` — controlled or uncontrolled
|
|
17
|
+
- `className`, `ref` and every other `<span>` prop go to the host
|
|
18
|
+
|
|
19
|
+
## The panel is a portal
|
|
20
|
+
The Angular port stands on CDK Overlay. Here the panel renders into a portal on `document.body`
|
|
21
|
+
with the same behaviour: positioned below the trigger, flipping above when there is no room, closed
|
|
22
|
+
by a click outside or by Escape, and following scroll and resize.
|
|
23
|
+
|
|
24
|
+
Clicking the trigger while the bubble is open closes it and does not reopen it — the transparent
|
|
25
|
+
backdrop takes that click, exactly as the CDK backdrop does.
|
|
26
|
+
|
|
27
|
+
## Examples
|
|
28
|
+
<KptPopover trigger={<KptButton variant="outline">Details</KptButton>}>
|
|
29
|
+
<div>Richer content in the bubble.</div>
|
|
30
|
+
</KptPopover>
|
|
31
|
+
|
|
32
|
+
<KptPopover open={open} onOpenChange={setOpen} trigger={<KptButton>Filters</KptButton>}>
|
|
33
|
+
<FilterForm onDone={() => setOpen(false)} />
|
|
34
|
+
</KptPopover>
|
|
35
|
+
|
|
36
|
+
## Tokens
|
|
37
|
+
`--kpt-color-surface-raised`, `--kpt-color-border`, `--kpt-radius-md`, `--kpt-elevation-3`,
|
|
38
|
+
`--kpt-z-overlay`.
|
|
39
|
+
|
|
40
|
+
## Accessibility
|
|
41
|
+
The panel is `role="dialog"` and Escape closes it. Focus is not trapped — the popover is meant for
|
|
42
|
+
supporting content, so for a real modal reach for a dialog instead.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# KptProgress (@konce-pt/react)
|
|
2
|
+
|
|
3
|
+
A progress indicator — linear or circular, determinate (0–100) or indeterminate (`value` = null).
|
|
4
|
+
Import: `import { KptProgress } from '@konce-pt/react';`
|
|
5
|
+
|
|
6
|
+
## DOM
|
|
7
|
+
<!-- linear -->
|
|
8
|
+
<div class="kpt-progress-host">
|
|
9
|
+
<div class="kpt-progress__linear" data-variant="primary" role="progressbar" aria-valuenow="65">
|
|
10
|
+
<div class="kpt-progress__bar" style="width: 65%"></div>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<!-- circular -->
|
|
15
|
+
<svg class="kpt-progress__circular" data-variant="success" viewBox="0 0 40 40" role="progressbar" aria-valuenow="75">
|
|
16
|
+
<circle class="kpt-progress__track" cx="20" cy="20" r="16"></circle>
|
|
17
|
+
<circle class="kpt-progress__bar" cx="20" cy="20" r="16" style="stroke-dasharray: 100.531; stroke-dashoffset: 25.1327"></circle>
|
|
18
|
+
</svg>
|
|
19
|
+
|
|
20
|
+
## Props
|
|
21
|
+
- `value`: number | null (default null) — 0–100, or null for indeterminate
|
|
22
|
+
- `variant`: 'primary' | 'success' | 'danger' | 'warning' | 'info' (default 'primary')
|
|
23
|
+
- `type`: 'linear' | 'circular' (default 'linear')
|
|
24
|
+
- `diameter`: number (default 40) — the circular variant's size in pixels
|
|
25
|
+
- `className`, `ref` and every other `<div>` prop go to the host
|
|
26
|
+
|
|
27
|
+
## How the arc is drawn
|
|
28
|
+
The circle lives in a fixed `viewBox="0 0 40 40"` with `r=16`, so the circumference is computed
|
|
29
|
+
from that radius, not from `diameter` — the SVG scales, the maths does not change. The arc is the
|
|
30
|
+
dash offset: full circumference means empty, zero means complete. An indeterminate circle is pinned
|
|
31
|
+
at a quarter of the circumference and spun by CSS.
|
|
32
|
+
|
|
33
|
+
Values outside 0–100 are clamped rather than rejected, so a computed percentage that briefly
|
|
34
|
+
overshoots cannot break the drawing.
|
|
35
|
+
|
|
36
|
+
## Examples
|
|
37
|
+
<KptProgress value={65} />
|
|
38
|
+
<KptProgress value={null} variant="info" />
|
|
39
|
+
<KptProgress type="circular" value={75} variant="success" diameter={64} />
|
|
40
|
+
|
|
41
|
+
## Tokens
|
|
42
|
+
The semantic colour of each variant (`--kpt-color-primary` / `-success` / `-danger` / `-warning` /
|
|
43
|
+
`-info`), `--kpt-color-muted` for the track.
|
|
44
|
+
|
|
45
|
+
## Accessibility
|
|
46
|
+
`role="progressbar"` with `aria-valuenow`; an indeterminate bar leaves the value out, which is how
|
|
47
|
+
a screen reader learns the progress is unknown rather than zero.
|