@akinon/ui-shell-dev 1.3.5 → 1.4.0
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/dist/assets/index-CX4XmW02.css +1 -0
- package/dist/assets/index-D6a6pO8M.js +434 -0
- package/dist/assets/index-kkeQGnUJ.js +1 -0
- package/dist/favicon.svg +3 -0
- package/dist/index.html +2 -2
- package/index.mjs +1 -1
- package/package.json +15 -16
- package/public/favicon.svg +3 -0
- package/src/components/Header.tsx +1 -1
- package/src/components/HeaderSearch.tsx +1 -1
- package/src/components/HeaderUser.tsx +9 -2
- package/src/components/Navigation.tsx +7 -5
- package/src/components/PageHeading.tsx +4 -8
- package/src/components/PluginTestPage.tsx +5 -9
- package/src/components/WelcomePage.tsx +415 -71
- package/src/main.tsx +8 -6
- package/src/providers.tsx +14 -13
- package/src/routes.tsx +19 -18
- package/src/server/dev-server.mjs +34 -13
- package/src/server/dev-server.ts +34 -13
- package/src/types.ts +6 -4
- package/src/utils/navigation.tsx +42 -13
- package/dist/assets/index-BFs1gfY5.css +0 -1
- package/dist/assets/index-CDUI6TEB.js +0 -408
|
@@ -1,86 +1,145 @@
|
|
|
1
1
|
import { useAppShell } from '@akinon/app-shell';
|
|
2
|
-
import {
|
|
2
|
+
import { Card, Divider, Tag } from '@akinon/ui-react';
|
|
3
3
|
import React from 'react';
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
import { ShellConfig } from '@/types';
|
|
6
|
+
|
|
7
|
+
// Component to display shared data from shell config
|
|
8
|
+
const SharedDataDisplay: React.FC<{ data: Record<string, unknown> }> = ({
|
|
9
|
+
data
|
|
10
|
+
}) => {
|
|
11
|
+
// Filter out default fields to show only custom data from config
|
|
12
|
+
const customData = { ...data };
|
|
13
|
+
delete customData.lng;
|
|
14
|
+
delete customData.username;
|
|
15
|
+
delete customData.searchParams;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<pre
|
|
19
|
+
style={{
|
|
20
|
+
backgroundColor: '#1e1e1e',
|
|
21
|
+
color: '#d4d4d4',
|
|
22
|
+
padding: '16px',
|
|
23
|
+
borderRadius: '6px',
|
|
24
|
+
border: '1px solid #424b6b',
|
|
25
|
+
fontSize: '13px',
|
|
26
|
+
fontFamily:
|
|
27
|
+
'"SF Mono", "Monaco", "Inconsolata", "Roboto Mono", "Source Code Pro", monospace',
|
|
28
|
+
lineHeight: '1.5',
|
|
29
|
+
overflow: 'auto',
|
|
30
|
+
margin: 0,
|
|
31
|
+
whiteSpace: 'pre-wrap',
|
|
32
|
+
wordBreak: 'break-word'
|
|
33
|
+
}}
|
|
34
|
+
>
|
|
35
|
+
{Object.keys(customData).length > 0
|
|
36
|
+
? JSON.stringify(customData, null, 2)
|
|
37
|
+
: '// No custom data configured in shell.config.js\n// Add data to the "data" field to share it with your application'}
|
|
38
|
+
</pre>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
5
41
|
|
|
6
42
|
export const WelcomePage: React.FC = () => {
|
|
7
|
-
const navigate = useNavigate();
|
|
8
43
|
const { apps } = useAppShell();
|
|
9
|
-
|
|
44
|
+
|
|
45
|
+
const config: ShellConfig =
|
|
46
|
+
((window as unknown as { __SHELL_CONFIG__?: ShellConfig })
|
|
47
|
+
.__SHELL_CONFIG__ as ShellConfig) || {};
|
|
48
|
+
const data = config.data;
|
|
10
49
|
|
|
11
50
|
return (
|
|
12
51
|
<div>
|
|
13
|
-
<Card title="
|
|
14
|
-
|
|
15
|
-
style={{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
gap: '
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
<Card title="Applications Configuration" className="mb-8">
|
|
53
|
+
{apps.length === 0 ? (
|
|
54
|
+
<p style={{ color: '#999' }}>No applications configured</p>
|
|
55
|
+
) : (
|
|
56
|
+
<div
|
|
57
|
+
style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}
|
|
58
|
+
>
|
|
59
|
+
{apps.map((app, index) => (
|
|
60
|
+
<div
|
|
61
|
+
key={app.id}
|
|
62
|
+
style={{
|
|
63
|
+
borderBottom:
|
|
64
|
+
index < apps.length - 1 ? '1px solid #e0e0e0' : 'none',
|
|
65
|
+
paddingBottom: index < apps.length - 1 ? '20px' : '0'
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
<h4 style={{ margin: '0 0 16px 0' }}>
|
|
69
|
+
{app.name} {apps.length > 1 && `(App ${index + 1})`}
|
|
70
|
+
</h4>
|
|
71
|
+
<div
|
|
72
|
+
style={{
|
|
73
|
+
display: 'grid',
|
|
74
|
+
gridTemplateColumns: '1fr 1fr',
|
|
75
|
+
gap: '16px'
|
|
76
|
+
}}
|
|
77
|
+
>
|
|
78
|
+
<div>
|
|
79
|
+
<strong>Application Type:</strong>
|
|
80
|
+
<p style={{ margin: '12px 0 4px 0' }}>
|
|
81
|
+
<Tag color={app.type === 'full_page' ? 'blue' : 'green'}>
|
|
82
|
+
{app.type === 'full_page' ? 'Full Page' : 'Plugin'}
|
|
83
|
+
</Tag>
|
|
84
|
+
</p>
|
|
85
|
+
</div>
|
|
86
|
+
<div>
|
|
87
|
+
<strong>Development URL:</strong>
|
|
88
|
+
<p
|
|
89
|
+
style={{
|
|
90
|
+
margin: '12px 0 4px 0',
|
|
91
|
+
color: '#999',
|
|
92
|
+
fontFamily: 'monospace',
|
|
93
|
+
fontSize: '13px'
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
{app.url}
|
|
97
|
+
</p>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
))}
|
|
102
|
+
<div style={{ marginTop: '10px' }}>
|
|
103
|
+
<strong>Shell Theme:</strong>
|
|
104
|
+
<p style={{ margin: '12px 0 4px 0', color: '#999' }}>
|
|
105
|
+
{config?.shell?.theme}
|
|
106
|
+
</p>
|
|
107
|
+
</div>
|
|
51
108
|
</div>
|
|
52
|
-
|
|
109
|
+
)}
|
|
53
110
|
</Card>
|
|
54
111
|
|
|
55
|
-
<Card title="
|
|
56
|
-
<
|
|
57
|
-
<Button
|
|
58
|
-
type="primary"
|
|
59
|
-
onClick={() => navigate(`/external/${app?.slug}`)}
|
|
60
|
-
>
|
|
61
|
-
Launch Application
|
|
62
|
-
</Button>
|
|
63
|
-
{app?.type === 'plugin' && (
|
|
64
|
-
<Button onClick={() => navigate('/plugin-test')}>
|
|
65
|
-
Test Plugin Integration
|
|
66
|
-
</Button>
|
|
67
|
-
)}
|
|
68
|
-
</div>
|
|
112
|
+
<Card title="Shared Data" className="mb-8">
|
|
113
|
+
{data && <SharedDataDisplay data={data} />}
|
|
69
114
|
</Card>
|
|
70
115
|
|
|
71
|
-
<Card title="Development Instructions">
|
|
116
|
+
<Card title="Development Instructions" className="mb-8">
|
|
72
117
|
<div style={{ lineHeight: '1.6' }}>
|
|
73
118
|
<h4 style={{ margin: '0 0 8px 0' }}>Getting Started:</h4>
|
|
74
119
|
<ol style={{ paddingLeft: '20px' }}>
|
|
75
120
|
<li>
|
|
76
|
-
Make sure your application
|
|
77
|
-
|
|
121
|
+
Make sure your application{apps.length > 1 ? 's are' : ' is'}{' '}
|
|
122
|
+
running at{' '}
|
|
123
|
+
<code>
|
|
124
|
+
{apps.length > 0 ? apps[0].url : 'http://localhost:4001'}
|
|
125
|
+
</code>
|
|
126
|
+
{apps.length > 1 && (
|
|
127
|
+
<>
|
|
128
|
+
{' and '}
|
|
129
|
+
{apps.slice(1).map((a, i) => (
|
|
130
|
+
<span key={a.id}>
|
|
131
|
+
{i > 0 && ', '}
|
|
132
|
+
<code>{a.url}</code>
|
|
133
|
+
</span>
|
|
134
|
+
))}
|
|
135
|
+
</>
|
|
136
|
+
)}
|
|
78
137
|
</li>
|
|
79
138
|
<li>
|
|
80
139
|
Click "Launch Application" to load your app in the shell
|
|
81
140
|
environment
|
|
82
141
|
</li>
|
|
83
|
-
{
|
|
142
|
+
{apps.some(a => a.type === 'plugin') && (
|
|
84
143
|
<li>
|
|
85
144
|
Use "Test Plugin Integration" to test your plugin in
|
|
86
145
|
different placeholder configurations
|
|
@@ -94,24 +153,309 @@ export const WelcomePage: React.FC = () => {
|
|
|
94
153
|
<Divider />
|
|
95
154
|
|
|
96
155
|
<h4 style={{ margin: '16px 0 8px 0' }}>
|
|
97
|
-
Application
|
|
98
|
-
{
|
|
156
|
+
Application Types:{' '}
|
|
157
|
+
{apps.map((a, i) => (
|
|
158
|
+
<span key={a.id}>
|
|
159
|
+
{i > 0 && ', '}
|
|
160
|
+
{a.type === 'full_page' ? 'Full Page' : 'Plugin'}
|
|
161
|
+
</span>
|
|
162
|
+
))}
|
|
99
163
|
</h4>
|
|
100
|
-
{
|
|
164
|
+
{apps.some(a => a.type === 'full_page') && (
|
|
101
165
|
<p style={{ margin: 0, color: '#666' }}>
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
166
|
+
Full page applications render as complete pages within the shell
|
|
167
|
+
environment, providing full control over the content area and
|
|
168
|
+
routing.
|
|
105
169
|
</p>
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
170
|
+
)}
|
|
171
|
+
{apps.some(a => a.type === 'plugin') && (
|
|
172
|
+
<p style={{ margin: '8px 0 0 0', color: '#666' }}>
|
|
173
|
+
Plugin applications render within designated placeholders in the
|
|
174
|
+
host application, providing component-level integration
|
|
110
175
|
capabilities.
|
|
111
176
|
</p>
|
|
112
177
|
)}
|
|
113
178
|
</div>
|
|
114
179
|
</Card>
|
|
180
|
+
|
|
181
|
+
<Card title="Component Usage">
|
|
182
|
+
<div style={{ lineHeight: '1.6' }}>
|
|
183
|
+
<h4 style={{ margin: '0 0 8px 0' }}>@akinon/ui-* Components:</h4>
|
|
184
|
+
<p style={{ margin: '0 0 16px 0', color: '#999' }}>
|
|
185
|
+
This shell environment includes all Akinon UI components. You can
|
|
186
|
+
use them in your application by importing from the respective
|
|
187
|
+
packages.
|
|
188
|
+
</p>
|
|
189
|
+
|
|
190
|
+
<pre
|
|
191
|
+
style={{
|
|
192
|
+
backgroundColor: '#1e1e1e',
|
|
193
|
+
color: '#d4d4d4',
|
|
194
|
+
padding: '16px',
|
|
195
|
+
borderRadius: '6px',
|
|
196
|
+
border: '1px solid #424b6b',
|
|
197
|
+
fontSize: '13px',
|
|
198
|
+
fontFamily:
|
|
199
|
+
'"SF Mono", "Monaco", "Inconsolata", "Roboto Mono", "Source Code Pro", monospace',
|
|
200
|
+
lineHeight: '1.5',
|
|
201
|
+
overflow: 'auto',
|
|
202
|
+
margin: 0,
|
|
203
|
+
whiteSpace: 'pre-wrap',
|
|
204
|
+
wordBreak: 'break-word'
|
|
205
|
+
}}
|
|
206
|
+
>
|
|
207
|
+
{`// Import components from @akinon/ui-react (main package)
|
|
208
|
+
import { Button, Card, Input, Modal } from '@akinon/ui-react';
|
|
209
|
+
|
|
210
|
+
// Or import from specific packages
|
|
211
|
+
import { Button } from '@akinon/ui-button';
|
|
212
|
+
import { Card } from '@akinon/ui-card';
|
|
213
|
+
import { Input } from '@akinon/ui-input';
|
|
214
|
+
import { Modal } from '@akinon/ui-modal';
|
|
215
|
+
|
|
216
|
+
// Usage in your component
|
|
217
|
+
function MyComponent() {
|
|
218
|
+
return (
|
|
219
|
+
<Card title="Example Card">
|
|
220
|
+
<Input placeholder="Enter text here" />
|
|
221
|
+
<Button type="primary">Submit</Button>
|
|
222
|
+
</Card>
|
|
223
|
+
);
|
|
224
|
+
}`}
|
|
225
|
+
</pre>
|
|
226
|
+
|
|
227
|
+
<h3 style={{ margin: '16px 0 8px 0' }}>Available Components:</h3>
|
|
228
|
+
|
|
229
|
+
<h4 style={{ margin: '24px 0 12px 0', fontSize: '16px' }}>
|
|
230
|
+
Data Display
|
|
231
|
+
</h4>
|
|
232
|
+
<div style={{ marginBottom: '20px' }}>
|
|
233
|
+
{[
|
|
234
|
+
{ name: 'Avatar', pkg: '@akinon/ui-avatar' },
|
|
235
|
+
{ name: 'Badge', pkg: '@akinon/ui-badge' },
|
|
236
|
+
{ name: 'Carousel', pkg: '@akinon/ui-carousel' },
|
|
237
|
+
{ name: 'Image', pkg: '@akinon/ui-image' },
|
|
238
|
+
{ name: 'List', pkg: '@akinon/ui-list' },
|
|
239
|
+
{ name: 'Popover', pkg: '@akinon/ui-popover' },
|
|
240
|
+
{ name: 'Table', pkg: '@akinon/ui-table' },
|
|
241
|
+
{ name: 'Tag', pkg: '@akinon/ui-tag' },
|
|
242
|
+
{ name: 'Tooltip', pkg: '@akinon/ui-tooltip' },
|
|
243
|
+
{ name: 'Tree', pkg: '@akinon/ui-tree' },
|
|
244
|
+
{ name: 'Typography', pkg: '@akinon/ui-typography' }
|
|
245
|
+
].map((component, index, array) => (
|
|
246
|
+
<div
|
|
247
|
+
key={component.name}
|
|
248
|
+
style={{
|
|
249
|
+
display: 'flex',
|
|
250
|
+
justifyContent: 'space-between',
|
|
251
|
+
alignItems: 'center',
|
|
252
|
+
padding: '8px 0',
|
|
253
|
+
borderBottom:
|
|
254
|
+
index < array.length - 1 ? '1px solid #4c5679' : 'none'
|
|
255
|
+
}}
|
|
256
|
+
>
|
|
257
|
+
<span>{component.name}</span>
|
|
258
|
+
<code
|
|
259
|
+
style={{
|
|
260
|
+
backgroundColor: '#1e1e1e',
|
|
261
|
+
color: '#d4d4d4',
|
|
262
|
+
padding: '4px 8px',
|
|
263
|
+
borderRadius: '4px',
|
|
264
|
+
border: '1px solid #424b6b',
|
|
265
|
+
fontSize: '12px',
|
|
266
|
+
fontFamily:
|
|
267
|
+
'"SF Mono", "Monaco", "Inconsolata", "Roboto Mono", "Source Code Pro", monospace'
|
|
268
|
+
}}
|
|
269
|
+
>
|
|
270
|
+
{component.pkg}
|
|
271
|
+
</code>
|
|
272
|
+
</div>
|
|
273
|
+
))}
|
|
274
|
+
</div>
|
|
275
|
+
|
|
276
|
+
<h4 style={{ margin: '24px 0 12px 0', fontSize: '16px' }}>
|
|
277
|
+
Feedback
|
|
278
|
+
</h4>
|
|
279
|
+
<div style={{ marginBottom: '20px' }}>
|
|
280
|
+
{[
|
|
281
|
+
{ name: 'Alert', pkg: '@akinon/ui-alert' },
|
|
282
|
+
{ name: 'Drawer', pkg: '@akinon/ui-drawer' },
|
|
283
|
+
{ name: 'Message', pkg: '@akinon/ui-message' },
|
|
284
|
+
{ name: 'Modal', pkg: '@akinon/ui-modal' },
|
|
285
|
+
{ name: 'Notification', pkg: '@akinon/ui-notification' },
|
|
286
|
+
{ name: 'Progress', pkg: '@akinon/ui-progress' },
|
|
287
|
+
{ name: 'Result', pkg: '@akinon/ui-result' },
|
|
288
|
+
{ name: 'Skeleton', pkg: '@akinon/ui-skeleton' },
|
|
289
|
+
{ name: 'Spin', pkg: '@akinon/ui-spin' }
|
|
290
|
+
].map((component, index, array) => (
|
|
291
|
+
<div
|
|
292
|
+
key={component.name}
|
|
293
|
+
style={{
|
|
294
|
+
display: 'flex',
|
|
295
|
+
justifyContent: 'space-between',
|
|
296
|
+
alignItems: 'center',
|
|
297
|
+
padding: '8px 0',
|
|
298
|
+
borderBottom:
|
|
299
|
+
index < array.length - 1 ? '1px solid #4c5679' : 'none'
|
|
300
|
+
}}
|
|
301
|
+
>
|
|
302
|
+
<span>{component.name}</span>
|
|
303
|
+
<code
|
|
304
|
+
style={{
|
|
305
|
+
backgroundColor: '#1e1e1e',
|
|
306
|
+
color: '#d4d4d4',
|
|
307
|
+
padding: '4px 8px',
|
|
308
|
+
borderRadius: '4px',
|
|
309
|
+
border: '1px solid #424b6b',
|
|
310
|
+
fontSize: '12px',
|
|
311
|
+
fontFamily:
|
|
312
|
+
'"SF Mono", "Monaco", "Inconsolata", "Roboto Mono", "Source Code Pro", monospace'
|
|
313
|
+
}}
|
|
314
|
+
>
|
|
315
|
+
{component.pkg}
|
|
316
|
+
</code>
|
|
317
|
+
</div>
|
|
318
|
+
))}
|
|
319
|
+
</div>
|
|
320
|
+
|
|
321
|
+
<h4 style={{ margin: '24px 0 12px 0', fontSize: '16px' }}>Form</h4>
|
|
322
|
+
<div style={{ marginBottom: '20px' }}>
|
|
323
|
+
{[
|
|
324
|
+
{ name: 'AutoComplete', pkg: '@akinon/ui-auto-complete' },
|
|
325
|
+
{ name: 'Button', pkg: '@akinon/ui-button' },
|
|
326
|
+
{ name: 'Checkbox', pkg: '@akinon/ui-checkbox' },
|
|
327
|
+
{ name: 'ColorPicker', pkg: '@akinon/ui-color-picker' },
|
|
328
|
+
{ name: 'DatePicker', pkg: '@akinon/ui-date-picker' },
|
|
329
|
+
{ name: 'Input', pkg: '@akinon/ui-input' },
|
|
330
|
+
{ name: 'InputNumber', pkg: '@akinon/ui-input-number' },
|
|
331
|
+
{ name: 'Radio', pkg: '@akinon/ui-radio' },
|
|
332
|
+
{ name: 'Select', pkg: '@akinon/ui-select' },
|
|
333
|
+
{ name: 'Slider', pkg: '@akinon/ui-slider' },
|
|
334
|
+
{ name: 'Switch', pkg: '@akinon/ui-switch' },
|
|
335
|
+
{ name: 'TimePicker', pkg: '@akinon/ui-time-picker' },
|
|
336
|
+
{ name: 'Transfer', pkg: '@akinon/ui-transfer' },
|
|
337
|
+
{ name: 'TreeSelect', pkg: '@akinon/ui-tree-select' },
|
|
338
|
+
{ name: 'Upload', pkg: '@akinon/ui-upload' }
|
|
339
|
+
].map((component, index, array) => (
|
|
340
|
+
<div
|
|
341
|
+
key={component.name}
|
|
342
|
+
style={{
|
|
343
|
+
display: 'flex',
|
|
344
|
+
justifyContent: 'space-between',
|
|
345
|
+
alignItems: 'center',
|
|
346
|
+
padding: '8px 0',
|
|
347
|
+
borderBottom:
|
|
348
|
+
index < array.length - 1 ? '1px solid #4c5679' : 'none'
|
|
349
|
+
}}
|
|
350
|
+
>
|
|
351
|
+
<span>{component.name}</span>
|
|
352
|
+
<code
|
|
353
|
+
style={{
|
|
354
|
+
backgroundColor: '#1e1e1e',
|
|
355
|
+
color: '#d4d4d4',
|
|
356
|
+
padding: '4px 8px',
|
|
357
|
+
borderRadius: '4px',
|
|
358
|
+
border: '1px solid #424b6b',
|
|
359
|
+
fontSize: '12px',
|
|
360
|
+
fontFamily:
|
|
361
|
+
'"SF Mono", "Monaco", "Inconsolata", "Roboto Mono", "Source Code Pro", monospace'
|
|
362
|
+
}}
|
|
363
|
+
>
|
|
364
|
+
{component.pkg}
|
|
365
|
+
</code>
|
|
366
|
+
</div>
|
|
367
|
+
))}
|
|
368
|
+
</div>
|
|
369
|
+
|
|
370
|
+
<h4 style={{ margin: '24px 0 12px 0', fontSize: '16px' }}>Layout</h4>
|
|
371
|
+
<div style={{ marginBottom: '20px' }}>
|
|
372
|
+
{[
|
|
373
|
+
{ name: 'Card', pkg: '@akinon/ui-card' },
|
|
374
|
+
{ name: 'Collapse', pkg: '@akinon/ui-collapse' },
|
|
375
|
+
{ name: 'Divider', pkg: '@akinon/ui-divider' },
|
|
376
|
+
{ name: 'Layout', pkg: '@akinon/ui-layout' },
|
|
377
|
+
{ name: 'Space', pkg: '@akinon/ui-space' }
|
|
378
|
+
].map((component, index, array) => (
|
|
379
|
+
<div
|
|
380
|
+
key={component.name}
|
|
381
|
+
style={{
|
|
382
|
+
display: 'flex',
|
|
383
|
+
justifyContent: 'space-between',
|
|
384
|
+
alignItems: 'center',
|
|
385
|
+
padding: '8px 0',
|
|
386
|
+
borderBottom:
|
|
387
|
+
index < array.length - 1 ? '1px solid #4c5679' : 'none'
|
|
388
|
+
}}
|
|
389
|
+
>
|
|
390
|
+
<span>{component.name}</span>
|
|
391
|
+
<code
|
|
392
|
+
style={{
|
|
393
|
+
backgroundColor: '#1e1e1e',
|
|
394
|
+
color: '#d4d4d4',
|
|
395
|
+
padding: '4px 8px',
|
|
396
|
+
borderRadius: '4px',
|
|
397
|
+
border: '1px solid #424b6b',
|
|
398
|
+
fontSize: '12px',
|
|
399
|
+
fontFamily:
|
|
400
|
+
'"SF Mono", "Monaco", "Inconsolata", "Roboto Mono", "Source Code Pro", monospace'
|
|
401
|
+
}}
|
|
402
|
+
>
|
|
403
|
+
{component.pkg}
|
|
404
|
+
</code>
|
|
405
|
+
</div>
|
|
406
|
+
))}
|
|
407
|
+
</div>
|
|
408
|
+
|
|
409
|
+
<h4 style={{ margin: '24px 0 12px 0', fontSize: '16px' }}>
|
|
410
|
+
Navigation
|
|
411
|
+
</h4>
|
|
412
|
+
<div style={{ marginBottom: '20px' }}>
|
|
413
|
+
{[
|
|
414
|
+
{ name: 'Breadcrumb', pkg: '@akinon/ui-breadcrumb' },
|
|
415
|
+
{ name: 'Dropdown', pkg: '@akinon/ui-dropdown' },
|
|
416
|
+
{ name: 'Menu', pkg: '@akinon/ui-menu' },
|
|
417
|
+
{ name: 'Pagination', pkg: '@akinon/ui-pagination' },
|
|
418
|
+
{ name: 'Segmented', pkg: '@akinon/ui-segmented' },
|
|
419
|
+
{ name: 'Steps', pkg: '@akinon/ui-steps' },
|
|
420
|
+
{ name: 'Tour', pkg: '@akinon/ui-tour' }
|
|
421
|
+
].map((component, index, array) => (
|
|
422
|
+
<div
|
|
423
|
+
key={component.name}
|
|
424
|
+
style={{
|
|
425
|
+
display: 'flex',
|
|
426
|
+
justifyContent: 'space-between',
|
|
427
|
+
alignItems: 'center',
|
|
428
|
+
padding: '8px 0',
|
|
429
|
+
borderBottom:
|
|
430
|
+
index < array.length - 1 ? '1px solid #4c5679' : 'none'
|
|
431
|
+
}}
|
|
432
|
+
>
|
|
433
|
+
<span>{component.name}</span>
|
|
434
|
+
<code
|
|
435
|
+
style={{
|
|
436
|
+
backgroundColor: '#1e1e1e',
|
|
437
|
+
color: '#d4d4d4',
|
|
438
|
+
padding: '4px 8px',
|
|
439
|
+
borderRadius: '4px',
|
|
440
|
+
border: '1px solid #424b6b',
|
|
441
|
+
fontSize: '12px',
|
|
442
|
+
fontFamily:
|
|
443
|
+
'"SF Mono", "Monaco", "Inconsolata", "Roboto Mono", "Source Code Pro", monospace'
|
|
444
|
+
}}
|
|
445
|
+
>
|
|
446
|
+
{component.pkg}
|
|
447
|
+
</code>
|
|
448
|
+
</div>
|
|
449
|
+
))}
|
|
450
|
+
</div>
|
|
451
|
+
|
|
452
|
+
<p style={{ margin: '0', color: '#999', fontSize: '14px' }}>
|
|
453
|
+
<strong>Note:</strong> All components follow Ant Design API
|
|
454
|
+
conventions with Akinon-specific styling and theming. Check the
|
|
455
|
+
Storybook documentation for detailed usage examples and props.
|
|
456
|
+
</p>
|
|
457
|
+
</div>
|
|
458
|
+
</Card>
|
|
115
459
|
</div>
|
|
116
460
|
);
|
|
117
461
|
};
|
package/src/main.tsx
CHANGED
|
@@ -12,12 +12,14 @@ import type { ShellConfig } from './types';
|
|
|
12
12
|
const config: ShellConfig = (
|
|
13
13
|
window as unknown as { __SHELL_CONFIG__?: ShellConfig }
|
|
14
14
|
).__SHELL_CONFIG__ || {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
apps: [
|
|
16
|
+
{
|
|
17
|
+
url: 'http://localhost:4001',
|
|
18
|
+
path: './src',
|
|
19
|
+
name: 'Development App',
|
|
20
|
+
type: 'full_page'
|
|
21
|
+
}
|
|
22
|
+
],
|
|
21
23
|
shell: {
|
|
22
24
|
port: 4000,
|
|
23
25
|
theme: 'omnitron',
|
package/src/providers.tsx
CHANGED
|
@@ -17,19 +17,17 @@ export const Providers: React.FC<ProvidersProps> = ({ config, children }) => {
|
|
|
17
17
|
const navigate = useNavigate();
|
|
18
18
|
|
|
19
19
|
// Convert shell config to apps format for AppShellProvider
|
|
20
|
-
const apps: RegisteredApp[] =
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
];
|
|
20
|
+
const apps: RegisteredApp[] = config.apps.map((app, index) => ({
|
|
21
|
+
id: index + 1,
|
|
22
|
+
url: app.url,
|
|
23
|
+
slug: app.name.toLowerCase().replace(/\s+/g, '-'),
|
|
24
|
+
path: '', // Empty path for development like playground
|
|
25
|
+
type: app.type,
|
|
26
|
+
name: app.navTitle || app.name // Use navTitle if provided, otherwise use name
|
|
27
|
+
}));
|
|
30
28
|
|
|
31
29
|
const navigation: ShellNavigation = {
|
|
32
|
-
navigate: ({ id, path, external }
|
|
30
|
+
navigate: ({ id, path, external }) => {
|
|
33
31
|
const app = apps.find(app => app.id === id);
|
|
34
32
|
if (!app) return;
|
|
35
33
|
|
|
@@ -41,7 +39,8 @@ export const Providers: React.FC<ProvidersProps> = ({ config, children }) => {
|
|
|
41
39
|
const data = {
|
|
42
40
|
lng: 'en',
|
|
43
41
|
username: 'Developer',
|
|
44
|
-
searchParams: Object.fromEntries([...searchParams])
|
|
42
|
+
searchParams: Object.fromEntries([...searchParams]),
|
|
43
|
+
...(config.data || {})
|
|
45
44
|
};
|
|
46
45
|
|
|
47
46
|
const defaultActions = {
|
|
@@ -83,7 +82,9 @@ export const Providers: React.FC<ProvidersProps> = ({ config, children }) => {
|
|
|
83
82
|
'logMessages',
|
|
84
83
|
JSON.stringify([...prevItems, newItem])
|
|
85
84
|
);
|
|
86
|
-
} catch {
|
|
85
|
+
} catch {
|
|
86
|
+
console.error('Failed to log message');
|
|
87
|
+
}
|
|
87
88
|
}
|
|
88
89
|
};
|
|
89
90
|
|
package/src/routes.tsx
CHANGED
|
@@ -16,24 +16,25 @@ export const Routes = () => {
|
|
|
16
16
|
<Route key={app.id} path={`/external/${app.slug}`}>
|
|
17
17
|
<Route index element={<PageExternal id={app.id} path={app.path} />} />
|
|
18
18
|
|
|
19
|
-
{(configs.get(app.id) as
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
19
|
+
{(configs.get(app.id) as unknown as { menu: unknown[] })?.menu?.map(
|
|
20
|
+
sub => {
|
|
21
|
+
const { path } = sub as { path: string };
|
|
22
|
+
return (
|
|
23
|
+
path !== '/' && (
|
|
24
|
+
<Route
|
|
25
|
+
key={path}
|
|
26
|
+
path={`/external/${app.slug}${path}`}
|
|
27
|
+
element={
|
|
28
|
+
<PageExternal
|
|
29
|
+
id={app.id}
|
|
30
|
+
path={app.subSlug ? `${app.subSlug}${path}` : path}
|
|
31
|
+
/>
|
|
32
|
+
}
|
|
33
|
+
/>
|
|
34
|
+
)
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
)}
|
|
37
38
|
</Route>
|
|
38
39
|
))}
|
|
39
40
|
|