listpage-next 0.0.241 → 0.0.243

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.
@@ -1,6 +1,12 @@
1
- import { ItemType } from 'antd/es/menu/interface';
2
1
  import { MenuProps as AntdMenuProps } from 'antd';
3
- export type MenuItem = ItemType;
2
+ import { JSX, ReactNode } from 'react';
3
+ export type MenuItem = {
4
+ key: string;
5
+ label: string;
6
+ icon?: ReactNode;
7
+ children?: MenuItem[];
8
+ element?: JSX.Element;
9
+ };
4
10
  export interface MenuProps extends Omit<AntdMenuProps, 'onSelect'> {
5
11
  onSelect?: (path: string) => void;
6
12
  defaultActiveKey?: string;
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { Avatar, Image } from "antd";
2
+ import { Image } from "antd";
3
3
  import { styled } from "styled-components";
4
4
  import { usePageContext } from "../PageProvider/index.js";
5
5
  const PageLogo = (props)=>{
@@ -11,11 +11,7 @@ const PageLogo = (props)=>{
11
11
  src: src,
12
12
  preview: true
13
13
  });
14
- const avatar = icon && /*#__PURE__*/ jsx(Avatar, {
15
- icon: icon,
16
- shape: "circle",
17
- size: 22
18
- });
14
+ const avatar = icon;
19
15
  if (collapsed) return /*#__PURE__*/ jsx(LogoContentCollapseWrapper, {
20
16
  children: image || avatar
21
17
  });
@@ -0,0 +1,11 @@
1
+ import { MenuItem } from '../../components';
2
+ import { JSX, ReactNode } from 'react';
3
+ export interface AppProps {
4
+ menus: MenuItem[];
5
+ basename?: string;
6
+ title?: string;
7
+ icon?: ReactNode;
8
+ hasAuth?: () => boolean;
9
+ loginElement?: JSX.Element;
10
+ }
11
+ export declare const App: (props: AppProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,42 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useMemo } from "react";
3
+ import { RouterProvider, createBrowserRouter } from "react-router-dom";
4
+ import { createRoutes } from "./utils.js";
5
+ import { Auth } from "./Auth.js";
6
+ import { Layout } from "./Layout.js";
7
+ const App = (props)=>{
8
+ const { menus, basename = '', title, icon, loginElement, hasAuth } = props;
9
+ const router = useMemo(()=>{
10
+ const routes = createRoutes(menus);
11
+ return createBrowserRouter([
12
+ loginElement && {
13
+ path: '/login',
14
+ element: loginElement
15
+ },
16
+ {
17
+ path: '/',
18
+ element: /*#__PURE__*/ jsx(Auth, {
19
+ hasAuth: hasAuth,
20
+ children: /*#__PURE__*/ jsx(Layout, {
21
+ menus: menus,
22
+ title: title,
23
+ icon: icon,
24
+ basename: basename
25
+ })
26
+ }),
27
+ children: routes
28
+ }
29
+ ].filter(Boolean), {
30
+ basename
31
+ });
32
+ }, [
33
+ basename,
34
+ title,
35
+ icon,
36
+ menus
37
+ ]);
38
+ return /*#__PURE__*/ jsx(RouterProvider, {
39
+ router: router
40
+ });
41
+ };
42
+ export { App };
@@ -0,0 +1,4 @@
1
+ export declare const Auth: ({ children, hasAuth, }: {
2
+ children: React.ReactNode;
3
+ hasAuth?: () => boolean;
4
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { Fragment, jsx } from "react/jsx-runtime";
2
+ import { Navigate, useLocation } from "react-router-dom";
3
+ const Auth = ({ children, hasAuth = ()=>true })=>{
4
+ const location = useLocation();
5
+ if (!hasAuth()) return /*#__PURE__*/ jsx(Navigate, {
6
+ to: "/login",
7
+ state: {
8
+ from: location
9
+ },
10
+ replace: true
11
+ });
12
+ return /*#__PURE__*/ jsx(Fragment, {
13
+ children: children
14
+ });
15
+ };
16
+ export { Auth };
@@ -0,0 +1,9 @@
1
+ import { ReactNode } from 'react';
2
+ import { MenuItem } from '../../components';
3
+ export interface LayoutProps {
4
+ menus: MenuItem[];
5
+ basename?: string;
6
+ title?: string;
7
+ icon?: ReactNode;
8
+ }
9
+ export declare const Layout: (props: LayoutProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,26 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useMemo } from "react";
3
+ import { Outlet, useNavigate } from "react-router-dom";
4
+ import { Menu, PageLayout } from "../../components/index.js";
5
+ import { getDefaultActiveKey } from "./utils.js";
6
+ const Layout = (props)=>{
7
+ const { menus, basename = '', title, icon } = props;
8
+ const navigate = useNavigate();
9
+ const defaultActiveKey = useMemo(()=>getDefaultActiveKey(basename, menus), [
10
+ basename,
11
+ menus
12
+ ]);
13
+ return /*#__PURE__*/ jsx(PageLayout, {
14
+ logo: {
15
+ icon,
16
+ title
17
+ },
18
+ sider: /*#__PURE__*/ jsx(Menu, {
19
+ items: menus,
20
+ defaultActiveKey: defaultActiveKey,
21
+ onSelect: navigate
22
+ }),
23
+ content: /*#__PURE__*/ jsx(Outlet, {})
24
+ });
25
+ };
26
+ export { Layout };
@@ -0,0 +1 @@
1
+ export { App } from './App';
@@ -0,0 +1,2 @@
1
+ import { App } from "./App.js";
2
+ export { App };
@@ -0,0 +1,4 @@
1
+ import { MenuItem } from '../../components';
2
+ import { RouteObject } from 'react-router-dom';
3
+ export declare const getDefaultActiveKey: (basename: string, menus: MenuItem[]) => string | undefined;
4
+ export declare const createRoutes: (menus: MenuItem[]) => RouteObject[];
@@ -0,0 +1,15 @@
1
+ import { detectActiveMenu } from "../../components/index.js";
2
+ const getDefaultActiveKey = (basename, menus)=>{
3
+ let pathname = window.location.pathname;
4
+ if (pathname.startsWith(`${basename}`)) pathname = pathname.slice(basename.length + 1);
5
+ return detectActiveMenu(pathname, menus);
6
+ };
7
+ const createRoutes = (menus)=>{
8
+ const routes = menus.filter((menu)=>menu?.element).map((menu)=>({
9
+ path: menu.key,
10
+ element: menu.element,
11
+ children: createRoutes(menu?.children ?? [])
12
+ }));
13
+ return routes;
14
+ };
15
+ export { createRoutes, getDefaultActiveKey };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ export interface LogEntry {
3
+ timestamp: string;
4
+ level: 'INFO' | 'WARN' | 'ERROR' | 'DEBUG';
5
+ message: string;
6
+ }
7
+ export interface LogPreviewProps {
8
+ logs: LogEntry[];
9
+ className?: string;
10
+ }
11
+ export declare const LogPreview: React.FC<LogPreviewProps>;
@@ -0,0 +1,70 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef } from "react";
3
+ import ansi_to_html from "ansi-to-html";
4
+ import dayjs from "dayjs";
5
+ const LogPreview = ({ logs, className = '' })=>{
6
+ const logsEndRef = useRef(null);
7
+ const convert = useMemo(()=>new ansi_to_html({
8
+ fg: '#d1d5db',
9
+ bg: '#030712',
10
+ newline: false,
11
+ escapeXML: true,
12
+ stream: false
13
+ }), []);
14
+ useEffect(()=>{
15
+ const endEl = logsEndRef.current;
16
+ const container = endEl?.parentElement;
17
+ if (!endEl || !container) return;
18
+ const THRESHOLD = 50;
19
+ const distanceFromBottom = container.scrollHeight - (container.scrollTop + container.clientHeight);
20
+ if (distanceFromBottom <= THRESHOLD) endEl.scrollIntoView({
21
+ behavior: 'smooth'
22
+ });
23
+ }, [
24
+ logs
25
+ ]);
26
+ const getLevelColor = (level)=>{
27
+ const uLevel = level?.toUpperCase() || 'INFO';
28
+ switch(uLevel){
29
+ case 'ERROR':
30
+ return 'text-red-500 font-bold';
31
+ case 'WARN':
32
+ return 'text-yellow-500';
33
+ case 'DEBUG':
34
+ return 'text-blue-500';
35
+ default:
36
+ return 'text-green-500';
37
+ }
38
+ };
39
+ return /*#__PURE__*/ jsxs("div", {
40
+ className: `flex-1 bg-gray-950 rounded-lg border border-gray-800 font-mono text-sm p-4 overflow-y-auto w-full} transition-all duration-300 ${className}`,
41
+ children: [
42
+ 0 === logs.length ? /*#__PURE__*/ jsx("div", {
43
+ className: "text-gray-600 italic p-4 text-center",
44
+ children: "暂无日志或无法获取"
45
+ }) : logs.map((log, idx)=>/*#__PURE__*/ jsxs("div", {
46
+ className: "mb-1 hover:bg-gray-900/50 p-0.5 rounded flex gap-3",
47
+ children: [
48
+ /*#__PURE__*/ jsx("span", {
49
+ className: "text-gray-600 select-none shrink-0 text-xs py-0.5",
50
+ children: dayjs(log.timestamp).format('YYYY-MM-DD HH:mm:ss')
51
+ }),
52
+ log.level && /*#__PURE__*/ jsx("span", {
53
+ className: `${getLevelColor(log.level)} w-12 shrink-0 select-none`,
54
+ children: log.level || 'INFO'
55
+ }),
56
+ /*#__PURE__*/ jsx("span", {
57
+ className: "text-gray-300 break-all whitespace-pre-wrap",
58
+ dangerouslySetInnerHTML: {
59
+ __html: convert.toHtml(log.message)
60
+ }
61
+ })
62
+ ]
63
+ }, idx)),
64
+ /*#__PURE__*/ jsx("div", {
65
+ ref: logsEndRef
66
+ })
67
+ ]
68
+ });
69
+ };
70
+ export { LogPreview };
@@ -1,2 +1,3 @@
1
1
  export { PromptEditor, type PromptEditorProps } from './PromptEditor';
2
2
  export { Button, type ButtonProps } from './Button';
3
+ export { LogPreview, type LogPreviewProps, type LogEntry } from './LogPreview';
package/dist/ui/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  import { PromptEditor } from "./PromptEditor/index.js";
2
2
  import { Button } from "./Button/index.js";
3
- export { Button, PromptEditor };
3
+ import { LogPreview } from "./LogPreview/index.js";
4
+ export { Button, LogPreview, PromptEditor };
package/dist/ui.css CHANGED
@@ -7,14 +7,20 @@
7
7
  "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
8
8
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
9
9
  "Courier New", monospace;
10
+ --color-red-500: oklch(63.7% 0.237 25.331);
11
+ --color-yellow-500: oklch(79.5% 0.184 86.047);
12
+ --color-green-500: oklch(72.3% 0.219 149.579);
10
13
  --color-blue-500: oklch(62.3% 0.214 259.815);
11
14
  --color-blue-600: oklch(54.6% 0.245 262.881);
12
15
  --color-blue-900: oklch(37.9% 0.146 265.522);
13
16
  --color-slate-300: oklch(86.9% 0.022 252.894);
14
17
  --color-gray-300: oklch(87.2% 0.01 258.338);
15
18
  --color-gray-500: oklch(55.1% 0.027 264.364);
19
+ --color-gray-600: oklch(44.6% 0.03 256.802);
16
20
  --color-gray-700: oklch(37.3% 0.034 259.733);
17
21
  --color-gray-800: oklch(27.8% 0.033 256.848);
22
+ --color-gray-900: oklch(21% 0.034 264.665);
23
+ --color-gray-950: oklch(13% 0.028 261.692);
18
24
  --color-white: #fff;
19
25
  --spacing: 0.25rem;
20
26
  --text-xs: 0.75rem;
@@ -22,6 +28,7 @@
22
28
  --text-sm: 0.875rem;
23
29
  --text-sm--line-height: calc(1.25 / 0.875);
24
30
  --font-weight-medium: 500;
31
+ --font-weight-bold: 700;
25
32
  --radius-lg: 0.5rem;
26
33
  --animate-spin: spin 1s linear infinite;
27
34
  --default-transition-duration: 150ms;
@@ -188,6 +195,27 @@
188
195
  .relative {
189
196
  position: relative;
190
197
  }
198
+ .container {
199
+ width: 100%;
200
+ @media (width >= 40rem) {
201
+ max-width: 40rem;
202
+ }
203
+ @media (width >= 48rem) {
204
+ max-width: 48rem;
205
+ }
206
+ @media (width >= 64rem) {
207
+ max-width: 64rem;
208
+ }
209
+ @media (width >= 80rem) {
210
+ max-width: 80rem;
211
+ }
212
+ @media (width >= 96rem) {
213
+ max-width: 96rem;
214
+ }
215
+ }
216
+ .mb-1 {
217
+ margin-bottom: calc(var(--spacing) * 1);
218
+ }
191
219
  .block {
192
220
  display: block;
193
221
  }
@@ -206,12 +234,18 @@
206
234
  .h-full {
207
235
  height: 100%;
208
236
  }
237
+ .w-12 {
238
+ width: calc(var(--spacing) * 12);
239
+ }
209
240
  .flex-1 {
210
241
  flex: 1;
211
242
  }
212
243
  .flex-shrink {
213
244
  flex-shrink: 1;
214
245
  }
246
+ .shrink-0 {
247
+ flex-shrink: 0;
248
+ }
215
249
  .flex-grow {
216
250
  flex-grow: 1;
217
251
  }
@@ -239,12 +273,18 @@
239
273
  .gap-2 {
240
274
  gap: calc(var(--spacing) * 2);
241
275
  }
276
+ .gap-3 {
277
+ gap: calc(var(--spacing) * 3);
278
+ }
242
279
  .overflow-auto {
243
280
  overflow: auto;
244
281
  }
245
282
  .overflow-hidden {
246
283
  overflow: hidden;
247
284
  }
285
+ .overflow-y-auto {
286
+ overflow-y: auto;
287
+ }
248
288
  .rounded {
249
289
  border-radius: 0.25rem;
250
290
  }
@@ -258,12 +298,24 @@
258
298
  .border-gray-700 {
259
299
  border-color: var(--color-gray-700);
260
300
  }
301
+ .border-gray-800 {
302
+ border-color: var(--color-gray-800);
303
+ }
261
304
  .bg-\[\#0B1120\] {
262
305
  background-color: #0B1120;
263
306
  }
264
307
  .bg-blue-600 {
265
308
  background-color: var(--color-blue-600);
266
309
  }
310
+ .bg-gray-950 {
311
+ background-color: var(--color-gray-950);
312
+ }
313
+ .p-0\.5 {
314
+ padding: calc(var(--spacing) * 0.5);
315
+ }
316
+ .p-4 {
317
+ padding: calc(var(--spacing) * 4);
318
+ }
267
319
  .px-3 {
268
320
  padding-inline: calc(var(--spacing) * 3);
269
321
  }
@@ -273,6 +325,9 @@
273
325
  .px-6 {
274
326
  padding-inline: calc(var(--spacing) * 6);
275
327
  }
328
+ .py-0\.5 {
329
+ padding-block: calc(var(--spacing) * 0.5);
330
+ }
276
331
  .py-1\.5 {
277
332
  padding-block: calc(var(--spacing) * 1.5);
278
333
  }
@@ -282,6 +337,9 @@
282
337
  .py-2\.5 {
283
338
  padding-block: calc(var(--spacing) * 2.5);
284
339
  }
340
+ .text-center {
341
+ text-align: center;
342
+ }
285
343
  .font-mono {
286
344
  font-family: var(--font-mono);
287
345
  }
@@ -293,19 +351,47 @@
293
351
  font-size: var(--text-xs);
294
352
  line-height: var(--tw-leading, var(--text-xs--line-height));
295
353
  }
354
+ .font-bold {
355
+ --tw-font-weight: var(--font-weight-bold);
356
+ font-weight: var(--font-weight-bold);
357
+ }
296
358
  .font-medium {
297
359
  --tw-font-weight: var(--font-weight-medium);
298
360
  font-weight: var(--font-weight-medium);
299
361
  }
362
+ .break-all {
363
+ word-break: break-all;
364
+ }
365
+ .whitespace-pre-wrap {
366
+ white-space: pre-wrap;
367
+ }
368
+ .text-blue-500 {
369
+ color: var(--color-blue-500);
370
+ }
300
371
  .text-gray-300 {
301
372
  color: var(--color-gray-300);
302
373
  }
374
+ .text-gray-600 {
375
+ color: var(--color-gray-600);
376
+ }
377
+ .text-green-500 {
378
+ color: var(--color-green-500);
379
+ }
380
+ .text-red-500 {
381
+ color: var(--color-red-500);
382
+ }
303
383
  .text-slate-300 {
304
384
  color: var(--color-slate-300);
305
385
  }
306
386
  .text-white {
307
387
  color: var(--color-white);
308
388
  }
389
+ .text-yellow-500 {
390
+ color: var(--color-yellow-500);
391
+ }
392
+ .italic {
393
+ font-style: italic;
394
+ }
309
395
  .shadow-lg {
310
396
  --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
311
397
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
@@ -338,6 +424,14 @@
338
424
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
339
425
  transition-duration: var(--tw-duration, var(--default-transition-duration));
340
426
  }
427
+ .duration-300 {
428
+ --tw-duration: 300ms;
429
+ transition-duration: 300ms;
430
+ }
431
+ .select-none {
432
+ -webkit-user-select: none;
433
+ user-select: none;
434
+ }
341
435
  .hover\:scale-\[1\.02\] {
342
436
  &:hover {
343
437
  @media (hover: hover) {
@@ -359,6 +453,16 @@
359
453
  }
360
454
  }
361
455
  }
456
+ .hover\:bg-gray-900\/50 {
457
+ &:hover {
458
+ @media (hover: hover) {
459
+ background-color: color-mix(in srgb, oklch(21% 0.034 264.665) 50%, transparent);
460
+ @supports (color: color-mix(in lab, red, red)) {
461
+ background-color: color-mix(in oklab, var(--color-gray-900) 50%, transparent);
462
+ }
463
+ }
464
+ }
465
+ }
362
466
  .hover\:text-white {
363
467
  &:hover {
364
468
  @media (hover: hover) {
@@ -573,6 +677,10 @@
573
677
  syntax: "*";
574
678
  inherits: false;
575
679
  }
680
+ @property --tw-duration {
681
+ syntax: "*";
682
+ inherits: false;
683
+ }
576
684
  @keyframes spin {
577
685
  to {
578
686
  transform: rotate(360deg);
@@ -616,6 +724,7 @@
616
724
  --tw-drop-shadow-color: initial;
617
725
  --tw-drop-shadow-alpha: 100%;
618
726
  --tw-drop-shadow-size: initial;
727
+ --tw-duration: initial;
619
728
  }
620
729
  }
621
730
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "listpage-next",
3
- "version": "0.0.241",
3
+ "version": "0.0.243",
4
4
  "description": "A React component library for creating filter forms with Ant Design",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -11,8 +11,12 @@
11
11
  "import": "./dist/index.js"
12
12
  },
13
13
  "./ui": {
14
- "types": "./dist/ui.d.ts",
15
- "import": "./dist/ui.js"
14
+ "types": "./dist/ui/index.d.ts",
15
+ "import": "./dist/ui/index.js"
16
+ },
17
+ "./features/*": {
18
+ "types": "./dist/features/*/index.d.ts",
19
+ "import": "./dist/features/*/index.js"
16
20
  },
17
21
  "./ui.css": "./dist/ui.css"
18
22
  },
@@ -84,6 +88,7 @@
84
88
  "react-simple-code-editor": "~0.14.1",
85
89
  "prismjs": "~1.30.0",
86
90
  "@types/prismjs": "~1.26.5",
87
- "json-schema-faker": "~0.5.9"
91
+ "json-schema-faker": "~0.5.9",
92
+ "ansi-to-html": "~0.7.2"
88
93
  }
89
94
  }
package/dist/ui.d.ts DELETED
@@ -1 +0,0 @@
1
- export * from './ui';
package/dist/ui.js DELETED
@@ -1 +0,0 @@
1
- export * from "./ui.js";