minecodex 2.0.12 → 2.0.13
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/README.md +12 -0
- package/apps/dashboard/app.js +37 -4
- package/apps/dashboard/assets/data-transfer.js +129 -0
- package/apps/dashboard/assets/download.svg +15 -0
- package/apps/dashboard/assets/upload.svg +15 -0
- package/apps/dashboard/index.html +10 -0
- package/apps/dashboard/styles.css +52 -1
- package/features/file-navigation/assets/book-open.svg +16 -0
- package/features/file-navigation/codex-feature.json +27 -0
- package/features/file-navigation/src/adapters/codex/modules.mjs +67 -0
- package/features/file-navigation/src/adapters/codex/navigation.mjs +84 -0
- package/features/file-navigation/src/domain/navigation.mjs +12 -0
- package/features/file-navigation/src/entry.mjs +34 -0
- package/features/file-navigation/src/frontend/navigation.mjs +140 -0
- package/features/file-navigation/src/injection-source.mjs +9 -0
- package/features/file-navigation/src/navigation.css +16 -0
- package/features/file-navigation/vendor/lucide-LICENSE +43 -0
- package/features/markdown-reading/assets/book-open.svg +16 -0
- package/features/markdown-reading/codex-feature.json +27 -0
- package/features/markdown-reading/src/adapters/codex/links.mjs +280 -0
- package/features/markdown-reading/src/adapters/codex/lists.mjs +168 -0
- package/features/markdown-reading/src/adapters/codex/markdown-native.mjs +28 -0
- package/features/markdown-reading/src/adapters/codex/preview.mjs +38 -0
- package/features/markdown-reading/src/adapters/codex/providers.mjs +18 -0
- package/features/markdown-reading/src/adapters/codex/reading-runtime.mjs +152 -0
- package/features/markdown-reading/src/adapters/codex/rich-text.mjs +561 -0
- package/features/markdown-reading/src/adapters/codex/table-actions.mjs +270 -0
- package/features/markdown-reading/src/adapters/codex/tables.mjs +493 -0
- package/features/markdown-reading/src/adapters/codex/toc-native.mjs +131 -0
- package/features/markdown-reading/src/adapters/codex/toc.mjs +334 -0
- package/features/markdown-reading/src/domain/footnotes.mjs +56 -0
- package/features/markdown-reading/src/injection-source.mjs +43 -0
- package/features/markdown-reading/src/markdown-reading.mjs +82 -0
- package/features/markdown-reading/src/reading.css +346 -0
- package/features/markdown-reading/vendor/lucide-LICENSE +43 -0
- package/features/model-slider/codex-feature.json +1 -0
- package/features/model-slider/src/backend/favorites.mjs +54 -0
- package/features/model-slider/src/domain/model-rules.mjs +6 -1
- package/features/model-slider/src/frontend/install.mjs +24 -3
- package/features/notes/assets/prompt-previews.json +26 -0
- package/features/notes/codex-feature.json +2 -1
- package/features/notes/src/backend/transfer.mjs +97 -0
- package/features/notes/src/frontend/entry.mjs +380 -10
- package/features/notes/src/frontend/icons.json +4 -1
- package/features/notes/src/frontend/styles.css +63 -0
- package/features/session-status/src/domain/session-stats.mjs +22 -8
- package/features/session-status/src/session-status.mjs +2 -2
- package/features/sites/src/backend/sites-service.mjs +20 -5
- package/features/sites/src/backend/transfer.mjs +43 -0
- package/package.json +11 -3
- package/packages/cli/src/config.mjs +4 -2
- package/packages/cli/src/control-server.mjs +23 -4
- package/packages/cli/src/data-transfer/service.mjs +42 -0
- package/packages/cli/src/runtime-manager.mjs +3 -0
- package/packages/runtime-host/src/codex-injection.mjs +1 -0
- package/packages/runtime-host/src/codex-runtime.mjs +11 -0
- package/packages/runtime-host/src/feature-registry.mjs +1 -0
- package/packages/ui/src/native/theme.mjs +22 -1
- package/packages/ui/src/native/tokens.mjs +4 -0
|
@@ -25,6 +25,7 @@ function appearanceLabel(key) {
|
|
|
25
25
|
}
|
|
26
26
|
function errorMessage(error) {
|
|
27
27
|
const messages = {
|
|
28
|
+
"Open a chat before using a prompt.": "请先打开一个对话,再使用提示词。",
|
|
28
29
|
"Category was not found": "未找到该分类",
|
|
29
30
|
"Prompt was not found": "未找到该提示词",
|
|
30
31
|
"Choose one emoji or leave it empty": "请选择一个 Emoji,或留空以继承分类图标",
|
|
@@ -74,6 +75,8 @@ function position() {
|
|
|
74
75
|
config.ui.composerMenu(panel, addButton);
|
|
75
76
|
}
|
|
76
77
|
function close(restoreFocus = false) {
|
|
78
|
+
clearQuickPreview(true);
|
|
79
|
+
quickTabsObserver?.disconnect();
|
|
77
80
|
generation++;
|
|
78
81
|
panel?.remove();
|
|
79
82
|
panel = null;
|
|
@@ -82,6 +85,108 @@ function close(restoreFocus = false) {
|
|
|
82
85
|
button?.setAttribute("data-state", "closed");
|
|
83
86
|
if (restoreFocus) button?.focus({ preventScroll: true });
|
|
84
87
|
}
|
|
88
|
+
let quickCategory = "all";
|
|
89
|
+
let quickTabsObserver = null;
|
|
90
|
+
let quickPreview = null;
|
|
91
|
+
let quickPreviewTimer = null;
|
|
92
|
+
let quickExitTimer = null;
|
|
93
|
+
function clearQuickPreview(immediate = false, shift = 0) {
|
|
94
|
+
clearTimeout(quickPreviewTimer);
|
|
95
|
+
clearTimeout(quickExitTimer);
|
|
96
|
+
const current = quickPreview;
|
|
97
|
+
if (!current) return;
|
|
98
|
+
current.anchor.removeAttribute("data-preview");
|
|
99
|
+
if (immediate || previewReducedMotion()) {
|
|
100
|
+
current.node.remove();
|
|
101
|
+
quickPreview = null;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
current.node.style.pointerEvents = "none";
|
|
105
|
+
tweenPreview(current.node, { opacity:0, transform:`translateY(${Math.max(-10, Math.min(10, shift))}px) scale(.98)` }, 150);
|
|
106
|
+
quickExitTimer = setTimeout(() => {
|
|
107
|
+
current.node.remove();
|
|
108
|
+
if (quickPreview === current) quickPreview = null;
|
|
109
|
+
}, 150);
|
|
110
|
+
}
|
|
111
|
+
function showQuickPreview(item, anchor) {
|
|
112
|
+
clearQuickPreview(true);
|
|
113
|
+
const preview = cardPreview(item);
|
|
114
|
+
if (!preview) return;
|
|
115
|
+
quickPreviewTimer = setTimeout(() => {
|
|
116
|
+
if (!panel || !anchor.isConnected) return;
|
|
117
|
+
const node = element("div", "qp-image-preview");
|
|
118
|
+
config.ui.surface(node, "popover");
|
|
119
|
+
config.ui.mount(node, "floating");
|
|
120
|
+
const image = element("img");
|
|
121
|
+
image.alt = text(`Full image: ${item.summary}`, `完整图片:${item.summary}`);
|
|
122
|
+
const place = () => {
|
|
123
|
+
if (quickPreview?.node !== node || !image.naturalWidth) return;
|
|
124
|
+
const r = anchor.getBoundingClientRect(), p = panel.getBoundingClientRect();
|
|
125
|
+
const right = innerWidth - p.right - 24, left = p.left - 24;
|
|
126
|
+
const available = Math.max(right, left);
|
|
127
|
+
if (available < 96) { clearQuickPreview(true); return; }
|
|
128
|
+
const scale = Math.min(280 / image.naturalWidth, available / image.naturalWidth, 360 / image.naturalHeight, (innerHeight - 24) / image.naturalHeight);
|
|
129
|
+
const width = image.naturalWidth * scale, height = image.naturalHeight * scale;
|
|
130
|
+
node.style.width = `${width}px`;
|
|
131
|
+
node.style.height = `${height}px`;
|
|
132
|
+
node.style.left = `${right >= width ? p.right + 12 : p.left - width - 12}px`;
|
|
133
|
+
node.style.top = `${Math.max(12, Math.min(r.top + (r.height - height) / 2, innerHeight - height - 12))}px`;
|
|
134
|
+
node.style.visibility = "visible";
|
|
135
|
+
if (!previewReducedMotion()) node.animate([{opacity:0,transform:"translateX(-4px) scale(.98)"},{opacity:1,transform:"none"}],{duration:180,easing:"cubic-bezier(.22,1,.36,1)"});
|
|
136
|
+
};
|
|
137
|
+
node.append(image);
|
|
138
|
+
quickPreview = {node, anchor};
|
|
139
|
+
anchor.dataset.preview = "true";
|
|
140
|
+
node.addEventListener("pointerenter", () => clearTimeout(quickPreviewTimer));
|
|
141
|
+
node.addEventListener("pointerleave", () => clearQuickPreview());
|
|
142
|
+
image.onload = place;
|
|
143
|
+
image.src = preview.data;
|
|
144
|
+
if (image.complete) place();
|
|
145
|
+
}, 160);
|
|
146
|
+
}
|
|
147
|
+
function quickCategoryTabs() {
|
|
148
|
+
const bar = element("div", "qp-tabs-bar");
|
|
149
|
+
const tabs = element("div", "qp-tabs");
|
|
150
|
+
tabs.setAttribute("role", "tablist");
|
|
151
|
+
tabs.setAttribute("aria-label", text("Prompt categories", "提示词分类"));
|
|
152
|
+
const choices = [{id:"all",name:text("All","全部")}, ...categories.filter(c => orderedItems(c.id).length), ...(orderedItems(null).length ? [{id:"other",name:text("Other","其他")}] : [])];
|
|
153
|
+
if (!choices.some(c => c.id === quickCategory)) quickCategory = "all";
|
|
154
|
+
for (const category of choices) {
|
|
155
|
+
const tab = control(category.name, () => { quickCategory = category.id; renderList(); panel.querySelector('[aria-selected="true"]')?.focus({preventScroll:true}); }, "qp-tab");
|
|
156
|
+
tab.setAttribute("role", "tab");
|
|
157
|
+
tab.setAttribute("aria-selected", String(category.id === quickCategory));
|
|
158
|
+
tab.setAttribute("aria-controls", "mcx-quick-results");
|
|
159
|
+
tabs.append(tab);
|
|
160
|
+
}
|
|
161
|
+
const arrows = element("div", "qp-tab-arrows");
|
|
162
|
+
const move = direction => tabs.scrollBy({left:direction * Math.max(100,tabs.clientWidth - 90), behavior:previewReducedMotion() ? "instant" : "smooth"});
|
|
163
|
+
const previous = control(text("Previous categories","前面的分类"), () => move(-1), "qp-tab-arrow qp-tab-previous", "chevron");
|
|
164
|
+
const next = control(text("More categories","后面的分类"), () => move(1), "qp-tab-arrow qp-tab-next", "chevron");
|
|
165
|
+
arrows.append(previous,next);
|
|
166
|
+
bar.append(tabs,arrows);
|
|
167
|
+
const update = () => {
|
|
168
|
+
const naturalWidth = [...tabs.children].reduce((width, tab) => width + tab.offsetWidth + 2, -2);
|
|
169
|
+
const overflow = naturalWidth > tabs.clientWidth + 1;
|
|
170
|
+
previous.hidden = !overflow || tabs.scrollLeft <= 1;
|
|
171
|
+
next.hidden = !overflow || tabs.scrollLeft + tabs.clientWidth >= tabs.scrollWidth - 1;
|
|
172
|
+
arrows.hidden = !overflow;
|
|
173
|
+
bar.dataset.overflow = String(overflow);
|
|
174
|
+
tabs.style.setProperty("--qp-arrow-space", `${overflow ? 68 : 0}px`);
|
|
175
|
+
};
|
|
176
|
+
tabs.addEventListener("scroll", update, {passive:true});
|
|
177
|
+
tabs.addEventListener("keydown", event => {
|
|
178
|
+
if (!["ArrowLeft","ArrowRight"].includes(event.key)) return;
|
|
179
|
+
event.preventDefault();
|
|
180
|
+
const buttons = [...tabs.children], i = buttons.indexOf(document.activeElement);
|
|
181
|
+
const target = buttons[Math.max(0,Math.min(buttons.length-1,i+(event.key === "ArrowRight" ? 1 : -1)))];
|
|
182
|
+
target?.focus();
|
|
183
|
+
});
|
|
184
|
+
quickTabsObserver = new ResizeObserver(update);
|
|
185
|
+
quickTabsObserver.observe(tabs);
|
|
186
|
+
requestAnimationFrame(() => { if (!bar.isConnected) return; update(); const selected=tabs.querySelector('[aria-selected="true"]'); if(selected) tabs.scrollLeft = Math.max(0,selected.offsetLeft-tabs.offsetLeft-tabs.clientWidth+selected.offsetWidth+68); update(); });
|
|
187
|
+
return bar;
|
|
188
|
+
}
|
|
189
|
+
|
|
85
190
|
// 输入框 Popover:只浏览与插入
|
|
86
191
|
async function loadList() {
|
|
87
192
|
const current = ++generation;
|
|
@@ -143,6 +248,8 @@ function orderedItems(categoryId) {
|
|
|
143
248
|
);
|
|
144
249
|
}
|
|
145
250
|
function renderList() {
|
|
251
|
+
clearQuickPreview(true);
|
|
252
|
+
quickTabsObserver?.disconnect();
|
|
146
253
|
panel.replaceChildren();
|
|
147
254
|
const list = element("div", "qp-scroll");
|
|
148
255
|
if (!items.length)
|
|
@@ -153,15 +260,19 @@ function renderList() {
|
|
|
153
260
|
.filter((item) => item.useCount > 0)
|
|
154
261
|
.sort((a, b) => b.calledAt - a.calledAt || a.id.localeCompare(b.id))
|
|
155
262
|
.slice(0, 3);
|
|
263
|
+
panel.append(quickCategoryTabs());
|
|
264
|
+
list.id = "mcx-quick-results";
|
|
265
|
+
let lastScroll = 0;
|
|
266
|
+
list.addEventListener("scroll", () => { const delta = lastScroll - list.scrollTop; lastScroll = list.scrollTop; clearQuickPreview(false, delta); }, {passive:true});
|
|
156
267
|
const sections = [
|
|
157
|
-
{ name: text("Recently used", "最近使用"), prompts: recent },
|
|
268
|
+
{ id:"recent", name: text("Recently used", "最近使用"), prompts: recent },
|
|
158
269
|
...categories.map((category) => ({
|
|
159
|
-
name: category.name,
|
|
270
|
+
id: category.id, name: category.name,
|
|
160
271
|
prompts: orderedItems(category.id),
|
|
161
272
|
})),
|
|
162
|
-
{ name: text("Other", "其他"), prompts: orderedItems(null) },
|
|
273
|
+
{ id:"other", name: text("Other", "其他"), prompts: orderedItems(null) },
|
|
163
274
|
];
|
|
164
|
-
for (const section of sections.filter((section) => section.prompts.length)) {
|
|
275
|
+
for (const section of sections.filter((section) => section.prompts.length && (quickCategory === "all" || section.id === quickCategory))) {
|
|
165
276
|
list.append(element("div", "qp-header", section.name));
|
|
166
277
|
for (const item of section.prompts) {
|
|
167
278
|
const row = element("div", "qp-row");
|
|
@@ -192,10 +303,15 @@ function renderList() {
|
|
|
192
303
|
insert.append(
|
|
193
304
|
element("span", "qp-preview", item.body.replace(/\s+/g, " ")),
|
|
194
305
|
);
|
|
306
|
+
insert.addEventListener("pointerenter", () => showQuickPreview(item, insert));
|
|
307
|
+
insert.addEventListener("focus", () => showQuickPreview(item, insert));
|
|
308
|
+
insert.addEventListener("pointerleave", () => { clearTimeout(quickPreviewTimer); quickPreviewTimer = setTimeout(() => clearQuickPreview(), 100); });
|
|
309
|
+
insert.addEventListener("blur", () => clearQuickPreview());
|
|
195
310
|
row.append(insert);
|
|
196
311
|
list.append(row);
|
|
197
312
|
}
|
|
198
313
|
}
|
|
314
|
+
if (!list.children.length) list.append(element("div", "qp-empty", text("No prompts yet", "还没有提示词")));
|
|
199
315
|
panel.append(list);
|
|
200
316
|
position();
|
|
201
317
|
}
|
|
@@ -292,6 +408,9 @@ let page = null;
|
|
|
292
408
|
let pageGeneration = 0;
|
|
293
409
|
let activeCategory = "all";
|
|
294
410
|
let pageSort = "manual";
|
|
411
|
+
let pageView = "cards";
|
|
412
|
+
try { pageView = localStorage.getItem("minecodex.prompts.view") === "list" ? "list" : "cards"; } catch {}
|
|
413
|
+
let cardResizeObserver = null;
|
|
295
414
|
let searchText = "";
|
|
296
415
|
let editor = null;
|
|
297
416
|
let pageFocus = null;
|
|
@@ -329,6 +448,8 @@ function restoreNavigationSelection() {
|
|
|
329
448
|
}
|
|
330
449
|
function closePage(restoreFocus = false, restoreNavigation = true) {
|
|
331
450
|
dragState?.cancel();
|
|
451
|
+
closeImagePreview();
|
|
452
|
+
cardResizeObserver?.disconnect();
|
|
332
453
|
pageGeneration++;
|
|
333
454
|
closePagePopup();
|
|
334
455
|
closeEditor(false);
|
|
@@ -381,7 +502,7 @@ function openPage() {
|
|
|
381
502
|
syncNavigationSelection();
|
|
382
503
|
positionPage();
|
|
383
504
|
page.append(element("div", "pm-empty", text("Loading…", "加载中…")));
|
|
384
|
-
|
|
505
|
+
return loadPage();
|
|
385
506
|
}
|
|
386
507
|
let pagePopup = null;
|
|
387
508
|
let popupTrigger = null;
|
|
@@ -541,6 +662,7 @@ function renderPage() {
|
|
|
541
662
|
actions.append(
|
|
542
663
|
sortButton,
|
|
543
664
|
pageIcon(text("Edit categories", "编辑分类"), "settings", manageCategories),
|
|
665
|
+
viewSwitcher(),
|
|
544
666
|
searchField,
|
|
545
667
|
pageControl(text("New prompt", "新建提示词"), () => editPrompt(), true),
|
|
546
668
|
);
|
|
@@ -594,7 +716,10 @@ function renderPage() {
|
|
|
594
716
|
renderRows(list);
|
|
595
717
|
}
|
|
596
718
|
function renderRows(list) {
|
|
719
|
+
closeImagePreview();
|
|
720
|
+
cardResizeObserver?.disconnect();
|
|
597
721
|
list.replaceChildren();
|
|
722
|
+
list.dataset.view = pageView;
|
|
598
723
|
const query = searchText.trim().toLocaleLowerCase();
|
|
599
724
|
const groups = [...categories, { id: null, name: text("Other", "其他") }];
|
|
600
725
|
let shown = items.filter(
|
|
@@ -617,21 +742,28 @@ function renderRows(list) {
|
|
|
617
742
|
if (pageSort === "recent")
|
|
618
743
|
shown.sort((a, b) => (b.calledAt ?? 0) - (a.calledAt ?? 0));
|
|
619
744
|
const sections =
|
|
620
|
-
pageSort === "manual"
|
|
745
|
+
(pageSort === "manual" || pageView === "cards")
|
|
621
746
|
? groups
|
|
622
747
|
.map((c) => ({
|
|
623
748
|
name: c.name,
|
|
624
|
-
items:
|
|
749
|
+
items: pageSort === "manual"
|
|
750
|
+
? orderedItems(c.id).filter((p) => shown.includes(p))
|
|
751
|
+
: shown.filter((p) => p.categoryId === c.id),
|
|
625
752
|
}))
|
|
626
753
|
.filter((c) => c.items.length)
|
|
627
754
|
: [{ items: shown }];
|
|
628
755
|
for (const section of sections) {
|
|
629
756
|
if (section.name && activeCategory === "all")
|
|
630
757
|
list.append(element("h2", "", section.name));
|
|
758
|
+
if (pageView === "cards") {
|
|
759
|
+
list.append(renderCardSection(section));
|
|
760
|
+
continue;
|
|
761
|
+
}
|
|
631
762
|
for (const item of section.items) {
|
|
632
763
|
const row = element("div", "pm-row");
|
|
633
764
|
row.dataset.promptId = item.id;
|
|
634
|
-
const
|
|
765
|
+
const use = control(text(`Use ${item.summary}`, `使用 ${item.summary}`), () => void usePagePrompt(item, use), "pm-list-use");
|
|
766
|
+
const info = element("div", "pm-info");
|
|
635
767
|
info.replaceChildren(
|
|
636
768
|
element("div", "pm-title", item.summary),
|
|
637
769
|
element("div", "pm-preview", item.body.replace(/\s+/g, " ")),
|
|
@@ -650,7 +782,8 @@ function renderRows(list) {
|
|
|
650
782
|
: text(`${item.useCount} ${item.useCount === 1 ? "call" : "calls"}`, `${item.useCount} 次调用`),
|
|
651
783
|
),
|
|
652
784
|
);
|
|
653
|
-
|
|
785
|
+
use.replaceChildren(categoryIcon(item), info, stats);
|
|
786
|
+
row.append(use, pageIcon(text("Edit prompt", "编辑提示词"), "square-pen", () => editPrompt(item)));
|
|
654
787
|
if (pageSort === "manual" && !query)
|
|
655
788
|
row.append(
|
|
656
789
|
orderControls(item, orderedItems(item.categoryId), false, row),
|
|
@@ -659,6 +792,241 @@ function renderRows(list) {
|
|
|
659
792
|
}
|
|
660
793
|
}
|
|
661
794
|
}
|
|
795
|
+
function viewSwitcher() {
|
|
796
|
+
const group = element("div", "pm-view-switch");
|
|
797
|
+
group.setAttribute("role", "group");
|
|
798
|
+
group.setAttribute("aria-label", text("View", "视图"));
|
|
799
|
+
for (const [value, label] of [["cards", text("Cards", "卡片")], ["list", text("List", "列表")]]) {
|
|
800
|
+
const button = control(label, () => {
|
|
801
|
+
pageView = value;
|
|
802
|
+
try { localStorage.setItem("minecodex.prompts.view", value); } catch {}
|
|
803
|
+
for (const child of group.children) child.setAttribute("aria-pressed", String(child === button));
|
|
804
|
+
renderRows(page.querySelector(".pm-list"));
|
|
805
|
+
}, "pm-view-option", value === "cards" ? "layout-grid" : "list");
|
|
806
|
+
button.setAttribute("aria-pressed", String(pageView === value));
|
|
807
|
+
group.append(button);
|
|
808
|
+
}
|
|
809
|
+
return group;
|
|
810
|
+
}
|
|
811
|
+
function cardPreview(item) {
|
|
812
|
+
// 当前只有分类语义,占位图不写入用户提示词,也不冒充生成结果。
|
|
813
|
+
const category = categories.find((c) => c.id === item.categoryId);
|
|
814
|
+
if (!/^(生图|图像生成|图片生成|image generation|images?)$/i.test(category?.name?.trim() ?? "")) return null;
|
|
815
|
+
const previews = config.resources.previews ?? [];
|
|
816
|
+
const index = orderedItems(item.categoryId).findIndex((p) => p.id === item.id);
|
|
817
|
+
return previews[index % previews.length] ?? null;
|
|
818
|
+
}
|
|
819
|
+
async function usePagePrompt(item, trigger) {
|
|
820
|
+
trigger.disabled = true;
|
|
821
|
+
closePage();
|
|
822
|
+
try {
|
|
823
|
+
// Page 归还原路由后等待输入框挂载;不自动发送消息。
|
|
824
|
+
let editable = null;
|
|
825
|
+
for (let attempt = 0; attempt < 40 && !signal.aborted; attempt++) {
|
|
826
|
+
editable = config.codex.composer(null, { purpose: "insertion" })?.editable;
|
|
827
|
+
if (editable) break;
|
|
828
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
829
|
+
}
|
|
830
|
+
if (signal.aborted) return;
|
|
831
|
+
if (!editable) throw new Error("Open a chat before using a prompt.");
|
|
832
|
+
window.__codexPersonalRuntime.insertText(item.body, editable);
|
|
833
|
+
} catch (error) {
|
|
834
|
+
await openPage();
|
|
835
|
+
pageError(error);
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
try {
|
|
839
|
+
await api(`/api/prompts/${encodeURIComponent(item.id)}/use`, {
|
|
840
|
+
method: "POST", body: { action: "insert", success: true },
|
|
841
|
+
});
|
|
842
|
+
} catch (error) {
|
|
843
|
+
// 正文已插入,计数失败不能再次插入。
|
|
844
|
+
console.warn("[Prompts] Usage could not be saved", error);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
let imagePreview = null;
|
|
848
|
+
let imagePreviewAnchor = null;
|
|
849
|
+
let imagePreviewTimer = null;
|
|
850
|
+
let imagePreviewSpotlight = null;
|
|
851
|
+
let imagePreviewExitTimer = null;
|
|
852
|
+
const previewReducedMotion = () => matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
853
|
+
function tweenPreview(node, target, duration) {
|
|
854
|
+
if (!node) return;
|
|
855
|
+
const computed = getComputedStyle(node);
|
|
856
|
+
const from = { opacity:computed.opacity, transform:computed.transform };
|
|
857
|
+
node.getAnimations().forEach((animation) => animation.cancel());
|
|
858
|
+
node.animate([from, target], { duration, easing:"cubic-bezier(.22,1,.36,1)", fill:"forwards" });
|
|
859
|
+
}
|
|
860
|
+
function retainImagePreview() {
|
|
861
|
+
clearTimeout(imagePreviewTimer);
|
|
862
|
+
if (imagePreviewExitTimer === null) return;
|
|
863
|
+
clearTimeout(imagePreviewExitTimer);
|
|
864
|
+
imagePreviewExitTimer = null;
|
|
865
|
+
tweenPreview(imagePreview, { opacity:1, transform:"none" }, 180);
|
|
866
|
+
tweenPreview(imagePreviewSpotlight?.overlay, { opacity:1, transform:"none" }, 180);
|
|
867
|
+
}
|
|
868
|
+
function dismissImagePreview() {
|
|
869
|
+
clearTimeout(imagePreviewTimer);
|
|
870
|
+
if (!imagePreview || previewReducedMotion()) { closeImagePreview(); return; }
|
|
871
|
+
if (imagePreviewExitTimer !== null) return;
|
|
872
|
+
tweenPreview(imagePreview, { opacity:0, transform:"scale(.97)" }, 160);
|
|
873
|
+
tweenPreview(imagePreviewSpotlight?.overlay, { opacity:0, transform:"none" }, 180);
|
|
874
|
+
imagePreviewExitTimer = setTimeout(closeImagePreview, 180);
|
|
875
|
+
}
|
|
876
|
+
function closeImagePreview() {
|
|
877
|
+
clearTimeout(imagePreviewExitTimer);
|
|
878
|
+
imagePreviewExitTimer = null;
|
|
879
|
+
clearTimeout(imagePreviewTimer);
|
|
880
|
+
imagePreviewAnchor?.removeAttribute("aria-describedby");
|
|
881
|
+
imagePreview?.remove();
|
|
882
|
+
if (imagePreviewSpotlight) {
|
|
883
|
+
const { card, placeholder, layer, overlay, cssText } = imagePreviewSpotlight;
|
|
884
|
+
card.style.cssText = cssText;
|
|
885
|
+
placeholder.replaceWith(card);
|
|
886
|
+
layer.remove();
|
|
887
|
+
overlay.remove();
|
|
888
|
+
imagePreviewSpotlight = null;
|
|
889
|
+
}
|
|
890
|
+
imagePreview = null;
|
|
891
|
+
imagePreviewAnchor = null;
|
|
892
|
+
}
|
|
893
|
+
function deferImagePreviewClose() {
|
|
894
|
+
if (document.activeElement === imagePreviewAnchor) return;
|
|
895
|
+
clearTimeout(imagePreviewTimer);
|
|
896
|
+
imagePreviewTimer = setTimeout(dismissImagePreview, 100);
|
|
897
|
+
}
|
|
898
|
+
function showImagePreview(anchor, preview, title) {
|
|
899
|
+
if (imagePreviewAnchor === anchor && imagePreview) {
|
|
900
|
+
retainImagePreview();
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
closeImagePreview();
|
|
904
|
+
imagePreviewAnchor = anchor;
|
|
905
|
+
imagePreviewTimer = setTimeout(() => {
|
|
906
|
+
if (!anchor.isConnected || !page || signal.aborted) return;
|
|
907
|
+
const panel = element("div", "pm-image-preview");
|
|
908
|
+
panel.id = "mcx-prompt-image-preview";
|
|
909
|
+
panel.setAttribute("role", "tooltip");
|
|
910
|
+
config.ui.surface(panel, "popover");
|
|
911
|
+
const image = element("img");
|
|
912
|
+
image.alt = text(`Full image: ${title}`, `完整图片:${title}`);
|
|
913
|
+
const position = () => {
|
|
914
|
+
if (imagePreview !== panel || !image.naturalWidth) return;
|
|
915
|
+
const r = anchor.getBoundingClientRect();
|
|
916
|
+
const scale = Math.min(520 / image.naturalWidth, (innerHeight - 40) / image.naturalHeight, (innerWidth - 40) / image.naturalWidth, 640 / image.naturalHeight);
|
|
917
|
+
const width = image.naturalWidth * scale;
|
|
918
|
+
const height = image.naturalHeight * scale;
|
|
919
|
+
panel.style.width = `${width}px`;
|
|
920
|
+
panel.style.height = `${height}px`;
|
|
921
|
+
const right = r.right + 12;
|
|
922
|
+
const left = r.left - width - 12;
|
|
923
|
+
panel.style.left = `${Math.max(14, Math.min(right + width <= innerWidth - 14 ? right : left >= 14 ? left : r.left + (r.width - width) / 2, innerWidth - width - 14))}px`;
|
|
924
|
+
panel.style.top = `${Math.max(14, Math.min(r.top + (r.height - height) / 2, innerHeight - height - 14))}px`;
|
|
925
|
+
panel.style.transformOrigin = `${Math.max(0, Math.min(width, r.left + r.width / 2 - parseFloat(panel.style.left)))}px ${Math.max(0, Math.min(height, r.top + r.height / 2 - parseFloat(panel.style.top)))}px`;
|
|
926
|
+
panel.style.visibility = "visible";
|
|
927
|
+
if (!panel.dataset.entered && !previewReducedMotion()) {
|
|
928
|
+
panel.animate([{ opacity:0, transform:"scale(.96)" }, { opacity:1, transform:"none" }], { duration:240, easing:"cubic-bezier(.22,1,.36,1)", fill:"forwards" });
|
|
929
|
+
}
|
|
930
|
+
panel.dataset.entered = "true";
|
|
931
|
+
};
|
|
932
|
+
image.addEventListener("load", position, { once: true });
|
|
933
|
+
image.src = preview.data;
|
|
934
|
+
panel.append(image);
|
|
935
|
+
panel.addEventListener("pointerenter", retainImagePreview);
|
|
936
|
+
panel.addEventListener("pointerleave", deferImagePreviewClose);
|
|
937
|
+
imagePreview = panel;
|
|
938
|
+
// 原卡片移入浮层,避开书架的 mask / overflow;占位保持页面不跳动。
|
|
939
|
+
const card = anchor.closest(".pm-card");
|
|
940
|
+
const rect = card.getBoundingClientRect();
|
|
941
|
+
const placeholder = element("div");
|
|
942
|
+
placeholder.style.width = `${rect.width}px`;
|
|
943
|
+
placeholder.style.height = `${rect.height}px`;
|
|
944
|
+
const overlay = element("div", "pm-preview-overlay");
|
|
945
|
+
config.ui.overlay(overlay);
|
|
946
|
+
config.ui.layer(overlay, "floating");
|
|
947
|
+
overlay.addEventListener("pointerdown", dismissImagePreview);
|
|
948
|
+
const layer = element("div", "pm-preview-spotlight");
|
|
949
|
+
layer.setAttribute(MARKER, "page");
|
|
950
|
+
config.ui.layer(layer, "floating");
|
|
951
|
+
const cssText = card.style.cssText;
|
|
952
|
+
imagePreviewSpotlight = { card, placeholder, layer, overlay, cssText };
|
|
953
|
+
card.replaceWith(placeholder);
|
|
954
|
+
Object.assign(card.style, { position:"absolute", left:`${rect.left}px`, top:`${rect.top}px`, width:`${rect.width}px`, height:`${rect.height}px`, pointerEvents:"auto" });
|
|
955
|
+
layer.append(card);
|
|
956
|
+
document.body.append(overlay, layer);
|
|
957
|
+
if (!previewReducedMotion()) overlay.animate([{ opacity:0 }, { opacity:1 }], { duration:220, easing:"cubic-bezier(.22,1,.36,1)", fill:"forwards" });
|
|
958
|
+
anchor.setAttribute("aria-describedby", panel.id);
|
|
959
|
+
document.body.append(panel);
|
|
960
|
+
position();
|
|
961
|
+
}, 200);
|
|
962
|
+
}
|
|
963
|
+
window.addEventListener("scroll", closeImagePreview, { capture:true, signal });
|
|
964
|
+
window.addEventListener("resize", closeImagePreview, { signal });
|
|
965
|
+
window.addEventListener("blur", closeImagePreview, { signal });
|
|
966
|
+
window.addEventListener("keydown", (event) => {
|
|
967
|
+
if (event.key === "Escape" && imagePreviewAnchor) {
|
|
968
|
+
event.preventDefault();
|
|
969
|
+
event.stopImmediatePropagation();
|
|
970
|
+
dismissImagePreview();
|
|
971
|
+
}
|
|
972
|
+
}, { capture:true, signal });
|
|
973
|
+
signal.addEventListener("abort", closeImagePreview, { once:true });
|
|
974
|
+
function renderCardSection(section) {
|
|
975
|
+
const shelf = element("div", activeCategory === "all" ? "pm-card-shelf" : "pm-card-grid");
|
|
976
|
+
if (activeCategory === "all") {
|
|
977
|
+
shelf.tabIndex = 0;
|
|
978
|
+
shelf.setAttribute("role", "region");
|
|
979
|
+
shelf.setAttribute("aria-label", section.name);
|
|
980
|
+
const updateEdges = () => {
|
|
981
|
+
shelf.dataset.left = String(shelf.scrollLeft > 3);
|
|
982
|
+
shelf.dataset.right = String(shelf.scrollLeft + shelf.clientWidth < shelf.scrollWidth - 3);
|
|
983
|
+
};
|
|
984
|
+
shelf.addEventListener("scroll", updateEdges, { passive: true });
|
|
985
|
+
cardResizeObserver ??= new ResizeObserver((entries) => {
|
|
986
|
+
for (const { target } of entries) target.dispatchEvent(new Event("scroll"));
|
|
987
|
+
});
|
|
988
|
+
cardResizeObserver.observe(shelf);
|
|
989
|
+
requestAnimationFrame(updateEdges);
|
|
990
|
+
}
|
|
991
|
+
for (const item of section.items) {
|
|
992
|
+
const preview = cardPreview(item);
|
|
993
|
+
const card = element("article", `pm-card${preview ? " pm-card-image" : ""}`);
|
|
994
|
+
card.dataset.promptId = item.id;
|
|
995
|
+
card.addEventListener("pointerenter", () => {
|
|
996
|
+
if (imagePreviewSpotlight?.card === card) retainImagePreview();
|
|
997
|
+
});
|
|
998
|
+
card.addEventListener("pointerleave", () => {
|
|
999
|
+
if (imagePreviewSpotlight?.card === card) deferImagePreviewClose();
|
|
1000
|
+
});
|
|
1001
|
+
if (preview) {
|
|
1002
|
+
const cover = control(text("Edit prompt", "编辑提示词"), () => editPrompt(item), "pm-card-cover");
|
|
1003
|
+
const image = element("img");
|
|
1004
|
+
image.src = preview.data;
|
|
1005
|
+
image.alt = "";
|
|
1006
|
+
image.loading = "lazy";
|
|
1007
|
+
cover.replaceChildren(image);
|
|
1008
|
+
cover.addEventListener("pointerenter", (event) => {
|
|
1009
|
+
if (event.pointerType !== "touch") showImagePreview(cover, preview, item.summary);
|
|
1010
|
+
});
|
|
1011
|
+
cover.addEventListener("pointerleave", (event) => {
|
|
1012
|
+
if (!card.contains(event.relatedTarget)) deferImagePreviewClose();
|
|
1013
|
+
});
|
|
1014
|
+
cover.addEventListener("focus", () => showImagePreview(cover, preview, item.summary));
|
|
1015
|
+
cover.addEventListener("blur", deferImagePreviewClose);
|
|
1016
|
+
cover.addEventListener("click", closeImagePreview);
|
|
1017
|
+
card.append(cover);
|
|
1018
|
+
}
|
|
1019
|
+
const content = control(item.summary, () => editPrompt(item), "pm-card-content");
|
|
1020
|
+
content.replaceChildren(categoryIcon(item), element("h3", "pm-card-title", item.summary), element("p", "pm-card-body", item.body));
|
|
1021
|
+
const footer = element("div", "pm-card-footer");
|
|
1022
|
+
const use = pageControl(text("Use", "使用"), () => void usePagePrompt(item, use));
|
|
1023
|
+
use.setAttribute("aria-label", text(`Use ${item.summary}`, `使用 ${item.summary}`));
|
|
1024
|
+
footer.append(element("span", "pm-count", text(`${item.useCount} ${item.useCount === 1 ? "call" : "calls"}`, `${item.useCount} 次调用`)), use);
|
|
1025
|
+
card.append(content, footer);
|
|
1026
|
+
shelf.append(card);
|
|
1027
|
+
}
|
|
1028
|
+
return shelf;
|
|
1029
|
+
}
|
|
662
1030
|
function emptyState(searching) {
|
|
663
1031
|
const empty = element("div", "pm-empty-state");
|
|
664
1032
|
const art = element("span", "pm-empty-art", searching ? "🔎" : "📖");
|
|
@@ -876,6 +1244,7 @@ function editorShell(title, back = null) {
|
|
|
876
1244
|
return editor;
|
|
877
1245
|
}
|
|
878
1246
|
function editPrompt(item = null) {
|
|
1247
|
+
closeImagePreview();
|
|
879
1248
|
const target = editorShell(
|
|
880
1249
|
item ? text("Edit prompt", "编辑提示词") : text("New prompt", "新建提示词"),
|
|
881
1250
|
);
|
|
@@ -1345,6 +1714,7 @@ document.addEventListener(
|
|
|
1345
1714
|
if (
|
|
1346
1715
|
panel &&
|
|
1347
1716
|
!panel.contains(event.target) &&
|
|
1717
|
+
!quickPreview?.node.contains(event.target) &&
|
|
1348
1718
|
!button?.contains(event.target)
|
|
1349
1719
|
)
|
|
1350
1720
|
close();
|
|
@@ -1373,7 +1743,7 @@ document.addEventListener(
|
|
|
1373
1743
|
},
|
|
1374
1744
|
{ signal, capture: true },
|
|
1375
1745
|
);
|
|
1376
|
-
window.addEventListener("resize", position, { signal });
|
|
1746
|
+
window.addEventListener("resize", () => { clearQuickPreview(true); position(); }, { signal });
|
|
1377
1747
|
window.addEventListener("scroll", position, { signal, capture: true });
|
|
1378
1748
|
sync();
|
|
1379
1749
|
|
|
@@ -9,5 +9,8 @@
|
|
|
9
9
|
"settings": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M6.33374 8.97461C7.54786 8.97484 8.56163 9.83236 8.80347 10.9746H13.3337C13.6235 10.9749 13.8591 11.2102 13.8591 11.5C13.8591 11.7898 13.6235 12.0251 13.3337 12.0254H8.80347C8.56163 13.1676 7.54786 14.0252 6.33374 14.0254C5.11907 14.0254 4.10455 13.1673 3.86304 12.0244L2.66675 12.0254C2.37691 12.0253 2.14138 11.7899 2.14136 11.5C2.14136 11.2102 2.37693 10.9748 2.66675 10.9746H3.86304C4.10491 9.83221 5.11941 8.97461 6.33374 8.97461ZM6.33374 10.0254C5.51912 10.0254 4.85913 10.6854 4.85913 11.5C4.85913 12.3146 5.51912 12.9746 6.33374 12.9746C7.14814 12.9743 7.80835 12.3145 7.80835 11.5C7.80835 10.6855 7.14814 10.0257 6.33374 10.0254Z\" fill=\"currentColor\"/> <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M9.66675 1.97461C10.881 1.97461 11.8935 2.83236 12.1355 3.97461H13.3328C13.6227 3.97459 13.8581 4.21005 13.8582 4.5C13.8581 4.78993 13.6227 5.02537 13.3328 5.02539H12.1365C11.8946 6.16774 10.881 7.02539 9.66675 7.02539C8.45245 7.02539 7.43893 6.16774 7.19702 5.02539H2.66675C2.3768 5.02539 2.14136 4.78995 2.14136 4.5C2.14136 4.21005 2.3768 3.97461 2.66675 3.97461H7.19702C7.43893 2.83226 8.45245 1.97461 9.66675 1.97461ZM9.66675 3.02539C8.85213 3.02539 8.19214 3.68538 8.19214 4.5C8.19214 5.31462 8.85213 5.97461 9.66675 5.97461C10.4814 5.97461 11.1414 5.31462 11.1414 4.5C11.1414 3.68538 10.4814 3.02539 9.66675 3.02539Z\" fill=\"currentColor\"/></svg>",
|
|
10
10
|
"drag": "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path d=\"M4 5h16\" />\n <path d=\"M4 12h16\" />\n <path d=\"M4 19h16\" />\n</svg>\n",
|
|
11
11
|
"prompt-nav": "<svg\n class=\"lucide lucide-book-open\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"-1.5 -1.5 27 27\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path d=\"M12 7v14 M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z\" />\n</svg>",
|
|
12
|
-
"prompt-nav-selected": "<svg width=\"20\" height=\"20\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M240,56V200a8,8,0,0,1-8,8H160a24,24,0,0,0-24,23.94,7.9,7.9,0,0,1-5.12,7.55A8,8,0,0,1,120,232a24,24,0,0,0-24-24H24a8,8,0,0,1-8-8V56a8,8,0,0,1,8-8H88a32,32,0,0,1,32,32v87.73a8.17,8.17,0,0,0,7.47,8.25,8,8,0,0,0,8.53-8V80a32,32,0,0,1,32-32h64A8,8,0,0,1,240,56Z\"/></svg>"
|
|
12
|
+
"prompt-nav-selected": "<svg width=\"20\" height=\"20\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M240,56V200a8,8,0,0,1-8,8H160a24,24,0,0,0-24,23.94,7.9,7.9,0,0,1-5.12,7.55A8,8,0,0,1,120,232a24,24,0,0,0-24-24H24a8,8,0,0,1-8-8V56a8,8,0,0,1,8-8H88a32,32,0,0,1,32,32v87.73a8.17,8.17,0,0,0,7.47,8.25,8,8,0,0,0,8.53-8V80a32,32,0,0,1,32-32h64A8,8,0,0,1,240,56Z\"/></svg>",
|
|
13
|
+
"layout-grid": "<!-- Lucide, ISC license; see assets/brand/references/lucide-LICENSE.txt -->\n<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <rect width=\"7\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"3\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"14\" y=\"14\" rx=\"1\" />\n <rect width=\"7\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\" />\n</svg>\n",
|
|
14
|
+
"list": "<!-- Lucide, ISC license; see assets/brand/references/lucide-LICENSE.txt -->\n<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path d=\"M3 5h.01\" />\n <path d=\"M3 12h.01\" />\n <path d=\"M3 19h.01\" />\n <path d=\"M8 5h13\" />\n <path d=\"M8 12h13\" />\n <path d=\"M8 19h13\" />\n</svg>\n",
|
|
15
|
+
"square-pen": "<!-- Lucide, ISC license; see assets/brand/references/lucide-LICENSE.txt -->\n<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path d=\"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\n <path d=\"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z\" />\n</svg>\n"
|
|
13
16
|
}
|
|
@@ -108,3 +108,66 @@
|
|
|
108
108
|
:is([data-minecodex-quick-prompts=page],[data-minecodex-quick-prompts=modal]) .pm-emoji-grid { display:grid; grid-template-columns:repeat(8,minmax(0,1fr)); gap:4px; max-height:264px; overflow:auto; }
|
|
109
109
|
:is([data-minecodex-quick-prompts=page],[data-minecodex-quick-prompts=modal]) .pm-emoji-grid .pm-emoji-choice { width:32px; height:32px; min-height:32px; padding:0; display:flex; justify-content:center; font-size:22px; border-radius:var(--mcx-radius-lg); }
|
|
110
110
|
:is([data-minecodex-quick-prompts=page],[data-minecodex-quick-prompts=modal]) .pm-emoji-choice[aria-pressed=true] { background:var(--mcx-color-background-primary-ghost-hover); }
|
|
111
|
+
|
|
112
|
+
/* 全页面卡片:All 横向书架,单分类自适应网格。 */
|
|
113
|
+
[data-minecodex-quick-prompts=page] {
|
|
114
|
+
--pm-card-width:292px;
|
|
115
|
+
--pm-card-height:344px;
|
|
116
|
+
--pm-image-card-height:416px;
|
|
117
|
+
--pm-card-gap:16px;
|
|
118
|
+
}
|
|
119
|
+
[data-minecodex-quick-prompts=page] .pm-view-switch { display:flex; flex:none; gap:2px; padding:3px; border-radius:var(--mcx-radius-full); background:var(--mcx-color-background-primary-ghost-hover); }
|
|
120
|
+
[data-minecodex-quick-prompts=page] .pm-view-option { display:flex; align-items:center; justify-content:center; width:32px; height:28px; padding:0; border-radius:inherit; color:var(--mcx-color-text-secondary); white-space:nowrap; }
|
|
121
|
+
[data-minecodex-quick-prompts=page] .pm-view-option[aria-pressed=true] { background:var(--mcx-color-surface); color:var(--mcx-color-text-primary); box-shadow:0 1px 4px #00000012; }
|
|
122
|
+
[data-minecodex-quick-prompts=page] .pm-list[data-view=cards] { gap:0; }
|
|
123
|
+
[data-minecodex-quick-prompts=page] .pm-list[data-view=cards]>h2 { margin:24px 0 14px; }
|
|
124
|
+
[data-minecodex-quick-prompts=page] .pm-card-shelf { display:grid; grid-auto-flow:column; grid-auto-columns:min(var(--pm-card-width), 86%); gap:var(--pm-card-gap); overflow-x:auto; overscroll-behavior-x:contain; scroll-snap-type:x proximity; scroll-padding-inline:2px; padding:4px 2px 18px; margin:0 -2px 8px; scrollbar-width:thin; --pm-fade-left:#000; --pm-fade-right:#000; mask-image:linear-gradient(to right,var(--pm-fade-left),#000 32px,#000 calc(100% - 48px),var(--pm-fade-right)); }
|
|
125
|
+
[data-minecodex-quick-prompts=page] .pm-card-shelf[data-left=true] { --pm-fade-left:transparent; }
|
|
126
|
+
[data-minecodex-quick-prompts=page] .pm-card-shelf[data-right=true] { --pm-fade-right:transparent; }
|
|
127
|
+
[data-minecodex-quick-prompts=page] .pm-card-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(min(100%,260px),1fr)); gap:var(--pm-card-gap); padding:4px 2px 18px; }
|
|
128
|
+
[data-minecodex-quick-prompts=page] .pm-card { display:flex; flex-direction:column; height:var(--pm-card-height); min-width:0; border:1px solid var(--mcx-color-border-subtle,var(--mcx-color-border)); border-radius:var(--mcx-radius-2xl); background:var(--mcx-color-surface); box-shadow:0 4px 16px -6px #00000012; scroll-snap-align:start; overflow:hidden; transition:box-shadow 160ms ease,border-color 160ms ease; }
|
|
129
|
+
[data-minecodex-quick-prompts=page] .pm-card:hover, [data-minecodex-quick-prompts=page] .pm-card:focus-within { border-color:var(--mcx-color-border-primary-outline); box-shadow:0 6px 22px -6px #0000001a; }
|
|
130
|
+
[data-minecodex-quick-prompts=page] .pm-card-content { display:flex; flex-direction:column; align-items:flex-start; text-align:left; padding:22px 22px 0; min-height:0; flex:1; overflow:hidden; }
|
|
131
|
+
[data-minecodex-quick-prompts=page] .pm-card-title { margin:14px 0 8px; font-size:var(--mcx-text-base); font-weight:var(--font-weight-medium,500); line-height:1.4; width:100%; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; flex:none; }
|
|
132
|
+
[data-minecodex-quick-prompts=page] .pm-card-body { margin:0; display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:8; overflow:hidden; color:var(--mcx-color-text-tertiary); font-size:var(--mcx-text-sm); line-height:1.65; white-space:pre-line; overflow-wrap:anywhere; }
|
|
133
|
+
[data-minecodex-quick-prompts=page] .pm-card-footer { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:16px 22px 20px; flex:none; }
|
|
134
|
+
[data-minecodex-quick-prompts=page] .pm-card-footer .pm-command { min-height:30px; height:30px; padding:4px 14px; }
|
|
135
|
+
[data-minecodex-quick-prompts=page] .pm-card-image { height:var(--pm-image-card-height); }
|
|
136
|
+
[data-minecodex-quick-prompts=page] .pm-card-cover { position:relative; width:100%; height:160px; flex:none; overflow:hidden; background:var(--mcx-color-background-primary-ghost-hover); padding:0; }
|
|
137
|
+
[data-minecodex-quick-prompts=page] .pm-card-cover img { width:100%; height:100%; object-fit:cover; object-position:center; }
|
|
138
|
+
[data-minecodex-quick-prompts=page] .pm-card-image .pm-card-content { padding-top:18px; }
|
|
139
|
+
[data-minecodex-quick-prompts=page] .pm-card-image .pm-card-body { -webkit-line-clamp:4; }
|
|
140
|
+
@media (max-width:900px) {
|
|
141
|
+
[data-minecodex-quick-prompts=page] .pm-heading { align-items:flex-start; flex-wrap:wrap; }
|
|
142
|
+
[data-minecodex-quick-prompts=page] .pm-header-actions { flex-wrap:wrap; max-width:100%; }
|
|
143
|
+
}
|
|
144
|
+
@media (prefers-reduced-motion:reduce) {
|
|
145
|
+
[data-minecodex-quick-prompts=page] .pm-card { transition:none; }
|
|
146
|
+
}
|
|
147
|
+
[data-minecodex-quick-prompts=page] .pm-card-footer .pm-command { box-shadow:inset 0 0 0 1px var(--mcx-color-border-primary-outline); }
|
|
148
|
+
[data-minecodex-quick-prompts=page] .pm-card-content:focus-visible, [data-minecodex-quick-prompts=page] .pm-card-cover:focus-visible { outline-offset:-3px; }
|
|
149
|
+
|
|
150
|
+
[data-minecodex-quick-prompts=page] .pm-view-option svg { width:16px; height:16px; }
|
|
151
|
+
[data-minecodex-quick-prompts=page] .pm-list-use { display:flex; align-items:center; gap:12px; flex:1; min-width:0; align-self:stretch; text-align:left; }
|
|
152
|
+
|
|
153
|
+
.pm-image-preview { position:fixed; visibility:hidden; padding:0; box-sizing:border-box; border-radius:var(--mcx-radius-2xl); overflow:hidden; }
|
|
154
|
+
.pm-image-preview img { display:block; width:100%; height:100%; object-fit:contain; border-radius:inherit; }
|
|
155
|
+
|
|
156
|
+
.pm-preview-overlay { position:fixed; inset:0; }
|
|
157
|
+
[data-minecodex-quick-prompts=page].pm-preview-spotlight { position:fixed; inset:0; overflow:visible; pointer-events:none; }
|
|
158
|
+
|
|
159
|
+
/* Quick Prompts:固定分类栏,箭头覆盖渐隐尾端,列表保持原生单行密度。 */
|
|
160
|
+
[data-minecodex-quick-prompts=panel] .qp-tabs-bar { position:relative; flex:none; padding:4px 4px 8px; border-bottom:1px solid var(--mcx-color-border); margin-bottom:4px; }
|
|
161
|
+
[data-minecodex-quick-prompts=panel] .qp-tabs { display:flex; gap:2px; overflow-x:auto; scrollbar-width:none; padding-right:var(--qp-arrow-space,0px); }
|
|
162
|
+
[data-minecodex-quick-prompts=panel] .qp-tabs::-webkit-scrollbar { display:none; }
|
|
163
|
+
[data-minecodex-quick-prompts=panel] .qp-tabs-bar[data-overflow=true] .qp-tabs { mask-image:linear-gradient(to right,#000 calc(100% - 90px),transparent calc(100% - 60px)); }
|
|
164
|
+
[data-minecodex-quick-prompts=panel] .qp-tab { flex:none; white-space:nowrap; padding:6px 12px; border-radius:var(--mcx-radius-full); color:var(--mcx-color-text-secondary); }
|
|
165
|
+
[data-minecodex-quick-prompts=panel] .qp-tab[aria-selected=true], [data-minecodex-quick-prompts=panel] .qp-tab:hover, [data-minecodex-quick-prompts=panel] .qp-tab-arrow:hover, [data-minecodex-quick-prompts=panel] .qp-select[data-preview=true] { background:var(--mcx-color-background-primary-ghost-hover); color:var(--mcx-color-text-primary); }
|
|
166
|
+
[data-minecodex-quick-prompts=panel] .qp-tab-arrows { position:absolute; right:4px; top:4px; display:flex; gap:2px; }
|
|
167
|
+
[data-minecodex-quick-prompts=panel] .qp-tab-arrow { display:flex; align-items:center; justify-content:center; width:28px; height:30px; border-radius:var(--mcx-radius-full); }
|
|
168
|
+
[data-minecodex-quick-prompts=panel] .qp-tab-previous svg { transform:rotate(90deg); }
|
|
169
|
+
[data-minecodex-quick-prompts=panel] .qp-tab-next svg { transform:rotate(-90deg); }
|
|
170
|
+
[data-minecodex-quick-prompts=panel] [hidden] { display:none!important; }
|
|
171
|
+
[data-minecodex-quick-prompts=panel] .qp-title { max-width:55%; flex-shrink:0; }
|
|
172
|
+
.qp-image-preview { position:fixed; visibility:hidden; padding:0; overflow:hidden; border-radius:var(--mcx-radius-2xl); transform-origin:left center; }
|
|
173
|
+
.qp-image-preview img { display:block; width:100%; height:100%; object-fit:contain; }
|