@localess/react 3.3.0-dev.20260708093226 → 3.3.0-dev.20260708124505
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 +14 -18
- package/SKILL.md +19 -26
- package/dist/core/components/localess-component.d.ts +2 -2
- package/dist/core/components/localess-document.js +1 -1
- package/dist/core/components/localess-document.mjs +18 -20
- package/dist/core/hooks/use-localess.js +1 -1
- package/dist/core/hooks/use-localess.mjs +13 -13
- package/dist/core/models/sync.d.ts +1 -1
- package/dist/core/state.d.ts +43 -5
- package/dist/core/state.js +1 -1
- package/dist/core/state.mjs +13 -3
- package/dist/index.js +1 -1
- package/dist/index.mjs +8 -8
- package/dist/rsc/index.d.ts +1 -1
- package/dist/rsc/index.js +1 -1
- package/dist/rsc/index.mjs +9 -9
- package/dist/rsc/localess-sync.js +1 -1
- package/dist/rsc/localess-sync.mjs +10 -9
- package/dist/ssr/index.d.ts +2 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -122,7 +122,7 @@ localessInit({
|
|
|
122
122
|
|
|
123
123
|
## `LocalessComponent`
|
|
124
124
|
|
|
125
|
-
`LocalessComponent` is a dynamic renderer that maps Localess content data to your registered React components by schema key. It
|
|
125
|
+
`LocalessComponent` is a dynamic renderer that maps Localess content data to your registered React components by schema key. It always applies Visual Editor attributes (`data-ll-id` / `data-ll-schema`) — they're inert outside the Visual Editor iframe.
|
|
126
126
|
|
|
127
127
|
```tsx
|
|
128
128
|
import { LocalessComponent } from "@localess/react";
|
|
@@ -424,20 +424,17 @@ If you manage content state yourself without `useLocaless` or `LocalessDocument`
|
|
|
424
424
|
'use client';
|
|
425
425
|
|
|
426
426
|
import { useEffect, useState } from "react";
|
|
427
|
-
import { LocalessComponent, localessEditable,
|
|
427
|
+
import { LocalessComponent, localessEditable, localessSyncOn } from "@localess/react";
|
|
428
428
|
import type { Content, Page } from "./.localess/localess";
|
|
429
429
|
|
|
430
430
|
export function PageClient({ initialContent }: { initialContent: Content<Page> }) {
|
|
431
431
|
const [pageData, setPageData] = useState(initialContent.data);
|
|
432
432
|
|
|
433
433
|
useEffect(() => {
|
|
434
|
-
if
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
}
|
|
439
|
-
});
|
|
440
|
-
}
|
|
434
|
+
// No-op if sync isn't enabled/usable; `event` is narrowed to the 'input' | 'change' variant
|
|
435
|
+
localessSyncOn(['input', 'change'], (event) => {
|
|
436
|
+
setPageData(event.data);
|
|
437
|
+
});
|
|
441
438
|
// No cleanup needed: window.localess has no .off() method
|
|
442
439
|
}, []);
|
|
443
440
|
|
|
@@ -465,6 +462,8 @@ export function PageClient({ initialContent }: { initialContent: Content<Page> }
|
|
|
465
462
|
|
|
466
463
|
> `window.localess` only exposes `.on()` and `.onChange()` — there is no `.off()` method.
|
|
467
464
|
|
|
465
|
+
`localessSyncOn(event, callback)` wraps `.on()`; `localessSyncOnChange(callback)` wraps `.onChange()` — equivalent to `localessSyncOn(['input', 'change'], callback)`, firing only for content-change events (`callback` receives the `input`/`change` variant, not the full `EventToApp` union). Both handle the `isSyncEnabled()` check and the `localessSyncReady()` wait internally.
|
|
466
|
+
|
|
468
467
|
---
|
|
469
468
|
|
|
470
469
|
## Full Example — SPA / Default (`@localess/react`)
|
|
@@ -582,7 +581,7 @@ Full control over state and sync subscription. Use when you need custom logic ar
|
|
|
582
581
|
'use client';
|
|
583
582
|
|
|
584
583
|
import { useEffect, useState } from "react";
|
|
585
|
-
import { LocalessComponent, localessEditable,
|
|
584
|
+
import { LocalessComponent, localessEditable, localessSyncOn } from "@localess/react";
|
|
586
585
|
import type { Content, Page } from "./.localess/localess";
|
|
587
586
|
|
|
588
587
|
export function PageClientManual({
|
|
@@ -594,13 +593,10 @@ export function PageClientManual({
|
|
|
594
593
|
const [pageData, setPageData] = useState(initialContent.data);
|
|
595
594
|
|
|
596
595
|
useEffect(() => {
|
|
597
|
-
if
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
}
|
|
602
|
-
});
|
|
603
|
-
}
|
|
596
|
+
// No-op if sync isn't enabled/usable; `event` is narrowed to the 'input' | 'change' variant
|
|
597
|
+
localessSyncOn(['input', 'change'], (event) => {
|
|
598
|
+
setPageData(event.data);
|
|
599
|
+
});
|
|
604
600
|
// No cleanup needed: window.localess has no .off() method
|
|
605
601
|
}, []);
|
|
606
602
|
|
|
@@ -760,7 +756,7 @@ The table below shows which symbols are available in each export.
|
|
|
760
756
|
| `useLocaless` | ✅ | ❌ | ✅ |
|
|
761
757
|
| `localessEditable` / `localessEditableField` | ✅ | ❌ | ✅ |
|
|
762
758
|
| `isBrowser` / `isIframe` | ✅ | ❌ | ✅ |
|
|
763
|
-
| `isSyncEnabled`
|
|
759
|
+
| `isSyncEnabled` / `localessSyncOn` / `localessSyncOnChange` / `localessSyncReady` | ✅ | ❌ | ✅ |
|
|
764
760
|
| Sync event types (`LocalessSync`, `EventToApp`, …) | ✅ | ❌ | ✅ |
|
|
765
761
|
|
|
766
762
|
---
|
package/SKILL.md
CHANGED
|
@@ -76,7 +76,7 @@ import { LocalessComponent } from "@localess/react";
|
|
|
76
76
|
|
|
77
77
|
1. Read `data._schema` as the component registry key
|
|
78
78
|
2. Look up registered component by that key
|
|
79
|
-
3. If found → render component with `data`, `links`, `references`;
|
|
79
|
+
3. If found → render component with `data`, `links`, `references`; always injects `data-ll-id` and `data-ll-schema` as props (harmless outside the Visual Editor iframe; user components should spread `{...localessEditable(data)}` on their root element)
|
|
80
80
|
4. If not found → try `fallbackComponent`
|
|
81
81
|
5. If no fallback → render error message
|
|
82
82
|
|
|
@@ -155,13 +155,14 @@ import { localessEditable, localessEditableField } from "@localess/react";
|
|
|
155
155
|
|
|
156
156
|
## Visual Editor Sync
|
|
157
157
|
|
|
158
|
-
`localessInit()` is the **single entry point** for Visual Editor integration. Setting `enableSync: true`
|
|
158
|
+
`localessInit()` is the **single entry point** for Visual Editor integration. Setting `enableSync: true` injects the sync script and enables live event subscription; component registration is independent of it.
|
|
159
159
|
|
|
160
160
|
### What `enableSync: true` activates
|
|
161
161
|
|
|
162
162
|
1. Injects the Localess sync script (`loadLocalessSync`) into `<head>`
|
|
163
|
-
2. Makes `
|
|
164
|
-
|
|
163
|
+
2. Makes `isSyncEnabled()` — and therefore `useLocaless`, `LocalessDocument`, `localessSyncOn`, `localessSyncOnChange` — actually subscribe to live editor events
|
|
164
|
+
|
|
165
|
+
`LocalessComponent`'s `data-ll-id` / `data-ll-schema` injection and `localessEditable()` / `localessEditableField()` are unconditional — they always emit their `data-ll-*` attributes regardless of `enableSync`. They're inert outside the Visual Editor iframe, so leaving them on in production is harmless (though sync itself should stay off — see below).
|
|
165
166
|
|
|
166
167
|
```typescript
|
|
167
168
|
localessInit({
|
|
@@ -246,22 +247,17 @@ If you manage content state yourself without `useLocaless` or `LocalessDocument`
|
|
|
246
247
|
'use client';
|
|
247
248
|
|
|
248
249
|
import { useEffect, useState } from "react";
|
|
249
|
-
import { LocalessComponent, localessEditable,
|
|
250
|
+
import { LocalessComponent, localessEditable, localessSyncOn } from "@localess/react";
|
|
250
251
|
import type { Content, Page } from "./.localess/localess";
|
|
251
252
|
|
|
252
253
|
export function PageClient({ initialContent }: { initialContent: Content<Page> }) {
|
|
253
254
|
const [pageData, setPageData] = useState(initialContent.data);
|
|
254
255
|
|
|
255
256
|
useEffect(() => {
|
|
256
|
-
if
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
setPageData(event.data);
|
|
261
|
-
}
|
|
262
|
-
});
|
|
263
|
-
});
|
|
264
|
-
}
|
|
257
|
+
// No-op if sync isn't enabled/usable; `event` is narrowed to the 'input' | 'change' variant
|
|
258
|
+
localessSyncOn(['input', 'change'], (event) => {
|
|
259
|
+
setPageData(event.data);
|
|
260
|
+
});
|
|
265
261
|
// No cleanup needed: window.localess has no .off() method
|
|
266
262
|
}, []);
|
|
267
263
|
|
|
@@ -294,6 +290,8 @@ export function PageClient({ initialContent }: { initialContent: Content<Page> }
|
|
|
294
290
|
|
|
295
291
|
> `window.localess` only exposes `.on()` and `.onChange()` — there is no `.off()`.
|
|
296
292
|
|
|
293
|
+
`localessSyncOn(event, callback)` wraps `.on()`; `localessSyncOnChange(callback)` wraps `.onChange()` — equivalent to `localessSyncOn(['input', 'change'], callback)`, firing only for content-change events (`callback` receives the `input`/`change` variant, not the full `EventToApp` union). Both handle the `isSyncEnabled()` check and the `localessSyncReady()` wait internally.
|
|
294
|
+
|
|
297
295
|
### Pattern: Split Server/Client Components (Next.js App Router)
|
|
298
296
|
|
|
299
297
|
**Preload data server-side** and pass it to the Client Component. The page renders immediately with server data — no loading flash — and Visual Editor sync kicks in on top.
|
|
@@ -365,7 +363,7 @@ export default async function HomePage({ params }: { params: Promise<{ locale?:
|
|
|
365
363
|
'use client';
|
|
366
364
|
|
|
367
365
|
import { useEffect, useState } from "react";
|
|
368
|
-
import { LocalessComponent, localessEditable,
|
|
366
|
+
import { LocalessComponent, localessEditable, localessSyncOn } from "@localess/react";
|
|
369
367
|
import type { Content, Page } from "./.localess/localess";
|
|
370
368
|
|
|
371
369
|
export function PageClient({ initialContent }: { initialContent: Content<Page> }) {
|
|
@@ -373,15 +371,10 @@ export function PageClient({ initialContent }: { initialContent: Content<Page> }
|
|
|
373
371
|
const [pageData, setPageData] = useState(initialContent.data);
|
|
374
372
|
|
|
375
373
|
useEffect(() => {
|
|
376
|
-
if
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
setPageData(event.data);
|
|
381
|
-
}
|
|
382
|
-
});
|
|
383
|
-
});
|
|
384
|
-
}
|
|
374
|
+
// No-op if sync isn't enabled/usable; `event` is narrowed to the 'input' | 'change' variant
|
|
375
|
+
localessSyncOn(['input', 'change'], (event) => {
|
|
376
|
+
setPageData(event.data);
|
|
377
|
+
});
|
|
385
378
|
// No cleanup needed: window.localess has no .off() method
|
|
386
379
|
}, []);
|
|
387
380
|
|
|
@@ -623,7 +616,7 @@ export { localessInit, getLocalessClient }
|
|
|
623
616
|
|
|
624
617
|
// Component registry
|
|
625
618
|
export { registerComponent, unregisterComponent, setComponents, getComponent }
|
|
626
|
-
export { setFallbackComponent, getFallbackComponent, isSyncEnabled }
|
|
619
|
+
export { setFallbackComponent, getFallbackComponent, isSyncEnabled, localessSyncOn, localessSyncOnChange, localessSyncReady }
|
|
627
620
|
|
|
628
621
|
// Rendering
|
|
629
622
|
export { LocalessComponent } // Dynamic schema-to-component renderer
|
|
@@ -647,7 +640,7 @@ export { isBrowser, isServer, isIframe }
|
|
|
647
640
|
// Types (re-exported from @localess/client + local)
|
|
648
641
|
export type { AssetTransformParams } // Image transform params for resolveAsset
|
|
649
642
|
export type { LocalessClient, LocalessOptions }
|
|
650
|
-
export type { LocalessSync, EventToApp, EventCallback, EventToAppType }
|
|
643
|
+
export type { LocalessSync, EventToApp, EventToAppOf, EventCallback, EventToAppType }
|
|
651
644
|
export type {
|
|
652
645
|
Content, ContentData, ContentMetadata, ContentDataSchema, ContentDataField,
|
|
653
646
|
ContentAsset, ContentRichText, ContentLink, ContentReference,
|
|
@@ -30,8 +30,8 @@ export type LocalessComponentProps<T extends ContentData = ContentData> = {
|
|
|
30
30
|
* Dynamic schema-to-component renderer for use in SPA and client-side contexts.
|
|
31
31
|
*
|
|
32
32
|
* Looks up `data._schema` in the component registry (set via `localessInit` or `setComponents`),
|
|
33
|
-
* renders the matched component, and
|
|
34
|
-
*
|
|
33
|
+
* renders the matched component, and always spreads `localessEditable` attributes on the root
|
|
34
|
+
* element (`data-ll-id` / `data-ll-schema`) so the Visual Editor can target it for live editing.
|
|
35
35
|
*
|
|
36
36
|
* Falls back to the `fallbackComponent` (if registered) when the schema key is not found,
|
|
37
37
|
* or renders an inline error message as a last resort.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require("../../console.js"),t=require("../state.js"),n=require("./localess-component.js");let r=require("react"),i=require("react/jsx-runtime");var a=(0,r.forwardRef)(({document:a},o)=>{let[s,c]=(0,r.useState)(a.data);return(0,r.useEffect)(()=>{t.
|
|
1
|
+
const e=require("../../console.js"),t=require("../state.js"),n=require("./localess-component.js");let r=require("react"),i=require("react/jsx-runtime");var a=(0,r.forwardRef)(({document:a},o)=>{let[s,c]=(0,r.useState)(a.data);return(0,r.useEffect)(()=>{t.localessSyncOn([`input`,`change`],e=>{c(e.data)})},[]),s?(0,i.jsx)(n.LocalessComponent,{ref:o,data:s,assets:a.assets,links:a.links,references:a.references}):(console.error(`LocalessDocument property %cdocument.data%c is not provided.`,e.FONT_BOLD,e.FONT_NORMAL),(0,i.jsxs)(`div`,{children:[`LocalessDocument property `,(0,i.jsx)(`b`,{children:`document.data`}),` is not provided.`]}))});exports.LocalessDocument=a;
|
|
@@ -1,28 +1,26 @@
|
|
|
1
1
|
import { FONT_BOLD as e, FONT_NORMAL as t } from "../../console.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { LocalessComponent as
|
|
4
|
-
import { forwardRef as
|
|
5
|
-
import { jsx as
|
|
2
|
+
import { localessSyncOn as n } from "../state.mjs";
|
|
3
|
+
import { LocalessComponent as r } from "./localess-component.mjs";
|
|
4
|
+
import { forwardRef as i, useEffect as a, useState as o } from "react";
|
|
5
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
6
6
|
//#region src/core/components/localess-document.tsx
|
|
7
|
-
var
|
|
8
|
-
let [
|
|
9
|
-
return
|
|
10
|
-
n(
|
|
11
|
-
|
|
12
|
-
(e.type === "change" || e.type === "input") && f(e.data);
|
|
13
|
-
});
|
|
7
|
+
var l = i(({ document: i }, l) => {
|
|
8
|
+
let [u, d] = o(i.data);
|
|
9
|
+
return a(() => {
|
|
10
|
+
n(["input", "change"], (e) => {
|
|
11
|
+
d(e.data);
|
|
14
12
|
});
|
|
15
|
-
}, []),
|
|
16
|
-
ref:
|
|
17
|
-
data:
|
|
18
|
-
assets:
|
|
19
|
-
links:
|
|
20
|
-
references:
|
|
21
|
-
}) : (console.error("LocalessDocument property %cdocument.data%c is not provided.", e, t), /* @__PURE__ */
|
|
13
|
+
}, []), u ? /* @__PURE__ */ s(r, {
|
|
14
|
+
ref: l,
|
|
15
|
+
data: u,
|
|
16
|
+
assets: i.assets,
|
|
17
|
+
links: i.links,
|
|
18
|
+
references: i.references
|
|
19
|
+
}) : (console.error("LocalessDocument property %cdocument.data%c is not provided.", e, t), /* @__PURE__ */ c("div", { children: [
|
|
22
20
|
"LocalessDocument property ",
|
|
23
|
-
/* @__PURE__ */
|
|
21
|
+
/* @__PURE__ */ s("b", { children: "document.data" }),
|
|
24
22
|
" is not provided."
|
|
25
23
|
] }));
|
|
26
24
|
});
|
|
27
25
|
//#endregion
|
|
28
|
-
export {
|
|
26
|
+
export { l as LocalessDocument };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require("../state.js");let t=require("react");var n=(n,r={})=>{let[i,a]=(0,t.useState)(),o=e.getLocalessClient(),s;return s=Array.isArray(n)?n.join(`/`):n,(0,t.useEffect)(()=>{async function t(){let t=await o.getContentBySlug(s,r);a(t),e.
|
|
1
|
+
const e=require("../state.js");let t=require("react");var n=(n,r={})=>{let[i,a]=(0,t.useState)(),o=e.getLocalessClient(),s;return s=Array.isArray(n)?n.join(`/`):n,(0,t.useEffect)(()=>{async function t(){let t=await o.getContentBySlug(s,r);a(t),e.localessSyncOn([`input`,`change`],e=>{a({...t,data:e.data})})}t()},[n,r,o]),i};exports.useLocaless=n;
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { getLocalessClient as e,
|
|
2
|
-
import { useEffect as
|
|
1
|
+
import { getLocalessClient as e, localessSyncOn as t } from "../state.mjs";
|
|
2
|
+
import { useEffect as n, useState as r } from "react";
|
|
3
3
|
//#region src/core/hooks/use-localess.ts
|
|
4
|
-
var
|
|
5
|
-
let [
|
|
6
|
-
return
|
|
4
|
+
var i = (i, a = {}) => {
|
|
5
|
+
let [o, s] = r(), c = e(), l;
|
|
6
|
+
return l = Array.isArray(i) ? i.join("/") : i, n(() => {
|
|
7
7
|
async function e() {
|
|
8
|
-
let e = await
|
|
9
|
-
|
|
10
|
-
(
|
|
8
|
+
let e = await c.getContentBySlug(l, a);
|
|
9
|
+
s(e), t(["input", "change"], (t) => {
|
|
10
|
+
s({
|
|
11
11
|
...e,
|
|
12
12
|
data: t.data
|
|
13
13
|
});
|
|
14
|
-
})
|
|
14
|
+
});
|
|
15
15
|
}
|
|
16
16
|
e();
|
|
17
17
|
}, [
|
|
18
|
+
i,
|
|
18
19
|
a,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
]), s;
|
|
20
|
+
c
|
|
21
|
+
]), o;
|
|
22
22
|
};
|
|
23
23
|
//#endregion
|
|
24
|
-
export {
|
|
24
|
+
export { i as useLocaless };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type { EventCallback, EventToApp, EventToAppType, LocalessSync } from '@localess/client';
|
|
1
|
+
export type { EventCallback, EventToApp, EventToAppOf, EventToAppType, LocalessSync } from '@localess/client';
|
package/dist/core/state.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AssetTransformParams, LocalessClient } from '@localess/client';
|
|
1
|
+
import { AssetTransformParams, EventToAppOf, EventToAppType, LocalessClient } from '@localess/client';
|
|
2
2
|
import { default as React } from 'react';
|
|
3
3
|
import { ContentAsset, LocalessOptions } from './models';
|
|
4
4
|
/**
|
|
@@ -107,8 +107,8 @@ export declare function getFallbackComponent(): React.ElementType | undefined;
|
|
|
107
107
|
*
|
|
108
108
|
* Self-sufficient: callers don't need to separately check {@link isBrowser} or {@link isIframe}.
|
|
109
109
|
*
|
|
110
|
-
* Used internally by {@link
|
|
111
|
-
* to
|
|
110
|
+
* Used internally by {@link localessSyncOn} and {@link localessSyncOnChange} to decide whether to
|
|
111
|
+
* subscribe to sync events — and therefore indirectly by {@link LocalessDocument} and {@link useLocaless}.
|
|
112
112
|
*
|
|
113
113
|
* @returns `true` if sync is enabled and usable, `false` otherwise.
|
|
114
114
|
*/
|
|
@@ -120,8 +120,9 @@ export declare function isSyncEnabled(): boolean;
|
|
|
120
120
|
* loaded. Never rejects — a failed script load is logged via {@link loadLocalessSync} and resolves
|
|
121
121
|
* anyway, since the rest of the app functions without live editing.
|
|
122
122
|
*
|
|
123
|
-
* Use this before subscribing to `window.localess.on(...)` to avoid a race where the
|
|
124
|
-
* attached before the sync script has run.
|
|
123
|
+
* Use this before subscribing directly to `window.localess.on(...)` to avoid a race where the
|
|
124
|
+
* listener is attached before the sync script has run. Prefer {@link localessSyncOn} instead —
|
|
125
|
+
* it wraps this exact pattern.
|
|
125
126
|
*
|
|
126
127
|
* @returns A promise that resolves when sync is ready (or immediately, if not applicable).
|
|
127
128
|
*
|
|
@@ -137,6 +138,43 @@ export declare function isSyncEnabled(): boolean;
|
|
|
137
138
|
* ```
|
|
138
139
|
*/
|
|
139
140
|
export declare function localessSyncReady(): Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* Subscribes to Visual Editor sync event(s), handling the `isSyncEnabled()` check and the
|
|
143
|
+
* {@link localessSyncReady} wait internally so call sites don't have to.
|
|
144
|
+
*
|
|
145
|
+
* No-op if sync isn't enabled or usable in the current context (see {@link isSyncEnabled}).
|
|
146
|
+
*
|
|
147
|
+
* @param event - A single event type or array of event types to subscribe to.
|
|
148
|
+
* @param callback - Called with the event, narrowed to the variant(s) matching `event`.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```ts
|
|
152
|
+
* useEffect(() => {
|
|
153
|
+
* localessSyncOn(['input', 'change'], event => setContentData(event.data));
|
|
154
|
+
* }, []);
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
export declare function localessSyncOn<T extends EventToAppType>(event: T | T[], callback: (event: EventToAppOf<T>) => void): void;
|
|
158
|
+
/**
|
|
159
|
+
* Subscribes to content-change Visual Editor sync events (`input` and `change`), handling the
|
|
160
|
+
* `isSyncEnabled()` check and the {@link localessSyncReady} wait internally so call sites don't
|
|
161
|
+
* have to.
|
|
162
|
+
*
|
|
163
|
+
* Equivalent to `localessSyncOn(['input', 'change'], callback)` (mirrors `window.localess.onChange`).
|
|
164
|
+
* For other event types (`save`, `publish`, `pong`, `enterSchema`, `hoverSchema`), use {@link localessSyncOn}.
|
|
165
|
+
*
|
|
166
|
+
* No-op if sync isn't enabled or usable in the current context (see {@link isSyncEnabled}).
|
|
167
|
+
*
|
|
168
|
+
* @param callback - Called with the `input`/`change` event.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* useEffect(() => {
|
|
173
|
+
* localessSyncOnChange(event => setContentData(event.data));
|
|
174
|
+
* }, []);
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
export declare function localessSyncOnChange(callback: (event: EventToAppOf<'change' | 'input'>) => void): void;
|
|
140
178
|
export declare function getOrigin(): string;
|
|
141
179
|
/**
|
|
142
180
|
* Resolves a {@link ContentAsset} to its full URL string.
|
package/dist/core/state.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require("../console.js");let t=require("@localess/client");var n=void 0,r=void 0,i={},a=void 0,o=!1,s=void 0,c=``;function l(e){let{components:l,fallbackComponent:u,enableSync:d,...f}=e;return r=(0,t.localessClient)(f),n=f.origin,c=`${e.origin}/api/v1/spaces/${e.spaceId}/assets/`,i=l||{},a=u,d&&(o=!0,s=(0,t.loadLocalessSync)(f.origin).catch(e=>{console.error(`[Localess] Failed to load sync script.`,e)})),r}function u(){if(!r)throw console.error(`[Localess] No client found. Please check if the Localess is initialized. Use localessInit function.`),Error(`[Localess] No client found.`);return r}function d(e,t){i[e]=t}function f(e){delete i[e]}function p(e){i=e}function m(t){if(Object.hasOwn(i,t))return i[t];console.error(`[Localess] component %c${t}%c can't be found.`,e.FONT_BOLD,e.FONT_NORMAL)}function h(e){a=e}function g(){return a}function _(){return o&&(0,t.isBrowser)()&&(0,t.isIframe)()}function v(){return s??Promise.resolve()}function y(){if(!n)throw console.error(`[Localess] No origin found. Please check if the Localess is initialized. Use localessInit function.`),Error(`[Localess] No origin found.`);return n}function
|
|
1
|
+
const e=require("../console.js");let t=require("@localess/client");var n=void 0,r=void 0,i={},a=void 0,o=!1,s=void 0,c=``;function l(e){let{components:l,fallbackComponent:u,enableSync:d,...f}=e;return r=(0,t.localessClient)(f),n=f.origin,c=`${e.origin}/api/v1/spaces/${e.spaceId}/assets/`,i=l||{},a=u,d&&(o=!0,s=(0,t.loadLocalessSync)(f.origin).catch(e=>{console.error(`[Localess] Failed to load sync script.`,e)})),r}function u(){if(!r)throw console.error(`[Localess] No client found. Please check if the Localess is initialized. Use localessInit function.`),Error(`[Localess] No client found.`);return r}function d(e,t){i[e]=t}function f(e){delete i[e]}function p(e){i=e}function m(t){if(Object.hasOwn(i,t))return i[t];console.error(`[Localess] component %c${t}%c can't be found.`,e.FONT_BOLD,e.FONT_NORMAL)}function h(e){a=e}function g(){return a}function _(){return o&&(0,t.isBrowser)()&&(0,t.isIframe)()}function v(){return s??Promise.resolve()}function y(e,t){_()&&v().then(()=>{window.localess?.on(e,t)})}function b(e){_()&&v().then(()=>{window.localess?.onChange(e)})}function x(){if(!n)throw console.error(`[Localess] No origin found. Please check if the Localess is initialized. Use localessInit function.`),Error(`[Localess] No origin found.`);return n}function S(e,n){let r=`${c}${e.uri}`,i=(0,t.buildAssetQueryString)(n);return i?`${r}?${i}`:r}exports.getComponent=m,exports.getFallbackComponent=g,exports.getLocalessClient=u,exports.getOrigin=x,exports.isSyncEnabled=_,exports.localessInit=l,exports.localessSyncOn=y,exports.localessSyncOnChange=b,exports.localessSyncReady=v,exports.registerComponent=d,exports.resolveAsset=S,exports.setComponents=p,exports.setFallbackComponent=h,exports.unregisterComponent=f;
|
package/dist/core/state.mjs
CHANGED
|
@@ -37,13 +37,23 @@ function S() {
|
|
|
37
37
|
function C() {
|
|
38
38
|
return f ?? Promise.resolve();
|
|
39
39
|
}
|
|
40
|
-
function w() {
|
|
40
|
+
function w(e, t) {
|
|
41
|
+
S() && C().then(() => {
|
|
42
|
+
window.localess?.on(e, t);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function T(e) {
|
|
46
|
+
S() && C().then(() => {
|
|
47
|
+
window.localess?.onChange(e);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function E() {
|
|
41
51
|
if (!s) throw console.error("[Localess] No origin found. Please check if the Localess is initialized. Use localessInit function."), Error("[Localess] No origin found.");
|
|
42
52
|
return s;
|
|
43
53
|
}
|
|
44
|
-
function
|
|
54
|
+
function D(e, t) {
|
|
45
55
|
let r = `${p}${e.uri}`, i = n(t);
|
|
46
56
|
return i ? `${r}?${i}` : r;
|
|
47
57
|
}
|
|
48
58
|
//#endregion
|
|
49
|
-
export { y as getComponent, x as getFallbackComponent, h as getLocalessClient,
|
|
59
|
+
export { y as getComponent, x as getFallbackComponent, h as getLocalessClient, E as getOrigin, S as isSyncEnabled, m as localessInit, w as localessSyncOn, T as localessSyncOnChange, C as localessSyncReady, g as registerComponent, D as resolveAsset, v as setComponents, b as setFallbackComponent, _ as unregisterComponent };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./core/state.js"),t=require("./core/utils/link.util.js"),n=require("./core/components/localess-component.js"),r=require("./core/components/localess-document.js"),i=require("./core/hooks/use-localess.js"),a=require("./core/richtext.js");let o=require("@localess/client");exports.LocalessComponent=n.LocalessComponent,exports.LocalessDocument=r.LocalessDocument,exports.findLink=t.findLink,exports.getComponent=e.getComponent,exports.getFallbackComponent=e.getFallbackComponent,exports.getLocalessClient=e.getLocalessClient,exports.getOrigin=e.getOrigin,Object.defineProperty(exports,"isBrowser",{enumerable:!0,get:function(){return o.isBrowser}}),Object.defineProperty(exports,"isIframe",{enumerable:!0,get:function(){return o.isIframe}}),Object.defineProperty(exports,"isServer",{enumerable:!0,get:function(){return o.isServer}}),exports.isSyncEnabled=e.isSyncEnabled,Object.defineProperty(exports,"localessEditable",{enumerable:!0,get:function(){return o.localessEditable}}),Object.defineProperty(exports,"localessEditableField",{enumerable:!0,get:function(){return o.localessEditableField}}),exports.localessInit=e.localessInit,exports.localessSyncReady=e.localessSyncReady,exports.registerComponent=e.registerComponent,exports.renderRichTextToReact=a.renderRichTextToReact,exports.resolveAsset=e.resolveAsset,exports.setComponents=e.setComponents,exports.setFallbackComponent=e.setFallbackComponent,exports.unregisterComponent=e.unregisterComponent,exports.useLocaless=i.useLocaless;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./core/state.js"),t=require("./core/utils/link.util.js"),n=require("./core/components/localess-component.js"),r=require("./core/components/localess-document.js"),i=require("./core/hooks/use-localess.js"),a=require("./core/richtext.js");let o=require("@localess/client");exports.LocalessComponent=n.LocalessComponent,exports.LocalessDocument=r.LocalessDocument,exports.findLink=t.findLink,exports.getComponent=e.getComponent,exports.getFallbackComponent=e.getFallbackComponent,exports.getLocalessClient=e.getLocalessClient,exports.getOrigin=e.getOrigin,Object.defineProperty(exports,"isBrowser",{enumerable:!0,get:function(){return o.isBrowser}}),Object.defineProperty(exports,"isIframe",{enumerable:!0,get:function(){return o.isIframe}}),Object.defineProperty(exports,"isServer",{enumerable:!0,get:function(){return o.isServer}}),exports.isSyncEnabled=e.isSyncEnabled,Object.defineProperty(exports,"localessEditable",{enumerable:!0,get:function(){return o.localessEditable}}),Object.defineProperty(exports,"localessEditableField",{enumerable:!0,get:function(){return o.localessEditableField}}),exports.localessInit=e.localessInit,exports.localessSyncOn=e.localessSyncOn,exports.localessSyncOnChange=e.localessSyncOnChange,exports.localessSyncReady=e.localessSyncReady,exports.registerComponent=e.registerComponent,exports.renderRichTextToReact=a.renderRichTextToReact,exports.resolveAsset=e.resolveAsset,exports.setComponents=e.setComponents,exports.setFallbackComponent=e.setFallbackComponent,exports.unregisterComponent=e.unregisterComponent,exports.useLocaless=i.useLocaless;
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { getComponent as e, getFallbackComponent as t, getLocalessClient as n, getOrigin as r, isSyncEnabled as i, localessInit as a,
|
|
2
|
-
import { findLink as
|
|
3
|
-
import { isBrowser as
|
|
4
|
-
import { LocalessComponent as
|
|
5
|
-
import { LocalessDocument as
|
|
6
|
-
import { useLocaless as
|
|
7
|
-
import { renderRichTextToReact as
|
|
8
|
-
export {
|
|
1
|
+
import { getComponent as e, getFallbackComponent as t, getLocalessClient as n, getOrigin as r, isSyncEnabled as i, localessInit as a, localessSyncOn as o, localessSyncOnChange as s, localessSyncReady as c, registerComponent as l, resolveAsset as u, setComponents as d, setFallbackComponent as f, unregisterComponent as p } from "./core/state.mjs";
|
|
2
|
+
import { findLink as m } from "./core/utils/link.util.mjs";
|
|
3
|
+
import { isBrowser as h, isIframe as g, isServer as _, localessEditable as v, localessEditableField as y } from "./core/utils/index.mjs";
|
|
4
|
+
import { LocalessComponent as b } from "./core/components/localess-component.mjs";
|
|
5
|
+
import { LocalessDocument as x } from "./core/components/localess-document.mjs";
|
|
6
|
+
import { useLocaless as S } from "./core/hooks/use-localess.mjs";
|
|
7
|
+
import { renderRichTextToReact as C } from "./core/richtext.mjs";
|
|
8
|
+
export { b as LocalessComponent, x as LocalessDocument, m as findLink, e as getComponent, t as getFallbackComponent, n as getLocalessClient, r as getOrigin, h as isBrowser, g as isIframe, _ as isServer, i as isSyncEnabled, v as localessEditable, y as localessEditableField, a as localessInit, o as localessSyncOn, s as localessSyncOnChange, c as localessSyncReady, l as registerComponent, C as renderRichTextToReact, u as resolveAsset, d as setComponents, f as setFallbackComponent, p as unregisterComponent, S as useLocaless };
|
package/dist/rsc/index.d.ts
CHANGED
|
@@ -25,6 +25,6 @@
|
|
|
25
25
|
* NOT compatible with Next.js `output: 'export'` — use `@localess/react/ssr` for static exports.
|
|
26
26
|
*/
|
|
27
27
|
export * from '../core/components/localess-component';
|
|
28
|
-
export { isSyncEnabled, localessSyncReady } from '../core/state';
|
|
28
|
+
export { isSyncEnabled, localessSyncOn, localessSyncOnChange, localessSyncReady } from '../core/state';
|
|
29
29
|
export * from '../ssr';
|
|
30
30
|
export * from './localess-document';
|
package/dist/rsc/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../core/state.js"),t=require("../core/utils/link.util.js"),n=require("../core/components/localess-component.js"),r=require("../core/richtext.js"),i=require("../ssr/localess-component.js"),a=require("../ssr/localess-document.js"),o=require("./localess-document.js");let s=require("@localess/client");exports.LocalessComponent=n.LocalessComponent,exports.LocalessDocument=o.LocalessDocument,exports.LocalessServerComponent=i.LocalessServerComponent,exports.LocalessServerDocument=a.LocalessServerDocument,exports.findLink=t.findLink,exports.getComponent=e.getComponent,exports.getFallbackComponent=e.getFallbackComponent,exports.getLocalessClient=e.getLocalessClient,Object.defineProperty(exports,"isBrowser",{enumerable:!0,get:function(){return s.isBrowser}}),Object.defineProperty(exports,"isIframe",{enumerable:!0,get:function(){return s.isIframe}}),Object.defineProperty(exports,"isServer",{enumerable:!0,get:function(){return s.isServer}}),exports.isSyncEnabled=e.isSyncEnabled,Object.defineProperty(exports,"localessEditable",{enumerable:!0,get:function(){return s.localessEditable}}),Object.defineProperty(exports,"localessEditableField",{enumerable:!0,get:function(){return s.localessEditableField}}),exports.localessInit=e.localessInit,exports.localessSyncReady=e.localessSyncReady,exports.registerComponent=e.registerComponent,exports.renderRichTextToReact=r.renderRichTextToReact,exports.resolveAsset=e.resolveAsset,exports.unregisterComponent=e.unregisterComponent;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../core/state.js"),t=require("../core/utils/link.util.js"),n=require("../core/components/localess-component.js"),r=require("../core/richtext.js"),i=require("../ssr/localess-component.js"),a=require("../ssr/localess-document.js"),o=require("./localess-document.js");let s=require("@localess/client");exports.LocalessComponent=n.LocalessComponent,exports.LocalessDocument=o.LocalessDocument,exports.LocalessServerComponent=i.LocalessServerComponent,exports.LocalessServerDocument=a.LocalessServerDocument,exports.findLink=t.findLink,exports.getComponent=e.getComponent,exports.getFallbackComponent=e.getFallbackComponent,exports.getLocalessClient=e.getLocalessClient,Object.defineProperty(exports,"isBrowser",{enumerable:!0,get:function(){return s.isBrowser}}),Object.defineProperty(exports,"isIframe",{enumerable:!0,get:function(){return s.isIframe}}),Object.defineProperty(exports,"isServer",{enumerable:!0,get:function(){return s.isServer}}),exports.isSyncEnabled=e.isSyncEnabled,Object.defineProperty(exports,"localessEditable",{enumerable:!0,get:function(){return s.localessEditable}}),Object.defineProperty(exports,"localessEditableField",{enumerable:!0,get:function(){return s.localessEditableField}}),exports.localessInit=e.localessInit,exports.localessSyncOn=e.localessSyncOn,exports.localessSyncOnChange=e.localessSyncOnChange,exports.localessSyncReady=e.localessSyncReady,exports.registerComponent=e.registerComponent,exports.renderRichTextToReact=r.renderRichTextToReact,exports.resolveAsset=e.resolveAsset,exports.unregisterComponent=e.unregisterComponent;
|
package/dist/rsc/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { getComponent as e, getFallbackComponent as t, getLocalessClient as n, isSyncEnabled as r, localessInit as i,
|
|
2
|
-
import { findLink as
|
|
3
|
-
import { isBrowser as
|
|
4
|
-
import { LocalessComponent as
|
|
5
|
-
import { renderRichTextToReact as
|
|
6
|
-
import { LocalessServerComponent as
|
|
7
|
-
import { LocalessServerDocument as
|
|
8
|
-
import { LocalessDocument as
|
|
9
|
-
export {
|
|
1
|
+
import { getComponent as e, getFallbackComponent as t, getLocalessClient as n, isSyncEnabled as r, localessInit as i, localessSyncOn as a, localessSyncOnChange as o, localessSyncReady as s, registerComponent as c, resolveAsset as l, unregisterComponent as u } from "../core/state.mjs";
|
|
2
|
+
import { findLink as d } from "../core/utils/link.util.mjs";
|
|
3
|
+
import { isBrowser as f, isIframe as p, isServer as m, localessEditable as h, localessEditableField as g } from "../core/utils/index.mjs";
|
|
4
|
+
import { LocalessComponent as _ } from "../core/components/localess-component.mjs";
|
|
5
|
+
import { renderRichTextToReact as v } from "../core/richtext.mjs";
|
|
6
|
+
import { LocalessServerComponent as y } from "../ssr/localess-component.mjs";
|
|
7
|
+
import { LocalessServerDocument as b } from "../ssr/localess-document.mjs";
|
|
8
|
+
import { LocalessDocument as x } from "./localess-document.mjs";
|
|
9
|
+
export { _ as LocalessComponent, x as LocalessDocument, y as LocalessServerComponent, b as LocalessServerDocument, d as findLink, e as getComponent, t as getFallbackComponent, n as getLocalessClient, f as isBrowser, p as isIframe, m as isServer, r as isSyncEnabled, h as localessEditable, g as localessEditableField, i as localessInit, a as localessSyncOn, o as localessSyncOnChange, s as localessSyncReady, c as registerComponent, v as renderRichTextToReact, l as resolveAsset, u as unregisterComponent };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";
|
|
1
|
+
"use client";const e=require("../core/state.js");let t=require("react"),n=require("@localess/client");var r=r=>(console.info(`LocalessSync:init`),(0,t.useEffect)(()=>{async function t(){r.enableSync&&(0,n.isBrowser)()&&(0,n.isIframe)()&&(await(0,n.loadLocalessSync)(r.origin),e.localessSyncOnChange(e=>{console.info(`LocalessSync:change:`,e),r.document.data=e.data}))}t()},[]),null);exports.LocalessSync=r;
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { localessSyncOnChange as e } from "../core/state.mjs";
|
|
3
|
+
import { isBrowser as t, isIframe as n } from "../core/utils/index.mjs";
|
|
4
|
+
import { useEffect as r } from "react";
|
|
5
|
+
import { loadLocalessSync as i } from "@localess/client";
|
|
5
6
|
//#region src/rsc/localess-sync.tsx
|
|
6
|
-
var
|
|
7
|
-
async function
|
|
8
|
-
|
|
9
|
-
console.info("LocalessSync:change:", e),
|
|
7
|
+
var a = (a) => (console.info("LocalessSync:init"), r(() => {
|
|
8
|
+
async function r() {
|
|
9
|
+
a.enableSync && t() && n() && (await i(a.origin), e((e) => {
|
|
10
|
+
console.info("LocalessSync:change:", e), a.document.data = e.data;
|
|
10
11
|
}));
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
+
r();
|
|
13
14
|
}, []), null);
|
|
14
15
|
//#endregion
|
|
15
|
-
export {
|
|
16
|
+
export { a as LocalessSync };
|
package/dist/ssr/index.d.ts
CHANGED
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
* - LocalessDocument (requires 'use client')
|
|
23
23
|
* - useLocaless (requires 'use client')
|
|
24
24
|
* - localessEditable / localessEditableField / isBrowser / isIframe (browser-only)
|
|
25
|
-
* - isSyncEnabled
|
|
26
|
-
* - Sync event types (LocalessSync, EventToApp, EventCallback, EventToAppType)
|
|
25
|
+
* - isSyncEnabled / localessSyncOn / localessSyncOnChange (not meaningful without live editing)
|
|
26
|
+
* - Sync event types (LocalessSync, EventToApp, EventToAppOf, EventCallback, EventToAppType)
|
|
27
27
|
*/
|
|
28
28
|
export type * from '../core/models';
|
|
29
29
|
export { renderRichTextToReact } from '../core/richtext';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@localess/react",
|
|
3
|
-
"version": "3.3.0-dev.
|
|
3
|
+
"version": "3.3.0-dev.20260708124505",
|
|
4
4
|
"description": "ReactJS JavaScript/TypeScript SDK for Localess's API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"localess",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"react-dom": "^17 || ^18 || ^19"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@localess/client": "3.3.0-dev.
|
|
64
|
+
"@localess/client": "3.3.0-dev.20260708124505",
|
|
65
65
|
"@tiptap/extension-bold": "^3.22.5",
|
|
66
66
|
"@tiptap/extension-bullet-list": "^3.22.5",
|
|
67
67
|
"@tiptap/extension-code": "^3.22.5",
|