@rakun-kit/manager-react 1.5.8 → 1.5.9

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.
Files changed (40) hide show
  1. package/README.md +300 -296
  2. package/dist/cjs/components/editor/themes/editor-theme.css +91 -91
  3. package/dist/cjs/components/ui/sortable.js +4 -4
  4. package/dist/cjs/router/dashboard/[contentType]/[edit]/ContentTypeEdit.js +6 -2
  5. package/dist/cjs/router/dashboard/[contentType]/[edit]/ContentTypeEdit.js.map +1 -1
  6. package/dist/cjs/router/dashboard/[contentType]/[edit]/_components/EditTabPanels.js +1 -1
  7. package/dist/cjs/router/dashboard/[contentType]/[edit]/_components/EditTabPanels.js.map +1 -1
  8. package/dist/cjs/router/dashboard/[contentType]/[edit]/_fields/RelationField/NewRelation.js +1 -1
  9. package/dist/cjs/router/dashboard/[contentType]/[edit]/_fields/RelationField/NewRelation.js.map +1 -1
  10. package/dist/cjs/router/dashboard/[contentType]/[edit]/_fields/RelationField/index.js.map +1 -1
  11. package/dist/cjs/router/dashboard/[contentType]/[edit]/_fields/seoBindings.js +36 -0
  12. package/dist/cjs/router/dashboard/[contentType]/[edit]/_fields/seoBindings.js.map +1 -0
  13. package/dist/cjs/state/theme-script.js +12 -12
  14. package/dist/docs/index.md +197 -191
  15. package/dist/esm/components/editor/themes/editor-theme.css +91 -91
  16. package/dist/esm/components/ui/sortable.js +4 -4
  17. package/dist/esm/i18n/useTranslations.d.ts.map +1 -1
  18. package/dist/esm/router/dashboard/[contentType]/[edit]/ContentTypeEdit.d.ts +2 -0
  19. package/dist/esm/router/dashboard/[contentType]/[edit]/ContentTypeEdit.d.ts.map +1 -1
  20. package/dist/esm/router/dashboard/[contentType]/[edit]/ContentTypeEdit.js +6 -2
  21. package/dist/esm/router/dashboard/[contentType]/[edit]/ContentTypeEdit.js.map +1 -1
  22. package/dist/esm/router/dashboard/[contentType]/[edit]/_components/EditTabPanels.d.ts.map +1 -1
  23. package/dist/esm/router/dashboard/[contentType]/[edit]/_components/EditTabPanels.js +1 -1
  24. package/dist/esm/router/dashboard/[contentType]/[edit]/_components/EditTabPanels.js.map +1 -1
  25. package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/RelationField/NewRelation.d.ts.map +1 -1
  26. package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/RelationField/NewRelation.js +1 -1
  27. package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/RelationField/NewRelation.js.map +1 -1
  28. package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/RelationField/index.d.ts +1 -0
  29. package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/RelationField/index.d.ts.map +1 -1
  30. package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/RelationField/index.js.map +1 -1
  31. package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/seoBindings.d.ts +6 -0
  32. package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/seoBindings.d.ts.map +1 -0
  33. package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/seoBindings.js +32 -0
  34. package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/seoBindings.js.map +1 -0
  35. package/dist/esm/router/dashboard/[contentType]/[edit]/_hooks/useRouteLayoutData.d.ts.map +1 -1
  36. package/dist/esm/state/theme-script.js +12 -12
  37. package/dist/styles.css +7 -7
  38. package/dist/styles.css.d.ts +3 -3
  39. package/dist/tsconfig.build.tsbuildinfo +1 -1
  40. package/package.json +217 -217
@@ -1,194 +1,200 @@
1
- # `@rakun-kit/manager-react` AI usage manual
2
-
3
- This package is the publishable React manager, its transport clients,
4
- navigation abstraction, locale runtime, plugin API and CSS. Most Next.js apps
5
- should use `@rakun-kit/next/manager`; use this package directly for custom
6
- React hosts.
7
-
8
- Read the core manual at
9
- `node_modules/@rakun-kit/core/dist/docs/index.md` before changing manager/server
10
- contracts.
11
-
12
- ## Install and mount
13
-
14
- ```sh
15
- bun add @rakun-kit/manager-react react react-dom
16
- ```
17
-
18
- ```tsx
19
- import { ManagerBrowserApp, createHttpManagerClient } from '@rakun-kit/manager-react'
20
- import '@rakun-kit/manager-react/styles.css'
21
-
22
- const client = createHttpManagerClient({ baseUrl: '/api/rakun' })
23
-
24
- export function ManagerPage() {
25
- return (
26
- <ManagerBrowserApp client={client} pathname={window.location.pathname} basePath="/backend" />
27
- )
28
- }
29
- ```
30
-
31
- Import the stylesheet exactly once. `ManagerBrowserApp` owns browser-history
32
- navigation. Use `ManagerRuntimeApp` when the host supplies navigation.
33
-
34
- ## Clients and navigation
35
-
36
- - HTTP: `createHttpManagerClient` from `/client/http`.
37
- - tRPC: `createTrpcManagerClient` from `/client/trpc`.
38
- - Custom transport: `createManagerClient` from `/client/request`.
39
- - Router bridge: `createPathManagerNavigation` from `/state/navigation`.
40
-
41
- Use operation names and payloads from Rakun contracts; do not recreate endpoint
42
- types in host code. Keep `baseUrl` (API) distinct from `basePath` (manager UI).
43
-
44
- ## Link field picker
45
-
46
- The `f.link()` editor always shows Title and Destination inputs. A typed or
47
- pasted URL is stored as `{ href, title }`. Opening the destination picker
48
- exposes the home page and configured page-route types with their content type
49
- icons; selecting an item fills an empty title from its manager label and stores
50
- `{ routeId, contentTypeId, title }` so core can resolve localized paths.
51
- Existing string and untitled reference values remain editable and are upgraded
52
- to the titled shape when changed.
53
-
54
- Compound arrays such as `f.array(f.link())` render each value as a reorderable
55
- card in the Info editor. Use the drag handle to change their persisted order;
56
- current nested input values are preserved while an item is moved.
57
-
58
- ## Media uploads
59
-
60
- The manager preserves Unicode original file names when uploading media. Names
61
- with accents, non-Latin scripts, or emoji are encoded into ASCII for the binary
62
- upload headers and restored by core before metadata is saved.
63
-
64
- When optimization is enabled, right-click an image and select `Reimport with
65
- current optimization` to regenerate its optimized source, preview, and
66
- responsive sizes. The action keeps the existing media ID, title, alt text,
67
- folder, and content references. You can also multi-select images and use the
68
- selection toolbar reimport action. Optimization is enabled by default in the
69
- media library; generated previews are stored as inline `data:image/...`
70
- strings on the media record for LQIP use.
71
-
72
- Gallery and file-field image previews use `@rakun-kit/react` `Image` with a
73
- layout-appropriate `sizes` value so responsive variants are selected when
74
- available.
75
-
76
- ## Manager plugins
77
-
78
- ```tsx
79
- import {
80
- defineRakunManagerPlugin,
81
- ManagerBrowserApp,
82
- } from '@rakun-kit/manager-react'
83
-
84
- const plugin = defineRakunManagerPlugin({
85
- id: '@acme/analytics',
86
- routes: [{
87
- id: 'dashboard',
88
- path: '/analytics',
89
- component: AnalyticsScreen,
90
- permissions: ['plugin.analytics.view'],
91
- }],
92
- sidebar: [{
93
- id: 'analytics',
94
- title: 'analytics.title',
95
- routeId: 'dashboard',
96
- position: 'primary',
97
- group: 'Plugins',
98
- }],
99
- })
100
-
101
- <ManagerBrowserApp plugins={[plugin]} {...props} />
102
- ```
103
-
104
- Plugins can contribute routes, sidebar entries, custom field editors and
105
- RichText extensions. Use exported plugin types from
106
- `@rakun-kit/manager-react/plugins`. Plugin ids, route ids, field editor ids,
107
- Lexical node types and RichText plugin ids must be unique.
108
-
109
- In Next.js, plugin registration belongs in a `'use client'` wrapper around
110
- `RakunManagerClientPage`; pass the wrapper to `RakunManagerPage` as
111
- `managerComponent`.
112
-
113
- ## Languages and copy
114
-
115
- English is built in. Additional server-provided UI packs come from
116
- `@rakun-kit/manager-locales` and are configured in core `managerLanguages`.
117
- Content editing locale and manager UI locale are separate states.
118
-
119
- Built-in manager copy must use the static manager translation catalog. Project
120
- labels may use arbitrary project keys. Fields resolve `field.<fieldName>` and
121
- layout slots resolve `layoutModule.<layoutKey>` with fallbacks.
122
-
123
- ## Content and template tabs
124
-
125
- For a routeable content type with `iterator`, Content edits the `_iterator`
126
- modules unique to the current document. Template is enabled automatically and
127
- edits one shared composition for every document of that type. Both tabs offer
128
- the same configured iterator modules. The Template module picker additionally
129
- adds a built-in Content item at its root and inside blocks fields; it marks the
130
- exact position where the current document's Content modules are inserted.
131
-
132
- Template changes require the content type's `updateAny` permission and are
133
- saved with optimistic revision checks. Preview includes unsaved changes from
134
- both tabs.
135
-
1
+ # `@rakun-kit/manager-react` AI usage manual
2
+
3
+ This package is the publishable React manager, its transport clients,
4
+ navigation abstraction, locale runtime, plugin API and CSS. Most Next.js apps
5
+ should use `@rakun-kit/next/manager`; use this package directly for custom
6
+ React hosts.
7
+
8
+ Read the core manual at
9
+ `node_modules/@rakun-kit/core/dist/docs/index.md` before changing manager/server
10
+ contracts.
11
+
12
+ ## Install and mount
13
+
14
+ ```sh
15
+ bun add @rakun-kit/manager-react react react-dom
16
+ ```
17
+
18
+ ```tsx
19
+ import { ManagerBrowserApp, createHttpManagerClient } from '@rakun-kit/manager-react'
20
+ import '@rakun-kit/manager-react/styles.css'
21
+
22
+ const client = createHttpManagerClient({ baseUrl: '/api/rakun' })
23
+
24
+ export function ManagerPage() {
25
+ return (
26
+ <ManagerBrowserApp client={client} pathname={window.location.pathname} basePath="/backend" />
27
+ )
28
+ }
29
+ ```
30
+
31
+ Import the stylesheet exactly once. `ManagerBrowserApp` owns browser-history
32
+ navigation. Use `ManagerRuntimeApp` when the host supplies navigation.
33
+
34
+ ## Clients and navigation
35
+
36
+ - HTTP: `createHttpManagerClient` from `/client/http`.
37
+ - tRPC: `createTrpcManagerClient` from `/client/trpc`.
38
+ - Custom transport: `createManagerClient` from `/client/request`.
39
+ - Router bridge: `createPathManagerNavigation` from `/state/navigation`.
40
+
41
+ Use operation names and payloads from Rakun contracts; do not recreate endpoint
42
+ types in host code. Keep `baseUrl` (API) distinct from `basePath` (manager UI).
43
+
44
+ ## Link field picker
45
+
46
+ The `f.link()` editor always shows Title and Destination inputs. A typed or
47
+ pasted URL is stored as `{ href, title }`. Opening the destination picker
48
+ exposes the home page and configured page-route types with their content type
49
+ icons; selecting an item fills an empty title from its manager label and stores
50
+ `{ routeId, contentTypeId, title }` so core can resolve localized paths.
51
+ Existing string and untitled reference values remain editable and are upgraded
52
+ to the titled shape when changed.
53
+
54
+ Compound arrays such as `f.array(f.link())` render each value as a reorderable
55
+ card in the Info editor. Use the drag handle to change their persisted order;
56
+ current nested input values are preserved while an item is moved.
57
+
58
+ ## Media uploads
59
+
60
+ The manager preserves Unicode original file names when uploading media. Names
61
+ with accents, non-Latin scripts, or emoji are encoded into ASCII for the binary
62
+ upload headers and restored by core before metadata is saved.
63
+
64
+ When optimization is enabled, right-click an image and select `Reimport with
65
+ current optimization` to regenerate its optimized source, preview, and
66
+ responsive sizes. The action keeps the existing media ID, title, alt text,
67
+ folder, and content references. You can also multi-select images and use the
68
+ selection toolbar reimport action. Optimization is enabled by default in the
69
+ media library; generated previews are stored as inline `data:image/...`
70
+ strings on the media record for LQIP use.
71
+
72
+ Gallery and file-field image previews use `@rakun-kit/react` `Image` with a
73
+ layout-appropriate `sizes` value so responsive variants are selected when
74
+ available.
75
+
76
+ ## Manager plugins
77
+
78
+ ```tsx
79
+ import {
80
+ defineRakunManagerPlugin,
81
+ ManagerBrowserApp,
82
+ } from '@rakun-kit/manager-react'
83
+
84
+ const plugin = defineRakunManagerPlugin({
85
+ id: '@acme/analytics',
86
+ routes: [{
87
+ id: 'dashboard',
88
+ path: '/analytics',
89
+ component: AnalyticsScreen,
90
+ permissions: ['plugin.analytics.view'],
91
+ }],
92
+ sidebar: [{
93
+ id: 'analytics',
94
+ title: 'analytics.title',
95
+ routeId: 'dashboard',
96
+ position: 'primary',
97
+ group: 'Plugins',
98
+ }],
99
+ })
100
+
101
+ <ManagerBrowserApp plugins={[plugin]} {...props} />
102
+ ```
103
+
104
+ Plugins can contribute routes, sidebar entries, custom field editors and
105
+ RichText extensions. Use exported plugin types from
106
+ `@rakun-kit/manager-react/plugins`. Plugin ids, route ids, field editor ids,
107
+ Lexical node types and RichText plugin ids must be unique.
108
+
109
+ In Next.js, plugin registration belongs in a `'use client'` wrapper around
110
+ `RakunManagerClientPage`; pass the wrapper to `RakunManagerPage` as
111
+ `managerComponent`.
112
+
113
+ ## Languages and copy
114
+
115
+ English is built in. Additional server-provided UI packs come from
116
+ `@rakun-kit/manager-locales` and are configured in core `managerLanguages`.
117
+ Content editing locale and manager UI locale are separate states.
118
+
119
+ Built-in manager copy must use the static manager translation catalog. Project
120
+ labels may use arbitrary project keys. Fields resolve `field.<fieldName>` and
121
+ layout slots resolve `layoutModule.<layoutKey>` with fallbacks.
122
+
123
+ ## Content and template tabs
124
+
125
+ For a routeable content type with `iterator`, Content edits the `_iterator`
126
+ modules unique to the current document. Template is enabled automatically and
127
+ edits one shared composition for every document of that type. Both tabs offer
128
+ the same configured iterator modules. The Template module picker additionally
129
+ adds a built-in Content item at its root and inside blocks fields; it marks the
130
+ exact position where the current document's Content modules are inserted.
131
+
132
+ Template changes require the content type's `updateAny` permission and are
133
+ saved with optimistic revision checks. Preview includes unsaved changes from
134
+ both tabs.
135
+
136
136
  ## Dynamic data mappings
137
-
138
- List bindings use a type-aware mapping editor. When a mapped target property is
139
- itself a `blocks` field, choose `Nested list` to open another collection, query,
140
- filter, and mapping editor for that property. Nested query conditions can select
141
- `Current item` to read the parent source item at that level, or `Current
142
- document` to read the root document. This supports mappings such as Category ->
143
- gallery item -> Project -> image card, and the editor can repeat the flow for
137
+
138
+ List bindings use a type-aware mapping editor. When a mapped target property is
139
+ itself a `blocks` field, choose `Nested list` to open another collection, query,
140
+ filter, and mapping editor for that property. Nested query conditions can select
141
+ `Current item` to read the parent source item at that level, or `Current
142
+ document` to read the root document. This supports mappings such as Category ->
143
+ gallery item -> Project -> image card, and the editor can repeat the flow for
144
144
  deeper block structures.
145
145
 
146
- ## Confirmations
147
-
148
- Use the shared async confirm API instead of ad-hoc yes/no dialogs:
149
-
150
- ```tsx
151
- import { confirm, useConfirm } from '@rakun-kit/manager-react'
152
-
153
- const result = await confirm({
154
- title: 'Delete item',
155
- description: 'This cannot be undone.',
156
- confirmLabel: 'Delete',
157
- variant: 'destructive',
158
- onConfirm: async () => {
159
- await deleteItem()
160
- },
161
- })
162
-
163
- // 'confirmed' | 'cancelled' | 'dismissed'
164
- if (result !== 'confirmed') return
165
-
166
- // Or boolean helper:
167
- if (!(await confirm.yes({ title: 'Continue?' }))) return
168
- ```
169
-
170
- `ConfirmProvider` is mounted by `ManagerRuntimeApp` / `ManagerBrowserApp`.
171
- `onConfirm` keeps the dialog open with a loading button until the promise
172
- settles; thrown errors leave it open.
173
-
174
- ## Public entrypoints
175
-
176
- - `@rakun-kit/manager-react`: manager apps, providers and common helpers.
177
- - `/client/http`, `/client/request`, `/client/trpc`: manager transports.
178
- - `/app/runtime-app`: runtime/browser app components.
179
- - `/state/navigation`, `/state/theme`, `/link`: host integration primitives.
180
- - `/plugins`, `/rich-text`: plugin and RichText extension contracts.
181
- - `/i18n`: locale runtime, catalog and locale types.
182
- - `confirm` / `useConfirm` / `ConfirmProvider`: shared async confirmation dialogs.
183
- - `/styles.css`: required bundled styles.
184
-
185
- ## Agent constraints
186
-
187
- - This package can run outside Next.js; do not assume Next navigation or server
188
- components.
189
- - Do not import the main React entrypoint into server bootstrap just to obtain
190
- locale types or data.
191
- - Permission-gate protected UI, and handle loading, empty and error states.
192
- - Use existing manager components and operations before adding parallel APIs.
193
- - Keep manager/core schemas synchronized when an operation changes.
194
- - Do not hardcode user-facing manager copy.
146
+ In the SEO tab, `Current document` exposes compatible fields from the complete
147
+ document (including fields edited in Info), while the reserved `_seo` relation
148
+ itself stays excluded as a source. On create forms, string fields configured in
149
+ core with `.seo('<seoField>')` appear as normal preconfigured dynamic bindings;
150
+ editors can replace or clear them before the first save.
151
+
152
+ ## Confirmations
153
+
154
+ Use the shared async confirm API instead of ad-hoc yes/no dialogs:
155
+
156
+ ```tsx
157
+ import { confirm, useConfirm } from '@rakun-kit/manager-react'
158
+
159
+ const result = await confirm({
160
+ title: 'Delete item',
161
+ description: 'This cannot be undone.',
162
+ confirmLabel: 'Delete',
163
+ variant: 'destructive',
164
+ onConfirm: async () => {
165
+ await deleteItem()
166
+ },
167
+ })
168
+
169
+ // 'confirmed' | 'cancelled' | 'dismissed'
170
+ if (result !== 'confirmed') return
171
+
172
+ // Or boolean helper:
173
+ if (!(await confirm.yes({ title: 'Continue?' }))) return
174
+ ```
175
+
176
+ `ConfirmProvider` is mounted by `ManagerRuntimeApp` / `ManagerBrowserApp`.
177
+ `onConfirm` keeps the dialog open with a loading button until the promise
178
+ settles; thrown errors leave it open.
179
+
180
+ ## Public entrypoints
181
+
182
+ - `@rakun-kit/manager-react`: manager apps, providers and common helpers.
183
+ - `/client/http`, `/client/request`, `/client/trpc`: manager transports.
184
+ - `/app/runtime-app`: runtime/browser app components.
185
+ - `/state/navigation`, `/state/theme`, `/link`: host integration primitives.
186
+ - `/plugins`, `/rich-text`: plugin and RichText extension contracts.
187
+ - `/i18n`: locale runtime, catalog and locale types.
188
+ - `confirm` / `useConfirm` / `ConfirmProvider`: shared async confirmation dialogs.
189
+ - `/styles.css`: required bundled styles.
190
+
191
+ ## Agent constraints
192
+
193
+ - This package can run outside Next.js; do not assume Next navigation or server
194
+ components.
195
+ - Do not import the main React entrypoint into server bootstrap just to obtain
196
+ locale types or data.
197
+ - Permission-gate protected UI, and handle loading, empty and error states.
198
+ - Use existing manager components and operations before adding parallel APIs.
199
+ - Keep manager/core schemas synchronized when an operation changes.
200
+ - Do not hardcode user-facing manager copy.
@@ -1,91 +1,91 @@
1
- .EditorTheme__code {
2
- background-color: transparent;
3
- font-family: Menlo, Consolas, Monaco, monospace;
4
- display: block;
5
- padding: 8px 8px 8px 52px;
6
- line-height: 1.53;
7
- font-size: 13px;
8
- margin: 0;
9
- margin-top: 8px;
10
- margin-bottom: 8px;
11
- overflow-x: auto;
12
- border: 1px solid #ccc;
13
- position: relative;
14
- border-radius: 8px;
15
- tab-size: 2;
16
- }
17
- .EditorTheme__code:before {
18
- content: attr(data-gutter);
19
- position: absolute;
20
- background-color: transparent;
21
- border-right: 1px solid #ccc;
22
- left: 0;
23
- top: 0;
24
- padding: 8px;
25
- color: #777;
26
- white-space: pre-wrap;
27
- text-align: right;
28
- min-width: 25px;
29
- }
30
- .EditorTheme__table {
31
- border-collapse: collapse;
32
- border-spacing: 0;
33
- overflow-y: scroll;
34
- overflow-x: scroll;
35
- table-layout: fixed;
36
- width: fit-content;
37
- width: 100%;
38
- margin: 0px 0px 30px 0px;
39
- }
40
- .EditorTheme__tokenComment {
41
- color: slategray;
42
- }
43
- .EditorTheme__tokenPunctuation {
44
- color: #999;
45
- }
46
- .EditorTheme__tokenProperty {
47
- color: #905;
48
- }
49
- .EditorTheme__tokenSelector {
50
- color: #690;
51
- }
52
- .EditorTheme__tokenOperator {
53
- color: #9a6e3a;
54
- }
55
- .EditorTheme__tokenAttr {
56
- color: #07a;
57
- }
58
- .EditorTheme__tokenVariable {
59
- color: #e90;
60
- }
61
- .EditorTheme__tokenFunction {
62
- color: #dd4a68;
63
- }
64
-
65
- .Collapsible__container {
66
- background-color: var(--background);
67
- border: 1px solid #ccc;
68
- border-radius: 0.5rem;
69
- margin-bottom: 0.5rem;
70
- }
71
-
72
- .Collapsible__title{
73
- padding: 0.25rem;
74
- padding-left: 1rem;
75
- position: relative;
76
- font-weight: bold;
77
- outline: none;
78
- cursor: pointer;
79
- list-style-type: disclosure-closed;
80
- list-style-position: inside;
81
- }
82
-
83
- .Collapsible__title p{
84
- display: inline-flex;
85
- }
86
- .Collapsible__title::marker{
87
- color: lightgray;
88
- }
89
- .Collapsible__container[open] >.Collapsible__title {
90
- list-style-type: disclosure-open;
91
- }
1
+ .EditorTheme__code {
2
+ background-color: transparent;
3
+ font-family: Menlo, Consolas, Monaco, monospace;
4
+ display: block;
5
+ padding: 8px 8px 8px 52px;
6
+ line-height: 1.53;
7
+ font-size: 13px;
8
+ margin: 0;
9
+ margin-top: 8px;
10
+ margin-bottom: 8px;
11
+ overflow-x: auto;
12
+ border: 1px solid #ccc;
13
+ position: relative;
14
+ border-radius: 8px;
15
+ tab-size: 2;
16
+ }
17
+ .EditorTheme__code:before {
18
+ content: attr(data-gutter);
19
+ position: absolute;
20
+ background-color: transparent;
21
+ border-right: 1px solid #ccc;
22
+ left: 0;
23
+ top: 0;
24
+ padding: 8px;
25
+ color: #777;
26
+ white-space: pre-wrap;
27
+ text-align: right;
28
+ min-width: 25px;
29
+ }
30
+ .EditorTheme__table {
31
+ border-collapse: collapse;
32
+ border-spacing: 0;
33
+ overflow-y: scroll;
34
+ overflow-x: scroll;
35
+ table-layout: fixed;
36
+ width: fit-content;
37
+ width: 100%;
38
+ margin: 0px 0px 30px 0px;
39
+ }
40
+ .EditorTheme__tokenComment {
41
+ color: slategray;
42
+ }
43
+ .EditorTheme__tokenPunctuation {
44
+ color: #999;
45
+ }
46
+ .EditorTheme__tokenProperty {
47
+ color: #905;
48
+ }
49
+ .EditorTheme__tokenSelector {
50
+ color: #690;
51
+ }
52
+ .EditorTheme__tokenOperator {
53
+ color: #9a6e3a;
54
+ }
55
+ .EditorTheme__tokenAttr {
56
+ color: #07a;
57
+ }
58
+ .EditorTheme__tokenVariable {
59
+ color: #e90;
60
+ }
61
+ .EditorTheme__tokenFunction {
62
+ color: #dd4a68;
63
+ }
64
+
65
+ .Collapsible__container {
66
+ background-color: var(--background);
67
+ border: 1px solid #ccc;
68
+ border-radius: 0.5rem;
69
+ margin-bottom: 0.5rem;
70
+ }
71
+
72
+ .Collapsible__title{
73
+ padding: 0.25rem;
74
+ padding-left: 1rem;
75
+ position: relative;
76
+ font-weight: bold;
77
+ outline: none;
78
+ cursor: pointer;
79
+ list-style-type: disclosure-closed;
80
+ list-style-position: inside;
81
+ }
82
+
83
+ .Collapsible__title p{
84
+ display: inline-flex;
85
+ }
86
+ .Collapsible__title::marker{
87
+ color: lightgray;
88
+ }
89
+ .Collapsible__container[open] >.Collapsible__title {
90
+ list-style-type: disclosure-open;
91
+ }
@@ -127,10 +127,10 @@ function Sortable(props) {
127
127
  },
128
128
  }), [value]);
129
129
  const screenReaderInstructions = React.useMemo(() => ({
130
- draggable: `
131
- To pick up a sortable item, press space or enter.
132
- While dragging, use the ${orientation === "vertical" ? "up and down" : orientation === "horizontal" ? "left and right" : "arrow"} keys to move the item.
133
- Press space or enter again to drop the item in its new position, or press escape to cancel.
130
+ draggable: `
131
+ To pick up a sortable item, press space or enter.
132
+ While dragging, use the ${orientation === "vertical" ? "up and down" : orientation === "horizontal" ? "left and right" : "arrow"} keys to move the item.
133
+ Press space or enter again to drop the item in its new position, or press escape to cancel.
134
134
  `,
135
135
  }), [orientation]);
136
136
  const contextValue = React.useMemo(() => ({
@@ -1 +1 @@
1
- {"version":3,"file":"useTranslations.d.ts","sourceRoot":"","sources":["../../../src/i18n/useTranslations.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe;iJAIqf,CAAC;;CADjhB,CAAA"}
1
+ {"version":3,"file":"useTranslations.d.ts","sourceRoot":"","sources":["../../../src/i18n/useTranslations.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe;iJAI6gB,CAAC;;CADziB,CAAA"}
@@ -9,6 +9,7 @@ type FieldComponentProps = EncodedFieldUnknown & {
9
9
  ref: React.Ref<FieldRef>;
10
10
  collapsible?: boolean;
11
11
  parentContentType?: EncodedContentType;
12
+ initializeSeoBindings?: boolean;
12
13
  };
13
14
  type FieldComponent = (config: FieldComponentProps) => React.ReactElement;
14
15
  export declare const fieldsMap: { [key in FieldType]: FieldComponent; };
@@ -24,6 +25,7 @@ declare const ContentTypeEdit: import("react").ForwardRefExoticComponent<{
24
25
  [key: string]: FieldValue;
25
26
  };
26
27
  parentContentType?: EncodedContentType;
28
+ initializeSeoBindings?: boolean;
27
29
  collapsible?: boolean;
28
30
  hideTitle?: boolean;
29
31
  } & import("react").RefAttributes<ManagerFieldEditorRef>>;
@@ -1 +1 @@
1
- {"version":3,"file":"ContentTypeEdit.d.ts","sourceRoot":"","sources":["../../../../../../src/router/dashboard/[contentType]/[edit]/ContentTypeEdit.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAA2B,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AACzF,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAavE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAsB7C,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,WAAW,CAAA;AAalB,KAAK,mBAAmB,GAAG,mBAAmB,GAAG;IAC/C,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,CAAC,EAAE,UAAU,CAAA;IACxB,0BAA0B,CAAC,EAAE,MAAM,CAAA;IACnC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,iBAAiB,CAAC,EAAE,kBAAkB,CAAA;CACvC,CAAA;AAED,KAAK,cAAc,GAAG,CAAC,MAAM,EAAE,mBAAmB,KAAK,KAAK,CAAC,YAAY,CAAA;AAoEzE,eAAO,MAAM,SAAS,EAYjB,GACF,GAAG,IAAI,SAAS,GAAG,cAAc,GACnC,CAAA;AAED,wBAAgB,YAAY,CAAC,CAAC;;oBAIL,MAAM,UAFM,CAAC,GAAG,IAAI,KAAK,IAAI;EAcrD;AAED,MAAM,MAAM,QAAQ,GAAG,qBAAqB,CAAA;AAwC5C,QAAA,MAAM,eAAe;iBAGJ,kBAAkB;QAC3B,MAAM;kBACI;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAA;KAAE;wBACvB,kBAAkB;kBACxB,OAAO;gBACT,OAAO;yDAuQrB,CAAA;AAEF,eAAe,eAAe,CAAA"}
1
+ {"version":3,"file":"ContentTypeEdit.d.ts","sourceRoot":"","sources":["../../../../../../src/router/dashboard/[contentType]/[edit]/ContentTypeEdit.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAA2B,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AACzF,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAavE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAsB7C,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,WAAW,CAAA;AAclB,KAAK,mBAAmB,GAAG,mBAAmB,GAAG;IAC/C,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,CAAC,EAAE,UAAU,CAAA;IACxB,0BAA0B,CAAC,EAAE,MAAM,CAAA;IACnC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,iBAAiB,CAAC,EAAE,kBAAkB,CAAA;IACtC,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAChC,CAAA;AAED,KAAK,cAAc,GAAG,CAAC,MAAM,EAAE,mBAAmB,KAAK,KAAK,CAAC,YAAY,CAAA;AAoEzE,eAAO,MAAM,SAAS,EAYjB,GACF,GAAG,IAAI,SAAS,GAAG,cAAc,GACnC,CAAA;AAED,wBAAgB,YAAY,CAAC,CAAC;;oBAIL,MAAM,UAFM,CAAC,GAAG,IAAI,KAAK,IAAI;EAcrD;AAED,MAAM,MAAM,QAAQ,GAAG,qBAAqB,CAAA;AAwC5C,QAAA,MAAM,eAAe;iBAGJ,kBAAkB;QAC3B,MAAM;kBACI;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAA;KAAE;wBACvB,kBAAkB;4BACd,OAAO;kBACjB,OAAO;gBACT,OAAO;yDA2QrB,CAAA;AAEF,eAAe,eAAe,CAAA"}
@@ -28,6 +28,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '../../../../components/
28
28
  import { DynamicDataControl, isDynamicFallbackRequired, isDynamicFieldEnabled, } from './_fields/DynamicDataControl.js';
29
29
  import { useManagerPlugins, } from '../../../../plugins.js';
30
30
  import MissingUI from './_fields/Missing.js';
31
+ import { getInitialSeoBindings } from './_fields/seoBindings.js';
31
32
  const REQUIRED_MARK = '*';
32
33
  const defaultDataExtractor = (fieldName, defaultData) => {
33
34
  if (!defaultData) {
@@ -119,7 +120,10 @@ const ContentTypeEdit = forwardRef((props, ref) => {
119
120
  ])), [contentType.fields, props.defaultData]);
120
121
  const [formState, setFormState] = useState(formStateInitialValue);
121
122
  const conditionFieldState = useMemo(() => mergeConditionFieldState(props.defaultData, formState), [formState, props.defaultData]);
122
- const [dynamicBindings, setDynamicBindings] = useState(getDefaultBindings(props.defaultData));
123
+ const [dynamicBindings, setDynamicBindings] = useState(() => getDefaultBindings(props.defaultData) ??
124
+ (props.initializeSeoBindings
125
+ ? getInitialSeoBindings({ contentType, parentContentType: props.parentContentType })
126
+ : undefined));
123
127
  const [dynamicEditorOpen, setDynamicEditorOpen] = useState(null);
124
128
  const allItems = useMemo(() => Object.entries(contentType.fields).filter(([_, fieldValue]) => !(fieldValue.visibility === 'api')), [contentType.fields]);
125
129
  const visibleItems = useMemo(() => allItems.filter(([, fieldValue]) => evaluateFieldCondition(fieldValue.condition, formState)), [allItems, formState]);
@@ -187,7 +191,7 @@ const ContentTypeEdit = forwardRef((props, ref) => {
187
191
  ? dynamicBindings?.lists?.[fieldName]
188
192
  : dynamicBindings?.fields?.[fieldName];
189
193
  const dynamicFallbackPlaceholder = showDynamicData && dynamicBinding ? t('contentEdit.fallbackValue') : undefined;
190
- const field = FieldComponent ? (_jsx(FieldComponent, { id: id + '.' + fieldName, ref: setRef(i), ...fieldValue, isRequired: isDynamicFallbackRequired(fieldValue, dynamicBinding), defaultData: defaultDataExtractor(fieldName, props.defaultData), dynamicFallbackPlaceholder: dynamicFallbackPlaceholder, parentContentType: dynamicSourceContentType })) : (_jsx(MissingUI, { field: fieldValue.config }));
194
+ const field = FieldComponent ? (_jsx(FieldComponent, { id: id + '.' + fieldName, ref: setRef(i), ...fieldValue, isRequired: isDynamicFallbackRequired(fieldValue, dynamicBinding), defaultData: defaultDataExtractor(fieldName, props.defaultData), dynamicFallbackPlaceholder: dynamicFallbackPlaceholder, parentContentType: dynamicSourceContentType, initializeSeoBindings: props.initializeSeoBindings })) : (_jsx(MissingUI, { field: fieldValue.config }));
191
195
  const dynamicOpen = dynamicEditorOpen === fieldName;
192
196
  const setDynamicOpen = (open) => setDynamicEditorOpen(open ? fieldName : null);
193
197
  const dynamicTrigger = showDynamicData ? (_jsx(DynamicDataControl, { contentType: contentType, documentContentType: dynamicSourceContentType, fieldName: fieldName, field: fieldValue, contentTypes: (contentTypesData ?? []), bindings: dynamicBindings, onChange: (bindings) => {