@rakun-kit/manager-react 1.4.8 → 1.4.10
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 +196 -196
- package/dist/cjs/components/editor/themes/editor-theme.css +91 -91
- package/dist/cjs/components/ui/sortable.js +4 -4
- package/dist/cjs/router/dashboard/[contentType]/[edit]/ContentTypeEdit.js +15 -4
- package/dist/cjs/router/dashboard/[contentType]/[edit]/ContentTypeEdit.js.map +1 -1
- package/dist/cjs/router/dashboard/[contentType]/[edit]/_fields/DynamicDataControl.js +3 -1
- package/dist/cjs/router/dashboard/[contentType]/[edit]/_fields/DynamicDataControl.js.map +1 -1
- package/dist/cjs/router/dashboard/[contentType]/[edit]/_fields/ListField/IteratorVisibilityDialog.js +42 -0
- package/dist/cjs/router/dashboard/[contentType]/[edit]/_fields/ListField/IteratorVisibilityDialog.js.map +1 -0
- package/dist/cjs/router/dashboard/[contentType]/[edit]/_fields/ListField/ListUI.js +48 -2
- package/dist/cjs/router/dashboard/[contentType]/[edit]/_fields/ListField/ListUI.js.map +1 -1
- package/dist/cjs/router/dashboard/[contentType]/[edit]/_fields/shared/condition-state.js +6 -1
- package/dist/cjs/router/dashboard/[contentType]/[edit]/_fields/shared/condition-state.js.map +1 -1
- package/dist/cjs/state/theme.js +12 -12
- package/dist/esm/components/editor/themes/editor-theme.css +91 -91
- package/dist/esm/components/ui/sortable.js +4 -4
- package/dist/esm/router/dashboard/[contentType]/[edit]/ContentTypeEdit.d.ts.map +1 -1
- package/dist/esm/router/dashboard/[contentType]/[edit]/ContentTypeEdit.js +17 -6
- package/dist/esm/router/dashboard/[contentType]/[edit]/ContentTypeEdit.js.map +1 -1
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/DynamicDataControl.d.ts +1 -0
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/DynamicDataControl.d.ts.map +1 -1
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/DynamicDataControl.js +1 -0
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/DynamicDataControl.js.map +1 -1
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/ListField/IteratorVisibilityDialog.d.ts +12 -0
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/ListField/IteratorVisibilityDialog.d.ts.map +1 -0
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/ListField/IteratorVisibilityDialog.js +38 -0
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/ListField/IteratorVisibilityDialog.js.map +1 -0
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/ListField/ListUI.d.ts.map +1 -1
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/ListField/ListUI.js +49 -3
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/ListField/ListUI.js.map +1 -1
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/shared/condition-state.d.ts +4 -0
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/shared/condition-state.d.ts.map +1 -1
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/shared/condition-state.js +4 -0
- package/dist/esm/router/dashboard/[contentType]/[edit]/_fields/shared/condition-state.js.map +1 -1
- package/dist/esm/state/theme.js +12 -12
- package/dist/styles.css +7 -7
- package/dist/styles.css.d.ts +3 -3
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +192 -192
package/README.md
CHANGED
|
@@ -1,196 +1,196 @@
|
|
|
1
|
-
# @rakun-kit/manager-react
|
|
2
|
-
|
|
3
|
-
React manager UI and client utilities for Rakun.
|
|
4
|
-
|
|
5
|
-
Most apps use this package through framework adapters such as
|
|
6
|
-
`@rakun-kit/next/manager`, but the runtime components and clients are also
|
|
7
|
-
published for custom integrations.
|
|
8
|
-
|
|
9
|
-
## Browser App
|
|
10
|
-
|
|
11
|
-
Render the manager with a manager client and navigation implementation:
|
|
12
|
-
|
|
13
|
-
```tsx
|
|
14
|
-
import {
|
|
15
|
-
ManagerBrowserApp,
|
|
16
|
-
createHttpManagerClient,
|
|
17
|
-
} from "@rakun-kit/manager-react";
|
|
18
|
-
import "@rakun-kit/manager-react/styles.css";
|
|
19
|
-
|
|
20
|
-
const client = createHttpManagerClient({
|
|
21
|
-
baseUrl: "/api/rakun",
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
export function ManagerPage() {
|
|
25
|
-
return (
|
|
26
|
-
<ManagerBrowserApp
|
|
27
|
-
client={client}
|
|
28
|
-
pathname={window.location.pathname}
|
|
29
|
-
basePath="/backend"
|
|
30
|
-
/>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
`ManagerBrowserApp` creates browser path navigation by default. Use
|
|
36
|
-
`ManagerRuntimeApp` when you need to provide custom navigation.
|
|
37
|
-
|
|
38
|
-
## Clients
|
|
39
|
-
|
|
40
|
-
HTTP client:
|
|
41
|
-
|
|
42
|
-
```ts
|
|
43
|
-
import { createHttpManagerClient } from "@rakun-kit/manager-react/client/http";
|
|
44
|
-
|
|
45
|
-
const client = createHttpManagerClient({
|
|
46
|
-
baseUrl: "/api/rakun",
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const contentTypes = await client.request("manager.contentTypes");
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
tRPC client adapter:
|
|
53
|
-
|
|
54
|
-
```ts
|
|
55
|
-
import { createTrpcManagerClient } from "@rakun-kit/manager-react/client/trpc";
|
|
56
|
-
|
|
57
|
-
const managerClient = createTrpcManagerClient(trpcProxyClient);
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
Custom client:
|
|
61
|
-
|
|
62
|
-
```ts
|
|
63
|
-
import { createManagerClient } from "@rakun-kit/manager-react/client/request";
|
|
64
|
-
|
|
65
|
-
const client = createManagerClient(async (name, input, options) => {
|
|
66
|
-
// call your transport here
|
|
67
|
-
});
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## Navigation
|
|
71
|
-
|
|
72
|
-
Use `createPathManagerNavigation` for router integrations:
|
|
73
|
-
|
|
74
|
-
```ts
|
|
75
|
-
import { createPathManagerNavigation } from "@rakun-kit/manager-react/state/navigation";
|
|
76
|
-
|
|
77
|
-
const navigation = createPathManagerNavigation({
|
|
78
|
-
basePath: "/backend",
|
|
79
|
-
push: (href) => router.push(href),
|
|
80
|
-
replace: (href) => router.replace(href),
|
|
81
|
-
});
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Styles
|
|
85
|
-
|
|
86
|
-
Import the package stylesheet once:
|
|
87
|
-
|
|
88
|
-
```ts
|
|
89
|
-
import "@rakun-kit/manager-react/styles.css";
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## Manager Plugins
|
|
93
|
-
|
|
94
|
-
Manager plugins run inside the normal providers and can add dashboard routes,
|
|
95
|
-
sidebar items, and custom field editors:
|
|
96
|
-
|
|
97
|
-
```tsx
|
|
98
|
-
import {
|
|
99
|
-
defineRakunManagerPlugin,
|
|
100
|
-
ManagerBrowserApp,
|
|
101
|
-
} from '@rakun-kit/manager-react'
|
|
102
|
-
|
|
103
|
-
const analyticsManagerPlugin = defineRakunManagerPlugin({
|
|
104
|
-
id: '@acme/rakun-analytics',
|
|
105
|
-
routes: [{
|
|
106
|
-
id: 'dashboard',
|
|
107
|
-
path: '/analytics',
|
|
108
|
-
component: AnalyticsScreen,
|
|
109
|
-
permissions: ['plugin.analytics.view'],
|
|
110
|
-
}],
|
|
111
|
-
sidebar: [{
|
|
112
|
-
id: 'analytics',
|
|
113
|
-
title: 'Analytics',
|
|
114
|
-
routeId: 'dashboard',
|
|
115
|
-
position: 'primary',
|
|
116
|
-
group: 'Plugins',
|
|
117
|
-
}],
|
|
118
|
-
fieldEditors: {
|
|
119
|
-
'@acme/rakun-analytics.query': QueryEditor,
|
|
120
|
-
},
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
<ManagerBrowserApp plugins={[analyticsManagerPlugin]} {...props} />
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
Use `ManagerFieldEditorProps`, `ManagerFieldEditorRef`, and
|
|
127
|
-
`useManagerFieldValue` from `@rakun-kit/manager-react/plugins` when implementing
|
|
128
|
-
field editors. Next.js applications should import plugin objects inside a
|
|
129
|
-
`'use client'` wrapper around `RakunManagerClientPage`; `RakunManagerPage` accepts
|
|
130
|
-
that wrapper through `managerComponent`.
|
|
131
|
-
|
|
132
|
-
### Extending the RichText editor
|
|
133
|
-
|
|
134
|
-
Manager plugins can register Lexical nodes and React plugins for every
|
|
135
|
-
`RichText` field, including fields rendered inside relations, blocks, and
|
|
136
|
-
modules:
|
|
137
|
-
|
|
138
|
-
```tsx
|
|
139
|
-
'use client'
|
|
140
|
-
|
|
141
|
-
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
|
142
|
-
import {
|
|
143
|
-
defineRakunManagerPlugin,
|
|
144
|
-
type ManagerRichTextPluginProps,
|
|
145
|
-
} from '@rakun-kit/manager-react/plugins'
|
|
146
|
-
import { MentionNode } from './MentionNode'
|
|
147
|
-
|
|
148
|
-
const MentionsPlugin = ({ id }: ManagerRichTextPluginProps) => {
|
|
149
|
-
const [editor] = useLexicalComposerContext()
|
|
150
|
-
|
|
151
|
-
// Register commands and listeners on `editor` here.
|
|
152
|
-
return null
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export const mentionsManagerPlugin = defineRakunManagerPlugin({
|
|
156
|
-
id: '@acme/rakun-mentions',
|
|
157
|
-
richText: {
|
|
158
|
-
nodes: [MentionNode],
|
|
159
|
-
plugins: [
|
|
160
|
-
{
|
|
161
|
-
id: '@acme/rakun-mentions.plugin',
|
|
162
|
-
component: MentionsPlugin,
|
|
163
|
-
placement: 'editor',
|
|
164
|
-
},
|
|
165
|
-
],
|
|
166
|
-
},
|
|
167
|
-
})
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
Lexical plugin components receive `ManagerRichTextPluginProps` (the field id,
|
|
171
|
-
configuration, current content type, and related field metadata) and render
|
|
172
|
-
inside `LexicalComposer`, so they can use the normal Lexical React hooks.
|
|
173
|
-
Supported placements are `toolbar`, `block-format`, `editor` (the default),
|
|
174
|
-
`actions-start`, and `actions-end`. `block-format` components render inside the
|
|
175
|
-
manager's block selector and can use `ManagerRichTextBlockFormatItem` from
|
|
176
|
-
`@rakun-kit/manager-react/rich-text`. Contributions keep declaration order
|
|
177
|
-
unless an explicit `order` is provided. Node types and plugin ids must be unique;
|
|
178
|
-
conflicts report both plugin owners. Node replacements use Lexical's standard
|
|
179
|
-
`LexicalNodeReplacement` configuration.
|
|
180
|
-
|
|
181
|
-
## Exports
|
|
182
|
-
|
|
183
|
-
- `@rakun-kit/manager-react`: manager app, providers, clients, navigation, router, layout, media, and state helpers.
|
|
184
|
-
- `@rakun-kit/manager-react/client/http`: HTTP manager client.
|
|
185
|
-
- `@rakun-kit/manager-react/client/request`: transport-agnostic manager client.
|
|
186
|
-
- `@rakun-kit/manager-react/client/trpc`: tRPC proxy client adapter.
|
|
187
|
-
- `@rakun-kit/manager-react/app/runtime-app`: `ManagerRuntimeApp`, `ManagerBrowserApp`.
|
|
188
|
-
- `@rakun-kit/manager-react/state/navigation`: navigation helpers and provider.
|
|
189
|
-
- `@rakun-kit/manager-react/link`: link component provider.
|
|
190
|
-
- `@rakun-kit/manager-react/styles.css`: bundled manager styles.
|
|
191
|
-
|
|
192
|
-
## Build
|
|
193
|
-
|
|
194
|
-
```sh
|
|
195
|
-
bun run build --workspace @rakun-kit/manager-react
|
|
196
|
-
```
|
|
1
|
+
# @rakun-kit/manager-react
|
|
2
|
+
|
|
3
|
+
React manager UI and client utilities for Rakun.
|
|
4
|
+
|
|
5
|
+
Most apps use this package through framework adapters such as
|
|
6
|
+
`@rakun-kit/next/manager`, but the runtime components and clients are also
|
|
7
|
+
published for custom integrations.
|
|
8
|
+
|
|
9
|
+
## Browser App
|
|
10
|
+
|
|
11
|
+
Render the manager with a manager client and navigation implementation:
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import {
|
|
15
|
+
ManagerBrowserApp,
|
|
16
|
+
createHttpManagerClient,
|
|
17
|
+
} from "@rakun-kit/manager-react";
|
|
18
|
+
import "@rakun-kit/manager-react/styles.css";
|
|
19
|
+
|
|
20
|
+
const client = createHttpManagerClient({
|
|
21
|
+
baseUrl: "/api/rakun",
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export function ManagerPage() {
|
|
25
|
+
return (
|
|
26
|
+
<ManagerBrowserApp
|
|
27
|
+
client={client}
|
|
28
|
+
pathname={window.location.pathname}
|
|
29
|
+
basePath="/backend"
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`ManagerBrowserApp` creates browser path navigation by default. Use
|
|
36
|
+
`ManagerRuntimeApp` when you need to provide custom navigation.
|
|
37
|
+
|
|
38
|
+
## Clients
|
|
39
|
+
|
|
40
|
+
HTTP client:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { createHttpManagerClient } from "@rakun-kit/manager-react/client/http";
|
|
44
|
+
|
|
45
|
+
const client = createHttpManagerClient({
|
|
46
|
+
baseUrl: "/api/rakun",
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const contentTypes = await client.request("manager.contentTypes");
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
tRPC client adapter:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import { createTrpcManagerClient } from "@rakun-kit/manager-react/client/trpc";
|
|
56
|
+
|
|
57
|
+
const managerClient = createTrpcManagerClient(trpcProxyClient);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Custom client:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import { createManagerClient } from "@rakun-kit/manager-react/client/request";
|
|
64
|
+
|
|
65
|
+
const client = createManagerClient(async (name, input, options) => {
|
|
66
|
+
// call your transport here
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Navigation
|
|
71
|
+
|
|
72
|
+
Use `createPathManagerNavigation` for router integrations:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { createPathManagerNavigation } from "@rakun-kit/manager-react/state/navigation";
|
|
76
|
+
|
|
77
|
+
const navigation = createPathManagerNavigation({
|
|
78
|
+
basePath: "/backend",
|
|
79
|
+
push: (href) => router.push(href),
|
|
80
|
+
replace: (href) => router.replace(href),
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Styles
|
|
85
|
+
|
|
86
|
+
Import the package stylesheet once:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import "@rakun-kit/manager-react/styles.css";
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Manager Plugins
|
|
93
|
+
|
|
94
|
+
Manager plugins run inside the normal providers and can add dashboard routes,
|
|
95
|
+
sidebar items, and custom field editors:
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
import {
|
|
99
|
+
defineRakunManagerPlugin,
|
|
100
|
+
ManagerBrowserApp,
|
|
101
|
+
} from '@rakun-kit/manager-react'
|
|
102
|
+
|
|
103
|
+
const analyticsManagerPlugin = defineRakunManagerPlugin({
|
|
104
|
+
id: '@acme/rakun-analytics',
|
|
105
|
+
routes: [{
|
|
106
|
+
id: 'dashboard',
|
|
107
|
+
path: '/analytics',
|
|
108
|
+
component: AnalyticsScreen,
|
|
109
|
+
permissions: ['plugin.analytics.view'],
|
|
110
|
+
}],
|
|
111
|
+
sidebar: [{
|
|
112
|
+
id: 'analytics',
|
|
113
|
+
title: 'Analytics',
|
|
114
|
+
routeId: 'dashboard',
|
|
115
|
+
position: 'primary',
|
|
116
|
+
group: 'Plugins',
|
|
117
|
+
}],
|
|
118
|
+
fieldEditors: {
|
|
119
|
+
'@acme/rakun-analytics.query': QueryEditor,
|
|
120
|
+
},
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
<ManagerBrowserApp plugins={[analyticsManagerPlugin]} {...props} />
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Use `ManagerFieldEditorProps`, `ManagerFieldEditorRef`, and
|
|
127
|
+
`useManagerFieldValue` from `@rakun-kit/manager-react/plugins` when implementing
|
|
128
|
+
field editors. Next.js applications should import plugin objects inside a
|
|
129
|
+
`'use client'` wrapper around `RakunManagerClientPage`; `RakunManagerPage` accepts
|
|
130
|
+
that wrapper through `managerComponent`.
|
|
131
|
+
|
|
132
|
+
### Extending the RichText editor
|
|
133
|
+
|
|
134
|
+
Manager plugins can register Lexical nodes and React plugins for every
|
|
135
|
+
`RichText` field, including fields rendered inside relations, blocks, and
|
|
136
|
+
modules:
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
'use client'
|
|
140
|
+
|
|
141
|
+
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
|
142
|
+
import {
|
|
143
|
+
defineRakunManagerPlugin,
|
|
144
|
+
type ManagerRichTextPluginProps,
|
|
145
|
+
} from '@rakun-kit/manager-react/plugins'
|
|
146
|
+
import { MentionNode } from './MentionNode'
|
|
147
|
+
|
|
148
|
+
const MentionsPlugin = ({ id }: ManagerRichTextPluginProps) => {
|
|
149
|
+
const [editor] = useLexicalComposerContext()
|
|
150
|
+
|
|
151
|
+
// Register commands and listeners on `editor` here.
|
|
152
|
+
return null
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export const mentionsManagerPlugin = defineRakunManagerPlugin({
|
|
156
|
+
id: '@acme/rakun-mentions',
|
|
157
|
+
richText: {
|
|
158
|
+
nodes: [MentionNode],
|
|
159
|
+
plugins: [
|
|
160
|
+
{
|
|
161
|
+
id: '@acme/rakun-mentions.plugin',
|
|
162
|
+
component: MentionsPlugin,
|
|
163
|
+
placement: 'editor',
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
})
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Lexical plugin components receive `ManagerRichTextPluginProps` (the field id,
|
|
171
|
+
configuration, current content type, and related field metadata) and render
|
|
172
|
+
inside `LexicalComposer`, so they can use the normal Lexical React hooks.
|
|
173
|
+
Supported placements are `toolbar`, `block-format`, `editor` (the default),
|
|
174
|
+
`actions-start`, and `actions-end`. `block-format` components render inside the
|
|
175
|
+
manager's block selector and can use `ManagerRichTextBlockFormatItem` from
|
|
176
|
+
`@rakun-kit/manager-react/rich-text`. Contributions keep declaration order
|
|
177
|
+
unless an explicit `order` is provided. Node types and plugin ids must be unique;
|
|
178
|
+
conflicts report both plugin owners. Node replacements use Lexical's standard
|
|
179
|
+
`LexicalNodeReplacement` configuration.
|
|
180
|
+
|
|
181
|
+
## Exports
|
|
182
|
+
|
|
183
|
+
- `@rakun-kit/manager-react`: manager app, providers, clients, navigation, router, layout, media, and state helpers.
|
|
184
|
+
- `@rakun-kit/manager-react/client/http`: HTTP manager client.
|
|
185
|
+
- `@rakun-kit/manager-react/client/request`: transport-agnostic manager client.
|
|
186
|
+
- `@rakun-kit/manager-react/client/trpc`: tRPC proxy client adapter.
|
|
187
|
+
- `@rakun-kit/manager-react/app/runtime-app`: `ManagerRuntimeApp`, `ManagerBrowserApp`.
|
|
188
|
+
- `@rakun-kit/manager-react/state/navigation`: navigation helpers and provider.
|
|
189
|
+
- `@rakun-kit/manager-react/link`: link component provider.
|
|
190
|
+
- `@rakun-kit/manager-react/styles.css`: bundled manager styles.
|
|
191
|
+
|
|
192
|
+
## Build
|
|
193
|
+
|
|
194
|
+
```sh
|
|
195
|
+
bun run build --workspace @rakun-kit/manager-react
|
|
196
|
+
```
|
|
@@ -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
|
+
}
|
|
@@ -167,10 +167,10 @@ function Sortable(props) {
|
|
|
167
167
|
},
|
|
168
168
|
}), [value]);
|
|
169
169
|
const screenReaderInstructions = React.useMemo(() => ({
|
|
170
|
-
draggable: `
|
|
171
|
-
To pick up a sortable item, press space or enter.
|
|
172
|
-
While dragging, use the ${orientation === "vertical" ? "up and down" : orientation === "horizontal" ? "left and right" : "arrow"} keys to move the item.
|
|
173
|
-
Press space or enter again to drop the item in its new position, or press escape to cancel.
|
|
170
|
+
draggable: `
|
|
171
|
+
To pick up a sortable item, press space or enter.
|
|
172
|
+
While dragging, use the ${orientation === "vertical" ? "up and down" : orientation === "horizontal" ? "left and right" : "arrow"} keys to move the item.
|
|
173
|
+
Press space or enter again to drop the item in its new position, or press escape to cancel.
|
|
174
174
|
`,
|
|
175
175
|
}), [orientation]);
|
|
176
176
|
const contextValue = React.useMemo(() => ({
|
|
@@ -97,11 +97,13 @@ const ContentTypeEdit = (0, react_1.forwardRef)((props, ref) => {
|
|
|
97
97
|
const { refs, setRef } = useArrayRefs();
|
|
98
98
|
const errors = (0, app_store_1.useEditErrorStore)((state) => state.errors);
|
|
99
99
|
const addError = (0, app_store_1.useEditErrorStore)((state) => state.addError);
|
|
100
|
+
const removeRelatedErrors = (0, app_store_1.useEditErrorStore)((state) => state.removeRelatedErrors);
|
|
100
101
|
const formStateInitialValue = (0, react_1.useMemo)(() => Object.fromEntries(Object.keys(contentType.fields).map((fieldName) => [
|
|
101
102
|
fieldName,
|
|
102
103
|
defaultDataExtractor(fieldName, props.defaultData),
|
|
103
104
|
])), [contentType.fields, props.defaultData]);
|
|
104
105
|
const [formState, setFormState] = (0, react_1.useState)(formStateInitialValue);
|
|
106
|
+
const conditionFieldState = (0, react_1.useMemo)(() => (0, condition_state_1.mergeConditionFieldState)(props.defaultData, formState), [formState, props.defaultData]);
|
|
105
107
|
const [dynamicBindings, setDynamicBindings] = (0, react_1.useState)(getDefaultBindings(props.defaultData));
|
|
106
108
|
const [dynamicEditorOpen, setDynamicEditorOpen] = (0, react_1.useState)(null);
|
|
107
109
|
const allItems = (0, react_1.useMemo)(() => Object.entries(contentType.fields).filter(([_, fieldValue]) => !(fieldValue.visibility === 'api')), [contentType.fields]);
|
|
@@ -154,7 +156,10 @@ const ContentTypeEdit = (0, react_1.forwardRef)((props, ref) => {
|
|
|
154
156
|
return bindings ? { ...states, _bindings: bindings } : states;
|
|
155
157
|
},
|
|
156
158
|
}), [addError, allItems, contentType.name, dynamicBindings, formState, id, visibleFieldNames]);
|
|
157
|
-
return ((0, jsx_runtime_1.jsx)(condition_state_1.ConditionFieldStateProvider, { value: {
|
|
159
|
+
return ((0, jsx_runtime_1.jsx)(condition_state_1.ConditionFieldStateProvider, { value: {
|
|
160
|
+
fieldState: conditionFieldState,
|
|
161
|
+
onFieldStateChange: handleFieldStateChange,
|
|
162
|
+
}, children: (0, jsx_runtime_1.jsx)("div", { className: "flex flex-1 flex-col gap-8 mx-auto w-full h-full", children: allItems.map(([fieldName, fieldValue], i) => {
|
|
158
163
|
const isVisible = visibleFieldNames.has(fieldName);
|
|
159
164
|
const description = getFieldDescription(fieldValue);
|
|
160
165
|
if (!isVisible) {
|
|
@@ -170,11 +175,17 @@ const ContentTypeEdit = (0, react_1.forwardRef)((props, ref) => {
|
|
|
170
175
|
? dynamicBindings?.lists?.[fieldName]
|
|
171
176
|
: dynamicBindings?.fields?.[fieldName];
|
|
172
177
|
const dynamicFallbackPlaceholder = showDynamicData && dynamicBinding ? 'Fallback value' : undefined;
|
|
173
|
-
const field = FieldComponent ? ((0, jsx_runtime_1.jsx)(FieldComponent, { id: id + '.' + fieldName, ref: setRef(i), ...fieldValue, defaultData: defaultDataExtractor(fieldName, props.defaultData), dynamicFallbackPlaceholder: dynamicFallbackPlaceholder, parentContentType: dynamicSourceContentType })) : ((0, jsx_runtime_1.jsx)(Missing_1.default, { field: fieldValue.config }));
|
|
178
|
+
const field = FieldComponent ? ((0, jsx_runtime_1.jsx)(FieldComponent, { id: id + '.' + fieldName, ref: setRef(i), ...fieldValue, isRequired: (0, DynamicDataControl_1.isDynamicFallbackRequired)(fieldValue, dynamicBinding), defaultData: defaultDataExtractor(fieldName, props.defaultData), dynamicFallbackPlaceholder: dynamicFallbackPlaceholder, parentContentType: dynamicSourceContentType })) : ((0, jsx_runtime_1.jsx)(Missing_1.default, { field: fieldValue.config }));
|
|
174
179
|
const dynamicOpen = dynamicEditorOpen === fieldName;
|
|
175
180
|
const setDynamicOpen = (open) => setDynamicEditorOpen(open ? fieldName : null);
|
|
176
|
-
const dynamicTrigger = showDynamicData ? ((0, jsx_runtime_1.jsx)(DynamicDataControl_1.DynamicDataControl, { contentType: contentType, documentContentType: dynamicSourceContentType, fieldName: fieldName, field: fieldValue, contentTypes: (contentTypesData ?? []), bindings: dynamicBindings, onChange:
|
|
177
|
-
|
|
181
|
+
const dynamicTrigger = showDynamicData ? ((0, jsx_runtime_1.jsx)(DynamicDataControl_1.DynamicDataControl, { contentType: contentType, documentContentType: dynamicSourceContentType, fieldName: fieldName, field: fieldValue, contentTypes: (contentTypesData ?? []), bindings: dynamicBindings, onChange: (bindings) => {
|
|
182
|
+
setDynamicBindings(bindings);
|
|
183
|
+
removeRelatedErrors(`${id}.${fieldName}`);
|
|
184
|
+
}, open: dynamicOpen, onOpenChange: setDynamicOpen, mode: "trigger" })) : null;
|
|
185
|
+
const dynamicDialog = showDynamicData ? ((0, jsx_runtime_1.jsx)(DynamicDataControl_1.DynamicDataControl, { contentType: contentType, documentContentType: dynamicSourceContentType, fieldName: fieldName, field: fieldValue, contentTypes: (contentTypesData ?? []), bindings: dynamicBindings, onChange: (bindings) => {
|
|
186
|
+
setDynamicBindings(bindings);
|
|
187
|
+
removeRelatedErrors(`${id}.${fieldName}`);
|
|
188
|
+
}, open: dynamicOpen, onOpenChange: setDynamicOpen, mode: "dialog" })) : null;
|
|
178
189
|
const Tags = ({ children }) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex min-w-0 shrink-0 items-center gap-2", children: [children, fieldValue.isTranslatable ? ((0, jsx_runtime_1.jsx)(FieldMetaIcon, { label: "Translatable field", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Languages, { "aria-hidden": "true", size: 16 }) })) : null, fieldValue.isRequired ? ((0, jsx_runtime_1.jsx)(FieldMetaIcon, { label: "Required field", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Shield, { "aria-hidden": "true", size: 16 }) })) : null] }));
|
|
179
190
|
const canCollapse = fieldValue.config.ui === 'ContentType' &&
|
|
180
191
|
fieldValue.only === 'new' &&
|