@localess/react 3.0.1-dev.20260408183951 → 3.0.1-dev.20260410065141
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 +189 -7
- package/dist/chunk-AJP75NRT.mjs +56 -0
- package/dist/chunk-ETSLIILF.mjs +149 -0
- package/dist/chunk-V6JSXN66.mjs +76 -0
- package/dist/index.d.mts +4 -89
- package/dist/index.d.ts +4 -89
- package/dist/index.js +73 -89
- package/dist/index.mjs +25 -210
- package/dist/richtext-XH7pH80J.d.mts +82 -0
- package/dist/richtext-XH7pH80J.d.ts +82 -0
- package/dist/rsc.d.mts +5 -0
- package/dist/rsc.d.ts +5 -0
- package/dist/rsc.js +294 -0
- package/dist/rsc.mjs +46 -0
- package/dist/ssr.d.mts +18 -0
- package/dist/ssr.d.ts +18 -0
- package/dist/ssr.js +223 -0
- package/dist/ssr.mjs +38 -0
- package/package.json +13 -3
package/README.md
CHANGED
|
@@ -34,6 +34,51 @@ pnpm add @localess/react
|
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
37
|
+
## Choosing the Right Export
|
|
38
|
+
|
|
39
|
+
`@localess/react` provides three different exports to suit different rendering strategies:
|
|
40
|
+
|
|
41
|
+
| Export | Use Case | Live Editing | Static Export |
|
|
42
|
+
|---|---|---|---|
|
|
43
|
+
| `@localess/react` | Single Page Applications (SPA), client-side rendering | ✅ | ✅ |
|
|
44
|
+
| `@localess/react/ssr` | SSR without live editing, Next.js static exports | ❌ | ✅ |
|
|
45
|
+
| `@localess/react/rsc` | React Server Components with live editing | ✅ | ❌ |
|
|
46
|
+
|
|
47
|
+
### When to Use Each Export
|
|
48
|
+
|
|
49
|
+
**Use `@localess/react`** (default) for:
|
|
50
|
+
- Single Page Applications (SPA) or fully client-rendered React apps
|
|
51
|
+
- Apps where `localessInit` and components run entirely in the browser
|
|
52
|
+
|
|
53
|
+
**Use `@localess/react/ssr`** for:
|
|
54
|
+
- Next.js projects with `output: 'export'` (static site generation)
|
|
55
|
+
- Server-side rendering where live editing is not required
|
|
56
|
+
- Scenarios where bundle size matters and you want to exclude all browser-only sync code
|
|
57
|
+
|
|
58
|
+
**Use `@localess/react/rsc`** for:
|
|
59
|
+
- Next.js App Router with React Server Components
|
|
60
|
+
- Apps that need live Visual Editor editing alongside server rendering
|
|
61
|
+
- Modern Next.js apps with a server/client component split
|
|
62
|
+
|
|
63
|
+
### Quick Comparison
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
// SPA — everything runs client-side
|
|
67
|
+
import { localessInit, LocalessComponent, useLocaless } from "@localess/react";
|
|
68
|
+
|
|
69
|
+
// SSR — server-safe, no live editing, no hooks
|
|
70
|
+
import { localessInit, LocalessComponent } from "@localess/react/ssr";
|
|
71
|
+
|
|
72
|
+
// RSC — server components + client components for live editing
|
|
73
|
+
import { localessInit, LocalessComponent } from "@localess/react/rsc"; // server
|
|
74
|
+
import { LocalessDocument, useLocaless, localessEditable } from "@localess/react/rsc"; // client
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
> [!NOTE]
|
|
78
|
+
> When using Next.js with `output: 'export'`, always use `@localess/react/ssr`. The RSC export is not compatible with static exports.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
37
82
|
## Getting Started
|
|
38
83
|
|
|
39
84
|
### 1. Initialize the SDK
|
|
@@ -421,9 +466,9 @@ export function PageClient({ initialContent }: { initialContent: Content<Page> }
|
|
|
421
466
|
|
|
422
467
|
---
|
|
423
468
|
|
|
424
|
-
## Full Example
|
|
469
|
+
## Full Example — SPA / Default (`@localess/react`)
|
|
425
470
|
|
|
426
|
-
|
|
471
|
+
For SPAs or fully client-rendered React apps. All imports use the default `@localess/react` export.
|
|
427
472
|
|
|
428
473
|
### Setup — `app/layout.tsx`
|
|
429
474
|
|
|
@@ -570,15 +615,152 @@ export function PageClientManual({
|
|
|
570
615
|
|
|
571
616
|
---
|
|
572
617
|
|
|
573
|
-
##
|
|
618
|
+
## Full Example — Next.js Static Export (`@localess/react/ssr`)
|
|
619
|
+
|
|
620
|
+
Use `@localess/react/ssr` when your Next.js project uses `output: 'export'` for static site generation. Live editing is not available in this mode.
|
|
621
|
+
|
|
622
|
+
### `next.config.js`
|
|
623
|
+
|
|
624
|
+
```js
|
|
625
|
+
/** @type {import('next').NextConfig} */
|
|
626
|
+
module.exports = { output: 'export' };
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
### Setup — `lib/localess.ts`
|
|
630
|
+
|
|
631
|
+
```ts
|
|
632
|
+
import { localessInit } from "@localess/react/ssr";
|
|
633
|
+
import { Page, Header, Teaser } from "@/components";
|
|
634
|
+
|
|
635
|
+
export const getClient = localessInit({
|
|
636
|
+
origin: process.env.LOCALESS_ORIGIN!,
|
|
637
|
+
spaceId: process.env.LOCALESS_SPACE_ID!,
|
|
638
|
+
token: process.env.LOCALESS_TOKEN!,
|
|
639
|
+
// enableSync is not applicable in static export — omit or set to false
|
|
640
|
+
components: { Page, Header, Teaser },
|
|
641
|
+
});
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
### Page — `app/page.tsx`
|
|
645
|
+
|
|
646
|
+
```tsx
|
|
647
|
+
import { LocalessComponent } from "@localess/react/ssr";
|
|
648
|
+
import { getLocalessClient } from "@localess/react/ssr";
|
|
649
|
+
import "@/lib/localess"; // ensure init runs
|
|
650
|
+
|
|
651
|
+
export default async function Home() {
|
|
652
|
+
const client = getLocalessClient();
|
|
653
|
+
const content = await client.getContentBySlug("home", { locale: "en" });
|
|
654
|
+
return (
|
|
655
|
+
<main>
|
|
656
|
+
<LocalessComponent data={content.data} links={content.links} references={content.references} />
|
|
657
|
+
</main>
|
|
658
|
+
);
|
|
659
|
+
}
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
---
|
|
663
|
+
|
|
664
|
+
## Full Example — Next.js App Router with RSC (`@localess/react/rsc`)
|
|
665
|
+
|
|
666
|
+
Use `@localess/react/rsc` when you want React Server Components and Visual Editor live editing together.
|
|
667
|
+
|
|
668
|
+
### Setup — `app/layout.tsx`
|
|
669
|
+
|
|
670
|
+
```tsx
|
|
671
|
+
// Server Component — safe to use API token here
|
|
672
|
+
import { localessInit } from "@localess/react/rsc";
|
|
673
|
+
import { Page, Header, Teaser, Footer } from "@/components";
|
|
674
|
+
|
|
675
|
+
localessInit({
|
|
676
|
+
origin: process.env.LOCALESS_ORIGIN!,
|
|
677
|
+
spaceId: process.env.LOCALESS_SPACE_ID!,
|
|
678
|
+
token: process.env.LOCALESS_TOKEN!,
|
|
679
|
+
enableSync: process.env.NODE_ENV !== 'production',
|
|
680
|
+
components: { Page, Header, Teaser, Footer },
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
684
|
+
return <html><body>{children}</body></html>;
|
|
685
|
+
}
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
### Server Component — `app/[locale]/page.tsx`
|
|
689
|
+
|
|
690
|
+
```tsx
|
|
691
|
+
import { getLocalessClient } from "@localess/react/rsc";
|
|
692
|
+
import PageClient from "./page-client";
|
|
693
|
+
|
|
694
|
+
export default async function Home({ params }: { params: { locale: string } }) {
|
|
695
|
+
const { locale } = await params;
|
|
696
|
+
const content = await getLocalessClient().getContentBySlug("home", { locale });
|
|
697
|
+
return <PageClient initialContent={content} locale={locale} />;
|
|
698
|
+
}
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### Client Component — `app/[locale]/page-client.tsx`
|
|
574
702
|
|
|
575
|
-
|
|
703
|
+
Use `LocalessDocument` for a zero-boilerplate live-editing integration, or `useLocaless` for more control:
|
|
576
704
|
|
|
577
|
-
**
|
|
705
|
+
**Option A — `LocalessDocument` (recommended):**
|
|
578
706
|
|
|
579
|
-
|
|
707
|
+
```tsx
|
|
708
|
+
'use client';
|
|
709
|
+
import { LocalessDocument } from "@localess/react/rsc";
|
|
710
|
+
|
|
711
|
+
export default function PageClient({ initialContent }) {
|
|
712
|
+
return (
|
|
713
|
+
<LocalessDocument
|
|
714
|
+
data={initialContent.data}
|
|
715
|
+
links={initialContent.links}
|
|
716
|
+
references={initialContent.references}
|
|
717
|
+
/>
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
**Option B — `useLocaless` hook:**
|
|
723
|
+
|
|
724
|
+
```tsx
|
|
725
|
+
'use client';
|
|
726
|
+
import { useLocaless, LocalessComponent, localessEditable } from "@localess/react/rsc";
|
|
727
|
+
|
|
728
|
+
export default function PageClient({ initialContent, locale }) {
|
|
729
|
+
const content = useLocaless("home", { locale }) ?? initialContent;
|
|
730
|
+
return (
|
|
731
|
+
<main {...localessEditable(content.data)}>
|
|
732
|
+
{content.data?.body?.map(item => (
|
|
733
|
+
<LocalessComponent key={item._id} data={item} links={content.links} references={content.references} />
|
|
734
|
+
))}
|
|
735
|
+
</main>
|
|
736
|
+
);
|
|
737
|
+
}
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
---
|
|
580
741
|
|
|
581
|
-
|
|
742
|
+
## Export Reference
|
|
743
|
+
|
|
744
|
+
The table below shows which symbols are available in each export.
|
|
745
|
+
|
|
746
|
+
| Symbol | `@localess/react` | `@localess/react/ssr` | `@localess/react/rsc` |
|
|
747
|
+
|---|:---:|:---:|:---:|
|
|
748
|
+
| `localessInit` | ✅ | ✅ | ✅ |
|
|
749
|
+
| `getLocalessClient` | ✅ | ✅ | ✅ |
|
|
750
|
+
| `registerComponent` / `setComponents` / `getComponent` | ✅ | ✅ | ✅ |
|
|
751
|
+
| `setFallbackComponent` / `getFallbackComponent` | ✅ | ✅ | ✅ |
|
|
752
|
+
| `resolveAsset` | ✅ | ✅ | ✅ |
|
|
753
|
+
| `LocalessComponent` | ✅ | ✅ | ✅ |
|
|
754
|
+
| `renderRichTextToReact` | ✅ | ✅ | ✅ |
|
|
755
|
+
| `findLink` | ✅ | ✅ | ✅ |
|
|
756
|
+
| `isServer` | ✅ | ✅ | ✅ |
|
|
757
|
+
| All content types | ✅ | ✅ | ✅ |
|
|
758
|
+
| `LocalessDocument` | ✅ | ❌ | ✅ |
|
|
759
|
+
| `useLocaless` | ✅ | ❌ | ✅ |
|
|
760
|
+
| `localessEditable` / `localessEditableField` | ✅ | ❌ | ✅ |
|
|
761
|
+
| `isBrowser` / `isIframe` | ✅ | ❌ | ✅ |
|
|
762
|
+
| `isSyncEnabled` | ✅ | ❌ | ✅ |
|
|
763
|
+
| Sync event types (`LocalessSync`, `EventToApp`, …) | ✅ | ❌ | ✅ |
|
|
582
764
|
|
|
583
765
|
---
|
|
584
766
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FONT_BOLD,
|
|
3
|
+
FONT_NORMAL,
|
|
4
|
+
getComponent,
|
|
5
|
+
getFallbackComponent
|
|
6
|
+
} from "./chunk-ETSLIILF.mjs";
|
|
7
|
+
|
|
8
|
+
// src/ssr/localess-component.tsx
|
|
9
|
+
import { forwardRef } from "react";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
var LocalessServerComponent = forwardRef(({ data, links, references, ...restProps }, ref) => {
|
|
12
|
+
if (!data) {
|
|
13
|
+
console.error("LocalessServerComponent property %cdata%c is not provided.", FONT_BOLD, FONT_NORMAL);
|
|
14
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
15
|
+
"LocalessServerComponent property ",
|
|
16
|
+
/* @__PURE__ */ jsx("b", { children: "data" }),
|
|
17
|
+
" is not provided."
|
|
18
|
+
] });
|
|
19
|
+
}
|
|
20
|
+
const Comp = getComponent(data._schema);
|
|
21
|
+
if (Comp) {
|
|
22
|
+
return /* @__PURE__ */ jsx(Comp, { ref, data, links, references, ...restProps });
|
|
23
|
+
}
|
|
24
|
+
const FallbackComponent = getFallbackComponent();
|
|
25
|
+
if (FallbackComponent) {
|
|
26
|
+
return /* @__PURE__ */ jsx(FallbackComponent, { ref, data, links, references, ...restProps });
|
|
27
|
+
}
|
|
28
|
+
return /* @__PURE__ */ jsxs("p", { children: [
|
|
29
|
+
/* @__PURE__ */ jsx("b", { children: "LocalessServerComponent" }),
|
|
30
|
+
" could not found component with key ",
|
|
31
|
+
/* @__PURE__ */ jsx("b", { children: data._schema }),
|
|
32
|
+
". ",
|
|
33
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
34
|
+
"Please check if your configuration is correct."
|
|
35
|
+
] });
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// src/ssr/localess-document.tsx
|
|
39
|
+
import { forwardRef as forwardRef2 } from "react";
|
|
40
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
41
|
+
var LocalessServerDocument = forwardRef2(({ document }, ref) => {
|
|
42
|
+
if (!document || !document.data) {
|
|
43
|
+
console.error("LocalessServerDocument property %cdocument.data%c is not provided.", FONT_BOLD, FONT_NORMAL);
|
|
44
|
+
return /* @__PURE__ */ jsxs2("div", { children: [
|
|
45
|
+
"LocalessServerDocument property ",
|
|
46
|
+
/* @__PURE__ */ jsx2("b", { children: "document.data" }),
|
|
47
|
+
" is not provided."
|
|
48
|
+
] });
|
|
49
|
+
}
|
|
50
|
+
return /* @__PURE__ */ jsx2(LocalessServerComponent, { ref, data: document.data, links: document.links, references: document.references });
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export {
|
|
54
|
+
LocalessServerComponent,
|
|
55
|
+
LocalessServerDocument
|
|
56
|
+
};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// src/core/state.ts
|
|
2
|
+
import { loadLocalessSync, localessClient } from "@localess/client";
|
|
3
|
+
|
|
4
|
+
// src/console.ts
|
|
5
|
+
var FONT_BOLD = "font-weight: bold";
|
|
6
|
+
var FONT_NORMAL = "font-weight: normal";
|
|
7
|
+
|
|
8
|
+
// src/core/state.ts
|
|
9
|
+
var _client = void 0;
|
|
10
|
+
var _components = {};
|
|
11
|
+
var _fallbackComponent = void 0;
|
|
12
|
+
var _enableSync = false;
|
|
13
|
+
var _assetPathPrefix = "";
|
|
14
|
+
function localessInit(options) {
|
|
15
|
+
console.log("localessInit", options);
|
|
16
|
+
const { components, fallbackComponent, enableSync, ...restOptions } = options;
|
|
17
|
+
_client = localessClient(restOptions);
|
|
18
|
+
_assetPathPrefix = `${options.origin}/api/v1/spaces/${options.spaceId}/assets/`;
|
|
19
|
+
_components = components || {};
|
|
20
|
+
_fallbackComponent = fallbackComponent;
|
|
21
|
+
if (enableSync) {
|
|
22
|
+
_enableSync = true;
|
|
23
|
+
loadLocalessSync(restOptions.origin);
|
|
24
|
+
}
|
|
25
|
+
return _client;
|
|
26
|
+
}
|
|
27
|
+
function getLocalessClient() {
|
|
28
|
+
if (!_client) {
|
|
29
|
+
console.error("[Localess] No client found. Please check if the Localess is initialized.");
|
|
30
|
+
throw new Error("[Localess] No client found.");
|
|
31
|
+
}
|
|
32
|
+
return _client;
|
|
33
|
+
}
|
|
34
|
+
function registerComponent(key, component) {
|
|
35
|
+
_components[key] = component;
|
|
36
|
+
}
|
|
37
|
+
function unregisterComponent(key) {
|
|
38
|
+
delete _components[key];
|
|
39
|
+
}
|
|
40
|
+
function setComponents(components) {
|
|
41
|
+
_components = components;
|
|
42
|
+
}
|
|
43
|
+
function getComponent(key) {
|
|
44
|
+
if (Object.hasOwn(_components, key)) {
|
|
45
|
+
return _components[key];
|
|
46
|
+
}
|
|
47
|
+
console.error(`[Localess] component %c${key}%c can't be found.`, FONT_BOLD, FONT_NORMAL);
|
|
48
|
+
return void 0;
|
|
49
|
+
}
|
|
50
|
+
function setFallbackComponent(fallbackComponent) {
|
|
51
|
+
_fallbackComponent = fallbackComponent;
|
|
52
|
+
}
|
|
53
|
+
function getFallbackComponent() {
|
|
54
|
+
return _fallbackComponent;
|
|
55
|
+
}
|
|
56
|
+
function isSyncEnabled() {
|
|
57
|
+
return _enableSync;
|
|
58
|
+
}
|
|
59
|
+
function resolveAsset(asset) {
|
|
60
|
+
return `${_assetPathPrefix}${asset.uri}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/core/utils/link.util.ts
|
|
64
|
+
function findLink(links, link) {
|
|
65
|
+
switch (link.type) {
|
|
66
|
+
case "content": {
|
|
67
|
+
if (links) {
|
|
68
|
+
const path = links[link.uri];
|
|
69
|
+
if (path) {
|
|
70
|
+
return "/" + path.fullSlug;
|
|
71
|
+
} else {
|
|
72
|
+
return "/not-found";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return "/not-found";
|
|
76
|
+
}
|
|
77
|
+
case "url":
|
|
78
|
+
return link.uri;
|
|
79
|
+
default:
|
|
80
|
+
return "no-type";
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// src/core/utils/index.ts
|
|
85
|
+
import { localessEditable, localessEditableField, isBrowser, isServer, isIframe } from "@localess/client";
|
|
86
|
+
|
|
87
|
+
// src/core/richtext.ts
|
|
88
|
+
import { renderToReactElement } from "@tiptap/static-renderer/pm/react";
|
|
89
|
+
import { Document } from "@tiptap/extension-document";
|
|
90
|
+
import { Text } from "@tiptap/extension-text";
|
|
91
|
+
import { Paragraph } from "@tiptap/extension-paragraph";
|
|
92
|
+
import { Heading } from "@tiptap/extension-heading";
|
|
93
|
+
import { Bold } from "@tiptap/extension-bold";
|
|
94
|
+
import { Italic } from "@tiptap/extension-italic";
|
|
95
|
+
import { Strike } from "@tiptap/extension-strike";
|
|
96
|
+
import { Underline } from "@tiptap/extension-underline";
|
|
97
|
+
import { History } from "@tiptap/extension-history";
|
|
98
|
+
import { ListItem } from "@tiptap/extension-list-item";
|
|
99
|
+
import { OrderedList } from "@tiptap/extension-ordered-list";
|
|
100
|
+
import { BulletList } from "@tiptap/extension-bullet-list";
|
|
101
|
+
import { Code } from "@tiptap/extension-code";
|
|
102
|
+
import { CodeBlockLowlight } from "@tiptap/extension-code-block-lowlight";
|
|
103
|
+
import { Link } from "@tiptap/extension-link";
|
|
104
|
+
function renderRichTextToReact(content) {
|
|
105
|
+
return renderToReactElement({
|
|
106
|
+
content,
|
|
107
|
+
extensions: [
|
|
108
|
+
Document,
|
|
109
|
+
Text,
|
|
110
|
+
Paragraph,
|
|
111
|
+
Heading.configure({
|
|
112
|
+
levels: [1, 2, 3, 4, 5, 6]
|
|
113
|
+
}),
|
|
114
|
+
Bold,
|
|
115
|
+
Italic,
|
|
116
|
+
Strike,
|
|
117
|
+
Underline,
|
|
118
|
+
History,
|
|
119
|
+
ListItem,
|
|
120
|
+
OrderedList,
|
|
121
|
+
BulletList,
|
|
122
|
+
Code,
|
|
123
|
+
CodeBlockLowlight,
|
|
124
|
+
Link
|
|
125
|
+
]
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export {
|
|
130
|
+
FONT_BOLD,
|
|
131
|
+
FONT_NORMAL,
|
|
132
|
+
localessInit,
|
|
133
|
+
getLocalessClient,
|
|
134
|
+
registerComponent,
|
|
135
|
+
unregisterComponent,
|
|
136
|
+
setComponents,
|
|
137
|
+
getComponent,
|
|
138
|
+
setFallbackComponent,
|
|
139
|
+
getFallbackComponent,
|
|
140
|
+
isSyncEnabled,
|
|
141
|
+
resolveAsset,
|
|
142
|
+
findLink,
|
|
143
|
+
localessEditable,
|
|
144
|
+
localessEditableField,
|
|
145
|
+
isBrowser,
|
|
146
|
+
isServer,
|
|
147
|
+
isIframe,
|
|
148
|
+
renderRichTextToReact
|
|
149
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FONT_BOLD,
|
|
3
|
+
FONT_NORMAL,
|
|
4
|
+
getComponent,
|
|
5
|
+
getFallbackComponent,
|
|
6
|
+
getLocalessClient,
|
|
7
|
+
isSyncEnabled,
|
|
8
|
+
localessEditable
|
|
9
|
+
} from "./chunk-ETSLIILF.mjs";
|
|
10
|
+
|
|
11
|
+
// src/core/components/localess-component.tsx
|
|
12
|
+
import { forwardRef } from "react";
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
var LocalessComponent = forwardRef(
|
|
15
|
+
({ data, links, references, ...restProps }, ref) => {
|
|
16
|
+
if (!data) {
|
|
17
|
+
console.error("LocalessComponent property %cdata%c is not provided.", FONT_BOLD, FONT_NORMAL);
|
|
18
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
19
|
+
"LocalessComponent property ",
|
|
20
|
+
/* @__PURE__ */ jsx("b", { children: "data" }),
|
|
21
|
+
" is not provided."
|
|
22
|
+
] });
|
|
23
|
+
}
|
|
24
|
+
const Comp = getComponent(data._schema);
|
|
25
|
+
if (Comp) {
|
|
26
|
+
const attr = isSyncEnabled() ? localessEditable(data) : {};
|
|
27
|
+
return /* @__PURE__ */ jsx(Comp, { ref, data, links, references, ...attr, ...restProps });
|
|
28
|
+
}
|
|
29
|
+
const FallbackComponent = getFallbackComponent();
|
|
30
|
+
if (FallbackComponent) {
|
|
31
|
+
return /* @__PURE__ */ jsx(FallbackComponent, { ref, data, links, references, ...restProps });
|
|
32
|
+
}
|
|
33
|
+
return /* @__PURE__ */ jsxs("p", { children: [
|
|
34
|
+
/* @__PURE__ */ jsx("b", { children: "LocalessComponent" }),
|
|
35
|
+
" could not found component with key ",
|
|
36
|
+
/* @__PURE__ */ jsx("b", { children: data._schema }),
|
|
37
|
+
". ",
|
|
38
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
39
|
+
"Please check if your configuration is correct."
|
|
40
|
+
] });
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
// src/core/hooks/use-localess.ts
|
|
45
|
+
import { useEffect, useState } from "react";
|
|
46
|
+
import { isBrowser } from "@localess/client";
|
|
47
|
+
var useLocaless = (slug, options = {}) => {
|
|
48
|
+
const [document, setDocument] = useState();
|
|
49
|
+
const client = getLocalessClient();
|
|
50
|
+
let normalizedSlug;
|
|
51
|
+
if (Array.isArray(slug)) {
|
|
52
|
+
normalizedSlug = slug.join("/");
|
|
53
|
+
} else {
|
|
54
|
+
normalizedSlug = slug;
|
|
55
|
+
}
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
async function loadDocument() {
|
|
58
|
+
const document2 = await client.getContentBySlug(normalizedSlug, options);
|
|
59
|
+
setDocument(document2);
|
|
60
|
+
if (isSyncEnabled() && isBrowser()) {
|
|
61
|
+
window.localess?.on(["input", "change"], (event) => {
|
|
62
|
+
if (event.type === "change" || event.type === "input") {
|
|
63
|
+
setDocument({ ...document2, data: event.data });
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
loadDocument();
|
|
69
|
+
}, [slug, options, client]);
|
|
70
|
+
return document;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
LocalessComponent,
|
|
75
|
+
useLocaless
|
|
76
|
+
};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
export { Content, ContentAsset, ContentData, ContentDataField, ContentDataSchema, ContentLink, ContentMetadata, ContentReference, ContentRichText, EventCallback, EventToApp, EventToAppType, Links, LocalessClient, LocalessSync, References, Translations, isBrowser, isIframe, isServer, localessEditable, localessEditableField } from '@localess/client';
|
|
1
|
+
export { L as LocalessOptions, f as findLink, g as getComponent, a as getFallbackComponent, b as getLocalessClient, i as isSyncEnabled, l as localessInit, r as registerComponent, c as renderRichTextToReact, d as resolveAsset, s as setComponents, e as setFallbackComponent, u as unregisterComponent } from './richtext-XH7pH80J.mjs';
|
|
3
2
|
import * as React from 'react';
|
|
4
|
-
import
|
|
3
|
+
import { ContentData, Links, References, ContentFetchParams, Content } from '@localess/client';
|
|
4
|
+
export { Content, ContentAsset, ContentData, ContentDataField, ContentDataSchema, ContentLink, ContentMetadata, ContentReference, ContentRichText, EventCallback, EventToApp, EventToAppType, Links, LocalessClient, LocalessSync, References, Translations, isBrowser, isIframe, isServer, localessEditable, localessEditableField } from '@localess/client';
|
|
5
5
|
|
|
6
6
|
type LocalessComponentProps<T extends ContentData = ContentData> = {
|
|
7
7
|
data: T;
|
|
@@ -10,92 +10,7 @@ type LocalessComponentProps<T extends ContentData = ContentData> = {
|
|
|
10
10
|
};
|
|
11
11
|
declare const LocalessComponent: React.ForwardRefExoticComponent<LocalessComponentProps<ContentData> & React.RefAttributes<HTMLElement>>;
|
|
12
12
|
|
|
13
|
-
type LocalessDocumentProps<T extends ContentData = ContentData> = {
|
|
14
|
-
data: T;
|
|
15
|
-
links?: Links;
|
|
16
|
-
references?: References;
|
|
17
|
-
};
|
|
18
|
-
declare const LocalessDocument: React.ForwardRefExoticComponent<LocalessDocumentProps<ContentData> & React.RefAttributes<HTMLElement>>;
|
|
19
|
-
|
|
20
|
-
type LocalessOptions = LocalessClientOptions & {
|
|
21
|
-
/**
|
|
22
|
-
* Components mapping for Localess Component integration
|
|
23
|
-
*/
|
|
24
|
-
components?: Record<string, React__default.ElementType>;
|
|
25
|
-
/**
|
|
26
|
-
* Component used if expected key didn't return anything
|
|
27
|
-
*/
|
|
28
|
-
fallbackComponent?: React__default.ElementType;
|
|
29
|
-
/**
|
|
30
|
-
* Load Sync Script, for Visual Editor integration
|
|
31
|
-
*/
|
|
32
|
-
enableSync?: boolean;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
13
|
type UseLocalessOptions = ContentFetchParams & {};
|
|
36
14
|
declare const useLocaless: <T extends ContentData = ContentData>(slug: string | string[], options?: UseLocalessOptions) => Content<T> | undefined;
|
|
37
15
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Render Localess Rich Text content to React elements
|
|
42
|
-
* @param content - The Rich Text content to render
|
|
43
|
-
* @returns React.ReactNode - The rendered React elements
|
|
44
|
-
*/
|
|
45
|
-
declare function renderRichTextToReact(content: ContentRichText): React__default.ReactNode;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Initialize Localess Client
|
|
49
|
-
* @param options
|
|
50
|
-
* @returns LocalessClient
|
|
51
|
-
*/
|
|
52
|
-
declare function localessInit(options: LocalessOptions): LocalessClient;
|
|
53
|
-
/**
|
|
54
|
-
* Get Localess Client
|
|
55
|
-
* @returns LocalessClient
|
|
56
|
-
*/
|
|
57
|
-
declare function getLocalessClient(): LocalessClient;
|
|
58
|
-
/**
|
|
59
|
-
* Register Component
|
|
60
|
-
* @param key - component key
|
|
61
|
-
* @param component - React Component
|
|
62
|
-
*/
|
|
63
|
-
declare function registerComponent(key: string, component: React__default.ElementType): void;
|
|
64
|
-
/**
|
|
65
|
-
* Unregister Component
|
|
66
|
-
* @param key - component key
|
|
67
|
-
*/
|
|
68
|
-
declare function unregisterComponent(key: string): void;
|
|
69
|
-
/**
|
|
70
|
-
* Set Components
|
|
71
|
-
* @param components - Record of components
|
|
72
|
-
*/
|
|
73
|
-
declare function setComponents(components: Record<string, React__default.ElementType>): void;
|
|
74
|
-
/**
|
|
75
|
-
* Get Component
|
|
76
|
-
* @param key - component key
|
|
77
|
-
* @returns React Component
|
|
78
|
-
*/
|
|
79
|
-
declare function getComponent(key: string): React__default.ElementType | undefined;
|
|
80
|
-
/**
|
|
81
|
-
* Set Fallback Component
|
|
82
|
-
* @param fallbackComponent
|
|
83
|
-
*/
|
|
84
|
-
declare function setFallbackComponent(fallbackComponent: React__default.ElementType): void;
|
|
85
|
-
/**
|
|
86
|
-
* Get Fallback Component
|
|
87
|
-
* @returns React Component
|
|
88
|
-
*/
|
|
89
|
-
declare function getFallbackComponent(): React__default.ElementType | undefined;
|
|
90
|
-
/**
|
|
91
|
-
* Check if Sync is enabled
|
|
92
|
-
*/
|
|
93
|
-
declare function isSyncEnabled(): boolean;
|
|
94
|
-
/**
|
|
95
|
-
* Resolve Asset URL
|
|
96
|
-
* @param asset - ContentAsset
|
|
97
|
-
* @returns Asset URL
|
|
98
|
-
*/
|
|
99
|
-
declare function resolveAsset(asset: ContentAsset): string;
|
|
100
|
-
|
|
101
|
-
export { LocalessComponent, type LocalessComponentProps, LocalessDocument, type LocalessDocumentProps, type LocalessOptions, type UseLocalessOptions, findLink, getComponent, getFallbackComponent, getLocalessClient, isSyncEnabled, localessInit, registerComponent, renderRichTextToReact, resolveAsset, setComponents, setFallbackComponent, unregisterComponent, useLocaless };
|
|
16
|
+
export { LocalessComponent, type LocalessComponentProps, type UseLocalessOptions, useLocaless };
|