@agentskillmania/skill-ui-shared 0.1.4 → 1.0.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.
Files changed (154) hide show
  1. package/README.md +27 -32
  2. package/README.zh_CN.md +46 -0
  3. package/dist/files/FilePreview.d.ts +4 -0
  4. package/dist/files/FilePreview.d.ts.map +1 -0
  5. package/dist/files/FilePreview.js +50 -0
  6. package/dist/files/FilePreview.js.map +1 -0
  7. package/dist/files/FileTabs.d.ts +3 -0
  8. package/dist/files/FileTabs.d.ts.map +1 -0
  9. package/dist/files/FileTabs.js +88 -0
  10. package/dist/files/FileTabs.js.map +1 -0
  11. package/dist/files/FileTree.d.ts +3 -0
  12. package/dist/files/FileTree.d.ts.map +1 -0
  13. package/dist/files/FileTree.js +64 -0
  14. package/dist/files/FileTree.js.map +1 -0
  15. package/dist/files/FileTypeIcon.d.ts +4 -0
  16. package/dist/files/FileTypeIcon.d.ts.map +1 -0
  17. package/dist/files/FileTypeIcon.js +26 -0
  18. package/dist/files/FileTypeIcon.js.map +1 -0
  19. package/dist/files/file-extensions.d.ts +31 -0
  20. package/dist/files/file-extensions.d.ts.map +1 -0
  21. package/dist/files/file-extensions.js +70 -0
  22. package/dist/files/file-extensions.js.map +1 -0
  23. package/dist/files/types.d.ts +49 -0
  24. package/dist/files/types.d.ts.map +1 -0
  25. package/dist/files/types.js +7 -0
  26. package/dist/files/types.js.map +1 -0
  27. package/dist/index.d.ts +18 -11
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +20 -14
  30. package/dist/index.js.map +1 -1
  31. package/dist/locales/en-US.d.ts +4 -5
  32. package/dist/locales/en-US.d.ts.map +1 -1
  33. package/dist/locales/en-US.js +4 -5
  34. package/dist/locales/en-US.js.map +1 -1
  35. package/dist/locales/index.d.ts +8 -10
  36. package/dist/locales/index.d.ts.map +1 -1
  37. package/dist/locales/zh-CN.d.ts +4 -5
  38. package/dist/locales/zh-CN.d.ts.map +1 -1
  39. package/dist/locales/zh-CN.js +4 -5
  40. package/dist/locales/zh-CN.js.map +1 -1
  41. package/dist/tsconfig.tsbuildinfo +1 -1
  42. package/dist/utils/format.d.ts +3 -23
  43. package/dist/utils/format.d.ts.map +1 -1
  44. package/dist/utils/format.js +15 -60
  45. package/dist/utils/format.js.map +1 -1
  46. package/package.json +4 -2
  47. package/dist/components/CollapsibleCard.d.ts +0 -22
  48. package/dist/components/CollapsibleCard.d.ts.map +0 -1
  49. package/dist/components/CollapsibleCard.js +0 -30
  50. package/dist/components/CollapsibleCard.js.map +0 -1
  51. package/dist/components/CopyValue.d.ts +0 -12
  52. package/dist/components/CopyValue.d.ts.map +0 -1
  53. package/dist/components/CopyValue.js +0 -39
  54. package/dist/components/CopyValue.js.map +0 -1
  55. package/dist/components/ExpandableItem.d.ts +0 -29
  56. package/dist/components/ExpandableItem.d.ts.map +0 -1
  57. package/dist/components/ExpandableItem.js +0 -28
  58. package/dist/components/ExpandableItem.js.map +0 -1
  59. package/dist/components/ExpandableRow.d.ts +0 -35
  60. package/dist/components/ExpandableRow.d.ts.map +0 -1
  61. package/dist/components/ExpandableRow.js +0 -69
  62. package/dist/components/ExpandableRow.js.map +0 -1
  63. package/dist/components/InfoRow.d.ts +0 -15
  64. package/dist/components/InfoRow.d.ts.map +0 -1
  65. package/dist/components/InfoRow.js +0 -27
  66. package/dist/components/InfoRow.js.map +0 -1
  67. package/dist/components/MetricTile.d.ts +0 -15
  68. package/dist/components/MetricTile.d.ts.map +0 -1
  69. package/dist/components/MetricTile.js +0 -32
  70. package/dist/components/MetricTile.js.map +0 -1
  71. package/dist/components/PaginationBar.d.ts +0 -17
  72. package/dist/components/PaginationBar.d.ts.map +0 -1
  73. package/dist/components/PaginationBar.js +0 -19
  74. package/dist/components/PaginationBar.js.map +0 -1
  75. package/dist/components/SectionHeader.d.ts +0 -15
  76. package/dist/components/SectionHeader.d.ts.map +0 -1
  77. package/dist/components/SectionHeader.js +0 -34
  78. package/dist/components/SectionHeader.js.map +0 -1
  79. package/dist/components/SectionLabel.d.ts +0 -10
  80. package/dist/components/SectionLabel.d.ts.map +0 -1
  81. package/dist/components/SectionLabel.js +0 -22
  82. package/dist/components/SectionLabel.js.map +0 -1
  83. package/dist/components/SplitDivider.d.ts +0 -13
  84. package/dist/components/SplitDivider.d.ts.map +0 -1
  85. package/dist/components/SplitDivider.js +0 -73
  86. package/dist/components/SplitDivider.js.map +0 -1
  87. package/dist/components/StatusDot.d.ts +0 -11
  88. package/dist/components/StatusDot.d.ts.map +0 -1
  89. package/dist/components/StatusDot.js +0 -21
  90. package/dist/components/StatusDot.js.map +0 -1
  91. package/dist/components/index.d.ts +0 -27
  92. package/dist/components/index.d.ts.map +0 -1
  93. package/dist/components/index.js +0 -14
  94. package/dist/components/index.js.map +0 -1
  95. package/dist/components/sidebar/Sidebar.d.ts +0 -21
  96. package/dist/components/sidebar/Sidebar.d.ts.map +0 -1
  97. package/dist/components/sidebar/Sidebar.js +0 -41
  98. package/dist/components/sidebar/Sidebar.js.map +0 -1
  99. package/dist/components/sidebar/SidebarIcons.d.ts +0 -25
  100. package/dist/components/sidebar/SidebarIcons.d.ts.map +0 -1
  101. package/dist/components/sidebar/SidebarIcons.js +0 -65
  102. package/dist/components/sidebar/SidebarIcons.js.map +0 -1
  103. package/dist/components/sidebar/SidebarPanel.d.ts +0 -13
  104. package/dist/components/sidebar/SidebarPanel.d.ts.map +0 -1
  105. package/dist/components/sidebar/SidebarPanel.js +0 -32
  106. package/dist/components/sidebar/SidebarPanel.js.map +0 -1
  107. package/dist/components/sidebar/index.d.ts +0 -7
  108. package/dist/components/sidebar/index.d.ts.map +0 -1
  109. package/dist/components/sidebar/index.js +0 -4
  110. package/dist/components/sidebar/index.js.map +0 -1
  111. package/dist/hooks/index.d.ts +0 -5
  112. package/dist/hooks/index.d.ts.map +0 -1
  113. package/dist/hooks/index.js +0 -3
  114. package/dist/hooks/index.js.map +0 -1
  115. package/dist/hooks/useResize.d.ts +0 -28
  116. package/dist/hooks/useResize.d.ts.map +0 -1
  117. package/dist/hooks/useResize.js +0 -39
  118. package/dist/hooks/useResize.js.map +0 -1
  119. package/dist/hooks/useToggle.d.ts +0 -17
  120. package/dist/hooks/useToggle.d.ts.map +0 -1
  121. package/dist/hooks/useToggle.js +0 -14
  122. package/dist/hooks/useToggle.js.map +0 -1
  123. package/dist/styles/card.d.ts +0 -12
  124. package/dist/styles/card.d.ts.map +0 -1
  125. package/dist/styles/card.js +0 -39
  126. package/dist/styles/card.js.map +0 -1
  127. package/dist/styles/empty-text.d.ts +0 -7
  128. package/dist/styles/empty-text.d.ts.map +0 -1
  129. package/dist/styles/empty-text.js +0 -13
  130. package/dist/styles/empty-text.js.map +0 -1
  131. package/dist/styles/expandable.d.ts +0 -12
  132. package/dist/styles/expandable.d.ts.map +0 -1
  133. package/dist/styles/expandable.js +0 -34
  134. package/dist/styles/expandable.js.map +0 -1
  135. package/dist/styles/index.d.ts +0 -5
  136. package/dist/styles/index.d.ts.map +0 -1
  137. package/dist/styles/index.js +0 -5
  138. package/dist/styles/index.js.map +0 -1
  139. package/dist/styles/metric.d.ts +0 -12
  140. package/dist/styles/metric.d.ts.map +0 -1
  141. package/dist/styles/metric.js +0 -26
  142. package/dist/styles/metric.js.map +0 -1
  143. package/dist/utils/avatar-color.d.ts +0 -32
  144. package/dist/utils/avatar-color.d.ts.map +0 -1
  145. package/dist/utils/avatar-color.js +0 -31
  146. package/dist/utils/avatar-color.js.map +0 -1
  147. package/dist/utils/fonts.d.ts +0 -6
  148. package/dist/utils/fonts.d.ts.map +0 -1
  149. package/dist/utils/fonts.js +0 -6
  150. package/dist/utils/fonts.js.map +0 -1
  151. package/dist/utils/pagination.d.ts +0 -6
  152. package/dist/utils/pagination.d.ts.map +0 -1
  153. package/dist/utils/pagination.js +0 -6
  154. package/dist/utils/pagination.js.map +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @agentskillmania/skill-ui-shared
2
2
 
3
- Shared UI components, hooks, and style presets for the @agentskillmania skill-ui ecosystem.
3
+ Shared foundation for @agentskillmania skill-ui packages — organized by faces, every member has real consumers.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,44 +8,39 @@ Shared UI components, hooks, and style presets for the @agentskillmania skill-ui
8
8
  pnpm add @agentskillmania/skill-ui-shared
9
9
  ```
10
10
 
11
- ## Components
11
+ ## Faces
12
12
 
13
- | Component | Description |
14
- |-----------|-------------|
15
- | `Sidebar` | Right-side collapsible sidebar shell |
16
- | `SidebarPanel` | Panel container with title bar + scrollable body |
17
- | `SidebarIcons` | Vertical icon bar for panel switching |
18
- | `CollapsibleCard` | antd Card (size="small") with collapse toggle |
19
- | `SectionHeader` | Icon + uppercase label + bottom divider |
20
- | `EmptyState` | Placeholder based on antd Empty |
21
- | `ExpandableItem` | Headless expandable list item container |
22
- | `SplitDivider` | 4px draggable vertical divider |
13
+ ### files file browsing domain
23
14
 
24
- ## Hooks
15
+ File tree / tabs / preview / type classification shared by the editor workbench and host side panels.
25
16
 
26
- | Hook | Description |
27
- |------|-------------|
28
- | `useToggle` | Boolean state with set/toggle/reset |
29
- | `useResize` | Drag-based width resizing |
17
+ | Export | Description |
18
+ |---|---|
19
+ | `FileTree` | File tree with directory expand/collapse and single selection |
20
+ | `FileTabs` | File tabs with dirty indicator and close button |
21
+ | `FilePreview` | Read-only preview — markdown rendered via `@ant-design/x-markdown`, code/text as `<pre>` |
22
+ | `FileTypeIcon` | Extension-driven lucide icon (markdown/code/image/doc/file) |
23
+ | `getFileKind` | Behavior classification: `'code' \| 'markdown' \| 'image' \| 'file'` |
24
+ | `getFileLabel` | Basename of a path |
25
+ | `FileNode` / `FileTab` / `FileTreeProps` / `FileTabsProps` / `FilePreviewProps` | Types |
30
26
 
31
- ## Style Presets
27
+ ### display
32
28
 
33
- | Preset | Description |
34
- |--------|-------------|
35
- | `cardBodyTransition` | Card body collapse/expand animation |
36
- | `cardHeaderInteractive` | Card header cursor + hover styles |
37
- | `expandableDetailTransition` | Expandable detail area animation |
38
- | `expandableSummaryHover` | Summary row hover styles |
29
+ | Export | Description |
30
+ |---|---|
31
+ | `EmptyState` | Empty placeholder based on antd Empty |
32
+
33
+ ### utils
34
+
35
+ | Export | Description |
36
+ |---|---|
37
+ | `formatTokens` | Compact token counts — `1200 → "1.2k"`, `1500000 → "1.5M"` |
38
+ | `formatDuration` | Milliseconds — `1500 → "1.5s"`, `42 → "42ms"` |
39
39
 
40
40
  ## i18n
41
41
 
42
- Exports `NAMESPACE` (`skill-ui-shared`) and `resources` for zh-CN / en-US locales.
42
+ `NAMESPACE` / `resources` are exported for host registration (zh-CN / en-US).
43
43
 
44
- ## Peer Dependencies
44
+ ## License
45
45
 
46
- - `@agentskillmania/skill-ui-theme`
47
- - `react`, `react-dom`
48
- - `antd` (^6.0.0)
49
- - `lucide-react`
50
- - `@emotion/react`
51
- - `react-i18next`
46
+ MIT © [yusangeng](https://github.com/yusangeng)
@@ -0,0 +1,46 @@
1
+ # @agentskillmania/skill-ui-shared
2
+
3
+ @agentskillmania skill-ui 生态的共享基础层 —— 按"面"组织,每个成员都有真实消费者。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ pnpm add @agentskillmania/skill-ui-shared
9
+ ```
10
+
11
+ ## 面
12
+
13
+ ### files — 文件浏览域
14
+
15
+ 编辑器工作台与宿主边窗共用的文件树 / 页签 / 预览 / 类型分类。
16
+
17
+ | 导出 | 说明 |
18
+ |---|---|
19
+ | `FileTree` | 文件树(目录展开/折叠 + 单选) |
20
+ | `FileTabs` | 文件页签(未保存标记 + 关闭按钮) |
21
+ | `FilePreview` | 只读预览 —— markdown 经 `@ant-design/x-markdown` 渲染,代码/文本为 `<pre>` |
22
+ | `FileTypeIcon` | 扩展名驱动的 lucide 图标(markdown/code/image/doc/file) |
23
+ | `getFileKind` | 行为分类:`'code' \| 'markdown' \| 'image' \| 'file'` |
24
+ | `getFileLabel` | 路径最后一段 |
25
+ | `FileNode` / `FileTab` / `FileTreeProps` / `FileTabsProps` / `FilePreviewProps` | 类型 |
26
+
27
+ ### display
28
+
29
+ | 导出 | 说明 |
30
+ |---|---|
31
+ | `EmptyState` | 基于 antd Empty 的空态占位 |
32
+
33
+ ### utils
34
+
35
+ | 导出 | 说明 |
36
+ |---|---|
37
+ | `formatTokens` | 紧凑 token 计数 —— `1200 → "1.2k"`,`1500000 → "1.5M"` |
38
+ | `formatDuration` | 毫秒时长 —— `1500 → "1.5s"`,`42 → "42ms"` |
39
+
40
+ ## i18n
41
+
42
+ 导出 `NAMESPACE` / `resources` 供宿主注册(zh-CN / en-US)。
43
+
44
+ ## License
45
+
46
+ MIT © [yusangeng](https://github.com/yusangeng)
@@ -0,0 +1,4 @@
1
+ import type { FilePreviewProps } from './types.js';
2
+ /** 只读文件内容预览:markdown 渲染 / 文本原样展示。 */
3
+ export declare function FilePreview({ path, content, className, style }: FilePreviewProps): import("@emotion/react/jsx-runtime").JSX.Element;
4
+ //# sourceMappingURL=FilePreview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilePreview.d.ts","sourceRoot":"","sources":["../../src/files/FilePreview.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAKnD,qCAAqC;AACrC,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,gBAAgB,oDAkDhF"}
@@ -0,0 +1,50 @@
1
+ import { jsx as _jsx } from "@emotion/react/jsx-runtime";
2
+ /** @jsxImportSource @emotion/react */
3
+ /**
4
+ * 只读文件预览器 — files 域通用件。
5
+ *
6
+ * 按 FileKind 路由:
7
+ * - markdown → @ant-design/x-markdown 静态渲染
8
+ * - code / file → 只读 <pre> 文本
9
+ *
10
+ * image(二进制)不进此组件 — 预览通道由宿主决定(如 antd Image / 静态 URL)。
11
+ * streaming 光标/防闪烁高亮属于聊天语义,这里不需要。
12
+ */
13
+ import { useTheme } from '@agentskillmania/skill-ui-theme';
14
+ import _XMarkdown from '@ant-design/x-markdown';
15
+ import { css } from '@emotion/react';
16
+ import { getFileKind } from './file-extensions.js';
17
+ // React 19 type compatibility: XMarkdown declared as FC but TS cannot recognize it as JSX component
18
+ const XMarkdown = _XMarkdown;
19
+ /** 只读文件内容预览:markdown 渲染 / 文本原样展示。 */
20
+ export function FilePreview({ path, content, className, style }) {
21
+ const theme = useTheme();
22
+ const kind = getFileKind(path);
23
+ if (kind === 'markdown') {
24
+ return (_jsx("div", { className: className, style: style, css: css `
25
+ height: 100%;
26
+ overflow-y: auto;
27
+ padding: ${theme.spacing[3]};
28
+ color: ${theme.color.text};
29
+ font-size: ${theme.font.size.sm};
30
+ line-height: 1.7;
31
+ `, children: _jsx(XMarkdown, { content: content, openLinksInNewTab: true,
32
+ // escape raw HTML in markdown as plain text to prevent XSS —
33
+ // previewed content may come from untrusted workspaces.
34
+ escapeRawHtml: true }) }));
35
+ }
36
+ return (_jsx("pre", { className: className, style: style, css: css `
37
+ margin: 0;
38
+ height: 100%;
39
+ overflow: auto;
40
+ padding: ${theme.spacing[3]};
41
+ background: ${theme.color.bgContainer};
42
+ color: ${theme.color.text};
43
+ font-family: ${theme.font.familyMono};
44
+ font-size: ${theme.font.size.sm};
45
+ line-height: 1.6;
46
+ white-space: pre-wrap;
47
+ word-break: break-word;
48
+ `, children: content }));
49
+ }
50
+ //# sourceMappingURL=FilePreview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilePreview.js","sourceRoot":"","sources":["../../src/files/FilePreview.tsx"],"names":[],"mappings":";AAAA,sCAAsC;AACtC;;;;;;;;;GASG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,UAAU,MAAM,wBAAwB,CAAC;AAEhD,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAGrC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,oGAAoG;AACpG,MAAM,SAAS,GAAG,UAA4D,CAAC;AAE/E,qCAAqC;AACrC,MAAM,UAAU,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAoB;IAC/E,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,OAAO,CACL,cACE,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,GAAG,CAAA;;;qBAGK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;mBAClB,KAAK,CAAC,KAAK,CAAC,IAAI;uBACZ,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;;SAEhC,YAED,KAAC,SAAS,IACR,OAAO,EAAE,OAAO,EAChB,iBAAiB;gBACjB,6DAA6D;gBAC7D,wDAAwD;gBACxD,aAAa,SACb,GACE,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,cACE,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,GAAG,CAAA;;;;mBAIK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;sBACb,KAAK,CAAC,KAAK,CAAC,WAAW;iBAC5B,KAAK,CAAC,KAAK,CAAC,IAAI;uBACV,KAAK,CAAC,IAAI,CAAC,UAAU;qBACvB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;;;;OAIhC,YAEA,OAAO,GACJ,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { FileTabsProps } from './types.js';
2
+ export declare function FileTabs({ tabs, activePath, onTabChange, onTabClose }: FileTabsProps): import("@emotion/react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=FileTabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileTabs.d.ts","sourceRoot":"","sources":["../../src/files/FileTabs.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAW,MAAM,YAAY,CAAC;AA8GzD,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,aAAa,oDA0BpF"}
@@ -0,0 +1,88 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
+ /** @jsxImportSource @emotion/react */
3
+ /**
4
+ * 文件页签组件 — 文件浏览域通用件(弹性收缩、未保存标记、关闭按钮)。
5
+ */
6
+ import { useTheme, interactiveItem, borderSeparator } from '@agentskillmania/skill-ui-theme';
7
+ import { css } from '@emotion/react';
8
+ import { X } from 'lucide-react';
9
+ import { useTranslation } from 'react-i18next';
10
+ import { FileTypeIcon } from './FileTypeIcon.js';
11
+ import { NAMESPACE } from '../locales/index.js';
12
+ /** Single tab */
13
+ function TabItem({ tab, isActive, onClick, onClose, }) {
14
+ const theme = useTheme();
15
+ const { t } = useTranslation(NAMESPACE);
16
+ return (_jsxs("div", { onClick: () => onClick(tab.path), css: css `
17
+ display: flex;
18
+ align-items: center;
19
+ gap: ${theme.spacing[1]};
20
+ padding: ${theme.spacing[1]} ${theme.spacing[2]};
21
+ background: ${isActive ? theme.color.primaryBg : 'transparent'};
22
+ border-radius: ${theme.radius.sm};
23
+ cursor: pointer;
24
+ transition: all ${theme.motion.duration.fast} ${theme.motion.easing.out};
25
+ flex: 1;
26
+ min-width: 0;
27
+ max-width: 180px;
28
+ flex-shrink: 1;
29
+ overflow: hidden;
30
+
31
+ ${interactiveItem(theme, theme.color.primaryBg)}
32
+ &:hover button {
33
+ opacity: 0.6;
34
+ }
35
+ `, children: [_jsx("span", { css: css `
36
+ display: flex;
37
+ align-items: center;
38
+ flex-shrink: 0;
39
+ color: ${isActive ? theme.color.primary : theme.color.textTertiary};
40
+ `, children: _jsx(FileTypeIcon, { path: tab.label, size: 12 }) }), _jsxs("span", { css: css `
41
+ flex: 1;
42
+ min-width: 0;
43
+ font-size: ${theme.font.size.sm};
44
+ color: ${isActive ? theme.color.text : theme.color.textSecondary};
45
+ white-space: nowrap;
46
+ overflow: hidden;
47
+ text-overflow: ellipsis;
48
+ `, children: [tab.label, tab.modified && (_jsx("span", { css: css `
49
+ color: ${theme.color.primary};
50
+ margin-left: 2px;
51
+ `, children: "\u2022" }))] }), _jsx("button", { onClick: (e) => {
52
+ e.stopPropagation();
53
+ onClose(tab.path);
54
+ }, css: css `
55
+ width: 20px;
56
+ height: 20px;
57
+ display: flex;
58
+ align-items: center;
59
+ justify-content: center;
60
+ border: none;
61
+ background: transparent;
62
+ border-radius: ${theme.radius.xs};
63
+ cursor: pointer;
64
+ color: ${theme.color.textTertiary};
65
+ opacity: ${isActive ? 0.7 : 0};
66
+ flex-shrink: 0;
67
+ transition: all ${theme.motion.duration.fast};
68
+
69
+ &:hover {
70
+ background: ${theme.color.fill};
71
+ color: ${theme.color.text};
72
+ opacity: 1;
73
+ }
74
+ `, type: "button", "aria-label": t('fileTabs.close', { label: tab.label }), children: _jsx(X, { size: 12 }) })] }));
75
+ }
76
+ export function FileTabs({ tabs, activePath, onTabChange, onTabClose }) {
77
+ const theme = useTheme();
78
+ return (_jsx("div", { css: css `
79
+ display: flex;
80
+ align-items: center;
81
+ gap: ${theme.spacing['0.5']};
82
+ min-width: 0;
83
+ overflow: hidden;
84
+ padding: ${theme.spacing['0.5']} ${theme.spacing[1]};
85
+ ${borderSeparator(theme)}
86
+ `, children: tabs.map((tab) => (_jsx(TabItem, { tab: tab, isActive: tab.path === activePath, onClick: onTabChange, onClose: onTabClose }, tab.path))) }));
87
+ }
88
+ //# sourceMappingURL=FileTabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileTabs.js","sourceRoot":"","sources":["../../src/files/FileTabs.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { FileTreeProps } from './types.js';
2
+ export declare function FileTree({ files, activeFilePath, onSelect }: FileTreeProps): import("@emotion/react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=FileTree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileTree.d.ts","sourceRoot":"","sources":["../../src/files/FileTree.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAY,aAAa,EAAE,MAAM,YAAY,CAAC;AAiG1D,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE,aAAa,oDA2B1E"}
@@ -0,0 +1,64 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
+ /** @jsxImportSource @emotion/react */
3
+ /**
4
+ * 文件树组件 — 文件浏览域通用件(文件树 + 目录展开 + 单选)。
5
+ */
6
+ import { useTheme, interactiveItem } from '@agentskillmania/skill-ui-theme';
7
+ import { css } from '@emotion/react';
8
+ import { ChevronRight, ChevronDown, FolderOpen } from 'lucide-react';
9
+ import { useCallback, useState } from 'react';
10
+ import { useTranslation } from 'react-i18next';
11
+ import { FileTypeIcon } from './FileTypeIcon.js';
12
+ import { EmptyState } from '../components/EmptyState.js';
13
+ import { NAMESPACE } from '../locales/index.js';
14
+ /** Single tree node */
15
+ function TreeNode({ file, activeFilePath, depth, onSelect, }) {
16
+ const theme = useTheme();
17
+ const [expanded, setExpanded] = useState(true);
18
+ const isActive = file.path === activeFilePath;
19
+ const handleClick = useCallback(() => {
20
+ if (file.isDirectory) {
21
+ setExpanded((prev) => !prev);
22
+ }
23
+ else {
24
+ onSelect(file.path);
25
+ }
26
+ }, [file, onSelect]);
27
+ return (_jsxs("div", { children: [_jsxs("div", { onClick: handleClick, "data-active": isActive ? 'true' : undefined, css: css `
28
+ display: flex;
29
+ align-items: center;
30
+ gap: ${theme.spacing[1]};
31
+ padding: ${theme.spacing['0.5']} ${theme.spacing[1]};
32
+ padding-left: ${theme.spacing[1 + depth * 2]};
33
+ cursor: pointer;
34
+ border-radius: ${theme.radius.xs};
35
+ background: ${isActive ? theme.color.primaryBg : 'transparent'};
36
+ color: ${isActive ? theme.color.primary : theme.color.text};
37
+ font-size: ${theme.font.size.sm};
38
+ transition: background ${theme.motion.duration.fast};
39
+ ${interactiveItem(theme, isActive ? theme.color.primaryBg : theme.color.fillSubtle)}
40
+ `, children: [file.isDirectory && (_jsx("span", { css: css `
41
+ display: flex;
42
+ color: ${theme.color.textTertiary};
43
+ `, children: expanded ? _jsx(ChevronDown, { size: 14 }) : _jsx(ChevronRight, { size: 14 }) })), _jsx("span", { css: css `
44
+ display: flex;
45
+ color: ${theme.color.textTertiary};
46
+ `, children: file.isDirectory ? (_jsx(FolderOpen, { size: 14 })) : (_jsx(FileTypeIcon, { path: file.path, size: 14 })) }), _jsx("span", { css: css `
47
+ overflow: hidden;
48
+ text-overflow: ellipsis;
49
+ white-space: nowrap;
50
+ `, children: file.path.split('/').pop() })] }), file.isDirectory && expanded && file.children && (_jsx("div", { children: file.children.map((child) => (_jsx(TreeNode, { file: child, activeFilePath: activeFilePath, depth: depth + 1, onSelect: onSelect }, child.path))) }))] }));
51
+ }
52
+ export function FileTree({ files, activeFilePath, onSelect }) {
53
+ const theme = useTheme();
54
+ const { t } = useTranslation(NAMESPACE);
55
+ if (!files || files.length === 0) {
56
+ return _jsx(EmptyState, { description: t('fileTree.emptyHint') });
57
+ }
58
+ return (_jsx("div", { css: css `
59
+ height: 100%;
60
+ overflow-y: auto;
61
+ padding: ${theme.spacing[1]} 0;
62
+ `, children: files.map((file) => (_jsx(TreeNode, { file: file, activeFilePath: activeFilePath, depth: 0, onSelect: onSelect }, file.path))) }));
63
+ }
64
+ //# sourceMappingURL=FileTree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileTree.js","sourceRoot":"","sources":["../../src/files/FileTree.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { FileTypeIconProps } from './types.js';
2
+ /** 按文件扩展名渲染对应图标。 */
3
+ export declare function FileTypeIcon({ path, size }: FileTypeIconProps): import("react").FunctionComponentElement<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
4
+ //# sourceMappingURL=FileTypeIcon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileTypeIcon.d.ts","sourceRoot":"","sources":["../../src/files/FileTypeIcon.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAWpD,oBAAoB;AACpB,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,IAAS,EAAE,EAAE,iBAAiB,4IAElE"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * 文件类型图标 — files 域共用(FileTree/FileTabs/宿主列表)。
3
+ *
4
+ * 图标映射独立于 FileKind:markdown→FileText、纯文本文档→Book、
5
+ * code→FileCode、image→FileImage、其他→File。
6
+ */
7
+ import { Book, File, FileCode, FileImage, FileText } from 'lucide-react';
8
+ import { createElement } from 'react';
9
+ import { getFileKind, isTextDoc } from './file-extensions.js';
10
+ function iconFor(path) {
11
+ const kind = getFileKind(path);
12
+ if (kind === 'markdown')
13
+ return FileText;
14
+ if (kind === 'image')
15
+ return FileImage;
16
+ if (kind === 'code')
17
+ return FileCode;
18
+ if (isTextDoc(path))
19
+ return Book;
20
+ return File;
21
+ }
22
+ /** 按文件扩展名渲染对应图标。 */
23
+ export function FileTypeIcon({ path, size = 14 }) {
24
+ return createElement(iconFor(path), { size });
25
+ }
26
+ //# sourceMappingURL=FileTypeIcon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileTypeIcon.js","sourceRoot":"","sources":["../../src/files/FileTypeIcon.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAmB,MAAM,cAAc,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAG9D,SAAS,OAAO,CAAC,IAAY;IAC3B,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,IAAI,KAAK,UAAU;QAAE,OAAO,QAAQ,CAAC;IACzC,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IACvC,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,QAAQ,CAAC;IACrC,IAAI,SAAS,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,oBAAoB;AACpB,MAAM,UAAU,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,EAAqB;IACjE,OAAO,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * 文件扩展名分类 — files 域共用(FileTree/FileTabs/FileTypeIcon/FilePreview)。
3
+ *
4
+ * 分类按行为差异定义,无装饰类:
5
+ * - `code` — 代码文本(可高亮语义)
6
+ * - `markdown` — 文本但需渲染为 HTML
7
+ * - `image` — 二进制图片
8
+ * - `file` — 其余兜底(普通文本/未知)
9
+ *
10
+ * DOC_EXTENSIONS(txt/rst/adoc 等)不构成 FileKind,只用于 FileTypeIcon
11
+ * 的图标细分(Book 图标),与行为无关。
12
+ */
13
+ /** 代码文本扩展名(FileCode 图标;编辑器可语法高亮)。 */
14
+ export declare const CODE_EXTENSIONS: readonly ["js", "jsx", "ts", "tsx", "py", "rb", "go", "rs", "java", "c", "cpp", "h", "sh", "bash", "zsh", "json", "yaml", "yml", "toml", "xml", "html", "css", "scss", "less", "sql"];
15
+ /** Markdown 扩展名(需渲染为 HTML 的文本)。 */
16
+ export declare const MARKDOWN_EXTENSIONS: readonly ["md", "mdx"];
17
+ /** 纯文本文档扩展名(仅图标细分为 Book,行为与普通文本一致)。 */
18
+ export declare const DOC_EXTENSIONS: readonly ["txt", "rst", "adoc"];
19
+ /** 图片扩展名(二进制,图片预览)。 */
20
+ export declare const IMAGE_EXTENSIONS: readonly ["png", "jpg", "jpeg", "gif", "webp", "svg", "bmp", "ico"];
21
+ /** 行为分类。 */
22
+ export type FileKind = 'code' | 'markdown' | 'image' | 'file';
23
+ /** Lowercased extension (without dot) for a file name or path, or '' if none. */
24
+ export declare function getExtension(name: string): string;
25
+ /** 由扩展名推导行为分类。 */
26
+ export declare function getFileKind(name: string): FileKind;
27
+ /** 纯文本文档判定(仅图标细分用;不是 FileKind)。 */
28
+ export declare function isTextDoc(name: string): boolean;
29
+ /** 文件显示名(路径最后一段)。 */
30
+ export declare function getFileLabel(filePath: string): string;
31
+ //# sourceMappingURL=file-extensions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-extensions.d.ts","sourceRoot":"","sources":["../../src/files/file-extensions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,qCAAqC;AACrC,eAAO,MAAM,eAAe,uLA0BlB,CAAC;AAEX,mCAAmC;AACnC,eAAO,MAAM,mBAAmB,wBAAyB,CAAC;AAE1D,uCAAuC;AACvC,eAAO,MAAM,cAAc,iCAAkC,CAAC;AAE9D,uBAAuB;AACvB,eAAO,MAAM,gBAAgB,qEAAsE,CAAC;AAEpG,YAAY;AACZ,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;AAE9D,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,kBAAkB;AAClB,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAMlD;AAED,mCAAmC;AACnC,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED,qBAAqB;AACrB,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErD"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * 文件扩展名分类 — files 域共用(FileTree/FileTabs/FileTypeIcon/FilePreview)。
3
+ *
4
+ * 分类按行为差异定义,无装饰类:
5
+ * - `code` — 代码文本(可高亮语义)
6
+ * - `markdown` — 文本但需渲染为 HTML
7
+ * - `image` — 二进制图片
8
+ * - `file` — 其余兜底(普通文本/未知)
9
+ *
10
+ * DOC_EXTENSIONS(txt/rst/adoc 等)不构成 FileKind,只用于 FileTypeIcon
11
+ * 的图标细分(Book 图标),与行为无关。
12
+ */
13
+ /** 代码文本扩展名(FileCode 图标;编辑器可语法高亮)。 */
14
+ export const CODE_EXTENSIONS = [
15
+ 'js',
16
+ 'jsx',
17
+ 'ts',
18
+ 'tsx',
19
+ 'py',
20
+ 'rb',
21
+ 'go',
22
+ 'rs',
23
+ 'java',
24
+ 'c',
25
+ 'cpp',
26
+ 'h',
27
+ 'sh',
28
+ 'bash',
29
+ 'zsh',
30
+ 'json',
31
+ 'yaml',
32
+ 'yml',
33
+ 'toml',
34
+ 'xml',
35
+ 'html',
36
+ 'css',
37
+ 'scss',
38
+ 'less',
39
+ 'sql',
40
+ ];
41
+ /** Markdown 扩展名(需渲染为 HTML 的文本)。 */
42
+ export const MARKDOWN_EXTENSIONS = ['md', 'mdx'];
43
+ /** 纯文本文档扩展名(仅图标细分为 Book,行为与普通文本一致)。 */
44
+ export const DOC_EXTENSIONS = ['txt', 'rst', 'adoc'];
45
+ /** 图片扩展名(二进制,图片预览)。 */
46
+ export const IMAGE_EXTENSIONS = ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp', 'ico'];
47
+ /** Lowercased extension (without dot) for a file name or path, or '' if none. */
48
+ export function getExtension(name) {
49
+ return name.split('.').pop()?.toLowerCase() ?? '';
50
+ }
51
+ /** 由扩展名推导行为分类。 */
52
+ export function getFileKind(name) {
53
+ const ext = getExtension(name);
54
+ if (MARKDOWN_EXTENSIONS.includes(ext))
55
+ return 'markdown';
56
+ if (IMAGE_EXTENSIONS.includes(ext))
57
+ return 'image';
58
+ if (CODE_EXTENSIONS.includes(ext))
59
+ return 'code';
60
+ return 'file';
61
+ }
62
+ /** 纯文本文档判定(仅图标细分用;不是 FileKind)。 */
63
+ export function isTextDoc(name) {
64
+ return DOC_EXTENSIONS.includes(getExtension(name));
65
+ }
66
+ /** 文件显示名(路径最后一段)。 */
67
+ export function getFileLabel(filePath) {
68
+ return filePath.split('/').pop() ?? filePath;
69
+ }
70
+ //# sourceMappingURL=file-extensions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-extensions.js","sourceRoot":"","sources":["../../src/files/file-extensions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,qCAAqC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,MAAM;IACN,GAAG;IACH,KAAK;IACL,GAAG;IACH,IAAI;IACJ,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,KAAK;CACG,CAAC;AAEX,mCAAmC;AACnC,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,IAAI,EAAE,KAAK,CAAU,CAAC;AAE1D,uCAAuC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAU,CAAC;AAE9D,uBAAuB;AACvB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAU,CAAC;AAKpG,iFAAiF;AACjF,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AACpD,CAAC;AAED,kBAAkB;AAClB,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAK,mBAAyC,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,UAAU,CAAC;IAChF,IAAK,gBAAsC,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IAC1E,IAAK,eAAqC,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC;IACxE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAQ,cAAoC,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,qBAAqB;AACrB,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,QAAQ,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @agentskillmania/skill-ui-shared — files 域类型定义
3
+ *
4
+ * 文件浏览(树/页签/预览)的通用契约,无 editor/gmemo 领域词汇。
5
+ */
6
+ /** 文件树节点(通用文件系统形状)。 */
7
+ export interface FileNode {
8
+ /** File path (relative to the workspace root, e.g. "README.md", "src/index.ts") */
9
+ path: string;
10
+ /** File content (optional — tree API typically doesn't return content) */
11
+ content?: string;
12
+ /** Whether it's a directory */
13
+ isDirectory?: boolean;
14
+ /** Child files (used for directories) */
15
+ children?: FileNode[];
16
+ }
17
+ /** 文件页签条目。 */
18
+ export interface FileTab {
19
+ path: string;
20
+ label: string;
21
+ modified?: boolean;
22
+ }
23
+ export interface FileTreeProps {
24
+ files: FileNode[];
25
+ activeFilePath: string | null;
26
+ onSelect: (path: string) => void;
27
+ }
28
+ export interface FileTabsProps {
29
+ tabs: FileTab[];
30
+ activePath: string | null;
31
+ onTabChange: (path: string) => void;
32
+ onTabClose: (path: string) => void;
33
+ }
34
+ export interface FileTypeIconProps {
35
+ /** File name or path — classification is derived from its extension */
36
+ path: string;
37
+ /** Icon size in pixels (default 14) */
38
+ size?: number;
39
+ }
40
+ export interface FilePreviewProps {
41
+ /** File path — preview routing is derived from its extension */
42
+ path: string;
43
+ /** Text content to preview */
44
+ content: string;
45
+ /** Optional CSS class / style passthrough */
46
+ className?: string;
47
+ style?: React.CSSProperties;
48
+ }
49
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/files/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,uBAAuB;AACvB,MAAM,WAAW,QAAQ;IACvB,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED,cAAc;AACd,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @agentskillmania/skill-ui-shared — files 域类型定义
3
+ *
4
+ * 文件浏览(树/页签/预览)的通用契约,无 editor/gmemo 领域词汇。
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/files/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
package/dist/index.d.ts CHANGED
@@ -1,15 +1,22 @@
1
1
  /**
2
- * @agentskillmania/skill-ui-shared
3
- * Shared UI components, hooks, and style presets for the skill-ui ecosystem.
2
+ * @agentskillmania/skill-ui-shared — 通用基础层
3
+ *
4
+ * 按"面"组织,每个成员都有 ≥2 个宿主/领域包的真实消费者:
5
+ *
6
+ * - **files**:文件浏览域(FileTree / FileTabs / FilePreview / FileTypeIcon +
7
+ * FileKind/getFileKind/getFileLabel + FileNode/FileTab 类型)——编辑器工作台
8
+ * 与 gmemo 边窗共用。
9
+ * - **display**:EmptyState —— FileTree/FilePreview/EditorWorkbench 共用的空态。
10
+ * - **utils**:formatTokens / formatDuration —— chat 与 editor 共用的格式化契约。
4
11
  */
5
- export { SectionHeader, EmptyState, ExpandableItem, CollapsibleCard, SplitDivider, Sidebar, SidebarPanel, SidebarIcons, MetricTile, SectionLabel, StatusDot, CopyValue, InfoRow, ExpandableRow, PaginationBar, } from './components/index.js';
6
- export type { SectionHeaderProps, EmptyStateProps, ExpandableItemProps, ExpandableItemContext, CollapsibleCardProps, SplitDividerProps, SidebarProps, SidebarPanelProps, SidebarIconsProps, SidebarIconItem, MetricTileProps, SectionLabelProps, StatusDotProps, CopyValueProps, InfoRowProps, ExpandableRowProps, DetailVariant, PaginationBarProps, } from './components/index.js';
7
- export { useToggle, useResize } from './hooks/index.js';
8
- export type { UseToggleReturn, UseResizeOptions, UseResizeReturn } from './hooks/index.js';
9
- export { cardBodyTransition, cardHeaderInteractive, expandableDetailTransition, expandableSummaryHover, metricsRow, metricGrid, emptyTextStyle, } from './styles/index.js';
10
- export { formatRelativeTime, formatTokens, formatNumber, formatDuration, truncate, formatTimestamp, } from './utils/format.js';
11
- export { PALETTE, hashId, getAvatarColor, getInitial } from './utils/avatar-color.js';
12
- export { FONT_DISPLAY } from './utils/fonts.js';
13
- export { DEFAULT_PAGE_SIZE } from './utils/pagination.js';
12
+ export { FileTree } from './files/FileTree.js';
13
+ export { FileTabs } from './files/FileTabs.js';
14
+ export { FileTypeIcon } from './files/FileTypeIcon.js';
15
+ export { FilePreview } from './files/FilePreview.js';
16
+ export { getFileKind, getFileLabel, getExtension, CODE_EXTENSIONS, MARKDOWN_EXTENSIONS, IMAGE_EXTENSIONS, type FileKind, } from './files/file-extensions.js';
17
+ export type { FileNode, FileTab, FileTreeProps, FileTabsProps, FileTypeIconProps, FilePreviewProps, } from './files/types.js';
18
+ export { EmptyState } from './components/EmptyState.js';
19
+ export type { EmptyStateProps } from './components/EmptyState.js';
20
+ export { formatTokens, formatDuration } from './utils/format.js';
14
21
  export { NAMESPACE, resources } from './locales/index.js';
15
22
  //# sourceMappingURL=index.d.ts.map