@stridge/noctis 1.0.0-beta.4 → 1.0.0-beta.6
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/breadcrumb/breadcrumb.d.ts +163 -0
- package/dist/components/breadcrumb/breadcrumb.js +152 -0
- package/dist/components/breadcrumb/breadcrumb.props.d.ts +59 -0
- package/dist/components/breadcrumb/breadcrumb.props.js +68 -0
- package/dist/components/breadcrumb/breadcrumb.slots.d.ts +16 -0
- package/dist/components/breadcrumb/breadcrumb.slots.js +32 -0
- package/dist/components/breadcrumb/breadcrumb.types.d.ts +9 -0
- package/dist/components/breadcrumb/index.d.ts +3 -0
- package/dist/components/command/command-listbox.js +174 -0
- package/dist/components/command/command-rank.d.ts +40 -0
- package/dist/components/command/command-rank.js +61 -0
- package/dist/components/command/command-score.d.ts +25 -0
- package/dist/components/command/command-score.js +85 -0
- package/dist/components/command/command.context.d.ts +17 -0
- package/dist/components/command/command.context.js +13 -0
- package/dist/components/command/command.d.ts +396 -0
- package/dist/components/command/command.js +471 -0
- package/dist/components/command/command.props.d.ts +91 -0
- package/dist/components/command/command.props.js +94 -0
- package/dist/components/command/command.slots.d.ts +23 -0
- package/dist/components/command/command.slots.js +60 -0
- package/dist/components/command/index.d.ts +6 -0
- package/dist/components/command/use-command-ranking.d.ts +37 -0
- package/dist/components/command/use-command-ranking.js +127 -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/components/search-dialog/parts/root.js +1 -1
- package/dist/components/skeleton/index.d.ts +3 -0
- package/dist/components/skeleton/skeleton.context.js +12 -0
- package/dist/components/skeleton/skeleton.d.ts +157 -0
- package/dist/components/skeleton/skeleton.js +130 -0
- package/dist/components/skeleton/skeleton.props.d.ts +47 -0
- package/dist/components/skeleton/skeleton.props.js +57 -0
- package/dist/components/skeleton/skeleton.slots.d.ts +15 -0
- package/dist/components/skeleton/skeleton.slots.js +28 -0
- package/dist/components/skeleton/skeleton.types.d.ts +13 -0
- package/dist/components/surface/surface.d.ts +1 -1
- package/dist/icons/glyphs.js +2 -2
- package/dist/index.d.ts +18 -3
- package/dist/index.js +15 -4
- package/dist/primitives/index.d.ts +1 -1
- package/dist/primitives/index.js +2 -2
- package/dist/props.d.ts +37 -33
- package/dist/props.js +37 -33
- package/dist/styles.css +841 -6
- package/package.json +4 -4
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Icon } from "../../icons/icon.js";
|
|
3
|
+
import { ChevronLeftIcon, ChevronRightIcon, ChevronsLeftIcon, ChevronsRightIcon } from "../../icons/glyphs.js";
|
|
4
|
+
import { useInjectedLabels, useNoctisStringFormatter } from "../../core/use-injected-labels.js";
|
|
5
|
+
import { Button } from "../button/button.js";
|
|
6
|
+
import { Input } from "../input/input.js";
|
|
7
|
+
import { Select } from "../select/select.js";
|
|
8
|
+
import { ButtonGroup } from "../button-group/button-group.js";
|
|
9
|
+
import { PaginationProvider, usePaginationContext } from "./pagination.context.js";
|
|
10
|
+
import { PAGINATION_SLOTS } from "./pagination.slots.js";
|
|
11
|
+
import { controlsProps, infoProps, pageProps, pageSizeLabelProps, pageSizeProps, rootProps, separatorProps } from "./pagination.props.js";
|
|
12
|
+
import { useEffect, useMemo, useState } from "react";
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
//#region src/components/pagination/pagination.tsx
|
|
15
|
+
/** Default page-size choices, matching the common "rows per page" ladder. */
|
|
16
|
+
const DEFAULT_PAGE_SIZE_OPTIONS = [
|
|
17
|
+
10,
|
|
18
|
+
25,
|
|
19
|
+
50,
|
|
20
|
+
100
|
|
21
|
+
];
|
|
22
|
+
/** English fallbacks for every accessible name + micro-copy; overridden by locale dict, then per-instance. */
|
|
23
|
+
const DEFAULT_LABELS = {
|
|
24
|
+
navigation: "Pagination",
|
|
25
|
+
firstPage: "First page",
|
|
26
|
+
previousPage: "Previous page",
|
|
27
|
+
nextPage: "Next page",
|
|
28
|
+
lastPage: "Last page",
|
|
29
|
+
pageNumber: "Page number",
|
|
30
|
+
pageSize: "Page size",
|
|
31
|
+
perPage: "Per page"
|
|
32
|
+
};
|
|
33
|
+
/** Each label field → its `@stridge/noctis-intl` catalog key. */
|
|
34
|
+
const LABEL_KEYS = {
|
|
35
|
+
navigation: "pagination.navigation",
|
|
36
|
+
firstPage: "pagination.firstPage",
|
|
37
|
+
previousPage: "pagination.previousPage",
|
|
38
|
+
nextPage: "pagination.nextPage",
|
|
39
|
+
lastPage: "pagination.lastPage",
|
|
40
|
+
pageNumber: "pagination.pageNumber",
|
|
41
|
+
pageSize: "pagination.pageSize",
|
|
42
|
+
perPage: "pagination.perPage"
|
|
43
|
+
};
|
|
44
|
+
/** Pagination's `sm`/`md` → the hosted Button/Input size (which share the `sm`/`md` rungs). */
|
|
45
|
+
const controlSize = (size) => size;
|
|
46
|
+
/** Pagination's `sm`/`md` → the hosted Icon size. */
|
|
47
|
+
const glyphSize = (size) => size;
|
|
48
|
+
/**
|
|
49
|
+
* Page navigation: a row of nav controls (a welded `ButtonGroup` of First/Previous/Next/Last buttons),
|
|
50
|
+
* an optional editable page field, a "Showing X–Y of Z" info line, and a page-size picker — composed
|
|
51
|
+
* from the shipped `Button`, `ButtonGroup`, `Input`, and `Select`. `Pagination.Root` is controlled:
|
|
52
|
+
* pass `page` + `onPageChange`, and `total` + `perPage` (so the info line and the last-page bound can
|
|
53
|
+
* be computed) or an explicit `pageCount`. Every part reads the shared model through context, so the
|
|
54
|
+
* bounds-disabling and clamping are handled for you.
|
|
55
|
+
*
|
|
56
|
+
* @see {@link Pagination.Root.Props}
|
|
57
|
+
*/
|
|
58
|
+
function PaginationRoot({ page = 1, onPageChange, total, perPage, pageCount: pageCountProp, size = "md", labels: labelsProp, className, children, ...props }) {
|
|
59
|
+
const labels = useInjectedLabels(DEFAULT_LABELS, LABEL_KEYS, labelsProp);
|
|
60
|
+
const pageCount = Math.max(1, pageCountProp ?? (total != null && perPage ? Math.ceil(total / perPage) : 1));
|
|
61
|
+
const value = useMemo(() => {
|
|
62
|
+
const goToPage = (next) => {
|
|
63
|
+
const clamped = Math.min(Math.max(Math.trunc(next), 1), pageCount);
|
|
64
|
+
if (clamped !== page) onPageChange?.(clamped);
|
|
65
|
+
};
|
|
66
|
+
return {
|
|
67
|
+
page,
|
|
68
|
+
pageCount,
|
|
69
|
+
perPage,
|
|
70
|
+
total,
|
|
71
|
+
size,
|
|
72
|
+
labels,
|
|
73
|
+
goToPage
|
|
74
|
+
};
|
|
75
|
+
}, [
|
|
76
|
+
page,
|
|
77
|
+
pageCount,
|
|
78
|
+
perPage,
|
|
79
|
+
total,
|
|
80
|
+
size,
|
|
81
|
+
labels,
|
|
82
|
+
onPageChange
|
|
83
|
+
]);
|
|
84
|
+
return /* @__PURE__ */ jsx("div", {
|
|
85
|
+
"data-slot": PAGINATION_SLOTS.root,
|
|
86
|
+
"data-size": size,
|
|
87
|
+
className,
|
|
88
|
+
...props,
|
|
89
|
+
children: /* @__PURE__ */ jsx(PaginationProvider, {
|
|
90
|
+
value,
|
|
91
|
+
children
|
|
92
|
+
})
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The "Showing X–Y of Z" status line, announced politely as the page changes. Renders nothing unless
|
|
97
|
+
* `total` and `perPage` are known on the root — or pass a render function as children for custom text
|
|
98
|
+
* (e.g. "Page X of Y"). Quieter than the controls by design.
|
|
99
|
+
*/
|
|
100
|
+
function PaginationInfo({ children, className, ...props }) {
|
|
101
|
+
const { page, pageCount, perPage, total } = usePaginationContext("Info");
|
|
102
|
+
const formatter = useNoctisStringFormatter();
|
|
103
|
+
const hasRange = total != null && perPage != null;
|
|
104
|
+
const from = !hasRange || total === 0 ? 0 : (page - 1) * perPage + 1;
|
|
105
|
+
const to = hasRange ? Math.min(page * perPage, total) : 0;
|
|
106
|
+
const content = children ? children({
|
|
107
|
+
page,
|
|
108
|
+
pageCount,
|
|
109
|
+
perPage,
|
|
110
|
+
total,
|
|
111
|
+
from,
|
|
112
|
+
to
|
|
113
|
+
}) : hasRange ? formatter.format("pagination.showing", {
|
|
114
|
+
from,
|
|
115
|
+
to,
|
|
116
|
+
total
|
|
117
|
+
}) : null;
|
|
118
|
+
if (content == null) return null;
|
|
119
|
+
return /* @__PURE__ */ jsx("div", {
|
|
120
|
+
"data-slot": PAGINATION_SLOTS.info,
|
|
121
|
+
"aria-live": "polite",
|
|
122
|
+
"aria-atomic": "true",
|
|
123
|
+
className,
|
|
124
|
+
...props,
|
|
125
|
+
children: content
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* The page-size cluster — a layout wrapper that holds a `Pagination.PageSizeLabel` and a
|
|
130
|
+
* `Pagination.PageSizeSelect` side by side. Compose them inside; the label and select are separate so
|
|
131
|
+
* the consumer can reorder, restyle, translate, or drop either independently.
|
|
132
|
+
*/
|
|
133
|
+
function PaginationPageSize({ className, children, ...props }) {
|
|
134
|
+
return /* @__PURE__ */ jsx("div", {
|
|
135
|
+
"data-slot": PAGINATION_SLOTS.pageSize,
|
|
136
|
+
className,
|
|
137
|
+
...props,
|
|
138
|
+
children
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The label beside the page-size select (visible "Per page" micro-copy). Defaults to the localized
|
|
143
|
+
* label; pass children to override the text. Purely visual — the select carries its own accessible name.
|
|
144
|
+
*/
|
|
145
|
+
function PaginationPageSizeLabel({ className, children, ...props }) {
|
|
146
|
+
const { labels } = usePaginationContext("PageSizeLabel");
|
|
147
|
+
return /* @__PURE__ */ jsx("span", {
|
|
148
|
+
"data-slot": PAGINATION_SLOTS.pageSizeLabel,
|
|
149
|
+
className,
|
|
150
|
+
...props,
|
|
151
|
+
children: children ?? labels.perPage
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* The page-size `Select` of "items per page" choices. Controlled via `value` + `onValueChange`;
|
|
156
|
+
* resetting the page to 1 on change is the consumer's call (do it in the handler).
|
|
157
|
+
*/
|
|
158
|
+
function PaginationPageSizeSelect({ value, onValueChange, options = DEFAULT_PAGE_SIZE_OPTIONS }) {
|
|
159
|
+
const { labels } = usePaginationContext("PageSizeSelect");
|
|
160
|
+
const items = useMemo(() => Object.fromEntries(options.map((option) => [option, String(option)])), [options]);
|
|
161
|
+
return /* @__PURE__ */ jsxs(Select.Root, {
|
|
162
|
+
items,
|
|
163
|
+
value,
|
|
164
|
+
onValueChange: (next) => onValueChange(next),
|
|
165
|
+
children: [/* @__PURE__ */ jsxs(Select.Trigger, {
|
|
166
|
+
"aria-label": labels.pageSize,
|
|
167
|
+
children: [/* @__PURE__ */ jsx(Select.Value, {}), /* @__PURE__ */ jsx(Select.Icon, {})]
|
|
168
|
+
}), /* @__PURE__ */ jsx(Select.Popup, { children: options.map((option) => /* @__PURE__ */ jsx(Select.Item, {
|
|
169
|
+
value: option,
|
|
170
|
+
children: option
|
|
171
|
+
}, option)) })]
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The navigation landmark wrapping a welded `ButtonGroup` of nav buttons. Compose `Pagination.First`,
|
|
176
|
+
* `Pagination.Previous`, `Pagination.Next`, `Pagination.Last`, and/or `Pagination.Page` inside — use
|
|
177
|
+
* only Previous/Next for a simple control, or add First/Last/Page for the full set.
|
|
178
|
+
*/
|
|
179
|
+
function PaginationControls({ className, children, ...props }) {
|
|
180
|
+
const { size, labels } = usePaginationContext("Controls");
|
|
181
|
+
return /* @__PURE__ */ jsx("nav", {
|
|
182
|
+
"aria-label": labels.navigation,
|
|
183
|
+
"data-slot": PAGINATION_SLOTS.controls,
|
|
184
|
+
className,
|
|
185
|
+
...props,
|
|
186
|
+
children: /* @__PURE__ */ jsx(ButtonGroup, {
|
|
187
|
+
variant: "secondary",
|
|
188
|
+
size: controlSize(size),
|
|
189
|
+
children
|
|
190
|
+
})
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/** Shared icon-only nav button: bounds-disabled, clamping `goToPage`, RTL-mirrored chevron. */
|
|
194
|
+
function NavButton({ glyph, label, target, disabled, "aria-label": ariaLabel, className, ...props }) {
|
|
195
|
+
const { size, goToPage } = usePaginationContext("Controls");
|
|
196
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
197
|
+
iconOnly: true,
|
|
198
|
+
"aria-label": ariaLabel ?? label,
|
|
199
|
+
disabled,
|
|
200
|
+
className,
|
|
201
|
+
...props,
|
|
202
|
+
onClick: () => goToPage(target),
|
|
203
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
204
|
+
icon: glyph,
|
|
205
|
+
directional: true,
|
|
206
|
+
size: glyphSize(size)
|
|
207
|
+
})
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
/** Jump to the first page. Disabled on page 1. */
|
|
211
|
+
function PaginationFirst(props) {
|
|
212
|
+
const { page, labels } = usePaginationContext("First");
|
|
213
|
+
return /* @__PURE__ */ jsx(NavButton, {
|
|
214
|
+
glyph: ChevronsLeftIcon,
|
|
215
|
+
label: labels.firstPage,
|
|
216
|
+
target: 1,
|
|
217
|
+
disabled: page <= 1,
|
|
218
|
+
...props
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
/** Step to the previous page. Disabled on page 1. */
|
|
222
|
+
function PaginationPrevious(props) {
|
|
223
|
+
const { page, labels } = usePaginationContext("Previous");
|
|
224
|
+
return /* @__PURE__ */ jsx(NavButton, {
|
|
225
|
+
glyph: ChevronLeftIcon,
|
|
226
|
+
label: labels.previousPage,
|
|
227
|
+
target: page - 1,
|
|
228
|
+
disabled: page <= 1,
|
|
229
|
+
...props
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/** Step to the next page. Disabled on the last page. */
|
|
233
|
+
function PaginationNext(props) {
|
|
234
|
+
const { page, pageCount, labels } = usePaginationContext("Next");
|
|
235
|
+
return /* @__PURE__ */ jsx(NavButton, {
|
|
236
|
+
glyph: ChevronRightIcon,
|
|
237
|
+
label: labels.nextPage,
|
|
238
|
+
target: page + 1,
|
|
239
|
+
disabled: page >= pageCount,
|
|
240
|
+
...props
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
/** Jump to the last page. Disabled on the last page. */
|
|
244
|
+
function PaginationLast(props) {
|
|
245
|
+
const { page, pageCount, labels } = usePaginationContext("Last");
|
|
246
|
+
return /* @__PURE__ */ jsx(NavButton, {
|
|
247
|
+
glyph: ChevronsRightIcon,
|
|
248
|
+
label: labels.lastPage,
|
|
249
|
+
target: pageCount,
|
|
250
|
+
disabled: page >= pageCount,
|
|
251
|
+
...props
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* An editable page-number field (the "full" affordance). Type a page and press Enter or blur to commit;
|
|
256
|
+
* the value is clamped to the valid range and snaps back if cleared. Sits beside the nav buttons.
|
|
257
|
+
*/
|
|
258
|
+
function PaginationPage({ className, ...props }) {
|
|
259
|
+
const { page, labels, goToPage } = usePaginationContext("Page");
|
|
260
|
+
const [draft, setDraft] = useState(String(page));
|
|
261
|
+
useEffect(() => {
|
|
262
|
+
setDraft(String(page));
|
|
263
|
+
}, [page]);
|
|
264
|
+
const commit = () => {
|
|
265
|
+
const next = Number(draft);
|
|
266
|
+
if (draft.trim() !== "" && Number.isFinite(next)) goToPage(next);
|
|
267
|
+
else setDraft(String(page));
|
|
268
|
+
};
|
|
269
|
+
return /* @__PURE__ */ jsx("div", {
|
|
270
|
+
"data-slot": PAGINATION_SLOTS.page,
|
|
271
|
+
"data-button-group-item": "",
|
|
272
|
+
className,
|
|
273
|
+
...props,
|
|
274
|
+
children: /* @__PURE__ */ jsx(Input.Root, { children: /* @__PURE__ */ jsx(Input.Control, {
|
|
275
|
+
"aria-label": labels.pageNumber,
|
|
276
|
+
inputMode: "numeric",
|
|
277
|
+
autoComplete: "off",
|
|
278
|
+
value: draft,
|
|
279
|
+
onChange: (event) => setDraft(event.currentTarget.value),
|
|
280
|
+
onBlur: commit,
|
|
281
|
+
onKeyDown: (event) => {
|
|
282
|
+
if (event.key === "Enter") commit();
|
|
283
|
+
}
|
|
284
|
+
}) })
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
/** A vertical hairline between pagination clusters. Purely decorative — a quiet visual rule, hidden
|
|
288
|
+
* from assistive tech (the clusters are already distinct landmarks/labels). */
|
|
289
|
+
function PaginationSeparator({ className, ...props }) {
|
|
290
|
+
return /* @__PURE__ */ jsx("div", {
|
|
291
|
+
"data-slot": PAGINATION_SLOTS.separator,
|
|
292
|
+
"aria-hidden": "true",
|
|
293
|
+
className,
|
|
294
|
+
...props
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Page navigation controls. `Pagination.Root` owns the controlled page model and shares it with the
|
|
299
|
+
* parts: `Pagination.Controls` (the welded nav `ButtonGroup`) hosting `Pagination.First` / `Previous` /
|
|
300
|
+
* `Next` / `Last` and the editable `Pagination.Page`, plus the `Pagination.Info` status line, the
|
|
301
|
+
* `Pagination.PageSize` picker, and the `Pagination.Separator` divider.
|
|
302
|
+
*
|
|
303
|
+
* The runtime compound is a plain object (kept tree-shakeable); per-part prop types are exposed through
|
|
304
|
+
* the matching `Pagination` namespace — e.g. `Pagination.Root.Props`.
|
|
305
|
+
*/
|
|
306
|
+
const Pagination = {
|
|
307
|
+
/** Owns the controlled page model + shared context. `Pagination.Root.props({ size })` → its prop bag. */
|
|
308
|
+
Root: Object.assign(PaginationRoot, { props: rootProps }),
|
|
309
|
+
/** The "Showing X–Y of Z" status line. `Pagination.Info.props()` → its prop bag. */
|
|
310
|
+
Info: Object.assign(PaginationInfo, { props: infoProps }),
|
|
311
|
+
/** The page-size cluster (compose `PageSizeLabel` + `PageSizeSelect`). `Pagination.PageSize.props()` → its prop bag. */
|
|
312
|
+
PageSize: Object.assign(PaginationPageSize, { props: pageSizeProps }),
|
|
313
|
+
/** The page-size label. `Pagination.PageSizeLabel.props()` → its prop bag. */
|
|
314
|
+
PageSizeLabel: Object.assign(PaginationPageSizeLabel, { props: pageSizeLabelProps }),
|
|
315
|
+
/** The page-size select control. */
|
|
316
|
+
PageSizeSelect: PaginationPageSizeSelect,
|
|
317
|
+
/** The nav landmark + welded `ButtonGroup`. `Pagination.Controls.props()` → its prop bag. */
|
|
318
|
+
Controls: Object.assign(PaginationControls, { props: controlsProps }),
|
|
319
|
+
/** First-page button. */
|
|
320
|
+
First: PaginationFirst,
|
|
321
|
+
/** Previous-page button. */
|
|
322
|
+
Previous: PaginationPrevious,
|
|
323
|
+
/** Next-page button. */
|
|
324
|
+
Next: PaginationNext,
|
|
325
|
+
/** Last-page button. */
|
|
326
|
+
Last: PaginationLast,
|
|
327
|
+
/** The editable page-number field. `Pagination.Page.props()` → its prop bag. */
|
|
328
|
+
Page: Object.assign(PaginationPage, { props: pageProps }),
|
|
329
|
+
/** A vertical divider between clusters. `Pagination.Separator.props()` → its prop bag. */
|
|
330
|
+
Separator: Object.assign(PaginationSeparator, { props: separatorProps })
|
|
331
|
+
};
|
|
332
|
+
//#endregion
|
|
333
|
+
export { Pagination };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { PaginationSize } from "./pagination.types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/components/pagination/pagination.props.d.ts
|
|
4
|
+
/** A spreadable data-attribute prop bag — the shape every `Pagination.*.props()` returns. */
|
|
5
|
+
type PaginationPartProps = {
|
|
6
|
+
/** The slot value the matching `pagination.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
|
+
interface BasePropsArgs {
|
|
11
|
+
/** Forwarded verbatim onto the returned prop bag. */
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
/** Argument to `Pagination.Root.props(...)` — the control scale fed to the hosted controls. */
|
|
15
|
+
interface PaginationRootPropsArgs extends BasePropsArgs {
|
|
16
|
+
/** Control scale. @default "md" */
|
|
17
|
+
size?: PaginationSize;
|
|
18
|
+
}
|
|
19
|
+
/** Argument to a stateless Pagination part's `.props(...)`. */
|
|
20
|
+
type PaginationStatelessPropsArgs = BasePropsArgs;
|
|
21
|
+
/** Root prop bag: `data-slot` plus the `data-size` the layout + hosted controls read. */
|
|
22
|
+
declare function rootProps({
|
|
23
|
+
size,
|
|
24
|
+
className
|
|
25
|
+
}?: PaginationRootPropsArgs): PaginationPartProps;
|
|
26
|
+
/** Info-line prop bag: just the slot anchor. */
|
|
27
|
+
declare function infoProps({
|
|
28
|
+
className
|
|
29
|
+
}?: PaginationStatelessPropsArgs): PaginationPartProps;
|
|
30
|
+
/** Page-size cluster prop bag: just the slot anchor. */
|
|
31
|
+
declare function pageSizeProps({
|
|
32
|
+
className
|
|
33
|
+
}?: PaginationStatelessPropsArgs): PaginationPartProps;
|
|
34
|
+
/** Page-size label prop bag: just the slot anchor. */
|
|
35
|
+
declare function pageSizeLabelProps({
|
|
36
|
+
className
|
|
37
|
+
}?: PaginationStatelessPropsArgs): PaginationPartProps;
|
|
38
|
+
/** Page-field cluster prop bag: just the slot anchor. */
|
|
39
|
+
declare function pageProps({
|
|
40
|
+
className
|
|
41
|
+
}?: PaginationStatelessPropsArgs): PaginationPartProps;
|
|
42
|
+
/** Controls cluster prop bag: just the slot anchor. */
|
|
43
|
+
declare function controlsProps({
|
|
44
|
+
className
|
|
45
|
+
}?: PaginationStatelessPropsArgs): PaginationPartProps;
|
|
46
|
+
/** Separator prop bag: just the slot anchor. */
|
|
47
|
+
declare function separatorProps({
|
|
48
|
+
className
|
|
49
|
+
}?: PaginationStatelessPropsArgs): PaginationPartProps;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { PaginationPartProps, PaginationRootPropsArgs, controlsProps, infoProps, pageProps, pageSizeLabelProps, pageSizeProps, rootProps, separatorProps };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { PAGINATION_SLOTS } from "./pagination.slots.js";
|
|
2
|
+
//#region src/components/pagination/pagination.props.ts
|
|
3
|
+
/**
|
|
4
|
+
* The D12 unified variant contract for Pagination — the data-attribute-native styling helpers.
|
|
5
|
+
*
|
|
6
|
+
* Each part Pagination *owns* exposes a `props(...)` builder returning a spreadable
|
|
7
|
+
* `{ "data-slot": "noctis-pagination-<part>", ...dataAttrs }` bag the precompiled `pagination.css` keys
|
|
8
|
+
* off, so spreading it onto a foreign element styles that element as the part. The hosted controls
|
|
9
|
+
* (`Button`/`ButtonGroup`/`Input`/`Select`) are composed in the orchestration and keep their own
|
|
10
|
+
* `.props()`; these helpers cover only Pagination's own layout slots. An optional `className` is
|
|
11
|
+
* forwarded verbatim.
|
|
12
|
+
*/
|
|
13
|
+
const withClassName = (bag, className) => className === void 0 ? bag : {
|
|
14
|
+
...bag,
|
|
15
|
+
className
|
|
16
|
+
};
|
|
17
|
+
/** Root prop bag: `data-slot` plus the `data-size` the layout + hosted controls read. */
|
|
18
|
+
function rootProps({ size = "md", className } = {}) {
|
|
19
|
+
return withClassName({
|
|
20
|
+
"data-slot": PAGINATION_SLOTS.root,
|
|
21
|
+
"data-size": size
|
|
22
|
+
}, className);
|
|
23
|
+
}
|
|
24
|
+
/** Info-line prop bag: just the slot anchor. */
|
|
25
|
+
function infoProps({ className } = {}) {
|
|
26
|
+
return withClassName({ "data-slot": PAGINATION_SLOTS.info }, className);
|
|
27
|
+
}
|
|
28
|
+
/** Page-size cluster prop bag: just the slot anchor. */
|
|
29
|
+
function pageSizeProps({ className } = {}) {
|
|
30
|
+
return withClassName({ "data-slot": PAGINATION_SLOTS.pageSize }, className);
|
|
31
|
+
}
|
|
32
|
+
/** Page-size label prop bag: just the slot anchor. */
|
|
33
|
+
function pageSizeLabelProps({ className } = {}) {
|
|
34
|
+
return withClassName({ "data-slot": PAGINATION_SLOTS.pageSizeLabel }, className);
|
|
35
|
+
}
|
|
36
|
+
/** Page-field cluster prop bag: just the slot anchor. */
|
|
37
|
+
function pageProps({ className } = {}) {
|
|
38
|
+
return withClassName({ "data-slot": PAGINATION_SLOTS.page }, className);
|
|
39
|
+
}
|
|
40
|
+
/** Controls cluster prop bag: just the slot anchor. */
|
|
41
|
+
function controlsProps({ className } = {}) {
|
|
42
|
+
return withClassName({ "data-slot": PAGINATION_SLOTS.controls }, className);
|
|
43
|
+
}
|
|
44
|
+
/** Separator prop bag: just the slot anchor. */
|
|
45
|
+
function separatorProps({ className } = {}) {
|
|
46
|
+
return withClassName({ "data-slot": PAGINATION_SLOTS.separator }, className);
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { controlsProps, infoProps, pageProps, pageSizeLabelProps, pageSizeProps, rootProps, separatorProps };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/components/pagination/pagination.slots.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The `data-*` hooks `Pagination` stamps on its own parts, for host-side styling and tests. The
|
|
4
|
+
* `data-size` axis (on the root) carries the recipe the precompiled `pagination.css` keys its layout
|
|
5
|
+
* off and that the orchestration feeds to the hosted controls. The nav buttons render `Button`, so
|
|
6
|
+
* their bounds-disabled state is the `Button`'s own `data-disabled` (stamped by the underlying control),
|
|
7
|
+
* not a Pagination attribute.
|
|
8
|
+
*/
|
|
9
|
+
declare enum PaginationDataAttributes {
|
|
10
|
+
/** The root navigation container. */
|
|
11
|
+
slot = "data-slot",
|
|
12
|
+
/** The control scale — `sm` | `md` (default); fed to the hosted Button/Input/Select. */
|
|
13
|
+
size = "data-size"
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { PaginationDataAttributes };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/components/pagination/pagination.slots.ts
|
|
2
|
+
/**
|
|
3
|
+
* The slot vocabulary every `Pagination` 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. The hosted controls (`Button`,
|
|
6
|
+
* `ButtonGroup`, `Input`, `Select`) keep their own slots — these mark only Pagination's own structure.
|
|
7
|
+
*/
|
|
8
|
+
const PAGINATION_SLOTS = {
|
|
9
|
+
root: "noctis-pagination",
|
|
10
|
+
info: "noctis-pagination-info",
|
|
11
|
+
pageSize: "noctis-pagination-page-size",
|
|
12
|
+
pageSizeLabel: "noctis-pagination-page-size-label",
|
|
13
|
+
page: "noctis-pagination-page",
|
|
14
|
+
controls: "noctis-pagination-controls",
|
|
15
|
+
separator: "noctis-pagination-separator"
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* The `data-*` hooks `Pagination` stamps on its own parts, for host-side styling and tests. The
|
|
19
|
+
* `data-size` axis (on the root) carries the recipe the precompiled `pagination.css` keys its layout
|
|
20
|
+
* off and that the orchestration feeds to the hosted controls. The nav buttons render `Button`, so
|
|
21
|
+
* their bounds-disabled state is the `Button`'s own `data-disabled` (stamped by the underlying control),
|
|
22
|
+
* not a Pagination attribute.
|
|
23
|
+
*/
|
|
24
|
+
let PaginationDataAttributes = /* @__PURE__ */ function(PaginationDataAttributes) {
|
|
25
|
+
/** The root navigation container. */
|
|
26
|
+
PaginationDataAttributes["slot"] = "data-slot";
|
|
27
|
+
/** The control scale — `sm` | `md` (default); fed to the hosted Button/Input/Select. */
|
|
28
|
+
PaginationDataAttributes["size"] = "data-size";
|
|
29
|
+
return PaginationDataAttributes;
|
|
30
|
+
}({});
|
|
31
|
+
//#endregion
|
|
32
|
+
export { PAGINATION_SLOTS, PaginationDataAttributes };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region src/components/pagination/pagination.types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The size vocabulary and the i18n label shape `Pagination` paints. Authored source of truth since
|
|
4
|
+
* styling is precompiled in `pagination.css`. Types-only: no runtime code.
|
|
5
|
+
*/
|
|
6
|
+
/** The pagination control scale — `sm` (dense rows) or `md` (the default). Fed to the hosted controls. */
|
|
7
|
+
type PaginationSize = "sm" | "md";
|
|
8
|
+
/**
|
|
9
|
+
* The accessible names and visible micro-copy for `Pagination`. Every field has an English default
|
|
10
|
+
* (overridden per-instance via the `labels` prop, or globally through `@stridge/noctis-intl`). Declared
|
|
11
|
+
* as a `type` (not an `interface`) so it carries the implicit index signature `useInjectedLabels` needs.
|
|
12
|
+
*/
|
|
13
|
+
type PaginationLabels = {
|
|
14
|
+
/** Accessible name for the navigation landmark. @default "Pagination" */navigation?: string; /** Accessible name for the first-page button. @default "First page" */
|
|
15
|
+
firstPage?: string; /** Accessible name for the previous-page button. @default "Previous page" */
|
|
16
|
+
previousPage?: string; /** Accessible name for the next-page button. @default "Next page" */
|
|
17
|
+
nextPage?: string; /** Accessible name for the last-page button. @default "Last page" */
|
|
18
|
+
lastPage?: string; /** Accessible name for the page-number input. @default "Page number" */
|
|
19
|
+
pageNumber?: string; /** Accessible name for the page-size select. @default "Page size" */
|
|
20
|
+
pageSize?: string; /** Visible label before the page-size select. @default "Per page" */
|
|
21
|
+
perPage?: string;
|
|
22
|
+
};
|
|
23
|
+
//#endregion
|
|
24
|
+
export { PaginationLabels, PaginationSize };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { VisuallyHidden } from "../../../core/visually-hidden/visually-hidden.js";
|
|
3
|
+
import { Dialog } from "../../dialog/dialog.js";
|
|
3
4
|
import { SearchDialogProvider } from "../search-dialog.context.js";
|
|
4
5
|
import { SEARCH_DIALOG_SLOTS } from "../search-dialog.slots.js";
|
|
5
|
-
import { Dialog } from "../../dialog/dialog.js";
|
|
6
6
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
//#region src/components/search-dialog/parts/root.tsx
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext, use } from "react";
|
|
3
|
+
//#region src/components/skeleton/skeleton.context.ts
|
|
4
|
+
const SkeletonContext = createContext({ variant: "shimmer" });
|
|
5
|
+
/** Provider used by `Skeleton.Root` to share its `variant` with descendant shapes. */
|
|
6
|
+
const SkeletonProvider = SkeletonContext.Provider;
|
|
7
|
+
/** Reads the active `Skeleton` context, falling back to the shimmer default for a standalone shape. */
|
|
8
|
+
function useSkeletonContext() {
|
|
9
|
+
return use(SkeletonContext);
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { SkeletonProvider, useSkeletonContext };
|