@viglet/shio-react-sdk 2026.2.1 → 2026.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +127 -0
- package/dist/components/shio-blocks.d.ts +40 -0
- package/dist/hooks/use-shio-post.d.ts +14 -4
- package/dist/hooks/use-shio-query.d.ts +9 -2
- package/dist/index.d.ts +3 -1
- package/dist/shio-react-sdk.js +209 -154
- package/dist/shio-react-sdk.umd.cjs +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +33 -10
package/README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# @viglet/shio-react-sdk
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@viglet/shio-react-sdk)
|
|
4
|
+
[](https://github.com/openviglet/shio/blob/HEAD/LICENSE)
|
|
5
|
+
[](https://openviglet.github.io/shio/)
|
|
6
|
+
|
|
7
|
+
The **React SDK** for **[Viglet Shio](https://openviglet.github.io/shio/)**, the open
|
|
8
|
+
source, **agent-ready CMS**. Hooks and render components for
|
|
9
|
+
consuming Shio content through the **Content Delivery API (CDA)**, built on
|
|
10
|
+
[`@viglet/shio-client`](https://www.npmjs.com/package/@viglet/shio-client).
|
|
11
|
+
|
|
12
|
+
- **React 18 / 19** — `react` is a peer dependency.
|
|
13
|
+
- Targets the stable, read-only CDA contract (`/api/v2/cda/**`).
|
|
14
|
+
- Everything the core client exports is **re-exported** here, so this is the only
|
|
15
|
+
package a React app needs.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @viglet/shio-react-sdk react
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick start
|
|
24
|
+
|
|
25
|
+
Wrap your tree once:
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { ShioProvider } from "@viglet/shio-react-sdk";
|
|
29
|
+
|
|
30
|
+
export function App({ children }: { children: React.ReactNode }) {
|
|
31
|
+
return (
|
|
32
|
+
<ShioProvider
|
|
33
|
+
baseUrl="https://cms.example.com"
|
|
34
|
+
apiToken={import.meta.env.VITE_SHIO_CDA_TOKEN}
|
|
35
|
+
>
|
|
36
|
+
{children}
|
|
37
|
+
</ShioProvider>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Then read content anywhere below it:
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { useShioPostByUrl, ShioRichText } from "@viglet/shio-react-sdk";
|
|
46
|
+
|
|
47
|
+
function Article({ siteId, url }: { siteId: string; url: string }) {
|
|
48
|
+
const { data: post, loading, error } = useShioPostByUrl(siteId, url);
|
|
49
|
+
|
|
50
|
+
if (loading) return <p>Loading…</p>;
|
|
51
|
+
if (error) return <p>{error.message}</p>;
|
|
52
|
+
if (!post) return <p>Not found</p>;
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<article>
|
|
56
|
+
<h1>{String(post.attrs.title ?? "")}</h1>
|
|
57
|
+
<ShioRichText html={String(post.attrs.content ?? "")} />
|
|
58
|
+
</article>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`<ShioProvider>` also accepts an already-built client:
|
|
64
|
+
`<ShioProvider client={myClient}>`.
|
|
65
|
+
|
|
66
|
+
## Hooks
|
|
67
|
+
|
|
68
|
+
Every hook returns a `ShioAsyncState<T>` — `{ data, loading, error }`.
|
|
69
|
+
|
|
70
|
+
| Hook | Returns |
|
|
71
|
+
|---|---|
|
|
72
|
+
| `useShioSites()` | Every site the token can see |
|
|
73
|
+
| `useShioSite(siteId)` | One site |
|
|
74
|
+
| `useShioChildren(folderId, params?)` | A folder's children, paged |
|
|
75
|
+
| `useShioBreadcrumb(objectId)` | The path from the site root to an object |
|
|
76
|
+
| `useShioPost(postId)` | One post by id |
|
|
77
|
+
| `useShioPostByUrl(siteId, url)` | One post by its friendly URL — built for `[...slug]` routing |
|
|
78
|
+
| `useShioQuery(params?, enabled?)` | A query across a site / folder / post-type, paged |
|
|
79
|
+
| `useShioClient()` | The `ShioClient` from context, for anything the hooks don't cover |
|
|
80
|
+
|
|
81
|
+
## Components
|
|
82
|
+
|
|
83
|
+
| Component | For |
|
|
84
|
+
|---|---|
|
|
85
|
+
| `<ShioRichText html={…} />` | Renders an HTML-editor field safely into a `div` (accepts any `div` props) |
|
|
86
|
+
| `<ShioImage src={…} baseUrl={…} alt={…} />` | Resolves a stored file reference to a URL and renders an `img` |
|
|
87
|
+
| `<ShioRelator items={…}>` | Maps over a Relator (nested repeatable) field |
|
|
88
|
+
| `<ShioField value={…} as={…} />` | Renders one attribute by kind — `text`, `html`, `image`, `list`, `json` |
|
|
89
|
+
|
|
90
|
+
## Next.js
|
|
91
|
+
|
|
92
|
+
For **server components**, use
|
|
93
|
+
[`@viglet/shio-client`](https://www.npmjs.com/package/@viglet/shio-client)
|
|
94
|
+
directly — it is zero-dependency and needs no provider. Reach for this package
|
|
95
|
+
in **client components**, where the hooks give you loading and error state.
|
|
96
|
+
|
|
97
|
+
The fastest way to a working project is the generator, which wires both up for
|
|
98
|
+
you:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm create @viglet/shio-app@latest my-site
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Related packages
|
|
105
|
+
|
|
106
|
+
| Package | For |
|
|
107
|
+
|---|---|
|
|
108
|
+
| [`@viglet/shio-client`](https://www.npmjs.com/package/@viglet/shio-client) | The framework-agnostic core this is built on |
|
|
109
|
+
| [`@viglet/shio`](https://www.npmjs.com/package/@viglet/shio) | The Shio CLI — content as files, `shio types`, and the MCP bridge for [Claude Code](https://claude.com/claude-code) |
|
|
110
|
+
| [`@viglet/shio-sections`](https://www.npmjs.com/package/@viglet/shio-sections) | The page-section vocabulary and its React components |
|
|
111
|
+
| [`@viglet/shio-model`](https://www.npmjs.com/package/@viglet/shio-model) | Author the content model as typed code |
|
|
112
|
+
| [`@viglet/shio-editor-cors`](https://www.npmjs.com/package/@viglet/shio-editor-cors) | Inline visual editing with the Universal Editor |
|
|
113
|
+
| [`@viglet/create-shio-app`](https://www.npmjs.com/package/@viglet/create-shio-app) | Next.js starter generator |
|
|
114
|
+
|
|
115
|
+
## Develop
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npm run build # vite lib build + .d.ts
|
|
119
|
+
npm run typecheck
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
Apache-2.0 — [Viglet Shio](https://openviglet.github.io/shio/) ·
|
|
125
|
+
[github.com/openviglet/shio](https://github.com/openviglet/shio) ·
|
|
126
|
+
[docs.viglet.org/shio](https://docs.viglet.org/shio/) ·
|
|
127
|
+
part of the [Viglet](https://www.viglet.org) open source family.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { ShioBlock } from "@viglet/shio-client";
|
|
3
|
+
/** A component rendering one block of its kind. */
|
|
4
|
+
export type ShioBlockComponent<T extends ShioBlock = ShioBlock> = (props: {
|
|
5
|
+
block: T;
|
|
6
|
+
}) => ReactNode;
|
|
7
|
+
/** Block type to component. Every key is optional: a kind with no entry falls back. */
|
|
8
|
+
export type ShioBlockComponents = {
|
|
9
|
+
[K in ShioBlock["type"]]?: ShioBlockComponent<Extract<ShioBlock, {
|
|
10
|
+
type: K;
|
|
11
|
+
}>>;
|
|
12
|
+
};
|
|
13
|
+
export interface ShioBlocksProps {
|
|
14
|
+
/** The field's blocks — `shioBlocks(post, "BODY")` from the core client. */
|
|
15
|
+
blocks: ShioBlock[] | null | undefined;
|
|
16
|
+
/** A component per block type. Anything not named here uses the fallback. */
|
|
17
|
+
components?: ShioBlockComponents;
|
|
18
|
+
/**
|
|
19
|
+
* The rendered HTML the CDA delivers beside the blocks (`post.rendered?.BODY`), used for a
|
|
20
|
+
* block type this build has no component for.
|
|
21
|
+
*/
|
|
22
|
+
fallbackHtml?: Record<string, string> | string | null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* SH1016 — a blocks body rendered with your own components.
|
|
26
|
+
*
|
|
27
|
+
* <p>The CDA delivers a body twice: as an array of typed blocks and as HTML. This maps the first
|
|
28
|
+
* onto components you own, which is the whole reason the body stopped being a string.</p>
|
|
29
|
+
*
|
|
30
|
+
* <h2>The fallback is per block, not per document</h2>
|
|
31
|
+
*
|
|
32
|
+
* <p>A page with one block type you have no component for should render the seven it knows. Falling
|
|
33
|
+
* back for the whole document would make adding a block type to the model blank a page that was
|
|
34
|
+
* working — which is the failure a fallback exists to prevent, arriving by the fallback.</p>
|
|
35
|
+
*
|
|
36
|
+
* <p>An unhandled block renders a readable default rather than nothing: a heading is a heading, a
|
|
37
|
+
* list is a list. Rendering nothing is how content goes missing silently, and "I did not write a
|
|
38
|
+
* component for `embed`" should not mean "the embed is gone".</p>
|
|
39
|
+
*/
|
|
40
|
+
export declare function ShioBlocks({ blocks, components, fallbackHtml }: ShioBlocksProps): import("react").JSX.Element | null;
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
import type { ShioPost } from "@viglet/shio-client";
|
|
2
|
-
/**
|
|
3
|
-
|
|
1
|
+
import type { ShioContentState, ShioPost } from "@viglet/shio-client";
|
|
2
|
+
/**
|
|
3
|
+
* Get a published post by id (attributes expanded). `null` when not found.
|
|
4
|
+
*
|
|
5
|
+
* SH1081 — `state` asks for another version (`"draft"`, `"rev:<n>"`), which needs a preview token.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useShioPost(postId: string | undefined, state?: ShioContentState): import("./use-async").ShioAsyncState<ShioPost | null>;
|
|
4
8
|
/**
|
|
5
9
|
* Resolve a published post by site + friendly URL — the client-side analog of
|
|
6
10
|
* the catch-all route. `null` when unresolved.
|
|
11
|
+
*
|
|
12
|
+
* SH1081 — `options.locale` pins a translation and `options.state` asks for another version, as
|
|
13
|
+
* the client's `getPostByUrl` takes them.
|
|
7
14
|
*/
|
|
8
|
-
export declare function useShioPostByUrl(siteId: string | undefined, url: string | undefined
|
|
15
|
+
export declare function useShioPostByUrl(siteId: string | undefined, url: string | undefined, options?: {
|
|
16
|
+
locale?: string;
|
|
17
|
+
state?: ShioContentState;
|
|
18
|
+
}): import("./use-async").ShioAsyncState<ShioPost | null>;
|
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
import type { ShioListing, ShioQueryParams } from "@viglet/shio-client";
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Query published posts by site / folder / post type (always returns a listing).
|
|
4
|
+
*
|
|
5
|
+
* Pass `enabled: false` to defer the request until its inputs are ready — e.g.
|
|
6
|
+
* while a `siteId` is still being resolved from {@link useShioSites}. While
|
|
7
|
+
* disabled the hook stays idle (`loading: false`, `data: undefined`) and never
|
|
8
|
+
* fires a request with half-resolved params.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useShioQuery(params?: ShioQueryParams, enabled?: boolean): import("./use-async").ShioAsyncState<ShioListing>;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export { useShioBreadcrumb } from "./hooks/use-shio-breadcrumb";
|
|
|
9
9
|
export { useShioPost, useShioPostByUrl } from "./hooks/use-shio-post";
|
|
10
10
|
export { useShioQuery } from "./hooks/use-shio-query";
|
|
11
11
|
export { ShioRichText } from "./components/shio-rich-text";
|
|
12
|
+
export { ShioBlocks } from "./components/shio-blocks";
|
|
13
|
+
export type { ShioBlocksProps, ShioBlockComponent, ShioBlockComponents } from "./components/shio-blocks";
|
|
12
14
|
export type { ShioRichTextProps } from "./components/shio-rich-text";
|
|
13
15
|
export { ShioImage } from "./components/shio-image";
|
|
14
16
|
export type { ShioImageProps } from "./components/shio-image";
|
|
@@ -16,4 +18,4 @@ export { ShioRelator } from "./components/shio-relator";
|
|
|
16
18
|
export type { ShioRelatorProps } from "./components/shio-relator";
|
|
17
19
|
export { ShioField } from "./components/shio-field";
|
|
18
20
|
export type { ShioFieldProps, ShioFieldKind } from "./components/shio-field";
|
|
19
|
-
export type { ShioClientConfig, ShioRequestOptions, ShioSite, ShioFolder, ShioPostSummary, ShioPost, ShioListing, ShioPath, ShioQueryParams, ShioPageParams, } from "@viglet/shio-client";
|
|
21
|
+
export type { ShioClientConfig, ShioRequestOptions, ShioSite, ShioSiteLocales, ShioFolder, ShioPostSummary, ShioPost, ShioListing, ShioPath, ShioQueryParams, ShioPageParams, } from "@viglet/shio-client";
|
package/dist/shio-react-sdk.js
CHANGED
|
@@ -1,154 +1,209 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
function
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
1
|
+
import { Fragment as e, createContext as t, useContext as n, useEffect as r, useMemo as i, useState as a } from "react";
|
|
2
|
+
import { ShioClient as o, ShioClient as s, ShioHttpError as c, createShioClient as l } from "@viglet/shio-client";
|
|
3
|
+
import { Fragment as u, jsx as d } from "react/jsx-runtime";
|
|
4
|
+
// src/provider.tsx
|
|
5
|
+
var f = t(null);
|
|
6
|
+
function p(e) {
|
|
7
|
+
let { children: t } = e, n = "client" in e ? e.client : void 0, r = n ? void 0 : e, a = i(() => n ?? new s(r), [
|
|
8
|
+
n,
|
|
9
|
+
r?.baseUrl,
|
|
10
|
+
r?.apiToken,
|
|
11
|
+
r?.fetch,
|
|
12
|
+
r?.credentials
|
|
13
|
+
]);
|
|
14
|
+
return /* @__PURE__ */ d(f.Provider, {
|
|
15
|
+
value: a,
|
|
16
|
+
children: t
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function m() {
|
|
20
|
+
let e = n(f);
|
|
21
|
+
if (!e) throw Error("useShioClient must be used within a <ShioProvider>");
|
|
22
|
+
return e;
|
|
23
|
+
}
|
|
24
|
+
// src/hooks/use-async.ts
|
|
25
|
+
function h(e, t, n = !0) {
|
|
26
|
+
let [i, o] = a({
|
|
27
|
+
data: void 0,
|
|
28
|
+
loading: n,
|
|
29
|
+
error: null
|
|
30
|
+
});
|
|
31
|
+
return r(() => {
|
|
32
|
+
if (!n) {
|
|
33
|
+
o({
|
|
34
|
+
data: void 0,
|
|
35
|
+
loading: !1,
|
|
36
|
+
error: null
|
|
37
|
+
});
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
let t = new AbortController();
|
|
41
|
+
return o((e) => ({
|
|
42
|
+
...e,
|
|
43
|
+
loading: !0,
|
|
44
|
+
error: null
|
|
45
|
+
})), e(t.signal).then((e) => {
|
|
46
|
+
t.signal.aborted || o({
|
|
47
|
+
data: e,
|
|
48
|
+
loading: !1,
|
|
49
|
+
error: null
|
|
50
|
+
});
|
|
51
|
+
}).catch((e) => {
|
|
52
|
+
t.signal.aborted || o({
|
|
53
|
+
data: void 0,
|
|
54
|
+
loading: !1,
|
|
55
|
+
error: e instanceof Error ? e : Error(String(e))
|
|
56
|
+
});
|
|
57
|
+
}), () => t.abort();
|
|
58
|
+
}, t), i;
|
|
59
|
+
}
|
|
60
|
+
// src/hooks/use-shio-sites.ts
|
|
61
|
+
function g() {
|
|
62
|
+
let e = m();
|
|
63
|
+
return h((t) => e.getSites({ signal: t }), [e]);
|
|
64
|
+
}
|
|
65
|
+
function _(e) {
|
|
66
|
+
let t = m();
|
|
67
|
+
return h((n) => t.getSite(e, { signal: n }), [t, e], !!e);
|
|
68
|
+
}
|
|
69
|
+
// src/hooks/use-shio-children.ts
|
|
70
|
+
function v(e, t) {
|
|
71
|
+
let n = m();
|
|
72
|
+
return h((r) => n.listChildren(e, t, { signal: r }), [
|
|
73
|
+
n,
|
|
74
|
+
e,
|
|
75
|
+
t?.page,
|
|
76
|
+
t?.size,
|
|
77
|
+
t?.locale,
|
|
78
|
+
t?.state
|
|
79
|
+
], !!e);
|
|
80
|
+
}
|
|
81
|
+
// src/hooks/use-shio-breadcrumb.ts
|
|
82
|
+
function y(e) {
|
|
83
|
+
let t = m();
|
|
84
|
+
return h((n) => t.getPath(e, { signal: n }), [t, e], !!e);
|
|
85
|
+
}
|
|
86
|
+
// src/hooks/use-shio-post.ts
|
|
87
|
+
function b(e, t) {
|
|
88
|
+
let n = m();
|
|
89
|
+
return h((r) => n.getPost(e, {
|
|
90
|
+
signal: r,
|
|
91
|
+
state: t
|
|
92
|
+
}), [
|
|
93
|
+
n,
|
|
94
|
+
e,
|
|
95
|
+
t
|
|
96
|
+
], !!e);
|
|
97
|
+
}
|
|
98
|
+
function x(e, t, n) {
|
|
99
|
+
let r = m(), i = n?.locale, a = n?.state;
|
|
100
|
+
return h((n) => i ? r.getPostByUrl(e, t, i, {
|
|
101
|
+
signal: n,
|
|
102
|
+
state: a
|
|
103
|
+
}) : r.getPostByUrl(e, t, {
|
|
104
|
+
signal: n,
|
|
105
|
+
state: a
|
|
106
|
+
}), [
|
|
107
|
+
r,
|
|
108
|
+
e,
|
|
109
|
+
t,
|
|
110
|
+
i,
|
|
111
|
+
a
|
|
112
|
+
], !!e && !!t);
|
|
113
|
+
}
|
|
114
|
+
// src/hooks/use-shio-query.ts
|
|
115
|
+
function S(e, t = !0) {
|
|
116
|
+
let n = m();
|
|
117
|
+
return h((t) => n.query(e, { signal: t }), [
|
|
118
|
+
n,
|
|
119
|
+
e?.siteId,
|
|
120
|
+
e?.folderId,
|
|
121
|
+
e?.postType,
|
|
122
|
+
e?.page,
|
|
123
|
+
e?.size,
|
|
124
|
+
e?.locale,
|
|
125
|
+
e?.state
|
|
126
|
+
], t);
|
|
127
|
+
}
|
|
128
|
+
// src/components/shio-rich-text.tsx
|
|
129
|
+
function C({ html: e, ...t }) {
|
|
130
|
+
return e ? /* @__PURE__ */ d("div", {
|
|
131
|
+
...t,
|
|
132
|
+
dangerouslySetInnerHTML: { __html: e }
|
|
133
|
+
}) : null;
|
|
134
|
+
}
|
|
135
|
+
// src/components/shio-blocks.tsx
|
|
136
|
+
function w({ blocks: e, components: t, fallbackHtml: n }) {
|
|
137
|
+
return e?.length ? /* @__PURE__ */ d(u, { children: e.map((e) => {
|
|
138
|
+
let r = t?.[e.type];
|
|
139
|
+
return /* @__PURE__ */ d("div", { children: r ? /* @__PURE__ */ d(r, { block: e }) : T(e, n) }, e.key);
|
|
140
|
+
}) }) : null;
|
|
141
|
+
}
|
|
142
|
+
function T(e, t) {
|
|
143
|
+
switch (e.type) {
|
|
144
|
+
case "heading": {
|
|
145
|
+
let t = `h${Math.min(6, Math.max(1, e.level ?? 2))}`;
|
|
146
|
+
return /* @__PURE__ */ d(t, { children: e.text });
|
|
147
|
+
}
|
|
148
|
+
case "paragraph": return /* @__PURE__ */ d("p", { children: e.text });
|
|
149
|
+
case "quote": return /* @__PURE__ */ d("blockquote", { children: e.text });
|
|
150
|
+
case "code": return /* @__PURE__ */ d("pre", { children: /* @__PURE__ */ d("code", { children: e.text }) });
|
|
151
|
+
case "list": return e.ordered ? /* @__PURE__ */ d("ol", { children: (e.items ?? []).map(E) }) : /* @__PURE__ */ d("ul", { children: (e.items ?? []).map(E) });
|
|
152
|
+
case "image": return /* @__PURE__ */ d("img", {
|
|
153
|
+
src: e.src,
|
|
154
|
+
alt: e.alt ?? ""
|
|
155
|
+
});
|
|
156
|
+
case "embed":
|
|
157
|
+
case "reference": return null;
|
|
158
|
+
default: return typeof t == "string" && t ? /* @__PURE__ */ d("div", { dangerouslySetInnerHTML: { __html: t } }) : null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function E(e, t) {
|
|
162
|
+
return /* @__PURE__ */ d("li", { children: e }, `${t}-${e}`);
|
|
163
|
+
}
|
|
164
|
+
// src/components/shio-image.tsx
|
|
165
|
+
function D({ src: e, baseUrl: t, alt: n = "", ...r }) {
|
|
166
|
+
if (!e) return null;
|
|
167
|
+
let i = /^(https?:)?\/\//.test(e) || e.startsWith("data:") || !t ? e : `${t.replace(/\/+$/, "")}/${e.replace(/^\/+/, "")}`;
|
|
168
|
+
return /* @__PURE__ */ d("img", {
|
|
169
|
+
src: i,
|
|
170
|
+
alt: n,
|
|
171
|
+
...r
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
// src/components/shio-relator.tsx
|
|
175
|
+
function O({ items: t, children: n, keyFor: r }) {
|
|
176
|
+
return /* @__PURE__ */ d(u, { children: (Array.isArray(t) ? t : []).map((t, i) => /* @__PURE__ */ d(e, { children: n(t, i) }, r ? r(t, i) : i)) });
|
|
177
|
+
}
|
|
178
|
+
// src/components/shio-field.tsx
|
|
179
|
+
var k = /<[a-z][\s\S]*>/i, A = /\.(png|jpe?g|gif|webp|svg|avif)$/i;
|
|
180
|
+
function j(e) {
|
|
181
|
+
return typeof e == "string" ? k.test(e) ? "html" : A.test(e.trim()) ? "image" : "text" : Array.isArray(e) ? "list" : typeof e == "object" && e ? "json" : "text";
|
|
182
|
+
}
|
|
183
|
+
function M({ value: e, as: t, baseUrl: n, className: r }) {
|
|
184
|
+
if (e == null || e === "") return null;
|
|
185
|
+
switch (t ?? j(e)) {
|
|
186
|
+
case "html": return /* @__PURE__ */ d(C, {
|
|
187
|
+
className: r,
|
|
188
|
+
html: String(e)
|
|
189
|
+
});
|
|
190
|
+
case "image": return /* @__PURE__ */ d(D, {
|
|
191
|
+
className: r,
|
|
192
|
+
src: String(e),
|
|
193
|
+
baseUrl: n
|
|
194
|
+
});
|
|
195
|
+
case "list": return /* @__PURE__ */ d("ul", {
|
|
196
|
+
className: r,
|
|
197
|
+
children: e.map((e, t) => /* @__PURE__ */ d("li", { children: typeof e == "object" ? JSON.stringify(e) : String(e) }, t))
|
|
198
|
+
});
|
|
199
|
+
case "json": return /* @__PURE__ */ d("pre", {
|
|
200
|
+
className: r,
|
|
201
|
+
children: JSON.stringify(e, null, 2)
|
|
202
|
+
});
|
|
203
|
+
default: return /* @__PURE__ */ d("span", {
|
|
204
|
+
className: r,
|
|
205
|
+
children: String(e)
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
export { w as ShioBlocks, o as ShioClient, M as ShioField, c as ShioHttpError, D as ShioImage, p as ShioProvider, O as ShioRelator, C as ShioRichText, l as createShioClient, y as useShioBreadcrumb, v as useShioChildren, m as useShioClient, b as useShioPost, x as useShioPostByUrl, S as useShioQuery, _ as useShioSite, g as useShioSites };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react"),require("@viglet/shio-client"),require("react/jsx-runtime")):typeof define==`function`&&define.amd?define([`exports`,`react`,`@viglet/shio-client`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ShioReactSdk={},e.React,e.ShioClient,e.jsxRuntime))})(this,function(e,t,n,r){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var i=(0,t.createContext)(null);function a(e){let{children:a}=e,o=`client`in e?e.client:void 0,s=o?void 0:e,c=(0,t.useMemo)(()=>o??new n.ShioClient(s),[o,s?.baseUrl,s?.apiToken,s?.fetch,s?.credentials]);return(0,r.jsx)(i.Provider,{value:c,children:a})}function o(){let e=(0,t.useContext)(i);if(!e)throw Error(`useShioClient must be used within a <ShioProvider>`);return e}function s(e,n,r=!0){let[i,a]=(0,t.useState)({data:void 0,loading:r,error:null});return(0,t.useEffect)(()=>{if(!r){a({data:void 0,loading:!1,error:null});return}let t=new AbortController;return a(e=>({...e,loading:!0,error:null})),e(t.signal).then(e=>{t.signal.aborted||a({data:e,loading:!1,error:null})}).catch(e=>{t.signal.aborted||a({data:void 0,loading:!1,error:e instanceof Error?e:Error(String(e))})}),()=>t.abort()},n),i}function c(){let e=o();return s(t=>e.getSites({signal:t}),[e])}function l(e){let t=o();return s(n=>t.getSite(e,{signal:n}),[t,e],!!e)}function u(e,t){let n=o();return s(r=>n.listChildren(e,t,{signal:r}),[n,e,t?.page,t?.size,t?.locale,t?.state],!!e)}function d(e){let t=o();return s(n=>t.getPath(e,{signal:n}),[t,e],!!e)}function f(e,t){let n=o();return s(r=>n.getPost(e,{signal:r,state:t}),[n,e,t],!!e)}function p(e,t,n){let r=o(),i=n?.locale,a=n?.state;return s(n=>i?r.getPostByUrl(e,t,i,{signal:n,state:a}):r.getPostByUrl(e,t,{signal:n,state:a}),[r,e,t,i,a],!!e&&!!t)}function m(e,t=!0){let n=o();return s(t=>n.query(e,{signal:t}),[n,e?.siteId,e?.folderId,e?.postType,e?.page,e?.size,e?.locale,e?.state],t)}function h({html:e,...t}){return e?(0,r.jsx)(`div`,{...t,dangerouslySetInnerHTML:{__html:e}}):null}function g({blocks:e,components:t,fallbackHtml:n}){return e?.length?(0,r.jsx)(r.Fragment,{children:e.map(e=>{let i=t?.[e.type];return(0,r.jsx)(`div`,{children:i?(0,r.jsx)(i,{block:e}):_(e,n)},e.key)})}):null}function _(e,t){switch(e.type){case`heading`:{let t=`h${Math.min(6,Math.max(1,e.level??2))}`;return(0,r.jsx)(t,{children:e.text})}case`paragraph`:return(0,r.jsx)(`p`,{children:e.text});case`quote`:return(0,r.jsx)(`blockquote`,{children:e.text});case`code`:return(0,r.jsx)(`pre`,{children:(0,r.jsx)(`code`,{children:e.text})});case`list`:return e.ordered?(0,r.jsx)(`ol`,{children:(e.items??[]).map(v)}):(0,r.jsx)(`ul`,{children:(e.items??[]).map(v)});case`image`:return(0,r.jsx)(`img`,{src:e.src,alt:e.alt??``});case`embed`:case`reference`:return null;default:return typeof t==`string`&&t?(0,r.jsx)(`div`,{dangerouslySetInnerHTML:{__html:t}}):null}}function v(e,t){return(0,r.jsx)(`li`,{children:e},`${t}-${e}`)}function y({src:e,baseUrl:t,alt:n=``,...i}){if(!e)return null;let a=/^(https?:)?\/\//.test(e)||e.startsWith(`data:`)||!t?e:`${t.replace(/\/+$/,``)}/${e.replace(/^\/+/,``)}`;return(0,r.jsx)(`img`,{src:a,alt:n,...i})}function b({items:e,children:n,keyFor:i}){return(0,r.jsx)(r.Fragment,{children:(Array.isArray(e)?e:[]).map((e,a)=>(0,r.jsx)(t.Fragment,{children:n(e,a)},i?i(e,a):a))})}var x=/<[a-z][\s\S]*>/i,S=/\.(png|jpe?g|gif|webp|svg|avif)$/i;function C(e){return typeof e==`string`?x.test(e)?`html`:S.test(e.trim())?`image`:`text`:Array.isArray(e)?`list`:typeof e==`object`&&e?`json`:`text`}function w({value:e,as:t,baseUrl:n,className:i}){if(e==null||e===``)return null;switch(t??C(e)){case`html`:return(0,r.jsx)(h,{className:i,html:String(e)});case`image`:return(0,r.jsx)(y,{className:i,src:String(e),baseUrl:n});case`list`:return(0,r.jsx)(`ul`,{className:i,children:e.map((e,t)=>(0,r.jsx)(`li`,{children:typeof e==`object`?JSON.stringify(e):String(e)},t))});case`json`:return(0,r.jsx)(`pre`,{className:i,children:JSON.stringify(e,null,2)});default:return(0,r.jsx)(`span`,{className:i,children:String(e)})}}e.ShioBlocks=g,Object.defineProperty(e,"ShioClient",{enumerable:!0,get:function(){return n.ShioClient}}),e.ShioField=w,Object.defineProperty(e,"ShioHttpError",{enumerable:!0,get:function(){return n.ShioHttpError}}),e.ShioImage=y,e.ShioProvider=a,e.ShioRelator=b,e.ShioRichText=h,Object.defineProperty(e,"createShioClient",{enumerable:!0,get:function(){return n.createShioClient}}),e.useShioBreadcrumb=d,e.useShioChildren=u,e.useShioClient=o,e.useShioPost=f,e.useShioPostByUrl=p,e.useShioQuery=m,e.useShioSite=l,e.useShioSites=c});
|
package/dist/types.d.ts
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* re-exported here for convenience, so React consumers can import them from a
|
|
4
4
|
* single package.
|
|
5
5
|
*/
|
|
6
|
-
export type { ShioClientConfig, ShioRequestOptions, ShioSite, ShioFolder, ShioPostSummary, ShioPost, ShioListing, ShioPath, ShioQueryParams, ShioPageParams, } from "@viglet/shio-client";
|
|
6
|
+
export type { ShioClientConfig, ShioRequestOptions, ShioSite, ShioSiteLocales, ShioFolder, ShioPostSummary, ShioPost, ShioListing, ShioPath, ShioQueryParams, ShioPageParams, } from "@viglet/shio-client";
|
package/package.json
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viglet/shio-react-sdk",
|
|
3
|
-
"version": "2026.
|
|
4
|
-
"description": "React SDK for consuming Shio
|
|
3
|
+
"version": "2026.3.3",
|
|
4
|
+
"description": "React SDK for consuming Viglet Shio content via the Content Delivery API (CDA). Hooks + render components built on @viglet/shio-client.",
|
|
5
|
+
"homepage": "https://openviglet.github.io/shio/",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/openviglet/shio.git",
|
|
9
|
+
"directory": "shio-react-sdk"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/openviglet/shio/issues"
|
|
13
|
+
},
|
|
5
14
|
"type": "module",
|
|
6
15
|
"main": "dist/shio-react-sdk.umd.cjs",
|
|
7
16
|
"module": "dist/shio-react-sdk.js",
|
|
@@ -17,27 +26,41 @@
|
|
|
17
26
|
"dist"
|
|
18
27
|
],
|
|
19
28
|
"dependencies": {
|
|
20
|
-
"@viglet/shio-client": "2026.
|
|
29
|
+
"@viglet/shio-client": "2026.3.3"
|
|
21
30
|
},
|
|
22
31
|
"peerDependencies": {
|
|
23
32
|
"react": ">=18.0.0"
|
|
24
33
|
},
|
|
25
34
|
"devDependencies": {
|
|
26
|
-
"@types/react": "^19.
|
|
27
|
-
"react": "^19.1
|
|
35
|
+
"@types/react": "^19.3.0",
|
|
36
|
+
"react": "^19.3.1",
|
|
28
37
|
"typescript": "^5.8.3",
|
|
29
|
-
"vite": "^
|
|
38
|
+
"vite": "^8.3.5"
|
|
30
39
|
},
|
|
31
40
|
"keywords": [
|
|
32
41
|
"shio",
|
|
42
|
+
"viglet",
|
|
33
43
|
"cms",
|
|
34
|
-
"headless",
|
|
44
|
+
"headless-cms",
|
|
45
|
+
"content-management-system",
|
|
46
|
+
"agent",
|
|
47
|
+
"ai",
|
|
48
|
+
"mcp",
|
|
49
|
+
"model-context-protocol",
|
|
50
|
+
"claude-code",
|
|
35
51
|
"react",
|
|
36
52
|
"sdk",
|
|
37
|
-
"cda"
|
|
53
|
+
"cda",
|
|
54
|
+
"hooks",
|
|
55
|
+
"nextjs",
|
|
56
|
+
"typescript",
|
|
57
|
+
"headless"
|
|
38
58
|
],
|
|
39
|
-
"author":
|
|
40
|
-
|
|
59
|
+
"author": {
|
|
60
|
+
"name": "Viglet Team",
|
|
61
|
+
"url": "https://www.viglet.org"
|
|
62
|
+
},
|
|
63
|
+
"license": "Apache-2.0",
|
|
41
64
|
"scripts": {
|
|
42
65
|
"dev": "vite build --watch",
|
|
43
66
|
"build": "vite build && tsc --emitDeclarationOnly",
|