@craftainer/crud-views 0.0.0-stage → 0.2.0
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/LICENSE +674 -0
- package/README.md +85 -2
- package/dist/index.d.mts +1180 -0
- package/dist/index.mjs +5468 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +87 -4
package/README.md
CHANGED
|
@@ -1,3 +1,86 @@
|
|
|
1
|
-
#
|
|
1
|
+
# lib-crud-views-ts
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> [!NOTE]
|
|
4
|
+
> This repository is vibe coded with [Claude](https://claude.com/product/claude-code).
|
|
5
|
+
|
|
6
|
+
`@craftainer/crud-views`: manifest-driven CRUD views for React on MUI. One
|
|
7
|
+
component renders any resource a craftainer CRUD server describes in its
|
|
8
|
+
manifest, using [`@craftainer/crud-sdk`](https://github.com/craftainer/lib-crud-sdk-ts)
|
|
9
|
+
for data and TanStack Query for caching. This version ships the **core**:
|
|
10
|
+
|
|
11
|
+
- `CrudProvider` (SDK client, `QueryClient`, optional MUI theme, renderers);
|
|
12
|
+
- `useResource(name, apiVersion?)`: manifest entry, capabilities, described
|
|
13
|
+
fields, SDK handle and TanStack hooks, and `ResourceGate` for its loading and
|
|
14
|
+
error states;
|
|
15
|
+
- the field-renderer registry (contract
|
|
16
|
+
[I4](docs/contracts/I4-field-renderers.md)): display, input and filter
|
|
17
|
+
renderers per field kind and format, overridable per field, per provider or
|
|
18
|
+
process-wide;
|
|
19
|
+
- layout shells: `PageShell`, `DialogShell`, `DrawerShell`.
|
|
20
|
+
|
|
21
|
+
The views build on it, one directory per area under `src/`: list (table,
|
|
22
|
+
cards, load-more), filter (bar, builder, facets, URL query state), form
|
|
23
|
+
(create and edit, validation, auto-save, conflicts), delete (four delete
|
|
24
|
+
variants), detail (record page, field list), revisions (history and diff),
|
|
25
|
+
bulk (selection, publish, delete, export), lifecycle (drafts, archive, trash,
|
|
26
|
+
status filter) and stats (stats dashboard and predictions). The package is theme-agnostic (it reads only the MUI
|
|
27
|
+
theme it is given) and uses only the MIT tier of MUI X. It is an instance of
|
|
28
|
+
[`template-npm-package`](https://github.com/craftainer/template-npm-package);
|
|
29
|
+
the conventions shared with every instance are in
|
|
30
|
+
[`docs/TEMPLATE.md`](docs/TEMPLATE.md), the design in
|
|
31
|
+
[`docs/adrs/0002-core-design-and-field-renderers.md`](docs/adrs/0002-core-design-and-field-renderers.md).
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
Every library is a peer dependency:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
pnpm add @craftainer/crud-views @craftainer/crud-sdk @tanstack/react-query \
|
|
39
|
+
@mui/material @mui/x-data-grid @mui/x-charts @emotion/react @emotion/styled react react-dom
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { createClient } from "@craftainer/crud-sdk";
|
|
44
|
+
import { CrudProvider, ResourceGate, PageShell } from "@craftainer/crud-views";
|
|
45
|
+
|
|
46
|
+
const client = createClient({ baseUrl: "https://api.example.com" });
|
|
47
|
+
|
|
48
|
+
<CrudProvider client={client} queryClient={queryClient} theme={theme}>
|
|
49
|
+
<PageShell title="Heroes">
|
|
50
|
+
<ResourceGate name="heroes">{(heroes) => /* a view */ null}</ResourceGate>
|
|
51
|
+
</PageShell>
|
|
52
|
+
</CrudProvider>;
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Inline edit and ETags
|
|
56
|
+
|
|
57
|
+
The list endpoint returns no ETags, so the table's inline edit takes
|
|
58
|
+
`ifMatch(row)` from the app. It may return a string, `undefined` (the PATCH
|
|
59
|
+
goes without `If-Match`) or a promise of either, the same shape as
|
|
60
|
+
`ResourceForm`'s `etag`. `fetchEtagById` stands for the app's own lookup, for
|
|
61
|
+
example fetching the row through the SDK and reading its cached ETag:
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
<ResourceList
|
|
65
|
+
resource="heroes"
|
|
66
|
+
editable
|
|
67
|
+
ifMatch={async (row) =>
|
|
68
|
+
(await fetchEtagById(row["id"] as number)) ?? undefined
|
|
69
|
+
}
|
|
70
|
+
/>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The edit waits for the promise and stays in a saving state (the cell stays
|
|
74
|
+
in edit mode and the table is `aria-busy`); a rejection sends nothing and shows "Could not save: ..." like
|
|
75
|
+
any other save error.
|
|
76
|
+
|
|
77
|
+
## Development
|
|
78
|
+
|
|
79
|
+
Open the repository in the devcontainer, then run
|
|
80
|
+
`prek run --all-files --hook-stage manual`. `pnpm storybook` starts Storybook;
|
|
81
|
+
`tests/visual/run.sh` runs the visual suite (arm64 hosts only, see
|
|
82
|
+
[`tests/visual/README.md`](tests/visual/README.md)).
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
Licensed under the [GNU General Public License v3.0 or later](LICENSE).
|