@yoka-ui/ui 1.0.6 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/@Docs-yoka/exports.generated.md +3 -3
- package/README.md +6 -6
- package/dist/es/assets/image/skills.zip +0 -0
- package/dist/es/business/Empty/index.js.map +1 -1
- package/dist/es/business/YkCharts/Area.d.ts +18 -0
- package/dist/es/business/YkCharts/Area.js +336 -0
- package/dist/es/business/YkCharts/Area.js.map +7 -0
- package/dist/es/business/YkCharts/Bar.d.ts +21 -0
- package/dist/es/business/YkCharts/Bar.js +316 -0
- package/dist/es/business/YkCharts/Bar.js.map +7 -0
- package/dist/es/business/YkCharts/BarProperty.d.ts +21 -0
- package/dist/es/business/YkCharts/BarProperty.js +357 -0
- package/dist/es/business/YkCharts/BarProperty.js.map +7 -0
- package/dist/es/business/YkCharts/BarTotal.d.ts +21 -0
- package/dist/es/business/YkCharts/BarTotal.js +288 -0
- package/dist/es/business/YkCharts/BarTotal.js.map +7 -0
- package/dist/es/business/YkCharts/Line.d.ts +21 -0
- package/dist/es/business/YkCharts/Line.js +342 -0
- package/dist/es/business/YkCharts/Line.js.map +7 -0
- package/dist/es/business/YkCharts/Pie.d.ts +19 -0
- package/dist/es/business/YkCharts/Pie.js +107 -0
- package/dist/es/business/YkCharts/Pie.js.map +7 -0
- package/dist/es/business/YkCharts/PieProperty.d.ts +18 -0
- package/dist/es/business/YkCharts/PieProperty.js +180 -0
- package/dist/es/business/YkCharts/PieProperty.js.map +7 -0
- package/dist/es/business/YkCharts/Pies.d.ts +26 -0
- package/dist/es/business/YkCharts/Pies.js +348 -0
- package/dist/es/business/YkCharts/Pies.js.map +7 -0
- package/dist/es/business/YkCharts/constants.d.ts +1 -0
- package/dist/es/business/YkCharts/constants.js +47 -0
- package/dist/es/business/YkCharts/constants.js.map +7 -0
- package/dist/es/business/YkCharts/hooks.d.ts +4 -0
- package/dist/es/business/YkCharts/hooks.js +37 -0
- package/dist/es/business/YkCharts/hooks.js.map +7 -0
- package/dist/es/business/YkCharts/index.d.ts +9 -0
- package/dist/es/business/YkCharts/index.js +20 -0
- package/dist/es/business/YkCharts/index.js.map +7 -0
- package/dist/es/business/YkCharts/index.module.less +164 -0
- package/dist/es/business/YkCharts/tooltip.less +92 -0
- package/dist/es/business/YkCharts/transformData.js +16 -0
- package/dist/es/business/YkCharts/transformData.js.map +7 -0
- package/dist/es/business/YkCharts/typing.d.ts +74 -0
- package/dist/es/business/YkCharts/typing.js +1 -0
- package/dist/es/business/YkCharts/typing.js.map +7 -0
- package/dist/es/business/YkCharts/utils.d.ts +4 -0
- package/dist/es/business/YkCharts/utils.js +109 -0
- package/dist/es/business/YkCharts/utils.js.map +7 -0
- package/dist/es/business/YkCharts/variables.less +13 -0
- package/dist/es/components/YKMarkdown/index.d.ts +11 -0
- package/dist/es/components/YKMarkdown/index.js +236 -0
- package/dist/es/components/YKMarkdown/index.js.map +7 -0
- package/dist/es/components/YKMarkdown/index.module.less +83 -0
- package/dist/es/components/YkDateRangePicker/YkDateRangePicker.mdx +3 -3
- package/dist/es/creative/GlassSegmentedRadio/index.d.ts +1 -1
- package/dist/es/creative/SkillsWriter/index.d.ts +3 -0
- package/dist/es/creative/SkillsWriter/index.js +191 -0
- package/dist/es/creative/SkillsWriter/index.js.map +7 -0
- package/dist/es/creative/SkillsWriter/index.module.less +21 -0
- package/dist/es/index.less +6 -1
- package/dist/es/utils/ykStorybookDoc.d.ts +15 -0
- package/dist/es/utils/ykStorybookDoc.js +24 -2
- package/dist/es/utils/ykStorybookDoc.js.map +2 -2
- package/dist/lib/assets/image/skills.zip +0 -0
- package/dist/lib/business/Empty/index.js.map +1 -1
- package/dist/lib/business/YkCharts/Area.d.ts +18 -0
- package/dist/lib/business/YkCharts/Area.js +346 -0
- package/dist/lib/business/YkCharts/Area.js.map +7 -0
- package/dist/lib/business/YkCharts/Bar.d.ts +21 -0
- package/dist/lib/business/YkCharts/Bar.js +323 -0
- package/dist/lib/business/YkCharts/Bar.js.map +7 -0
- package/dist/lib/business/YkCharts/BarProperty.d.ts +21 -0
- package/dist/lib/business/YkCharts/BarProperty.js +370 -0
- package/dist/lib/business/YkCharts/BarProperty.js.map +7 -0
- package/dist/lib/business/YkCharts/BarTotal.d.ts +21 -0
- package/dist/lib/business/YkCharts/BarTotal.js +295 -0
- package/dist/lib/business/YkCharts/BarTotal.js.map +7 -0
- package/dist/lib/business/YkCharts/Line.d.ts +21 -0
- package/dist/lib/business/YkCharts/Line.js +349 -0
- package/dist/lib/business/YkCharts/Line.js.map +7 -0
- package/dist/lib/business/YkCharts/Pie.d.ts +19 -0
- package/dist/lib/business/YkCharts/Pie.js +117 -0
- package/dist/lib/business/YkCharts/Pie.js.map +7 -0
- package/dist/lib/business/YkCharts/PieProperty.d.ts +18 -0
- package/dist/lib/business/YkCharts/PieProperty.js +193 -0
- package/dist/lib/business/YkCharts/PieProperty.js.map +7 -0
- package/dist/lib/business/YkCharts/Pies.d.ts +26 -0
- package/dist/lib/business/YkCharts/Pies.js +337 -0
- package/dist/lib/business/YkCharts/Pies.js.map +7 -0
- package/dist/lib/business/YkCharts/constants.d.ts +1 -0
- package/dist/lib/business/YkCharts/constants.js +71 -0
- package/dist/lib/business/YkCharts/constants.js.map +7 -0
- package/dist/lib/business/YkCharts/hooks.d.ts +4 -0
- package/dist/lib/business/YkCharts/hooks.js +62 -0
- package/dist/lib/business/YkCharts/hooks.js.map +7 -0
- package/dist/lib/business/YkCharts/index.d.ts +9 -0
- package/dist/lib/business/YkCharts/index.js +61 -0
- package/dist/lib/business/YkCharts/index.js.map +7 -0
- package/dist/lib/business/YkCharts/index.module.less +164 -0
- package/dist/lib/business/YkCharts/tooltip.less +92 -0
- package/dist/lib/business/YkCharts/transformData.js +40 -0
- package/dist/lib/business/YkCharts/transformData.js.map +7 -0
- package/dist/lib/business/YkCharts/typing.d.ts +74 -0
- package/dist/lib/business/YkCharts/typing.js +18 -0
- package/dist/lib/business/YkCharts/typing.js.map +7 -0
- package/dist/lib/business/YkCharts/utils.d.ts +4 -0
- package/dist/lib/business/YkCharts/utils.js +143 -0
- package/dist/lib/business/YkCharts/utils.js.map +7 -0
- package/dist/lib/business/YkCharts/variables.less +13 -0
- package/dist/lib/components/YKMarkdown/index.d.ts +11 -0
- package/dist/lib/components/YKMarkdown/index.js +188 -0
- package/dist/lib/components/YKMarkdown/index.js.map +7 -0
- package/dist/lib/components/YKMarkdown/index.module.less +83 -0
- package/dist/lib/components/YkDateRangePicker/YkDateRangePicker.mdx +3 -3
- package/dist/lib/creative/GlassSegmentedRadio/index.d.ts +1 -1
- package/dist/lib/creative/SkillsWriter/index.d.ts +3 -0
- package/dist/lib/creative/SkillsWriter/index.js +200 -0
- package/dist/lib/creative/SkillsWriter/index.js.map +7 -0
- package/dist/lib/creative/SkillsWriter/index.module.less +21 -0
- package/dist/lib/index.less +6 -1
- package/dist/lib/utils/ykStorybookDoc.d.ts +15 -0
- package/dist/lib/utils/ykStorybookDoc.js +23 -1
- package/dist/lib/utils/ykStorybookDoc.js.map +2 -2
- package/package.json +152 -143
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
9
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10
|
+
var __spreadValues = (a, b) => {
|
|
11
|
+
for (var prop in b || (b = {}))
|
|
12
|
+
if (__hasOwnProp.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
if (__getOwnPropSymbols)
|
|
15
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
16
|
+
if (__propIsEnum.call(b, prop))
|
|
17
|
+
__defNormalProp(a, prop, b[prop]);
|
|
18
|
+
}
|
|
19
|
+
return a;
|
|
20
|
+
};
|
|
21
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
22
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
23
|
+
}) : x)(function(x) {
|
|
24
|
+
if (typeof require !== "undefined")
|
|
25
|
+
return require.apply(this, arguments);
|
|
26
|
+
throw new Error('Dynamic require of "' + x + '" is not supported');
|
|
27
|
+
});
|
|
28
|
+
var __objRest = (source, exclude) => {
|
|
29
|
+
var target = {};
|
|
30
|
+
for (var prop in source)
|
|
31
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
32
|
+
target[prop] = source[prop];
|
|
33
|
+
if (source != null && __getOwnPropSymbols)
|
|
34
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
35
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
36
|
+
target[prop] = source[prop];
|
|
37
|
+
}
|
|
38
|
+
return target;
|
|
39
|
+
};
|
|
40
|
+
var __copyProps = (to, from, except, desc) => {
|
|
41
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
42
|
+
for (let key of __getOwnPropNames(from))
|
|
43
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
44
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
45
|
+
}
|
|
46
|
+
return to;
|
|
47
|
+
};
|
|
48
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
49
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
50
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
51
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
52
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
53
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
54
|
+
mod
|
|
55
|
+
));
|
|
56
|
+
var __async = (__this, __arguments, generator) => {
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
var fulfilled = (value) => {
|
|
59
|
+
try {
|
|
60
|
+
step(generator.next(value));
|
|
61
|
+
} catch (e) {
|
|
62
|
+
reject(e);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var rejected = (value) => {
|
|
66
|
+
try {
|
|
67
|
+
step(generator.throw(value));
|
|
68
|
+
} catch (e) {
|
|
69
|
+
reject(e);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
73
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// src/components/YKMarkdown/index.tsx
|
|
78
|
+
import MarkdownPreview from "@uiw/react-markdown-preview";
|
|
79
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
80
|
+
import styles from "./index.module.less";
|
|
81
|
+
var YKMarkdown = ({ markdown, showToc = false }) => {
|
|
82
|
+
const contentRef = useRef(null);
|
|
83
|
+
const [headings, setHeadings] = useState([]);
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (!showToc) {
|
|
86
|
+
setHeadings([]);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (!contentRef.current)
|
|
90
|
+
return;
|
|
91
|
+
const headingElements = contentRef.current.querySelectorAll("h1, h2, h3, h4, h5, h6");
|
|
92
|
+
const headingList = Array.from(headingElements).map((el) => ({
|
|
93
|
+
id: el.id,
|
|
94
|
+
text: el.textContent || "",
|
|
95
|
+
level: parseInt(el.tagName.charAt(1), 10)
|
|
96
|
+
}));
|
|
97
|
+
setHeadings(headingList);
|
|
98
|
+
}, [markdown, showToc]);
|
|
99
|
+
const handleScrollTo = useCallback((id) => {
|
|
100
|
+
const element = document.getElementById(id);
|
|
101
|
+
if (element) {
|
|
102
|
+
element.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
103
|
+
}
|
|
104
|
+
}, []);
|
|
105
|
+
return /* @__PURE__ */ React.createElement("div", { className: styles.container }, showToc && headings.length > 0 && /* @__PURE__ */ React.createElement("div", { className: styles.toc }, /* @__PURE__ */ React.createElement("h3", null, "目录"), /* @__PURE__ */ React.createElement("ul", { style: { paddingLeft: "16px", fontSize: "12px", color: "#666" } }, headings.map((heading) => /* @__PURE__ */ React.createElement(
|
|
106
|
+
"li",
|
|
107
|
+
{
|
|
108
|
+
key: heading.id,
|
|
109
|
+
style: {
|
|
110
|
+
marginLeft: `${(heading.level - 1) * 12}px`,
|
|
111
|
+
listStyle: "none",
|
|
112
|
+
marginBottom: "8px"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
/* @__PURE__ */ React.createElement(
|
|
116
|
+
"a",
|
|
117
|
+
{
|
|
118
|
+
href: `#${heading.id}`,
|
|
119
|
+
onClick: (e) => {
|
|
120
|
+
e.preventDefault();
|
|
121
|
+
handleScrollTo(heading.id);
|
|
122
|
+
},
|
|
123
|
+
style: { color: "#000", textDecoration: "none" }
|
|
124
|
+
},
|
|
125
|
+
heading.text
|
|
126
|
+
)
|
|
127
|
+
)))), /* @__PURE__ */ React.createElement("div", { ref: contentRef, className: styles.content }, /* @__PURE__ */ React.createElement(
|
|
128
|
+
MarkdownPreview,
|
|
129
|
+
{
|
|
130
|
+
source: markdown,
|
|
131
|
+
components: { code: Code, pre: Pre },
|
|
132
|
+
style: { padding: 16 }
|
|
133
|
+
}
|
|
134
|
+
)), showToc && headings.length > 0 && /* @__PURE__ */ React.createElement("div", { className: styles.spacer }));
|
|
135
|
+
};
|
|
136
|
+
var MermaidCode = ({ code, className }) => {
|
|
137
|
+
const demoid = useMemo(() => `dome${parseInt(String(Math.random() * 1e15), 10).toString(36)}`, []);
|
|
138
|
+
const [container, setContainer] = useState(null);
|
|
139
|
+
const [mermaidInstance, setMermaidInstance] = useState(null);
|
|
140
|
+
const isMermaid = className && /^language-mermaid/.test(className.toLocaleLowerCase());
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
if (isMermaid && !mermaidInstance) {
|
|
143
|
+
Promise.resolve().then(() => __toESM(__require("mermaid"))).then((mod) => {
|
|
144
|
+
setMermaidInstance(mod.default || mod);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}, [isMermaid, mermaidInstance]);
|
|
148
|
+
const reRender = useCallback(() => __async(void 0, null, function* () {
|
|
149
|
+
if (container && isMermaid && mermaidInstance) {
|
|
150
|
+
try {
|
|
151
|
+
const str = yield mermaidInstance.render(demoid, code);
|
|
152
|
+
container.innerHTML = str.svg;
|
|
153
|
+
} catch (error) {
|
|
154
|
+
container.innerHTML = String(error);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}), [container, isMermaid, code, demoid, mermaidInstance]);
|
|
158
|
+
useEffect(() => {
|
|
159
|
+
reRender();
|
|
160
|
+
}, [reRender]);
|
|
161
|
+
const refElement = useCallback((node) => {
|
|
162
|
+
if (node !== null) {
|
|
163
|
+
setContainer(node);
|
|
164
|
+
}
|
|
165
|
+
}, []);
|
|
166
|
+
if (isMermaid) {
|
|
167
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("code", { id: demoid, style: { display: "none" } }), /* @__PURE__ */ React.createElement("code", { ref: refElement, "data-name": "mermaid" }));
|
|
168
|
+
}
|
|
169
|
+
return /* @__PURE__ */ React.createElement("code", null, code);
|
|
170
|
+
};
|
|
171
|
+
var getCodeString = (children) => {
|
|
172
|
+
let result = "";
|
|
173
|
+
const traverse = (nodes) => {
|
|
174
|
+
for (const node of nodes) {
|
|
175
|
+
if (typeof node === "object" && node !== null && "type" in node) {
|
|
176
|
+
const n = node;
|
|
177
|
+
if (n.type === "text" && n.value) {
|
|
178
|
+
result += n.value;
|
|
179
|
+
} else if (n.children) {
|
|
180
|
+
traverse(n.children);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
traverse(children);
|
|
186
|
+
return result;
|
|
187
|
+
};
|
|
188
|
+
var Code = (_a) => {
|
|
189
|
+
var _b = _a, { inline, children, className, node } = _b, props = __objRest(_b, ["inline", "children", "className", "node"]);
|
|
190
|
+
if (inline) {
|
|
191
|
+
return /* @__PURE__ */ React.createElement("code", __spreadValues({}, props), children);
|
|
192
|
+
}
|
|
193
|
+
const code = (node == null ? void 0 : node.children) ? getCodeString(node.children) : Array.isArray(children) ? String(children[0] || "") : String(children || "");
|
|
194
|
+
return /* @__PURE__ */ React.createElement(MermaidCode, { code, className });
|
|
195
|
+
};
|
|
196
|
+
var Pre = (_a) => {
|
|
197
|
+
var _b = _a, { children, node } = _b, props = __objRest(_b, ["children", "node"]);
|
|
198
|
+
let codeStr = "";
|
|
199
|
+
let mermaidCode = "";
|
|
200
|
+
let mermaidClassName = "";
|
|
201
|
+
React.Children.forEach(children, (child) => {
|
|
202
|
+
var _a2, _b2;
|
|
203
|
+
if (React.isValidElement(child)) {
|
|
204
|
+
const childProps = child.props;
|
|
205
|
+
if (childProps == null ? void 0 : childProps.node) {
|
|
206
|
+
codeStr = getCodeString(childProps.node.children);
|
|
207
|
+
}
|
|
208
|
+
if ((_b2 = (_a2 = childProps == null ? void 0 : childProps.className) == null ? void 0 : _a2.includes) == null ? void 0 : _b2.call(_a2, "language-mermaid")) {
|
|
209
|
+
mermaidCode = codeStr;
|
|
210
|
+
mermaidClassName = childProps.className || "";
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
if (!codeStr && (node == null ? void 0 : node.children)) {
|
|
215
|
+
codeStr = getCodeString(node.children);
|
|
216
|
+
}
|
|
217
|
+
const renderContent = (child) => {
|
|
218
|
+
var _a2, _b2, _c, _d;
|
|
219
|
+
if (React.isValidElement(child)) {
|
|
220
|
+
const childElement = child;
|
|
221
|
+
if ((_c = (_b2 = (_a2 = childElement.props) == null ? void 0 : _a2.className) == null ? void 0 : _b2.includes) == null ? void 0 : _c.call(_b2, "language-mermaid")) {
|
|
222
|
+
return /* @__PURE__ */ React.createElement(MermaidCode, { code: mermaidCode, className: mermaidClassName });
|
|
223
|
+
}
|
|
224
|
+
return React.cloneElement(childElement, {
|
|
225
|
+
children: React.Children.map((_d = childElement.props) == null ? void 0 : _d.children, renderContent)
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
return child;
|
|
229
|
+
};
|
|
230
|
+
return /* @__PURE__ */ React.createElement("div", { className: styles.codeBlock }, /* @__PURE__ */ React.createElement("pre", __spreadValues({}, props), React.Children.map(children, renderContent)));
|
|
231
|
+
};
|
|
232
|
+
var YKMarkdown_default = YKMarkdown;
|
|
233
|
+
export {
|
|
234
|
+
YKMarkdown_default as default
|
|
235
|
+
};
|
|
236
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/components/YKMarkdown/index.tsx"],
|
|
4
|
+
"sourcesContent": ["/**\n * Markdown 渲染器组件\n */\n\nimport MarkdownPreview from '@uiw/react-markdown-preview';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport styles from './index.module.less';\n\ninterface HeadingItem {\n id: string;\n text: string;\n level: number;\n}\n\nexport interface YKMarkdownProps {\n markdown: string;\n showToc?: boolean;\n language?: string;\n}\n\nconst YKMarkdown: React.FC<YKMarkdownProps> = ({ markdown, showToc = false }) => {\n const contentRef = useRef<HTMLDivElement>(null);\n const [headings, setHeadings] = useState<HeadingItem[]>([]);\n\n useEffect(() => {\n if (!showToc) {\n setHeadings([]);\n return;\n }\n if (!contentRef.current) return;\n\n const headingElements = contentRef.current.querySelectorAll('h1, h2, h3, h4, h5, h6');\n const headingList: HeadingItem[] = Array.from(headingElements).map((el: HTMLElement) => ({\n id: el.id,\n text: el.textContent || '',\n level: parseInt(el.tagName.charAt(1), 10),\n }));\n\n setHeadings(headingList);\n }, [markdown, showToc]);\n\n const handleScrollTo = useCallback((id: string) => {\n const element = document.getElementById(id);\n if (element) {\n element.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n }, []);\n\n return (\n <div className={styles.container}>\n {showToc && headings.length > 0 && (\n <div className={styles.toc}>\n <h3>目录</h3>\n <ul style={{ paddingLeft: '16px', fontSize: '12px', color: '#666' }}>\n {headings.map((heading) => (\n <li\n key={heading.id}\n style={{\n marginLeft: `${(heading.level - 1) * 12}px`,\n listStyle: 'none',\n marginBottom: '8px',\n }}\n >\n <a\n href={`#${heading.id}`}\n onClick={(e) => {\n e.preventDefault();\n handleScrollTo(heading.id);\n }}\n style={{ color: '#000', textDecoration: 'none' }}\n >\n {heading.text}\n </a>\n </li>\n ))}\n </ul>\n </div>\n )}\n\n <div ref={contentRef} className={styles.content}>\n <MarkdownPreview\n source={markdown}\n components={{ code: Code as React.ComponentType, pre: Pre as React.ComponentType }}\n style={{ padding: 16 }}\n />\n </div>\n\n {showToc && headings.length > 0 && <div className={styles.spacer} />}\n </div>\n );\n};\n\ninterface MermaidInstance {\n render: (id: string, code: string) => Promise<{ svg: string }>;\n}\n\nconst MermaidCode: React.FC<{ code: string; className?: string }> = ({ code, className }) => {\n const demoid = useMemo(() => `dome${parseInt(String(Math.random() * 1e15), 10).toString(36)}`, []);\n const [container, setContainer] = useState<HTMLElement | null>(null);\n const [mermaidInstance, setMermaidInstance] = useState<MermaidInstance | null>(null);\n const isMermaid = className && /^language-mermaid/.test(className.toLocaleLowerCase());\n\n useEffect(() => {\n if (isMermaid && !mermaidInstance) {\n import('mermaid').then((mod) => {\n // @ts-expect-error mermaid module type\n setMermaidInstance(mod.default || mod);\n });\n }\n }, [isMermaid, mermaidInstance]);\n\n const reRender = useCallback(async () => {\n if (container && isMermaid && mermaidInstance) {\n try {\n const str = await mermaidInstance.render(demoid, code);\n container.innerHTML = str.svg;\n } catch (error) {\n container.innerHTML = String(error);\n }\n }\n }, [container, isMermaid, code, demoid, mermaidInstance]);\n\n useEffect(() => {\n reRender();\n }, [reRender]);\n\n const refElement = useCallback((node: HTMLElement | null) => {\n if (node !== null) {\n setContainer(node);\n }\n }, []);\n\n if (isMermaid) {\n return (\n <>\n <code id={demoid} style={{ display: 'none' }} />\n <code ref={refElement} data-name='mermaid' />\n </>\n );\n }\n return <code>{code}</code>;\n};\n\ninterface CodeProps {\n inline?: boolean;\n children?: React.ReactNode;\n className?: string;\n node?: { children?: unknown[] };\n [key: string]: unknown;\n}\n\nconst getCodeString = (children: unknown[]): string => {\n let result = '';\n const traverse = (nodes: unknown[]) => {\n for (const node of nodes) {\n if (typeof node === 'object' && node !== null && 'type' in node) {\n const n = node as { type: string; children?: unknown[]; value?: string };\n if (n.type === 'text' && n.value) {\n result += n.value;\n } else if (n.children) {\n traverse(n.children);\n }\n }\n }\n };\n traverse(children);\n return result;\n};\n\nconst Code: React.FC<CodeProps> = ({ inline, children, className, node, ...props }) => {\n if (inline) {\n return <code {...props}>{children}</code>;\n }\n const code = node?.children\n ? getCodeString(node.children as unknown[])\n : Array.isArray(children)\n ? String(children[0] || '')\n : String(children || '');\n return <MermaidCode code={code} className={className} />;\n};\n\ninterface PreProps {\n children?: React.ReactNode;\n node?: { children?: unknown[] };\n [key: string]: unknown;\n}\n\nconst Pre: React.FC<PreProps> = ({ children, node, ...props }) => {\n let codeStr = '';\n let mermaidCode = '';\n let mermaidClassName = '';\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child)) {\n const childProps = child.props as CodeProps;\n if (childProps?.node) {\n codeStr = getCodeString(childProps.node.children as unknown[]);\n }\n if (childProps?.className?.includes?.('language-mermaid')) {\n mermaidCode = codeStr;\n mermaidClassName = childProps.className || '';\n }\n }\n });\n if (!codeStr && node?.children) {\n codeStr = getCodeString(node.children as unknown[]);\n }\n\n const renderContent = (child: React.ReactNode): React.ReactNode => {\n if (React.isValidElement(child)) {\n const childElement = child as React.ReactElement<{ children?: React.ReactNode; className?: string }>;\n if (childElement.props?.className?.includes?.('language-mermaid')) {\n return <MermaidCode code={mermaidCode} className={mermaidClassName} />;\n }\n return React.cloneElement(childElement, {\n children: React.Children.map(childElement.props?.children, renderContent),\n });\n }\n return child;\n };\n\n return (\n <div className={styles.codeBlock}>\n <pre {...props}>{React.Children.map(children, renderContent)}</pre>\n </div>\n );\n};\n\nexport default YKMarkdown;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["_a", "_b"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
.container {
|
|
2
|
+
display: flex;
|
|
3
|
+
gap: 24px;
|
|
4
|
+
position: relative;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.toc {
|
|
8
|
+
width: 220px;
|
|
9
|
+
flex-shrink: 0;
|
|
10
|
+
position: sticky;
|
|
11
|
+
top: 80px;
|
|
12
|
+
max-height: calc(100vh - 96px);
|
|
13
|
+
overflow-y: auto;
|
|
14
|
+
z-index: 10;
|
|
15
|
+
background-color: #fff;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.content {
|
|
19
|
+
flex: 1;
|
|
20
|
+
min-width: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.codeBlock {
|
|
24
|
+
position: relative;
|
|
25
|
+
|
|
26
|
+
.copyBtn {
|
|
27
|
+
position: absolute;
|
|
28
|
+
top: 8px;
|
|
29
|
+
right: 8px;
|
|
30
|
+
padding: 4px 8px;
|
|
31
|
+
background: rgba(255, 255, 255, 0.1);
|
|
32
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
33
|
+
border-radius: 4px;
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
color: #999;
|
|
36
|
+
font-size: 12px;
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
justify-content: center;
|
|
40
|
+
transition: all 0.2s;
|
|
41
|
+
z-index: 10;
|
|
42
|
+
opacity: 0;
|
|
43
|
+
|
|
44
|
+
&:hover {
|
|
45
|
+
background: rgba(255, 255, 255, 0.2);
|
|
46
|
+
color: #fff;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&.success {
|
|
50
|
+
color: #52c41a;
|
|
51
|
+
border-color: #52c41a;
|
|
52
|
+
opacity: 1;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.codeBlock:hover .copyBtn {
|
|
58
|
+
opacity: 1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.spacer {
|
|
62
|
+
width: 220px;
|
|
63
|
+
flex-shrink: 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@media (max-width: 1024px) {
|
|
67
|
+
.container {
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
gap: 16px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.toc {
|
|
73
|
+
width: 100%;
|
|
74
|
+
position: static;
|
|
75
|
+
max-height: none;
|
|
76
|
+
border-bottom: 1px solid #eee;
|
|
77
|
+
padding-bottom: 16px;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.spacer {
|
|
81
|
+
display: none;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -36,7 +36,7 @@ import * as YkDateRangePickerStories from './index.stories';
|
|
|
36
36
|
|
|
37
37
|
```tsx
|
|
38
38
|
import { useState, useRef } from 'react';
|
|
39
|
-
import { YkDateRangePicker, type DateRangeValue, type YkDateRangePickerRef } from '@yoka/ui';
|
|
39
|
+
import { YkDateRangePicker, type DateRangeValue, type YkDateRangePickerRef } from '@yoka-ui/ui';
|
|
40
40
|
import dayjs from 'dayjs';
|
|
41
41
|
|
|
42
42
|
function App() {
|
|
@@ -138,10 +138,10 @@ onChange={(val) => {
|
|
|
138
138
|
|
|
139
139
|
## ⚠️ 注意事项
|
|
140
140
|
|
|
141
|
-
1. **样式引入**:业务侧使用 `@yoka/ui` 时,需确保引入 Ant Design 全局样式和组件库样式:
|
|
141
|
+
1. **样式引入**:业务侧使用 `@yoka-ui/ui` 时,需确保引入 Ant Design 全局样式和组件库样式:
|
|
142
142
|
```tsx
|
|
143
143
|
import 'antd/dist/reset.css';
|
|
144
|
-
import '@yoka/ui/dist/index.less';
|
|
144
|
+
import '@yoka-ui/ui/dist/index.less';
|
|
145
145
|
```
|
|
146
146
|
|
|
147
147
|
2. **版本要求**:需要 React 18+ 和 Ant Design 5+,与库的版本保持一致。
|
|
@@ -14,7 +14,7 @@ export type GlassSegmentedRadioProps = Omit<React.ComponentPropsWithoutRef<'div'
|
|
|
14
14
|
* 毛玻璃分段单选:滑块随选中项平移,每一档对应独立渐变配色(银/金/铂等);容器在 `html[data-theme="light"]` 下为浅色毛玻璃。
|
|
15
15
|
* 请为分组设置 `aria-label` 或 `aria-labelledby` 以便读屏识别。
|
|
16
16
|
*/
|
|
17
|
-
export declare const GlassSegmentedRadio: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "
|
|
17
|
+
export declare const GlassSegmentedRadio: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "children" | "role" | "onChange"> & {
|
|
18
18
|
options: GlassSegmentOption[];
|
|
19
19
|
value: string;
|
|
20
20
|
onChange: (value: string) => void;
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
var __async = (__this, __arguments, generator) => {
|
|
2
|
+
return new Promise((resolve, reject) => {
|
|
3
|
+
var fulfilled = (value) => {
|
|
4
|
+
try {
|
|
5
|
+
step(generator.next(value));
|
|
6
|
+
} catch (e) {
|
|
7
|
+
reject(e);
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
var rejected = (value) => {
|
|
11
|
+
try {
|
|
12
|
+
step(generator.throw(value));
|
|
13
|
+
} catch (e) {
|
|
14
|
+
reject(e);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
18
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// src/creative/SkillsWriter/index.tsx
|
|
23
|
+
import { CloudDownloadOutlined, FolderOpenOutlined } from "@ant-design/icons";
|
|
24
|
+
import { Button, Card, Checkbox, message, Space, Typography } from "antd";
|
|
25
|
+
import JSZip from "jszip";
|
|
26
|
+
import React, { useState } from "react";
|
|
27
|
+
import styles from "./index.module.less";
|
|
28
|
+
var { Text, Title } = Typography;
|
|
29
|
+
var { Group: CheckboxGroup } = Checkbox;
|
|
30
|
+
var skillsOptions = [
|
|
31
|
+
{
|
|
32
|
+
id: "traue",
|
|
33
|
+
path: ".trae/skills/",
|
|
34
|
+
label: "Traue",
|
|
35
|
+
description: "Traue IDE 的 skills 插件目录"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: "cursor",
|
|
39
|
+
path: ".cursor/skills/",
|
|
40
|
+
label: "Cursor",
|
|
41
|
+
description: "Cursor IDE 的 skills 插件目录"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "codebuddy",
|
|
45
|
+
path: ".codebuddy/skills/",
|
|
46
|
+
label: "CodeBuddy",
|
|
47
|
+
description: "CodeBuddy 的 skills 插件目录"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "claudeCode",
|
|
51
|
+
path: ".claude/skills/",
|
|
52
|
+
label: "Claude Code",
|
|
53
|
+
description: "Claude Code 的 skills 插件目录"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "qwenCode",
|
|
57
|
+
path: ".qwen/skills/",
|
|
58
|
+
label: "Qwen Code",
|
|
59
|
+
description: "Qwen Code 的 skills 插件目录"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: "openAICodex",
|
|
63
|
+
path: ".codex/skills/",
|
|
64
|
+
label: "OpenAI Codex",
|
|
65
|
+
description: "OpenAI Codex 的 skills 插件目录"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: "standard",
|
|
69
|
+
path: ".skills/",
|
|
70
|
+
label: "标准目录",
|
|
71
|
+
description: "标准 skills 配置目录"
|
|
72
|
+
}
|
|
73
|
+
];
|
|
74
|
+
var SkillsWriter = () => {
|
|
75
|
+
const [selectedIds, setSelectedIds] = useState([]);
|
|
76
|
+
const [loading, setLoading] = useState(false);
|
|
77
|
+
const isSupported = typeof window !== "undefined" && "showDirectoryPicker" in window;
|
|
78
|
+
const handleCheckboxChange = (checkedIds) => {
|
|
79
|
+
setSelectedIds(checkedIds);
|
|
80
|
+
};
|
|
81
|
+
const selectedSkills = skillsOptions.filter((opt) => selectedIds.includes(opt.id));
|
|
82
|
+
const createDirectoryHandle = (baseHandle, pathParts) => __async(void 0, null, function* () {
|
|
83
|
+
let currentHandle = baseHandle;
|
|
84
|
+
for (const part of pathParts) {
|
|
85
|
+
try {
|
|
86
|
+
currentHandle = yield currentHandle.getDirectoryHandle(part, { create: true });
|
|
87
|
+
} catch (e) {
|
|
88
|
+
currentHandle = yield currentHandle.getDirectoryHandle(part);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return currentHandle;
|
|
92
|
+
});
|
|
93
|
+
const writeFile = (handle, filePath, content) => __async(void 0, null, function* () {
|
|
94
|
+
const pathParts = filePath.split("/").filter((p) => p);
|
|
95
|
+
const fileName = pathParts.pop();
|
|
96
|
+
const dirHandle = yield createDirectoryHandle(handle, pathParts);
|
|
97
|
+
const fileHandle = yield dirHandle.getFileHandle(fileName, { create: true });
|
|
98
|
+
const writable = yield fileHandle.createWritable();
|
|
99
|
+
yield writable.write(content);
|
|
100
|
+
yield writable.close();
|
|
101
|
+
});
|
|
102
|
+
const downloadAndExtractSkills = () => __async(void 0, null, function* () {
|
|
103
|
+
if (selectedSkills.length === 0) {
|
|
104
|
+
message.error("请至少选择一个工具");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (!("showDirectoryPicker" in window)) {
|
|
108
|
+
message.error("当前浏览器不支持目录选择器");
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const handle = yield window.showDirectoryPicker();
|
|
113
|
+
setLoading(true);
|
|
114
|
+
const response = yield fetch("/skills.zip");
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
throw new Error("下载失败,请稍后重试");
|
|
117
|
+
}
|
|
118
|
+
const blob = yield response.blob();
|
|
119
|
+
const zip = yield JSZip.loadAsync(blob);
|
|
120
|
+
const selectedPaths = selectedSkills.map((s) => s.path);
|
|
121
|
+
const skillsFolderEntry = Object.entries(zip.files).find(
|
|
122
|
+
([path]) => path === "yoka-ui" || path.startsWith("yoka-ui/")
|
|
123
|
+
);
|
|
124
|
+
if (!skillsFolderEntry) {
|
|
125
|
+
throw new Error("压缩包中未找到 yoka-ui 目录");
|
|
126
|
+
}
|
|
127
|
+
let totalCount = 0;
|
|
128
|
+
for (const selectedPath of selectedPaths) {
|
|
129
|
+
const normalizedPath = selectedPath.replace(/^\//, "").replace(/\/$/, "");
|
|
130
|
+
const pathParts = normalizedPath.split("/");
|
|
131
|
+
let currentHandle = handle;
|
|
132
|
+
for (const part of pathParts) {
|
|
133
|
+
try {
|
|
134
|
+
currentHandle = yield currentHandle.getDirectoryHandle(part, { create: true });
|
|
135
|
+
} catch (e) {
|
|
136
|
+
currentHandle = yield currentHandle.getDirectoryHandle(part);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
let skillsHandle;
|
|
140
|
+
try {
|
|
141
|
+
skillsHandle = yield currentHandle.getDirectoryHandle("yoka-ui", { create: true });
|
|
142
|
+
} catch (e) {
|
|
143
|
+
skillsHandle = yield currentHandle.getDirectoryHandle("yoka-ui");
|
|
144
|
+
}
|
|
145
|
+
for (const [filePath, zipEntry] of Object.entries(zip.files)) {
|
|
146
|
+
if (filePath.startsWith("yoka-ui/")) {
|
|
147
|
+
const relativePath = filePath.replace("yoka-ui/", "");
|
|
148
|
+
if (!zipEntry.dir && relativePath) {
|
|
149
|
+
const content = yield zipEntry.async("uint8array");
|
|
150
|
+
yield writeFile(skillsHandle, relativePath, content);
|
|
151
|
+
totalCount++;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
message.success(`成功添加 ${totalCount} 个文件到项目`);
|
|
157
|
+
} catch (err) {
|
|
158
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
159
|
+
} else {
|
|
160
|
+
console.error("添加到项目失败:", err);
|
|
161
|
+
message.error(err instanceof Error ? err.message : "添加到项目失败");
|
|
162
|
+
}
|
|
163
|
+
} finally {
|
|
164
|
+
setLoading(false);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
return /* @__PURE__ */ React.createElement("div", { className: styles.skillsWriter }, /* @__PURE__ */ React.createElement(Card, { className: styles.card }, /* @__PURE__ */ React.createElement("div", { className: styles.header }, /* @__PURE__ */ React.createElement(CloudDownloadOutlined, { style: { fontSize: 20, color: "#1890ff" } }), /* @__PURE__ */ React.createElement(Title, { level: 5, style: { margin: 0, fontSize: 20, fontWeight: 600 } }, "Skills 同步工具")), /* @__PURE__ */ React.createElement(Text, { type: "secondary", style: { display: "block", marginBottom: 16 } }, "将 YokaUI Skills 同步到本地 IDE 的插件目录中"), /* @__PURE__ */ React.createElement(
|
|
168
|
+
CheckboxGroup,
|
|
169
|
+
{
|
|
170
|
+
value: selectedIds,
|
|
171
|
+
onChange: (values) => handleCheckboxChange(values),
|
|
172
|
+
style: { display: "flex", flexDirection: "column", gap: 8 }
|
|
173
|
+
},
|
|
174
|
+
skillsOptions.map((option) => /* @__PURE__ */ React.createElement(Checkbox, { key: option.id, value: option.id, style: { alignItems: "flex-start" } }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column" } }, /* @__PURE__ */ React.createElement(Space, null, /* @__PURE__ */ React.createElement(Text, { strong: true }, option.label), /* @__PURE__ */ React.createElement(Text, { type: "secondary", style: { fontSize: 12 } }, "(", option.path, ")")), /* @__PURE__ */ React.createElement(Text, { type: "secondary", style: { fontSize: 12, marginTop: 2 } }, option.description))))
|
|
175
|
+
), /* @__PURE__ */ React.createElement("div", { className: styles.actions }, /* @__PURE__ */ React.createElement(Space, { direction: "vertical", style: { width: "100%" } }, /* @__PURE__ */ React.createElement(Space, null, /* @__PURE__ */ React.createElement(
|
|
176
|
+
Button,
|
|
177
|
+
{
|
|
178
|
+
type: "primary",
|
|
179
|
+
icon: /* @__PURE__ */ React.createElement(FolderOpenOutlined, null),
|
|
180
|
+
onClick: downloadAndExtractSkills,
|
|
181
|
+
loading,
|
|
182
|
+
disabled: selectedSkills.length === 0 || !isSupported
|
|
183
|
+
},
|
|
184
|
+
"同步到本地"
|
|
185
|
+
), !isSupported && /* @__PURE__ */ React.createElement(Text, { type: "warning", style: { fontSize: 12 } }, "需要 HTTPS 或 localhost 环境,请手动下载")), /* @__PURE__ */ React.createElement(Space, null, /* @__PURE__ */ React.createElement(Button, { icon: /* @__PURE__ */ React.createElement(CloudDownloadOutlined, null), href: "/skills.zip", download: true }, "手动下载 skills.zip"), /* @__PURE__ */ React.createElement(Text, { type: "secondary", style: { fontSize: 12 } }, "解压到对应工具的 skills 目录"))))));
|
|
186
|
+
};
|
|
187
|
+
var SkillsWriter_default = SkillsWriter;
|
|
188
|
+
export {
|
|
189
|
+
SkillsWriter_default as default
|
|
190
|
+
};
|
|
191
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/creative/SkillsWriter/index.tsx"],
|
|
4
|
+
"sourcesContent": ["import { CloudDownloadOutlined, FolderOpenOutlined } from '@ant-design/icons';\nimport { Button, Card, Checkbox, message, Space, Typography } from 'antd';\nimport JSZip from 'jszip';\nimport React, { useState } from 'react';\nimport styles from './index.module.less';\n\nconst { Text, Title } = Typography;\nconst { Group: CheckboxGroup } = Checkbox;\n\n// 确认支持 skills 的工具及其路径\nconst skillsOptions = [\n {\n id: 'traue',\n path: '.trae/skills/',\n label: 'Traue',\n description: 'Traue IDE 的 skills 插件目录',\n },\n {\n id: 'cursor',\n path: '.cursor/skills/',\n label: 'Cursor',\n description: 'Cursor IDE 的 skills 插件目录',\n },\n {\n id: 'codebuddy',\n path: '.codebuddy/skills/',\n label: 'CodeBuddy',\n description: 'CodeBuddy 的 skills 插件目录',\n },\n {\n id: 'claudeCode',\n path: '.claude/skills/',\n label: 'Claude Code',\n description: 'Claude Code 的 skills 插件目录',\n },\n {\n id: 'qwenCode',\n path: '.qwen/skills/',\n label: 'Qwen Code',\n description: 'Qwen Code 的 skills 插件目录',\n },\n {\n id: 'openAICodex',\n path: '.codex/skills/',\n label: 'OpenAI Codex',\n description: 'OpenAI Codex 的 skills 插件目录',\n },\n {\n id: 'standard',\n path: '.skills/',\n label: '标准目录',\n description: '标准 skills 配置目录',\n },\n];\n\nconst SkillsWriter: React.FC = () => {\n const [selectedIds, setSelectedIds] = useState<string[]>([]);\n const [loading, setLoading] = useState(false);\n\n const isSupported = typeof window !== 'undefined' && 'showDirectoryPicker' in window;\n\n const handleCheckboxChange = (checkedIds: string[]) => {\n setSelectedIds(checkedIds);\n };\n\n const selectedSkills = skillsOptions.filter((opt) => selectedIds.includes(opt.id));\n\n // 递归创建目录\n const createDirectoryHandle = async (baseHandle: FileSystemDirectoryHandle, pathParts: string[]) => {\n let currentHandle = baseHandle;\n for (const part of pathParts) {\n try {\n currentHandle = await currentHandle.getDirectoryHandle(part, { create: true });\n } catch {\n currentHandle = await currentHandle.getDirectoryHandle(part);\n }\n }\n return currentHandle;\n };\n\n // 递归写入文件\n const writeFile = async (handle: FileSystemDirectoryHandle, filePath: string, content: Uint8Array) => {\n const pathParts = filePath.split('/').filter((p) => p);\n const fileName = pathParts.pop()!;\n const dirHandle = await createDirectoryHandle(handle, pathParts);\n const fileHandle = await dirHandle.getFileHandle(fileName, { create: true });\n const writable = await fileHandle.createWritable();\n await writable.write(content as BufferSource);\n await writable.close();\n };\n\n // 下载并解压 skills.zip\n const downloadAndExtractSkills = async () => {\n if (selectedSkills.length === 0) {\n message.error('请至少选择一个工具');\n return;\n }\n\n // 检查是否支持目录选择器\n if (!('showDirectoryPicker' in window)) {\n message.error('当前浏览器不支持目录选择器');\n return;\n }\n\n try {\n // 1. 先让用户选择目录\n const handle = await (window as Window & { showDirectoryPicker?: () => Promise<FileSystemDirectoryHandle> })\n .showDirectoryPicker!();\n\n // 2. 用户选择目录后开始处理\n setLoading(true);\n\n // 3. 下载 skills.zip\n const response = await fetch('/skills.zip');\n if (!response.ok) {\n throw new Error('下载失败,请稍后重试');\n }\n const blob = await response.blob();\n\n // 4. 解压 zip 文件,把 skills/yoka-ui 文件夹写入到用户选择的路径下\n const zip = await JSZip.loadAsync(blob);\n\n // 获取用户选择的路径列表\n const selectedPaths = selectedSkills.map((s) => s.path);\n\n // 找到 zip 中的 yoka-ui 文件夹\n const skillsFolderEntry = Object.entries(zip.files).find(\n ([path]) => path === 'yoka-ui' || path.startsWith('yoka-ui/'),\n );\n\n if (!skillsFolderEntry) {\n throw new Error('压缩包中未找到 yoka-ui 目录');\n }\n\n // 对每个用户选择的路径,创建 yoka-ui 文件夹并写入内容\n let totalCount = 0;\n\n for (const selectedPath of selectedPaths) {\n // 在用户选择的路径下创建 yoka-ui 文件夹\n const normalizedPath = selectedPath.replace(/^\\//, '').replace(/\\/$/, '');\n const pathParts = normalizedPath.split('/');\n\n let currentHandle = handle;\n for (const part of pathParts) {\n try {\n currentHandle = await currentHandle.getDirectoryHandle(part, { create: true });\n } catch {\n currentHandle = await currentHandle.getDirectoryHandle(part);\n }\n }\n\n // 创建 yoka-ui 文件夹\n let skillsHandle: FileSystemDirectoryHandle;\n try {\n skillsHandle = await currentHandle.getDirectoryHandle('yoka-ui', { create: true });\n } catch {\n skillsHandle = await currentHandle.getDirectoryHandle('yoka-ui');\n }\n\n // 遍历 zip 中 yoka-ui 文件夹下的所有文件\n for (const [filePath, zipEntry] of Object.entries(zip.files)) {\n if (filePath.startsWith('yoka-ui/')) {\n const relativePath = filePath.replace('yoka-ui/', '');\n\n if (!zipEntry.dir && relativePath) {\n // 写入文件\n const content = await zipEntry.async('uint8array');\n await writeFile(skillsHandle, relativePath, content);\n totalCount++;\n }\n }\n }\n }\n\n message.success(`成功添加 ${totalCount} 个文件到项目`);\n } catch (err: unknown) {\n if (err instanceof Error && err.name === 'AbortError') {\n // 用户取消选择,不显示任何消息\n } else {\n console.error('添加到项目失败:', err);\n message.error(err instanceof Error ? err.message : '添加到项目失败');\n }\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <div className={styles.skillsWriter}>\n <Card className={styles.card}>\n <div className={styles.header}>\n <CloudDownloadOutlined style={{ fontSize: 20, color: '#1890ff' }} />\n <Title level={5} style={{ margin: 0, fontSize: 20, fontWeight: 600 }}>\n Skills 同步工具\n </Title>\n </div>\n\n <Text type='secondary' style={{ display: 'block', marginBottom: 16 }}>\n 将 YokaUI Skills 同步到本地 IDE 的插件目录中\n </Text>\n\n <CheckboxGroup\n value={selectedIds}\n onChange={(values) => handleCheckboxChange(values as string[])}\n style={{ display: 'flex', flexDirection: 'column', gap: 8 }}\n >\n {skillsOptions.map((option) => (\n <Checkbox key={option.id} value={option.id} style={{ alignItems: 'flex-start' }}>\n <div style={{ display: 'flex', flexDirection: 'column' }}>\n <Space>\n <Text strong>{option.label}</Text>\n <Text type='secondary' style={{ fontSize: 12 }}>\n ({option.path})\n </Text>\n </Space>\n <Text type='secondary' style={{ fontSize: 12, marginTop: 2 }}>\n {option.description}\n </Text>\n </div>\n </Checkbox>\n ))}\n </CheckboxGroup>\n\n <div className={styles.actions}>\n <Space direction='vertical' style={{ width: '100%' }}>\n <Space>\n <Button\n type='primary'\n icon={<FolderOpenOutlined />}\n onClick={downloadAndExtractSkills}\n loading={loading}\n disabled={selectedSkills.length === 0 || !isSupported}\n >\n 同步到本地\n </Button>\n {!isSupported && (\n <Text type='warning' style={{ fontSize: 12 }}>\n 需要 HTTPS 或 localhost 环境,请手动下载\n </Text>\n )}\n </Space>\n <Space>\n <Button icon={<CloudDownloadOutlined />} href='/skills.zip' download>\n 手动下载 skills.zip\n </Button>\n <Text type='secondary' style={{ fontSize: 12 }}>\n 解压到对应工具的 skills 目录\n </Text>\n </Space>\n </Space>\n </div>\n </Card>\n </div>\n );\n};\n\nexport default SkillsWriter;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
.skillsWriter {
|
|
2
|
+
margin: 24px 0;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.card {
|
|
6
|
+
border-radius: 8px;
|
|
7
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.header {
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: 8px;
|
|
14
|
+
margin-bottom: 16px;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.actions {
|
|
18
|
+
margin-top: 24px;
|
|
19
|
+
padding-top: 16px;
|
|
20
|
+
border-top: 1px solid #f0f0f0;
|
|
21
|
+
}
|