@lobehub/lobehub 2.0.0-next.173 → 2.0.0-next.174

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 (44) hide show
  1. package/.cursor/rules/db-migrations.mdc +10 -4
  2. package/.cursor/rules/drizzle-schema-style-guide.mdc +33 -17
  3. package/.cursor/rules/hotkey.mdc +161 -0
  4. package/.cursor/rules/i18n.mdc +2 -5
  5. package/.cursor/rules/project-introduce.mdc +3 -2
  6. package/.cursor/rules/project-structure.mdc +33 -37
  7. package/.cursor/rules/react.mdc +155 -0
  8. package/.cursor/rules/recent-data-usage.mdc +138 -0
  9. package/.cursor/rules/rules-index.mdc +1 -1
  10. package/.cursor/rules/testing-guide/agent-runtime-e2e.mdc +285 -0
  11. package/.cursor/rules/testing-guide/zustand-store-action-test.mdc +11 -16
  12. package/.cursor/rules/typescript.mdc +0 -4
  13. package/.cursor/rules/zustand-action-patterns.mdc +137 -169
  14. package/.cursor/rules/zustand-slice-organization.mdc +16 -8
  15. package/.husky/pre-commit +1 -1
  16. package/.i18nrc.js +3 -1
  17. package/AGENTS.md +3 -2
  18. package/CHANGELOG.md +25 -0
  19. package/CLAUDE.md +10 -3
  20. package/GEMINI.md +2 -1
  21. package/README.md +2 -2
  22. package/README.zh-CN.md +5 -5
  23. package/changelog/v1.json +9 -0
  24. package/docs/development/database-schema.dbml +18 -3
  25. package/docs/development/state-management/state-management-selectors.mdx +1 -1
  26. package/glossary.json +8 -0
  27. package/package.json +3 -3
  28. package/packages/database/migrations/0063_add_columns_for_several_tables.sql +30 -0
  29. package/packages/database/migrations/meta/0063_snapshot.json +9113 -0
  30. package/packages/database/migrations/meta/_journal.json +7 -0
  31. package/packages/database/src/core/migrations.json +29 -0
  32. package/packages/database/src/schemas/_helpers.ts +5 -1
  33. package/packages/database/src/schemas/agent.ts +2 -1
  34. package/packages/database/src/schemas/aiInfra.ts +18 -3
  35. package/packages/database/src/schemas/message.ts +11 -6
  36. package/packages/database/src/schemas/topic.ts +17 -2
  37. package/packages/database/src/schemas/user.ts +5 -2
  38. package/packages/database/src/schemas/userMemories.ts +9 -8
  39. package/packages/types/src/topic/thread.ts +24 -0
  40. package/packages/types/src/user/index.ts +1 -0
  41. package/packages/types/src/user/onboarding.ts +16 -0
  42. package/vitest.config.mts +3 -0
  43. package/.cursor/rules/group-chat.mdc +0 -35
  44. package/.cursor/rules/react-component.mdc +0 -173
@@ -441,6 +441,13 @@
441
441
  "when": 1765728439737,
442
442
  "tag": "0062_add_more_index",
443
443
  "breakpoints": true
444
+ },
445
+ {
446
+ "idx": 63,
447
+ "version": "7",
448
+ "when": 1766157362540,
449
+ "tag": "0063_add_columns_for_several_tables",
450
+ "breakpoints": true
444
451
  }
445
452
  ],
446
453
  "version": "6"
@@ -994,5 +994,34 @@
994
994
  "bps": true,
995
995
  "folderMillis": 1765728439737,
996
996
  "hash": "ba6a6beff2ad39419ec4aa7887539c9db0472e13f9242cb8780ff96eec450268"
997
+ },
998
+ {
999
+ "sql": [
1000
+ "DROP INDEX IF EXISTS \"user_memories_contexts_title_vector_index\";",
1001
+ "\nALTER TABLE \"agents\" ALTER COLUMN \"plugins\" DROP DEFAULT;",
1002
+ "\nALTER TABLE \"agents\" ADD COLUMN IF NOT EXISTS \"pinned\" boolean;",
1003
+ "\nALTER TABLE \"message_groups\" ADD COLUMN IF NOT EXISTS \"type\" text;",
1004
+ "\nALTER TABLE \"message_groups\" ADD COLUMN IF NOT EXISTS \"content\" text;",
1005
+ "\nALTER TABLE \"message_groups\" ADD COLUMN IF NOT EXISTS \"editor_data\" jsonb;",
1006
+ "\nALTER TABLE \"messages\" ADD COLUMN IF NOT EXISTS \"summary\" text;",
1007
+ "\nALTER TABLE \"threads\" ADD COLUMN IF NOT EXISTS \"agent_id\" text;",
1008
+ "\nALTER TABLE \"threads\" ADD COLUMN IF NOT EXISTS \"group_id\" text;",
1009
+ "\nALTER TABLE \"threads\" ADD COLUMN IF NOT EXISTS \"metadata\" jsonb;",
1010
+ "\nALTER TABLE \"user_settings\" ADD COLUMN IF NOT EXISTS \"memory\" jsonb;",
1011
+ "\nALTER TABLE \"users\" ADD COLUMN IF NOT EXISTS \"interests\" varchar(64)[];",
1012
+ "\nALTER TABLE \"users\" ADD COLUMN IF NOT EXISTS \"onboarding\" jsonb;",
1013
+ "\nDO $$ BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'threads_agent_id_agents_id_fk') THEN\n ALTER TABLE \"threads\" ADD CONSTRAINT \"threads_agent_id_agents_id_fk\" FOREIGN KEY (\"agent_id\") REFERENCES \"public\".\"agents\"(\"id\") ON DELETE cascade ON UPDATE no action;\n END IF;\nEND $$;",
1014
+ "\nDO $$ BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'threads_group_id_chat_groups_id_fk') THEN\n ALTER TABLE \"threads\" ADD CONSTRAINT \"threads_group_id_chat_groups_id_fk\" FOREIGN KEY (\"group_id\") REFERENCES \"public\".\"chat_groups\"(\"id\") ON DELETE cascade ON UPDATE no action;\n END IF;\nEND $$;",
1015
+ "\nCREATE INDEX IF NOT EXISTS \"ai_models_user_id_idx\" ON \"ai_models\" USING btree (\"user_id\");",
1016
+ "\nCREATE INDEX IF NOT EXISTS \"ai_providers_user_id_idx\" ON \"ai_providers\" USING btree (\"user_id\");",
1017
+ "\nCREATE INDEX IF NOT EXISTS \"message_groups_type_idx\" ON \"message_groups\" USING btree (\"type\");",
1018
+ "\nCREATE INDEX IF NOT EXISTS \"message_plugins_tool_call_id_idx\" ON \"message_plugins\" USING btree (\"tool_call_id\");",
1019
+ "\nCREATE INDEX IF NOT EXISTS \"threads_agent_id_idx\" ON \"threads\" USING btree (\"agent_id\");",
1020
+ "\nCREATE INDEX IF NOT EXISTS \"threads_group_id_idx\" ON \"threads\" USING btree (\"group_id\");",
1021
+ "\nALTER TABLE \"user_memories_contexts\" DROP COLUMN IF EXISTS \"title_vector\";\n"
1022
+ ],
1023
+ "bps": true,
1024
+ "folderMillis": 1766157362540,
1025
+ "hash": "7a8ee107778222390e676951173baa81bfa09dd47216a8467575fca54915172c"
997
1026
  }
998
1027
  ]
@@ -10,7 +10,11 @@ export const updatedAt = () =>
10
10
  .notNull()
11
11
  .defaultNow()
12
12
  .$onUpdate(() => new Date());
13
- export const accessedAt = () => timestamptz('accessed_at').notNull().defaultNow();
13
+ export const accessedAt = () =>
14
+ timestamptz('accessed_at')
15
+ .notNull()
16
+ .defaultNow()
17
+ .$onUpdate(() => new Date());
14
18
 
15
19
  // columns.helpers.ts
16
20
  export const timestamps = {
@@ -37,7 +37,7 @@ export const agents = pgTable(
37
37
  backgroundColor: text('background_color'),
38
38
  marketIdentifier: text('market_identifier'),
39
39
 
40
- plugins: jsonb('plugins').$type<string[]>().default([]),
40
+ plugins: jsonb('plugins').$type<string[]>(),
41
41
 
42
42
  clientId: text('client_id'),
43
43
 
@@ -55,6 +55,7 @@ export const agents = pgTable(
55
55
  tts: jsonb('tts').$type<LobeAgentTTSConfig>(),
56
56
 
57
57
  virtual: boolean('virtual').default(false),
58
+ pinned: boolean('pinned'),
58
59
 
59
60
  openingMessage: text('opening_message'),
60
61
  openingQuestions: text('opening_questions').array().default([]),
@@ -1,6 +1,15 @@
1
1
  /* eslint-disable sort-keys-fix/sort-keys-fix */
2
2
  import type { AiProviderConfig, AiProviderSettings } from '@lobechat/types';
3
- import { boolean, integer, jsonb, pgTable, primaryKey, text, varchar } from 'drizzle-orm/pg-core';
3
+ import {
4
+ boolean,
5
+ index,
6
+ integer,
7
+ jsonb,
8
+ pgTable,
9
+ primaryKey,
10
+ text,
11
+ varchar,
12
+ } from 'drizzle-orm/pg-core';
4
13
  import { AiModelSettings } from 'model-bank';
5
14
 
6
15
  import { timestamps } from './_helpers';
@@ -36,7 +45,10 @@ export const aiProviders = pgTable(
36
45
 
37
46
  ...timestamps,
38
47
  },
39
- (table) => [primaryKey({ columns: [table.id, table.userId] })],
48
+ (table) => [
49
+ primaryKey({ columns: [table.id, table.userId] }),
50
+ index('ai_providers_user_id_idx').on(table.userId),
51
+ ],
40
52
  );
41
53
 
42
54
  export type NewAiProviderItem = Omit<typeof aiProviders.$inferInsert, 'userId'>;
@@ -68,7 +80,10 @@ export const aiModels = pgTable(
68
80
 
69
81
  ...timestamps,
70
82
  },
71
- (table) => [primaryKey({ columns: [table.id, table.providerId, table.userId] })],
83
+ (table) => [
84
+ primaryKey({ columns: [table.id, table.providerId, table.userId] }),
85
+ index('ai_models_user_id_idx').on(table.userId),
86
+ ],
72
87
  );
73
88
 
74
89
  export type NewAiModelItem = Omit<typeof aiModels.$inferInsert, 'userId'>;
@@ -58,6 +58,11 @@ export const messageGroups = pgTable(
58
58
  title: varchar255('title'),
59
59
  description: text('description'),
60
60
 
61
+ // Compression fields
62
+ type: text('type', { enum: ['parallel', 'compression'] }),
63
+ content: text('content'), // compression summary (plain text)
64
+ editorData: jsonb('editor_data'), // rich text editor data (future extension)
65
+
61
66
  clientId: varchar255('client_id'),
62
67
 
63
68
  ...timestamps,
@@ -65,6 +70,7 @@ export const messageGroups = pgTable(
65
70
  (t) => [
66
71
  uniqueIndex('message_groups_client_id_user_id_unique').on(t.clientId, t.userId),
67
72
  index('message_groups_topic_id_idx').on(t.topicId),
73
+ index('message_groups_type_idx').on(t.type),
68
74
  ],
69
75
  );
70
76
 
@@ -84,6 +90,7 @@ export const messages = pgTable(
84
90
  role: varchar255('role').notNull(),
85
91
  content: text('content'),
86
92
  editorData: jsonb('editor_data'),
93
+ summary: text('summary'),
87
94
  reasoning: jsonb('reasoning').$type<ModelReasoning>(),
88
95
  search: jsonb('search').$type<GroundingSearch>(),
89
96
  metadata: jsonb('metadata'),
@@ -164,12 +171,10 @@ export const messagePlugins = pgTable(
164
171
  .references(() => users.id, { onDelete: 'cascade' })
165
172
  .notNull(),
166
173
  },
167
- (t) => ({
168
- clientIdUnique: uniqueIndex('message_plugins_client_id_user_id_unique').on(
169
- t.clientId,
170
- t.userId,
171
- ),
172
- }),
174
+ (t) => [
175
+ uniqueIndex('message_plugins_client_id_user_id_unique').on(t.clientId, t.userId),
176
+ index('message_plugins_tool_call_id_idx').on(t.toolCallId),
177
+ ],
173
178
  );
174
179
 
175
180
  export const messageTTS = pgTable(
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable sort-keys-fix/sort-keys-fix */
2
- import type { ChatTopicMetadata } from '@lobechat/types';
2
+ import type { ChatTopicMetadata, ThreadMetadata } from '@lobechat/types';
3
3
  import { sql } from 'drizzle-orm';
4
4
  import { boolean, index, jsonb, pgTable, primaryKey, text, uniqueIndex } from 'drizzle-orm/pg-core';
5
5
  import { createInsertSchema } from 'drizzle-zod';
@@ -63,7 +63,16 @@ export const threads = pgTable(
63
63
  editor_data: jsonb('editor_data'),
64
64
  type: text('type', { enum: ['continuation', 'standalone', 'isolation'] }).notNull(),
65
65
  status: text('status', {
66
- enum: ['active', 'processing', 'pending', 'inReview', 'todo', 'cancel'],
66
+ enum: [
67
+ 'active',
68
+ 'processing',
69
+ 'pending',
70
+ 'inReview',
71
+ 'todo',
72
+ 'cancel',
73
+ 'completed',
74
+ 'failed',
75
+ ],
67
76
  }),
68
77
 
69
78
  topicId: text('topic_id')
@@ -74,6 +83,10 @@ export const threads = pgTable(
74
83
  parentThreadId: text('parent_thread_id').references(() => threads.id, { onDelete: 'set null' }),
75
84
  clientId: text('client_id'),
76
85
 
86
+ agentId: text('agent_id').references(() => agents.id, { onDelete: 'cascade' }),
87
+ groupId: text('group_id').references(() => chatGroups.id, { onDelete: 'cascade' }),
88
+ metadata: jsonb('metadata').$type<ThreadMetadata | undefined>(),
89
+
77
90
  userId: text('user_id')
78
91
  .references(() => users.id, { onDelete: 'cascade' })
79
92
  .notNull(),
@@ -84,6 +97,8 @@ export const threads = pgTable(
84
97
  (t) => [
85
98
  uniqueIndex('threads_client_id_user_id_unique').on(t.clientId, t.userId),
86
99
  index('threads_topic_id_idx').on(t.topicId),
100
+ index('threads_agent_id_idx').on(t.agentId),
101
+ index('threads_group_id_idx').on(t.groupId),
87
102
  ],
88
103
  );
89
104
 
@@ -1,9 +1,9 @@
1
1
  /* eslint-disable sort-keys-fix/sort-keys-fix */
2
2
  import { DEFAULT_PREFERENCE } from '@lobechat/const';
3
- import type { CustomPluginParams } from '@lobechat/types';
3
+ import type { CustomPluginParams, UserOnboarding } from '@lobechat/types';
4
4
  import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
5
5
  import { sql } from 'drizzle-orm';
6
- import { boolean, index, jsonb, pgTable, primaryKey, text } from 'drizzle-orm/pg-core';
6
+ import { boolean, index, jsonb, pgTable, primaryKey, text, varchar } from 'drizzle-orm/pg-core';
7
7
 
8
8
  import { timestamps, timestamptz, varchar255 } from './_helpers';
9
9
 
@@ -20,8 +20,10 @@ export const users = pgTable(
20
20
  firstName: text('first_name'),
21
21
  lastName: text('last_name'),
22
22
  fullName: text('full_name'),
23
+ interests: varchar('interests', { length: 64 }).array(),
23
24
 
24
25
  isOnboarded: boolean('is_onboarded').default(false),
26
+ onboarding: jsonb('onboarding').$type<UserOnboarding>(),
25
27
  // Time user was created in Clerk
26
28
  clerkCreatedAt: timestamptz('clerk_created_at'),
27
29
 
@@ -77,6 +79,7 @@ export const userSettings = pgTable('user_settings', {
77
79
  systemAgent: jsonb('system_agent'),
78
80
  defaultAgent: jsonb('default_agent'),
79
81
  market: jsonb('market'),
82
+ memory: jsonb('memory'),
80
83
  tool: jsonb('tool'),
81
84
  image: jsonb('image'),
82
85
  });
@@ -55,16 +55,21 @@ export const userMemoriesContexts = pgTable(
55
55
  .primaryKey(),
56
56
 
57
57
  userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
58
- userMemoryIds: jsonb('user_memory_ids'),
58
+ userMemoryIds: jsonb('user_memory_ids').$type<string[]>(),
59
59
 
60
60
  metadata: jsonb('metadata').$type<Record<string, unknown>>(),
61
61
  tags: text('tags').array(),
62
62
 
63
- associatedObjects: jsonb('associated_objects'),
64
- associatedSubjects: jsonb('associated_subjects'),
63
+ associatedObjects:
64
+ jsonb('associated_objects').$type<
65
+ { extra?: Record<string, unknown>; name?: string; type?: string }[]
66
+ >(),
67
+ associatedSubjects:
68
+ jsonb('associated_subjects').$type<
69
+ { extra?: Record<string, unknown>; name?: string; type?: string }[]
70
+ >(),
65
71
 
66
72
  title: text('title'),
67
- titleVector: vector('title_vector', { dimensions: 1024 }),
68
73
  description: text('description'),
69
74
  descriptionVector: vector('description_vector', { dimensions: 1024 }),
70
75
 
@@ -79,10 +84,6 @@ export const userMemoriesContexts = pgTable(
79
84
  ...timestamps,
80
85
  },
81
86
  (table) => [
82
- index('user_memories_contexts_title_vector_index').using(
83
- 'hnsw',
84
- table.titleVector.op('vector_cosine_ops'),
85
- ),
86
87
  index('user_memories_contexts_description_vector_index').using(
87
88
  'hnsw',
88
89
  table.descriptionVector.op('vector_cosine_ops'),
@@ -25,6 +25,30 @@ export interface ThreadItem {
25
25
  userId: string;
26
26
  }
27
27
 
28
+ /**
29
+ * Metadata for Thread, used for agent task execution
30
+ */
31
+ export interface ThreadMetadata {
32
+ /** Task completion time */
33
+ completedAt?: string;
34
+ /** Execution duration in milliseconds */
35
+ duration?: number;
36
+ /** Error message when task failed */
37
+ error?: string;
38
+ /** Operation ID for tracking */
39
+ operationId?: string;
40
+ /** Task start time, used to calculate duration */
41
+ startedAt?: string;
42
+ /** Total cost in dollars */
43
+ totalCost?: number;
44
+ /** Total messages created during execution */
45
+ totalMessages?: number;
46
+ /** Total tokens consumed */
47
+ totalTokens?: number;
48
+ /** Total tool calls made */
49
+ totalToolCalls?: number;
50
+ }
51
+
28
52
  export interface CreateThreadParams {
29
53
  parentThreadId?: string;
30
54
  sourceMessageId?: string;
@@ -1,2 +1,3 @@
1
+ export * from './onboarding';
1
2
  export * from './preference';
2
3
  export * from './settings';
@@ -0,0 +1,16 @@
1
+ import { z } from 'zod';
2
+
3
+ export interface UserOnboarding {
4
+ /** Current step number (1-based), for resuming onboarding */
5
+ currentStep?: number;
6
+ /** Timestamp when onboarding was completed (ISO 8601) */
7
+ finishedAt?: string;
8
+ /** Onboarding flow version for future upgrades */
9
+ version: number;
10
+ }
11
+
12
+ export const UserOnboardingSchema = z.object({
13
+ currentStep: z.number().optional(),
14
+ finishedAt: z.string().optional(),
15
+ version: z.number(),
16
+ });
package/vitest.config.mts CHANGED
@@ -47,6 +47,9 @@ export default defineConfig({
47
47
  '**/node_modules/**',
48
48
  '**/dist/**',
49
49
  '**/build/**',
50
+ '**/tmp/**',
51
+ '**/temp/**',
52
+ '**/.temp/**',
50
53
  '**/apps/desktop/**',
51
54
  '**/apps/mobile/**',
52
55
  '**/packages/**',
@@ -1,35 +0,0 @@
1
- ---
2
- description: Explain how group chat works in LobeHub (Multi-agent orchestratoin)
3
- globs:
4
- alwaysApply: false
5
- ---
6
-
7
- This rule explains how group chat (multi-agent orchestration) works. Not confused with session group, which is a organization method to manage session.
8
-
9
- ## Key points
10
-
11
- - A supervisor will devide who and how will speak next
12
- - Each agent will speak just like in single chat (if was asked to speak)
13
- - Not coufused with session group
14
-
15
- ## Related Files
16
-
17
- - src/store/chat/slices/message/supervisor.ts
18
- - src/store/chat/slices/aiChat/actions/generateAIGroupChat.ts
19
- - src/prompts/groupChat/index.ts (All prompts here)
20
-
21
- ## Snippets
22
-
23
- ```tsx
24
- // Detect whether in group chat
25
- const isGroupSession = useSessionStore(sessionSelectors.isCurrentSessionGroupSession);
26
-
27
- // Member actions
28
- const addAgentsToGroup = useChatGroupStore((s) => s.addAgentsToGroup);
29
- const removeAgentFromGroup = useChatGroupStore((s) => s.removeAgentFromGroup);
30
- const persistReorder = useChatGroupStore((s) => s.reorderGroupMembers);
31
-
32
- // Get group info
33
- const groupConfig = useChatGroupStore(chatGroupSelectors.currentGroupConfig);
34
- const currentGroupMemebers = useSessionStore(sessionSelectors.currentGroupAgents);
35
- ```
@@ -1,173 +0,0 @@
1
- ---
2
- description:
3
- globs: *.tsx
4
- alwaysApply: false
5
- ---
6
-
7
- # react component 编写指南
8
-
9
- - 如果要写复杂样式的话用 antd-style ,简单的话可以用 style 属性直接写内联样式
10
- - 如果需要 flex 布局或者居中布局应该使用 react-layout-kit 的 Flexbox 和 Center 组件
11
- - 选择组件时优先顺序应该是 src/components > 安装的组件 package > lobe-ui > antd
12
- - 使用 selector 访问 zustand store 的数据,而不是直接从 store 获取
13
-
14
- ## antd-style token system
15
-
16
- ### 访问 token system 的两种方式
17
-
18
- #### 使用 antd-style 的 useTheme hook
19
-
20
- ```tsx
21
- import { useTheme } from 'antd-style';
22
-
23
- const MyComponent = () => {
24
- const theme = useTheme();
25
-
26
- return (
27
- <div
28
- style={{
29
- color: theme.colorPrimary,
30
- backgroundColor: theme.colorBgContainer,
31
- padding: theme.padding,
32
- borderRadius: theme.borderRadius,
33
- }}
34
- >
35
- 使用主题 token 的组件
36
- </div>
37
- );
38
- };
39
- ```
40
-
41
- #### 使用 antd-style 的 createStyles
42
-
43
- ```tsx
44
- const useStyles = createStyles(({ css, token }) => {
45
- return {
46
- container: css`
47
- background-color: ${token.colorBgContainer};
48
- border-radius: ${token.borderRadius}px;
49
- padding: ${token.padding}px;
50
- color: ${token.colorText};
51
- `,
52
- title: css`
53
- font-size: ${token.fontSizeLG}px;
54
- font-weight: ${token.fontWeightStrong};
55
- margin-bottom: ${token.marginSM}px;
56
- `,
57
- content: css`
58
- font-size: ${token.fontSize}px;
59
- line-height: ${token.lineHeight};
60
- `,
61
- };
62
- });
63
-
64
- const Card: FC<CardProps> = ({ title, content }) => {
65
- const { styles } = useStyles();
66
-
67
- return (
68
- <Flexbox className={styles.container}>
69
- <div className={styles.title}>{title}</div>
70
- <div className={styles.content}>{content}</div>
71
- </Flexbox>
72
- );
73
- };
74
- ```
75
-
76
- ### 一些你经常会忘记使用的 token
77
-
78
- 请注意使用下面的 token 而不是 css 字面值。可以访问 https://ant.design/docs/react/customize-theme-cn 了解所有 token
79
-
80
- - 动画类
81
- - token.motionDurationMid
82
- - token.motionEaseInOut
83
- - 包围盒属性
84
- - token.paddingSM
85
- - token.marginLG
86
-
87
- ## Lobe UI 包含的组件
88
-
89
- - 不知道 `@lobehub/ui` 的组件怎么用,有哪些属性,就自己搜下这个项目其它地方怎么用的,不要瞎猜,大部分组件都是在 antd 的基础上扩展了属性
90
- - 具体用法不懂可以联网搜索,例如 ActionIcon 就爬取 https://ui.lobehub.com/components/action-icon
91
- - 可以阅读 `node_modules/@lobehub/ui/es/index.js` 了解有哪些组件,每个组件的属性是什么
92
-
93
- - General
94
- - ActionIcon
95
- - ActionIconGroup
96
- - Block
97
- - Button
98
- - DownloadButton
99
- - Icon
100
- - Data Display
101
- - Avatar
102
- - AvatarGroup
103
- - GroupAvatar
104
- - Collapse
105
- - FileTypeIcon
106
- - FluentEmoji
107
- - GuideCard
108
- - Highlighter
109
- - Hotkey
110
- - Image
111
- - List
112
- - Markdown
113
- - SearchResultCards
114
- - MaterialFileTypeIcon
115
- - Mermaid
116
- - Typography
117
- - Text
118
- - Segmented
119
- - Snippet
120
- - SortableList
121
- - Tag
122
- - Tooltip
123
- - Video
124
- - Data Entry
125
- - AutoComplete
126
- - CodeEditor
127
- - ColorSwatches
128
- - CopyButton
129
- - DatePicker
130
- - EditableText
131
- - EmojiPicker
132
- - Form
133
- - FormModal
134
- - HotkeyInput
135
- - ImageSelect
136
- - Input
137
- - SearchBar
138
- - Select
139
- - SliderWithInput
140
- - ThemeSwitch
141
- - Feedback
142
- - Alert
143
- - Drawer
144
- - Modal
145
- - Layout
146
- - DraggablePanel
147
- - DraggablePanelBody
148
- - DraggablePanelContainer
149
- - DraggablePanelFooter
150
- - DraggablePanelHeader
151
- - Footer
152
- - Grid
153
- - Header
154
- - Layout
155
- - LayoutFooter
156
- - LayoutHeader
157
- - LayoutMain
158
- - LayoutSidebar
159
- - LayoutSidebarInner
160
- - LayoutToc
161
- - MaskShadow
162
- - ScrollShadow
163
- - Navigation
164
- - Burger
165
- - Dropdown
166
- - Menu
167
- - SideNav
168
- - Tabs
169
- - Toc
170
- - Theme
171
- - ConfigProvider
172
- - FontLoader
173
- - ThemeProvider