@lobehub/ui 1.103.3 → 1.104.1

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.
@@ -34,17 +34,19 @@ var Burger = /*#__PURE__*/memo(function (_ref) {
34
34
  icon: opened ? X : MenuIcon,
35
35
  size: "site"
36
36
  }), /*#__PURE__*/_jsxs(Drawer, {
37
- bodyStyle: {
38
- padding: 0
39
- },
40
37
  className: styles.drawer,
41
38
  closeIcon: undefined,
42
- headerStyle: {
43
- display: 'none'
44
- },
45
39
  open: opened,
46
40
  placement: 'left',
47
41
  rootClassName: styles.drawerRoot,
42
+ styles: {
43
+ body: {
44
+ padding: 0
45
+ },
46
+ header: {
47
+ display: 'none'
48
+ }
49
+ },
48
50
  width: '100vw',
49
51
  children: [/*#__PURE__*/_jsx(Menu, {
50
52
  className: styles.menu,
@@ -16,7 +16,7 @@ var Actions = /*#__PURE__*/memo(function (_ref) {
16
16
  return /*#__PURE__*/_jsx(Flexbox, {
17
17
  align: 'flex-start',
18
18
  className: styles.actions,
19
- role: "widget",
19
+ role: "menubar",
20
20
  children: actions
21
21
  });
22
22
  });
@@ -24,7 +24,7 @@ export var useStyles = createStyles(function (_ref, _ref2) {
24
24
  alert: css(_templateObject7 || (_templateObject7 = _taggedTemplateLiteral([""]))),
25
25
  avatarContainer: css(_templateObject8 || (_templateObject8 = _taggedTemplateLiteral(["\n position: relative;\n flex: none;\n width: ", "px;\n height: ", "px;\n "])), avatarSize, avatarSize),
26
26
  avatarGroupContainer: css(_templateObject9 || (_templateObject9 = _taggedTemplateLiteral(["\n width: ", "px;\n "])), avatarSize),
27
- container: cx(type === 'pure' && pureContainerStylish, css(_templateObject10 || (_templateObject10 = _taggedTemplateLiteral(["\n position: relative;\n width: 100%;\n max-width: 100vw;\n padding: 12px 16px;\n\n time {\n display: inline-block;\n white-space: nowrap;\n }\n\n div[role='widget'] {\n display: flex;\n }\n\n time,\n div[role='widget'] {\n pointer-events: none;\n opacity: 0;\n transition: opacity 200ms ", ";\n }\n\n &:hover {\n time,\n div[role='widget'] {\n pointer-events: unset;\n opacity: 1;\n }\n }\n\n ", " {\n padding: 4px 16px;\n }\n "])), token.motionEaseOut, responsive.mobile)),
27
+ container: cx(type === 'pure' && pureContainerStylish, css(_templateObject10 || (_templateObject10 = _taggedTemplateLiteral(["\n position: relative;\n width: 100%;\n max-width: 100vw;\n padding: 12px 16px;\n\n time {\n display: inline-block;\n white-space: nowrap;\n }\n\n div[role='menubar'] {\n display: flex;\n }\n\n time,\n div[role='menubar'] {\n pointer-events: none;\n opacity: 0;\n transition: opacity 200ms ", ";\n }\n\n &:hover {\n time,\n div[role='menubar'] {\n pointer-events: unset;\n opacity: 1;\n }\n }\n\n ", " {\n padding: 4px 16px;\n }\n "])), token.motionEaseOut, responsive.mobile)),
28
28
  editingContainer: cx(editingStylish, css(_templateObject11 || (_templateObject11 = _taggedTemplateLiteral(["\n padding: 8px 12px 12px;\n border: 1px solid ", ";\n\n &:active,\n &:hover {\n border-color: ", ";\n }\n "])), token.colorBorderSecondary, token.colorBorder), type === 'pure' && css(_templateObject12 || (_templateObject12 = _taggedTemplateLiteral(["\n background: ", ";\n border-radius: ", "px;\n "])), token.colorFillQuaternary, token.borderRadius)),
29
29
  editingInput: css(_templateObject13 || (_templateObject13 = _taggedTemplateLiteral(["\n width: 100%;\n "]))),
30
30
  loading: css(_templateObject14 || (_templateObject14 = _taggedTemplateLiteral(["\n position: absolute;\n right: ", ";\n bottom: 0;\n left: ", ";\n\n width: 16px;\n height: 16px;\n\n color: ", ";\n\n background: ", ";\n border-radius: 50%;\n "])), placement === 'left' ? '-4px' : 'unset', placement === 'right' ? '-4px' : 'unset', token.colorBgLayout, token.colorPrimary),
@@ -4,7 +4,7 @@ import { ChatMessage } from "../types/chatMessage";
4
4
  import { LLMRoleType } from "../types/llm";
5
5
  import { type ActionsBarProps } from './ActionsBar';
6
6
  export type OnMessageChange = (id: string, content: string) => void;
7
- export type OnActionClick = (actionKey: string, messageId: string) => void;
7
+ export type OnActionClick = (props: ChatMessage) => void;
8
8
  export type RenderRole = LLMRoleType | 'default' | string;
9
9
  export type RenderItem = FC<{
10
10
  key: string;
@@ -21,13 +21,15 @@ export interface ListItemProps {
21
21
  /**
22
22
  * @description 点击操作按钮的回调函数
23
23
  */
24
- onActionClick?: OnActionClick;
24
+ onActionsClick?: {
25
+ [actionKey: string]: OnActionClick;
26
+ };
25
27
  /**
26
28
  * @description 消息变化的回调函数
27
29
  */
28
30
  onMessageChange?: OnMessageChange;
29
31
  renderActions?: {
30
- [role: RenderRole]: RenderAction;
32
+ [actionKey: string]: RenderAction;
31
33
  };
32
34
  /**
33
35
  * @description 渲染错误消息的函数
@@ -1,19 +1,20 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
2
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
3
3
  import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
4
- var _excluded = ["renderMessagesExtra", "showTitle", "onActionClick", "onMessageChange", "type", "text", "renderMessages", "renderErrorMessages", "renderActions", "loading", "groupNav", "renderItems"];
4
+ var _excluded = ["renderMessagesExtra", "showTitle", "onActionsClick", "onMessageChange", "type", "text", "renderMessages", "renderErrorMessages", "renderActions", "loading", "groupNav", "renderItems"];
5
5
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
6
6
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
7
7
  import { App } from 'antd';
8
- import copy from 'copy-to-clipboard';
8
+ import _copy from 'copy-to-clipboard';
9
9
  import { memo, useCallback, useMemo, useState } from 'react';
10
10
  import ChatItem from "../ChatItem";
11
11
  import ActionsBar from "./ActionsBar";
12
12
  import { jsx as _jsx } from "react/jsx-runtime";
13
13
  var Item = /*#__PURE__*/memo(function (props) {
14
+ var _item$error2;
14
15
  var renderMessagesExtra = props.renderMessagesExtra,
15
16
  showTitle = props.showTitle,
16
- _onActionClick = props.onActionClick,
17
+ onActionsClick = props.onActionsClick,
17
18
  onMessageChange = props.onMessageChange,
18
19
  type = props.type,
19
20
  text = props.text,
@@ -37,85 +38,99 @@ var Item = /*#__PURE__*/memo(function (props) {
37
38
  if (!renderFunction && renderItems !== null && renderItems !== void 0 && renderItems['default']) renderFunction = renderItems['default'];
38
39
  if (!renderFunction) return;
39
40
  return renderFunction;
40
- }, [renderItems, item]);
41
- var innerRenderMessage = useCallback(function (editableContent) {
41
+ }, [renderItems === null || renderItems === void 0 ? void 0 : renderItems[item.role]]);
42
+ var RenderMessage = useCallback(function (_ref) {
43
+ var editableContent = _ref.editableContent,
44
+ data = _ref.data;
42
45
  if (!renderMessages || !(item !== null && item !== void 0 && item.role)) return;
43
46
  var RenderFunction;
44
47
  if (renderMessages !== null && renderMessages !== void 0 && renderMessages[item.role]) RenderFunction = renderMessages[item.role];
45
48
  if (!RenderFunction && renderMessages !== null && renderMessages !== void 0 && renderMessages['default']) RenderFunction = renderMessages['default'];
46
49
  if (!RenderFunction) return;
47
- return /*#__PURE__*/_jsx(RenderFunction, _objectSpread(_objectSpread({}, item), {}, {
50
+ return /*#__PURE__*/_jsx(RenderFunction, _objectSpread(_objectSpread({}, data), {}, {
48
51
  editableContent: editableContent
49
52
  }));
50
- }, [renderMessages, item]);
51
- var MessageExtra = useCallback(function () {
53
+ }, [renderMessages === null || renderMessages === void 0 ? void 0 : renderMessages[item.role]]);
54
+ var MessageExtra = useCallback(function (_ref2) {
55
+ var data = _ref2.data;
52
56
  if (!renderMessagesExtra || !(item !== null && item !== void 0 && item.role)) return;
53
57
  var RenderFunction;
54
58
  if (renderMessagesExtra !== null && renderMessagesExtra !== void 0 && renderMessagesExtra[item.role]) RenderFunction = renderMessagesExtra[item.role];
55
59
  if (renderMessagesExtra !== null && renderMessagesExtra !== void 0 && renderMessagesExtra['default']) RenderFunction = renderMessagesExtra['default'];
56
60
  if (!RenderFunction && !RenderFunction) return;
57
- return /*#__PURE__*/_jsx(RenderFunction, _objectSpread({}, item));
58
- }, [renderMessagesExtra, item]);
59
- var ErrorMessage = useCallback(function () {
61
+ return /*#__PURE__*/_jsx(RenderFunction, _objectSpread({}, data));
62
+ }, [renderMessagesExtra === null || renderMessagesExtra === void 0 ? void 0 : renderMessagesExtra[item.role]]);
63
+ var ErrorMessage = useCallback(function (_ref3) {
60
64
  var _item$error;
65
+ var data = _ref3.data;
61
66
  if (!renderErrorMessages || !(item !== null && item !== void 0 && (_item$error = item.error) !== null && _item$error !== void 0 && _item$error.type)) return;
62
67
  var RenderFunction;
63
68
  if (renderErrorMessages !== null && renderErrorMessages !== void 0 && renderErrorMessages[item.error.type]) RenderFunction = renderErrorMessages[item.error.type];
64
69
  if (!RenderFunction && renderErrorMessages !== null && renderErrorMessages !== void 0 && renderErrorMessages['default']) RenderFunction = renderErrorMessages['default'];
65
70
  if (!RenderFunction) return;
66
- return /*#__PURE__*/_jsx(RenderFunction, _objectSpread({}, item));
67
- }, [renderErrorMessages, item.error]);
68
- var Actions = useCallback(function () {
71
+ return /*#__PURE__*/_jsx(RenderFunction, _objectSpread({}, data));
72
+ }, [renderErrorMessages === null || renderErrorMessages === void 0 ? void 0 : renderErrorMessages[item === null || item === void 0 ? void 0 : (_item$error2 = item.error) === null || _item$error2 === void 0 ? void 0 : _item$error2.type]]);
73
+ var Actions = useCallback(function (_ref4) {
74
+ var data = _ref4.data;
69
75
  if (!renderActions || !(item !== null && item !== void 0 && item.role)) return;
70
76
  var RenderFunction;
71
77
  if (renderActions !== null && renderActions !== void 0 && renderActions[item.role]) RenderFunction = renderActions[item.role];
72
78
  if (renderActions !== null && renderActions !== void 0 && renderActions['default']) RenderFunction = renderActions['default'];
73
79
  if (!RenderFunction) RenderFunction = ActionsBar;
74
- return /*#__PURE__*/_jsx(RenderFunction, _objectSpread(_objectSpread({}, item), {}, {
80
+ var handleActionClick = _objectSpread({
81
+ copy: function copy(_ref5) {
82
+ var content = _ref5.content;
83
+ _copy(content);
84
+ message.success((text === null || text === void 0 ? void 0 : text.copySuccess) || 'Copy Success');
85
+ },
86
+ edit: function edit() {
87
+ return setEditing(true);
88
+ }
89
+ }, onActionsClick);
90
+ return /*#__PURE__*/_jsx(RenderFunction, _objectSpread(_objectSpread({}, data), {}, {
75
91
  onActionClick: function onActionClick(actionKey) {
76
- switch (actionKey) {
77
- case 'copy':
78
- {
79
- copy(item.content);
80
- message.success((text === null || text === void 0 ? void 0 : text.copySuccess) || 'Copy Success');
81
- break;
82
- }
83
- case 'edit':
84
- {
85
- setEditing(true);
86
- break;
87
- }
88
- }
89
- _onActionClick === null || _onActionClick === void 0 ? void 0 : _onActionClick(actionKey, item.id);
92
+ var _handleActionClick$ac;
93
+ return handleActionClick === null || handleActionClick === void 0 ? void 0 : (_handleActionClick$ac = handleActionClick[actionKey]) === null || _handleActionClick$ac === void 0 ? void 0 : _handleActionClick$ac.call(handleActionClick, data);
90
94
  },
91
95
  text: text
92
96
  }));
93
- }, [renderActions, item, text, _onActionClick]);
97
+ }, [renderActions === null || renderActions === void 0 ? void 0 : renderActions[item.role], text, onActionsClick]);
94
98
  var error = useMemo(function () {
95
- var _item$error2;
99
+ var _item$error3;
96
100
  if (!item.error) return;
97
101
  return {
98
- message: (_item$error2 = item.error) === null || _item$error2 === void 0 ? void 0 : _item$error2.message
102
+ message: (_item$error3 = item.error) === null || _item$error3 === void 0 ? void 0 : _item$error3.message
99
103
  };
100
104
  }, [item.error]);
101
105
  if (RenderItem) return /*#__PURE__*/_jsx(RenderItem, _objectSpread({}, props), item.id);
102
106
  return /*#__PURE__*/_jsx(ChatItem, {
103
- actions: /*#__PURE__*/_jsx(Actions, {}),
107
+ actions: /*#__PURE__*/_jsx(Actions, {
108
+ data: item
109
+ }),
104
110
  avatar: item.meta,
105
111
  avatarAddon: groupNav,
106
112
  editing: editing,
107
113
  error: error,
108
- errorMessage: /*#__PURE__*/_jsx(ErrorMessage, {}),
114
+ errorMessage: /*#__PURE__*/_jsx(ErrorMessage, {
115
+ data: item
116
+ }),
109
117
  loading: loading,
110
118
  message: item.content,
111
- messageExtra: /*#__PURE__*/_jsx(MessageExtra, {}),
119
+ messageExtra: /*#__PURE__*/_jsx(MessageExtra, {
120
+ data: item
121
+ }),
112
122
  onChange: function onChange(value) {
113
123
  return onMessageChange === null || onMessageChange === void 0 ? void 0 : onMessageChange(item.id, value);
114
124
  },
115
125
  onEditingChange: setEditing,
116
126
  placement: type === 'chat' ? item.role === 'user' ? 'right' : 'left' : 'left',
117
127
  primary: item.role === 'user',
118
- renderMessage: innerRenderMessage,
128
+ renderMessage: function renderMessage(editableContent) {
129
+ return /*#__PURE__*/_jsx(RenderMessage, {
130
+ data: item,
131
+ editableContent: editableContent
132
+ });
133
+ },
119
134
  showTitle: showTitle,
120
135
  text: text,
121
136
  time: item.updateAt || item.createAt,
@@ -1,6 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
2
  import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
3
- var _excluded = ["onActionClick", "renderMessagesExtra", "className", "data", "type", "text", "showTitle", "onMessageChange", "renderMessages", "renderErrorMessages", "loadingId", "renderItems", "enableHistoryCount", "renderActions", "historyCount"];
3
+ var _excluded = ["onActionsClick", "renderMessagesExtra", "className", "data", "type", "text", "showTitle", "onMessageChange", "renderMessages", "renderErrorMessages", "loadingId", "renderItems", "enableHistoryCount", "renderActions", "historyCount"];
4
4
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
5
5
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
6
6
  import { Fragment, memo } from 'react';
@@ -10,7 +10,7 @@ import { useStyles } from "./style";
10
10
  import { jsx as _jsx } from "react/jsx-runtime";
11
11
  import { jsxs as _jsxs } from "react/jsx-runtime";
12
12
  var ChatList = /*#__PURE__*/memo(function (_ref) {
13
- var onActionClick = _ref.onActionClick,
13
+ var onActionsClick = _ref.onActionsClick,
14
14
  renderMessagesExtra = _ref.renderMessagesExtra,
15
15
  className = _ref.className,
16
16
  data = _ref.data,
@@ -37,7 +37,7 @@ var ChatList = /*#__PURE__*/memo(function (_ref) {
37
37
  children: data.map(function (item, index) {
38
38
  var itemProps = {
39
39
  loading: loadingId === item.id,
40
- onActionClick: onActionClick,
40
+ onActionsClick: onActionsClick,
41
41
  onMessageChange: onMessageChange,
42
42
  renderActions: renderActions,
43
43
  renderErrorMessages: renderErrorMessages,
@@ -43,9 +43,6 @@ var MessageModal = /*#__PURE__*/memo(function (_ref) {
43
43
  overflowY: 'auto'
44
44
  };
45
45
  return /*#__PURE__*/_jsx(Modal, {
46
- bodyStyle: mobile ? {
47
- padding: 16
48
- } : {},
49
46
  cancelText: (text === null || text === void 0 ? void 0 : text.cancel) || 'Cancel',
50
47
  footer: isEdit ? null : undefined,
51
48
  okText: (text === null || text === void 0 ? void 0 : text.edit) || 'Edit',
@@ -56,6 +53,11 @@ var MessageModal = /*#__PURE__*/memo(function (_ref) {
56
53
  return setTyping(true);
57
54
  },
58
55
  open: expand,
56
+ styles: mobile ? {
57
+ body: {
58
+ padding: 16
59
+ }
60
+ } : {},
59
61
  title: (text === null || text === void 0 ? void 0 : text.title) || 'Prompt',
60
62
  children: isEdit ? /*#__PURE__*/_jsx(MessageInput, {
61
63
  defaultValue: value,
package/es/Modal/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
2
  import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
3
3
  import _taggedTemplateLiteral from "@babel/runtime/helpers/esm/taggedTemplateLiteral";
4
- var _excluded = ["children", "title", "className", "wrapClassName", "width", "onCancel", "open", "destroyOnClose", "bodyStyle"];
4
+ var _excluded = ["children", "title", "className", "wrapClassName", "width", "onCancel", "open", "destroyOnClose"];
5
5
  var _templateObject, _templateObject2;
6
6
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
7
7
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
@@ -32,7 +32,6 @@ var Modal = /*#__PURE__*/memo(function (_ref2) {
32
32
  onCancel = _ref2.onCancel,
33
33
  open = _ref2.open,
34
34
  destroyOnClose = _ref2.destroyOnClose,
35
- bodyStyle = _ref2.bodyStyle,
36
35
  props = _objectWithoutProperties(_ref2, _excluded);
37
36
  var _useResponsive = useResponsive(),
38
37
  mobile = _useResponsive.mobile;
@@ -41,9 +40,6 @@ var Modal = /*#__PURE__*/memo(function (_ref2) {
41
40
  cx = _useStyles.cx,
42
41
  theme = _useStyles.theme;
43
42
  if (mobile) return /*#__PURE__*/_jsx(Drawer, {
44
- bodyStyle: bodyStyle || {
45
- padding: 0
46
- },
47
43
  closeIcon: /*#__PURE__*/_jsx(ActionIcon, {
48
44
  icon: X,
49
45
  size: {
@@ -55,14 +51,19 @@ var Modal = /*#__PURE__*/memo(function (_ref2) {
55
51
  drawerStyle: {
56
52
  background: "linear-gradient(to bottom, ".concat(theme.colorBgContainer, ", ").concat(theme.colorBgLayout, ")")
57
53
  },
58
- headerStyle: {
59
- padding: '8px 4px'
60
- },
61
54
  height: '75vh',
62
55
  maskClassName: cx(styles.wrap, wrapClassName),
63
56
  onClose: onCancel,
64
57
  open: open,
65
58
  placement: 'bottom',
59
+ styles: _objectSpread({
60
+ body: {
61
+ padding: 0
62
+ },
63
+ header: {
64
+ padding: '8px 4px'
65
+ }
66
+ }, props.styles),
66
67
  title: title,
67
68
  children: children
68
69
  });
@@ -73,7 +74,6 @@ var Modal = /*#__PURE__*/memo(function (_ref2) {
73
74
  }
74
75
  },
75
76
  children: /*#__PURE__*/_jsx(AntModal, _objectSpread(_objectSpread({
76
- bodyStyle: bodyStyle,
77
77
  className: cx(styles.content, className),
78
78
  closable: true,
79
79
  closeIcon: /*#__PURE__*/_jsx(Icon, {
@@ -8,7 +8,7 @@ export var useChatListActionsBar = function useChatListActionsBar(text) {
8
8
  },
9
9
  del: {
10
10
  icon: Trash,
11
- key: 'delete',
11
+ key: 'del',
12
12
  label: (text === null || text === void 0 ? void 0 : text.delete) || 'Delete'
13
13
  },
14
14
  divider: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/ui",
3
- "version": "1.103.3",
3
+ "version": "1.104.1",
4
4
  "description": "Lobe UI is an open-source UI component library for building AIGC web apps",
5
5
  "keywords": [
6
6
  "lobehub",