@lijinmei-810/dev-inspector 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -37,6 +37,40 @@ var import_lucide_react = require("lucide-react");
37
37
  // src/DevInspectorProvider.tsx
38
38
  var import_react = require("react");
39
39
 
40
+ // src/tokens/typography.json
41
+ var typography_default = {
42
+ title: {
43
+ fontSize: "15px",
44
+ fontWeight: "700",
45
+ lineHeight: "1.4",
46
+ color: "#111827"
47
+ },
48
+ sectionLabel: {
49
+ fontSize: "12px",
50
+ fontWeight: "700",
51
+ lineHeight: "1.4",
52
+ color: "#374151"
53
+ },
54
+ body: {
55
+ fontSize: "12px",
56
+ fontWeight: "400",
57
+ lineHeight: "1.5",
58
+ color: "#6b7280"
59
+ },
60
+ meta: {
61
+ fontSize: "11px",
62
+ fontWeight: "600",
63
+ lineHeight: "1.35",
64
+ color: "#94a3b8"
65
+ },
66
+ tinyBadge: {
67
+ fontSize: "10px",
68
+ fontWeight: "700",
69
+ lineHeight: "1.2",
70
+ color: "#64748b"
71
+ }
72
+ };
73
+
40
74
  // src/config.ts
41
75
  var FALLBACK_TYPOGRAPHY_STYLES = [
42
76
  {
@@ -136,6 +170,7 @@ var FALLBACK_SHADOW_TOKENS = [
136
170
  var FALLBACK_TOKENS = {
137
171
  colorPalette: [],
138
172
  tokenLabels: {},
173
+ inspectorTypography: typography_default,
139
174
  radiusPresets: [
140
175
  { label: "\u65E0", sub: "", value: "0px", token: "" },
141
176
  { label: "S", sub: "4px", value: "4px", token: "" },
@@ -306,12 +341,22 @@ function handleArrowKeyStep(event, onStep, onEnter) {
306
341
  }
307
342
  if (event.key === "Enter") onEnter?.();
308
343
  }
344
+ function renderSubmitLabel(submitMsg) {
345
+ if (submitMsg === "\u5DF2\u590D\u5236") {
346
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "di-btn-save-content", children: [
347
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Check, { size: 14, strokeWidth: 2.4, "aria-hidden": "true" }),
348
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u5DF2\u590D\u5236" })
349
+ ] });
350
+ }
351
+ return submitMsg || "\u53D1\u9001\u7ED9AI";
352
+ }
309
353
  var COLOR_PROPS = [
310
354
  { label: "\u80CC\u666F\u8272", prop: "background-color" }
311
355
  ];
312
356
  function getColorLabel(val, colorPalette) {
357
+ const normalizedVal = resolveColorValue(val);
313
358
  for (const g of colorPalette) {
314
- const found = g.colors.find((c) => c.val === val);
359
+ const found = g.colors.find((c) => resolveColorValue(c.val) === normalizedVal);
315
360
  if (found) return `${g.group}\xB7${found.label}`;
316
361
  }
317
362
  return null;
@@ -521,10 +566,26 @@ function isTextEntryTarget(target) {
521
566
  function normalizeColor(val) {
522
567
  const raw = val.trim();
523
568
  if (raw === "transparent" || /^rgba\(\s*0,\s*0,\s*0,\s*0\s*\)$/i.test(raw)) return "transparent";
524
- const m = val.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
569
+ const m = raw.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)$/);
525
570
  if (m) return "#" + [m[1], m[2], m[3]].map((n) => parseInt(n).toString(16).padStart(2, "0")).join("");
571
+ if (/^#[0-9a-f]{3,8}$/i.test(raw)) return raw.toLowerCase();
526
572
  return raw;
527
573
  }
574
+ function resolveColorValue(val) {
575
+ const normalized = normalizeColor(val || "");
576
+ if (!normalized || normalized === "transparent") return normalized || "transparent";
577
+ if (/^#[0-9a-f]{6}$/i.test(normalized)) return normalized;
578
+ if (typeof document === "undefined" || !document.body) return normalized;
579
+ const probe = document.createElement("div");
580
+ probe.style.color = normalized;
581
+ probe.style.position = "fixed";
582
+ probe.style.opacity = "0";
583
+ probe.style.pointerEvents = "none";
584
+ document.body.appendChild(probe);
585
+ const computed = normalizeColor(getComputedStyle(probe).color.trim());
586
+ probe.remove();
587
+ return computed || normalized;
588
+ }
528
589
  function isTransparentColor(val) {
529
590
  return normalizeColor(val || "transparent") === "transparent";
530
591
  }
@@ -667,7 +728,7 @@ function getComponentClasses(el) {
667
728
  if (primitiveClasses.length) return primitiveClasses;
668
729
  const classes = getClasses(el);
669
730
  const cardBaseClass = classes.find(
670
- (className) => /(^|[-_])card([-_]|$)/i.test(className) && !className.includes("--")
731
+ (className) => isCardRootClass(className) && !className.includes("--")
671
732
  );
672
733
  if (cardBaseClass) return [cardBaseClass];
673
734
  const badgeBaseClass = classes.find(
@@ -726,6 +787,7 @@ var TEXT_ONLY_TAGS = /* @__PURE__ */ new Set([
726
787
  var TEXT_SEMANTIC_CLASS_RE = /(^|[-_])(caption|copy|desc|description|eyebrow|heading|label|subtitle|text|title)([-_]|$)/i;
727
788
  var STRUCTURAL_CONTAINER_CLASS_RE = /(^|[-_])(area|block|card|container|content|group|grid|item|layout|list|panel|row|section|shell|stack|zone)([-_]|$)/i;
728
789
  var PAGE_SHELL_CLASS_RE = /(^|[-_])(app|page|root|screen|shell|workspace)([-_]|$)/i;
790
+ var CARD_ROOT_CLASS_NAMES = /* @__PURE__ */ new Set(["task-card"]);
729
791
  var TEXT_GROUP_EXCLUDED_SELECTOR = [
730
792
  "button",
731
793
  "input",
@@ -756,6 +818,12 @@ function hasTextSemanticClass(el) {
756
818
  (className) => !isStateClass(className) && !/^lucide(-|$)/.test(className) && TEXT_SEMANTIC_CLASS_RE.test(className)
757
819
  );
758
820
  }
821
+ function getRegisteredComponentType(el) {
822
+ return (el.getAttribute("data-component") || "").trim();
823
+ }
824
+ function isCardRootClass(className) {
825
+ return CARD_ROOT_CLASS_NAMES.has(className) || /(^|[-_])card($|--)/i.test(className);
826
+ }
759
827
  function hasStructuralContainerClass(el) {
760
828
  return getClasses(el).some(
761
829
  (className) => !isStateClass(className) && STRUCTURAL_CONTAINER_CLASS_RE.test(className)
@@ -891,6 +959,17 @@ function getInspectorComponentMeta(el) {
891
959
  const tag = el.tagName.toLowerCase();
892
960
  const classes = getClasses(el);
893
961
  const componentClasses = getComponentClasses(el);
962
+ const registeredComponentType = getRegisteredComponentType(el);
963
+ if (registeredComponentType) {
964
+ const type = registeredComponentType;
965
+ return {
966
+ name: componentClasses[0] ?? type,
967
+ type,
968
+ layer: "Component",
969
+ variant: inferVariantFromClasses(classes),
970
+ state: inferStateFromElement(el, classes)
971
+ };
972
+ }
894
973
  if (tag === "svg" && classes.includes("lucide")) {
895
974
  const iconClass = classes.find((className) => /^lucide-/.test(className));
896
975
  return {
@@ -911,9 +990,9 @@ function getInspectorComponentMeta(el) {
911
990
  state: inferStateFromElement(el, classes)
912
991
  };
913
992
  }
914
- if (classIncludes(classes, /(^|[-_])card([-_]|$)/i)) {
993
+ if (classes.some(isCardRootClass)) {
915
994
  return {
916
- name: componentClasses.find((className) => /card/i.test(className)) ?? componentClasses[0] ?? "card",
995
+ name: componentClasses.find((className) => isCardRootClass(className)) ?? componentClasses[0] ?? "card",
917
996
  type: "Card",
918
997
  layer: "Component",
919
998
  variant: inferCardVariant(classes),
@@ -1541,6 +1620,14 @@ function canPersistSelector(el, scope) {
1541
1620
  function isInsidePanel(el) {
1542
1621
  return el.closest(".di-panel") !== null || el.closest(".di-trigger") !== null || el.closest(".di-label") !== null;
1543
1622
  }
1623
+ function resolveSelectionTarget(raw) {
1624
+ let cursor = raw;
1625
+ while (cursor && cursor !== document.body && cursor !== document.documentElement) {
1626
+ if (getInspectorComponentMeta(cursor)) return cursor;
1627
+ cursor = cursor.parentElement;
1628
+ }
1629
+ return raw;
1630
+ }
1544
1631
  function scanTokenMap() {
1545
1632
  const map = {};
1546
1633
  try {
@@ -1571,6 +1658,12 @@ function getComputedColor(el, prop) {
1571
1658
  function getComputedRadius(el) {
1572
1659
  return getComputedStyle(el).getPropertyValue("border-radius").trim();
1573
1660
  }
1661
+ function getComputedPadding(el) {
1662
+ const cs = getComputedStyle(el);
1663
+ const t = cs.paddingTop, r = cs.paddingRight, b = cs.paddingBottom, l = cs.paddingLeft;
1664
+ if (t === r && r === b && b === l) return t;
1665
+ return `${t} ${r} ${b} ${l}`;
1666
+ }
1574
1667
  function parseTranslate(val) {
1575
1668
  const raw = (val || "none").trim();
1576
1669
  if (!raw || raw === "none") return { x: 0, y: 0 };
@@ -2014,6 +2107,93 @@ function getTextContent(el) {
2014
2107
  const text = Array.from(el.childNodes).filter((n) => n.nodeType === Node.TEXT_NODE).map((n) => n.textContent ?? "").join("").trim();
2015
2108
  return text.length > 0 ? el.textContent?.trim() ?? null : null;
2016
2109
  }
2110
+ function MatchBadge({
2111
+ label,
2112
+ tooltip,
2113
+ tone
2114
+ }) {
2115
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2116
+ "span",
2117
+ {
2118
+ className: `di-match-badge di-match-badge--${tone}`,
2119
+ title: tooltip,
2120
+ "data-tooltip": tooltip,
2121
+ tabIndex: 0,
2122
+ children: label
2123
+ }
2124
+ );
2125
+ }
2126
+ function getComputedMargin(el) {
2127
+ const cs = getComputedStyle(el);
2128
+ const t = cs.marginTop, r = cs.marginRight, b = cs.marginBottom, l = cs.marginLeft;
2129
+ if (t === r && r === b && b === l) return t;
2130
+ return `${t} ${r} ${b} ${l}`;
2131
+ }
2132
+ function formatReadableColor(value) {
2133
+ if (!value || isTransparentColor(value)) return "\u900F\u660E";
2134
+ return formatColorDisplay(resolveColorValue(value));
2135
+ }
2136
+ function getComponentElementStyleSummary(el) {
2137
+ const cs = getComputedStyle(el);
2138
+ const parts = [];
2139
+ const text = getTextContent(el);
2140
+ const tag = el.tagName.toLowerCase();
2141
+ const borderWidth = getNumericCssValue(cs.borderTopWidth);
2142
+ const radius = cs.borderRadius.trim();
2143
+ const bg = cs.backgroundColor.trim();
2144
+ const color = cs.color.trim();
2145
+ if (text || /^(p|span|a|button|label|h1|h2|h3|h4|h5|h6|li|strong|em)$/i.test(tag)) {
2146
+ parts.push(`\u5B57 ${formatLengthControlValue(cs.fontSize)}`);
2147
+ parts.push(`\u91CD ${cs.fontWeight}`);
2148
+ parts.push(`\u8272 ${formatReadableColor(color)}`);
2149
+ }
2150
+ if (!isTransparentColor(bg)) {
2151
+ parts.push(`\u80CC\u666F ${formatReadableColor(bg)}`);
2152
+ }
2153
+ if (borderWidth > 0 && !isTransparentColor(cs.borderTopColor)) {
2154
+ parts.push(`\u63CF\u8FB9 ${formatLengthControlValue(cs.borderTopWidth)} ${formatReadableColor(cs.borderTopColor)}`);
2155
+ }
2156
+ if (!isZeroLengthValue(radius)) {
2157
+ parts.push(`\u5706\u89D2 ${formatLengthControlValue(radius)}`);
2158
+ }
2159
+ return parts.join(" / ") || "\u65E0\u660E\u663E\u6837\u5F0F";
2160
+ }
2161
+ function getComponentElementSpacingSummary(el) {
2162
+ const cs = getComputedStyle(el);
2163
+ const parts = [];
2164
+ const paddingSummary = getSpaceSummary("padding", getComputedPadding(el));
2165
+ const marginSummary = getSpaceSummary("margin", getComputedMargin(el));
2166
+ const gapSummary = canControlElementGap(el) ? getSpaceSummary("gap", cs.gap.trim()) : "";
2167
+ if (paddingSummary) parts.push(`\u5185\u8FB9\u8DDD ${paddingSummary}`);
2168
+ if (marginSummary) parts.push(`\u5916\u8FB9\u8DDD ${marginSummary}`);
2169
+ if (gapSummary) parts.push(`\u5143\u7D20\u95F4\u8DDD ${gapSummary.replace(/^gap\s*/i, "")}`);
2170
+ return parts.join(" / ") || "\u65E0\u989D\u5916\u95F4\u8DDD";
2171
+ }
2172
+ function getComponentElementStyleStatus(el, tokenMap, colorPalette, tokenLabels, typographyTokens) {
2173
+ const cs = getComputedStyle(el);
2174
+ const colorInfo = getDisplayLabel(normalizeColor(cs.color), tokenMap, colorPalette, tokenLabels);
2175
+ const backgroundInfo = getDisplayLabel(normalizeColor(cs.backgroundColor), tokenMap, colorPalette, tokenLabels);
2176
+ const borderInfo = getDisplayLabel(normalizeColor(cs.borderTopColor), tokenMap, colorPalette, tokenLabels);
2177
+ const typographyMatched = Boolean(getTypographyToken(cs.fontSize.trim(), cs.fontWeight.trim(), normalizeColor(cs.color), typographyTokens));
2178
+ if (typographyMatched) return "token";
2179
+ if (!colorInfo.isHardcoded || !backgroundInfo.isHardcoded || !borderInfo.isHardcoded) return "token";
2180
+ return "raw";
2181
+ }
2182
+ function getComponentElementSpacingStatus(el, spaceSteps) {
2183
+ const cs = getComputedStyle(el);
2184
+ const paddingValue = getComputedPadding(el);
2185
+ const marginValue = getComputedMargin(el);
2186
+ const gapValue = cs.gap.trim();
2187
+ const paddingSummary = getSpaceSummary("padding", paddingValue);
2188
+ const marginSummary = getSpaceSummary("margin", marginValue);
2189
+ const gapSummary = canControlElementGap(el) ? getSpaceSummary("gap", gapValue) : "";
2190
+ const hasSpacing = Boolean(paddingSummary || marginSummary || gapSummary);
2191
+ if (!hasSpacing) return null;
2192
+ const paddingMatched = !paddingSummary || Boolean(getSpaceStepMatch("padding", paddingValue, spaceSteps));
2193
+ const marginMatched = !marginSummary || Boolean(getSpaceStepMatch("margin", marginValue, spaceSteps));
2194
+ const gapMatched = !gapSummary || Boolean(getSpaceStepMatch("gap", gapValue, spaceSteps));
2195
+ return paddingMatched && marginMatched && gapMatched ? "token" : "raw";
2196
+ }
2017
2197
  var TOKEN_TYPES = [
2018
2198
  { key: "bg", label: "\u80CC\u666F\u8272", code: "bg" },
2019
2199
  { key: "text", label: "\u6587\u5B57\u8272", code: "text" },
@@ -2037,9 +2217,15 @@ var TOKEN_STATES = [
2037
2217
  { key: "warning", label: "\u8B66\u544A\u6001", code: "warning" }
2038
2218
  ];
2039
2219
  function ColorDropdown({ value, onChange, onClose, onAddToken, pos, colorPalette }) {
2040
- const initHex = value.startsWith("#") ? value : "#6b7280";
2220
+ const resolvedValue = resolveColorValue(value);
2221
+ const initHex = /^#[0-9a-f]{6}$/i.test(resolvedValue) ? resolvedValue : "#6b7280";
2222
+ const initAlpha = (() => {
2223
+ const rgbaMatch = value.match(/^rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)$/i);
2224
+ if (!rgbaMatch) return 100;
2225
+ return Math.max(0, Math.min(100, Math.round(parseFloat(rgbaMatch[4]) * 100)));
2226
+ })();
2041
2227
  const [hexInput, setHexInput] = (0, import_react2.useState)(initHex);
2042
- const [alpha, setAlpha] = (0, import_react2.useState)(100);
2228
+ const [alpha, setAlpha] = (0, import_react2.useState)(initAlpha);
2043
2229
  const customColorInputRef = (0, import_react2.useRef)(null);
2044
2230
  function buildColor(hex, a) {
2045
2231
  const m = hex.match(/^#([0-9a-f]{6})$/i);
@@ -2309,10 +2495,11 @@ function AddTokenModal({ value, cssProp, elementClasses, onClose, onConfirm, col
2309
2495
  }
2310
2496
  function getDisplayLabel(val, tokenMap, colorPalette, tokenLabels) {
2311
2497
  if (isTransparentColor(val)) return { label: "\u65E0", sub: "", isHardcoded: true };
2312
- const displayVal = formatColorDisplay(val);
2313
- const paletteLabel = getColorLabel(val, colorPalette);
2498
+ const resolvedVal = resolveColorValue(val);
2499
+ const displayVal = formatColorDisplay(resolvedVal);
2500
+ const paletteLabel = getColorLabel(resolvedVal, colorPalette);
2314
2501
  if (paletteLabel) return { label: paletteLabel, sub: displayVal, isHardcoded: false };
2315
- const token = tokenMap[val];
2502
+ const token = tokenMap[val] ?? tokenMap[resolvedVal];
2316
2503
  if (token) return { label: tokenLabels[token] ?? token.replace("--", ""), sub: displayVal, isHardcoded: false };
2317
2504
  return { label: displayVal, sub: "", isHardcoded: true };
2318
2505
  }
@@ -2595,6 +2782,7 @@ function InspectorPanel({
2595
2782
  const {
2596
2783
  colorPalette,
2597
2784
  tokenLabels,
2785
+ inspectorTypography,
2598
2786
  radiusPresets,
2599
2787
  spaceSteps,
2600
2788
  borderWidthSteps,
@@ -2609,6 +2797,28 @@ function InspectorPanel({
2609
2797
  { cssVar: "", value: "none", label: "\u65E0", usage: "\u4E0D\u4F7F\u7528\u9634\u5F71" },
2610
2798
  ...shadowTokens
2611
2799
  ];
2800
+ const inspectorTypographyVars = {
2801
+ "--di-text-title-size": inspectorTypography.title.fontSize,
2802
+ "--di-text-title-weight": inspectorTypography.title.fontWeight,
2803
+ "--di-text-title-line-height": inspectorTypography.title.lineHeight,
2804
+ "--di-text-title-color": inspectorTypography.title.color,
2805
+ "--di-text-label-size": inspectorTypography.sectionLabel.fontSize,
2806
+ "--di-text-label-weight": inspectorTypography.sectionLabel.fontWeight,
2807
+ "--di-text-label-line-height": inspectorTypography.sectionLabel.lineHeight,
2808
+ "--di-text-label-color": inspectorTypography.sectionLabel.color,
2809
+ "--di-text-body-size": inspectorTypography.body.fontSize,
2810
+ "--di-text-body-weight": inspectorTypography.body.fontWeight,
2811
+ "--di-text-body-line-height": inspectorTypography.body.lineHeight,
2812
+ "--di-text-body-color": inspectorTypography.body.color,
2813
+ "--di-text-meta-size": inspectorTypography.meta.fontSize,
2814
+ "--di-text-meta-weight": inspectorTypography.meta.fontWeight,
2815
+ "--di-text-meta-line-height": inspectorTypography.meta.lineHeight,
2816
+ "--di-text-meta-color": inspectorTypography.meta.color,
2817
+ "--di-text-tiny-badge-size": inspectorTypography.tinyBadge.fontSize,
2818
+ "--di-text-tiny-badge-weight": inspectorTypography.tinyBadge.fontWeight,
2819
+ "--di-text-tiny-badge-line-height": inspectorTypography.tinyBadge.lineHeight,
2820
+ "--di-text-tiny-badge-color": inspectorTypography.tinyBadge.color
2821
+ };
2612
2822
  const [isEditing, setIsEditing] = (0, import_react2.useState)(false);
2613
2823
  const panelElRef = (0, import_react2.useRef)(null);
2614
2824
  const [selected, setSelected] = (0, import_react2.useState)(targetEl);
@@ -2708,6 +2918,9 @@ function InspectorPanel({
2708
2918
  const [cardVariantVal, setCardVariantVal] = (0, import_react2.useState)("default");
2709
2919
  const [cardVariantClassVal, setCardVariantClassVal] = (0, import_react2.useState)("");
2710
2920
  const [pendingCardVariant, setPendingCardVariant] = (0, import_react2.useState)("");
2921
+ const [componentInfoOpen, setComponentInfoOpen] = (0, import_react2.useState)(false);
2922
+ const [annotationOpen, setAnnotationOpen] = (0, import_react2.useState)(false);
2923
+ const [annotationText, setAnnotationText] = (0, import_react2.useState)("");
2711
2924
  const [componentMakerSourceMode, setComponentMakerSourceMode] = (0, import_react2.useState)("new");
2712
2925
  const [componentMakerAction, setComponentMakerAction] = (0, import_react2.useState)("create-current");
2713
2926
  const [componentSpecDraft, setComponentSpecDraft] = (0, import_react2.useState)(EMPTY_COMPONENT_SPEC_DRAFT);
@@ -2742,6 +2955,8 @@ function InspectorPanel({
2742
2955
  const [selectedLibraryComponentVariantId, setSelectedLibraryComponentVariantId] = (0, import_react2.useState)("");
2743
2956
  const [libraryTokenForm, setLibraryTokenForm] = (0, import_react2.useState)(null);
2744
2957
  const [libraryComponentForm, setLibraryComponentForm] = (0, import_react2.useState)(null);
2958
+ const [libraryComponentImportOpen, setLibraryComponentImportOpen] = (0, import_react2.useState)(false);
2959
+ const [libraryComponentImportMsg, setLibraryComponentImportMsg] = (0, import_react2.useState)("");
2745
2960
  const [libraryCustomTokens, setLibraryCustomTokens] = (0, import_react2.useState)([]);
2746
2961
  const [libraryTokenOverrides, setLibraryTokenOverrides] = (0, import_react2.useState)({});
2747
2962
  const [libraryDeletedTokenIds, setLibraryDeletedTokenIds] = (0, import_react2.useState)({});
@@ -2758,6 +2973,9 @@ function InspectorPanel({
2758
2973
  (0, import_react2.useEffect)(() => {
2759
2974
  localDraftsRef.current = localDrafts;
2760
2975
  }, [localDrafts]);
2976
+ (0, import_react2.useEffect)(() => {
2977
+ setComponentInfoOpen(false);
2978
+ }, [selected]);
2761
2979
  const formatStyleIntentSummary = (0, import_react2.useCallback)((r) => ({
2762
2980
  pendingCount: r.pendingCount ?? 0,
2763
2981
  latestPending: r.latestPending ? {
@@ -2806,6 +3024,50 @@ function InspectorPanel({
2806
3024
  return next;
2807
3025
  });
2808
3026
  }
3027
+ function getAnnotationTargetInfo(el) {
3028
+ const componentMeta2 = getInspectorComponentMeta(el);
3029
+ const selector = getSelectorForScope(el, "current");
3030
+ return {
3031
+ key: `current:${selector}`,
3032
+ selector,
3033
+ targetLabel: getTargetDisplayLabel(el, componentMeta2),
3034
+ scopeLabel: "\u5F53\u524D\u5143\u7D20"
3035
+ };
3036
+ }
3037
+ function getAnnotationChange(changes = []) {
3038
+ return changes.find((change) => change.prop === "annotation:intent");
3039
+ }
3040
+ function updateAnnotationDraft(nextText) {
3041
+ const el = selectedRef.current;
3042
+ if (!el) return;
3043
+ const text = nextText.trim();
3044
+ const info = getAnnotationTargetInfo(el);
3045
+ setLocalDrafts((prev) => {
3046
+ const existing = prev[info.key];
3047
+ const remainingChanges = existing?.changes.filter((change2) => change2.prop !== "annotation:intent") ?? [];
3048
+ if (!text) {
3049
+ if (!existing) return prev;
3050
+ const next = { ...prev };
3051
+ if (remainingChanges.length === 0) {
3052
+ delete next[info.key];
3053
+ } else {
3054
+ next[info.key] = { ...existing, changes: remainingChanges, updatedAt: Date.now() };
3055
+ }
3056
+ return next;
3057
+ }
3058
+ const change = {
3059
+ prop: "annotation:intent",
3060
+ from: "AI\u8BC6\u522B",
3061
+ val: text
3062
+ };
3063
+ const nextEntry = {
3064
+ ...info,
3065
+ changes: [...remainingChanges, change],
3066
+ updatedAt: Date.now()
3067
+ };
3068
+ return { ...prev, [info.key]: nextEntry };
3069
+ });
3070
+ }
2809
3071
  const selectEl = (0, import_react2.useCallback)((el) => {
2810
3072
  selectedRef.current = el;
2811
3073
  const rect = el.getBoundingClientRect();
@@ -2814,6 +3076,8 @@ function InspectorPanel({
2814
3076
  const elCs = getComputedStyle(el);
2815
3077
  const selectedComponentMeta = getInspectorComponentMeta(el);
2816
3078
  const selectedCapability = getComponentCapability(selectedComponentMeta);
3079
+ const annotationDraft = localDraftsRef.current[getAnnotationTargetInfo(el).key];
3080
+ setAnnotationText(getAnnotationChange(annotationDraft?.changes)?.val ?? "");
2817
3081
  const isButtonComponent = selectedCapability?.type === "Button";
2818
3082
  const isIconComponent = selectedCapability?.type === "Icon";
2819
3083
  const isBadgeComponent = selectedCapability?.type === "Badge";
@@ -3276,6 +3540,15 @@ function InspectorPanel({
3276
3540
  setPendingBadgeStatus(status);
3277
3541
  setBadgeStatusOnTargets(targets, status);
3278
3542
  }
3543
+ function updateBadgeStatusOnElement(element, status) {
3544
+ const currentStatus = inferBadgeStatus(getClasses(element));
3545
+ const currentClass = getBadgeStatusClass(element);
3546
+ if (status === currentStatus) {
3547
+ setBadgeStatusOnTargets([element], currentStatus, currentClass);
3548
+ return;
3549
+ }
3550
+ setBadgeStatusOnTargets([element], status);
3551
+ }
3279
3552
  function updateCardVariant(variant) {
3280
3553
  const targets = getComponentTargets();
3281
3554
  if (variant === cardVariantVal) {
@@ -4129,6 +4402,7 @@ function InspectorPanel({
4129
4402
  }
4130
4403
  function copyPluginPrompt(prompt, successMsg) {
4131
4404
  if (!prompt) return;
4405
+ debugAiPrompt(prompt, "plugin");
4132
4406
  copyTextToClipboard(prompt).then((copied) => {
4133
4407
  setPluginMsg(copied ? successMsg : "\u590D\u5236\u5931\u8D25");
4134
4408
  setTimeout(() => setPluginMsg(""), copied ? 2200 : 1800);
@@ -4466,6 +4740,7 @@ function InspectorPanel({
4466
4740
  return `${item.label} / ${item.type} / ${item.categoryLabel} / ${item.summary || "\u672A\u767B\u8BB0\u80FD\u529B"} / ${item.selector || "\u672A\u767B\u8BB0 selector"} / ${item.status}`;
4467
4741
  }
4468
4742
  function openLibraryComponentCreate() {
4743
+ setLibraryComponentImportOpen(false);
4469
4744
  setLibraryComponentForm({
4470
4745
  mode: "create",
4471
4746
  category: libraryComponentCategory === "all" ? "custom" : libraryComponentCategory,
@@ -4477,6 +4752,7 @@ function InspectorPanel({
4477
4752
  });
4478
4753
  }
4479
4754
  function openLibraryComponentEdit(item) {
4755
+ setLibraryComponentImportOpen(false);
4480
4756
  setSelectedLibraryComponentId(item.id);
4481
4757
  setLibraryComponentForm({
4482
4758
  mode: "update",
@@ -4489,6 +4765,103 @@ function InspectorPanel({
4489
4765
  status: item.status.includes("\u8349\u7A3F") ? item.status : "\u7F16\u8F91\u8349\u7A3F"
4490
4766
  });
4491
4767
  }
4768
+ function normalizeComponentImportDraft(raw) {
4769
+ const type = String(raw.type || "").trim() || "Custom";
4770
+ const category = raw.category || getLibraryComponentCategory(type);
4771
+ const variantText = Array.isArray(raw.variants) && raw.variants.length ? `\u53D8\u4F53\uFF1A${raw.variants.join(" / ")}` : "";
4772
+ const sizeText = Array.isArray(raw.sizes) && raw.sizes.length ? `\u5C3A\u5BF8\uFF1A${raw.sizes.join(" / ")}` : "";
4773
+ const tokenText = Array.isArray(raw.tokenRefs) && raw.tokenRefs.length ? `Token\uFF1A${raw.tokenRefs.join(" / ")}` : "";
4774
+ return {
4775
+ mode: "create",
4776
+ category,
4777
+ type,
4778
+ label: String(raw.label || LIBRARY_COMPONENT_LABELS[type] || type).trim(),
4779
+ summary: String(raw.summary || [variantText, sizeText, tokenText].filter(Boolean).join("\uFF1B") || "\u5BFC\u5165\u7EC4\u4EF6\u8349\u7A3F").trim(),
4780
+ selector: String(raw.selector || `.${type.toLowerCase()}`).trim(),
4781
+ status: String(raw.status || "\u5BFC\u5165\u8349\u7A3F").trim()
4782
+ };
4783
+ }
4784
+ function submitImportedLibraryComponents(drafts) {
4785
+ const normalized = drafts.map(normalizeComponentImportDraft);
4786
+ const nextItems = normalized.map((form, index) => ({
4787
+ id: `draft-component-import:${Date.now()}:${index}:${form.type}`,
4788
+ category: form.category,
4789
+ categoryLabel: getLibraryComponentCategoryLabel(form.category),
4790
+ type: form.type,
4791
+ label: form.label,
4792
+ summary: form.summary,
4793
+ selector: form.selector,
4794
+ status: form.status,
4795
+ source: "draft"
4796
+ }));
4797
+ if (!nextItems.length) {
4798
+ setLibraryComponentImportMsg("\u6CA1\u6709\u8BC6\u522B\u5230\u7EC4\u4EF6");
4799
+ setTimeout(() => setLibraryComponentImportMsg(""), 1800);
4800
+ return;
4801
+ }
4802
+ setLibraryCustomComponents((prev) => [...nextItems, ...prev]);
4803
+ setSelectedLibraryComponentId(nextItems[0].id);
4804
+ nextItems.forEach((item) => {
4805
+ recordLibraryCrudChange({
4806
+ resource: "component",
4807
+ action: "create",
4808
+ name: item.type,
4809
+ from: "\u672A\u767B\u8BB0",
4810
+ val: formatLibraryComponentSummary(item)
4811
+ });
4812
+ });
4813
+ setLibraryComponentImportMsg(`\u5DF2\u5BFC\u5165 ${nextItems.length} \u4E2A\u7EC4\u4EF6\u8349\u7A3F`);
4814
+ setTimeout(() => setLibraryComponentImportMsg(""), 2200);
4815
+ }
4816
+ async function handleComponentImportFile(file) {
4817
+ if (!file) return;
4818
+ try {
4819
+ const content = await file.text();
4820
+ const parsed = JSON.parse(content);
4821
+ const drafts = Array.isArray(parsed) ? parsed : parsed.components ?? [];
4822
+ submitImportedLibraryComponents(drafts);
4823
+ } catch {
4824
+ setLibraryComponentImportMsg("JSON \u89E3\u6790\u5931\u8D25");
4825
+ setTimeout(() => setLibraryComponentImportMsg(""), 1800);
4826
+ }
4827
+ }
4828
+ function copyComponentLibraryImportPrompt() {
4829
+ const prompt = [
4830
+ "\u8BF7\u4E3A\u5F53\u524D\u9879\u76EE\u751F\u6210 DevInspector \u7EC4\u4EF6\u5E93\u63A5\u5165\u8349\u7A3F\u3002",
4831
+ "",
4832
+ "\u76EE\u6807\uFF1A",
4833
+ "1. \u626B\u63CF\u73B0\u6709\u7EC4\u4EF6\u6E90\u7801\uFF0C\u8BC6\u522B\u7EC4\u4EF6 type\u3001\u4E2D\u6587 label\u3001selector\u3001\u53D8\u4F53\u3001\u5C3A\u5BF8\u548C tokenRefs\u3002",
4834
+ "2. \u4F18\u5148\u4F7F\u7528 data-component / registry / \u7A33\u5B9A class\uFF1B\u4E0D\u786E\u5B9A\u9879\u6807\u4E3A\u201C\u5F85\u786E\u8BA4\u201D\u3002",
4835
+ "3. \u8F93\u51FA componentPreviews registry \u6216\u4E0B\u9762\u8FD9\u79CD JSON \u8349\u7A3F\u3002",
4836
+ "",
4837
+ "JSON \u683C\u5F0F\uFF1A",
4838
+ "{",
4839
+ ' "components": [',
4840
+ " {",
4841
+ ' "type": "Button",',
4842
+ ' "label": "\u6309\u94AE",',
4843
+ ' "category": "action",',
4844
+ ' "summary": "\u4E3B\u6309\u94AE\u3001\u6B21\u6309\u94AE\u3001\u5F31\u6309\u94AE",',
4845
+ ' "selector": ".button, [data-component=\\"Button\\"]",',
4846
+ ' "variants": ["primary", "secondary", "ghost"],',
4847
+ ' "sizes": ["s", "m", "l"],',
4848
+ ' "tokenRefs": ["--color-brand-primary"],',
4849
+ ' "status": "\u5F85\u786E\u8BA4"',
4850
+ " }",
4851
+ " ]",
4852
+ "}",
4853
+ "",
4854
+ "\u7EA6\u675F\uFF1A\u8BF7\u4FEE\u6539\u6E90\u7801\u5C42\u63A5\u5165\uFF0C\u4E0D\u8981\u76F4\u63A5\u6539 dist \u4EA7\u7269\u3002"
4855
+ ].join("\n");
4856
+ debugAiPrompt(prompt, "plugin");
4857
+ copyTextToClipboard(prompt).then((copied) => {
4858
+ setLibraryComponentImportMsg(copied ? "\u63A5\u5165\u63D0\u793A\u5DF2\u590D\u5236" : "\u590D\u5236\u5931\u8D25");
4859
+ setTimeout(() => setLibraryComponentImportMsg(""), copied ? 2200 : 1800);
4860
+ }).catch(() => {
4861
+ setLibraryComponentImportMsg("\u590D\u5236\u5931\u8D25");
4862
+ setTimeout(() => setLibraryComponentImportMsg(""), 1800);
4863
+ });
4864
+ }
4492
4865
  function submitLibraryComponentForm() {
4493
4866
  if (!libraryComponentForm) return;
4494
4867
  const category = libraryComponentForm.category || getLibraryComponentCategory(libraryComponentForm.type);
@@ -4544,47 +4917,79 @@ function InspectorPanel({
4544
4917
  });
4545
4918
  }
4546
4919
  function buildAiTaskPrompt(params) {
4547
- const changes = params.changes.map((change, index) => `${index + 1}. ${getChangeLabel(change.prop)}\uFF1A${formatStoredChangeRecordValue(change.prop, change.from)} \u2192 ${formatStoredChangeRecordValue(change.prop, change.val)}`).join("\n");
4548
- const latestHint = params.entryId ? `\u4F18\u5148\u5904\u7406 id = ${params.entryId} \u8FD9\u6761\u8BB0\u5F55\u3002` : "\u8FD9\u6761\u4EFB\u52A1\u6765\u81EA DevInspector \u5F53\u524D\u9009\u4E2D\u5143\u7D20\u3002";
4920
+ const changes = formatPromptChanges(params.changes);
4549
4921
  return [
4550
- "DevInspector \u6837\u5F0F\u4EFB\u52A1",
4551
4922
  `\u9875\u9762\uFF1A${params.pageLabel}`,
4552
- `\u5143\u7D20\uFF1A${params.targetLabel}`,
4923
+ "\u5F85\u5904\u7406\u5BF9\u8C61\uFF1A1",
4924
+ `1. \u5143\u7D20\uFF1A${params.targetLabel}`,
4553
4925
  `\u8303\u56F4\uFF1A${params.scopeLabel}`,
4554
4926
  `\u9009\u62E9\u5668\uFF1A${params.selector}`,
4927
+ `\u7C7B\u578B\uFF1A${getPromptChangeTypes(params.changes).join(" / ") || "none"}`,
4555
4928
  "\u6539\u52A8\uFF1A",
4556
- changes || "\u65E0\u6837\u5F0F\u6539\u52A8",
4929
+ changes || "1. \u65E0\u6539\u52A8",
4557
4930
  ...params.note ? ["\u8865\u5145\uFF1A", params.note] : [],
4558
- "\u5B9A\u4F4D\u63D0\u793A\uFF1A",
4559
- latestHint,
4560
- "\u8BF7\u4F18\u5148\u5B9A\u4F4D\u8BE5\u9009\u62E9\u5668\u5BF9\u5E94\u7684\u7EC4\u4EF6\u6216\u6837\u5F0F\u6E90\u7801\uFF0C\u5224\u65AD\u662F\u5426\u5E94\u56FA\u5316\u4E3A\u6B63\u5F0F\u7EC4\u4EF6\u6837\u5F0F\uFF1B\u4E0D\u8981\u624B\u6539 dist\u3002"
4931
+ "\u7ED9AI\uFF1A\u6309\u9009\u62E9\u5668\u5148\u5B9A\u4F4D\u6E90\u7801\uFF0C\u518D\u5224\u65AD\u843D\u4E3A\u7EC4\u4EF6\u6837\u5F0F\u3001token\u3001\u5C40\u90E8\u8986\u76D6\u6216\u5B9E\u73B0\u7EA6\u675F\uFF1B\u4E0D\u8981\u624B\u6539 dist\u3002"
4561
4932
  ].join("\n");
4562
4933
  }
4563
4934
  function buildAiDraftBasketPrompt(drafts) {
4564
4935
  const hasComponentSpec = drafts.some((draft) => draft.changes.some((change) => change.prop === "component-spec" || change.prop.startsWith("component-new-variant:") || change.prop.startsWith("component-variant-group:")));
4565
4936
  const hasLibraryChange = drafts.some((draft) => draft.changes.some((change) => change.prop.startsWith("library-")));
4937
+ const mode = hasLibraryChange ? "library-crud" : hasComponentSpec ? "component-spec" : "style-update";
4566
4938
  const sections = drafts.sort((a, b) => a.updatedAt - b.updatedAt).map((draft, index) => {
4567
- const changes = draft.changes.map((change, changeIndex) => `${changeIndex + 1}. ${getChangeLabel(change.prop)}\uFF1A${formatStoredChangeRecordValue(change.prop, change.from)} \u2192 ${formatStoredChangeRecordValue(change.prop, change.val)}`).join("\n");
4939
+ const changes = formatPromptChanges(draft.changes);
4568
4940
  return [
4569
4941
  `${index + 1}. \u5143\u7D20\uFF1A${draft.targetLabel}`,
4570
4942
  `\u8303\u56F4\uFF1A${draft.scopeLabel}`,
4571
4943
  `\u9009\u62E9\u5668\uFF1A${draft.selector}`,
4944
+ `\u7C7B\u578B\uFF1A${getPromptChangeTypes(draft.changes).join(" / ") || "none"}`,
4572
4945
  "\u6539\u52A8\uFF1A",
4573
- changes || "\u65E0\u6837\u5F0F\u6539\u52A8"
4946
+ changes || "1. \u65E0\u6539\u52A8"
4574
4947
  ].join("\n");
4575
4948
  }).join("\n\n");
4576
- const title = hasLibraryChange ? "DevInspector \u8BBE\u8BA1\u5E93 / \u7EC4\u4EF6 / \u6837\u5F0F\u4EFB\u52A1" : hasComponentSpec ? "DevInspector \u7EC4\u4EF6 / \u6837\u5F0F\u4EFB\u52A1" : "DevInspector \u6837\u5F0F\u4EFB\u52A1";
4577
- const locationHint = hasLibraryChange ? "\u8FD9\u4E9B\u5185\u5BB9\u6765\u81EA DevInspector \u8BBE\u8BA1\u5E93\u5DE5\u4F5C\u53F0\uFF1BToken / Component \u7684\u589E\u5220\u6539\u90FD\u662F\u7528\u6237\u786E\u8BA4\u7684\u53D7\u63A7\u8349\u7A3F\uFF0C\u8BF7\u5148\u5B9A\u4F4D\u8BBE\u8BA1 token \u914D\u7F6E\u3001\u7EC4\u4EF6\u80FD\u529B\u8868\u6216\u6E90\u7801\u4E2D\u7684\u6B63\u5F0F\u5B9A\u4E49\uFF0C\u518D\u5224\u65AD\u5982\u4F55\u843D\u5730\uFF1B\u5220\u9664\u64CD\u4F5C\u9700\u5148\u5904\u7406\u4F7F\u7528\u5173\u7CFB\uFF0C\u4E0D\u8981\u624B\u6539 dist\u3002" : hasComponentSpec ? "\u8FD9\u4E9B\u5185\u5BB9\u6765\u81EA DevInspector \u672C\u6B21\u4FEE\u6539\u5185\u5BB9\uFF1B\u7EC4\u4EF6\u89C4\u683C\u548C\u65B0\u53D8\u4F53\u662F\u7528\u6237\u786E\u8BA4\u7684\u8349\u7A3F\uFF0C\u8BF7\u6309\u7EC4\u4EF6\u540D\u3001\u53EF\u7F16\u8F91\u5185\u5BB9\u3001\u53D8\u4F53\u7EF4\u5EA6\u3001\u72B6\u6001\u3001\u5C3A\u5BF8\u548C\u6837\u5F0F\u89C4\u5219\u5B9A\u4F4D\u6E90\u7801\u843D\u5730\uFF1B\u4E0D\u8981\u624B\u6539 dist\u3002" : "\u8FD9\u4E9B\u5185\u5BB9\u6765\u81EA DevInspector \u672C\u6B21\u4FEE\u6539\u5185\u5BB9\uFF0C\u8BF7\u6309\u5BF9\u8C61\u9010\u4E00\u5B9A\u4F4D\u6E90\u7801\uFF0C\u5224\u65AD\u662F\u5426\u5E94\u56FA\u5316\u4E3A\u7EC4\u4EF6\u6837\u5F0F\u3001token \u6216\u5C40\u90E8\u8986\u76D6\uFF1B\u4E0D\u8981\u624B\u6539 dist\u3002";
4949
+ const aiHint = hasLibraryChange ? "\u7ED9AI\uFF1A\u5148\u5B9A\u4F4D\u6B63\u5F0F token \u914D\u7F6E\u3001\u7EC4\u4EF6\u80FD\u529B\u8868\u6216\u6E90\u7801\u5B9A\u4E49\uFF0C\u518D\u5904\u7406\u589E\u5220\u6539\uFF1B\u5220\u9664\u524D\u5148\u68C0\u67E5\u4F7F\u7528\u5173\u7CFB\uFF1B\u4E0D\u8981\u624B\u6539 dist\u3002" : hasComponentSpec ? "\u7ED9AI\uFF1A\u7EC4\u4EF6\u89C4\u683C\u548C\u65B0\u53D8\u4F53\u6309\u5DF2\u786E\u8BA4\u8349\u7A3F\u5904\u7406\uFF1B\u5148\u5B9A\u4F4D\u7EC4\u4EF6\u5B9A\u4E49\u3001\u53EF\u7F16\u8F91\u5185\u5BB9\u3001\u53D8\u4F53\u7EF4\u5EA6\u548C token \u6620\u5C04\uFF1B\u4E0D\u8981\u624B\u6539 dist\u3002" : "\u7ED9AI\uFF1A\u6309\u5BF9\u8C61\u9010\u4E00\u5B9A\u4F4D\u6E90\u7801\uFF0C\u518D\u5224\u65AD\u843D\u4E3A\u7EC4\u4EF6\u6837\u5F0F\u3001token\u3001\u5C40\u90E8\u8986\u76D6\u6216\u5B9E\u73B0\u7EA6\u675F\uFF1B\u4E0D\u8981\u624B\u6539 dist\u3002";
4578
4950
  return [
4579
- title,
4580
4951
  `\u9875\u9762\uFF1A${document.title || "\u5F53\u524D\u9875\u9762"}\uFF08${window.location.href}\uFF09`,
4581
4952
  `\u5F85\u5904\u7406\u5BF9\u8C61\uFF1A${drafts.length}`,
4582
4953
  sections,
4583
4954
  ...note ? ["\u8865\u5145\uFF1A", note] : [],
4584
- "\u5B9A\u4F4D\u63D0\u793A\uFF1A",
4585
- locationHint
4955
+ aiHint
4586
4956
  ].join("\n");
4587
4957
  }
4958
+ function getPromptChangeType(prop) {
4959
+ if (prop.startsWith("annotation:")) return "annotation";
4960
+ if (prop === "component-spec") return "component-spec";
4961
+ if (prop.startsWith("component-new-variant:")) return "component-new-variant";
4962
+ if (prop.startsWith("component-variant-group:")) return "component-variant-group";
4963
+ if (prop.startsWith("library-token:create")) return "library-token-create";
4964
+ if (prop.startsWith("library-token:update")) return "library-token-update";
4965
+ if (prop.startsWith("library-token:delete")) return "library-token-delete";
4966
+ if (prop.startsWith("library-component:create")) return "library-component-create";
4967
+ if (prop.startsWith("library-component:update")) return "library-component-update";
4968
+ if (prop.startsWith("library-component:delete")) return "library-component-delete";
4969
+ return "style";
4970
+ }
4971
+ function getPromptChangeTypes(changes) {
4972
+ return Array.from(new Set(changes.map((change) => getPromptChangeType(change.prop))));
4973
+ }
4974
+ function formatPromptChanges(changes) {
4975
+ return changes.map((change, index) => {
4976
+ const type = getPromptChangeType(change.prop);
4977
+ if (type === "annotation") {
4978
+ return [
4979
+ `${index + 1}. \u6807\u6CE8\uFF1A${change.val || "\u7A7A"}`
4980
+ ].join("\n");
4981
+ }
4982
+ return [
4983
+ `${index + 1}. ${getChangeLabel(change.prop)}\uFF1A${formatStoredChangeRecordValue(change.prop, change.from) || "\u7A7A"} \u2192 ${formatStoredChangeRecordValue(change.prop, change.val) || "\u7A7A"}`
4984
+ ].join("\n");
4985
+ }).join("\n");
4986
+ }
4987
+ function debugAiPrompt(prompt, source) {
4988
+ window.__DEV_INSPECTOR_LAST_PROMPT__ = prompt;
4989
+ console.groupCollapsed(`[DevInspector] AI prompt (${source})`);
4990
+ console.log(prompt);
4991
+ console.groupEnd();
4992
+ }
4588
4993
  function handleSubmitToAi() {
4589
4994
  const draftEntries = Object.values(localDraftsRef.current);
4590
4995
  if (draftEntries.length > 0) {
@@ -4612,8 +5017,9 @@ function InspectorPanel({
4612
5017
  changes,
4613
5018
  note
4614
5019
  });
5020
+ debugAiPrompt(prompt, "single");
4615
5021
  copyTextToClipboard(prompt).then((copied) => {
4616
- setSubmitMsg(copied ? "\u4EFB\u52A1\u6587\u672C\u5DF2\u590D\u5236 \u2713" : "\u590D\u5236\u5931\u8D25");
5022
+ setSubmitMsg(copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u5931\u8D25");
4617
5023
  setTimeout(() => setSubmitMsg(""), copied ? 2200 : 1800);
4618
5024
  }).catch(() => {
4619
5025
  setSubmitMsg("\u590D\u5236\u5931\u8D25");
@@ -4622,8 +5028,9 @@ function InspectorPanel({
4622
5028
  }
4623
5029
  function copyDraftEntriesToAi(draftEntries) {
4624
5030
  const prompt = buildAiDraftBasketPrompt(draftEntries);
5031
+ debugAiPrompt(prompt, "draft-basket");
4625
5032
  copyTextToClipboard(prompt).then((copied) => {
4626
- setSubmitMsg(copied ? "\u4EFB\u52A1\u6587\u672C\u5DF2\u590D\u5236 \u2713" : "\u590D\u5236\u5931\u8D25");
5033
+ setSubmitMsg(copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u5931\u8D25");
4627
5034
  setTimeout(() => setSubmitMsg(""), copied ? 2200 : 1800);
4628
5035
  }).catch(() => {
4629
5036
  setSubmitMsg("\u590D\u5236\u5931\u8D25");
@@ -4805,6 +5212,9 @@ function InspectorPanel({
4805
5212
  });
4806
5213
  });
4807
5214
  function getChangeLabel(prop) {
5215
+ if (prop.startsWith("annotation:")) {
5216
+ return "\u6807\u6CE8 \xB7 AI\u8BC6\u522B";
5217
+ }
4808
5218
  if (prop.startsWith("library-token:") || prop.startsWith("library-component:")) {
4809
5219
  const [resource = "", action = "", name = "\u672A\u547D\u540D"] = prop.split(":");
4810
5220
  const resourceLabel = resource === "library-token" ? "Token" : "\u7EC4\u4EF6\u89C4\u683C";
@@ -4934,6 +5344,7 @@ function InspectorPanel({
4934
5344
  function resetDraftChangeOnPage(draft, change) {
4935
5345
  const isCurrentDraft = selectedRef.current ? getDraftTargetInfo(selectedRef.current).key === draft.key : false;
4936
5346
  if (isCurrentDraft) clearPendingForProp(change.prop);
5347
+ if (change.prop.startsWith("annotation:")) return;
4937
5348
  if (change.prop.startsWith("library-")) return;
4938
5349
  if (change.prop === "component-spec" || change.prop.startsWith("component-new-variant:")) return;
4939
5350
  const targets = getDraftSelectorTargets(draft.selector);
@@ -5250,6 +5661,29 @@ function InspectorPanel({
5250
5661
  const activeBadgeStatus = pendingBadgeStatus || badgeStatusVal;
5251
5662
  const activeCardVariant = pendingCardVariant || cardVariantVal;
5252
5663
  const componentSizeOptions = getComponentSizeControlOptions(componentCapability);
5664
+ const componentPrimaryText = pendingComponentText ?? componentTextDraft ?? componentTextVal ?? componentEditableSlots.map((slot) => componentTextSlotDrafts[slot.key] || componentTextSlotVals[slot.key] || "").find(Boolean) ?? textContent ?? "";
5665
+ const componentElementInfos = componentMeta ? (() => {
5666
+ const items = [];
5667
+ const seen = /* @__PURE__ */ new Set();
5668
+ const pushItem = (label, element) => {
5669
+ if (!element || seen.has(element)) return;
5670
+ seen.add(element);
5671
+ items.push({
5672
+ key: `${label}:${getSelectorForScope(element, "current")}`,
5673
+ label,
5674
+ selector: getSelectorForScope(element, "current"),
5675
+ text: (element.textContent ?? "").trim() || "\u7A7A",
5676
+ style: getComponentElementStyleSummary(element),
5677
+ spacing: getComponentElementSpacingSummary(element),
5678
+ styleStatus: getComponentElementStyleStatus(element, tokenMap, colorPalette, tokenLabels, typographyTokens),
5679
+ spacingStatus: getComponentElementSpacingStatus(element, spaceSteps)
5680
+ });
5681
+ };
5682
+ pushItem("\u7EC4\u4EF6\u5916\u5C42", selected);
5683
+ componentEditableSlots.forEach((slot) => pushItem(slot.label, getComponentSlotElement(selected, slot)));
5684
+ componentChildSlots.forEach((slot) => pushItem(slot.label, getComponentSlotElement(selected, slot)));
5685
+ return items;
5686
+ })() : [];
5253
5687
  const showElementStyleSections = !componentMeta;
5254
5688
  const localDraftEntries = Object.values(localDrafts).sort((a, b) => b.updatedAt - a.updatedAt);
5255
5689
  const localDraftChangeCount = localDraftEntries.reduce((sum, entry) => sum + entry.changes.length, 0);
@@ -5636,7 +6070,7 @@ function InspectorPanel({
5636
6070
  ref: panelElRef,
5637
6071
  className: `di-panel${componentCreateOpen || libraryOpen ? " di-panel--drawer-open" : ""}${libraryWorkbenchOpen ? " di-panel--workbench-open" : ""}`,
5638
6072
  "data-di-panel-role": "primary",
5639
- style: { top: panelPos.top, left: panelPos.left },
6073
+ style: { top: panelPos.top, left: panelPos.left, ...inspectorTypographyVars },
5640
6074
  children: [
5641
6075
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-head", onMouseDown: onDragStart, children: [
5642
6076
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-head-left", children: [
@@ -6057,7 +6491,24 @@ function InspectorPanel({
6057
6491
  " \u4E2A\u89C4\u683C"
6058
6492
  ] })
6059
6493
  ] }),
6060
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "di-btn-save", onClick: openLibraryComponentCreate, children: "+ \u7EC4\u4EF6\u89C4\u683C" })
6494
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-library-toolbar-actions", children: [
6495
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
6496
+ "button",
6497
+ {
6498
+ type: "button",
6499
+ className: "di-library-workbench-soft-btn",
6500
+ onClick: () => {
6501
+ setLibraryComponentImportOpen(true);
6502
+ setLibraryComponentForm(null);
6503
+ },
6504
+ children: [
6505
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Upload, { size: 13, strokeWidth: 2.2, "aria-hidden": "true" }),
6506
+ "\u5BFC\u5165\u7EC4\u4EF6\u5E93"
6507
+ ]
6508
+ }
6509
+ ),
6510
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "di-btn-save", onClick: openLibraryComponentCreate, children: "+ \u7EC4\u4EF6\u89C4\u683C" })
6511
+ ] })
6061
6512
  ] }),
6062
6513
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-library-component-preview-grid", role: "list", "aria-label": "\u7EC4\u4EF6\u771F\u5B9E\u9884\u89C8", children: [
6063
6514
  filteredLibraryComponentItems.map((item) => {
@@ -6129,7 +6580,7 @@ function InspectorPanel({
6129
6580
  className: "di-btn-save",
6130
6581
  disabled: localDraftChangeCount === 0,
6131
6582
  onClick: handleSubmitToAi,
6132
- children: submitMsg || "\u53D1\u9001\u7ED9AI"
6583
+ children: renderSubmitLabel(submitMsg)
6133
6584
  }
6134
6585
  )
6135
6586
  ] }),
@@ -6322,7 +6773,67 @@ function InspectorPanel({
6322
6773
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: () => focusLibraryTokenUsage(selectedLibraryToken), children: "\u5B9A\u4F4D\u4F7F\u7528" }),
6323
6774
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: () => openLibraryTokenEdit(selectedLibraryToken), children: "\u7F16\u8F91" })
6324
6775
  ] })
6325
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-library-workbench-empty", children: "\u9009\u62E9\u4E00\u4E2A token \u67E5\u770B\u8BE6\u60C5" }) : libraryTab === "components" ? libraryComponentForm ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-library-edit-panel", children: [
6776
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-library-workbench-empty", children: "\u9009\u62E9\u4E00\u4E2A token \u67E5\u770B\u8BE6\u60C5" }) : libraryTab === "components" ? libraryComponentImportOpen ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-library-import-panel", children: [
6777
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-library-edit-head", children: [
6778
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: "\u5BFC\u5165\u7EC4\u4EF6\u5E93" }),
6779
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "di-head-icon-btn", onClick: () => setLibraryComponentImportOpen(false), "aria-label": "\u5173\u95ED\u5BFC\u5165\u7EC4\u4EF6\u5E93", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.X, { size: 15, strokeWidth: 2.2, "aria-hidden": "true" }) })
6780
+ ] }),
6781
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-library-import-steps", children: [
6782
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u9009\u4E00\u79CD\u65B9\u5F0F" }),
6783
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u751F\u6210\u63A5\u5165\u8349\u7A3F" }),
6784
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u53D1\u9001\u7ED9 AI \u843D\u5730" })
6785
+ ] }),
6786
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-library-import-option di-library-import-option--primary", children: [
6787
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
6788
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.WandSparkles, { size: 15, strokeWidth: 2.2, "aria-hidden": "true" }),
6789
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: "\u8BA9 AI \u5E2E\u4F60\u6574\u7406" }),
6790
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u9002\u5408\u7B2C\u4E00\u6B21\u63A5\u5165\u3002\u4F1A\u590D\u5236\u4E00\u6BB5\u63D0\u793A\uFF0C\u8BA9 AI \u626B\u63CF\u9879\u76EE\u5E76\u751F\u6210\u7EC4\u4EF6\u6E05\u5355\u3002" })
6791
+ ] }),
6792
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: copyComponentLibraryImportPrompt, children: "\u590D\u5236\u63D0\u793A" })
6793
+ ] }),
6794
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "di-library-import-option", children: [
6795
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
6796
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Upload, { size: 15, strokeWidth: 2.2, "aria-hidden": "true" }),
6797
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: "\u5DF2\u6709\u7EC4\u4EF6\u6E05\u5355" }),
6798
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u4E0A\u4F20 JSON \u540E\u5148\u53D8\u6210\u8349\u7A3F\uFF0C\u4E0D\u4F1A\u76F4\u63A5\u6539\u6E90\u7801\u3002" })
6799
+ ] }),
6800
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
6801
+ "input",
6802
+ {
6803
+ type: "file",
6804
+ accept: "application/json,.json",
6805
+ onChange: (event) => {
6806
+ void handleComponentImportFile(event.currentTarget.files?.[0] ?? null);
6807
+ event.currentTarget.value = "";
6808
+ }
6809
+ }
6810
+ )
6811
+ ] }),
6812
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-library-import-option", children: [
6813
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
6814
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Component, { size: 15, strokeWidth: 2.2, "aria-hidden": "true" }),
6815
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: "\u5148\u52A0\u4E00\u4E2A\u8BD5\u8BD5" }),
6816
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u53EA\u767B\u8BB0\u4E00\u4E2A\u7EC4\u4EF6\uFF0C\u6BD4\u5982 Button \u6216 Card\u3002" })
6817
+ ] }),
6818
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: openLibraryComponentCreate, children: "\u6DFB\u52A0\u7EC4\u4EF6" })
6819
+ ] }),
6820
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("details", { className: "di-library-import-format", children: [
6821
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("summary", { children: "\u67E5\u770B JSON \u683C\u5F0F" }),
6822
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("pre", { children: `{
6823
+ "components": [
6824
+ {
6825
+ "type": "Button",
6826
+ "label": "\u6309\u94AE",
6827
+ "category": "action",
6828
+ "selector": ".button",
6829
+ "variants": ["primary", "secondary"],
6830
+ "tokenRefs": ["--color-brand-primary"]
6831
+ }
6832
+ ]
6833
+ }` })
6834
+ ] }),
6835
+ libraryComponentImportMsg ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-library-import-msg", children: libraryComponentImportMsg }) : null
6836
+ ] }) : libraryComponentForm ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-library-edit-panel", children: [
6326
6837
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-library-edit-head", children: [
6327
6838
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: libraryComponentForm.mode === "create" ? "\u65B0\u589E\u7EC4\u4EF6\u89C4\u683C" : "\u7F16\u8F91\u7EC4\u4EF6\u89C4\u683C" }),
6328
6839
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "di-head-icon-btn", onClick: () => setLibraryComponentForm(null), "aria-label": "\u5173\u95ED\u7EC4\u4EF6\u89C4\u683C\u8868\u5355", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.X, { size: 15, strokeWidth: 2.2, "aria-hidden": "true" }) })
@@ -6448,7 +6959,7 @@ function InspectorPanel({
6448
6959
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("dd", { children: "\u53EA\u751F\u6210 AI \u4EFB\u52A1\uFF0C\u4E0D\u76F4\u63A5\u5199\u6E90\u7801" })
6449
6960
  ] })
6450
6961
  ] }),
6451
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-library-detail-actions", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: handleSubmitToAi, disabled: localDraftChangeCount === 0, children: submitMsg || "\u53D1\u9001\u7ED9AI" }) })
6962
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-library-detail-actions", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: handleSubmitToAi, disabled: localDraftChangeCount === 0, children: renderSubmitLabel(submitMsg) }) })
6452
6963
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-library-detail-card", children: [
6453
6964
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-library-detail-kicker", children: "Usage" }),
6454
6965
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: "\u4F7F\u7528\u6CBB\u7406" }),
@@ -6480,7 +6991,7 @@ function InspectorPanel({
6480
6991
  className: "di-btn-save",
6481
6992
  disabled: localDraftChangeCount === 0,
6482
6993
  onClick: handleSubmitToAi,
6483
- children: submitMsg || "\u53D1\u9001\u7ED9AI"
6994
+ children: renderSubmitLabel(submitMsg)
6484
6995
  }
6485
6996
  )
6486
6997
  ] })
@@ -7051,18 +7562,74 @@ function InspectorPanel({
7051
7562
  componentMeta && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-section", children: [
7052
7563
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-section-title", children: "\u7EC4\u4EF6" }),
7053
7564
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-component-card", children: [
7054
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-component-head", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-component-main", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "di-component-name", children: componentDisplayName }) }) }),
7055
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-component-meta-row", children: [
7056
- showComponentVariantMeta && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
7057
- componentCapability?.variantKind === "card" ? "\u5C55\u793A" : "\u53D8\u4F53",
7058
- "\uFF1A",
7059
- componentCapability?.variantKind === "card" ? getCardDisplayLabel(componentMeta.variant) : componentMeta.variant
7565
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-component-head", children: [
7566
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-component-main", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-component-title-row", children: [
7567
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "di-component-name", children: componentDisplayName }),
7568
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
7569
+ MatchBadge,
7570
+ {
7571
+ label: componentCapability ? "\u5DF2\u5339\u914D" : "\u5F85\u8865\u5145",
7572
+ tone: componentCapability ? "matched" : "pending",
7573
+ tooltip: componentCapability ? "\u5DF2\u5339\u914D\u5230\u53EF\u590D\u7528\u89C4\u5219\uFF0C\u53EF\u6309\u7EC4\u4EF6\u65B9\u5F0F\u67E5\u770B\u548C\u5904\u7406\u3002" : "\u5F53\u524D\u8FD8\u6CA1\u6709\u53EF\u590D\u7528\u89C4\u5219\uFF0C\u5148\u6309\u5F53\u524D\u6837\u5F0F\u5904\u7406\uFF0C\u540E\u7EED\u53EF\u8865\u5145\u5230\u8BBE\u8BA1\u5E93\u3002"
7574
+ }
7575
+ )
7576
+ ] }) }),
7577
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
7578
+ "button",
7579
+ {
7580
+ type: "button",
7581
+ className: `di-component-meta-toggle${componentInfoOpen ? " di-component-meta-toggle--on" : ""}`,
7582
+ onClick: () => setComponentInfoOpen((open) => !open),
7583
+ "aria-expanded": componentInfoOpen,
7584
+ "aria-label": componentInfoOpen ? "\u6536\u8D77\u5143\u7D20\u4FE1\u606F" : "\u67E5\u770B\u5143\u7D20\u4FE1\u606F",
7585
+ title: componentInfoOpen ? "\u6536\u8D77\u5143\u7D20\u4FE1\u606F" : "\u67E5\u770B\u5143\u7D20\u4FE1\u606F",
7586
+ children: [
7587
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u5143\u7D20\u4FE1\u606F" }),
7588
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.ChevronDown, { size: 14, strokeWidth: 2.2, "aria-hidden": "true" })
7589
+ ]
7590
+ }
7591
+ )
7592
+ ] }),
7593
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-component-meta-block", children: componentInfoOpen && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-component-info-panel", children: componentElementInfos.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-component-info-elements", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-component-info-element-list", children: componentElementInfos.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: "di-component-info-element-card", children: [
7594
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-component-info-element-head", children: [
7595
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "di-component-info-element-label", children: item.label }),
7596
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "di-component-info-element-selector", title: item.selector, children: item.selector })
7060
7597
  ] }),
7061
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
7062
- "\u72B6\u6001\uFF1A",
7063
- getComponentStateLabel(componentMeta.state)
7598
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("dl", { className: "di-component-info-element-meta", children: [
7599
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-component-info-row", children: [
7600
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("dt", { children: "\u5185\u5BB9" }),
7601
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("dd", { title: item.text, children: item.text })
7602
+ ] }),
7603
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-component-info-row", children: [
7604
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("dt", { children: "\u6837\u5F0F" }),
7605
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("dd", { title: item.style, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "di-component-info-inline", children: [
7606
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: item.style }),
7607
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
7608
+ MatchBadge,
7609
+ {
7610
+ label: item.styleStatus === "token" ? "Token" : "\u771F\u5B9E\u503C",
7611
+ tone: item.styleStatus,
7612
+ tooltip: item.styleStatus === "token" ? "\u5F53\u524D\u503C\u5DF2\u6620\u5C04\u5230\u8BBE\u8BA1 token\u3002" : "\u5F53\u524D\u5C55\u793A\u7684\u662F\u9875\u9762\u5B9E\u9645\u6837\u5F0F\u503C\uFF0C\u5C1A\u672A\u6620\u5C04\u5230\u8BBE\u8BA1 token \u6216\u7EC4\u4EF6\u89C4\u5219\u3002"
7613
+ }
7614
+ )
7615
+ ] }) })
7616
+ ] }),
7617
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-component-info-row", children: [
7618
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("dt", { children: "\u95F4\u8DDD" }),
7619
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("dd", { title: item.spacing, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "di-component-info-inline", children: [
7620
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: item.spacing }),
7621
+ item.spacingStatus && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
7622
+ MatchBadge,
7623
+ {
7624
+ label: item.spacingStatus === "token" ? "Token" : "\u771F\u5B9E\u503C",
7625
+ tone: item.spacingStatus,
7626
+ tooltip: item.spacingStatus === "token" ? "\u5F53\u524D\u503C\u5DF2\u6620\u5C04\u5230\u8BBE\u8BA1 token\u3002" : "\u5F53\u524D\u5C55\u793A\u7684\u662F\u9875\u9762\u5B9E\u9645\u6837\u5F0F\u503C\uFF0C\u5C1A\u672A\u6620\u5C04\u5230\u8BBE\u8BA1 token \u6216\u7EC4\u4EF6\u89C4\u5219\u3002"
7627
+ }
7628
+ )
7629
+ ] }) })
7630
+ ] })
7064
7631
  ] })
7065
- ] }),
7632
+ ] }, item.key)) }) }) }) }),
7066
7633
  componentCapability && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-component-fields", children: [
7067
7634
  componentEditableSlots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "di-component-field di-component-field--text", children: [
7068
7635
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: slot.label }),
@@ -7079,24 +7646,38 @@ function InspectorPanel({
7079
7646
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: visibleChildSlots.length === 1 ? visibleChildSlots[0].slot.label : "\u53EF\u9009\u9879" }),
7080
7647
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-component-child-list", children: visibleChildSlots.map(({ slot, value, element }) => {
7081
7648
  const childMeta = element ? getInspectorComponentMeta(element) : null;
7649
+ const childCapability = getComponentCapability(childMeta);
7082
7650
  const childName = childMeta ? getComponentDisplayName(childMeta) : slot.label;
7083
7651
  const childValue = value || childMeta?.variant || childName;
7084
7652
  const showChildLabel = visibleChildSlots.length > 1;
7653
+ const childBadgeStatus = element && childCapability?.statusKind === "badge" ? inferBadgeStatus(getClasses(element)) : null;
7085
7654
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `di-component-child-item${showChildLabel ? " di-component-child-item--with-label" : ""}`, children: [
7086
7655
  showChildLabel && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "di-component-child-label", children: slot.label }),
7087
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "di-component-child-value", children: childValue }),
7088
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
7656
+ element && childCapability?.statusKind === "badge" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-component-child-variant-grid", role: "group", "aria-label": `${childName} \u72B6\u6001`, children: BADGE_STATUS_OPTIONS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
7089
7657
  "button",
7090
7658
  {
7091
7659
  type: "button",
7092
- className: "di-component-child-select",
7093
- onClick: () => {
7094
- if (element) selectEl(element);
7095
- },
7096
- title: `\u9009\u62E9 ${childName}`,
7097
- children: "\u9009\u62E9"
7098
- }
7099
- )
7660
+ className: `di-component-child-variant-tile${childBadgeStatus === option.key ? " di-component-child-variant-tile--on" : ""}`,
7661
+ onClick: () => updateBadgeStatusOnElement(element, option.key),
7662
+ title: `${childName} \xB7 ${option.label}`,
7663
+ children: option.label
7664
+ },
7665
+ option.key
7666
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
7667
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "di-component-child-value", children: childValue }),
7668
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
7669
+ "button",
7670
+ {
7671
+ type: "button",
7672
+ className: "di-component-child-select",
7673
+ onClick: () => {
7674
+ if (element) selectEl(element);
7675
+ },
7676
+ title: `\u9009\u62E9 ${childName}`,
7677
+ children: "\u9009\u62E9"
7678
+ }
7679
+ )
7680
+ ] })
7100
7681
  ] }, slot.key);
7101
7682
  }) })
7102
7683
  ] }),
@@ -7152,11 +7733,11 @@ function InspectorPanel({
7152
7733
  ] }),
7153
7734
  componentCapability.statusKind === "badge" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-component-field", children: [
7154
7735
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u72B6\u6001" }),
7155
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-component-segment di-component-segment--tone", role: "group", "aria-label": "\u6807\u7B7E\u72B6\u6001", children: BADGE_STATUS_OPTIONS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
7736
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-component-variant-grid", role: "group", "aria-label": "\u6807\u7B7E\u72B6\u6001", children: BADGE_STATUS_OPTIONS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
7156
7737
  "button",
7157
7738
  {
7158
7739
  type: "button",
7159
- className: `di-component-segment-btn${activeBadgeStatus === option.key ? " di-component-segment-btn--on" : ""}`,
7740
+ className: `di-component-variant-tile${activeBadgeStatus === option.key ? " di-component-variant-tile--on" : ""}`,
7160
7741
  onClick: () => updateBadgeStatus(option.key),
7161
7742
  children: option.label
7162
7743
  },
@@ -8305,6 +8886,43 @@ function InspectorPanel({
8305
8886
  ] })
8306
8887
  ] })
8307
8888
  ] }),
8889
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-section di-annotation-section", children: [
8890
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `di-section-title-row di-section-title-row--action${annotationOpen ? "" : " di-section-title-row--empty"}`, children: [
8891
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-section-title-group", children: [
8892
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-section-title", children: "\u6807\u6CE8" }),
8893
+ localDraftEntries.some((entry) => entry.changes.some((change) => change.prop.startsWith("annotation:"))) && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "di-annotation-count", children: "\u5DF2\u8BB0\u5F55" })
8894
+ ] }),
8895
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
8896
+ "button",
8897
+ {
8898
+ type: "button",
8899
+ className: "di-section-icon-action",
8900
+ onClick: () => setAnnotationOpen((open) => !open),
8901
+ title: annotationOpen ? "\u6536\u8D77\u6807\u6CE8" : "\u6DFB\u52A0\u6807\u6CE8",
8902
+ "aria-label": annotationOpen ? "\u6536\u8D77\u6807\u6CE8" : "\u6DFB\u52A0\u6807\u6CE8",
8903
+ children: annotationOpen ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Minus, { size: 14, strokeWidth: 2.4, "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Plus, { size: 14, strokeWidth: 2.4, "aria-hidden": "true" })
8904
+ }
8905
+ )
8906
+ ] }),
8907
+ annotationOpen && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-annotation-card", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "di-annotation-row di-annotation-row--text", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
8908
+ "textarea",
8909
+ {
8910
+ className: "di-annotation-textarea",
8911
+ value: annotationText,
8912
+ placeholder: "\u76F4\u63A5\u5199\u4F60\u7684\u60F3\u6CD5\uFF0C\u4F8B\u5982\uFF1A\u8FD9\u91CC\u8981\u4FDD\u6301\u9AD8\u4EAE\u4F46\u4E0D\u8981\u7528\u5B9E\u5E95\u4E3B\u6309\u94AE\u6837\u5F0F\u3002AI \u4F1A\u5224\u65AD\u8FD9\u662F\u8BBE\u8BA1\u8BF4\u660E\u3001\u4EA7\u54C1\u89C4\u5219\u8FD8\u662F\u5F00\u53D1\u5907\u6CE8\u3002",
8913
+ rows: 2,
8914
+ onChange: (event) => {
8915
+ const nextText = event.currentTarget.value;
8916
+ setAnnotationText(nextText);
8917
+ updateAnnotationDraft(nextText);
8918
+ resizeTextareaToContent(event.currentTarget);
8919
+ },
8920
+ ref: (node) => {
8921
+ if (node) resizeTextareaToContent(node);
8922
+ }
8923
+ }
8924
+ ) }) })
8925
+ ] }),
8308
8926
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-section", children: [
8309
8927
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-section-title", children: [
8310
8928
  "\u672C\u6B21\u4FEE\u6539\u5185\u5BB9 ",
@@ -8454,7 +9072,7 @@ ${pending.map(([p, v]) => ` ${p}: ${v};`).join("\n")}
8454
9072
  disabled: !hasPending,
8455
9073
  style: !hasPending ? { opacity: 0.4, cursor: "not-allowed" } : {},
8456
9074
  title: "\u590D\u5236\u4E00\u6BB5\u53EF\u76F4\u63A5\u53D1\u7ED9 AI \u7684\u4EFB\u52A1\u6587\u672C",
8457
- children: submitMsg || "\u53D1\u9001\u7ED9AI"
9075
+ children: renderSubmitLabel(submitMsg)
8458
9076
  }
8459
9077
  )
8460
9078
  ] });
@@ -8490,115 +9108,6 @@ ${pending.map(([p, v]) => ` ${p}: ${v};`).join("\n")}
8490
9108
  )
8491
9109
  ] });
8492
9110
  }
8493
- var CODE_FILES = [
8494
- { name: "src/", desc: "React \u7EC4\u4EF6\u3001\u9875\u9762\u3001\u6837\u5F0F\u6E90\u7801\uFF08\u4E0D\u542B\u8C03\u8BD5\u5DE5\u5177\uFF09" },
8495
- { name: "index.html", desc: "\u5E94\u7528\u5165\u53E3 HTML" },
8496
- { name: "package.json", desc: "\u4F9D\u8D56\u5305\u4E0E\u811A\u672C\u914D\u7F6E" },
8497
- { name: "tsconfig.json", desc: "TypeScript \u7F16\u8BD1\u914D\u7F6E" },
8498
- { name: "vite.config.ts", desc: "\u6784\u5EFA\u5DE5\u5177\u914D\u7F6E" }
8499
- ];
8500
- var PRODUCT_FILES = [
8501
- { name: "docs/PRODUCT_PLAN.md", desc: "\u4EA7\u54C1\u89C4\u5212\u4E0E\u8DEF\u7EBF\u56FE" },
8502
- { name: "docs/PROJECT.md", desc: "\u9879\u76EE\u80CC\u666F\u4E0E\u76EE\u6807\u6982\u8FF0" },
8503
- { name: "docs/DECISIONS.md", desc: "\u5173\u952E\u4EA7\u54C1\u51B3\u7B56\u8BB0\u5F55" },
8504
- { name: "docs/CHANGELOG.md", desc: "\u529F\u80FD\u8FED\u4EE3\u53D8\u66F4\u65E5\u5FD7" },
8505
- { name: "docs/CODE_STRUCTURE.md", desc: "\u524D\u7AEF\u76EE\u5F55\u7ED3\u6784\u8BF4\u660E" },
8506
- { name: "docs/DESIGN_STANDARDS.md", desc: "\u8BBE\u8BA1\u89C4\u8303\u603B\u89C8" }
8507
- ];
8508
- var DESIGN_FILES = [
8509
- { name: "docs/design/OVERVIEW.md", desc: "\u8BBE\u8BA1\u7CFB\u7EDF\u603B\u89C8" },
8510
- { name: "docs/design/tokens.md", desc: "Design Token \u4F7F\u7528\u8BF4\u660E" },
8511
- { name: "docs/design/layout.md", desc: "\u9875\u9762\u5E03\u5C40\u89C4\u8303" },
8512
- { name: "docs/design/component-index.md", desc: "\u7EC4\u4EF6\u6E05\u5355\u7D22\u5F15" },
8513
- { name: "docs/design/business-components.md", desc: "\u4E1A\u52A1\u7EC4\u4EF6\u8BF4\u660E" }
8514
- ];
8515
- function FileList({ files }) {
8516
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ul", { className: "di-dl-file-list", children: files.map((f) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { children: [
8517
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "di-dl-file-name", children: f.name }),
8518
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "di-dl-file-desc", children: f.desc })
8519
- ] }, f.name)) });
8520
- }
8521
- function DownloadButton() {
8522
- const { endpoints } = useDevInspectorConfig();
8523
- const [open, setOpen] = (0, import_react2.useState)(false);
8524
- const [status, setStatus] = (0, import_react2.useState)("idle");
8525
- const [filePath, setFilePath] = (0, import_react2.useState)("");
8526
- const [details, setDetails] = (0, import_react2.useState)({ code: false, product: false, design: false });
8527
- const [opts, setOpts] = (0, import_react2.useState)({ code: true, product: false, design: false });
8528
- function toggle(k) {
8529
- setOpts((prev) => ({ ...prev, [k]: !prev[k] }));
8530
- }
8531
- function toggleDetail(k) {
8532
- setDetails((prev) => ({ ...prev, [k]: !prev[k] }));
8533
- }
8534
- function handleOpen() {
8535
- setOpen((v) => !v);
8536
- if (open) setStatus("idle");
8537
- }
8538
- async function download() {
8539
- if (!opts.code && !opts.product && !opts.design) return;
8540
- setStatus("packing");
8541
- try {
8542
- const params = new URLSearchParams({
8543
- code: opts.code ? "1" : "0",
8544
- product: opts.product ? "1" : "0",
8545
- design: opts.design ? "1" : "0"
8546
- });
8547
- const res = await fetch(`${endpoints.handoff}?${params}`);
8548
- const json = await res.json();
8549
- if (!json.ok) throw new Error(json.error);
8550
- setFilePath(json.path);
8551
- setStatus("done");
8552
- } catch {
8553
- setStatus("error");
8554
- }
8555
- }
8556
- async function revealInFinder() {
8557
- await fetch(`${endpoints.reveal}?path=${encodeURIComponent(filePath)}`);
8558
- }
8559
- const sections = [
8560
- { key: "code", label: "\u524D\u7AEF\u4EE3\u7801", files: CODE_FILES },
8561
- { key: "product", label: "\u4EA7\u54C1\u6587\u6863", files: PRODUCT_FILES },
8562
- { key: "design", label: "\u8BBE\u8BA1\u6587\u6863", files: DESIGN_FILES }
8563
- ];
8564
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
8565
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "di-dl-btn", onClick: handleOpen, children: "\u4E0B\u8F7D" }),
8566
- open && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-dl-modal", children: [
8567
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-dl-title", children: "\u9009\u62E9\u4E0B\u8F7D\u5185\u5BB9" }),
8568
- status === "packing" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-dl-status", children: [
8569
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "di-dl-spinner" }),
8570
- "\u6B63\u5728\u6253\u5305\uFF0C\u8BF7\u7A0D\u5019\u2026"
8571
- ] }),
8572
- status === "done" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-dl-done", children: [
8573
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-dl-done-check", children: "\u2713 \u5DF2\u4FDD\u5B58\u81F3\u684C\u9762" }),
8574
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-dl-done-path", children: filePath.replace(/.*\//, "") }),
8575
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "di-dl-reveal-btn", onClick: revealInFinder, children: "\u5728 Finder \u4E2D\u663E\u793A" })
8576
- ] }),
8577
- status === "error" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "di-dl-status di-dl-status--error", children: "\u6253\u5305\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B\u63A7\u5236\u53F0" }),
8578
- (status === "idle" || status === "error") && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
8579
- sections.map(({ key, label, files }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
8580
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "di-dl-row", children: [
8581
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "di-dl-check-label", children: [
8582
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { type: "checkbox", checked: opts[key], onChange: () => toggle(key) }),
8583
- label
8584
- ] }),
8585
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { className: "di-dl-detail-btn", onClick: () => toggleDetail(key), children: details[key] ? "\u6536\u8D77" : "\u8BE6\u60C5" })
8586
- ] }),
8587
- details[key] && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FileList, { files })
8588
- ] }, key)),
8589
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
8590
- "button",
8591
- {
8592
- className: "di-dl-confirm",
8593
- onClick: download,
8594
- disabled: !opts.code && !opts.product && !opts.design,
8595
- children: "\u4E0B\u8F7D"
8596
- }
8597
- )
8598
- ] })
8599
- ] })
8600
- ] });
8601
- }
8602
9111
  function DevInspector() {
8603
9112
  const [active, setActive] = (0, import_react2.useState)(false);
8604
9113
  const [tokenMap, setTokenMap] = (0, import_react2.useState)({});
@@ -8628,26 +9137,29 @@ function DevInspector() {
8628
9137
  (0, import_react2.useEffect)(() => {
8629
9138
  const onOver = (e) => {
8630
9139
  if (!active || modalOpenRef.current) return;
8631
- const el = e.target;
8632
- if (!el?.classList) return;
8633
- if (isInsidePanel(el)) {
8634
- el.classList.remove("di-hover");
9140
+ const raw = e.target;
9141
+ if (!raw?.classList) return;
9142
+ if (isInsidePanel(raw)) {
9143
+ raw.classList.remove("di-hover");
8635
9144
  return;
8636
9145
  }
8637
- el.classList.add("di-hover");
9146
+ document.querySelectorAll(".di-hover").forEach((item) => item.classList.remove("di-hover"));
9147
+ resolveSelectionTarget(raw).classList.add("di-hover");
8638
9148
  };
8639
- const onOut = (e) => {
8640
- e.target?.classList?.remove("di-hover");
9149
+ const onOut = () => {
9150
+ document.querySelectorAll(".di-hover").forEach((item) => item.classList.remove("di-hover"));
8641
9151
  };
8642
9152
  const onClick = (e) => {
8643
9153
  if (!active || modalOpenRef.current) return;
8644
- const el = e.target;
8645
- if (isInsidePanel(el)) return;
9154
+ const raw = e.target;
9155
+ if (!raw?.classList) return;
9156
+ if (isInsidePanel(raw)) return;
8646
9157
  e.preventDefault();
8647
9158
  e.stopPropagation();
8648
- el.classList.remove("di-hover");
9159
+ const target = resolveSelectionTarget(raw);
9160
+ document.querySelectorAll(".di-hover").forEach((item) => item.classList.remove("di-hover"));
8649
9161
  setPanels(
8650
- (prev) => prev.length === 0 ? [{ id: "main", el }] : prev.map((p, i) => i === 0 ? { ...p, el } : p)
9162
+ (prev) => prev.length === 0 ? [{ id: "main", el: target }] : prev.map((p, i) => i === 0 ? { ...p, el: target } : p)
8651
9163
  );
8652
9164
  };
8653
9165
  document.addEventListener("mouseover", onOver, true);
@@ -8688,7 +9200,6 @@ function DevInspector() {
8688
9200
  const primaryEl = panels[0]?.el;
8689
9201
  const triggerTooltip = active ? `\u9000\u51FA\u7F16\u8F91\uFF08${EXIT_SHORTCUT_LABEL}\uFF09` : `\u8FDB\u5165\u7F16\u8F91\uFF08${EDIT_SHORTCUT_LABEL}\uFF09`;
8690
9202
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
8691
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DownloadButton, {}),
8692
9203
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
8693
9204
  "button",
8694
9205
  {