@localess/react 3.0.0 → 3.0.1-dev.20260323212140

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 CHANGED
@@ -99,7 +99,7 @@ import { LocalessComponent } from "@localess/react";
99
99
 
100
100
  | Prop | Type | Required | Description |
101
101
  |------|------|----------|-------------|
102
- | `data` | `ContentData` | ✅ | Content data object from Localess. The component looks up `data._schema` or `data.schema` in the component registry |
102
+ | `data` | `ContentData` | ✅ | Content data object from Localess. The component looks up `data._schema` in the component registry |
103
103
  | `links` | `Links` | ❌ | Resolved content links map, forwarded to the rendered component |
104
104
  | `references` | `References` | ❌ | Resolved references map, forwarded to the rendered component |
105
105
  | `ref` | `React.Ref<HTMLElement>` | ❌ | Ref forwarded to the rendered component's root element |
@@ -346,6 +346,31 @@ The following are re-exported for convenience so you only need to import from `@
346
346
 
347
347
  ---
348
348
 
349
+ ## AI Coding Agents
350
+
351
+ This package ships a [`SKILL.md`](./SKILL.md) file that provides AI coding agents (GitHub Copilot, Claude Code, Cursor, and others) with accurate, up-to-date APIs, patterns, and best practices. Most agents automatically read `SKILL.md` when starting a session.
352
+
353
+ ### Using SKILL.md in your project
354
+
355
+ `SKILL.md` is included in the npm package, so it is available locally after installation. Reference it from your project's `AGENTS.md` to ensure your agent reads accurate Localess documentation every session:
356
+
357
+ ```markdown
358
+ ## Localess
359
+
360
+ @node_modules/@localess/react/SKILL.md
361
+ ```
362
+
363
+ The `@` prefix is the syntax used by most agent tools (GitHub Copilot, Claude Code, Cursor) to import file contents inline into the agent context.
364
+
365
+ When you change the public API of this package, update `SKILL.md` alongside your code:
366
+
367
+ - **New option or parameter** → add it to the relevant options table and usage example
368
+ - **Changed behaviour** → update the description and any affected code snippets
369
+ - **Deprecated API** → mark it clearly and point to the replacement
370
+ - **New component or hook** → add a full entry with props and usage example
371
+
372
+ ---
373
+
349
374
  ## License
350
375
 
351
376
  [MIT](../../LICENSE)
package/SKILL.md ADDED
@@ -0,0 +1,458 @@
1
+ # SKILL: @localess/react
2
+
3
+ ## Overview
4
+
5
+ `@localess/react` is the **React integration layer** for Localess. It builds on `@localess/client` and adds:
6
+
7
+ - A **component registry** mapping Localess schema keys to React components
8
+ - `<LocalessComponent>` — dynamic content renderer
9
+ - **Visual Editor sync** support with editable attributes
10
+ - **Rich text** rendering from Tiptap JSON format
11
+ - **Asset URL** resolution
12
+
13
+ **Peer dependencies:** React 17, 18, or 19 + react-dom.
14
+
15
+ ---
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install @localess/react
21
+ ```
22
+
23
+ ---
24
+
25
+ ## Initialization
26
+
27
+ Call `localessInit()` **once** at app startup — in your root layout or `_app.tsx`. This is safe in Server Components since it only sets up global state.
28
+
29
+ ```typescript
30
+ import { localessInit } from "@localess/react";
31
+
32
+ localessInit({
33
+ // Required — same as @localess/client
34
+ origin: process.env.LOCALESS_ORIGIN!,
35
+ spaceId: process.env.LOCALESS_SPACE_ID!,
36
+ token: process.env.LOCALESS_TOKEN!,
37
+
38
+ // Optional client settings
39
+ version: 'draft', // undefined = published (default), 'draft' for preview
40
+ cacheTTL: 300000, // 5 minutes default
41
+ debug: false,
42
+
43
+ // React-specific options
44
+ enableSync: process.env.NODE_ENV !== 'production', // Load Visual Editor sync
45
+ components: {
46
+ 'page': PageComponent,
47
+ 'hero-section': HeroSection,
48
+ 'nav-menu': NavMenu,
49
+ 'footer': Footer,
50
+ },
51
+ fallbackComponent: UnknownBlock, // Rendered when schema has no registered component
52
+ });
53
+ ```
54
+
55
+ > **Security:** `token` is only safe here because this runs server-side. Never expose it to the browser.
56
+
57
+ ---
58
+
59
+ ## LocalessComponent
60
+
61
+ Dynamically renders a Localess content block by looking up its `_schema` in the component registry.
62
+
63
+ ```tsx
64
+ import { LocalessComponent } from "@localess/react";
65
+
66
+ // In a Server Component
67
+ <LocalessComponent
68
+ data={content.data}
69
+ links={content.links}
70
+ references={content.references}
71
+ />
72
+ ```
73
+
74
+ ### Rendering Logic
75
+
76
+ 1. Read `data._schema` as the component registry key
77
+ 2. Look up registered component by that key
78
+ 3. If found → render component with `data`, `links`, `references`; when sync is enabled, also injects `data-ll-id` and `data-ll-schema` as props (user components should spread `{...localessEditable(data)}` on their root element)
79
+ 4. If not found → try `fallbackComponent`
80
+ 5. If no fallback → render error message
81
+
82
+ ### Nested Content
83
+
84
+ Use `LocalessComponent` recursively for nested structures:
85
+
86
+ ```tsx
87
+ const Page = ({ data, links, references }) => (
88
+ <main {...localessEditable(data)}>
89
+ {data.sections?.map(section => (
90
+ <LocalessComponent
91
+ key={section._id}
92
+ data={section}
93
+ links={links}
94
+ references={references}
95
+ />
96
+ ))}
97
+ </main>
98
+ );
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Writing Components
104
+
105
+ Each component receives `data`, `links`, and `references` as props. Always spread editable attributes when Visual Editor sync is enabled.
106
+
107
+ ```tsx
108
+ import { localessEditable, localessEditableField, resolveAsset } from "@localess/react";
109
+ import type { HeroSection } from "./.localess/localess";
110
+
111
+ type Props = LocalessComponentProps<HeroSection>;
112
+
113
+ const HeroSection = ({ data, links, references }: Props) => (
114
+ <section {...localessEditable(data)}>
115
+ <h1 {...localessEditableField<HeroSection>('title')}>
116
+ {data.title}
117
+ </h1>
118
+ <p {...localessEditableField<HeroSection>('subtitle')}>
119
+ {data.subtitle}
120
+ </p>
121
+ {data.image && (
122
+ <img
123
+ src={resolveAsset(data.image)}
124
+ alt={data.imageAlt}
125
+ />
126
+ )}
127
+ {data.cta && (
128
+ <LocalessComponent data={data.cta} links={links} references={references} />
129
+ )}
130
+ </section>
131
+ );
132
+
133
+ export default HeroSection;
134
+ ```
135
+
136
+ ---
137
+
138
+ ## Editable Attribute Helpers
139
+
140
+ These add attributes recognized by the Localess Visual Editor for highlighting and inline editing.
141
+
142
+ ```typescript
143
+ import { localessEditable, localessEditableField } from "@localess/react";
144
+
145
+ // On root element of a block — adds data-ll-id and data-ll-schema
146
+ <article {...localessEditable(data)} />
147
+
148
+ // On a specific field — adds data-ll-field="fieldName"
149
+ // Generic type T restricts fieldName to valid keys of that content type
150
+ <span {...localessEditableField<MyBlock>('description')} />
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Visual Editor Sync
156
+
157
+ `localessInit()` is the **single entry point** for Visual Editor integration. Setting `enableSync: true` handles everything: injecting the sync script, registering components, and enabling editable attribute injection on `LocalessComponent`.
158
+
159
+ ### What `enableSync: true` activates
160
+
161
+ 1. Injects the Localess sync script (`loadLocalessSync`) into `<head>`
162
+ 2. Makes `LocalessComponent` inject `data-ll-id` and `data-ll-schema` on rendered elements
163
+ 3. Makes `localessEditable()` / `localessEditableField()` emit their `data-ll-*` attributes (no-op when sync is off)
164
+
165
+ ```typescript
166
+ localessInit({
167
+ origin: process.env.LOCALESS_ORIGIN!,
168
+ spaceId: process.env.LOCALESS_SPACE_ID!,
169
+ token: process.env.LOCALESS_TOKEN!,
170
+ enableSync: process.env.NODE_ENV !== 'production', // only in editor/preview environments
171
+ components: { ... },
172
+ });
173
+ ```
174
+
175
+ > Never enable sync in production — the script is only meaningful inside the Localess Visual Editor iframe.
176
+
177
+ ### Receiving Real-time Editor Events
178
+
179
+ Once the sync script is loaded, `window.localess` becomes available inside the iframe. Subscribe to it in a Client Component to apply live updates:
180
+
181
+ ```tsx
182
+ 'use client';
183
+
184
+ import { useEffect, useState } from "react";
185
+ import { LocalessComponent, localessEditable } from "@localess/react";
186
+ import type { Content, Page } from "./.localess/localess";
187
+
188
+ export function PageClient({ initialContent }: { initialContent: Content<Page> }) {
189
+ const [pageData, setPageData] = useState(initialContent.data);
190
+
191
+ useEffect(() => {
192
+ if (window.localess) {
193
+ window.localess.on(['input', 'change'], (event) => {
194
+ if (event.type === 'input' || event.type === 'change') {
195
+ setPageData(event.data);
196
+ }
197
+ });
198
+ }
199
+ // No cleanup needed: window.localess has no .off() method
200
+ }, []);
201
+
202
+ return (
203
+ <main {...localessEditable(pageData)}>
204
+ {pageData?.body?.map(item => (
205
+ <LocalessComponent
206
+ key={item._id}
207
+ data={item}
208
+ links={initialContent.links}
209
+ references={initialContent.references}
210
+ />
211
+ ))}
212
+ </main>
213
+ );
214
+ }
215
+ ```
216
+
217
+ **Available events via `window.localess.on()`:**
218
+
219
+ | Event | When |
220
+ |---------------|-----------------------------------------------|
221
+ | `input` | User is typing in a field (real-time preview) |
222
+ | `change` | Field value confirmed |
223
+ | `save` | Content saved |
224
+ | `publish` | Content published |
225
+ | `pong` | Editor heartbeat response |
226
+ | `enterSchema` | Editor cursor enters a schema block |
227
+ | `hoverSchema` | Editor cursor hovers over a schema block |
228
+
229
+ > `window.localess` only exposes `.on()` and `.onChange()` — there is no `.off()`.
230
+
231
+ ### Pattern: Split Server/Client Components (Next.js App Router)
232
+
233
+ The recommended pattern keeps data fetching server-side while the Client Component handles live sync:
234
+
235
+ ```tsx
236
+ // app/[locale]/page.tsx — Server Component: fetches data, no sync logic
237
+ import { getLocalessClient } from "@localess/react";
238
+ import { PageClient } from "./page-client";
239
+ import type { Page } from "./.localess/localess";
240
+
241
+ export default async function HomePage({
242
+ searchParams,
243
+ }: {
244
+ searchParams: Promise<{ locale?: string }>;
245
+ }) {
246
+ const { locale } = await searchParams;
247
+ const client = getLocalessClient();
248
+ const content = await client.getContentBySlug<Page>('home', { locale });
249
+
250
+ return <PageClient initialContent={content} />;
251
+ }
252
+ ```
253
+
254
+ ```tsx
255
+ // app/[locale]/page-client.tsx — Client Component: renders + handles live edits
256
+ 'use client';
257
+
258
+ import { useEffect, useState } from "react";
259
+ import { LocalessComponent, localessEditable } from "@localess/react";
260
+ import type { Content, Page } from "./.localess/localess";
261
+
262
+ export function PageClient({ initialContent }: { initialContent: Content<Page> }) {
263
+ const [pageData, setPageData] = useState(initialContent.data);
264
+
265
+ useEffect(() => {
266
+ if (window.localess) {
267
+ window.localess.on(['input', 'change'], (event) => {
268
+ if (event.type === 'input' || event.type === 'change') {
269
+ setPageData(event.data);
270
+ }
271
+ });
272
+ }
273
+ }, []);
274
+
275
+ return (
276
+ <main {...localessEditable(pageData)}>
277
+ {pageData?.body?.map(item => (
278
+ <LocalessComponent
279
+ key={item._id}
280
+ data={item}
281
+ links={initialContent.links}
282
+ references={initialContent.references}
283
+ />
284
+ ))}
285
+ </main>
286
+ );
287
+ }
288
+ ```
289
+
290
+ ---
291
+
292
+ ## Rich Text Rendering
293
+
294
+ Converts Localess `ContentRichText` (Tiptap JSON) to a React node tree.
295
+
296
+ ```tsx
297
+ import { renderRichTextToReact } from "@localess/react";
298
+
299
+ const Article = ({ data }) => (
300
+ <article>
301
+ <h1>{data.title}</h1>
302
+ <div>{renderRichTextToReact(data.body)}</div>
303
+ </article>
304
+ );
305
+ ```
306
+
307
+ **Supported elements:** headings (h1–h6), paragraphs, bold, italic, strikethrough, underline, ordered/unordered lists, code, code blocks, links.
308
+
309
+ ---
310
+
311
+ ## Asset Resolution
312
+
313
+ ```typescript
314
+ import { resolveAsset } from "@localess/react";
315
+
316
+ // ContentAsset → full URL
317
+ const imageUrl = resolveAsset(data.heroImage);
318
+ // Returns: https://my-localess.web.app/api/v1/spaces/{spaceId}/assets/{uri}
319
+ ```
320
+
321
+ Set up automatically during `localessInit()` from `origin` + `spaceId`.
322
+
323
+ ---
324
+
325
+ ## Component Registry Management
326
+
327
+ For dynamic/lazy registration (e.g., plugin systems):
328
+
329
+ ```typescript
330
+ import {
331
+ registerComponent,
332
+ unregisterComponent,
333
+ setComponents,
334
+ getComponent,
335
+ setFallbackComponent,
336
+ getFallbackComponent,
337
+ } from "@localess/react";
338
+
339
+ registerComponent('promo-banner', PromoBanner);
340
+ unregisterComponent('promo-banner');
341
+ setComponents({ 'page': Page, 'hero': Hero }); // replaces entire registry
342
+ const HeroComp = getComponent('hero');
343
+ setFallbackComponent(UnknownBlock);
344
+ ```
345
+
346
+ ---
347
+
348
+ ## Accessing the Client
349
+
350
+ In Server Components, access the initialized client directly:
351
+
352
+ ```typescript
353
+ import { getLocalessClient } from "@localess/react";
354
+
355
+ const client = getLocalessClient(); // throws if localessInit() not called
356
+ const [content, translations] = await Promise.all([
357
+ client.getContentBySlug<Page>('home', { locale: 'en', resolveReference: true }),
358
+ client.getTranslations('en'),
359
+ ]);
360
+ ```
361
+
362
+ ---
363
+
364
+ ## Full Next.js 15 App Router Setup
365
+
366
+ ```typescript
367
+ // app/layout.tsx (Server Component)
368
+ import { localessInit } from "@localess/react";
369
+ import { Page, HeroSection, NavMenu, Footer } from "@/components/localess";
370
+
371
+ localessInit({
372
+ origin: process.env.LOCALESS_ORIGIN!,
373
+ spaceId: process.env.LOCALESS_SPACE_ID!,
374
+ token: process.env.LOCALESS_TOKEN!,
375
+ enableSync: process.env.NODE_ENV !== 'production',
376
+ components: {
377
+ 'page': Page,
378
+ 'hero-section': HeroSection,
379
+ 'nav-menu': NavMenu,
380
+ 'footer': Footer,
381
+ },
382
+ });
383
+
384
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
385
+ return (
386
+ <html>
387
+ <body>{children}</body>
388
+ </html>
389
+ );
390
+ }
391
+ ```
392
+
393
+ ---
394
+
395
+ ## Schema Key Convention
396
+
397
+ Schema keys must match exactly what is configured in Localess CMS settings. Use lowercase hyphenated names:
398
+
399
+ ```typescript
400
+ components: {
401
+ 'page': Page, // _schema === 'page'
402
+ 'hero-section': Hero, // _schema === 'hero-section'
403
+ 'card-grid': CardGrid, // _schema === 'card-grid'
404
+ 'rich-text-block': RTE, // _schema === 'rich-text-block'
405
+ }
406
+ ```
407
+
408
+ ---
409
+
410
+ ## Best Practices
411
+
412
+ 1. **Call `localessInit()` once** in root layout — never in individual page components.
413
+
414
+ 2. **Disable sync in production**: `enableSync: process.env.NODE_ENV !== 'production'` — the sync script is only useful inside the Localess editor.
415
+
416
+ 3. **Always use generated types** (`localess types generate`) for full `data` type safety in components.
417
+
418
+ 4. **Use `localessEditable` on every block root element** and `localessEditableField` on key editable fields so editors can click-to-edit.
419
+
420
+ 5. **Pass `links` and `references` through the tree** — child `LocalessComponent`s need them for resolved data.
421
+
422
+ 6. **Use `resolveAsset()` instead of manually constructing asset URLs** — the format may change between versions.
423
+
424
+ 7. **Fetch data server-side only** — `getLocalessClient()` in React Server Components, API routes, or loaders. Never in `useEffect` or client components.
425
+
426
+ ---
427
+
428
+ ## Exports Reference
429
+
430
+ ```typescript
431
+ // Initialization & client
432
+ export { localessInit, getLocalessClient }
433
+
434
+ // Component registry
435
+ export { registerComponent, unregisterComponent, setComponents, getComponent }
436
+ export { setFallbackComponent, getFallbackComponent, isSyncEnabled }
437
+
438
+ // Rendering
439
+ export { LocalessComponent } // Dynamic schema-to-component renderer
440
+ export { renderRichTextToReact } // Rich text → React nodes
441
+ export { resolveAsset } // ContentAsset → full URL
442
+
443
+ // Visual editor (re-exported from @localess/client)
444
+ export { localessEditable, localessEditableField }
445
+ export { llEditable, llEditableField } // Deprecated
446
+
447
+ // Environment utilities (re-exported from @localess/client)
448
+ export { isBrowser, isServer, isIframe }
449
+
450
+ // Types (re-exported from @localess/client + local)
451
+ export type { LocalessClient, LocalessOptions }
452
+ export type { LocalessSync, EventToApp, EventCallback, EventToAppType }
453
+ export type {
454
+ Content, ContentData, ContentMetadata, ContentDataSchema, ContentDataField,
455
+ ContentAsset, ContentRichText, ContentLink, ContentReference,
456
+ Links, References, Translations,
457
+ }
458
+ ```
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import React__default from 'react';
3
3
  import { LocalessClientOptions, ContentData, Links, References, ContentRichText, LocalessClient, ContentAsset } 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, llEditable, llEditableField, localessEditable, localessEditableField } 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 LocalessOptions = LocalessClientOptions & {
7
7
  /**
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import React__default from 'react';
3
3
  import { LocalessClientOptions, ContentData, Links, References, ContentRichText, LocalessClient, ContentAsset } 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, llEditable, llEditableField, localessEditable, localessEditableField } 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 LocalessOptions = LocalessClientOptions & {
7
7
  /**
package/dist/index.js CHANGED
@@ -28,8 +28,6 @@ __export(index_exports, {
28
28
  isIframe: () => import_client3.isIframe,
29
29
  isServer: () => import_client3.isServer,
30
30
  isSyncEnabled: () => isSyncEnabled,
31
- llEditable: () => import_client3.llEditable,
32
- llEditableField: () => import_client3.llEditableField,
33
31
  localessEditable: () => import_client3.localessEditable,
34
32
  localessEditableField: () => import_client3.localessEditableField,
35
33
  localessInit: () => localessInit,
@@ -63,7 +61,7 @@ var LocalessComponent = (0, import_react.forwardRef)(({ data, links, references,
63
61
  " is not provided."
64
62
  ] });
65
63
  }
66
- const Comp = getComponent(data._schema || data.schema);
64
+ const Comp = getComponent(data._schema);
67
65
  if (Comp) {
68
66
  const attr = isSyncEnabled() ? (0, import_client.localessEditable)(data) : {};
69
67
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Comp, { ref, data, links, references, ...attr, ...restProps });
@@ -188,8 +186,6 @@ function resolveAsset(asset) {
188
186
  isIframe,
189
187
  isServer,
190
188
  isSyncEnabled,
191
- llEditable,
192
- llEditableField,
193
189
  localessEditable,
194
190
  localessEditableField,
195
191
  localessInit,
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ var FONT_BOLD = "font-weight: bold";
6
6
  var FONT_NORMAL = "font-weight: normal";
7
7
 
8
8
  // src/index.ts
9
- import { llEditable, llEditableField, localessEditable as localessEditable2, localessEditableField, isBrowser, isServer, isIframe } from "@localess/client";
9
+ import { localessEditable as localessEditable2, localessEditableField, isBrowser, isServer, isIframe } from "@localess/client";
10
10
 
11
11
  // src/localess-componenet.tsx
12
12
  import { forwardRef } from "react";
@@ -21,7 +21,7 @@ var LocalessComponent = forwardRef(({ data, links, references, ...restProps }, r
21
21
  " is not provided."
22
22
  ] });
23
23
  }
24
- const Comp = getComponent(data._schema || data.schema);
24
+ const Comp = getComponent(data._schema);
25
25
  if (Comp) {
26
26
  const attr = isSyncEnabled() ? localessEditable(data) : {};
27
27
  return /* @__PURE__ */ jsx(Comp, { ref, data, links, references, ...attr, ...restProps });
@@ -145,8 +145,6 @@ export {
145
145
  isIframe,
146
146
  isServer,
147
147
  isSyncEnabled,
148
- llEditable,
149
- llEditableField,
150
148
  localessEditable2 as localessEditable,
151
149
  localessEditableField,
152
150
  localessInit,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@localess/react",
3
- "version": "3.0.0",
3
+ "version": "3.0.1-dev.20260323212140",
4
4
  "description": "ReactJS JavaScript/TypeScript SDK for Localess's API.",
5
5
  "keywords": [
6
6
  "localess",
@@ -23,7 +23,8 @@
23
23
  "url": "https://github.com/Lessify/localess-js/issues"
24
24
  },
25
25
  "files": [
26
- "dist"
26
+ "dist",
27
+ "SKILL.md"
27
28
  ],
28
29
  "main": "dist/index.js",
29
30
  "module": "dist/index.mjs",
@@ -45,7 +46,7 @@
45
46
  "react-dom": "^17 || ^18 || ^19"
46
47
  },
47
48
  "dependencies": {
48
- "@localess/client": "3.0.0",
49
+ "@localess/client": "3.0.1-dev.20260323212140",
49
50
  "@tiptap/static-renderer": "^3.20.1",
50
51
  "@tiptap/html": "^3.20.1",
51
52
  "@tiptap/extension-bold": "^3.20.1",