@panneau/lists 4.1.1 → 5.0.0-alpha.1
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 +116 -0
- package/dist/List.d.ts +26 -0
- package/dist/List.d.ts.map +1 -0
- package/dist/List.js +38 -0
- package/dist/List.js.map +1 -0
- package/dist/ListView.css +101 -0
- package/dist/ListView.d.ts +76 -0
- package/dist/ListView.d.ts.map +1 -0
- package/dist/ListView.js +325 -0
- package/dist/ListView.js.map +1 -0
- package/dist/ListView.module.js +28 -0
- package/dist/ListView.module.js.map +1 -0
- package/dist/actions/ActionButton.d.ts +18 -0
- package/dist/actions/ActionButton.d.ts.map +1 -0
- package/dist/actions/ActionButton.js +34 -0
- package/dist/actions/ActionButton.js.map +1 -0
- package/dist/actions/Actions.css +58 -0
- package/dist/actions/Actions.module.js +20 -0
- package/dist/actions/Actions.module.js.map +1 -0
- package/dist/actions/ConfirmDialog.d.ts +15 -0
- package/dist/actions/ConfirmDialog.d.ts.map +1 -0
- package/dist/actions/ConfirmDialog.js +157 -0
- package/dist/actions/ConfirmDialog.js.map +1 -0
- package/dist/actions/RowActions.d.ts +20 -0
- package/dist/actions/RowActions.d.ts.map +1 -0
- package/dist/actions/RowActions.js +99 -0
- package/dist/actions/RowActions.js.map +1 -0
- package/dist/actions/actions.d.ts +23 -0
- package/dist/actions/actions.d.ts.map +1 -0
- package/dist/actions/actions.js +56 -0
- package/dist/actions/actions.js.map +1 -0
- package/dist/actions/icons.d.ts +10 -0
- package/dist/actions/icons.d.ts.map +1 -0
- package/dist/actions/icons.js +27 -0
- package/dist/actions/icons.js.map +1 -0
- package/dist/cx.d.ts +3 -0
- package/dist/cx.d.ts.map +1 -0
- package/dist/cx.js +9 -0
- package/dist/cx.js.map +1 -0
- package/dist/displays/Displays.css +71 -0
- package/dist/displays/Displays.module.js +30 -0
- package/dist/displays/Displays.module.js.map +1 -0
- package/dist/displays/displays.d.ts +36 -0
- package/dist/displays/displays.d.ts.map +1 -0
- package/dist/displays/displays.js +570 -0
- package/dist/displays/displays.js.map +1 -0
- package/dist/filters/Filters.css +71 -0
- package/dist/filters/Filters.d.ts +38 -0
- package/dist/filters/Filters.d.ts.map +1 -0
- package/dist/filters/Filters.js +240 -0
- package/dist/filters/Filters.js.map +1 -0
- package/dist/filters/Filters.module.js +24 -0
- package/dist/filters/Filters.module.js.map +1 -0
- package/dist/filters/controls.d.ts +23 -0
- package/dist/filters/controls.d.ts.map +1 -0
- package/dist/filters/controls.js +431 -0
- package/dist/filters/controls.js.map +1 -0
- package/dist/filters/format.d.ts +16 -0
- package/dist/filters/format.d.ts.map +1 -0
- package/dist/filters/format.js +46 -0
- package/dist/filters/format.js.map +1 -0
- package/dist/index.d.ts +19 -10
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -66
- package/dist/layouts/CardsLayout.css +72 -0
- package/dist/layouts/CardsLayout.d.ts +4 -0
- package/dist/layouts/CardsLayout.d.ts.map +1 -0
- package/dist/layouts/CardsLayout.js +111 -0
- package/dist/layouts/CardsLayout.js.map +1 -0
- package/dist/layouts/CardsLayout.module.js +24 -0
- package/dist/layouts/CardsLayout.module.js.map +1 -0
- package/dist/layouts/ItemTitle.d.ts +10 -0
- package/dist/layouts/ItemTitle.d.ts.map +1 -0
- package/dist/layouts/ItemTitle.js +30 -0
- package/dist/layouts/ItemTitle.js.map +1 -0
- package/dist/layouts/TableLayout.css +177 -0
- package/dist/layouts/TableLayout.d.ts +9 -0
- package/dist/layouts/TableLayout.d.ts.map +1 -0
- package/dist/layouts/TableLayout.js +208 -0
- package/dist/layouts/TableLayout.js.map +1 -0
- package/dist/layouts/TableLayout.module.js +32 -0
- package/dist/layouts/TableLayout.module.js.map +1 -0
- package/dist/layouts/builtIn.d.ts +6 -0
- package/dist/layouts/builtIn.d.ts.map +1 -0
- package/dist/layouts/builtIn.js +12 -0
- package/dist/layouts/builtIn.js.map +1 -0
- package/dist/layouts/link.css +16 -0
- package/dist/layouts/link.module.js +8 -0
- package/dist/layouts/link.module.js.map +1 -0
- package/dist/messages.d.ts +2 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +1 -0
- package/dist/plugin.d.ts +13 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +19 -0
- package/dist/plugin.js.map +1 -0
- package/dist/query.d.ts +21 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +70 -0
- package/dist/query.js.map +1 -0
- package/dist/selection.d.ts +9 -0
- package/dist/selection.d.ts.map +1 -0
- package/dist/selection.js +19 -0
- package/dist/selection.js.map +1 -0
- package/dist/toolbar/LayoutSwitch.d.ts +8 -0
- package/dist/toolbar/LayoutSwitch.d.ts.map +1 -0
- package/dist/toolbar/LayoutSwitch.js +108 -0
- package/dist/toolbar/LayoutSwitch.js.map +1 -0
- package/dist/toolbar/Pagination.d.ts +13 -0
- package/dist/toolbar/Pagination.d.ts.map +1 -0
- package/dist/toolbar/Pagination.js +62 -0
- package/dist/toolbar/Pagination.js.map +1 -0
- package/dist/toolbar/SearchField.d.ts +9 -0
- package/dist/toolbar/SearchField.d.ts.map +1 -0
- package/dist/toolbar/SearchField.js +64 -0
- package/dist/toolbar/SearchField.js.map +1 -0
- package/dist/toolbar/SortSelect.d.ts +9 -0
- package/dist/toolbar/SortSelect.d.ts.map +1 -0
- package/dist/toolbar/SortSelect.js +90 -0
- package/dist/toolbar/SortSelect.js.map +1 -0
- package/dist/toolbar/Toolbar.css +72 -0
- package/dist/toolbar/Toolbar.module.js +22 -0
- package/dist/toolbar/Toolbar.module.js.map +1 -0
- package/dist/types.d.ts +106 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/useDraft.d.ts +11 -0
- package/dist/useDraft.d.ts.map +1 -0
- package/dist/useDraft.js +77 -0
- package/dist/useDraft.js.map +1 -0
- package/dist/useListState.d.ts +4 -0
- package/dist/useListState.d.ts.map +1 -0
- package/dist/useListState.js +10 -0
- package/dist/useListState.js.map +1 -0
- package/dist/values.d.ts +21 -0
- package/dist/values.d.ts.map +1 -0
- package/dist/values.js +52 -0
- package/dist/values.js.map +1 -0
- package/package.json +27 -57
package/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# @panneau/lists
|
|
2
|
+
|
|
3
|
+
Lists of Panneau: items in a table or as cards, with columns and their displays, sorting, search, filters, pagination, selection and actions. They render the list state of [`@panneau/core`](../core) (query and selection) and fetch nothing: the caller gives the items of the query.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @panneau/lists@^5.0.0-alpha.0 @panneau/core@^5.0.0-alpha.0 @panneau/ui@^5.0.0-alpha.0 react-aria-components react-intl
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Without a definition
|
|
10
|
+
|
|
11
|
+
A product with its own API writes its columns, keeps the query in a list state, and fetches its items:
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { useList } from '@panneau/core';
|
|
15
|
+
import { ListView } from '@panneau/lists';
|
|
16
|
+
import { PanneauRoot } from '@panneau/ui';
|
|
17
|
+
|
|
18
|
+
function Members() {
|
|
19
|
+
const { query, list } = useList({ defaults: { perPage: 20, sort: ['name'] } });
|
|
20
|
+
const { data, isPending, error } = useMembers(query); // the product's own fetching
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<ListView
|
|
24
|
+
list={list}
|
|
25
|
+
aria-label="Members"
|
|
26
|
+
columns={[
|
|
27
|
+
{ id: 'name', label: 'Name', sortable: true },
|
|
28
|
+
{ id: 'email', label: 'Email', display: 'email' },
|
|
29
|
+
{ id: 'role', label: 'Role', field: roleField, display: 'select' },
|
|
30
|
+
{ id: 'joined_on', label: 'Joined', display: 'date', sortable: true },
|
|
31
|
+
]}
|
|
32
|
+
items={data?.items}
|
|
33
|
+
total={data?.total}
|
|
34
|
+
isLoading={isPending}
|
|
35
|
+
error={error}
|
|
36
|
+
search
|
|
37
|
+
filters={[{ id: 'role', type: 'select', options: roles }]}
|
|
38
|
+
actions={[
|
|
39
|
+
{
|
|
40
|
+
id: 'remove',
|
|
41
|
+
label: 'Remove',
|
|
42
|
+
kind: 'server',
|
|
43
|
+
scope: ['item', 'selection'],
|
|
44
|
+
destructive: true,
|
|
45
|
+
confirm: true,
|
|
46
|
+
},
|
|
47
|
+
]}
|
|
48
|
+
onAction={({ action, item, selection }) => api.run(action.id, item?.id ?? selection)}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
With every item at hand, `List` does the query in memory: `<List columns={columns} items={members} search />`.
|
|
55
|
+
|
|
56
|
+
## From a definition
|
|
57
|
+
|
|
58
|
+
`resolveList()` of `@panneau/core` gives the props of a resource's list:
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
const { resource, list: resolved } = useResource('pages');
|
|
62
|
+
const { query, list } = useList({ list: resolved });
|
|
63
|
+
const { data, isFetching, error } = useResourceList('pages', query); // @panneau/data/query
|
|
64
|
+
|
|
65
|
+
<ListView
|
|
66
|
+
{...resolved}
|
|
67
|
+
list={list}
|
|
68
|
+
items={data?.data}
|
|
69
|
+
total={data?.meta.total}
|
|
70
|
+
isLoading={isFetching}
|
|
71
|
+
error={error}
|
|
72
|
+
fields={resource.fields}
|
|
73
|
+
itemTitle={resource.itemTitle}
|
|
74
|
+
onAction={(event) => runAction(event)}
|
|
75
|
+
/>;
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## What a list does
|
|
79
|
+
|
|
80
|
+
| Feature | How |
|
|
81
|
+
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
82
|
+
| Columns | `item[id]` shown with a display: the column's `display`, else text. Localized values in the UI's locale. `render` for a cell of its own |
|
|
83
|
+
| Displays | `text`, `textarea`, `slug`, `richtext`, `number`, `boolean`, `date`, `datetime`, `time`, `select`, `relation`, `url`, `email`, `color`, `media` |
|
|
84
|
+
| Layouts | `table` and `cards` (`layouts`, the first is the default). On narrow lists, table rows stack and show the label of each value |
|
|
85
|
+
| Sorting | Sortable column headers (`aria-sort`), and a select for cards and phones |
|
|
86
|
+
| Filters | `text`, `select`, `toggle`, `date`, `date-range` (sent as bounds: `filter[id][from]`, `filter[id][to]`), `relation`, with chips for the active filters and the search |
|
|
87
|
+
| Pagination | With `total`: the range, previous and next pages, and the page size (`perPageOptions`) |
|
|
88
|
+
| Selection | Checkboxes, the page, then "select all N items", which selects every item matching the query, with exceptions |
|
|
89
|
+
| Actions | `row` (buttons), `menu` (the row's menu), `toolbar` (selection and resource actions), with `confirm`, hidden by abilities ([0011](../../docs/decisions/0011-permissions.md)) |
|
|
90
|
+
| States | A spinner, an error with a retry, an empty message, and "no results" with a button that clears the filters |
|
|
91
|
+
|
|
92
|
+
An action shows the Lucide icon it names (`"icon": "send"`, through `getNamedIcon()` of `@panneau/ui`), or the icon of a built-in action (`edit`, `delete`…). Actions written in code can get icon components by id instead, which win over names: `actionIcons={{ archive: Archive }}`.
|
|
93
|
+
|
|
94
|
+
Lists confirm an action when it has `confirm` (its title and message are ICU messages with `{count}`), or when some selected items don't allow it, then call `onAction` with the action, its scope, the item or the `Selection` of the protocol, the count and the skipped items. A promise shows the action as pending; when it rejects, a toast says that it failed. After a selection action, the selection is cleared.
|
|
95
|
+
|
|
96
|
+
A `relation` filter keeps ids in the query (`filter[author]=7`). Its chip and picker show the labels of the items it picked, and those of ids from the URL once the relation source's `resolve()` gives them.
|
|
97
|
+
|
|
98
|
+
## Plugins
|
|
99
|
+
|
|
100
|
+
Displays and layouts are registry entries. Plugins of `PanneauProvider` add or replace them, and so do the `displays` and `layoutComponents` props:
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
definePlugin({ id: 'my-site', displays: { 'page-slug': PageSlugDisplay } });
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
A display gets `{ value, item, column, field }`. A layout gets the items, the columns, `renderValue(item, column)`, the selection and the actions (`ListLayoutProps`).
|
|
107
|
+
|
|
108
|
+
## Messages
|
|
109
|
+
|
|
110
|
+
Strings go through react-intl, with English defaults. Their descriptors and their French text live in [`@panneau/intl`](../intl) (`listsMessages`), with those of the other packages: give the app's `IntlProvider` `withPanneauMessages(locale, appMessages)`, or pass `listsPlugin`, which carries them.
|
|
111
|
+
|
|
112
|
+
| Export | Content |
|
|
113
|
+
| ---------------- | --------------------------------------------------------------------- |
|
|
114
|
+
| `@panneau/lists` | `ListView`, `List`, displays, layouts, filter controls, `listsPlugin` |
|
|
115
|
+
|
|
116
|
+
The package layout, scripts and API reports are explained in [`docs/packages.md`](../../docs/packages.md).
|
package/dist/List.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ListOptions } from '@panneau/core';
|
|
2
|
+
import { type ListViewProps } from './ListView';
|
|
3
|
+
import type { ListItem } from './types';
|
|
4
|
+
export interface ListProps extends Omit<ListViewProps, 'list' | 'total' | 'items'> {
|
|
5
|
+
/** Every item: the list searches, filters, sorts and paginates them in memory. */
|
|
6
|
+
items: readonly ListItem[] | undefined;
|
|
7
|
+
/** Items per page. Defaults to 20. */
|
|
8
|
+
perPage?: number;
|
|
9
|
+
/** Default sort, as `sort` query values (`['-published_at']`). */
|
|
10
|
+
defaultSort?: string[];
|
|
11
|
+
/**
|
|
12
|
+
* Keeps the query in a router (`createHistoryRouter()`). Defaults to the router of the closest
|
|
13
|
+
* `PanneauProvider`; `null` keeps it in memory.
|
|
14
|
+
*/
|
|
15
|
+
router?: ListOptions['router'];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A list of items held in memory, from columns and items, with or without a definition. It
|
|
19
|
+
* creates its state with `useList()` of `@panneau/core`, and applies the query to `items` itself.
|
|
20
|
+
* For items fetched page by page, create the state with `useList()`, fetch its `query`, and render
|
|
21
|
+
* `ListView`.
|
|
22
|
+
*
|
|
23
|
+
* The page size and the default sort are read once.
|
|
24
|
+
*/
|
|
25
|
+
export declare function List({ items, perPage, defaultSort, router, ...props }: ListProps): import("react").JSX.Element;
|
|
26
|
+
//# sourceMappingURL=List.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"List.d.ts","sourceRoot":"","sources":["../src/List.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAW,MAAM,eAAe,CAAC;AAG1D,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAE1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IAC9E,kFAAkF;IAClF,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,SAAS,CAAC;IACvC,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,EAAE,KAAK,EAAE,OAAY,EAAE,WAAgB,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,EAAE,SAAS,+BAW1F"}
|
package/dist/List.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ListView } from "./ListView.js";
|
|
2
|
+
import { applyListQuery } from "./query.js";
|
|
3
|
+
import { useList } from "@panneau/core";
|
|
4
|
+
import { usePanneauIntl } from "@panneau/ui";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
//#region src/List.tsx
|
|
7
|
+
/**
|
|
8
|
+
* A list of items held in memory, from columns and items, with or without a definition. It
|
|
9
|
+
* creates its state with `useList()` of `@panneau/core`, and applies the query to `items` itself.
|
|
10
|
+
* For items fetched page by page, create the state with `useList()`, fetch its `query`, and render
|
|
11
|
+
* `ListView`.
|
|
12
|
+
*
|
|
13
|
+
* The page size and the default sort are read once.
|
|
14
|
+
*/
|
|
15
|
+
function List({ items, perPage = 20, defaultSort = [], router, ...props }) {
|
|
16
|
+
const intl = usePanneauIntl();
|
|
17
|
+
const { query, list } = useList({
|
|
18
|
+
defaults: {
|
|
19
|
+
perPage,
|
|
20
|
+
sort: defaultSort
|
|
21
|
+
},
|
|
22
|
+
...router !== void 0 ? { router } : {}
|
|
23
|
+
});
|
|
24
|
+
const result = items !== void 0 ? applyListQuery(items, query, {
|
|
25
|
+
columns: props.columns,
|
|
26
|
+
locale: intl.locale
|
|
27
|
+
}) : void 0;
|
|
28
|
+
return /* @__PURE__ */ jsx(ListView, {
|
|
29
|
+
...props,
|
|
30
|
+
list,
|
|
31
|
+
items: result?.items,
|
|
32
|
+
total: result?.total
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { List };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=List.js.map
|
package/dist/List.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"List.js","names":[],"sources":["../src/List.tsx"],"sourcesContent":["import { type ListOptions, useList } from '@panneau/core';\nimport { usePanneauIntl } from '@panneau/ui';\n\nimport { ListView, type ListViewProps } from './ListView';\nimport { applyListQuery } from './query';\nimport type { ListItem } from './types';\n\nexport interface ListProps extends Omit<ListViewProps, 'list' | 'total' | 'items'> {\n /** Every item: the list searches, filters, sorts and paginates them in memory. */\n items: readonly ListItem[] | undefined;\n /** Items per page. Defaults to 20. */\n perPage?: number;\n /** Default sort, as `sort` query values (`['-published_at']`). */\n defaultSort?: string[];\n /**\n * Keeps the query in a router (`createHistoryRouter()`). Defaults to the router of the closest\n * `PanneauProvider`; `null` keeps it in memory.\n */\n router?: ListOptions['router'];\n}\n\n/**\n * A list of items held in memory, from columns and items, with or without a definition. It\n * creates its state with `useList()` of `@panneau/core`, and applies the query to `items` itself.\n * For items fetched page by page, create the state with `useList()`, fetch its `query`, and render\n * `ListView`.\n *\n * The page size and the default sort are read once.\n */\nexport function List({ items, perPage = 20, defaultSort = [], router, ...props }: ListProps) {\n const intl = usePanneauIntl();\n const { query, list } = useList({\n defaults: { perPage, sort: defaultSort },\n ...(router !== undefined ? { router } : {}),\n });\n const result =\n items !== undefined\n ? applyListQuery(items, query, { columns: props.columns, locale: intl.locale })\n : undefined;\n return <ListView {...props} list={list} items={result?.items} total={result?.total} />;\n}\n"],"mappings":";;;;;;;;;;;;;;AA6BA,SAAgB,KAAK,EAAE,OAAO,UAAU,IAAI,cAAc,CAAA,GAAI,QAAQ,GAAG,SAAoB;CACzF,MAAM,OAAO,eAAe;CAC5B,MAAM,EAAE,OAAO,SAAS,QAAQ;EAC5B,UAAU;GAAE;GAAS,MAAM;EAAY;EACvC,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;CAC7C,CAAC;CACD,MAAM,SACF,UAAU,KAAA,IACJ,eAAe,OAAO,OAAO;EAAE,SAAS,MAAM;EAAS,QAAQ,KAAK;CAAO,CAAC,IAC5E,KAAA;CACV,OAAO,oBAAC,UAAD;EAAU,GAAI;EAAa;EAAM,OAAO,QAAQ;EAAO,OAAO,QAAQ;CAAM,CAAA;AACvF"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
.panneau-list-BmsDb5 {
|
|
2
|
+
container: panneau-list / inline-size;
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
gap: var(--panneau-space-3);
|
|
6
|
+
min-width: 0;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.panneau-toolbar-Q043Ps {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-wrap: wrap;
|
|
12
|
+
align-items: flex-end;
|
|
13
|
+
gap: var(--panneau-space-3);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.panneau-toolbarStart-hzlm5k {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex: 1 1 auto;
|
|
19
|
+
flex-wrap: wrap;
|
|
20
|
+
align-items: flex-end;
|
|
21
|
+
gap: var(--panneau-space-3);
|
|
22
|
+
min-width: 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.panneau-toolbarEnd-0mOtOR {
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-wrap: wrap;
|
|
28
|
+
align-items: flex-end;
|
|
29
|
+
gap: var(--panneau-space-2);
|
|
30
|
+
margin-inline-start: auto;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* With the table layout, the column headers sort, until the list is too narrow to show them. */
|
|
34
|
+
.panneau-tableSort-w-YpFE {
|
|
35
|
+
display: none;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.panneau-selection-MHT4Rl {
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-wrap: wrap;
|
|
41
|
+
align-items: center;
|
|
42
|
+
gap: var(--panneau-space-2) var(--panneau-space-3);
|
|
43
|
+
padding: var(--panneau-space-2) var(--panneau-space-3);
|
|
44
|
+
font-size: var(--panneau-font-size-sm);
|
|
45
|
+
background-color: var(--panneau-color-accent-subtle);
|
|
46
|
+
border: var(--panneau-border-width) solid var(--panneau-color-border);
|
|
47
|
+
border-radius: var(--panneau-radius-lg);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.panneau-selectionCount-maD7mZ {
|
|
51
|
+
font-weight: var(--panneau-font-weight-medium);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.panneau-selectionActions-lQgDIc {
|
|
55
|
+
display: flex;
|
|
56
|
+
flex-wrap: wrap;
|
|
57
|
+
gap: var(--panneau-space-2);
|
|
58
|
+
margin-inline-start: auto;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.panneau-body-m0W7NQ[aria-busy='true'] {
|
|
62
|
+
opacity: 0.6;
|
|
63
|
+
transition: opacity var(--panneau-duration);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.panneau-state-VVBIkb {
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
align-items: center;
|
|
70
|
+
gap: var(--panneau-space-3);
|
|
71
|
+
padding: var(--panneau-space-10) var(--panneau-space-4);
|
|
72
|
+
color: var(--panneau-color-text-muted);
|
|
73
|
+
text-align: center;
|
|
74
|
+
background-color: var(--panneau-color-surface);
|
|
75
|
+
border: var(--panneau-border-width) dashed var(--panneau-color-border);
|
|
76
|
+
border-radius: var(--panneau-radius-lg);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.panneau-state-VVBIkb p {
|
|
80
|
+
margin: 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@container panneau-list (max-width: 40rem) {
|
|
84
|
+
.panneau-toolbarStart-hzlm5k,
|
|
85
|
+
.panneau-toolbarEnd-0mOtOR {
|
|
86
|
+
flex-basis: 100%;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.panneau-toolbarEnd-0mOtOR {
|
|
90
|
+
margin-inline-start: 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.panneau-tableSort-w-YpFE {
|
|
94
|
+
display: block;
|
|
95
|
+
width: 100%;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.panneau-selectionActions-lQgDIc {
|
|
99
|
+
margin-inline-start: 0;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { List } from '@panneau/core';
|
|
3
|
+
import type { Field, Filter } from '@panneau/protocol';
|
|
4
|
+
import { type ListActions } from './actions/actions';
|
|
5
|
+
import type { ActionIcons } from './actions/icons';
|
|
6
|
+
import type { DisplayEntry, FilterEntry, ListActionHandler, ListColumn, ListItem, ListLayoutEntry } from './types';
|
|
7
|
+
export interface ListViewProps {
|
|
8
|
+
/** The list state of `@panneau/core` (`useList()`): query and selection. */
|
|
9
|
+
list: List;
|
|
10
|
+
/** The items of the current page. `undefined` while they load for the first time. */
|
|
11
|
+
items: readonly ListItem[] | undefined;
|
|
12
|
+
columns: readonly ListColumn[];
|
|
13
|
+
/**
|
|
14
|
+
* How many items match the query, on every page (`meta.total`). With it, the list shows
|
|
15
|
+
* pagination and offers to select every matching item. Without it, `items` is the whole list.
|
|
16
|
+
*/
|
|
17
|
+
total?: number | undefined;
|
|
18
|
+
/** Shows that items are loading. Items already shown stay, dimmed. */
|
|
19
|
+
isLoading?: boolean;
|
|
20
|
+
/** An error while loading: an alert with a retry replaces the items. */
|
|
21
|
+
error?: Error | null;
|
|
22
|
+
onRetry?: () => void;
|
|
23
|
+
/** Filter controls, with chips for the active filters. */
|
|
24
|
+
filters?: readonly Filter[];
|
|
25
|
+
/** Fields of the items, for the labels and options of filters that are not columns. */
|
|
26
|
+
fields?: readonly Field[];
|
|
27
|
+
/** Shows a search field (`q`). */
|
|
28
|
+
search?: boolean;
|
|
29
|
+
/** Layouts to choose from, the first one being the default. Defaults to `['table']`. */
|
|
30
|
+
layouts?: readonly string[];
|
|
31
|
+
/** The layout, controlled. */
|
|
32
|
+
layout?: string;
|
|
33
|
+
onLayoutChange?: (layout: string) => void;
|
|
34
|
+
/** Page sizes to choose from. */
|
|
35
|
+
perPageOptions?: readonly number[];
|
|
36
|
+
/** Shows checkboxes. Defaults to whether there are selection actions. */
|
|
37
|
+
selectable?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Actions: a list (placed by their `placement`, or by scope), or grouped by placement as
|
|
40
|
+
* `resolveList()` does. Those the user can't run (`abilities.run`) are hidden.
|
|
41
|
+
*/
|
|
42
|
+
actions?: ListActions;
|
|
43
|
+
/** Runs an action, after its confirmation. */
|
|
44
|
+
onAction?: ListActionHandler;
|
|
45
|
+
/**
|
|
46
|
+
* Icons of actions by action id (`{ archive: Archive }`), for actions written in code. They
|
|
47
|
+
* win over the Lucide icon an action names (`"icon": "archive"`).
|
|
48
|
+
*/
|
|
49
|
+
actionIcons?: ActionIcons;
|
|
50
|
+
/** The field that titles items, for their label (`itemTitle` of the resource). */
|
|
51
|
+
itemTitle?: string;
|
|
52
|
+
/** The label of an item, for checkboxes and actions. Defaults to its title, then its id. */
|
|
53
|
+
getItemLabel?: (item: ListItem) => string;
|
|
54
|
+
/** A link to an item, on its title. */
|
|
55
|
+
getItemHref?: (item: ListItem) => string | null;
|
|
56
|
+
/** Displays by name, over the built-in ones and those of the plugins. */
|
|
57
|
+
displays?: Readonly<Record<string, DisplayEntry>>;
|
|
58
|
+
/** Layouts by id, over the built-in ones and those of the plugins. */
|
|
59
|
+
layoutComponents?: Readonly<Record<string, ListLayoutEntry>>;
|
|
60
|
+
/** Filter controls by filter type, over the built-in ones. */
|
|
61
|
+
filterControls?: Readonly<Record<string, FilterEntry>>;
|
|
62
|
+
/** Content at the end of the toolbar, such as a button to create an item. */
|
|
63
|
+
toolbar?: ReactNode;
|
|
64
|
+
/** Shown when the list has no items, without filters or search. */
|
|
65
|
+
emptyMessage?: ReactNode;
|
|
66
|
+
/** Accessible name of the list. Defaults to "Items". */
|
|
67
|
+
'aria-label'?: string;
|
|
68
|
+
className?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Renders the list state of `@panneau/core`: the items of the current page in a layout (table or
|
|
72
|
+
* cards), with sorting, search, filters and their chips, pagination, selection and actions. It
|
|
73
|
+
* fetches nothing: the caller gives the items of the list's query and their total.
|
|
74
|
+
*/
|
|
75
|
+
export declare function ListView({ list, items, columns, total, isLoading, error, onRetry, filters, fields, search, layouts: layoutsProp, layout: controlledLayout, onLayoutChange, perPageOptions, selectable: selectableProp, actions: actionsProp, onAction, actionIcons, itemTitle, getItemLabel: getItemLabelProp, getItemHref, displays, layoutComponents, filterControls, toolbar, emptyMessage, 'aria-label': ariaLabel, className, }: ListViewProps): import("react").JSX.Element;
|
|
76
|
+
//# sourceMappingURL=ListView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListView.d.ts","sourceRoot":"","sources":["../src/ListView.tsx"],"names":[],"mappings":"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"}
|