@stridge/noctis 1.0.0-beta.3 → 1.0.0-beta.5
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/dist/components/avatar/avatar.d.ts +2 -2
- package/dist/components/avatar/avatar.js +1 -1
- package/dist/components/avatar/avatar.props.d.ts +1 -1
- package/dist/components/avatar/avatar.slots.d.ts +1 -1
- package/dist/components/avatar/avatar.slots.js +1 -1
- package/dist/components/badge/badge.d.ts +114 -0
- package/dist/components/badge/badge.js +74 -0
- package/dist/components/badge/badge.props.d.ts +42 -0
- package/dist/components/badge/badge.props.js +42 -0
- package/dist/components/badge/badge.slots.d.ts +19 -0
- package/dist/components/badge/badge.slots.js +30 -0
- package/dist/components/badge/badge.types.d.ts +24 -0
- package/dist/components/badge/index.d.ts +3 -0
- package/dist/components/pagination/index.d.ts +3 -0
- package/dist/components/pagination/pagination.context.js +16 -0
- package/dist/components/pagination/pagination.d.ts +217 -0
- package/dist/components/pagination/pagination.js +333 -0
- package/dist/components/pagination/pagination.props.d.ts +51 -0
- package/dist/components/pagination/pagination.props.js +49 -0
- package/dist/components/pagination/pagination.slots.d.ts +16 -0
- package/dist/components/pagination/pagination.slots.js +32 -0
- package/dist/components/pagination/pagination.types.d.ts +24 -0
- package/dist/icons/glyphs.js +2 -2
- package/dist/index.d.ts +7 -1
- package/dist/index.js +5 -1
- package/dist/props.d.ts +31 -29
- package/dist/props.js +31 -29
- package/dist/styles.css +560 -40
- package/dist/tailwind.css +11 -11
- package/package.json +4 -4
|
@@ -38,7 +38,7 @@ declare function AvatarImage({
|
|
|
38
38
|
}: Avatar.Image.Props): ReactElement;
|
|
39
39
|
/**
|
|
40
40
|
* Shown when no image loads — initials or a glyph on a static, accent-independent swatch. Pass `seed`
|
|
41
|
-
* (a user id, name, or email) to hash a stable `bg-
|
|
41
|
+
* (a user id, name, or email) to hash a stable `bg-palette-N` colour, so the same person always gets the
|
|
42
42
|
* same hue; omit it for the neutral muted fill. Base UI handles the `delay` before it appears.
|
|
43
43
|
*/
|
|
44
44
|
declare function AvatarFallback({
|
|
@@ -182,7 +182,7 @@ declare namespace Avatar {
|
|
|
182
182
|
}
|
|
183
183
|
namespace Fallback {
|
|
184
184
|
type Props = avatar_d_exports.Avatar.Fallback.Props & {
|
|
185
|
-
/** A stable identifier hashed to one of ten `bg-
|
|
185
|
+
/** A stable identifier hashed to one of ten `bg-palette-N` swatches; omit for the neutral muted fill. */seed?: string;
|
|
186
186
|
};
|
|
187
187
|
type State = avatar_d_exports.Avatar.Fallback.State;
|
|
188
188
|
/** Argument to the `Avatar.Fallback.props(...)` escape-hatch helper. */
|
|
@@ -72,7 +72,7 @@ function AvatarImage({ onLoadingStatusChange, className, ...props }) {
|
|
|
72
72
|
}
|
|
73
73
|
/**
|
|
74
74
|
* Shown when no image loads — initials or a glyph on a static, accent-independent swatch. Pass `seed`
|
|
75
|
-
* (a user id, name, or email) to hash a stable `bg-
|
|
75
|
+
* (a user id, name, or email) to hash a stable `bg-palette-N` colour, so the same person always gets the
|
|
76
76
|
* same hue; omit it for the neutral muted fill. Base UI handles the `delay` before it appears.
|
|
77
77
|
*/
|
|
78
78
|
function AvatarFallback({ seed, className, children, ...props }) {
|
|
@@ -28,7 +28,7 @@ type AvatarStatelessPropsArgs = BasePropsArgs;
|
|
|
28
28
|
/** Argument to `Avatar.Fallback.props(...)` — the seed that selects the static swatch the fill reads. */
|
|
29
29
|
interface AvatarFallbackPropsArgs extends BasePropsArgs {
|
|
30
30
|
/**
|
|
31
|
-
* A stable identifier (a user id, name, or email) hashed to one of the ten `bg-
|
|
31
|
+
* A stable identifier (a user id, name, or email) hashed to one of the ten `bg-palette-N` swatches,
|
|
32
32
|
* so the same person always lands on the same colour. Omit to fall back to the neutral muted fill.
|
|
33
33
|
*/
|
|
34
34
|
seed?: string;
|
|
@@ -16,7 +16,7 @@ declare enum AvatarDataAttributes {
|
|
|
16
16
|
size = "data-size",
|
|
17
17
|
/** The shape — `circle` (default, fully round) | `rounded` (rounded corners). */
|
|
18
18
|
shape = "data-shape",
|
|
19
|
-
/** `1`–`10`, the stable hashed swatch index the fallback fill reads its `bg-
|
|
19
|
+
/** `1`–`10`, the stable hashed swatch index the fallback fill reads its `bg-palette-N` role from. */
|
|
20
20
|
avatarIndex = "data-avatar-index",
|
|
21
21
|
/** Present when the avatar is dimmed/inactive — gates interactive states and applies the disabled opacity. */
|
|
22
22
|
disabled = "data-disabled",
|
|
@@ -29,7 +29,7 @@ let AvatarDataAttributes = /* @__PURE__ */ function(AvatarDataAttributes) {
|
|
|
29
29
|
AvatarDataAttributes["size"] = "data-size";
|
|
30
30
|
/** The shape — `circle` (default, fully round) | `rounded` (rounded corners). */
|
|
31
31
|
AvatarDataAttributes["shape"] = "data-shape";
|
|
32
|
-
/** `1`–`10`, the stable hashed swatch index the fallback fill reads its `bg-
|
|
32
|
+
/** `1`–`10`, the stable hashed swatch index the fallback fill reads its `bg-palette-N` role from. */
|
|
33
33
|
AvatarDataAttributes["avatarIndex"] = "data-avatar-index";
|
|
34
34
|
/** Present when the avatar is dimmed/inactive — gates interactive states and applies the disabled opacity. */
|
|
35
35
|
AvatarDataAttributes["disabled"] = "data-disabled";
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { BadgeSize, BadgeTone, BadgeVariant } from "./badge.types.js";
|
|
2
|
+
import { BadgePartProps, BadgeRootPropsArgs, BadgeStatelessPropsArgs, dotProps, iconProps, rootProps } from "./badge.props.js";
|
|
3
|
+
import { ComponentProps, ReactElement } from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/components/badge/badge.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* A small label for status, categorization, or metadata — a pill chip that sits inline with text or in
|
|
8
|
+
* a row of its own. The look is two orthogonal axes: `variant` is the emphasis (a filled `solid`, a
|
|
9
|
+
* quiet `soft` tint, or a transparent `outline`) and `tone` is the colour identity (the six semantic
|
|
10
|
+
* tones — `neutral`/`accent` and the four statuses — plus eight accent-independent decorative hues for
|
|
11
|
+
* categorization). Compose a leading `Badge.Dot` for an at-a-glance status dot or a `Badge.Icon` for a
|
|
12
|
+
* glyph; both inherit the chip's text colour so they stay legible in every variant.
|
|
13
|
+
*
|
|
14
|
+
* Decorative and accent-independent: the styling is precompiled CSS keyed off the `data-slot` anchor
|
|
15
|
+
* (`badge.css`), and the colour grid reads the semantic roles and the shared categorical palette directly, so a
|
|
16
|
+
* retheme propagates and a categorical tone never re-derives off the accent. Renders a `<span>` by
|
|
17
|
+
* default; spread `Badge.Root.props(...)` onto an `<a>` (or any element) to style it as a chip.
|
|
18
|
+
*
|
|
19
|
+
* @see {@link Badge.Root.Props}
|
|
20
|
+
*/
|
|
21
|
+
declare function BadgeRoot({
|
|
22
|
+
variant,
|
|
23
|
+
tone,
|
|
24
|
+
size,
|
|
25
|
+
className,
|
|
26
|
+
...props
|
|
27
|
+
}: Badge.Root.Props): ReactElement;
|
|
28
|
+
/**
|
|
29
|
+
* An optional leading status dot. Decorative by default (`aria-hidden`) — the chip's label carries the
|
|
30
|
+
* meaning — so it is never a colour-only signal; pair a label like "Online" with it. Fills with the
|
|
31
|
+
* chip's `currentColor`, so it reads as a knockout on a `solid` chip and as the saturated tone on a
|
|
32
|
+
* `soft`/`outline` one.
|
|
33
|
+
*/
|
|
34
|
+
declare function BadgeDot({
|
|
35
|
+
className,
|
|
36
|
+
...props
|
|
37
|
+
}: Badge.Dot.Props): ReactElement;
|
|
38
|
+
/**
|
|
39
|
+
* An optional leading icon. Clamps its glyph to the chip's icon size and inherits the chip's text
|
|
40
|
+
* colour. Decorative by default (`aria-hidden`); wrap an `<Icon>` or any inline svg inside it — don't
|
|
41
|
+
* put `data-slot` on the icon itself, which would drop its own token sizing.
|
|
42
|
+
*/
|
|
43
|
+
declare function BadgeIcon({
|
|
44
|
+
className,
|
|
45
|
+
children,
|
|
46
|
+
...props
|
|
47
|
+
}: Badge.Icon.Props): ReactElement;
|
|
48
|
+
/**
|
|
49
|
+
* A small status/label chip. `Badge.Root` owns the pill and its `variant` (emphasis) + `tone` (colour)
|
|
50
|
+
* + `size`; compose a leading `Badge.Dot` (a status dot) or `Badge.Icon` (a glyph) before the label.
|
|
51
|
+
*
|
|
52
|
+
* The runtime compound is a plain object (kept tree-shakeable); per-part prop types are exposed through
|
|
53
|
+
* the matching `Badge` namespace — e.g. `Badge.Root.Props`.
|
|
54
|
+
*/
|
|
55
|
+
declare const Badge: {
|
|
56
|
+
/** Owns the pill + its variant/tone/size. `Badge.Root.props({ variant, tone, size })` → its prop bag. */Root: typeof BadgeRoot & {
|
|
57
|
+
props: typeof rootProps;
|
|
58
|
+
}; /** A leading status dot (decorative). `Badge.Dot.props()` → its spreadable prop bag. */
|
|
59
|
+
Dot: typeof BadgeDot & {
|
|
60
|
+
props: typeof dotProps;
|
|
61
|
+
}; /** A leading icon glyph (decorative). `Badge.Icon.props()` → its spreadable prop bag. */
|
|
62
|
+
Icon: typeof BadgeIcon & {
|
|
63
|
+
props: typeof iconProps;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Per-part prop types. Types-only — it emits no runtime code and merges with the `Badge` object above,
|
|
68
|
+
* so `Badge.Root` is the component value while `Badge.Root.Props` is its prop type.
|
|
69
|
+
*/
|
|
70
|
+
declare namespace Badge {
|
|
71
|
+
/** Emphasis axis — `solid` | `soft` | `outline`. */
|
|
72
|
+
type Variant = BadgeVariant;
|
|
73
|
+
/** Colour identity — a semantic tone or a decorative hue. */
|
|
74
|
+
type Tone = BadgeTone;
|
|
75
|
+
/** Chip scale — `sm` | `md`. */
|
|
76
|
+
type Size = BadgeSize;
|
|
77
|
+
/** The spreadable data-attribute prop bag every `Badge.*.props()` returns (D12). */
|
|
78
|
+
type PartProps = BadgePartProps;
|
|
79
|
+
namespace Root {
|
|
80
|
+
type Props = ComponentProps<"span"> & {
|
|
81
|
+
/**
|
|
82
|
+
* Emphasis — a filled `solid` chip, a quiet `soft` tint, a transparent `outline`, or a
|
|
83
|
+
* neutral `dot` chip whose only colour is its leading `Badge.Dot`.
|
|
84
|
+
* @default "soft"
|
|
85
|
+
*/
|
|
86
|
+
variant?: BadgeVariant;
|
|
87
|
+
/**
|
|
88
|
+
* Colour identity — a semantic tone (`neutral`/`accent`/`success`/`warning`/`danger`/`info`)
|
|
89
|
+
* or a decorative hue (`red`…`pink`) for categorization.
|
|
90
|
+
* @default "neutral"
|
|
91
|
+
*/
|
|
92
|
+
tone?: BadgeTone;
|
|
93
|
+
/**
|
|
94
|
+
* Chip scale.
|
|
95
|
+
* @default "md"
|
|
96
|
+
*/
|
|
97
|
+
size?: BadgeSize;
|
|
98
|
+
};
|
|
99
|
+
/** Argument to the `Badge.Root.props(...)` escape-hatch helper. */
|
|
100
|
+
type PropsArgs = BadgeRootPropsArgs;
|
|
101
|
+
}
|
|
102
|
+
namespace Dot {
|
|
103
|
+
type Props = ComponentProps<"span">;
|
|
104
|
+
/** Argument to the `Badge.Dot.props(...)` escape-hatch helper. */
|
|
105
|
+
type PropsArgs = BadgeStatelessPropsArgs;
|
|
106
|
+
}
|
|
107
|
+
namespace Icon {
|
|
108
|
+
type Props = ComponentProps<"span">;
|
|
109
|
+
/** Argument to the `Badge.Icon.props(...)` escape-hatch helper. */
|
|
110
|
+
type PropsArgs = BadgeStatelessPropsArgs;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
export { Badge };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { BADGE_SLOTS } from "./badge.slots.js";
|
|
2
|
+
import { dotProps, iconProps, rootProps } from "./badge.props.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/badge/badge.tsx
|
|
5
|
+
/**
|
|
6
|
+
* A small label for status, categorization, or metadata — a pill chip that sits inline with text or in
|
|
7
|
+
* a row of its own. The look is two orthogonal axes: `variant` is the emphasis (a filled `solid`, a
|
|
8
|
+
* quiet `soft` tint, or a transparent `outline`) and `tone` is the colour identity (the six semantic
|
|
9
|
+
* tones — `neutral`/`accent` and the four statuses — plus eight accent-independent decorative hues for
|
|
10
|
+
* categorization). Compose a leading `Badge.Dot` for an at-a-glance status dot or a `Badge.Icon` for a
|
|
11
|
+
* glyph; both inherit the chip's text colour so they stay legible in every variant.
|
|
12
|
+
*
|
|
13
|
+
* Decorative and accent-independent: the styling is precompiled CSS keyed off the `data-slot` anchor
|
|
14
|
+
* (`badge.css`), and the colour grid reads the semantic roles and the shared categorical palette directly, so a
|
|
15
|
+
* retheme propagates and a categorical tone never re-derives off the accent. Renders a `<span>` by
|
|
16
|
+
* default; spread `Badge.Root.props(...)` onto an `<a>` (or any element) to style it as a chip.
|
|
17
|
+
*
|
|
18
|
+
* @see {@link Badge.Root.Props}
|
|
19
|
+
*/
|
|
20
|
+
function BadgeRoot({ variant = "soft", tone = "neutral", size = "md", className, ...props }) {
|
|
21
|
+
return /* @__PURE__ */ jsx("span", {
|
|
22
|
+
"data-slot": BADGE_SLOTS.root,
|
|
23
|
+
"data-variant": variant,
|
|
24
|
+
"data-tone": tone,
|
|
25
|
+
"data-size": size,
|
|
26
|
+
className,
|
|
27
|
+
...props
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* An optional leading status dot. Decorative by default (`aria-hidden`) — the chip's label carries the
|
|
32
|
+
* meaning — so it is never a colour-only signal; pair a label like "Online" with it. Fills with the
|
|
33
|
+
* chip's `currentColor`, so it reads as a knockout on a `solid` chip and as the saturated tone on a
|
|
34
|
+
* `soft`/`outline` one.
|
|
35
|
+
*/
|
|
36
|
+
function BadgeDot({ className, ...props }) {
|
|
37
|
+
return /* @__PURE__ */ jsx("span", {
|
|
38
|
+
"data-slot": BADGE_SLOTS.dot,
|
|
39
|
+
"aria-hidden": true,
|
|
40
|
+
className,
|
|
41
|
+
...props
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* An optional leading icon. Clamps its glyph to the chip's icon size and inherits the chip's text
|
|
46
|
+
* colour. Decorative by default (`aria-hidden`); wrap an `<Icon>` or any inline svg inside it — don't
|
|
47
|
+
* put `data-slot` on the icon itself, which would drop its own token sizing.
|
|
48
|
+
*/
|
|
49
|
+
function BadgeIcon({ className, children, ...props }) {
|
|
50
|
+
return /* @__PURE__ */ jsx("span", {
|
|
51
|
+
"data-slot": BADGE_SLOTS.icon,
|
|
52
|
+
"aria-hidden": true,
|
|
53
|
+
className,
|
|
54
|
+
...props,
|
|
55
|
+
children
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A small status/label chip. `Badge.Root` owns the pill and its `variant` (emphasis) + `tone` (colour)
|
|
60
|
+
* + `size`; compose a leading `Badge.Dot` (a status dot) or `Badge.Icon` (a glyph) before the label.
|
|
61
|
+
*
|
|
62
|
+
* The runtime compound is a plain object (kept tree-shakeable); per-part prop types are exposed through
|
|
63
|
+
* the matching `Badge` namespace — e.g. `Badge.Root.Props`.
|
|
64
|
+
*/
|
|
65
|
+
const Badge = {
|
|
66
|
+
/** Owns the pill + its variant/tone/size. `Badge.Root.props({ variant, tone, size })` → its prop bag. */
|
|
67
|
+
Root: Object.assign(BadgeRoot, { props: rootProps }),
|
|
68
|
+
/** A leading status dot (decorative). `Badge.Dot.props()` → its spreadable prop bag. */
|
|
69
|
+
Dot: Object.assign(BadgeDot, { props: dotProps }),
|
|
70
|
+
/** A leading icon glyph (decorative). `Badge.Icon.props()` → its spreadable prop bag. */
|
|
71
|
+
Icon: Object.assign(BadgeIcon, { props: iconProps })
|
|
72
|
+
};
|
|
73
|
+
//#endregion
|
|
74
|
+
export { Badge };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { BadgeSize, BadgeTone, BadgeVariant } from "./badge.types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/components/badge/badge.props.d.ts
|
|
4
|
+
/** A spreadable data-attribute prop bag — the shape every `Badge.*.props()` returns. */
|
|
5
|
+
type BadgePartProps = {
|
|
6
|
+
/** The slot value the matching `badge.css` rules anchor on. */"data-slot": string; /** Forwarded verbatim — styling is attribute-driven, so this is an optional consumer passthrough. */
|
|
7
|
+
className?: string; /** A data-attribute present (string) or absent (`undefined`); never `false`. */
|
|
8
|
+
[attr: `data-${string}`]: string | undefined;
|
|
9
|
+
};
|
|
10
|
+
/** Common shape: every part's `.props()` accepts an optional `className` passthrough. */
|
|
11
|
+
interface BasePropsArgs {
|
|
12
|
+
/** Forwarded verbatim onto the returned prop bag. */
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
/** Argument to `Badge.Root.props(...)` — the chip's variant + tone + size. */
|
|
16
|
+
interface BadgeRootPropsArgs extends BasePropsArgs {
|
|
17
|
+
/** Emphasis — `solid` (filled) | `soft` (tint) | `outline` (edge) | `dot` (neutral chip, coloured dot). @default "soft" */
|
|
18
|
+
variant?: BadgeVariant;
|
|
19
|
+
/** Colour identity — a semantic tone or a decorative hue. @default "neutral" */
|
|
20
|
+
tone?: BadgeTone;
|
|
21
|
+
/** Chip scale. @default "md" */
|
|
22
|
+
size?: BadgeSize;
|
|
23
|
+
}
|
|
24
|
+
/** Argument to a stateless part's `.props(...)` — no recipe of its own; colour flows from the root. */
|
|
25
|
+
type BadgeStatelessPropsArgs = BasePropsArgs;
|
|
26
|
+
/** Root prop bag: `data-slot` plus the `data-variant`/`data-tone`/`data-size` the colour grid reads. */
|
|
27
|
+
declare function rootProps({
|
|
28
|
+
variant,
|
|
29
|
+
tone,
|
|
30
|
+
size,
|
|
31
|
+
className
|
|
32
|
+
}?: BadgeRootPropsArgs): BadgePartProps;
|
|
33
|
+
/** Dot prop bag: just the slot anchor (it fills with the chip's `currentColor`). */
|
|
34
|
+
declare function dotProps({
|
|
35
|
+
className
|
|
36
|
+
}?: BadgeStatelessPropsArgs): BadgePartProps;
|
|
37
|
+
/** Icon prop bag: just the slot anchor (the glyph is clamped to the chip's icon size and inherits its colour). */
|
|
38
|
+
declare function iconProps({
|
|
39
|
+
className
|
|
40
|
+
}?: BadgeStatelessPropsArgs): BadgePartProps;
|
|
41
|
+
//#endregion
|
|
42
|
+
export { BadgePartProps, BadgeRootPropsArgs, BadgeStatelessPropsArgs, dotProps, iconProps, rootProps };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { BADGE_SLOTS } from "./badge.slots.js";
|
|
2
|
+
//#region src/components/badge/badge.props.ts
|
|
3
|
+
/**
|
|
4
|
+
* The D12 unified variant contract for Badge — the data-attribute-native styling helpers.
|
|
5
|
+
*
|
|
6
|
+
* Each compound part exposes a `props(...)` builder returning a **spreadable props object** of the form
|
|
7
|
+
* `{ "data-slot": "noctis-badge-<part>", ...dataAttrs }`, derived from the part's variant/tone/size
|
|
8
|
+
* inputs. Under the single-`data-slot` anchor model the `data-slot` is the only styling hook needed —
|
|
9
|
+
* `badge.css` keys every rule off it plus the `data-*` recipe — so spreading a part's `props()` onto a
|
|
10
|
+
* *foreign* element styles it as that part:
|
|
11
|
+
*
|
|
12
|
+
* <a {...Badge.Root.props({ tone: "success" })} href="/status">Live</a>
|
|
13
|
+
* // → <a data-slot="noctis-badge" data-variant="soft" data-tone="success" data-size="md">
|
|
14
|
+
*
|
|
15
|
+
* The escape hatch carries no className (styling is attribute-driven); an optional `className`
|
|
16
|
+
* passthrough is accepted and forwarded verbatim. The same variant→data-attribute→values mapping is
|
|
17
|
+
* emitted as data from the token graph (`generated/declarations.json` → `variantSchema`) so non-React /
|
|
18
|
+
* agent consumers can hand-write the markup from the docs.
|
|
19
|
+
*/
|
|
20
|
+
const withClassName = (bag, className) => className === void 0 ? bag : {
|
|
21
|
+
...bag,
|
|
22
|
+
className
|
|
23
|
+
};
|
|
24
|
+
/** Root prop bag: `data-slot` plus the `data-variant`/`data-tone`/`data-size` the colour grid reads. */
|
|
25
|
+
function rootProps({ variant = "soft", tone = "neutral", size = "md", className } = {}) {
|
|
26
|
+
return withClassName({
|
|
27
|
+
"data-slot": BADGE_SLOTS.root,
|
|
28
|
+
"data-variant": variant,
|
|
29
|
+
"data-tone": tone,
|
|
30
|
+
"data-size": size
|
|
31
|
+
}, className);
|
|
32
|
+
}
|
|
33
|
+
/** Dot prop bag: just the slot anchor (it fills with the chip's `currentColor`). */
|
|
34
|
+
function dotProps({ className } = {}) {
|
|
35
|
+
return withClassName({ "data-slot": BADGE_SLOTS.dot }, className);
|
|
36
|
+
}
|
|
37
|
+
/** Icon prop bag: just the slot anchor (the glyph is clamped to the chip's icon size and inherits its colour). */
|
|
38
|
+
function iconProps({ className } = {}) {
|
|
39
|
+
return withClassName({ "data-slot": BADGE_SLOTS.icon }, className);
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { dotProps, iconProps, rootProps };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/components/badge/badge.slots.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The `data-*` hooks `Badge` stamps on its parts, for host-side styling and tests. The slot values
|
|
4
|
+
* mark each rendered element; the `data-variant`/`data-tone`/`data-size` axes carry the recipe the
|
|
5
|
+
* precompiled `badge.css` keys its colour grid and per-size metrics off. The dot and icon take no
|
|
6
|
+
* axis of their own — they ride the chip's `currentColor`, so they stay legible in every variant.
|
|
7
|
+
*/
|
|
8
|
+
declare enum BadgeDataAttributes {
|
|
9
|
+
/** The root chip element. */
|
|
10
|
+
slot = "data-slot",
|
|
11
|
+
/** The emphasis — `solid` (filled) | `soft` (tint, default) | `outline` (transparent, coloured edge). */
|
|
12
|
+
variant = "data-variant",
|
|
13
|
+
/** The colour identity — a semantic tone (`neutral`…`info`) or a decorative hue (`red`…`pink`). */
|
|
14
|
+
tone = "data-tone",
|
|
15
|
+
/** The chip scale — `sm` | `md` (default); the generated layer keys the per-size internals off it. */
|
|
16
|
+
size = "data-size"
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { BadgeDataAttributes };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/components/badge/badge.slots.ts
|
|
2
|
+
/**
|
|
3
|
+
* The slot vocabulary every `Badge` part stamps as its `data-slot`. The authored source the
|
|
4
|
+
* orchestration file reads from, kebab-cased `{component}[-{part}]` under the `noctis-` prefix;
|
|
5
|
+
* SLOTS.md still generates from the token-graph declarations.
|
|
6
|
+
*/
|
|
7
|
+
const BADGE_SLOTS = {
|
|
8
|
+
root: "noctis-badge",
|
|
9
|
+
dot: "noctis-badge-dot",
|
|
10
|
+
icon: "noctis-badge-icon"
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* The `data-*` hooks `Badge` stamps on its parts, for host-side styling and tests. The slot values
|
|
14
|
+
* mark each rendered element; the `data-variant`/`data-tone`/`data-size` axes carry the recipe the
|
|
15
|
+
* precompiled `badge.css` keys its colour grid and per-size metrics off. The dot and icon take no
|
|
16
|
+
* axis of their own — they ride the chip's `currentColor`, so they stay legible in every variant.
|
|
17
|
+
*/
|
|
18
|
+
let BadgeDataAttributes = /* @__PURE__ */ function(BadgeDataAttributes) {
|
|
19
|
+
/** The root chip element. */
|
|
20
|
+
BadgeDataAttributes["slot"] = "data-slot";
|
|
21
|
+
/** The emphasis — `solid` (filled) | `soft` (tint, default) | `outline` (transparent, coloured edge). */
|
|
22
|
+
BadgeDataAttributes["variant"] = "data-variant";
|
|
23
|
+
/** The colour identity — a semantic tone (`neutral`…`info`) or a decorative hue (`red`…`pink`). */
|
|
24
|
+
BadgeDataAttributes["tone"] = "data-tone";
|
|
25
|
+
/** The chip scale — `sm` | `md` (default); the generated layer keys the per-size internals off it. */
|
|
26
|
+
BadgeDataAttributes["size"] = "data-size";
|
|
27
|
+
return BadgeDataAttributes;
|
|
28
|
+
}({});
|
|
29
|
+
//#endregion
|
|
30
|
+
export { BADGE_SLOTS, BadgeDataAttributes };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/components/badge/badge.types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The variant/tone/size vocabulary `Badge` paints. Authored source of truth since styling is
|
|
4
|
+
* precompiled in `badge.css`. Types-only: no runtime code, so it never participates in the styling
|
|
5
|
+
* layer.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* A badge's emphasis — a filled `solid` chip, a quiet `soft` tint, a transparent `outline` with a
|
|
9
|
+
* coloured edge, or a neutral `dot` chip whose only colour is its leading status dot (the rest of the
|
|
10
|
+
* chip stays neutral). Crossed with {@link BadgeTone} to form the colour grid.
|
|
11
|
+
*/
|
|
12
|
+
type BadgeVariant = "solid" | "soft" | "outline" | "dot";
|
|
13
|
+
/**
|
|
14
|
+
* A badge's colour identity. The six **semantic** tones carry meaning — `neutral` (the default
|
|
15
|
+
* metadata chip), `accent`, and the four statuses `success`/`warning`/`danger`/`info`. The eight
|
|
16
|
+
* **decorative** tones (`red`/`orange`/`amber`/`green`/`teal`/`blue`/`purple`/`pink`) are
|
|
17
|
+
* accent-independent category colours drawn from the shared categorical palette — use them to distinguish
|
|
18
|
+
* categories, not to signal status.
|
|
19
|
+
*/
|
|
20
|
+
type BadgeTone = "neutral" | "accent" | "success" | "warning" | "danger" | "info" | "red" | "orange" | "amber" | "green" | "teal" | "blue" | "purple" | "pink";
|
|
21
|
+
/** A badge's chip scale — `sm` (the inline-with-text chip) or `md` (the default). */
|
|
22
|
+
type BadgeSize = "sm" | "md";
|
|
23
|
+
//#endregion
|
|
24
|
+
export { BadgeSize, BadgeTone, BadgeVariant };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext, use } from "react";
|
|
3
|
+
//#region src/components/pagination/pagination.context.ts
|
|
4
|
+
const PaginationContext = createContext(null);
|
|
5
|
+
const PaginationProvider = PaginationContext.Provider;
|
|
6
|
+
/**
|
|
7
|
+
* Read the enclosing `Pagination.Root` state. Every compound part is meaningless on its own (it needs
|
|
8
|
+
* the page model and shared labels), so this throws a part-named error when used outside the root.
|
|
9
|
+
*/
|
|
10
|
+
function usePaginationContext(part) {
|
|
11
|
+
const context = use(PaginationContext);
|
|
12
|
+
if (!context) throw new Error(`Pagination.${part} must be rendered inside a <Pagination.Root>.`);
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { PaginationProvider, usePaginationContext };
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { Button } from "../button/button.js";
|
|
2
|
+
import { PaginationLabels, PaginationSize } from "./pagination.types.js";
|
|
3
|
+
import { PaginationPartProps, PaginationRootPropsArgs, controlsProps, infoProps, pageProps, pageSizeLabelProps, pageSizeProps, rootProps, separatorProps } from "./pagination.props.js";
|
|
4
|
+
import { ComponentProps, ReactElement, ReactNode } from "react";
|
|
5
|
+
|
|
6
|
+
//#region src/components/pagination/pagination.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Page navigation: a row of nav controls (a welded `ButtonGroup` of First/Previous/Next/Last buttons),
|
|
9
|
+
* an optional editable page field, a "Showing X–Y of Z" info line, and a page-size picker — composed
|
|
10
|
+
* from the shipped `Button`, `ButtonGroup`, `Input`, and `Select`. `Pagination.Root` is controlled:
|
|
11
|
+
* pass `page` + `onPageChange`, and `total` + `perPage` (so the info line and the last-page bound can
|
|
12
|
+
* be computed) or an explicit `pageCount`. Every part reads the shared model through context, so the
|
|
13
|
+
* bounds-disabling and clamping are handled for you.
|
|
14
|
+
*
|
|
15
|
+
* @see {@link Pagination.Root.Props}
|
|
16
|
+
*/
|
|
17
|
+
declare function PaginationRoot({
|
|
18
|
+
page,
|
|
19
|
+
onPageChange,
|
|
20
|
+
total,
|
|
21
|
+
perPage,
|
|
22
|
+
pageCount: pageCountProp,
|
|
23
|
+
size,
|
|
24
|
+
labels: labelsProp,
|
|
25
|
+
className,
|
|
26
|
+
children,
|
|
27
|
+
...props
|
|
28
|
+
}: Pagination.Root.Props): ReactElement;
|
|
29
|
+
/** The render-prop state `Pagination.Info` exposes for custom info text. */
|
|
30
|
+
interface PaginationInfoState {
|
|
31
|
+
/** Current page, 1-indexed. */
|
|
32
|
+
page: number;
|
|
33
|
+
/** The last reachable page. */
|
|
34
|
+
pageCount: number;
|
|
35
|
+
/** Items per page, when known. */
|
|
36
|
+
perPage?: number;
|
|
37
|
+
/** Total item count, when known. */
|
|
38
|
+
total?: number;
|
|
39
|
+
/** First item index on the current page (1-indexed), or 0 when the set is empty. */
|
|
40
|
+
from: number;
|
|
41
|
+
/** Last item index on the current page. */
|
|
42
|
+
to: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The "Showing X–Y of Z" status line, announced politely as the page changes. Renders nothing unless
|
|
46
|
+
* `total` and `perPage` are known on the root — or pass a render function as children for custom text
|
|
47
|
+
* (e.g. "Page X of Y"). Quieter than the controls by design.
|
|
48
|
+
*/
|
|
49
|
+
declare function PaginationInfo({
|
|
50
|
+
children,
|
|
51
|
+
className,
|
|
52
|
+
...props
|
|
53
|
+
}: Pagination.Info.Props): ReactElement | null;
|
|
54
|
+
/**
|
|
55
|
+
* The page-size cluster — a layout wrapper that holds a `Pagination.PageSizeLabel` and a
|
|
56
|
+
* `Pagination.PageSizeSelect` side by side. Compose them inside; the label and select are separate so
|
|
57
|
+
* the consumer can reorder, restyle, translate, or drop either independently.
|
|
58
|
+
*/
|
|
59
|
+
declare function PaginationPageSize({
|
|
60
|
+
className,
|
|
61
|
+
children,
|
|
62
|
+
...props
|
|
63
|
+
}: Pagination.PageSize.Props): ReactElement;
|
|
64
|
+
/**
|
|
65
|
+
* The label beside the page-size select (visible "Per page" micro-copy). Defaults to the localized
|
|
66
|
+
* label; pass children to override the text. Purely visual — the select carries its own accessible name.
|
|
67
|
+
*/
|
|
68
|
+
declare function PaginationPageSizeLabel({
|
|
69
|
+
className,
|
|
70
|
+
children,
|
|
71
|
+
...props
|
|
72
|
+
}: Pagination.PageSizeLabel.Props): ReactElement;
|
|
73
|
+
/**
|
|
74
|
+
* The page-size `Select` of "items per page" choices. Controlled via `value` + `onValueChange`;
|
|
75
|
+
* resetting the page to 1 on change is the consumer's call (do it in the handler).
|
|
76
|
+
*/
|
|
77
|
+
declare function PaginationPageSizeSelect({
|
|
78
|
+
value,
|
|
79
|
+
onValueChange,
|
|
80
|
+
options
|
|
81
|
+
}: Pagination.PageSizeSelect.Props): ReactElement;
|
|
82
|
+
/**
|
|
83
|
+
* The navigation landmark wrapping a welded `ButtonGroup` of nav buttons. Compose `Pagination.First`,
|
|
84
|
+
* `Pagination.Previous`, `Pagination.Next`, `Pagination.Last`, and/or `Pagination.Page` inside — use
|
|
85
|
+
* only Previous/Next for a simple control, or add First/Last/Page for the full set.
|
|
86
|
+
*/
|
|
87
|
+
declare function PaginationControls({
|
|
88
|
+
className,
|
|
89
|
+
children,
|
|
90
|
+
...props
|
|
91
|
+
}: Pagination.Controls.Props): ReactElement;
|
|
92
|
+
/** Jump to the first page. Disabled on page 1. */
|
|
93
|
+
declare function PaginationFirst(props: Pagination.NavButton.Props): ReactElement;
|
|
94
|
+
/** Step to the previous page. Disabled on page 1. */
|
|
95
|
+
declare function PaginationPrevious(props: Pagination.NavButton.Props): ReactElement;
|
|
96
|
+
/** Step to the next page. Disabled on the last page. */
|
|
97
|
+
declare function PaginationNext(props: Pagination.NavButton.Props): ReactElement;
|
|
98
|
+
/** Jump to the last page. Disabled on the last page. */
|
|
99
|
+
declare function PaginationLast(props: Pagination.NavButton.Props): ReactElement;
|
|
100
|
+
/**
|
|
101
|
+
* An editable page-number field (the "full" affordance). Type a page and press Enter or blur to commit;
|
|
102
|
+
* the value is clamped to the valid range and snaps back if cleared. Sits beside the nav buttons.
|
|
103
|
+
*/
|
|
104
|
+
declare function PaginationPage({
|
|
105
|
+
className,
|
|
106
|
+
...props
|
|
107
|
+
}: Pagination.Page.Props): ReactElement;
|
|
108
|
+
/** A vertical hairline between pagination clusters. Purely decorative — a quiet visual rule, hidden
|
|
109
|
+
* from assistive tech (the clusters are already distinct landmarks/labels). */
|
|
110
|
+
declare function PaginationSeparator({
|
|
111
|
+
className,
|
|
112
|
+
...props
|
|
113
|
+
}: Pagination.Separator.Props): ReactElement;
|
|
114
|
+
/**
|
|
115
|
+
* Page navigation controls. `Pagination.Root` owns the controlled page model and shares it with the
|
|
116
|
+
* parts: `Pagination.Controls` (the welded nav `ButtonGroup`) hosting `Pagination.First` / `Previous` /
|
|
117
|
+
* `Next` / `Last` and the editable `Pagination.Page`, plus the `Pagination.Info` status line, the
|
|
118
|
+
* `Pagination.PageSize` picker, and the `Pagination.Separator` divider.
|
|
119
|
+
*
|
|
120
|
+
* The runtime compound is a plain object (kept tree-shakeable); per-part prop types are exposed through
|
|
121
|
+
* the matching `Pagination` namespace — e.g. `Pagination.Root.Props`.
|
|
122
|
+
*/
|
|
123
|
+
declare const Pagination: {
|
|
124
|
+
/** Owns the controlled page model + shared context. `Pagination.Root.props({ size })` → its prop bag. */Root: typeof PaginationRoot & {
|
|
125
|
+
props: typeof rootProps;
|
|
126
|
+
}; /** The "Showing X–Y of Z" status line. `Pagination.Info.props()` → its prop bag. */
|
|
127
|
+
Info: typeof PaginationInfo & {
|
|
128
|
+
props: typeof infoProps;
|
|
129
|
+
}; /** The page-size cluster (compose `PageSizeLabel` + `PageSizeSelect`). `Pagination.PageSize.props()` → its prop bag. */
|
|
130
|
+
PageSize: typeof PaginationPageSize & {
|
|
131
|
+
props: typeof pageSizeProps;
|
|
132
|
+
}; /** The page-size label. `Pagination.PageSizeLabel.props()` → its prop bag. */
|
|
133
|
+
PageSizeLabel: typeof PaginationPageSizeLabel & {
|
|
134
|
+
props: typeof pageSizeLabelProps;
|
|
135
|
+
}; /** The page-size select control. */
|
|
136
|
+
PageSizeSelect: typeof PaginationPageSizeSelect; /** The nav landmark + welded `ButtonGroup`. `Pagination.Controls.props()` → its prop bag. */
|
|
137
|
+
Controls: typeof PaginationControls & {
|
|
138
|
+
props: typeof controlsProps;
|
|
139
|
+
}; /** First-page button. */
|
|
140
|
+
First: typeof PaginationFirst; /** Previous-page button. */
|
|
141
|
+
Previous: typeof PaginationPrevious; /** Next-page button. */
|
|
142
|
+
Next: typeof PaginationNext; /** Last-page button. */
|
|
143
|
+
Last: typeof PaginationLast; /** The editable page-number field. `Pagination.Page.props()` → its prop bag. */
|
|
144
|
+
Page: typeof PaginationPage & {
|
|
145
|
+
props: typeof pageProps;
|
|
146
|
+
}; /** A vertical divider between clusters. `Pagination.Separator.props()` → its prop bag. */
|
|
147
|
+
Separator: typeof PaginationSeparator & {
|
|
148
|
+
props: typeof separatorProps;
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Per-part prop types. Types-only — it emits no runtime code and merges with the `Pagination` object
|
|
153
|
+
* above, so `Pagination.Root` is the component value while `Pagination.Root.Props` is its prop type.
|
|
154
|
+
*/
|
|
155
|
+
declare namespace Pagination {
|
|
156
|
+
/** Control scale — `sm` | `md`. */
|
|
157
|
+
type Size = PaginationSize;
|
|
158
|
+
/** The accessible-name + micro-copy overrides. */
|
|
159
|
+
type Labels = PaginationLabels;
|
|
160
|
+
/** The spreadable data-attribute prop bag every owned `Pagination.*.props()` returns (D12). */
|
|
161
|
+
type PartProps = PaginationPartProps;
|
|
162
|
+
namespace Root {
|
|
163
|
+
type Props = Omit<ComponentProps<"div">, "onChange"> & {
|
|
164
|
+
/**
|
|
165
|
+
* Current page, 1-indexed.
|
|
166
|
+
* @default 1
|
|
167
|
+
*/
|
|
168
|
+
page?: number; /** Called with the next page (already clamped to `[1, pageCount]`) when the user navigates. */
|
|
169
|
+
onPageChange?: (page: number) => void; /** Total item count across all pages — drives the info range and the last-page bound. */
|
|
170
|
+
total?: number; /** Items shown per page — drives the info range and the last-page bound. */
|
|
171
|
+
perPage?: number; /** The last reachable page, when you'd rather supply it than derive it from `total`/`perPage`. */
|
|
172
|
+
pageCount?: number;
|
|
173
|
+
/**
|
|
174
|
+
* Control scale, fed to the hosted Button/Input/Select.
|
|
175
|
+
* @default "md"
|
|
176
|
+
*/
|
|
177
|
+
size?: PaginationSize; /** Per-instance overrides for the accessible names + micro-copy. */
|
|
178
|
+
labels?: PaginationLabels;
|
|
179
|
+
};
|
|
180
|
+
/** Argument to the `Pagination.Root.props(...)` escape-hatch helper. */
|
|
181
|
+
type PropsArgs = PaginationRootPropsArgs;
|
|
182
|
+
}
|
|
183
|
+
namespace Info {
|
|
184
|
+
type Props = Omit<ComponentProps<"div">, "children"> & {
|
|
185
|
+
/** Render function for custom info text; omit for the default "Showing X–Y of Z". */children?: (state: PaginationInfoState) => ReactNode;
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
namespace PageSize {
|
|
189
|
+
/** The cluster wrapper — compose `Pagination.PageSizeLabel` and `Pagination.PageSizeSelect` inside. */
|
|
190
|
+
type Props = ComponentProps<"div">;
|
|
191
|
+
}
|
|
192
|
+
namespace PageSizeLabel {
|
|
193
|
+
/** The visible "Per page" label; children override the default localized text. */
|
|
194
|
+
type Props = ComponentProps<"span">;
|
|
195
|
+
}
|
|
196
|
+
namespace PageSizeSelect {
|
|
197
|
+
type Props = {
|
|
198
|
+
/** The current page size. */value: number; /** Called with the chosen page size. */
|
|
199
|
+
onValueChange: (size: number) => void; /** The available page-size choices. @default [10, 25, 50, 100] */
|
|
200
|
+
options?: readonly number[];
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
namespace Controls {
|
|
204
|
+
type Props = ComponentProps<"nav">;
|
|
205
|
+
}
|
|
206
|
+
namespace NavButton {
|
|
207
|
+
type Props = Omit<Button.Props, "iconOnly" | "startIcon" | "endIcon" | "onClick" | "children">;
|
|
208
|
+
}
|
|
209
|
+
namespace Page {
|
|
210
|
+
type Props = ComponentProps<"div">;
|
|
211
|
+
}
|
|
212
|
+
namespace Separator {
|
|
213
|
+
type Props = ComponentProps<"div">;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
//#endregion
|
|
217
|
+
export { Pagination };
|