@21stware/rpui 0.1.1 → 0.3.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/README.md +47 -87
- package/dist/canvas/annotation.d.ts +6 -0
- package/dist/core/icons.d.ts +1 -1
- package/dist/core/style.d.ts +1 -1
- package/dist/gallery.d.ts +5 -0
- package/dist/gallery.js +2654 -0
- package/dist/gallery.js.map +1 -0
- package/dist/primitives/agent.d.ts +39 -0
- package/dist/primitives/controls.d.ts +21 -0
- package/dist/primitives/data-display.d.ts +75 -0
- package/dist/primitives/ios.d.ts +33 -0
- package/dist/primitives/layout.d.ts +9 -0
- package/dist/primitives/macos.d.ts +33 -0
- package/dist/primitives/navigation.d.ts +21 -0
- package/dist/rpml-loader.d.ts +2 -0
- package/dist/rpml-loader.js +27 -0
- package/dist/rpml-loader.js.map +1 -0
- package/dist/rpui.d.ts +2 -1
- package/dist/rpui.js +1769 -235
- package/dist/rpui.js.map +1 -1
- package/dist/serve/cli.d.ts +1 -0
- package/dist/serve.js +143 -0
- package/package.json +14 -22
- package/LICENSE +0 -20
- package/llms.txt +0 -195
- package/skill.txt +0 -143
package/dist/gallery.js
ADDED
|
@@ -0,0 +1,2654 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
const PRIMITIVES = [
|
|
5
|
+
// layout
|
|
6
|
+
"viewport",
|
|
7
|
+
"layout",
|
|
8
|
+
"panel",
|
|
9
|
+
"sidebar",
|
|
10
|
+
"logo",
|
|
11
|
+
"split-pane",
|
|
12
|
+
"divider",
|
|
13
|
+
"spacer",
|
|
14
|
+
// controls
|
|
15
|
+
"search",
|
|
16
|
+
"input",
|
|
17
|
+
"textarea",
|
|
18
|
+
"select",
|
|
19
|
+
"button",
|
|
20
|
+
"button-group",
|
|
21
|
+
"checkbox",
|
|
22
|
+
"radio",
|
|
23
|
+
"toggle",
|
|
24
|
+
"form",
|
|
25
|
+
"form-item",
|
|
26
|
+
"date-picker",
|
|
27
|
+
"upload",
|
|
28
|
+
"image-placeholder",
|
|
29
|
+
"progress",
|
|
30
|
+
"slider",
|
|
31
|
+
"range",
|
|
32
|
+
"number-input",
|
|
33
|
+
"rating",
|
|
34
|
+
"pin-input",
|
|
35
|
+
"color-swatch",
|
|
36
|
+
"autocomplete",
|
|
37
|
+
// navigation
|
|
38
|
+
"badge",
|
|
39
|
+
"avatar",
|
|
40
|
+
"list",
|
|
41
|
+
"list-item",
|
|
42
|
+
"tabs",
|
|
43
|
+
"tab",
|
|
44
|
+
"pagination",
|
|
45
|
+
"steps",
|
|
46
|
+
"breadcrumb",
|
|
47
|
+
"segmented",
|
|
48
|
+
"command-palette",
|
|
49
|
+
"context-menu",
|
|
50
|
+
"menu",
|
|
51
|
+
"menu-item",
|
|
52
|
+
"toc",
|
|
53
|
+
"kbd",
|
|
54
|
+
// data display
|
|
55
|
+
"table",
|
|
56
|
+
"table-row",
|
|
57
|
+
"bulk-action-bar",
|
|
58
|
+
"empty",
|
|
59
|
+
"loading",
|
|
60
|
+
"alert",
|
|
61
|
+
"toast",
|
|
62
|
+
"dropdown",
|
|
63
|
+
"popover",
|
|
64
|
+
"tooltip",
|
|
65
|
+
"modal",
|
|
66
|
+
"drawer",
|
|
67
|
+
"card",
|
|
68
|
+
"stat-card",
|
|
69
|
+
"tag",
|
|
70
|
+
"chip",
|
|
71
|
+
"tree",
|
|
72
|
+
"tree-item",
|
|
73
|
+
"timeline",
|
|
74
|
+
"timeline-item",
|
|
75
|
+
"calendar",
|
|
76
|
+
"kanban",
|
|
77
|
+
"kanban-column",
|
|
78
|
+
"kanban-card",
|
|
79
|
+
"code-block",
|
|
80
|
+
"diff",
|
|
81
|
+
"image-grid",
|
|
82
|
+
"key-value",
|
|
83
|
+
"kv-row",
|
|
84
|
+
"accordion",
|
|
85
|
+
"accordion-item",
|
|
86
|
+
"banner",
|
|
87
|
+
"skeleton",
|
|
88
|
+
"countdown",
|
|
89
|
+
"result",
|
|
90
|
+
"permission-gate",
|
|
91
|
+
"quota-bar",
|
|
92
|
+
"api-key",
|
|
93
|
+
"audit-row",
|
|
94
|
+
"workflow-node",
|
|
95
|
+
// iOS
|
|
96
|
+
"ios-navbar",
|
|
97
|
+
"ios-tabbar",
|
|
98
|
+
"ios-list",
|
|
99
|
+
"ios-list-item",
|
|
100
|
+
"ios-action-sheet",
|
|
101
|
+
"ios-alert",
|
|
102
|
+
"ios-switch",
|
|
103
|
+
"ios-segmented",
|
|
104
|
+
"ios-button",
|
|
105
|
+
"ios-search",
|
|
106
|
+
"ios-stepper",
|
|
107
|
+
// macOS
|
|
108
|
+
"macos-window",
|
|
109
|
+
"macos-toolbar",
|
|
110
|
+
"macos-menubar",
|
|
111
|
+
"macos-sidebar",
|
|
112
|
+
"macos-source-item",
|
|
113
|
+
"macos-segmented",
|
|
114
|
+
"macos-popover",
|
|
115
|
+
"macos-sheet",
|
|
116
|
+
"macos-stepper",
|
|
117
|
+
"macos-disclosure",
|
|
118
|
+
"macos-table",
|
|
119
|
+
// agent / conversational UI
|
|
120
|
+
"chat",
|
|
121
|
+
"user-message",
|
|
122
|
+
"assistant-message",
|
|
123
|
+
"system-message",
|
|
124
|
+
"tool-call",
|
|
125
|
+
"agent-output",
|
|
126
|
+
"reasoning",
|
|
127
|
+
"message-actions",
|
|
128
|
+
"suggestions",
|
|
129
|
+
"typing",
|
|
130
|
+
"composer",
|
|
131
|
+
"citation",
|
|
132
|
+
"token-usage"
|
|
133
|
+
];
|
|
134
|
+
function primitiveComponentTag(lang) {
|
|
135
|
+
return lang.includes("-") ? lang : `${lang}-el`;
|
|
136
|
+
}
|
|
137
|
+
const EXPLICIT = {
|
|
138
|
+
// canvas
|
|
139
|
+
page: "page-el",
|
|
140
|
+
view: "main-view",
|
|
141
|
+
annotation: "annotation-el",
|
|
142
|
+
enum: "enum-el",
|
|
143
|
+
"enum-item": "enum-item",
|
|
144
|
+
viewport: "viewport-el",
|
|
145
|
+
// curated primitive rename
|
|
146
|
+
navigator: "navbar-el"
|
|
147
|
+
};
|
|
148
|
+
const LANG_TO_COMPONENT = (() => {
|
|
149
|
+
const map = {};
|
|
150
|
+
for (const lang of PRIMITIVES) map[lang] = primitiveComponentTag(lang);
|
|
151
|
+
for (const [lang, comp] of Object.entries(EXPLICIT)) map[lang] = comp;
|
|
152
|
+
return map;
|
|
153
|
+
})();
|
|
154
|
+
(() => {
|
|
155
|
+
const map = {};
|
|
156
|
+
for (const [lang, comp] of Object.entries(LANG_TO_COMPONENT)) map[comp] = lang;
|
|
157
|
+
return map;
|
|
158
|
+
})();
|
|
159
|
+
function toComponentTag(tag) {
|
|
160
|
+
return LANG_TO_COMPONENT[tag.toLowerCase()] ?? tag;
|
|
161
|
+
}
|
|
162
|
+
function expandSelfClosing(source) {
|
|
163
|
+
return source.replace(
|
|
164
|
+
/<([a-zA-Z][\w:-]*)((?:"[^"]*"|'[^']*'|[^>"'])*?)\/>/g,
|
|
165
|
+
(_m, tag, attrs) => `<${tag}${attrs}></${tag}>`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
function rewriteTags(source) {
|
|
169
|
+
return source.replace(
|
|
170
|
+
/<(\/?)([a-zA-Z][\w:-]*)((?:"[^"]*"|'[^']*'|[^>])*)>/g,
|
|
171
|
+
(_m, slash, tag, rest) => `<${slash}${toComponentTag(tag)}${rest}>`
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
function normalize(source) {
|
|
175
|
+
return rewriteTags(expandSelfClosing(source.trim()));
|
|
176
|
+
}
|
|
177
|
+
function parseToPage(source) {
|
|
178
|
+
const holder = document.createElement("div");
|
|
179
|
+
holder.innerHTML = normalize(source);
|
|
180
|
+
const root = holder.querySelector("page-el") ?? holder.firstElementChild;
|
|
181
|
+
if (!root) throw new Error("RPML parse error: no <page> root element found");
|
|
182
|
+
return root;
|
|
183
|
+
}
|
|
184
|
+
function attr(el, name, fallback = "") {
|
|
185
|
+
return el.getAttribute(name) ?? fallback;
|
|
186
|
+
}
|
|
187
|
+
function intAttr(el, name, fallback) {
|
|
188
|
+
const raw = el.getAttribute(name);
|
|
189
|
+
const value = raw === null || raw === "" ? NaN : Number(raw);
|
|
190
|
+
return Number.isFinite(value) ? value : fallback;
|
|
191
|
+
}
|
|
192
|
+
function escapeHtml(value) {
|
|
193
|
+
return value.replace(/[&<>'"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", "'": "'", '"': """ })[c] || c);
|
|
194
|
+
}
|
|
195
|
+
function csv(el, name, fallback) {
|
|
196
|
+
return attr(el, name, fallback).split(",").map((s) => s.trim()).filter(Boolean);
|
|
197
|
+
}
|
|
198
|
+
const deviceWidths = { web: 1440, ipad: 834, mobile: 390 };
|
|
199
|
+
function resolveWidth(el, fallback) {
|
|
200
|
+
const raw = el.getAttribute("width");
|
|
201
|
+
const width = raw === null || raw === "" ? NaN : Number(raw);
|
|
202
|
+
if (Number.isFinite(width)) return width;
|
|
203
|
+
return deviceWidths[attr(el, "device")] ?? fallback;
|
|
204
|
+
}
|
|
205
|
+
function hasExplicitNumericHeight(el) {
|
|
206
|
+
const raw = el.getAttribute("height");
|
|
207
|
+
return raw !== null && raw !== "" && Number.isFinite(Number(raw));
|
|
208
|
+
}
|
|
209
|
+
function usesAutoHeight(el) {
|
|
210
|
+
const raw = el.getAttribute("height");
|
|
211
|
+
return raw === "auto" || el.hasAttribute("auto-height") || !!el.getAttribute("device") && !hasExplicitNumericHeight(el);
|
|
212
|
+
}
|
|
213
|
+
function resolveHeight(el, fallback) {
|
|
214
|
+
const raw = el.getAttribute("height");
|
|
215
|
+
const height = raw === null || raw === "" ? NaN : Number(raw);
|
|
216
|
+
return Number.isFinite(height) ? height : fallback;
|
|
217
|
+
}
|
|
218
|
+
function isTopAnnotation(node) {
|
|
219
|
+
if (!(node instanceof HTMLElement)) return false;
|
|
220
|
+
const tag = node.tagName.toLowerCase();
|
|
221
|
+
return tag === "annotation-el" || tag === "annotation-el";
|
|
222
|
+
}
|
|
223
|
+
function isViewportNode(node) {
|
|
224
|
+
if (!(node instanceof HTMLElement)) return false;
|
|
225
|
+
const tag = node.tagName.toLowerCase();
|
|
226
|
+
return tag === "viewport-el" || tag === "viewport-el";
|
|
227
|
+
}
|
|
228
|
+
function define(name, ctor) {
|
|
229
|
+
if (customElements.get(name)) return;
|
|
230
|
+
const Alias = class extends ctor {
|
|
231
|
+
};
|
|
232
|
+
customElements.define(name, Alias);
|
|
233
|
+
}
|
|
234
|
+
const RPUI_STYLE_ID = "rpui-runtime-style";
|
|
235
|
+
const style = `
|
|
236
|
+
:root { --rp-bg:#f0f2f5; --rp-surface:#fff; --rp-surface-soft:#f9fafb; --rp-text:#111827; --rp-muted:#6b7280; --rp-border:#e5e7eb; --rp-border-strong:#d1d5db; --rp-primary:#2563eb; --rp-success:#059669; --rp-warning:#d97706; --rp-danger:#dc2626; --rp-purple:#7c3aed; --rp-radius-sm:4px; --rp-radius-md:8px; --rp-radius-lg:12px; --rp-shadow:0 8px 28px rgba(15,23,42,.08); --rp-font:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; }
|
|
237
|
+
* { box-sizing:border-box; }
|
|
238
|
+
body { margin:0; font-family:var(--rp-font); color:var(--rp-text); background:var(--rp-bg); }
|
|
239
|
+
.rp-icon { display:inline-block; flex:0 0 auto; vertical-align:-0.16em; }
|
|
240
|
+
page-el, page-el { display:block; min-height:100vh; padding:32px 40px; overflow:auto; }
|
|
241
|
+
.page-el-shell { display:grid; grid-template-columns:max-content max-content; gap:24px; min-height:100vh; align-items:start; }
|
|
242
|
+
.page-el-main { display:flex; flex-direction:column; min-width:0; overflow:visible; }
|
|
243
|
+
.page-el-header { flex:0 0 auto; width:fit-content; max-width:none; margin:0 0 22px; }
|
|
244
|
+
.page-el-title-row { display:flex; align-items:baseline; gap:12px; flex-wrap:wrap; }
|
|
245
|
+
.page-el-title { margin:0; font-size:28px; line-height:1.2; letter-spacing:-.02em; }
|
|
246
|
+
.page-el-route { font-size:13px; color:var(--rp-muted); font-family:ui-monospace,SFMono-Regular,Menlo,monospace; background:rgba(255,255,255,.7); border:1px solid var(--rp-border); border-radius:999px; padding:3px 9px; }
|
|
247
|
+
.page-el-description { margin:10px 0 0; color:#374151; line-height:1.6; font-size:14px; }
|
|
248
|
+
.page-el-body { flex:0 1 auto; display:block; width:fit-content; max-width:100%; min-height:0; overflow:visible; }
|
|
249
|
+
.annotation-el-pane { min-width:380px; max-width:680px; position:sticky; top:0; height:100vh; overflow-y:auto; overflow-x:auto; padding:0 0 48px 0; align-self:start; }
|
|
250
|
+
.annotation-el-pane-inner { padding:4px 12px 24px 6px; }
|
|
251
|
+
main-view, main-view { display:block; width:fit-content; margin:0 0 28px; position:relative; }
|
|
252
|
+
.rp-main-shell { position:relative; overflow:visible; border:1px solid var(--rp-border-strong); border-radius:var(--rp-radius-md); background:var(--rp-surface); box-shadow:var(--rp-shadow); }
|
|
253
|
+
.rp-main-stage-clip { overflow:hidden; border-radius:var(--rp-radius-md); }
|
|
254
|
+
.rp-main-stage { position:relative; transform-origin:top left; background:var(--rp-surface); }
|
|
255
|
+
.rp-pin { position:absolute; z-index:20; display:grid; place-items:center; width:24px; height:24px; color:#fff; font-size:11px; font-weight:700; background:var(--rp-primary); border-radius:50% 50% 50% 0; transform:translate(-6px,-6px) rotate(-45deg); box-shadow:0 2px 8px rgba(37,99,235,.25); cursor:pointer; }
|
|
256
|
+
.rp-pin > span { transform:rotate(45deg); }
|
|
257
|
+
.rp-pin:hover { opacity:0.85; }
|
|
258
|
+
annotation-el, annotation-el { display:block; width:fit-content; max-width:980px; margin:14px 0; line-height:1.65; color:#1f2937; font-size:14px; }
|
|
259
|
+
annotation-el annotation-el, annotation-el annotation-el, annotation-el annotation-el, annotation-el annotation-el { margin:10px 0 8px 22px; }
|
|
260
|
+
.annotation-el-head { display:flex; align-items:center; gap:8px; margin:0 0 4px; width:fit-content; }
|
|
261
|
+
.annotation-el-title { font-weight:700; color:#111827; }
|
|
262
|
+
.annotation-el-marker { display:inline-grid; place-items:center; flex:0 0 auto; color:#fff; font-size:10px; font-weight:700; line-height:1; }
|
|
263
|
+
.annotation-el-marker.drop { width:22px; height:22px; background:var(--rp-primary); border-radius:50% 50% 50% 0; transform:rotate(-45deg); }
|
|
264
|
+
.annotation-el-marker.drop > span { transform:rotate(45deg); }
|
|
265
|
+
.annotation-el-marker.circle { width:16px; height:16px; background:var(--rp-purple); border-radius:50%; }
|
|
266
|
+
.annotation-el-marker.triangle { width:18px; height:16px; background:var(--rp-success); clip-path:polygon(50% 0, 100% 100%, 0 100%); }
|
|
267
|
+
.annotation-el-marker.triangle > span { transform:translateY(2px); font-size:9px; }
|
|
268
|
+
.annotation-el-body { display:block; position:relative; width:fit-content; max-width:920px; }
|
|
269
|
+
.rp-pin-slice { width:18px; height:18px; font-size:10px; box-shadow:0 1px 5px rgba(37,99,235,.3); }
|
|
270
|
+
.annotation-el-body > :not(annotation-el):not(annotation-el):not(enum-el):not(enum-el) { max-width:820px; }
|
|
271
|
+
.annotation-el-pane annotation-el, .annotation-el-pane annotation-el { max-width:none; }
|
|
272
|
+
.annotation-el-pane .annotation-el-body { max-width:none; }
|
|
273
|
+
.annotation-el-pane .annotation-el-body > :not(annotation-el):not(annotation-el):not(enum-el):not(enum-el) { max-width:420px; }
|
|
274
|
+
.annotation-el-body p { margin:0 0 8px; }
|
|
275
|
+
enum-el, enum-el { display:flex; align-items:flex-start; flex-wrap:wrap; gap:10px; width:fit-content; margin:8px 0 12px; }
|
|
276
|
+
.annotation-el-pane enum-el, .annotation-el-pane enum-el { flex-wrap:wrap; }
|
|
277
|
+
enum-item, enum-item { display:block; flex:0 0 auto; width:fit-content; min-width:180px; max-width:600px; border:1px solid #f0f0f0; border-radius:var(--rp-radius-md); background:#fff; overflow:hidden; }
|
|
278
|
+
.enum-el-label { display:flex; align-items:flex-start; gap:6px; padding:5px 9px 4px; font-size:12px; font-weight:650; color:#374151; }
|
|
279
|
+
.enum-el-index { display:inline-grid; place-items:center; min-width:16px; height:16px; padding:0 4px; background:#111827; color:#fff; font-size:10px; font-weight:750; border-radius:3px; flex:0 0 auto; margin-top:1px; }
|
|
280
|
+
.enum-el-label-text { display:block; }
|
|
281
|
+
.enum-el-description { display:block; margin-top:2px; font-size:11px; line-height:1.35; font-weight:400; color:var(--rp-muted); }
|
|
282
|
+
.enum-el-content { display:block; width:fit-content; padding:8px; }
|
|
283
|
+
.annotation-el-title { font-weight:700; color:#111827; cursor:pointer; }
|
|
284
|
+
.annotation-el-title:hover { color:var(--rp-primary); }
|
|
285
|
+
.rp-section-focus { outline:2px dashed var(--rp-primary); outline-offset:4px; border-radius:4px; }
|
|
286
|
+
viewport-el, viewport-el { display:flex; flex-direction:column; width:var(--snap-width,1440px); height:var(--snap-height,900px); background:#f8fafc; overflow:hidden; color:#111827; }
|
|
287
|
+
layout-el, layout-el { display:grid; grid-template-columns:var(--snap-columns,1fr); grid-template-rows:var(--snap-rows,auto); gap:var(--snap-gap,0); align-content:start; width:fit-content; max-width:100%; min-width:0; }
|
|
288
|
+
layout-el > *, layout-el > * { min-width:0; }
|
|
289
|
+
viewport-el layout-el, viewport-el layout-el { width:100%; }
|
|
290
|
+
viewport-el > layout-el, viewport-el > layout-el { flex:1 1 auto; min-height:0; }
|
|
291
|
+
viewport-el > navbar-el, viewport-el > navbar-el { flex:0 0 auto; }
|
|
292
|
+
panel-el, panel-el { display:block; width:fit-content; max-width:100%; background:#fff; border:1px solid var(--rp-border); border-radius:var(--rp-radius-md); padding:var(--snap-padding,16px); }
|
|
293
|
+
viewport-el panel-el, viewport-el panel-el { width:auto; min-width:0; }
|
|
294
|
+
panel-el[elevation="1"], panel-el[elevation="1"] { box-shadow:0 4px 16px rgba(15,23,42,.06); }
|
|
295
|
+
panel-el[elevation="2"], panel-el[elevation="2"] { box-shadow:var(--rp-shadow); }
|
|
296
|
+
navbar-el, navbar-el { display:flex; align-items:center; gap:14px; height:var(--snap-height,64px); padding:0 24px; background:#fff; border-bottom:1px solid var(--rp-border); }
|
|
297
|
+
sidebar-el, sidebar-el { display:block; width:var(--snap-width,260px); min-height:0; background:#fff; border-right:1px solid var(--rp-border); padding:14px; }
|
|
298
|
+
viewport-el sidebar-el, viewport-el sidebar-el { min-height:100%; }
|
|
299
|
+
sidebar-el[collapsed], sidebar-el[collapsed] { width:72px; }
|
|
300
|
+
logo-el, logo-el { display:inline-grid; place-items:center; width:var(--snap-size,82px); height:32px; border-radius:8px; background:#111827; color:#fff; font-size:12px; font-weight:800; letter-spacing:.08em; }
|
|
301
|
+
search-el, search-el, input-el, input-el, date-picker, date-picker { display:inline-flex; align-items:center; gap:8px; width:280px; min-height:36px; padding:0 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; color:#111827; }
|
|
302
|
+
textarea-el, textarea-el { display:block; width:320px; min-height:calc(var(--snap-rows,3) * 24px + 22px); padding:9px 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; color:#111827; white-space:pre-wrap; }
|
|
303
|
+
search-el[state="focus"], search-el[state="focus"], input-el[state="focus"], input-el[state="focus"], textarea-el[state="focus"], textarea-el[state="focus"], date-picker[state="focus"], date-picker[state="focus"] { border-color:var(--rp-primary); box-shadow:0 0 0 3px rgba(37,99,235,.12); }
|
|
304
|
+
search-el[state="filled"], search-el[state="filled"], input-el[state="filled"], input-el[state="filled"], textarea-el[state="filled"], textarea-el[state="filled"], date-picker[state="filled"], date-picker[state="filled"] { border-color:#93c5fd; background:#f8fbff; }
|
|
305
|
+
search-el[state="error"], search-el[state="error"], input-el[state="error"], input-el[state="error"], textarea-el[state="error"], textarea-el[state="error"], date-picker[state="error"], date-picker[state="error"] { border-color:var(--rp-danger); box-shadow:0 0 0 3px rgba(220,38,38,.1); }
|
|
306
|
+
search-el[state="disabled"], search-el[state="disabled"], input-el[state="disabled"], input-el[state="disabled"], textarea-el[state="disabled"], textarea-el[state="disabled"], date-picker[state="disabled"], date-picker[state="disabled"] { opacity:.55; background:#f3f4f6; }
|
|
307
|
+
input-el[label], input-el[label], date-picker[label], date-picker[label] { display:inline-grid; align-items:start; gap:6px; width:280px; min-height:0; padding:0; border:0; background:transparent; box-shadow:none; }
|
|
308
|
+
input-el[label][state="focus"], input-el[label][state="focus"], input-el[label][state="filled"], input-el[label][state="filled"], input-el[label][state="error"], input-el[label][state="error"], date-picker[label][state="focus"], date-picker[label][state="focus"], date-picker[label][state="filled"], date-picker[label][state="filled"], date-picker[label][state="error"], date-picker[label][state="error"] { border:0; background:transparent; box-shadow:none; }
|
|
309
|
+
.rp-field-control { display:flex; align-items:center; gap:8px; min-height:36px; padding:0 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; color:#111827; }
|
|
310
|
+
input-el[state="focus"] .rp-field-control, input-el[state="focus"] .rp-field-control, date-picker[state="focus"] .rp-field-control, date-picker[state="focus"] .rp-field-control { border-color:var(--rp-primary); box-shadow:0 0 0 3px rgba(37,99,235,.12); }
|
|
311
|
+
input-el[state="filled"] .rp-field-control, input-el[state="filled"] .rp-field-control, date-picker[state="filled"] .rp-field-control, date-picker[state="filled"] .rp-field-control { border-color:#93c5fd; background:#f8fbff; }
|
|
312
|
+
input-el[state="error"] .rp-field-control, input-el[state="error"] .rp-field-control, date-picker[state="error"] .rp-field-control, date-picker[state="error"] .rp-field-control { border-color:var(--rp-danger); box-shadow:0 0 0 3px rgba(220,38,38,.1); }
|
|
313
|
+
.rp-field-label { display:block; margin:0 0 6px; color:#374151; font-size:12px; font-weight:650; }
|
|
314
|
+
.rp-placeholder { color:#9ca3af; }
|
|
315
|
+
.rp-value { color:#111827; }
|
|
316
|
+
.rp-error-text { color:var(--rp-danger); font-size:12px; }
|
|
317
|
+
select-el, select-el { display:inline-block; width:280px; max-width:100%; }
|
|
318
|
+
.select-el-control { display:flex; align-items:center; gap:8px; min-height:36px; padding:0 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; }
|
|
319
|
+
select-el[state="expanded"] .select-el-control, select-el[state="expanded"] .select-el-control { border-color:var(--rp-primary); box-shadow:0 0 0 3px rgba(37,99,235,.12); }
|
|
320
|
+
select-el[state="disabled"], select-el[state="disabled"] { opacity:.55; }
|
|
321
|
+
.select-el-value { flex:1 1 auto; min-width:0; }
|
|
322
|
+
.select-el-options { display:none; margin-top:6px; padding:5px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; box-shadow:0 10px 18px rgba(15,23,42,.08); }
|
|
323
|
+
select-el[state="expanded"] .select-el-options, select-el[state="expanded"] .select-el-options { display:grid; gap:2px; }
|
|
324
|
+
.select-el-option { padding:7px 8px; border-radius:6px; font-size:13px; color:#374151; }
|
|
325
|
+
.select-el-option.selected { background:#eff6ff; color:#1d4ed8; font-weight:700; }
|
|
326
|
+
badge-el, badge-el { display:inline-grid; place-items:center; min-width:20px; height:20px; padding:0 6px; border-radius:999px; background:#ef4444; color:#fff; font-size:11px; font-weight:750; }
|
|
327
|
+
avatar-el, avatar-el { display:inline-grid; place-items:center; width:var(--snap-size,32px); height:var(--snap-size,32px); border-radius:999px; background:#e0e7ff; color:#3730a3; font-size:12px; font-weight:800; }
|
|
328
|
+
list-el, list-el { display:flex; flex-direction:column; gap:4px; width:100%; }
|
|
329
|
+
list-item, list-item { display:flex; align-items:center; gap:8px; width:100%; min-width:180px; height:36px; padding:0 10px; border-radius:8px; color:#374151; }
|
|
330
|
+
list-item[state="selected"], list-item[state="selected"] { background:#eff6ff; color:#1d4ed8; font-weight:700; }
|
|
331
|
+
list-item[state="disabled"], list-item[state="disabled"] { opacity:.5; }
|
|
332
|
+
.list-el-label { flex:1 1 auto; }
|
|
333
|
+
.list-el-badge { margin-left:auto; min-width:18px; height:18px; border-radius:999px; display:grid; place-items:center; padding:0 6px; background:#e5e7eb; color:#374151; font-size:11px; font-weight:700; }
|
|
334
|
+
tabs-el, tabs-el { display:flex; gap:6px; border-bottom:1px solid var(--rp-border); margin-bottom:12px; width:fit-content; }
|
|
335
|
+
tab-el, tab-el { display:inline-flex; align-items:center; gap:6px; padding:9px 13px; border-bottom:2px solid transparent; color:#6b7280; font-size:14px; }
|
|
336
|
+
tab-el.tab-el-active, tab-el.tab-el-active { color:var(--rp-primary); border-bottom-color:var(--rp-primary); font-weight:700; }
|
|
337
|
+
button-el, button-el { display:inline-flex; align-items:center; justify-content:center; gap:7px; min-height:34px; padding:0 12px; border-radius:8px; border:1px solid var(--rp-border); background:#fff; color:#374151; font-size:13px; font-weight:650; }
|
|
338
|
+
button-el[size="sm"], button-el[size="sm"] { min-height:28px; padding:0 9px; font-size:12px; border-radius:6px; }
|
|
339
|
+
button-el[size="lg"], button-el[size="lg"] { min-height:40px; padding:0 16px; font-size:14px; }
|
|
340
|
+
button-el[variant="primary"], button-el[variant="primary"] { border-color:var(--rp-primary); background:var(--rp-primary); color:#fff; }
|
|
341
|
+
button-el[variant="secondary"], button-el[variant="secondary"] { border-color:#bfdbfe; background:#eff6ff; color:#1d4ed8; }
|
|
342
|
+
button-el[variant="danger"], button-el[variant="danger"] { border-color:var(--rp-danger); color:var(--rp-danger); }
|
|
343
|
+
button-el[variant="link"], button-el[variant="link"] { border-color:transparent; background:transparent; color:var(--rp-primary); padding-inline:2px; }
|
|
344
|
+
button-el[variant="ghost"], button-el[variant="ghost"] { border-color:transparent; background:transparent; }
|
|
345
|
+
button-el[state="disabled"], button-el[state="disabled"], button-el[disabled], button-el[disabled] { opacity:.5; }
|
|
346
|
+
button-group, button-group { display:inline-flex; gap:0; width:fit-content; }
|
|
347
|
+
button-group > button-el, button-group > button-el { border-radius:0; margin-left:-1px; }
|
|
348
|
+
button-group > :first-child { border-radius:8px 0 0 8px; margin-left:0; }
|
|
349
|
+
button-group > :last-child { border-radius:0 8px 8px 0; }
|
|
350
|
+
table-el, table-el { display:table; border-collapse:collapse; width:fit-content; min-width:720px; max-width:980px; background:#fff; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
|
|
351
|
+
viewport-el table-el, viewport-el table-el { width:100%; max-width:none; }
|
|
352
|
+
.table-row { display:table-row; }
|
|
353
|
+
.table-el-cell { display:table-cell; padding:11px 12px; border-bottom:1px solid var(--rp-border); font-size:13px; vertical-align:middle; white-space:nowrap; }
|
|
354
|
+
.table-el-head .table-el-cell { background:#f9fafb; color:#6b7280; font-size:12px; font-weight:750; }
|
|
355
|
+
.table-row:last-child .table-el-cell { border-bottom:0; }
|
|
356
|
+
table-row, table-row { display:grid; grid-template-columns:44px 150px 240px 90px 90px; align-items:center; min-width:560px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; background:#fff; }
|
|
357
|
+
table-row > span, table-row > span { padding:10px 12px; font-size:13px; }
|
|
358
|
+
table-row[state="unread"], table-row[state="unread"] { background:#eff6ff; font-weight:700; }
|
|
359
|
+
table-row[state="selected"], table-row[state="selected"] { outline:2px solid rgba(37,99,235,.35); background:#f8fbff; }
|
|
360
|
+
table-row[state="highlighted"], table-row[state="highlighted"] { background:#fffbeb; }
|
|
361
|
+
table-row[state="disabled"], table-row[state="disabled"] { opacity:.5; }
|
|
362
|
+
bulk-action-bar, bulk-action-bar { display:flex; align-items:center; gap:8px; width:fit-content; padding:8px 10px; margin:0 0 10px; border:1px solid #bfdbfe; background:#eff6ff; border-radius:8px; color:#1e40af; font-size:13px; font-weight:650; }
|
|
363
|
+
empty-el, empty-el { display:grid; justify-items:center; gap:8px; width:fit-content; min-width:240px; padding:24px; border:1px dashed var(--rp-border-strong); border-radius:10px; background:#fff; color:#6b7280; text-align:center; }
|
|
364
|
+
.empty-el-title { color:#111827; font-weight:700; }
|
|
365
|
+
.empty-el-desc { font-size:13px; }
|
|
366
|
+
loading-el, loading-el { display:grid; gap:8px; min-width:260px; color:var(--rp-primary); }
|
|
367
|
+
.skeleton-el-line { height:14px; border-radius:999px; background:linear-gradient(90deg,#f3f4f6,#e5e7eb,#f3f4f6); }
|
|
368
|
+
.rp-spinner { display:inline-grid; place-items:center; width:32px; height:32px; }
|
|
369
|
+
alert-el, alert-el, toast-el, toast-el { display:flex; align-items:flex-start; gap:8px; width:fit-content; max-width:420px; padding:10px 12px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; font-size:13px; }
|
|
370
|
+
alert-el[type="info"], alert-el[type="info"], toast-el[type="info"], toast-el[type="info"] { border-color:#bfdbfe; background:#eff6ff; color:#1e40af; }
|
|
371
|
+
alert-el[type="success"], alert-el[type="success"], toast-el[type="success"], toast-el[type="success"] { border-color:#bbf7d0; background:#f0fdf4; color:#166534; }
|
|
372
|
+
alert-el[type="warning"], alert-el[type="warning"], toast-el[type="warning"], toast-el[type="warning"] { border-color:#fde68a; background:#fffbeb; color:#92400e; }
|
|
373
|
+
alert-el[type="error"], alert-el[type="error"], toast-el[type="error"], toast-el[type="error"] { border-color:#fecaca; background:#fef2f2; color:#991b1b; }
|
|
374
|
+
dropdown-el, dropdown-el, popover-el, popover-el { display:block; width:var(--snap-width,300px); padding:8px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; box-shadow:0 12px 24px rgba(15,23,42,.1); }
|
|
375
|
+
tooltip-el, tooltip-el { display:inline-block; width:fit-content; max-width:240px; padding:6px 8px; border-radius:6px; background:#111827; color:#fff; font-size:12px; }
|
|
376
|
+
.rp-overlay-title { margin:0 0 8px; color:#111827; font-size:14px; font-weight:750; }
|
|
377
|
+
modal-el, modal-el { display:block; width:min(var(--snap-width,480px), 100%); border:1px solid var(--rp-border); border-radius:12px; background:#fff; box-shadow:0 24px 48px rgba(15,23,42,.18); overflow:hidden; }
|
|
378
|
+
drawer-el, drawer-el { display:block; width:min(var(--snap-width,360px), 100%); min-height:320px; border:1px solid var(--rp-border); background:#fff; box-shadow:0 18px 40px rgba(15,23,42,.14); }
|
|
379
|
+
.modal-el-head, .drawer-el-head { display:flex; align-items:center; justify-content:space-between; padding:14px 16px; border-bottom:1px solid var(--rp-border); font-weight:750; }
|
|
380
|
+
.modal-el-body, .drawer-el-body { padding:16px; }
|
|
381
|
+
.modal-el-footer { display:flex; justify-content:flex-end; gap:8px; padding:12px 16px; border-top:1px solid var(--rp-border); background:#f9fafb; }
|
|
382
|
+
card-el, card-el { display:block; width:auto; min-width:220px; padding:14px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; }
|
|
383
|
+
.card-el-image { display:grid; place-items:center; height:120px; margin:-14px -14px 12px; border-radius:10px 10px 0 0; background:#f3f4f6; color:#6b7280; }
|
|
384
|
+
.card-el-title { display:block; color:#111827; font-weight:750; }
|
|
385
|
+
.card-el-subtitle { display:block; margin-top:4px; color:#6b7280; font-size:13px; }
|
|
386
|
+
.card-el-footer { display:block; margin:12px -14px -14px; padding:10px 14px; border-top:1px solid var(--rp-border); background:#f9fafb; }
|
|
387
|
+
stat-card, stat-card { display:grid; gap:6px; width:auto; min-width:0; padding:16px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; }
|
|
388
|
+
.rp-stat-label { color:#6b7280; font-size:12px; font-weight:650; }
|
|
389
|
+
.rp-stat-value { color:#111827; font-size:26px; font-weight:800; }
|
|
390
|
+
.rp-stat-change { font-size:12px; font-weight:700; }
|
|
391
|
+
stat-card[trend="up"] .rp-stat-change, stat-card[trend="up"] .rp-stat-change { color:var(--rp-success); }
|
|
392
|
+
stat-card[trend="down"] .rp-stat-change, stat-card[trend="down"] .rp-stat-change { color:var(--rp-danger); }
|
|
393
|
+
tag-el, tag-el { display:inline-flex; align-items:center; gap:5px; height:24px; padding:0 8px; border-radius:999px; background:#eef2ff; color:#3730a3; font-size:12px; font-weight:650; }
|
|
394
|
+
tag-el[color="green"], tag-el[color="green"] { background:#dcfce7; color:#166534; }
|
|
395
|
+
tag-el[color="orange"], tag-el[color="orange"] { background:#ffedd5; color:#9a3412; }
|
|
396
|
+
tag-el[color="red"], tag-el[color="red"] { background:#fee2e2; color:#991b1b; }
|
|
397
|
+
checkbox-el, checkbox-el, radio-el, radio-el { display:inline-flex; align-items:center; gap:8px; font-size:13px; }
|
|
398
|
+
.rp-box { display:inline-grid; place-items:center; width:16px; height:16px; border:1px solid var(--rp-border-strong); border-radius:4px; color:#fff; }
|
|
399
|
+
checkbox-el[state="checked"] .rp-box, checkbox-el[state="checked"] .rp-box, radio-el[state="checked"] .rp-box, radio-el[state="checked"] .rp-box, checkbox-el[state="indeterminate"] .rp-box, checkbox-el[state="indeterminate"] .rp-box { background:var(--rp-primary); border-color:var(--rp-primary); }
|
|
400
|
+
checkbox-el[state="disabled"], checkbox-el[state="disabled"], radio-el[state="disabled"], radio-el[state="disabled"] { opacity:.5; }
|
|
401
|
+
radio-el .rp-box, radio-el .rp-box { border-radius:999px; }
|
|
402
|
+
toggle-el, toggle-el { display:inline-flex; align-items:center; gap:8px; font-size:13px; }
|
|
403
|
+
.toggle-el-track { display:flex; align-items:center; width:34px; height:20px; border-radius:999px; background:#d1d5db; padding:2px; }
|
|
404
|
+
.toggle-el-dot { display:block; width:16px; height:16px; border-radius:999px; background:#fff; box-shadow:0 1px 2px rgba(0,0,0,.2); transition:none; }
|
|
405
|
+
toggle-el[state="on"] .toggle-el-track, toggle-el[state="on"] .toggle-el-track { background:var(--rp-primary); }
|
|
406
|
+
toggle-el[state="on"] .toggle-el-dot, toggle-el[state="on"] .toggle-el-dot { margin-left:14px; }
|
|
407
|
+
toggle-el[state="disabled"], toggle-el[state="disabled"] { opacity:.5; }
|
|
408
|
+
form-el, form-el { display:grid; gap:12px; width:fit-content; max-width:100%; }
|
|
409
|
+
form-el[layout="horizontal"], form-el[layout="horizontal"] { grid-template-columns:max-content 1fr; align-items:start; }
|
|
410
|
+
form-item, form-item { display:grid; gap:6px; width:fit-content; max-width:100%; }
|
|
411
|
+
form-item > *, form-item > * { max-width:100%; }
|
|
412
|
+
.form-el-label { color:#374151; font-size:12px; font-weight:700; }
|
|
413
|
+
.form-el-label.required::after { content:" *"; color:var(--rp-danger); }
|
|
414
|
+
.form-el-error { color:var(--rp-danger); font-size:12px; }
|
|
415
|
+
upload-el, upload-el { display:grid; justify-items:center; gap:8px; width:280px; padding:18px; border:1px dashed var(--rp-border-strong); border-radius:10px; background:#fff; color:#6b7280; text-align:center; font-size:13px; }
|
|
416
|
+
upload-el[state="has-file"], upload-el[state="has-file"] { justify-items:start; border-style:solid; color:#374151; }
|
|
417
|
+
upload-el[state="uploading"], upload-el[state="uploading"] { border-color:#bfdbfe; background:#eff6ff; color:#1e40af; }
|
|
418
|
+
image-placeholder, image-placeholder { display:grid; place-items:center; width:var(--snap-width,160px); height:var(--snap-height,100px); background:#f3f4f6; border:1px dashed var(--rp-border-strong); border-radius:8px; color:#6b7280; font-size:12px; }
|
|
419
|
+
progress-el, progress-el { display:block; width:180px; height:8px; border-radius:999px; background:#e5e7eb; overflow:hidden; }
|
|
420
|
+
progress-el[kind="circle"], progress-el[kind="circle"], progress-el[style="circle"], progress-el[style="circle"] { display:grid; place-items:center; width:52px; height:52px; border-radius:999px; background:conic-gradient(var(--rp-primary) var(--progress,40%), #e5e7eb 0); font-size:12px; font-weight:750; }
|
|
421
|
+
.progress-el-bar { display:block; height:100%; width:var(--progress,40%); background:var(--rp-primary); }
|
|
422
|
+
progress-el[status="success"] .progress-el-bar, progress-el[status="success"] .progress-el-bar { background:var(--rp-success); }
|
|
423
|
+
progress-el[status="error"] .progress-el-bar, progress-el[status="error"] .progress-el-bar { background:var(--rp-danger); }
|
|
424
|
+
pagination-el, pagination-el { display:inline-flex; align-items:center; gap:6px; width:fit-content; font-size:13px; }
|
|
425
|
+
.page-el-btn { display:inline-grid; place-items:center; min-width:30px; height:30px; padding:0 8px; border:1px solid var(--rp-border); border-radius:6px; background:#fff; color:#374151; }
|
|
426
|
+
.page-el-btn.active { border-color:var(--rp-primary); background:var(--rp-primary); color:#fff; font-weight:750; }
|
|
427
|
+
steps-el, steps-el { display:flex; align-items:center; gap:8px; width:fit-content; }
|
|
428
|
+
.rp-step { display:inline-flex; align-items:center; gap:6px; color:#6b7280; font-size:13px; }
|
|
429
|
+
.rp-step-dot { display:inline-grid; place-items:center; width:22px; height:22px; border-radius:999px; border:1px solid var(--rp-border-strong); background:#fff; color:#6b7280; font-size:11px; font-weight:750; }
|
|
430
|
+
.rp-step.active { color:var(--rp-primary); font-weight:750; }
|
|
431
|
+
.rp-step.active .rp-step-dot { border-color:var(--rp-primary); background:var(--rp-primary); color:#fff; }
|
|
432
|
+
.rp-step.done .rp-step-dot { border-color:var(--rp-success); background:var(--rp-success); color:#fff; }
|
|
433
|
+
.rp-step-sep { width:28px; height:1px; background:var(--rp-border); }
|
|
434
|
+
breadcrumb-el, breadcrumb-el { display:inline-flex; align-items:center; gap:6px; color:#6b7280; font-size:13px; }
|
|
435
|
+
.breadcrumb-el-current { color:#111827; font-weight:650; }
|
|
436
|
+
|
|
437
|
+
/* --- data input --- */
|
|
438
|
+
slider-el, slider-el { display:inline-flex; align-items:center; gap:10px; width:220px; }
|
|
439
|
+
.slider-el-track { position:relative; flex:1; height:4px; border-radius:999px; background:#e5e7eb; }
|
|
440
|
+
.slider-el-fill { position:absolute; height:100%; border-radius:999px; background:var(--rp-primary); }
|
|
441
|
+
.slider-el-thumb { position:absolute; top:50%; width:16px; height:16px; margin-left:-8px; transform:translateY(-50%); border-radius:50%; background:#fff; border:1px solid var(--rp-border-strong); }
|
|
442
|
+
.slider-el-value { font-size:12px; color:#374151; min-width:24px; }
|
|
443
|
+
range-el, range-el { display:inline-flex; align-items:center; width:220px; }
|
|
444
|
+
number-input, number-input { display:inline-flex; align-items:center; gap:6px; min-height:34px; padding:0 4px 0 11px; border:1px solid var(--rp-border-strong); border-radius:8px; background:#fff; width:120px; }
|
|
445
|
+
.rp-num-value { flex:1; font-size:13px; }
|
|
446
|
+
.rp-num-steppers { display:flex; flex-direction:column; }
|
|
447
|
+
.rp-num-step { display:grid; place-items:center; width:20px; height:15px; color:#6b7280; cursor:pointer; }
|
|
448
|
+
rating-el, rating-el { display:inline-flex; gap:2px; color:#d1d5db; }
|
|
449
|
+
.rp-star.filled { color:#f59e0b; }
|
|
450
|
+
pin-input, pin-input { display:inline-flex; gap:8px; }
|
|
451
|
+
.rp-pin-cell { display:grid; place-items:center; width:40px; height:46px; border:1px solid var(--rp-border-strong); border-radius:8px; font-size:18px; font-weight:700; background:#fff; }
|
|
452
|
+
.rp-pin-cell.active { border-color:var(--rp-primary); }
|
|
453
|
+
color-swatch, color-swatch { display:inline-flex; align-items:center; gap:8px; padding:4px 10px 4px 4px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; }
|
|
454
|
+
.rp-swatch-chip { width:24px; height:24px; border-radius:6px; border:1px solid rgba(0,0,0,.1); }
|
|
455
|
+
.rp-swatch-hex { font-family:ui-monospace,Menlo,monospace; font-size:12px; color:#374151; }
|
|
456
|
+
autocomplete-el, autocomplete-el { display:inline-block; width:280px; }
|
|
457
|
+
.rp-ac-options { display:grid; gap:1px; margin-top:6px; padding:5px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; }
|
|
458
|
+
.rp-ac-option { padding:7px 8px; border-radius:6px; font-size:13px; color:#374151; }
|
|
459
|
+
.rp-ac-option:first-child { background:#eff6ff; color:#1d4ed8; }
|
|
460
|
+
|
|
461
|
+
/* --- data display additions --- */
|
|
462
|
+
chip-el, chip-el { display:inline-flex; align-items:center; gap:5px; height:26px; padding:0 9px; border-radius:999px; border:1px solid var(--rp-border); background:#f9fafb; color:#374151; font-size:12px; }
|
|
463
|
+
tree-el, tree-el { display:flex; flex-direction:column; gap:1px; width:fit-content; min-width:240px; }
|
|
464
|
+
.tree-el-row { display:flex; align-items:center; gap:6px; padding:5px 8px; border-radius:6px; color:#374151; font-size:13px; padding-left:calc(8px + var(--tree-level,0) * 18px); }
|
|
465
|
+
.tree-el-row.selected { background:#eff6ff; color:#1d4ed8; font-weight:650; }
|
|
466
|
+
.tree-el-spacer { display:inline-block; width:12px; }
|
|
467
|
+
.tree-el-label { flex:1; }
|
|
468
|
+
timeline-el, timeline-el { display:flex; flex-direction:column; width:fit-content; min-width:260px; }
|
|
469
|
+
timeline-item, timeline-item { display:flex; gap:12px; padding-bottom:16px; position:relative; }
|
|
470
|
+
timeline-item:not(:last-child)::before, timeline-item:not(:last-child)::before { content:''; position:absolute; left:6px; top:16px; bottom:0; width:2px; background:var(--rp-border); }
|
|
471
|
+
.timeline-el-dot { flex:0 0 auto; width:14px; height:14px; margin-top:2px; border-radius:50%; background:#fff; border:2px solid var(--rp-border-strong); z-index:1; }
|
|
472
|
+
.timeline-el-dot.active { border-color:var(--rp-primary); background:var(--rp-primary); }
|
|
473
|
+
.timeline-el-dot.done { border-color:var(--rp-success); background:var(--rp-success); }
|
|
474
|
+
.timeline-el-dot.error { border-color:var(--rp-danger); background:var(--rp-danger); }
|
|
475
|
+
.timeline-el-main { flex:1; }
|
|
476
|
+
.timeline-el-head { display:flex; align-items:baseline; gap:8px; }
|
|
477
|
+
.timeline-el-label { font-weight:650; color:#111827; font-size:13px; }
|
|
478
|
+
.timeline-el-time { font-size:12px; color:#9ca3af; }
|
|
479
|
+
.timeline-el-content { font-size:13px; color:#6b7280; margin-top:2px; }
|
|
480
|
+
calendar-el, calendar-el { display:inline-block; width:280px; padding:12px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; }
|
|
481
|
+
.rp-cal-head { text-align:center; font-weight:700; font-size:14px; margin-bottom:10px; }
|
|
482
|
+
.rp-cal-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:2px; }
|
|
483
|
+
.rp-cal-dow { display:grid; place-items:center; height:24px; font-size:11px; color:#9ca3af; }
|
|
484
|
+
.rp-cal-cell { display:grid; place-items:center; height:32px; border-radius:6px; font-size:13px; color:#374151; }
|
|
485
|
+
.rp-cal-cell.selected { background:var(--rp-primary); color:#fff; font-weight:700; }
|
|
486
|
+
.rp-cal-cell.muted { color:transparent; }
|
|
487
|
+
kanban-el, kanban-el { display:flex; gap:12px; width:fit-content; align-items:flex-start; }
|
|
488
|
+
kanban-column, kanban-column { display:flex; flex-direction:column; width:200px; padding:10px; border-radius:10px; background:#f3f4f6; }
|
|
489
|
+
.kanban-el-head { display:flex; align-items:center; justify-content:space-between; font-weight:650; font-size:13px; margin-bottom:8px; color:#374151; }
|
|
490
|
+
.kanban-el-count { display:grid; place-items:center; min-width:18px; height:18px; padding:0 5px; border-radius:999px; background:#e5e7eb; font-size:11px; }
|
|
491
|
+
.kanban-el-body { display:flex; flex-direction:column; gap:8px; }
|
|
492
|
+
kanban-card, kanban-card { display:block; padding:10px; border-radius:8px; background:#fff; border:1px solid var(--rp-border); }
|
|
493
|
+
.kanban-card-title { display:block; font-size:13px; color:#111827; }
|
|
494
|
+
.kanban-card-tag { display:inline-block; margin-top:6px; padding:1px 7px; border-radius:999px; background:#eef2ff; color:#3730a3; font-size:11px; }
|
|
495
|
+
code-block, code-block { display:block; width:fit-content; min-width:320px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; background:#0f172a; }
|
|
496
|
+
.rp-code-head { padding:6px 12px; font-family:ui-monospace,Menlo,monospace; font-size:11px; color:#94a3b8; background:#1e293b; }
|
|
497
|
+
.rp-code-body { padding:10px 0; }
|
|
498
|
+
.rp-code-line { display:flex; align-items:center; gap:12px; padding:1px 12px; }
|
|
499
|
+
.rp-code-ln { width:20px; text-align:right; color:#475569; font-family:ui-monospace,Menlo,monospace; font-size:11px; }
|
|
500
|
+
.rp-code-bar { height:8px; border-radius:3px; background:#334155; }
|
|
501
|
+
diff-el, diff-el { display:block; width:fit-content; min-width:320px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; font-family:ui-monospace,Menlo,monospace; }
|
|
502
|
+
.diff-el-line { display:flex; align-items:center; gap:10px; padding:2px 10px; }
|
|
503
|
+
.diff-el-line.add { background:#dcfce7; }
|
|
504
|
+
.diff-el-line.del { background:#fee2e2; }
|
|
505
|
+
.diff-el-sign { width:10px; color:#6b7280; }
|
|
506
|
+
.diff-el-line.add .rp-code-bar { background:#86efac; }
|
|
507
|
+
.diff-el-line.del .rp-code-bar { background:#fca5a5; }
|
|
508
|
+
.diff-el-line.ctx .rp-code-bar { background:#e5e7eb; }
|
|
509
|
+
image-grid, image-grid { display:grid; grid-template-columns:repeat(var(--grid-cols,3),1fr); gap:8px; width:fit-content; }
|
|
510
|
+
.rp-grid-cell { display:grid; place-items:center; width:80px; height:80px; border-radius:8px; background:#f3f4f6; color:#9ca3af; }
|
|
511
|
+
key-value, key-value { display:flex; flex-direction:column; width:fit-content; min-width:240px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
|
|
512
|
+
kv-row, kv-row { display:flex; border-bottom:1px solid var(--rp-border); }
|
|
513
|
+
kv-row:last-child, kv-row:last-child { border-bottom:0; }
|
|
514
|
+
.rp-kv-key { width:120px; padding:8px 12px; background:#f9fafb; color:#6b7280; font-size:13px; }
|
|
515
|
+
.rp-kv-val { flex:1; padding:8px 12px; color:#111827; font-size:13px; }
|
|
516
|
+
accordion-el, accordion-el { display:flex; flex-direction:column; width:fit-content; min-width:320px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
|
|
517
|
+
accordion-item, accordion-item { display:block; border-bottom:1px solid var(--rp-border); }
|
|
518
|
+
accordion-item:last-child, accordion-item:last-child { border-bottom:0; }
|
|
519
|
+
.accordion-el-head { display:flex; align-items:center; gap:8px; padding:11px 14px; font-weight:650; font-size:13px; color:#111827; }
|
|
520
|
+
.accordion-el-body { padding:0 14px 14px 36px; font-size:13px; color:#6b7280; }
|
|
521
|
+
banner-el, banner-el { display:flex; align-items:center; gap:10px; width:fit-content; min-width:480px; padding:12px 16px; border-radius:8px; font-size:13px; background:#eff6ff; color:#1e40af; border:1px solid #bfdbfe; }
|
|
522
|
+
banner-el[type="success"], banner-el[type="success"] { background:#f0fdf4; color:#166534; border-color:#bbf7d0; }
|
|
523
|
+
banner-el[type="warning"], banner-el[type="warning"] { background:#fffbeb; color:#92400e; border-color:#fde68a; }
|
|
524
|
+
banner-el[type="error"], banner-el[type="error"] { background:#fef2f2; color:#991b1b; border-color:#fecaca; }
|
|
525
|
+
.banner-el-text { flex:1; }
|
|
526
|
+
skeleton-el, skeleton-el { display:flex; flex-direction:column; gap:8px; width:fit-content; min-width:240px; }
|
|
527
|
+
.rp-skel { border-radius:8px; background:linear-gradient(90deg,#f3f4f6,#e5e7eb,#f3f4f6); }
|
|
528
|
+
.rp-skel-block { height:120px; }
|
|
529
|
+
.rp-skel-avatar { width:40px; height:40px; border-radius:50%; }
|
|
530
|
+
.rp-skel-avatar.sm { width:28px; height:28px; }
|
|
531
|
+
.rp-skel-row { display:flex; align-items:center; gap:10px; }
|
|
532
|
+
countdown-el, countdown-el { display:inline-flex; align-items:center; gap:5px; padding:3px 9px; border-radius:999px; background:#fef2f2; color:#991b1b; font-size:12px; font-weight:650; font-variant-numeric:tabular-nums; }
|
|
533
|
+
result-el, result-el { display:grid; justify-items:center; gap:8px; width:fit-content; min-width:280px; padding:32px; text-align:center; }
|
|
534
|
+
.result-el-icon.success { color:var(--rp-success); }
|
|
535
|
+
.result-el-icon.error { color:var(--rp-danger); }
|
|
536
|
+
.result-el-icon.empty { color:#9ca3af; }
|
|
537
|
+
.result-el-title { font-size:16px; font-weight:700; color:#111827; }
|
|
538
|
+
.result-el-desc { font-size:13px; color:#6b7280; }
|
|
539
|
+
permission-gate, permission-gate { display:block; position:relative; width:fit-content; }
|
|
540
|
+
.rp-gate-content { opacity:.4; filter:grayscale(1); pointer-events:none; }
|
|
541
|
+
.rp-gate-overlay { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; gap:6px; background:rgba(255,255,255,.6); color:#6b7280; font-size:12px; font-weight:650; border-radius:8px; }
|
|
542
|
+
quota-bar, quota-bar { display:block; width:fit-content; min-width:240px; }
|
|
543
|
+
.rp-quota-head { display:flex; justify-content:space-between; font-size:12px; color:#374151; margin-bottom:5px; }
|
|
544
|
+
.rp-quota-num.danger { color:var(--rp-danger); font-weight:700; }
|
|
545
|
+
.rp-quota-track { display:block; height:8px; border-radius:999px; background:#e5e7eb; overflow:hidden; }
|
|
546
|
+
.rp-quota-fill { display:block; height:100%; background:var(--rp-primary); }
|
|
547
|
+
.rp-quota-fill.danger { background:var(--rp-danger); }
|
|
548
|
+
api-key, api-key { display:inline-flex; align-items:center; gap:8px; padding:6px 8px 6px 12px; border:1px solid var(--rp-border); border-radius:8px; background:#f9fafb; }
|
|
549
|
+
.rp-apikey-val { font-family:ui-monospace,Menlo,monospace; font-size:12px; color:#374151; }
|
|
550
|
+
.rp-apikey-copy { display:grid; place-items:center; width:26px; height:26px; border-radius:6px; color:#6b7280; }
|
|
551
|
+
audit-row, audit-row { display:flex; align-items:baseline; gap:8px; padding:8px 0; border-bottom:1px solid var(--rp-border); width:fit-content; min-width:320px; font-size:13px; }
|
|
552
|
+
.rp-audit-actor { font-weight:650; color:#111827; }
|
|
553
|
+
.rp-audit-action { flex:1; color:#6b7280; }
|
|
554
|
+
.rp-audit-time { color:#9ca3af; font-size:12px; }
|
|
555
|
+
workflow-node, workflow-node { display:inline-flex; align-items:center; gap:7px; padding:7px 12px; border:1px solid var(--rp-border); border-radius:8px; background:#fff; font-size:13px; }
|
|
556
|
+
.rp-wf-icon.done { color:var(--rp-success); }
|
|
557
|
+
.rp-wf-icon.active { color:var(--rp-primary); }
|
|
558
|
+
.rp-wf-icon.error { color:var(--rp-danger); }
|
|
559
|
+
.rp-wf-icon.default { color:#9ca3af; }
|
|
560
|
+
|
|
561
|
+
/* --- navigation & layout additions --- */
|
|
562
|
+
segmented-el, segmented-el { display:inline-flex; padding:2px; border-radius:8px; background:#f3f4f6; gap:2px; }
|
|
563
|
+
.rp-seg-item { padding:5px 14px; border-radius:6px; font-size:13px; color:#6b7280; }
|
|
564
|
+
.rp-seg-item.active { background:#fff; color:#111827; font-weight:650; }
|
|
565
|
+
command-palette, command-palette { display:block; width:520px; border:1px solid var(--rp-border); border-radius:12px; background:#fff; overflow:hidden; }
|
|
566
|
+
.rp-cmdk-input { display:flex; align-items:center; gap:10px; padding:14px 16px; border-bottom:1px solid var(--rp-border); }
|
|
567
|
+
.rp-cmdk-list { padding:6px; }
|
|
568
|
+
.rp-cmdk-item { display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:8px; font-size:13px; color:#374151; }
|
|
569
|
+
.rp-cmdk-item.active { background:#eff6ff; color:#1d4ed8; }
|
|
570
|
+
context-menu, context-menu, menu-el, menu-el { display:inline-flex; flex-direction:column; min-width:180px; padding:5px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; }
|
|
571
|
+
.menu-item, menu-item, menu-item { display:flex; align-items:center; gap:8px; padding:7px 10px; border-radius:6px; font-size:13px; color:#374151; }
|
|
572
|
+
.menu-item.danger, menu-item.danger, menu-item.danger { color:var(--rp-danger); }
|
|
573
|
+
.menu-item.disabled, menu-item.disabled, menu-item.disabled { opacity:.45; }
|
|
574
|
+
.menu-el-label { flex:1; }
|
|
575
|
+
.menu-el-shortcut { color:#9ca3af; font-size:12px; }
|
|
576
|
+
toc-el, toc-el { display:flex; flex-direction:column; gap:2px; width:fit-content; min-width:160px; border-left:2px solid var(--rp-border); }
|
|
577
|
+
.toc-el-item { padding:4px 12px; font-size:13px; color:#6b7280; border-left:2px solid transparent; margin-left:-2px; }
|
|
578
|
+
.toc-el-item.active { color:var(--rp-primary); border-left-color:var(--rp-primary); font-weight:650; }
|
|
579
|
+
kbd-el, kbd-el { display:inline-flex; align-items:center; gap:3px; }
|
|
580
|
+
.kbd-el-key { display:inline-grid; place-items:center; min-width:20px; height:20px; padding:0 5px; border:1px solid var(--rp-border-strong); border-bottom-width:2px; border-radius:5px; background:#f9fafb; font-size:11px; font-family:var(--rp-font); color:#374151; }
|
|
581
|
+
.kbd-el-plus { color:#9ca3af; font-size:11px; }
|
|
582
|
+
split-pane, split-pane { display:grid; grid-template-columns:var(--snap-columns,1fr 1fr); width:fit-content; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
|
|
583
|
+
split-pane > *, split-pane > * { padding:14px; }
|
|
584
|
+
split-pane > *:not(:last-child), split-pane > *:not(:last-child) { border-right:1px solid var(--rp-border); }
|
|
585
|
+
divider-el, divider-el { display:block; height:1px; background:var(--rp-border); margin:12px 0; }
|
|
586
|
+
divider-el.divider-el-v, divider-el.divider-el-v { display:inline-block; width:1px; height:auto; align-self:stretch; margin:0 12px; }
|
|
587
|
+
spacer-el, spacer-el { display:block; height:var(--snap-size,16px); }
|
|
588
|
+
|
|
589
|
+
/* --- iOS --- */
|
|
590
|
+
ios-navbar, ios-navbar { display:block; background:rgba(249,249,249,.94); border-bottom:1px solid #d8d8dc; padding:6px 12px; font-family:-apple-system,BlinkMacSystemFont,sans-serif; }
|
|
591
|
+
.ios-navbar-row { display:grid; grid-template-columns:1fr auto 1fr; align-items:center; min-height:36px; }
|
|
592
|
+
.rp-ios-nav-leading { display:flex; align-items:center; gap:2px; color:#007aff; font-size:15px; }
|
|
593
|
+
.rp-ios-nav-title { text-align:center; font-weight:600; font-size:16px; color:#000; }
|
|
594
|
+
.rp-ios-nav-trailing { text-align:right; color:#007aff; font-size:15px; }
|
|
595
|
+
.rp-ios-nav-large { font-size:30px; font-weight:700; color:#000; padding:2px 2px 6px; }
|
|
596
|
+
ios-tabbar, ios-tabbar { display:flex; background:rgba(249,249,249,.94); border-top:1px solid #d8d8dc; padding:6px 0 4px; }
|
|
597
|
+
.rp-ios-tab { flex:1; display:flex; flex-direction:column; align-items:center; gap:2px; color:#8e8e93; font-size:10px; }
|
|
598
|
+
.rp-ios-tab.active { color:#007aff; }
|
|
599
|
+
.rp-ios-tab-label { font-size:10px; }
|
|
600
|
+
ios-list, ios-list { display:block; border-radius:10px; background:#fff; overflow:hidden; width:fit-content; min-width:300px; border:1px solid #e5e5ea; font-family:-apple-system,sans-serif; }
|
|
601
|
+
.ios-list-header { padding:6px 16px; font-size:13px; color:#6d6d72; background:#f2f2f7; text-transform:none; }
|
|
602
|
+
ios-list-item, ios-list-item { display:flex; align-items:center; gap:10px; padding:11px 16px; border-bottom:1px solid #e5e5ea; font-size:15px; color:#000; }
|
|
603
|
+
ios-list-item:last-child, ios-list-item:last-child { border-bottom:0; }
|
|
604
|
+
.rp-ios-li-icon { display:grid; place-items:center; width:28px; height:28px; border-radius:6px; background:#007aff; color:#fff; }
|
|
605
|
+
.rp-ios-li-label { flex:1; }
|
|
606
|
+
.rp-ios-li-detail { color:#8e8e93; }
|
|
607
|
+
.rp-ios-li-chevron { color:#c7c7cc; }
|
|
608
|
+
ios-action-sheet, ios-action-sheet { display:flex; flex-direction:column; gap:8px; width:fit-content; min-width:320px; padding:8px; font-family:-apple-system,sans-serif; }
|
|
609
|
+
.rp-ios-as-group { border-radius:14px; overflow:hidden; background:rgba(255,255,255,.82); backdrop-filter:blur(20px); }
|
|
610
|
+
.rp-ios-as-title { padding:14px; text-align:center; font-size:13px; color:#8e8e93; border-bottom:1px solid #d1d1d6; }
|
|
611
|
+
.rp-ios-as-action { padding:16px; text-align:center; font-size:18px; color:#007aff; border-bottom:1px solid #d1d1d6; }
|
|
612
|
+
.rp-ios-as-action:last-child { border-bottom:0; }
|
|
613
|
+
.rp-ios-as-action.destructive { color:#ff3b30; }
|
|
614
|
+
.rp-ios-as-action.cancel { font-weight:600; }
|
|
615
|
+
ios-alert, ios-alert { display:block; width:270px; border-radius:14px; overflow:hidden; background:rgba(255,255,255,.92); backdrop-filter:blur(20px); font-family:-apple-system,sans-serif; }
|
|
616
|
+
.ios-alert-body { padding:18px 16px 14px; text-align:center; }
|
|
617
|
+
.ios-alert-title { font-size:17px; font-weight:600; color:#000; }
|
|
618
|
+
.ios-alert-msg { margin-top:3px; font-size:13px; color:#000; }
|
|
619
|
+
.ios-alert-actions { display:flex; border-top:1px solid #d1d1d6; }
|
|
620
|
+
.ios-alert-btn { flex:1; padding:11px; text-align:center; font-size:17px; color:#007aff; }
|
|
621
|
+
.ios-alert-btn.primary { font-weight:600; }
|
|
622
|
+
.ios-alert-btn:not(:last-child) { border-right:1px solid #d1d1d6; }
|
|
623
|
+
ios-switch, ios-switch { display:inline-flex; align-items:center; gap:8px; font-family:-apple-system,sans-serif; font-size:15px; }
|
|
624
|
+
.ios-switch-track { width:51px; height:31px; border-radius:999px; background:#34c759; padding:2px; }
|
|
625
|
+
.ios-switch-dot { display:block; width:27px; height:27px; border-radius:50%; background:#fff; margin-left:20px; }
|
|
626
|
+
ios-segmented, ios-segmented { display:inline-flex; padding:2px; border-radius:9px; background:#767680; background:rgba(118,118,128,.12); gap:2px; font-family:-apple-system,sans-serif; }
|
|
627
|
+
.rp-ios-seg-item { padding:6px 16px; border-radius:7px; font-size:13px; color:#000; }
|
|
628
|
+
.rp-ios-seg-item.active { background:#fff; font-weight:600; }
|
|
629
|
+
ios-button, ios-button { display:inline-grid; place-items:center; min-height:34px; padding:0 16px; border-radius:8px; background:#007aff; color:#fff; font-size:15px; font-weight:600; font-family:-apple-system,sans-serif; }
|
|
630
|
+
ios-button[variant="tinted"], ios-button[variant="tinted"] { background:rgba(0,122,255,.15); color:#007aff; }
|
|
631
|
+
ios-button[variant="plain"], ios-button[variant="plain"] { background:transparent; color:#007aff; }
|
|
632
|
+
ios-search, ios-search { display:inline-flex; align-items:center; gap:6px; width:280px; height:36px; padding:0 10px; border-radius:10px; background:rgba(118,118,128,.12); color:#8e8e93; font-size:15px; font-family:-apple-system,sans-serif; }
|
|
633
|
+
ios-stepper, ios-stepper { display:inline-flex; align-items:center; border-radius:8px; background:rgba(118,118,128,.12); }
|
|
634
|
+
.rp-ios-step { display:grid; place-items:center; width:46px; height:32px; color:#000; }
|
|
635
|
+
.rp-ios-step-div { width:1px; height:18px; background:rgba(0,0,0,.15); }
|
|
636
|
+
|
|
637
|
+
/* --- macOS --- */
|
|
638
|
+
macos-window, macos-window { display:block; width:fit-content; min-width:480px; border-radius:10px; overflow:hidden; border:1px solid #d1d1d6; background:#fff; font-family:-apple-system,sans-serif; }
|
|
639
|
+
.rp-mac-titlebar { display:flex; align-items:center; gap:10px; height:38px; padding:0 14px; background:#ececec; border-bottom:1px solid #d1d1d6; }
|
|
640
|
+
.rp-mac-lights { display:flex; gap:8px; }
|
|
641
|
+
.rp-mac-light { width:12px; height:12px; border-radius:50%; }
|
|
642
|
+
.rp-mac-light.close { background:#ff5f57; }
|
|
643
|
+
.rp-mac-light.min { background:#febc2e; }
|
|
644
|
+
.rp-mac-light.max { background:#28c840; }
|
|
645
|
+
.rp-mac-title { flex:1; text-align:center; font-size:13px; font-weight:600; color:#3c3c43; }
|
|
646
|
+
.rp-mac-window-body { padding:0; }
|
|
647
|
+
macos-toolbar, macos-toolbar { display:flex; align-items:center; gap:10px; padding:8px 14px; background:#f6f6f6; border-bottom:1px solid #d1d1d6; }
|
|
648
|
+
macos-menubar, macos-menubar { display:flex; align-items:center; gap:18px; height:26px; padding:0 14px; background:rgba(246,246,246,.9); border-bottom:1px solid #d1d1d6; font-size:13px; font-family:-apple-system,sans-serif; }
|
|
649
|
+
.rp-mac-menubar-apple { color:#000; }
|
|
650
|
+
.rp-mac-menu-title { color:#000; }
|
|
651
|
+
.rp-mac-menu-title.active { background:#007aff; color:#fff; padding:1px 7px; border-radius:4px; }
|
|
652
|
+
macos-sidebar, macos-sidebar { display:flex; flex-direction:column; gap:1px; width:220px; padding:8px; background:rgba(246,246,246,.85); font-family:-apple-system,sans-serif; }
|
|
653
|
+
macos-source-item, macos-source-item { display:flex; align-items:center; gap:7px; padding:5px 8px; border-radius:6px; font-size:13px; color:#3c3c43; }
|
|
654
|
+
macos-source-item.selected, macos-source-item.selected { background:#007aff; color:#fff; }
|
|
655
|
+
.rp-mac-source-group { padding:8px 8px 3px; font-size:11px; font-weight:700; color:#8e8e93; text-transform:uppercase; }
|
|
656
|
+
macos-segmented, macos-segmented { display:inline-flex; border:1px solid #c4c4c7; border-radius:6px; overflow:hidden; font-family:-apple-system,sans-serif; }
|
|
657
|
+
.rp-mac-seg-item { padding:4px 14px; font-size:13px; color:#000; background:#fff; border-right:1px solid #c4c4c7; }
|
|
658
|
+
.rp-mac-seg-item:last-child { border-right:0; }
|
|
659
|
+
.rp-mac-seg-item.active { background:#007aff; color:#fff; }
|
|
660
|
+
macos-popover, macos-popover { display:inline-block; position:relative; }
|
|
661
|
+
.rp-mac-pop-arrow { display:block; width:16px; height:8px; margin:0 auto -1px; clip-path:polygon(50% 0,100% 100%,0 100%); background:#fff; border:1px solid #d1d1d6; }
|
|
662
|
+
.rp-mac-pop-body { min-width:220px; padding:12px; border-radius:10px; border:1px solid #d1d1d6; background:#fff; }
|
|
663
|
+
.rp-mac-pop-title { font-weight:600; font-size:13px; margin-bottom:8px; }
|
|
664
|
+
macos-sheet, macos-sheet { display:block; width:fit-content; min-width:420px; border-radius:10px; background:#fff; box-shadow:0 24px 60px rgba(0,0,0,.3); padding:18px; font-family:-apple-system,sans-serif; }
|
|
665
|
+
.rp-mac-sheet-title { font-size:15px; font-weight:700; margin-bottom:12px; }
|
|
666
|
+
.rp-mac-sheet-actions { display:flex; justify-content:flex-end; gap:8px; margin-top:16px; }
|
|
667
|
+
macos-stepper, macos-stepper { display:inline-flex; flex-direction:column; border:1px solid #c4c4c7; border-radius:5px; overflow:hidden; }
|
|
668
|
+
.rp-mac-step { display:grid; place-items:center; width:22px; height:13px; background:#fff; color:#3c3c43; }
|
|
669
|
+
.rp-mac-step.up { border-bottom:1px solid #c4c4c7; }
|
|
670
|
+
macos-disclosure, macos-disclosure { display:block; font-family:-apple-system,sans-serif; }
|
|
671
|
+
.rp-mac-disc-head { display:flex; align-items:center; gap:5px; font-size:13px; font-weight:600; color:#000; }
|
|
672
|
+
.rp-mac-disc-tri { display:inline-flex; transition:none; }
|
|
673
|
+
.rp-mac-disc-tri.open { transform:rotate(90deg); }
|
|
674
|
+
.rp-mac-disc-body { padding:8px 0 0 18px; font-size:13px; color:#3c3c43; }
|
|
675
|
+
macos-table, macos-table { display:flex; flex-direction:column; width:fit-content; min-width:360px; border:1px solid #d1d1d6; border-radius:6px; overflow:hidden; font-family:-apple-system,sans-serif; }
|
|
676
|
+
.rp-mac-tr { display:flex; }
|
|
677
|
+
.rp-mac-tr.rp-mac-th { background:#f6f6f6; border-bottom:1px solid #d1d1d6; font-size:12px; font-weight:600; color:#3c3c43; }
|
|
678
|
+
.rp-mac-tr.alt { background:#f5f8ff; }
|
|
679
|
+
.rp-mac-td { flex:1; display:flex; align-items:center; gap:6px; padding:6px 12px; font-size:13px; color:#3c3c43; }
|
|
680
|
+
.rp-mac-cell-bar { height:8px; border-radius:3px; background:#e5e7eb; }
|
|
681
|
+
|
|
682
|
+
/* --- agent / conversational UI (Codex-style: single column, de-bubbled) --- */
|
|
683
|
+
chat-el, chat-el { display:flex; flex-direction:column; gap:24px; width:fit-content; min-width:520px; max-width:680px; }
|
|
684
|
+
user-message, user-message, assistant-message, assistant-message { display:block; }
|
|
685
|
+
.rp-msg-role { font-size:12px; font-weight:700; color:#9ca3af; letter-spacing:.02em; margin:0 0 6px; }
|
|
686
|
+
.rp-msg-content { display:flex; flex-direction:column; gap:12px; font-size:14px; line-height:1.7; color:#1f2937; }
|
|
687
|
+
user-message .rp-msg-content, user-message .rp-msg-content { color:#111827; }
|
|
688
|
+
system-message, system-message { display:flex; justify-content:center; }
|
|
689
|
+
.rp-sysmsg-line { padding:3px 12px; border-radius:999px; background:#f3f4f6; color:#6b7280; font-size:12px; }
|
|
690
|
+
tool-call, tool-call { display:block; width:fit-content; min-width:280px; max-width:600px; }
|
|
691
|
+
.rp-tool-head { display:flex; align-items:center; gap:8px; font-size:13px; color:#6b7280; }
|
|
692
|
+
.rp-tool-glyph { display:inline-flex; }
|
|
693
|
+
.rp-tool-glyph.done { color:var(--rp-success); }
|
|
694
|
+
.rp-tool-glyph.running { color:var(--rp-primary); }
|
|
695
|
+
.rp-tool-glyph.error { color:var(--rp-danger); }
|
|
696
|
+
.rp-tool-name { font-family:ui-monospace,Menlo,monospace; font-weight:650; color:#374151; }
|
|
697
|
+
.rp-tool-args-inline { font-family:ui-monospace,Menlo,monospace; color:#9ca3af; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
698
|
+
.rp-tool-body { margin-top:8px; padding-left:21px; }
|
|
699
|
+
agent-output, agent-output { display:block; width:fit-content; min-width:280px; max-width:600px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; background:#f8fafc; }
|
|
700
|
+
.rp-output-head { padding:6px 12px; font-size:12px; color:#6b7280; border-bottom:1px solid var(--rp-border); font-family:ui-monospace,Menlo,monospace; }
|
|
701
|
+
.rp-output-body { padding:12px; font-family:ui-monospace,Menlo,monospace; font-size:12.5px; line-height:1.6; color:#334155; white-space:pre-wrap; }
|
|
702
|
+
reasoning-el, reasoning-el { display:block; width:fit-content; min-width:280px; max-width:600px; }
|
|
703
|
+
.rp-reason-head { display:flex; align-items:center; gap:6px; font-size:13px; color:#9ca3af; }
|
|
704
|
+
.rp-reason-body { margin-top:8px; padding-left:19px; border-left:2px solid var(--rp-border); font-size:13px; line-height:1.7; color:#6b7280; }
|
|
705
|
+
message-actions, message-actions { display:inline-flex; gap:2px; }
|
|
706
|
+
.rp-msg-action { display:grid; place-items:center; width:28px; height:28px; border-radius:6px; color:#9ca3af; cursor:pointer; }
|
|
707
|
+
.rp-msg-action:hover { background:#f3f4f6; color:#374151; }
|
|
708
|
+
suggestions-el, suggestions-el { display:flex; flex-wrap:wrap; gap:8px; }
|
|
709
|
+
.rp-suggestion { padding:7px 13px; border:1px solid var(--rp-border); border-radius:8px; font-size:13px; color:#374151; background:#fff; cursor:pointer; }
|
|
710
|
+
.rp-suggestion:hover { border-color:var(--rp-border-strong); background:#f9fafb; }
|
|
711
|
+
typing-el, typing-el { display:flex; align-items:center; }
|
|
712
|
+
.typing-el-dots { display:inline-flex; gap:4px; }
|
|
713
|
+
.typing-el-dots > span { width:7px; height:7px; border-radius:50%; background:#c7c7cc; }
|
|
714
|
+
composer-el, composer-el { display:flex; align-items:center; gap:10px; width:fit-content; min-width:520px; max-width:680px; padding:9px 9px 9px 14px; border:1px solid var(--rp-border-strong); border-radius:14px; background:#fff; }
|
|
715
|
+
.composer-el-attach { display:inline-flex; color:#9ca3af; }
|
|
716
|
+
.composer-el-input { flex:1; font-size:14px; }
|
|
717
|
+
.composer-el-send { display:grid; place-items:center; width:32px; height:32px; border-radius:8px; background:#111827; color:#fff; }
|
|
718
|
+
.composer-el-send.streaming { background:var(--rp-danger); }
|
|
719
|
+
citation-el, citation-el { display:inline-flex; align-items:center; gap:6px; max-width:280px; padding:3px 9px 3px 3px; border:1px solid var(--rp-border); border-radius:6px; background:#f9fafb; font-size:12px; color:#374151; }
|
|
720
|
+
.rp-cite-idx { display:grid; place-items:center; width:17px; height:17px; border-radius:4px; background:#e5e7eb; color:#374151; font-size:11px; font-weight:700; }
|
|
721
|
+
.rp-cite-title { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
722
|
+
token-usage, token-usage { display:inline-flex; align-items:center; gap:7px; font-size:12px; color:#9ca3af; }
|
|
723
|
+
.rp-token-track { width:90px; height:5px; border-radius:999px; background:#e5e7eb; overflow:hidden; }
|
|
724
|
+
.rp-token-fill { display:block; height:100%; background:#9ca3af; }
|
|
725
|
+
`;
|
|
726
|
+
function injectStyle() {
|
|
727
|
+
if (document.getElementById(RPUI_STYLE_ID)) return;
|
|
728
|
+
const el = document.createElement("style");
|
|
729
|
+
el.id = RPUI_STYLE_ID;
|
|
730
|
+
el.textContent = style;
|
|
731
|
+
document.head.appendChild(el);
|
|
732
|
+
}
|
|
733
|
+
class RpAnnotation extends HTMLElement {
|
|
734
|
+
constructor() {
|
|
735
|
+
super(...arguments);
|
|
736
|
+
__publicField(this, "ro");
|
|
737
|
+
__publicField(this, "frame", 0);
|
|
738
|
+
}
|
|
739
|
+
connectedCallback() {
|
|
740
|
+
var _a;
|
|
741
|
+
injectStyle();
|
|
742
|
+
if (this.dataset.rpReady) {
|
|
743
|
+
this.setupSlicePins();
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
this.dataset.rpReady = "true";
|
|
747
|
+
const existing = Array.from(this.childNodes);
|
|
748
|
+
const depth = this.annotationDepth();
|
|
749
|
+
const id = attr(this, "id");
|
|
750
|
+
const label = attr(this, "label", id ? `Annotation ${id}` : "Annotation");
|
|
751
|
+
let sectionPath;
|
|
752
|
+
if (id) {
|
|
753
|
+
sectionPath = id;
|
|
754
|
+
} else {
|
|
755
|
+
const parentSection = ((_a = this.closest("[data-rp-section]")) == null ? void 0 : _a.dataset.rpSection) ?? "";
|
|
756
|
+
const siblings = this.parentElement ? Array.from(this.parentElement.children).filter(
|
|
757
|
+
(el) => el.tagName.toLowerCase() === "annotation-el" || el.tagName.toLowerCase() === "annotation-el"
|
|
758
|
+
) : [];
|
|
759
|
+
const idx = siblings.indexOf(this) + 1;
|
|
760
|
+
sectionPath = parentSection ? `${parentSection}-${idx}` : String(idx);
|
|
761
|
+
}
|
|
762
|
+
this.dataset.rpSection = sectionPath;
|
|
763
|
+
const marker = document.createElement("span");
|
|
764
|
+
const kind = id ? "drop" : depth <= 1 ? "circle" : "triangle";
|
|
765
|
+
marker.className = `annotation-el-marker ${kind}`;
|
|
766
|
+
const localIndex = id || sectionPath.split("-").pop() || "";
|
|
767
|
+
marker.innerHTML = `<span>${escapeHtml(localIndex)}</span>`;
|
|
768
|
+
const head = document.createElement("div");
|
|
769
|
+
head.className = "annotation-el-head";
|
|
770
|
+
head.append(marker);
|
|
771
|
+
const title = document.createElement("span");
|
|
772
|
+
title.className = "annotation-el-title";
|
|
773
|
+
title.textContent = label;
|
|
774
|
+
title.addEventListener("click", () => {
|
|
775
|
+
const url = new URL(location.href);
|
|
776
|
+
url.searchParams.set("section", sectionPath);
|
|
777
|
+
history.pushState(null, "", url);
|
|
778
|
+
window.dispatchEvent(new CustomEvent("rp-section", { detail: sectionPath }));
|
|
779
|
+
});
|
|
780
|
+
head.append(title);
|
|
781
|
+
const body = document.createElement("div");
|
|
782
|
+
body.className = "annotation-el-body";
|
|
783
|
+
existing.forEach((n) => body.appendChild(n));
|
|
784
|
+
this.append(head, body);
|
|
785
|
+
this.setupSlicePins();
|
|
786
|
+
}
|
|
787
|
+
disconnectedCallback() {
|
|
788
|
+
var _a;
|
|
789
|
+
(_a = this.ro) == null ? void 0 : _a.disconnect();
|
|
790
|
+
if (this.frame) cancelAnimationFrame(this.frame);
|
|
791
|
+
}
|
|
792
|
+
// A UI slice inside this annotation may carry data-pin markers on sub-regions.
|
|
793
|
+
// Render pins on those slices so their numbers connect to the deeper annotations
|
|
794
|
+
// that explain them — mirroring how main-view pins top-level regions.
|
|
795
|
+
setupSlicePins() {
|
|
796
|
+
var _a;
|
|
797
|
+
const body = this.querySelector(":scope > .annotation-el-body");
|
|
798
|
+
if (!body || !body.querySelector("[data-pin]")) return;
|
|
799
|
+
(_a = this.ro) == null ? void 0 : _a.disconnect();
|
|
800
|
+
this.scheduleSlicePins(body);
|
|
801
|
+
this.ro = new ResizeObserver(() => this.scheduleSlicePins(body));
|
|
802
|
+
this.ro.observe(this);
|
|
803
|
+
}
|
|
804
|
+
scheduleSlicePins(body) {
|
|
805
|
+
if (this.frame) return;
|
|
806
|
+
this.frame = requestAnimationFrame(() => {
|
|
807
|
+
this.frame = 0;
|
|
808
|
+
this.renderSlicePins(body);
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
renderSlicePins(body) {
|
|
812
|
+
body.querySelectorAll(":scope > .rp-pin").forEach((p) => p.remove());
|
|
813
|
+
const bodyRect = body.getBoundingClientRect();
|
|
814
|
+
body.querySelectorAll("[data-pin]").forEach((target) => {
|
|
815
|
+
if (target.closest("annotation-el, annotation-el") !== this) return;
|
|
816
|
+
const pinId = target.dataset.pin;
|
|
817
|
+
if (!pinId) return;
|
|
818
|
+
const r = target.getBoundingClientRect();
|
|
819
|
+
const pin = document.createElement("span");
|
|
820
|
+
pin.className = "rp-pin rp-pin-slice";
|
|
821
|
+
pin.style.left = `${r.left - bodyRect.left}px`;
|
|
822
|
+
pin.style.top = `${r.top - bodyRect.top}px`;
|
|
823
|
+
pin.innerHTML = `<span>${escapeHtml(pinId)}</span>`;
|
|
824
|
+
body.appendChild(pin);
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
annotationDepth() {
|
|
828
|
+
let d = 0;
|
|
829
|
+
let p = this.parentElement;
|
|
830
|
+
while (p) {
|
|
831
|
+
if (p.tagName.toLowerCase() === "annotation-el" || p.tagName.toLowerCase() === "annotation-el") d++;
|
|
832
|
+
p = p.parentElement;
|
|
833
|
+
}
|
|
834
|
+
return d;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
class RpEnum extends HTMLElement {
|
|
838
|
+
connectedCallback() {
|
|
839
|
+
injectStyle();
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
class RpEnumItem extends HTMLElement {
|
|
843
|
+
connectedCallback() {
|
|
844
|
+
injectStyle();
|
|
845
|
+
if (this.dataset.rpReady) return;
|
|
846
|
+
this.dataset.rpReady = "true";
|
|
847
|
+
const children = Array.from(this.childNodes);
|
|
848
|
+
const parent = this.parentElement;
|
|
849
|
+
const siblings = parent ? Array.from(parent.children).filter(
|
|
850
|
+
(el) => el.tagName.toLowerCase() === "enum-item" || el.tagName.toLowerCase() === "enum-item"
|
|
851
|
+
) : [];
|
|
852
|
+
const idx = siblings.indexOf(this) + 1;
|
|
853
|
+
const labelEl = document.createElement("span");
|
|
854
|
+
labelEl.className = "enum-el-label";
|
|
855
|
+
const idxBadge = document.createElement("span");
|
|
856
|
+
idxBadge.className = "enum-el-index";
|
|
857
|
+
idxBadge.textContent = String(idx);
|
|
858
|
+
const labelText = document.createElement("span");
|
|
859
|
+
labelText.className = "enum-el-label-text";
|
|
860
|
+
labelText.textContent = attr(this, "label", "State");
|
|
861
|
+
const description = attr(this, "description");
|
|
862
|
+
if (description) {
|
|
863
|
+
const desc = document.createElement("span");
|
|
864
|
+
desc.className = "enum-el-description";
|
|
865
|
+
desc.textContent = description;
|
|
866
|
+
labelText.appendChild(desc);
|
|
867
|
+
}
|
|
868
|
+
labelEl.append(idxBadge, labelText);
|
|
869
|
+
const content = document.createElement("div");
|
|
870
|
+
content.className = "enum-el-content";
|
|
871
|
+
children.forEach((n) => content.appendChild(n));
|
|
872
|
+
this.append(labelEl, content);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
class RpMainView extends HTMLElement {
|
|
876
|
+
constructor() {
|
|
877
|
+
super(...arguments);
|
|
878
|
+
__publicField(this, "ro");
|
|
879
|
+
__publicField(this, "frame", 0);
|
|
880
|
+
}
|
|
881
|
+
connectedCallback() {
|
|
882
|
+
injectStyle();
|
|
883
|
+
if (!this.dataset.rpReady) {
|
|
884
|
+
this.dataset.rpReady = "true";
|
|
885
|
+
const width = resolveWidth(this, 1440);
|
|
886
|
+
const height = resolveHeight(this, 900);
|
|
887
|
+
const autoHeight = usesAutoHeight(this);
|
|
888
|
+
const scale = Number(attr(this, "scale", "0.7")) || 0.7;
|
|
889
|
+
const children = Array.from(this.childNodes);
|
|
890
|
+
const shell = document.createElement("div");
|
|
891
|
+
shell.className = "rp-main-shell";
|
|
892
|
+
shell.style.width = `${width * scale}px`;
|
|
893
|
+
if (!autoHeight) shell.style.height = `${height * scale}px`;
|
|
894
|
+
const stage2 = document.createElement("div");
|
|
895
|
+
stage2.className = "rp-main-stage";
|
|
896
|
+
stage2.style.width = `${width}px`;
|
|
897
|
+
stage2.style.minHeight = autoHeight ? "0" : `${height}px`;
|
|
898
|
+
stage2.style.height = autoHeight ? "auto" : `${height}px`;
|
|
899
|
+
stage2.style.transform = `scale(${scale})`;
|
|
900
|
+
const clip = document.createElement("div");
|
|
901
|
+
clip.className = "rp-main-stage-clip";
|
|
902
|
+
children.forEach((n) => {
|
|
903
|
+
if (isViewportNode(n)) {
|
|
904
|
+
if (!n.hasAttribute("width") && !n.hasAttribute("device")) n.style.setProperty("--snap-width", `${width}px`);
|
|
905
|
+
if (!n.hasAttribute("height")) n.style.setProperty("--snap-height", autoHeight ? "auto" : `${height}px`);
|
|
906
|
+
}
|
|
907
|
+
stage2.appendChild(n);
|
|
908
|
+
});
|
|
909
|
+
clip.appendChild(stage2);
|
|
910
|
+
shell.appendChild(clip);
|
|
911
|
+
this.appendChild(shell);
|
|
912
|
+
}
|
|
913
|
+
this.scheduleRender();
|
|
914
|
+
this.ro = new ResizeObserver(() => this.scheduleRender());
|
|
915
|
+
this.ro.observe(this);
|
|
916
|
+
const stage = this.querySelector(".rp-main-stage");
|
|
917
|
+
if (stage) this.ro.observe(stage);
|
|
918
|
+
}
|
|
919
|
+
disconnectedCallback() {
|
|
920
|
+
var _a;
|
|
921
|
+
(_a = this.ro) == null ? void 0 : _a.disconnect();
|
|
922
|
+
if (this.frame) {
|
|
923
|
+
cancelAnimationFrame(this.frame);
|
|
924
|
+
this.frame = 0;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
scheduleRender() {
|
|
928
|
+
if (this.frame) return;
|
|
929
|
+
this.frame = requestAnimationFrame(() => {
|
|
930
|
+
this.frame = 0;
|
|
931
|
+
this.syncAutoHeight();
|
|
932
|
+
this.renderPins();
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
syncAutoHeight() {
|
|
936
|
+
if (!usesAutoHeight(this)) return;
|
|
937
|
+
const shell = this.querySelector(".rp-main-shell");
|
|
938
|
+
const stage = this.querySelector(".rp-main-stage");
|
|
939
|
+
if (!shell || !stage) return;
|
|
940
|
+
const scale = Number(attr(this, "scale", "0.7")) || 0.7;
|
|
941
|
+
const next = `${Math.ceil(stage.scrollHeight * scale)}px`;
|
|
942
|
+
if (shell.style.height !== next) shell.style.height = next;
|
|
943
|
+
}
|
|
944
|
+
renderPins() {
|
|
945
|
+
const shell = this.querySelector(".rp-main-shell");
|
|
946
|
+
const stage = this.querySelector(".rp-main-stage");
|
|
947
|
+
if (!shell || !stage) return;
|
|
948
|
+
shell.querySelectorAll(".rp-pin").forEach((p) => p.remove());
|
|
949
|
+
const shellRect = shell.getBoundingClientRect();
|
|
950
|
+
stage.querySelectorAll("[data-pin]").forEach((target) => {
|
|
951
|
+
const id = target.dataset.pin;
|
|
952
|
+
if (!id) return;
|
|
953
|
+
const r = target.getBoundingClientRect();
|
|
954
|
+
const pin = document.createElement("span");
|
|
955
|
+
pin.className = "rp-pin";
|
|
956
|
+
pin.style.left = `${r.left - shellRect.left}px`;
|
|
957
|
+
pin.style.top = `${r.top - shellRect.top}px`;
|
|
958
|
+
pin.innerHTML = `<span>${escapeHtml(id)}</span>`;
|
|
959
|
+
pin.addEventListener("click", () => {
|
|
960
|
+
const url = new URL(location.href);
|
|
961
|
+
url.searchParams.set("section", id);
|
|
962
|
+
history.pushState(null, "", url);
|
|
963
|
+
window.dispatchEvent(new CustomEvent("rp-section", { detail: id }));
|
|
964
|
+
});
|
|
965
|
+
shell.appendChild(pin);
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
function activateSection(path, pane) {
|
|
970
|
+
document.querySelectorAll(".rp-section-focus").forEach((el) => el.classList.remove("rp-section-focus"));
|
|
971
|
+
const target = document.querySelector(`[data-rp-section="${CSS.escape(path)}"]`);
|
|
972
|
+
if (!target) return;
|
|
973
|
+
target.classList.add("rp-section-focus");
|
|
974
|
+
if (pane) {
|
|
975
|
+
const paneEl = pane;
|
|
976
|
+
const targetRect = target.getBoundingClientRect();
|
|
977
|
+
const paneRect = paneEl.getBoundingClientRect();
|
|
978
|
+
paneEl.scrollTo({ top: paneEl.scrollTop + targetRect.top - paneRect.top - 20, behavior: "smooth" });
|
|
979
|
+
}
|
|
980
|
+
setTimeout(() => target.classList.remove("rp-section-focus"), 3e3);
|
|
981
|
+
}
|
|
982
|
+
class RpPage extends HTMLElement {
|
|
983
|
+
connectedCallback() {
|
|
984
|
+
injectStyle();
|
|
985
|
+
if (this.dataset.rpReady) return;
|
|
986
|
+
this.dataset.rpReady = "true";
|
|
987
|
+
const pageTitle = attr(this, "title", "Untitled");
|
|
988
|
+
const route = attr(this, "route", "/");
|
|
989
|
+
const description = attr(this, "description", "");
|
|
990
|
+
this.removeAttribute("title");
|
|
991
|
+
const existing = Array.from(this.childNodes);
|
|
992
|
+
const header = document.createElement("div");
|
|
993
|
+
header.className = "page-el-header";
|
|
994
|
+
header.innerHTML = `<div class="page-el-title-row"><h1 class="page-el-title">${escapeHtml(pageTitle)}</h1><span class="page-el-route">${escapeHtml(route)}</span></div><p class="page-el-description">${escapeHtml(description)}</p>`;
|
|
995
|
+
const body = document.createElement("div");
|
|
996
|
+
body.className = "page-el-body";
|
|
997
|
+
const main = document.createElement("main");
|
|
998
|
+
main.className = "page-el-main";
|
|
999
|
+
const pane = document.createElement("aside");
|
|
1000
|
+
pane.className = "annotation-el-pane";
|
|
1001
|
+
pane.setAttribute("aria-label", "Annotations");
|
|
1002
|
+
const paneInner = document.createElement("div");
|
|
1003
|
+
paneInner.className = "annotation-el-pane-inner";
|
|
1004
|
+
existing.forEach((n) => (isTopAnnotation(n) ? paneInner : body).appendChild(n));
|
|
1005
|
+
pane.appendChild(paneInner);
|
|
1006
|
+
main.append(header, body);
|
|
1007
|
+
const shell = document.createElement("div");
|
|
1008
|
+
shell.className = "page-el-shell";
|
|
1009
|
+
shell.append(main, pane);
|
|
1010
|
+
this.appendChild(shell);
|
|
1011
|
+
requestAnimationFrame(() => {
|
|
1012
|
+
const mv = body.querySelector("main-view, main-view");
|
|
1013
|
+
if (mv) header.style.maxWidth = `${mv.offsetWidth}px`;
|
|
1014
|
+
});
|
|
1015
|
+
const go = () => {
|
|
1016
|
+
const sec = new URLSearchParams(location.search).get("section");
|
|
1017
|
+
if (sec) activateSection(sec, pane);
|
|
1018
|
+
};
|
|
1019
|
+
window.addEventListener("popstate", go);
|
|
1020
|
+
window.addEventListener("rp-section", (e) => activateSection(e.detail, pane));
|
|
1021
|
+
requestAnimationFrame(go);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
class GenericElement extends HTMLElement {
|
|
1025
|
+
connectedCallback() {
|
|
1026
|
+
injectStyle();
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
class ViewportElement extends HTMLElement {
|
|
1030
|
+
connectedCallback() {
|
|
1031
|
+
injectStyle();
|
|
1032
|
+
if (this.hasAttribute("width") || this.hasAttribute("device")) this.style.setProperty("--snap-width", `${resolveWidth(this, 1440)}px`);
|
|
1033
|
+
if (hasExplicitNumericHeight(this)) this.style.setProperty("--snap-height", `${resolveHeight(this, 900)}px`);
|
|
1034
|
+
else if (usesAutoHeight(this)) this.style.setProperty("--snap-height", "auto");
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
class LayoutElement extends HTMLElement {
|
|
1038
|
+
connectedCallback() {
|
|
1039
|
+
injectStyle();
|
|
1040
|
+
this.style.setProperty("--snap-columns", attr(this, "columns", "1fr"));
|
|
1041
|
+
this.style.setProperty("--snap-rows", attr(this, "rows", "auto"));
|
|
1042
|
+
if (this.hasAttribute("gap")) this.style.setProperty("--snap-gap", `${attr(this, "gap", "0")}px`);
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
class PanelElement extends HTMLElement {
|
|
1046
|
+
connectedCallback() {
|
|
1047
|
+
injectStyle();
|
|
1048
|
+
this.style.setProperty("--snap-padding", `${attr(this, "padding", "16")}px`);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
class NavbarElement extends HTMLElement {
|
|
1052
|
+
connectedCallback() {
|
|
1053
|
+
injectStyle();
|
|
1054
|
+
this.style.setProperty("--snap-height", `${attr(this, "height", "64")}px`);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
class SidebarElement extends HTMLElement {
|
|
1058
|
+
connectedCallback() {
|
|
1059
|
+
injectStyle();
|
|
1060
|
+
this.style.setProperty("--snap-width", `${attr(this, "width", "260")}px`);
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
class LogoElement extends HTMLElement {
|
|
1064
|
+
connectedCallback() {
|
|
1065
|
+
injectStyle();
|
|
1066
|
+
if (this.hasAttribute("size")) this.style.setProperty("--snap-size", `${attr(this, "size", "82")}px`);
|
|
1067
|
+
if (!this.innerHTML.trim()) this.textContent = attr(this, "label", "LOGO");
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
class SplitPaneElement extends HTMLElement {
|
|
1071
|
+
connectedCallback() {
|
|
1072
|
+
injectStyle();
|
|
1073
|
+
this.style.setProperty("--snap-columns", attr(this, "columns", "1fr 1fr"));
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
class DividerElement extends HTMLElement {
|
|
1077
|
+
connectedCallback() {
|
|
1078
|
+
injectStyle();
|
|
1079
|
+
if (this.hasAttribute("vertical")) this.classList.add("divider-el-v");
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
class SpacerElement extends HTMLElement {
|
|
1083
|
+
connectedCallback() {
|
|
1084
|
+
injectStyle();
|
|
1085
|
+
if (this.hasAttribute("size")) this.style.setProperty("--snap-size", `${attr(this, "size", "16")}px`);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
const iconPaths = {
|
|
1089
|
+
search: '<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>',
|
|
1090
|
+
bell: '<path d="M10.3 21a1.9 1.9 0 0 0 3.4 0"/><path d="M18 8a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9"/>',
|
|
1091
|
+
user: '<path d="M20 21a8 8 0 0 0-16 0"/><circle cx="12" cy="7" r="4"/>',
|
|
1092
|
+
inbox: '<polyline points="22 12 16 12 14 15 10 15 8 12 2 12"/><path d="M5.5 5h13L22 12v7a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-7z"/>',
|
|
1093
|
+
archive: '<rect width="20" height="5" x="2" y="3" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/><path d="M10 12h4"/>',
|
|
1094
|
+
"at-sign": '<circle cx="12" cy="12" r="4"/><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-4 8"/>',
|
|
1095
|
+
check: '<path d="M20 6 9 17l-5-5"/>',
|
|
1096
|
+
"trash-2": '<path d="M3 6h18"/><path d="M8 6V4h8v2"/><path d="M19 6l-1 14H6L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/>',
|
|
1097
|
+
x: '<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',
|
|
1098
|
+
loader: '<path d="M21 12a9 9 0 1 1-6.2-8.6"/>',
|
|
1099
|
+
image: '<rect width="18" height="18" x="3" y="3" rx="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.1-3.1a2 2 0 0 0-2.8 0L6 21"/>',
|
|
1100
|
+
"circle-alert": '<circle cx="12" cy="12" r="10"/><path d="M12 8v4"/><path d="M12 16h.01"/>',
|
|
1101
|
+
"chevron-down": '<path d="m6 9 6 6 6-6"/>',
|
|
1102
|
+
"layout-dashboard": '<rect width="7" height="9" x="3" y="3" rx="1"/><rect width="7" height="5" x="14" y="3" rx="1"/><rect width="7" height="9" x="14" y="12" rx="1"/><rect width="7" height="5" x="3" y="16" rx="1"/>',
|
|
1103
|
+
"message-square": '<path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z"/>',
|
|
1104
|
+
settings: '<path d="M12.2 2h-.4l-1 3a7 7 0 0 0-1.6.7l-3-1.4-.3.3-2 3 .2.4 2.6 2a7 7 0 0 0 0 2l-2.6 2-.2.4 2 3 .3.3 3-1.4a7 7 0 0 0 1.6.7l1 3h.4l1-3a7 7 0 0 0 1.6-.7l3 1.4.3-.3 2-3-.2-.4-2.6-2a7 7 0 0 0 0-2l2.6-2 .2-.4-2-3-.3-.3-3 1.4a7 7 0 0 0-1.6-.7z"/><circle cx="12" cy="12" r="3"/>',
|
|
1105
|
+
plus: '<path d="M5 12h14"/><path d="M12 5v14"/>',
|
|
1106
|
+
file: '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/>',
|
|
1107
|
+
users: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.9"/><path d="M16 3.1a4 4 0 0 1 0 7.8"/>',
|
|
1108
|
+
shield: '<path d="M20 13c0 5-3.5 7.5-8 9-4.5-1.5-8-4-8-9V5l8-3 8 3z"/>',
|
|
1109
|
+
calendar: '<path d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/>',
|
|
1110
|
+
upload: '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m17 8-5-5-5 5"/><path d="M12 3v12"/>',
|
|
1111
|
+
empty: '<path d="M4 7h16"/><path d="M5 7l1.5 13h11L19 7"/><path d="M9 11h6"/>',
|
|
1112
|
+
"chevron-left": '<path d="m15 18-6-6 6-6"/>',
|
|
1113
|
+
"chevron-right": '<path d="m9 18 6-6-6-6"/>',
|
|
1114
|
+
minus: '<path d="M5 12h14"/>',
|
|
1115
|
+
"alert-triangle": '<path d="m21.7 18-8-14a2 2 0 0 0-3.4 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.7-3Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',
|
|
1116
|
+
info: '<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>',
|
|
1117
|
+
"circle-check": '<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>',
|
|
1118
|
+
circle: '<circle cx="12" cy="12" r="10"/>',
|
|
1119
|
+
"chevron-up": '<path d="m18 15-6-6-6 6"/>',
|
|
1120
|
+
star: '<path d="M12 2l3 6.3 6.9 1-5 4.9 1.2 6.8-6.1-3.2-6.1 3.2 1.2-6.8-5-4.9 6.9-1z"/>',
|
|
1121
|
+
copy: '<rect width="13" height="13" x="9" y="9" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>',
|
|
1122
|
+
lock: '<rect width="18" height="11" x="3" y="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>',
|
|
1123
|
+
"circle-x": '<circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',
|
|
1124
|
+
"more-horizontal": '<circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/>',
|
|
1125
|
+
"more-vertical": '<circle cx="12" cy="12" r="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/>',
|
|
1126
|
+
grip: '<circle cx="9" cy="6" r="1"/><circle cx="9" cy="12" r="1"/><circle cx="9" cy="18" r="1"/><circle cx="15" cy="6" r="1"/><circle cx="15" cy="12" r="1"/><circle cx="15" cy="18" r="1"/>',
|
|
1127
|
+
folder: '<path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2z"/>',
|
|
1128
|
+
"file-code": '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/><path d="m9 13-2 2 2 2"/><path d="m15 13 2 2-2 2"/>',
|
|
1129
|
+
"git-branch": '<line x1="6" x2="6" y1="3" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/>',
|
|
1130
|
+
clock: '<circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/>',
|
|
1131
|
+
key: '<circle cx="7.5" cy="15.5" r="5.5"/><path d="m21 2-9.6 9.6"/><path d="m15.5 7.5 3 3L22 7l-3-3"/>',
|
|
1132
|
+
zap: '<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/>',
|
|
1133
|
+
home: '<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/>',
|
|
1134
|
+
heart: '<path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/>',
|
|
1135
|
+
bookmark: '<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>',
|
|
1136
|
+
download: '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/>',
|
|
1137
|
+
edit: '<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.1 2.1 0 0 1 3 3L12 15l-4 1 1-4Z"/>',
|
|
1138
|
+
eye: '<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/>',
|
|
1139
|
+
filter: '<polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/>',
|
|
1140
|
+
refresh: '<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/><path d="M3 21v-5h5"/>',
|
|
1141
|
+
sparkles: '<path d="M9.9 2.5 12 8l5.5 2.1L12 12l-2.1 5.5L7.8 12 2.3 9.9 7.8 8z"/><path d="M18 5l.9 2.1L21 8l-2.1.9L18 11l-.9-2.1L15 8l2.1-.9z"/>',
|
|
1142
|
+
bot: '<rect width="16" height="11" x="4" y="9" rx="2"/><path d="M12 5v4"/><circle cx="12" cy="4" r="1"/><path d="M9 13v1.5"/><path d="M15 13v1.5"/>',
|
|
1143
|
+
wrench: '<path d="M14.7 6.3a4 4 0 0 0-5.4 5.4L3 18l3 3 6.3-6.3a4 4 0 0 0 5.4-5.4l-2.6 2.6-2.4-.6-.6-2.4z"/>',
|
|
1144
|
+
terminal: '<polyline points="4 17 10 11 4 5"/><line x1="12" x2="20" y1="19" y2="19"/>',
|
|
1145
|
+
"thumbs-up": '<path d="M7 10v11"/><path d="M15 5.9 14 10h5.5a2 2 0 0 1 2 2.4l-1.4 7A2 2 0 0 1 18 21H7V10l4-8a2 2 0 0 1 3 1.7z"/>',
|
|
1146
|
+
"thumbs-down": '<path d="M17 14V3"/><path d="M9 18.1 10 14H4.5a2 2 0 0 1-2-2.4l1.4-7A2 2 0 0 1 6 3h11v11l-4 8a2 2 0 0 1-3-1.7z"/>',
|
|
1147
|
+
send: '<path d="M14.5 9.5 21 3l-6.5 18-2.5-7-7-2.5z"/>',
|
|
1148
|
+
stop: '<rect width="14" height="14" x="5" y="5" rx="2"/>',
|
|
1149
|
+
paperclip: '<path d="m21 8-9.5 9.5a4 4 0 0 1-5.7-5.7L13 4.6a2.7 2.7 0 0 1 3.8 3.8L9.5 15.7a1.3 1.3 0 0 1-1.9-1.9l7.4-7.4"/>',
|
|
1150
|
+
globe: '<circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15 15 0 0 1 0 20 15 15 0 0 1 0-20z"/>'
|
|
1151
|
+
};
|
|
1152
|
+
function icon(name, size = 16) {
|
|
1153
|
+
const key = name || "file";
|
|
1154
|
+
const paths = iconPaths[key] || iconPaths.file;
|
|
1155
|
+
return `<svg class="rp-icon" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${paths}</svg>`;
|
|
1156
|
+
}
|
|
1157
|
+
class FieldElement extends HTMLElement {
|
|
1158
|
+
connectedCallback() {
|
|
1159
|
+
injectStyle();
|
|
1160
|
+
if (this.dataset.rpReady) return;
|
|
1161
|
+
this.dataset.rpReady = "true";
|
|
1162
|
+
const value = attr(this, "value");
|
|
1163
|
+
const placeholder = attr(this, "placeholder", "Search");
|
|
1164
|
+
const label = attr(this, "label");
|
|
1165
|
+
const error = attr(this, "error-message");
|
|
1166
|
+
const showValue = value || attr(this, "state") === "filled";
|
|
1167
|
+
const content = `${this.fieldIcon()}<span class="${showValue ? "rp-value" : "rp-placeholder"}">${escapeHtml(value || placeholder)}</span>${this.hasAttribute("has-clear-button") ? icon("x", 14) : ""}`;
|
|
1168
|
+
this.innerHTML = label || error ? `<span class="rp-field-label">${escapeHtml(label)}</span><span class="rp-field-control">${content}</span>${error ? `<span class="rp-error-text">${escapeHtml(error)}</span>` : ""}` : content;
|
|
1169
|
+
}
|
|
1170
|
+
fieldIcon() {
|
|
1171
|
+
return icon(this.tagName.toLowerCase().includes("date-picker") ? "calendar" : "search");
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
class TextareaElement extends HTMLElement {
|
|
1175
|
+
connectedCallback() {
|
|
1176
|
+
injectStyle();
|
|
1177
|
+
if (this.dataset.rpReady) return;
|
|
1178
|
+
this.dataset.rpReady = "true";
|
|
1179
|
+
this.style.setProperty("--snap-rows", attr(this, "rows", "3"));
|
|
1180
|
+
const value = attr(this, "value") || attr(this, "placeholder", "Textarea");
|
|
1181
|
+
this.innerHTML = `<span class="${attr(this, "value") ? "rp-value" : "rp-placeholder"}">${escapeHtml(value)}</span>`;
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
class SelectElement extends HTMLElement {
|
|
1185
|
+
connectedCallback() {
|
|
1186
|
+
injectStyle();
|
|
1187
|
+
if (this.dataset.rpReady) return;
|
|
1188
|
+
this.dataset.rpReady = "true";
|
|
1189
|
+
const options = csv(this, "options", "选项 A,选项 B,选项 C");
|
|
1190
|
+
const value = attr(this, "value", options[0] || "Select");
|
|
1191
|
+
const label = attr(this, "label");
|
|
1192
|
+
this.innerHTML = `${label ? `<span class="rp-field-label">${escapeHtml(label)}</span>` : ""}<span class="select-el-control"><span class="select-el-value">${escapeHtml(value)}</span>${icon("chevron-down")}</span><span class="select-el-options">${options.map((o) => `<span class="select-el-option${o === value ? " selected" : ""}">${escapeHtml(o)}</span>`).join("")}</span>`;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
class ButtonElement extends HTMLElement {
|
|
1196
|
+
connectedCallback() {
|
|
1197
|
+
var _a;
|
|
1198
|
+
injectStyle();
|
|
1199
|
+
if (this.dataset.rpReady) return;
|
|
1200
|
+
this.dataset.rpReady = "true";
|
|
1201
|
+
const label = attr(this, "label", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "Button");
|
|
1202
|
+
const ic = attr(this, "icon");
|
|
1203
|
+
const loading = attr(this, "state") === "loading";
|
|
1204
|
+
this.innerHTML = `${loading ? icon("loader") : ic ? icon(ic) : ""}<span>${escapeHtml(label)}</span>`;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
class CheckboxElement extends HTMLElement {
|
|
1208
|
+
connectedCallback() {
|
|
1209
|
+
injectStyle();
|
|
1210
|
+
if (this.dataset.rpReady) return;
|
|
1211
|
+
this.dataset.rpReady = "true";
|
|
1212
|
+
const state = attr(this, "state");
|
|
1213
|
+
const mark = state === "checked" ? icon("check", 12) : state === "indeterminate" ? icon("minus", 12) : "";
|
|
1214
|
+
this.innerHTML = `<span class="rp-box">${mark}</span><span>${escapeHtml(attr(this, "label", ""))}</span>`;
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
class RadioElement extends HTMLElement {
|
|
1218
|
+
connectedCallback() {
|
|
1219
|
+
injectStyle();
|
|
1220
|
+
if (this.dataset.rpReady) return;
|
|
1221
|
+
this.dataset.rpReady = "true";
|
|
1222
|
+
const checked = attr(this, "state") === "checked";
|
|
1223
|
+
this.innerHTML = `<span class="rp-box">${checked ? icon("circle", 8) : ""}</span><span>${escapeHtml(attr(this, "label", ""))}</span>`;
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
class ToggleElement extends HTMLElement {
|
|
1227
|
+
connectedCallback() {
|
|
1228
|
+
injectStyle();
|
|
1229
|
+
if (this.dataset.rpReady) return;
|
|
1230
|
+
this.dataset.rpReady = "true";
|
|
1231
|
+
this.innerHTML = `<span class="toggle-el-track"><span class="toggle-el-dot"></span></span><span>${escapeHtml(attr(this, "label", ""))}</span>`;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
class FormElement extends HTMLElement {
|
|
1235
|
+
connectedCallback() {
|
|
1236
|
+
injectStyle();
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
class FormItemElement extends HTMLElement {
|
|
1240
|
+
connectedCallback() {
|
|
1241
|
+
injectStyle();
|
|
1242
|
+
if (this.dataset.rpReady) return;
|
|
1243
|
+
this.dataset.rpReady = "true";
|
|
1244
|
+
const children = Array.from(this.childNodes);
|
|
1245
|
+
const label = attr(this, "label");
|
|
1246
|
+
const error = attr(this, "error");
|
|
1247
|
+
this.innerHTML = `${label ? `<span class="form-el-label${this.hasAttribute("required") ? " required" : ""}">${escapeHtml(label)}</span>` : ""}`;
|
|
1248
|
+
children.forEach((n) => this.appendChild(n));
|
|
1249
|
+
if (error) this.insertAdjacentHTML("beforeend", `<span class="form-el-error">${escapeHtml(error)}</span>`);
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
class DatePickerElement extends FieldElement {
|
|
1253
|
+
fieldIcon() {
|
|
1254
|
+
return icon("calendar");
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
class UploadElement extends HTMLElement {
|
|
1258
|
+
connectedCallback() {
|
|
1259
|
+
injectStyle();
|
|
1260
|
+
if (this.dataset.rpReady) return;
|
|
1261
|
+
this.dataset.rpReady = "true";
|
|
1262
|
+
const state = attr(this, "state", "empty");
|
|
1263
|
+
if (state === "has-file") this.innerHTML = `${icon("file")}<span>${escapeHtml(attr(this, "file", "document.pdf"))}</span>`;
|
|
1264
|
+
else if (state === "uploading") this.innerHTML = `${icon("loader")}<span>上传中...</span><span class="progress-el-bar" style="width:${escapeHtml(attr(this, "progress", "60"))}%"></span>`;
|
|
1265
|
+
else this.innerHTML = `${icon("upload", 24)}<span>${escapeHtml(attr(this, "label", "点击或拖拽文件上传"))}</span>`;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
class ImagePlaceholderElement extends HTMLElement {
|
|
1269
|
+
connectedCallback() {
|
|
1270
|
+
injectStyle();
|
|
1271
|
+
this.style.setProperty("--snap-width", `${attr(this, "width", "160")}px`);
|
|
1272
|
+
this.style.setProperty("--snap-height", `${attr(this, "height", "100")}px`);
|
|
1273
|
+
if (!this.innerHTML.trim()) this.innerHTML = `${icon("image")} ${escapeHtml(attr(this, "label", "Image"))}`;
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
class ProgressElement extends HTMLElement {
|
|
1277
|
+
connectedCallback() {
|
|
1278
|
+
injectStyle();
|
|
1279
|
+
if (this.dataset.rpReady) return;
|
|
1280
|
+
this.dataset.rpReady = "true";
|
|
1281
|
+
const value = attr(this, "value", "40");
|
|
1282
|
+
this.style.setProperty("--progress", `${value}%`);
|
|
1283
|
+
const kind = attr(this, "kind", attr(this, "style"));
|
|
1284
|
+
this.innerHTML = kind === "circle" ? `${escapeHtml(value)}%` : '<span class="progress-el-bar"></span>';
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
class SliderElement extends HTMLElement {
|
|
1288
|
+
connectedCallback() {
|
|
1289
|
+
injectStyle();
|
|
1290
|
+
if (this.dataset.rpReady) return;
|
|
1291
|
+
this.dataset.rpReady = "true";
|
|
1292
|
+
const min = intAttr(this, "min", 0);
|
|
1293
|
+
const max = intAttr(this, "max", 100);
|
|
1294
|
+
const value = intAttr(this, "value", 40);
|
|
1295
|
+
const pct = max > min ? Math.max(0, Math.min(100, (value - min) / (max - min) * 100)) : 0;
|
|
1296
|
+
const label = attr(this, "label");
|
|
1297
|
+
this.innerHTML = `${label ? `<span class="rp-field-label">${escapeHtml(label)}</span>` : ""}<span class="slider-el-track"><span class="slider-el-fill" style="width:${pct}%"></span><span class="slider-el-thumb" style="left:${pct}%"></span></span>${this.hasAttribute("show-value") ? `<span class="slider-el-value">${value}</span>` : ""}`;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
class RangeElement extends HTMLElement {
|
|
1301
|
+
connectedCallback() {
|
|
1302
|
+
injectStyle();
|
|
1303
|
+
if (this.dataset.rpReady) return;
|
|
1304
|
+
this.dataset.rpReady = "true";
|
|
1305
|
+
const min = intAttr(this, "min", 0);
|
|
1306
|
+
const max = intAttr(this, "max", 100);
|
|
1307
|
+
const low = intAttr(this, "low", 25);
|
|
1308
|
+
const high = intAttr(this, "high", 75);
|
|
1309
|
+
const span = max - min || 1;
|
|
1310
|
+
const l = (low - min) / span * 100;
|
|
1311
|
+
const h = (high - min) / span * 100;
|
|
1312
|
+
this.innerHTML = `<span class="slider-el-track"><span class="slider-el-fill" style="left:${l}%;width:${h - l}%"></span><span class="slider-el-thumb" style="left:${l}%"></span><span class="slider-el-thumb" style="left:${h}%"></span></span>`;
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
class NumberInputElement extends HTMLElement {
|
|
1316
|
+
connectedCallback() {
|
|
1317
|
+
injectStyle();
|
|
1318
|
+
if (this.dataset.rpReady) return;
|
|
1319
|
+
this.dataset.rpReady = "true";
|
|
1320
|
+
const value = attr(this, "value", "0");
|
|
1321
|
+
this.innerHTML = `<span class="rp-num-value">${escapeHtml(value)}</span><span class="rp-num-steppers"><span class="rp-num-step">${icon("chevron-up", 12)}</span><span class="rp-num-step">${icon("chevron-down", 12)}</span></span>`;
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
class RatingElement extends HTMLElement {
|
|
1325
|
+
connectedCallback() {
|
|
1326
|
+
injectStyle();
|
|
1327
|
+
if (this.dataset.rpReady) return;
|
|
1328
|
+
this.dataset.rpReady = "true";
|
|
1329
|
+
const max = intAttr(this, "max", 5);
|
|
1330
|
+
const value = intAttr(this, "value", 3);
|
|
1331
|
+
this.innerHTML = Array.from({ length: max }, (_, i) => `<span class="rp-star${i < value ? " filled" : ""}">${icon("star", 16)}</span>`).join("");
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
class PinInputElement extends HTMLElement {
|
|
1335
|
+
connectedCallback() {
|
|
1336
|
+
injectStyle();
|
|
1337
|
+
if (this.dataset.rpReady) return;
|
|
1338
|
+
this.dataset.rpReady = "true";
|
|
1339
|
+
const len = intAttr(this, "length", 4);
|
|
1340
|
+
const value = attr(this, "value", "");
|
|
1341
|
+
const chars = value.split("");
|
|
1342
|
+
this.innerHTML = Array.from({ length: len }, (_, i) => `<span class="rp-pin-cell${i === chars.length ? " active" : ""}">${escapeHtml(chars[i] || "")}</span>`).join("");
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
class ColorSwatchElement extends HTMLElement {
|
|
1346
|
+
connectedCallback() {
|
|
1347
|
+
injectStyle();
|
|
1348
|
+
if (this.dataset.rpReady) return;
|
|
1349
|
+
this.dataset.rpReady = "true";
|
|
1350
|
+
const value = attr(this, "value", "#2563eb");
|
|
1351
|
+
this.innerHTML = `<span class="rp-swatch-chip" style="background:${escapeHtml(value)}"></span><span class="rp-swatch-hex">${escapeHtml(attr(this, "label", value))}</span>`;
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
class AutocompleteElement extends HTMLElement {
|
|
1355
|
+
connectedCallback() {
|
|
1356
|
+
injectStyle();
|
|
1357
|
+
if (this.dataset.rpReady) return;
|
|
1358
|
+
this.dataset.rpReady = "true";
|
|
1359
|
+
const value = attr(this, "value");
|
|
1360
|
+
const options = csv(this, "options", "选项一,选项二,选项三");
|
|
1361
|
+
this.innerHTML = `<span class="rp-field-control">${icon("search")}<span class="${value ? "rp-value" : "rp-placeholder"}">${escapeHtml(value || attr(this, "placeholder", "输入以搜索"))}</span></span>${this.hasAttribute("open") ? `<span class="rp-ac-options">${options.map((o) => `<span class="rp-ac-option">${escapeHtml(o)}</span>`).join("")}</span>` : ""}`;
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
class BadgeElement extends HTMLElement {
|
|
1365
|
+
connectedCallback() {
|
|
1366
|
+
injectStyle();
|
|
1367
|
+
const count = attr(this, "count", "0");
|
|
1368
|
+
const max = intAttr(this, "max", 99);
|
|
1369
|
+
const n = Number(count);
|
|
1370
|
+
this.textContent = Number.isFinite(n) && n > max ? `${max}+` : count;
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
class AvatarElement extends HTMLElement {
|
|
1374
|
+
connectedCallback() {
|
|
1375
|
+
var _a;
|
|
1376
|
+
injectStyle();
|
|
1377
|
+
const size = attr(this, "size", "32");
|
|
1378
|
+
this.style.setProperty("--snap-size", `${size}px`);
|
|
1379
|
+
if (!((_a = this.textContent) == null ? void 0 : _a.trim())) this.textContent = attr(this, "initials", "U");
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
class ListElement extends HTMLElement {
|
|
1383
|
+
connectedCallback() {
|
|
1384
|
+
injectStyle();
|
|
1385
|
+
if (this.dataset.rpReady || this.children.length) return;
|
|
1386
|
+
this.dataset.rpReady = "true";
|
|
1387
|
+
const items = intAttr(this, "items", 3);
|
|
1388
|
+
const state = attr(this, "state");
|
|
1389
|
+
this.innerHTML = Array.from({ length: items }, (_, i) => `<list-item label="${["全部", "未读", "@ 我", "已归档", "设置"][i] || `Item ${i + 1}`}" icon="${["inbox", "message-square", "at-sign", "archive", "settings"][i] || "file"}"${state === "first-selected" && i === 0 ? ' state="selected"' : ""}></list-item>`).join("");
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
class ListItemElement extends HTMLElement {
|
|
1393
|
+
connectedCallback() {
|
|
1394
|
+
var _a;
|
|
1395
|
+
injectStyle();
|
|
1396
|
+
if (this.dataset.rpReady) return;
|
|
1397
|
+
this.dataset.rpReady = "true";
|
|
1398
|
+
const label = attr(this, "label", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "Item");
|
|
1399
|
+
const badge = attr(this, "badge");
|
|
1400
|
+
const ic = attr(this, "icon");
|
|
1401
|
+
this.innerHTML = `${ic ? icon(ic) : ""}<span class="list-el-label">${escapeHtml(label)}</span>${badge ? `<span class="list-el-badge">${escapeHtml(badge)}</span>` : ""}`;
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
class TabsElement extends HTMLElement {
|
|
1405
|
+
connectedCallback() {
|
|
1406
|
+
injectStyle();
|
|
1407
|
+
const active = attr(this, "active", "0");
|
|
1408
|
+
const numeric = Number(active);
|
|
1409
|
+
const children = Array.from(this.children);
|
|
1410
|
+
children.forEach((child, i) => {
|
|
1411
|
+
var _a;
|
|
1412
|
+
const label = child.getAttribute("label") || ((_a = child.textContent) == null ? void 0 : _a.trim()) || "";
|
|
1413
|
+
const isActive = Number.isFinite(numeric) ? i === numeric : label === active;
|
|
1414
|
+
child.classList.toggle("tab-el-active", isActive);
|
|
1415
|
+
});
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
class TabElement extends HTMLElement {
|
|
1419
|
+
connectedCallback() {
|
|
1420
|
+
var _a;
|
|
1421
|
+
injectStyle();
|
|
1422
|
+
if (this.dataset.rpReady) return;
|
|
1423
|
+
this.dataset.rpReady = "true";
|
|
1424
|
+
const label = attr(this, "label", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "Tab");
|
|
1425
|
+
const badge = attr(this, "badge");
|
|
1426
|
+
this.innerHTML = `<span>${escapeHtml(label)}</span>${badge ? `<span class="list-el-badge">${escapeHtml(badge)}</span>` : ""}`;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
class PaginationElement extends HTMLElement {
|
|
1430
|
+
connectedCallback() {
|
|
1431
|
+
injectStyle();
|
|
1432
|
+
if (this.dataset.rpReady) return;
|
|
1433
|
+
this.dataset.rpReady = "true";
|
|
1434
|
+
const total = intAttr(this, "total", 10);
|
|
1435
|
+
const current = intAttr(this, "current", 1);
|
|
1436
|
+
const pageSize = intAttr(this, "page-size", 10);
|
|
1437
|
+
const pages = Math.max(1, Math.ceil(total / pageSize));
|
|
1438
|
+
const visible = Array.from({ length: Math.min(pages, 5) }, (_, i) => i + 1);
|
|
1439
|
+
this.innerHTML = `<span class="page-el-btn">${icon("chevron-left", 14)}</span>${visible.map((p) => `<span class="page-el-btn${p === current ? " active" : ""}">${p}</span>`).join("")}<span class="page-el-btn">${icon("chevron-right", 14)}</span><span>共 ${total} 条</span>`;
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
class StepsElement extends HTMLElement {
|
|
1443
|
+
connectedCallback() {
|
|
1444
|
+
injectStyle();
|
|
1445
|
+
if (this.dataset.rpReady) return;
|
|
1446
|
+
this.dataset.rpReady = "true";
|
|
1447
|
+
const steps = csv(this, "steps", "步骤一,步骤二,步骤三");
|
|
1448
|
+
const active = intAttr(this, "active", 0);
|
|
1449
|
+
this.innerHTML = steps.map((s, i) => `<span class="rp-step ${i < active ? "done" : i === active ? "active" : ""}"><span class="rp-step-dot">${i < active ? icon("check", 12) : i + 1}</span>${escapeHtml(s)}</span>${i < steps.length - 1 ? '<span class="rp-step-sep"></span>' : ""}`).join("");
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
class BreadcrumbElement extends HTMLElement {
|
|
1453
|
+
connectedCallback() {
|
|
1454
|
+
injectStyle();
|
|
1455
|
+
if (this.dataset.rpReady) return;
|
|
1456
|
+
this.dataset.rpReady = "true";
|
|
1457
|
+
const items = csv(this, "items", "首页,当前页");
|
|
1458
|
+
this.innerHTML = items.map((item, i) => `<span class="${i === items.length - 1 ? "breadcrumb-el-current" : ""}">${escapeHtml(item)}</span>${i < items.length - 1 ? "<span>/</span>" : ""}`).join("");
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
class SegmentedElement extends HTMLElement {
|
|
1462
|
+
connectedCallback() {
|
|
1463
|
+
injectStyle();
|
|
1464
|
+
if (this.dataset.rpReady) return;
|
|
1465
|
+
this.dataset.rpReady = "true";
|
|
1466
|
+
const options = csv(this, "options", "日,周,月");
|
|
1467
|
+
const active = attr(this, "active", "0");
|
|
1468
|
+
const idx = Number(active);
|
|
1469
|
+
this.innerHTML = options.map((o, i) => `<span class="rp-seg-item${(Number.isFinite(idx) ? i === idx : o === active) ? " active" : ""}">${escapeHtml(o)}</span>`).join("");
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
class CommandPaletteElement extends HTMLElement {
|
|
1473
|
+
connectedCallback() {
|
|
1474
|
+
injectStyle();
|
|
1475
|
+
if (this.dataset.rpReady) return;
|
|
1476
|
+
this.dataset.rpReady = "true";
|
|
1477
|
+
const query = attr(this, "query");
|
|
1478
|
+
const results = csv(this, "results", "新建文件,打开设置,搜索工单,切换主题");
|
|
1479
|
+
this.innerHTML = `<div class="rp-cmdk-input">${icon("search")}<span class="${query ? "rp-value" : "rp-placeholder"}">${escapeHtml(query || "输入命令…")}</span></div><div class="rp-cmdk-list">${results.map((r, i) => `<div class="rp-cmdk-item${i === 0 ? " active" : ""}">${icon("zap", 14)}<span>${escapeHtml(r)}</span></div>`).join("")}</div>`;
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
class ContextMenuElement extends HTMLElement {
|
|
1483
|
+
connectedCallback() {
|
|
1484
|
+
injectStyle();
|
|
1485
|
+
if (this.dataset.rpReady || this.children.length) return;
|
|
1486
|
+
this.dataset.rpReady = "true";
|
|
1487
|
+
const items = csv(this, "items", "复制,重命名,移动到,删除");
|
|
1488
|
+
this.innerHTML = items.map((it) => `<div class="menu-item${it === "删除" ? " danger" : ""}"><span>${escapeHtml(it)}</span></div>`).join("");
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
class MenuElement extends HTMLElement {
|
|
1492
|
+
connectedCallback() {
|
|
1493
|
+
injectStyle();
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
class MenuItemElement extends HTMLElement {
|
|
1497
|
+
connectedCallback() {
|
|
1498
|
+
var _a;
|
|
1499
|
+
injectStyle();
|
|
1500
|
+
if (this.dataset.rpReady) return;
|
|
1501
|
+
this.dataset.rpReady = "true";
|
|
1502
|
+
const label = attr(this, "label", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "菜单项");
|
|
1503
|
+
const ic = attr(this, "icon");
|
|
1504
|
+
const shortcut = attr(this, "shortcut");
|
|
1505
|
+
const disabled = attr(this, "state") === "disabled";
|
|
1506
|
+
this.innerHTML = `${ic ? icon(ic, 14) : ""}<span class="menu-el-label">${escapeHtml(label)}</span>${shortcut ? `<span class="menu-el-shortcut">${escapeHtml(shortcut)}</span>` : ""}`;
|
|
1507
|
+
if (disabled) this.classList.add("disabled");
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
class TocElement extends HTMLElement {
|
|
1511
|
+
connectedCallback() {
|
|
1512
|
+
injectStyle();
|
|
1513
|
+
if (this.dataset.rpReady || this.children.length) return;
|
|
1514
|
+
this.dataset.rpReady = "true";
|
|
1515
|
+
const items = csv(this, "items", "概述,安装,用法,API,常见问题");
|
|
1516
|
+
this.innerHTML = items.map((it, i) => `<span class="toc-el-item${i === 0 ? " active" : ""}">${escapeHtml(it)}</span>`).join("");
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
class KbdElement extends HTMLElement {
|
|
1520
|
+
connectedCallback() {
|
|
1521
|
+
injectStyle();
|
|
1522
|
+
if (this.dataset.rpReady) return;
|
|
1523
|
+
this.dataset.rpReady = "true";
|
|
1524
|
+
const keys = csv(this, "keys", "⌘,K");
|
|
1525
|
+
this.innerHTML = keys.map((k) => `<kbd class="kbd-el-key">${escapeHtml(k)}</kbd>`).join('<span class="kbd-el-plus">+</span>');
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
function sampleCell(c, j, i) {
|
|
1529
|
+
const lower = c.toLowerCase();
|
|
1530
|
+
if (c.includes("发件") || lower.includes("name")) return ["张三", "李四", "系统通知", "运营助手", "王五", "安全团队"][i % 6];
|
|
1531
|
+
if (c.includes("预览") || lower.includes("preview")) return ["请确认新的项目评审时间", "本周周报已发送", "你的账号存在新的登录", "活动报名已通过审核", "附件已更新", "安全策略变更提醒"][i % 6];
|
|
1532
|
+
if (c.includes("时间") || lower.includes("time")) return ["09:12", "昨天", "周二", "5月30日", "5月28日", "5月20日"][i % 6];
|
|
1533
|
+
if (c.includes("状态") || lower.includes("status")) return i % 2 ? "未读" : "已读";
|
|
1534
|
+
return `Data ${i + 1}-${j + 1}`;
|
|
1535
|
+
}
|
|
1536
|
+
class TableElement extends HTMLElement {
|
|
1537
|
+
connectedCallback() {
|
|
1538
|
+
injectStyle();
|
|
1539
|
+
if (this.dataset.rpReady) return;
|
|
1540
|
+
this.dataset.rpReady = "true";
|
|
1541
|
+
const cols = csv(this, "columns", "Name,Preview,Time,Status");
|
|
1542
|
+
const rows = intAttr(this, "rows", 4);
|
|
1543
|
+
const hasCheckbox = this.hasAttribute("has-checkbox");
|
|
1544
|
+
const hasAction = this.hasAttribute("has-action");
|
|
1545
|
+
const finalCols = hasAction ? [...cols, "操作"] : cols;
|
|
1546
|
+
const headCells = `${hasCheckbox ? '<span class="table-el-cell">✓</span>' : ""}${finalCols.map((c) => `<span class="table-el-cell">${escapeHtml(c)}</span>`).join("")}`;
|
|
1547
|
+
const body = Array.from({ length: rows }, (_, i) => `<div class="table-row">${hasCheckbox ? `<span class="table-el-cell"><span class="rp-box">${i === 1 ? icon("check", 12) : ""}</span></span>` : ""}${finalCols.map((c, j) => `<span class="table-el-cell">${c === "操作" ? '<button-el label="查看" variant="link"></button-el>' : escapeHtml(sampleCell(c, j, i))}</span>`).join("")}</div>`).join("");
|
|
1548
|
+
this.innerHTML = `<div class="table-row table-el-head">${headCells}</div>${body}`;
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
class TableRowElement extends HTMLElement {
|
|
1552
|
+
connectedCallback() {
|
|
1553
|
+
injectStyle();
|
|
1554
|
+
if (this.dataset.rpReady) return;
|
|
1555
|
+
this.dataset.rpReady = "true";
|
|
1556
|
+
this.innerHTML = `<span><span class="rp-box">${attr(this, "state") === "selected" ? icon("check", 12) : ""}</span></span><span>张三</span><span>消息内容预览文本</span><span>09:12</span><span>${escapeHtml(attr(this, "state", "default"))}</span>`;
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
class BulkActionBarElement extends HTMLElement {
|
|
1560
|
+
connectedCallback() {
|
|
1561
|
+
injectStyle();
|
|
1562
|
+
if (this.dataset.rpReady) return;
|
|
1563
|
+
this.dataset.rpReady = "true";
|
|
1564
|
+
const count = attr(this, "count", "1");
|
|
1565
|
+
const actions = csv(this, "actions", "确认,取消");
|
|
1566
|
+
this.innerHTML = `${icon("check")}<span>已选 ${escapeHtml(count)} 项</span>${actions.map((a) => `<button-el label="${escapeHtml(a)}" variant="ghost"></button-el>`).join("")}`;
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
class EmptyElement extends HTMLElement {
|
|
1570
|
+
connectedCallback() {
|
|
1571
|
+
injectStyle();
|
|
1572
|
+
if (this.dataset.rpReady) return;
|
|
1573
|
+
this.dataset.rpReady = "true";
|
|
1574
|
+
this.innerHTML = `${icon("empty", 28)}<span class="empty-el-title">${escapeHtml(attr(this, "label", "暂无数据"))}</span><span class="empty-el-desc">${escapeHtml(attr(this, "description", ""))}</span>${this.hasAttribute("has-action") ? '<button-el label="新建" variant="primary" icon="plus"></button-el>' : ""}`;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
class LoadingElement extends HTMLElement {
|
|
1578
|
+
connectedCallback() {
|
|
1579
|
+
injectStyle();
|
|
1580
|
+
if (this.dataset.rpReady) return;
|
|
1581
|
+
this.dataset.rpReady = "true";
|
|
1582
|
+
const rows = intAttr(this, "rows", 3);
|
|
1583
|
+
this.innerHTML = attr(this, "kind") === "spinner" || attr(this, "style") === "spinner" ? `<span class="rp-spinner">${icon("loader", 24)}</span>` : Array.from({ length: rows }, (_, i) => `<span class="skeleton-el-line" style="width:${220 - i * 24}px"></span>`).join("");
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
class AlertElement extends HTMLElement {
|
|
1587
|
+
connectedCallback() {
|
|
1588
|
+
injectStyle();
|
|
1589
|
+
if (this.dataset.rpReady) return;
|
|
1590
|
+
this.dataset.rpReady = "true";
|
|
1591
|
+
const type = attr(this, "type", "info");
|
|
1592
|
+
const title = attr(this, "title", type === "error" ? "错误" : "提示");
|
|
1593
|
+
const message = attr(this, "message", "");
|
|
1594
|
+
const ic = type === "error" ? "circle-alert" : type === "warning" ? "alert-triangle" : type === "success" ? "circle-check" : "info";
|
|
1595
|
+
this.innerHTML = `${icon(ic)}<span><strong>${escapeHtml(title)}</strong>${message ? `<br>${escapeHtml(message)}` : ""}</span>${this.hasAttribute("closable") ? icon("x", 14) : ""}`;
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
class OverlayElement extends HTMLElement {
|
|
1599
|
+
connectedCallback() {
|
|
1600
|
+
injectStyle();
|
|
1601
|
+
if (this.dataset.rpReady) return;
|
|
1602
|
+
this.dataset.rpReady = "true";
|
|
1603
|
+
const children = Array.from(this.childNodes);
|
|
1604
|
+
const title = attr(this, "title");
|
|
1605
|
+
if (!title) return;
|
|
1606
|
+
const head = document.createElement("div");
|
|
1607
|
+
head.className = "rp-overlay-title";
|
|
1608
|
+
head.textContent = title;
|
|
1609
|
+
this.prepend(head);
|
|
1610
|
+
children.forEach((n) => this.appendChild(n));
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
class TooltipElement extends HTMLElement {
|
|
1614
|
+
connectedCallback() {
|
|
1615
|
+
var _a;
|
|
1616
|
+
injectStyle();
|
|
1617
|
+
if (!((_a = this.textContent) == null ? void 0 : _a.trim())) this.textContent = attr(this, "text", "提示内容");
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
class ModalElement extends HTMLElement {
|
|
1621
|
+
connectedCallback() {
|
|
1622
|
+
injectStyle();
|
|
1623
|
+
if (this.dataset.rpReady) return;
|
|
1624
|
+
this.dataset.rpReady = "true";
|
|
1625
|
+
this.style.setProperty("--snap-width", `${attr(this, "width", "480")}px`);
|
|
1626
|
+
const children = Array.from(this.childNodes);
|
|
1627
|
+
const body = document.createElement("div");
|
|
1628
|
+
body.className = "modal-el-body";
|
|
1629
|
+
children.forEach((n) => body.appendChild(n));
|
|
1630
|
+
this.innerHTML = `<div class="modal-el-head"><span>${escapeHtml(attr(this, "title", "标题"))}</span>${icon("x", 14)}</div>`;
|
|
1631
|
+
this.appendChild(body);
|
|
1632
|
+
if (this.hasAttribute("has-footer")) this.insertAdjacentHTML("beforeend", '<div class="modal-el-footer"><button-el label="取消"></button-el><button-el label="确认" variant="primary"></button-el></div>');
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
class DrawerElement extends HTMLElement {
|
|
1636
|
+
connectedCallback() {
|
|
1637
|
+
injectStyle();
|
|
1638
|
+
if (this.dataset.rpReady) return;
|
|
1639
|
+
this.dataset.rpReady = "true";
|
|
1640
|
+
this.style.setProperty("--snap-width", `${attr(this, "width", "360")}px`);
|
|
1641
|
+
const children = Array.from(this.childNodes);
|
|
1642
|
+
const body = document.createElement("div");
|
|
1643
|
+
body.className = "drawer-el-body";
|
|
1644
|
+
children.forEach((n) => body.appendChild(n));
|
|
1645
|
+
this.innerHTML = `<div class="drawer-el-head"><span>${escapeHtml(attr(this, "title", "抽屉"))}</span>${icon("x", 14)}</div>`;
|
|
1646
|
+
this.appendChild(body);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
class CardElement extends HTMLElement {
|
|
1650
|
+
connectedCallback() {
|
|
1651
|
+
injectStyle();
|
|
1652
|
+
if (this.dataset.rpReady) return;
|
|
1653
|
+
this.dataset.rpReady = "true";
|
|
1654
|
+
const children = Array.from(this.childNodes);
|
|
1655
|
+
const title = attr(this, "title");
|
|
1656
|
+
const subtitle = attr(this, "subtitle");
|
|
1657
|
+
this.innerHTML = `${this.hasAttribute("has-image") ? `<span class="card-el-image">${icon("image")} Image</span>` : ""}${title ? `<span class="card-el-title">${escapeHtml(title)}</span>` : ""}${subtitle ? `<span class="card-el-subtitle">${escapeHtml(subtitle)}</span>` : ""}`;
|
|
1658
|
+
children.forEach((n) => this.appendChild(n));
|
|
1659
|
+
if (this.hasAttribute("has-footer")) this.insertAdjacentHTML("beforeend", '<span class="card-el-footer"><button-el label="查看" variant="secondary"></button-el></span>');
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
class StatCardElement extends HTMLElement {
|
|
1663
|
+
connectedCallback() {
|
|
1664
|
+
injectStyle();
|
|
1665
|
+
if (this.dataset.rpReady) return;
|
|
1666
|
+
this.dataset.rpReady = "true";
|
|
1667
|
+
this.innerHTML = `<span class="rp-stat-label">${escapeHtml(attr(this, "label", "指标"))}</span><span class="rp-stat-value">${escapeHtml(attr(this, "value", "128"))}</span><span class="rp-stat-change">${escapeHtml(attr(this, "change", "0%"))}</span>`;
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
class TagElement extends HTMLElement {
|
|
1671
|
+
connectedCallback() {
|
|
1672
|
+
var _a;
|
|
1673
|
+
injectStyle();
|
|
1674
|
+
if (this.dataset.rpReady) return;
|
|
1675
|
+
this.dataset.rpReady = "true";
|
|
1676
|
+
const label = attr(this, "label", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "Tag");
|
|
1677
|
+
this.innerHTML = `<span>${escapeHtml(label)}</span>${this.hasAttribute("closable") ? icon("x", 12) : ""}`;
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
class ChipElement extends HTMLElement {
|
|
1681
|
+
connectedCallback() {
|
|
1682
|
+
var _a;
|
|
1683
|
+
injectStyle();
|
|
1684
|
+
if (this.dataset.rpReady) return;
|
|
1685
|
+
this.dataset.rpReady = "true";
|
|
1686
|
+
const label = attr(this, "label", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "Chip");
|
|
1687
|
+
const ic = attr(this, "icon");
|
|
1688
|
+
this.innerHTML = `${ic ? icon(ic, 12) : ""}<span>${escapeHtml(label)}</span>${this.hasAttribute("closable") ? icon("x", 11) : ""}`;
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
class TreeElement extends HTMLElement {
|
|
1692
|
+
connectedCallback() {
|
|
1693
|
+
injectStyle();
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
class TreeItemElement extends HTMLElement {
|
|
1697
|
+
connectedCallback() {
|
|
1698
|
+
injectStyle();
|
|
1699
|
+
if (this.dataset.rpReady) return;
|
|
1700
|
+
this.dataset.rpReady = "true";
|
|
1701
|
+
const level = intAttr(this, "level", 0);
|
|
1702
|
+
const label = attr(this, "label", "Node");
|
|
1703
|
+
const ic = attr(this, "icon");
|
|
1704
|
+
const expandable = this.hasAttribute("expanded") || this.hasAttribute("collapsed");
|
|
1705
|
+
const expanded = this.hasAttribute("expanded");
|
|
1706
|
+
const caret = expandable ? icon(expanded ? "chevron-down" : "chevron-right", 12) : '<span class="tree-el-spacer"></span>';
|
|
1707
|
+
this.style.setProperty("--tree-level", String(level));
|
|
1708
|
+
this.innerHTML = `<span class="tree-el-row${attr(this, "state") === "selected" ? " selected" : ""}">${caret}${icon(ic || (expandable ? "folder" : "file"), 14)}<span class="tree-el-label">${escapeHtml(label)}</span></span>`;
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
class TimelineElement extends HTMLElement {
|
|
1712
|
+
connectedCallback() {
|
|
1713
|
+
injectStyle();
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
class TimelineItemElement extends HTMLElement {
|
|
1717
|
+
connectedCallback() {
|
|
1718
|
+
injectStyle();
|
|
1719
|
+
if (this.dataset.rpReady) return;
|
|
1720
|
+
this.dataset.rpReady = "true";
|
|
1721
|
+
const children = Array.from(this.childNodes);
|
|
1722
|
+
const label = attr(this, "label");
|
|
1723
|
+
const time = attr(this, "time");
|
|
1724
|
+
const state = attr(this, "state", "default");
|
|
1725
|
+
const dot = `<span class="timeline-el-dot ${state}"></span>`;
|
|
1726
|
+
const head = `<div class="timeline-el-head"><span class="timeline-el-label">${escapeHtml(label)}</span>${time ? `<span class="timeline-el-time">${escapeHtml(time)}</span>` : ""}</div>`;
|
|
1727
|
+
const body = document.createElement("div");
|
|
1728
|
+
body.className = "timeline-el-content";
|
|
1729
|
+
children.forEach((n) => body.appendChild(n));
|
|
1730
|
+
this.innerHTML = `${dot}<div class="timeline-el-main">${head}</div>`;
|
|
1731
|
+
this.querySelector(".timeline-el-main").appendChild(body);
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
class CalendarElement extends HTMLElement {
|
|
1735
|
+
connectedCallback() {
|
|
1736
|
+
injectStyle();
|
|
1737
|
+
if (this.dataset.rpReady) return;
|
|
1738
|
+
this.dataset.rpReady = "true";
|
|
1739
|
+
const month = attr(this, "month", "2026 年 6 月");
|
|
1740
|
+
const selected = intAttr(this, "selected", 15);
|
|
1741
|
+
const dows = ["一", "二", "三", "四", "五", "六", "日"];
|
|
1742
|
+
const cells = Array.from({ length: 35 }, (_, i) => {
|
|
1743
|
+
const day = i - 1;
|
|
1744
|
+
const valid = day >= 1 && day <= 30;
|
|
1745
|
+
return `<span class="rp-cal-cell${valid && day === selected ? " selected" : ""}${valid ? "" : " muted"}">${valid ? day : ""}</span>`;
|
|
1746
|
+
}).join("");
|
|
1747
|
+
this.innerHTML = `<div class="rp-cal-head"><span>${escapeHtml(month)}</span></div><div class="rp-cal-grid">${dows.map((d) => `<span class="rp-cal-dow">${d}</span>`).join("")}${cells}</div>`;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
class KanbanElement extends HTMLElement {
|
|
1751
|
+
connectedCallback() {
|
|
1752
|
+
injectStyle();
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
class KanbanColumnElement extends HTMLElement {
|
|
1756
|
+
connectedCallback() {
|
|
1757
|
+
injectStyle();
|
|
1758
|
+
if (this.dataset.rpReady) return;
|
|
1759
|
+
this.dataset.rpReady = "true";
|
|
1760
|
+
const children = Array.from(this.childNodes);
|
|
1761
|
+
const title = attr(this, "title", "列");
|
|
1762
|
+
const count = attr(this, "count");
|
|
1763
|
+
const head = document.createElement("div");
|
|
1764
|
+
head.className = "kanban-el-head";
|
|
1765
|
+
head.innerHTML = `<span>${escapeHtml(title)}</span>${count ? `<span class="kanban-el-count">${escapeHtml(count)}</span>` : ""}`;
|
|
1766
|
+
const body = document.createElement("div");
|
|
1767
|
+
body.className = "kanban-el-body";
|
|
1768
|
+
children.forEach((n) => body.appendChild(n));
|
|
1769
|
+
this.append(head, body);
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
class KanbanCardElement extends HTMLElement {
|
|
1773
|
+
connectedCallback() {
|
|
1774
|
+
injectStyle();
|
|
1775
|
+
if (this.dataset.rpReady) return;
|
|
1776
|
+
this.dataset.rpReady = "true";
|
|
1777
|
+
const label = attr(this, "label", "卡片");
|
|
1778
|
+
const tag = attr(this, "tag");
|
|
1779
|
+
this.innerHTML = `<span class="kanban-card-title">${escapeHtml(label)}</span>${tag ? `<span class="kanban-card-tag">${escapeHtml(tag)}</span>` : ""}`;
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
class CodeBlockElement extends HTMLElement {
|
|
1783
|
+
connectedCallback() {
|
|
1784
|
+
injectStyle();
|
|
1785
|
+
if (this.dataset.rpReady) return;
|
|
1786
|
+
this.dataset.rpReady = "true";
|
|
1787
|
+
const lines = intAttr(this, "lines", 5);
|
|
1788
|
+
const lang = attr(this, "lang", "ts");
|
|
1789
|
+
const body = Array.from({ length: lines }, (_, i) => `<span class="rp-code-line"><span class="rp-code-ln">${i + 1}</span><span class="rp-code-bar" style="width:${40 + i * 37 % 50}%"></span></span>`).join("");
|
|
1790
|
+
this.innerHTML = `<div class="rp-code-head">${escapeHtml(lang)}</div><div class="rp-code-body">${body}</div>`;
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
class DiffElement extends HTMLElement {
|
|
1794
|
+
connectedCallback() {
|
|
1795
|
+
injectStyle();
|
|
1796
|
+
if (this.dataset.rpReady) return;
|
|
1797
|
+
this.dataset.rpReady = "true";
|
|
1798
|
+
const rows = intAttr(this, "rows", 4);
|
|
1799
|
+
const body = Array.from({ length: rows }, (_, i) => {
|
|
1800
|
+
const kind = i % 3 === 0 ? "add" : i % 3 === 1 ? "del" : "ctx";
|
|
1801
|
+
const sign = kind === "add" ? "+" : kind === "del" ? "-" : " ";
|
|
1802
|
+
return `<span class="diff-el-line ${kind}"><span class="diff-el-sign">${sign}</span><span class="rp-code-bar" style="width:${45 + i * 29 % 45}%"></span></span>`;
|
|
1803
|
+
}).join("");
|
|
1804
|
+
this.innerHTML = body;
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
class ImageGridElement extends HTMLElement {
|
|
1808
|
+
connectedCallback() {
|
|
1809
|
+
injectStyle();
|
|
1810
|
+
if (this.dataset.rpReady) return;
|
|
1811
|
+
this.dataset.rpReady = "true";
|
|
1812
|
+
const count = intAttr(this, "count", 6);
|
|
1813
|
+
const cols = intAttr(this, "columns", 3);
|
|
1814
|
+
this.style.setProperty("--grid-cols", String(cols));
|
|
1815
|
+
this.innerHTML = Array.from({ length: count }, () => `<span class="rp-grid-cell">${icon("image", 20)}</span>`).join("");
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
class KeyValueElement extends HTMLElement {
|
|
1819
|
+
connectedCallback() {
|
|
1820
|
+
injectStyle();
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
class KvRowElement extends HTMLElement {
|
|
1824
|
+
connectedCallback() {
|
|
1825
|
+
injectStyle();
|
|
1826
|
+
if (this.dataset.rpReady) return;
|
|
1827
|
+
this.dataset.rpReady = "true";
|
|
1828
|
+
this.innerHTML = `<span class="rp-kv-key">${escapeHtml(attr(this, "label", "键"))}</span><span class="rp-kv-val">${escapeHtml(attr(this, "value", "值"))}</span>`;
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
class AccordionElement extends HTMLElement {
|
|
1832
|
+
connectedCallback() {
|
|
1833
|
+
injectStyle();
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
class AccordionItemElement extends HTMLElement {
|
|
1837
|
+
connectedCallback() {
|
|
1838
|
+
injectStyle();
|
|
1839
|
+
if (this.dataset.rpReady) return;
|
|
1840
|
+
this.dataset.rpReady = "true";
|
|
1841
|
+
const children = Array.from(this.childNodes);
|
|
1842
|
+
const label = attr(this, "label", "分节");
|
|
1843
|
+
const expanded = this.hasAttribute("expanded");
|
|
1844
|
+
const head = document.createElement("div");
|
|
1845
|
+
head.className = "accordion-el-head";
|
|
1846
|
+
head.innerHTML = `${icon(expanded ? "chevron-down" : "chevron-right", 14)}<span>${escapeHtml(label)}</span>`;
|
|
1847
|
+
this.appendChild(head);
|
|
1848
|
+
if (expanded) {
|
|
1849
|
+
const body = document.createElement("div");
|
|
1850
|
+
body.className = "accordion-el-body";
|
|
1851
|
+
children.forEach((n) => body.appendChild(n));
|
|
1852
|
+
this.appendChild(body);
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
class BannerElement extends HTMLElement {
|
|
1857
|
+
connectedCallback() {
|
|
1858
|
+
injectStyle();
|
|
1859
|
+
if (this.dataset.rpReady) return;
|
|
1860
|
+
this.dataset.rpReady = "true";
|
|
1861
|
+
const type = attr(this, "type", "info");
|
|
1862
|
+
const ic = type === "error" ? "circle-alert" : type === "warning" ? "alert-triangle" : type === "success" ? "circle-check" : "info";
|
|
1863
|
+
this.innerHTML = `${icon(ic)}<span class="banner-el-text"><strong>${escapeHtml(attr(this, "title", "通知"))}</strong>${attr(this, "message") ? ` ${escapeHtml(attr(this, "message"))}` : ""}</span>${this.hasAttribute("has-action") ? '<button-el label="查看" variant="link"></button-el>' : ""}${this.hasAttribute("closable") ? icon("x", 14) : ""}`;
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
class SkeletonElement extends HTMLElement {
|
|
1867
|
+
connectedCallback() {
|
|
1868
|
+
injectStyle();
|
|
1869
|
+
if (this.dataset.rpReady) return;
|
|
1870
|
+
this.dataset.rpReady = "true";
|
|
1871
|
+
const shape = attr(this, "shape", "line");
|
|
1872
|
+
if (shape === "avatar") this.innerHTML = '<span class="rp-skel rp-skel-avatar"></span>';
|
|
1873
|
+
else if (shape === "card") this.innerHTML = '<span class="rp-skel rp-skel-block"></span><span class="skeleton-el-line" style="width:70%"></span><span class="skeleton-el-line" style="width:50%"></span>';
|
|
1874
|
+
else if (shape === "list") this.innerHTML = Array.from({ length: 3 }, () => '<span class="rp-skel-row"><span class="rp-skel rp-skel-avatar sm"></span><span class="skeleton-el-line" style="width:60%"></span></span>').join("");
|
|
1875
|
+
else this.innerHTML = '<span class="skeleton-el-line"></span>';
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
class CountdownElement extends HTMLElement {
|
|
1879
|
+
connectedCallback() {
|
|
1880
|
+
injectStyle();
|
|
1881
|
+
if (this.dataset.rpReady) return;
|
|
1882
|
+
this.dataset.rpReady = "true";
|
|
1883
|
+
this.innerHTML = `${icon("clock", 13)}<span>${escapeHtml(attr(this, "value", "02:45:18"))}</span>`;
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
class ResultElement extends HTMLElement {
|
|
1887
|
+
connectedCallback() {
|
|
1888
|
+
injectStyle();
|
|
1889
|
+
if (this.dataset.rpReady) return;
|
|
1890
|
+
this.dataset.rpReady = "true";
|
|
1891
|
+
const status = attr(this, "status", "success");
|
|
1892
|
+
const ic = status === "error" ? "circle-x" : status === "empty" ? "empty" : "circle-check";
|
|
1893
|
+
this.innerHTML = `<span class="result-el-icon ${status}">${icon(ic, 40)}</span><span class="result-el-title">${escapeHtml(attr(this, "title", "操作成功"))}</span><span class="result-el-desc">${escapeHtml(attr(this, "description", ""))}</span>${this.hasAttribute("has-action") ? '<button-el label="返回" variant="primary"></button-el>' : ""}`;
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
class PermissionGateElement extends HTMLElement {
|
|
1897
|
+
connectedCallback() {
|
|
1898
|
+
injectStyle();
|
|
1899
|
+
if (this.dataset.rpReady) return;
|
|
1900
|
+
this.dataset.rpReady = "true";
|
|
1901
|
+
const children = Array.from(this.childNodes);
|
|
1902
|
+
const wrap = document.createElement("div");
|
|
1903
|
+
wrap.className = "rp-gate-content";
|
|
1904
|
+
children.forEach((n) => wrap.appendChild(n));
|
|
1905
|
+
const overlay = document.createElement("div");
|
|
1906
|
+
overlay.className = "rp-gate-overlay";
|
|
1907
|
+
overlay.innerHTML = `${icon("lock", 16)}<span>${escapeHtml(attr(this, "reason", "无权限"))}</span>`;
|
|
1908
|
+
this.append(wrap, overlay);
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
class QuotaBarElement extends HTMLElement {
|
|
1912
|
+
connectedCallback() {
|
|
1913
|
+
injectStyle();
|
|
1914
|
+
if (this.dataset.rpReady) return;
|
|
1915
|
+
this.dataset.rpReady = "true";
|
|
1916
|
+
const used = intAttr(this, "used", 70);
|
|
1917
|
+
const limit = intAttr(this, "limit", 100);
|
|
1918
|
+
const pct = limit ? Math.min(100, used / limit * 100) : 0;
|
|
1919
|
+
const danger = pct >= 90;
|
|
1920
|
+
this.innerHTML = `<div class="rp-quota-head"><span>${escapeHtml(attr(this, "label", "用量"))}</span><span class="rp-quota-num${danger ? " danger" : ""}">${used} / ${limit}</span></div><span class="rp-quota-track"><span class="rp-quota-fill${danger ? " danger" : ""}" style="width:${pct}%"></span></span>`;
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
class ApiKeyElement extends HTMLElement {
|
|
1924
|
+
connectedCallback() {
|
|
1925
|
+
injectStyle();
|
|
1926
|
+
if (this.dataset.rpReady) return;
|
|
1927
|
+
this.dataset.rpReady = "true";
|
|
1928
|
+
const value = attr(this, "value", "sk_live_••••••••••••3f9a");
|
|
1929
|
+
this.innerHTML = `<span class="rp-apikey-val">${escapeHtml(value)}</span><span class="rp-apikey-copy">${icon("copy", 14)}</span>`;
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
class AuditRowElement extends HTMLElement {
|
|
1933
|
+
connectedCallback() {
|
|
1934
|
+
injectStyle();
|
|
1935
|
+
if (this.dataset.rpReady) return;
|
|
1936
|
+
this.dataset.rpReady = "true";
|
|
1937
|
+
this.innerHTML = `<span class="rp-audit-actor">${escapeHtml(attr(this, "actor", "用户"))}</span><span class="rp-audit-action">${escapeHtml(attr(this, "action", "执行了操作"))}</span><span class="rp-audit-time">${escapeHtml(attr(this, "time", "刚刚"))}</span>`;
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
class WorkflowNodeElement extends HTMLElement {
|
|
1941
|
+
connectedCallback() {
|
|
1942
|
+
injectStyle();
|
|
1943
|
+
if (this.dataset.rpReady) return;
|
|
1944
|
+
this.dataset.rpReady = "true";
|
|
1945
|
+
const state = attr(this, "state", "default");
|
|
1946
|
+
const ic = state === "done" ? "circle-check" : state === "active" ? "circle" : state === "error" ? "circle-x" : "circle";
|
|
1947
|
+
this.innerHTML = `<span class="rp-wf-icon ${state}">${icon(ic, 16)}</span><span class="rp-wf-label">${escapeHtml(attr(this, "label", "节点"))}</span>`;
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
class IosNavbarElement extends HTMLElement {
|
|
1951
|
+
connectedCallback() {
|
|
1952
|
+
injectStyle();
|
|
1953
|
+
if (this.dataset.rpReady) return;
|
|
1954
|
+
this.dataset.rpReady = "true";
|
|
1955
|
+
const title = attr(this, "title", "标题");
|
|
1956
|
+
const large = this.hasAttribute("large");
|
|
1957
|
+
const back = attr(this, "back");
|
|
1958
|
+
const trailing = attr(this, "trailing");
|
|
1959
|
+
this.innerHTML = `<div class="ios-navbar-row"><span class="rp-ios-nav-leading">${back ? `${icon("chevron-left", 18)}<span>${escapeHtml(back)}</span>` : ""}</span><span class="rp-ios-nav-title${large ? " inline" : ""}">${large ? "" : escapeHtml(title)}</span><span class="rp-ios-nav-trailing">${trailing ? escapeHtml(trailing) : ""}</span></div>${large ? `<div class="rp-ios-nav-large">${escapeHtml(title)}</div>` : ""}`;
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
class IosTabbarElement extends HTMLElement {
|
|
1963
|
+
connectedCallback() {
|
|
1964
|
+
injectStyle();
|
|
1965
|
+
if (this.dataset.rpReady) return;
|
|
1966
|
+
this.dataset.rpReady = "true";
|
|
1967
|
+
const items = csv(this, "items", "首页,搜索,通知,我的");
|
|
1968
|
+
const icons = csv(this, "icons", "home,search,bell,user");
|
|
1969
|
+
const active = intAttr(this, "active", 0);
|
|
1970
|
+
this.innerHTML = items.map((it, i) => `<span class="rp-ios-tab${i === active ? " active" : ""}">${icon(icons[i] || "circle", 22)}<span class="rp-ios-tab-label">${escapeHtml(it)}</span></span>`).join("");
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
class IosListElement extends HTMLElement {
|
|
1974
|
+
connectedCallback() {
|
|
1975
|
+
injectStyle();
|
|
1976
|
+
if (this.dataset.rpReady) return;
|
|
1977
|
+
this.dataset.rpReady = "true";
|
|
1978
|
+
const header = attr(this, "header");
|
|
1979
|
+
if (header) {
|
|
1980
|
+
const h = document.createElement("div");
|
|
1981
|
+
h.className = "ios-list-header";
|
|
1982
|
+
h.textContent = header;
|
|
1983
|
+
this.insertBefore(h, this.firstChild);
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
class IosListItemElement extends HTMLElement {
|
|
1988
|
+
connectedCallback() {
|
|
1989
|
+
injectStyle();
|
|
1990
|
+
if (this.dataset.rpReady) return;
|
|
1991
|
+
this.dataset.rpReady = "true";
|
|
1992
|
+
const label = attr(this, "label", "项");
|
|
1993
|
+
const detail = attr(this, "detail");
|
|
1994
|
+
const ic = attr(this, "icon");
|
|
1995
|
+
const chevron = this.hasAttribute("chevron");
|
|
1996
|
+
this.innerHTML = `${ic ? `<span class="rp-ios-li-icon">${icon(ic, 16)}</span>` : ""}<span class="rp-ios-li-label">${escapeHtml(label)}</span>${detail ? `<span class="rp-ios-li-detail">${escapeHtml(detail)}</span>` : ""}${chevron ? `<span class="rp-ios-li-chevron">${icon("chevron-right", 16)}</span>` : ""}`;
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
class IosActionSheetElement extends HTMLElement {
|
|
2000
|
+
connectedCallback() {
|
|
2001
|
+
injectStyle();
|
|
2002
|
+
if (this.dataset.rpReady) return;
|
|
2003
|
+
this.dataset.rpReady = "true";
|
|
2004
|
+
const title = attr(this, "title");
|
|
2005
|
+
const actions = csv(this, "actions", "拍照,从相册选择,选择文件");
|
|
2006
|
+
const destructive = attr(this, "destructive");
|
|
2007
|
+
const group = `<div class="rp-ios-as-group">${title ? `<div class="rp-ios-as-title">${escapeHtml(title)}</div>` : ""}${actions.map((a) => `<div class="rp-ios-as-action${a === destructive ? " destructive" : ""}">${escapeHtml(a)}</div>`).join("")}</div>`;
|
|
2008
|
+
const cancel = `<div class="rp-ios-as-group"><div class="rp-ios-as-action cancel">取消</div></div>`;
|
|
2009
|
+
this.innerHTML = group + cancel;
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
class IosAlertElement extends HTMLElement {
|
|
2013
|
+
connectedCallback() {
|
|
2014
|
+
injectStyle();
|
|
2015
|
+
if (this.dataset.rpReady) return;
|
|
2016
|
+
this.dataset.rpReady = "true";
|
|
2017
|
+
const title = attr(this, "title", "提示");
|
|
2018
|
+
const message = attr(this, "message", "");
|
|
2019
|
+
const actions = csv(this, "actions", "取消,确定");
|
|
2020
|
+
this.innerHTML = `<div class="ios-alert-body"><div class="ios-alert-title">${escapeHtml(title)}</div>${message ? `<div class="ios-alert-msg">${escapeHtml(message)}</div>` : ""}</div><div class="ios-alert-actions">${actions.map((a, i) => `<span class="ios-alert-btn${i === actions.length - 1 ? " primary" : ""}">${escapeHtml(a)}</span>`).join("")}</div>`;
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
class IosSwitchElement extends HTMLElement {
|
|
2024
|
+
connectedCallback() {
|
|
2025
|
+
injectStyle();
|
|
2026
|
+
if (this.dataset.rpReady) return;
|
|
2027
|
+
this.dataset.rpReady = "true";
|
|
2028
|
+
const label = attr(this, "label");
|
|
2029
|
+
this.innerHTML = `${label ? `<span class="ios-switch-label">${escapeHtml(label)}</span>` : ""}<span class="ios-switch-track"><span class="ios-switch-dot"></span></span>`;
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
class IosSegmentedElement extends HTMLElement {
|
|
2033
|
+
connectedCallback() {
|
|
2034
|
+
injectStyle();
|
|
2035
|
+
if (this.dataset.rpReady) return;
|
|
2036
|
+
this.dataset.rpReady = "true";
|
|
2037
|
+
const options = csv(this, "options", "第一,第二,第三");
|
|
2038
|
+
const active = intAttr(this, "active", 0);
|
|
2039
|
+
this.innerHTML = options.map((o, i) => `<span class="rp-ios-seg-item${i === active ? " active" : ""}">${escapeHtml(o)}</span>`).join("");
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
class IosButtonElement extends HTMLElement {
|
|
2043
|
+
connectedCallback() {
|
|
2044
|
+
var _a;
|
|
2045
|
+
injectStyle();
|
|
2046
|
+
if (this.dataset.rpReady) return;
|
|
2047
|
+
this.dataset.rpReady = "true";
|
|
2048
|
+
this.innerHTML = `<span>${escapeHtml(attr(this, "label", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "按钮"))}</span>`;
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
class IosSearchElement extends HTMLElement {
|
|
2052
|
+
connectedCallback() {
|
|
2053
|
+
injectStyle();
|
|
2054
|
+
if (this.dataset.rpReady) return;
|
|
2055
|
+
this.dataset.rpReady = "true";
|
|
2056
|
+
const value = attr(this, "value");
|
|
2057
|
+
this.innerHTML = `${icon("search", 15)}<span class="${value ? "rp-value" : "rp-placeholder"}">${escapeHtml(value || attr(this, "placeholder", "搜索"))}</span>`;
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
class IosStepperElement extends HTMLElement {
|
|
2061
|
+
connectedCallback() {
|
|
2062
|
+
injectStyle();
|
|
2063
|
+
if (this.dataset.rpReady) return;
|
|
2064
|
+
this.dataset.rpReady = "true";
|
|
2065
|
+
this.innerHTML = `<span class="rp-ios-step minus">${icon("minus", 16)}</span><span class="rp-ios-step-div"></span><span class="rp-ios-step plus">${icon("plus", 16)}</span>`;
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
class MacWindowElement extends HTMLElement {
|
|
2069
|
+
connectedCallback() {
|
|
2070
|
+
injectStyle();
|
|
2071
|
+
if (this.dataset.rpReady) return;
|
|
2072
|
+
this.dataset.rpReady = "true";
|
|
2073
|
+
const children = Array.from(this.childNodes);
|
|
2074
|
+
const title = attr(this, "title", "窗口");
|
|
2075
|
+
const titlebar = `<div class="rp-mac-titlebar"><span class="rp-mac-lights"><span class="rp-mac-light close"></span><span class="rp-mac-light min"></span><span class="rp-mac-light max"></span></span><span class="rp-mac-title">${escapeHtml(title)}</span></div>`;
|
|
2076
|
+
const body = document.createElement("div");
|
|
2077
|
+
body.className = "rp-mac-window-body";
|
|
2078
|
+
children.forEach((n) => body.appendChild(n));
|
|
2079
|
+
this.innerHTML = titlebar;
|
|
2080
|
+
this.appendChild(body);
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
class MacToolbarElement extends HTMLElement {
|
|
2084
|
+
connectedCallback() {
|
|
2085
|
+
injectStyle();
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
class MacMenubarElement extends HTMLElement {
|
|
2089
|
+
connectedCallback() {
|
|
2090
|
+
injectStyle();
|
|
2091
|
+
if (this.dataset.rpReady) return;
|
|
2092
|
+
this.dataset.rpReady = "true";
|
|
2093
|
+
const items = csv(this, "items", "文件,编辑,显示,窗口,帮助");
|
|
2094
|
+
this.innerHTML = `<span class="rp-mac-menubar-apple">${icon("home", 14)}</span>` + items.map((it, i) => `<span class="rp-mac-menu-title${i === 0 ? " active" : ""}">${escapeHtml(it)}</span>`).join("");
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
class MacSidebarElement extends HTMLElement {
|
|
2098
|
+
connectedCallback() {
|
|
2099
|
+
injectStyle();
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
class MacSourceItemElement extends HTMLElement {
|
|
2103
|
+
connectedCallback() {
|
|
2104
|
+
injectStyle();
|
|
2105
|
+
if (this.dataset.rpReady) return;
|
|
2106
|
+
this.dataset.rpReady = "true";
|
|
2107
|
+
const label = attr(this, "label", "项");
|
|
2108
|
+
const ic = attr(this, "icon");
|
|
2109
|
+
if (this.hasAttribute("group")) {
|
|
2110
|
+
this.classList.add("rp-mac-source-group");
|
|
2111
|
+
this.textContent = label;
|
|
2112
|
+
return;
|
|
2113
|
+
}
|
|
2114
|
+
this.innerHTML = `${ic ? icon(ic, 15) : ""}<span class="rp-mac-source-label">${escapeHtml(label)}</span>`;
|
|
2115
|
+
if (attr(this, "state") === "selected") this.classList.add("selected");
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
class MacSegmentedElement extends HTMLElement {
|
|
2119
|
+
connectedCallback() {
|
|
2120
|
+
injectStyle();
|
|
2121
|
+
if (this.dataset.rpReady) return;
|
|
2122
|
+
this.dataset.rpReady = "true";
|
|
2123
|
+
const options = csv(this, "options", "全部,未读,标记");
|
|
2124
|
+
const active = intAttr(this, "active", 0);
|
|
2125
|
+
this.innerHTML = options.map((o, i) => `<span class="rp-mac-seg-item${i === active ? " active" : ""}">${escapeHtml(o)}</span>`).join("");
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
class MacPopoverElement extends HTMLElement {
|
|
2129
|
+
connectedCallback() {
|
|
2130
|
+
injectStyle();
|
|
2131
|
+
if (this.dataset.rpReady) return;
|
|
2132
|
+
this.dataset.rpReady = "true";
|
|
2133
|
+
const children = Array.from(this.childNodes);
|
|
2134
|
+
const title = attr(this, "title");
|
|
2135
|
+
const arrow = '<span class="rp-mac-pop-arrow"></span>';
|
|
2136
|
+
const body = document.createElement("div");
|
|
2137
|
+
body.className = "rp-mac-pop-body";
|
|
2138
|
+
if (title) {
|
|
2139
|
+
const h = document.createElement("div");
|
|
2140
|
+
h.className = "rp-mac-pop-title";
|
|
2141
|
+
h.textContent = title;
|
|
2142
|
+
body.appendChild(h);
|
|
2143
|
+
}
|
|
2144
|
+
children.forEach((n) => body.appendChild(n));
|
|
2145
|
+
this.innerHTML = arrow;
|
|
2146
|
+
this.appendChild(body);
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
class MacSheetElement extends HTMLElement {
|
|
2150
|
+
connectedCallback() {
|
|
2151
|
+
injectStyle();
|
|
2152
|
+
if (this.dataset.rpReady) return;
|
|
2153
|
+
this.dataset.rpReady = "true";
|
|
2154
|
+
const children = Array.from(this.childNodes);
|
|
2155
|
+
const title = attr(this, "title", "操作");
|
|
2156
|
+
const body = document.createElement("div");
|
|
2157
|
+
body.className = "rp-mac-sheet-body";
|
|
2158
|
+
children.forEach((n) => body.appendChild(n));
|
|
2159
|
+
this.innerHTML = `<div class="rp-mac-sheet-title">${escapeHtml(title)}</div>`;
|
|
2160
|
+
this.appendChild(body);
|
|
2161
|
+
this.insertAdjacentHTML("beforeend", '<div class="rp-mac-sheet-actions"><button-el label="取消"></button-el><button-el label="完成" variant="primary"></button-el></div>');
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
class MacStepperElement extends HTMLElement {
|
|
2165
|
+
connectedCallback() {
|
|
2166
|
+
injectStyle();
|
|
2167
|
+
if (this.dataset.rpReady) return;
|
|
2168
|
+
this.dataset.rpReady = "true";
|
|
2169
|
+
this.innerHTML = `<span class="rp-mac-step up">${icon("chevron-up", 11)}</span><span class="rp-mac-step down">${icon("chevron-down", 11)}</span>`;
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
class MacDisclosureElement extends HTMLElement {
|
|
2173
|
+
connectedCallback() {
|
|
2174
|
+
injectStyle();
|
|
2175
|
+
if (this.dataset.rpReady) return;
|
|
2176
|
+
this.dataset.rpReady = "true";
|
|
2177
|
+
const children = Array.from(this.childNodes);
|
|
2178
|
+
const label = attr(this, "label", "详情");
|
|
2179
|
+
const expanded = this.hasAttribute("expanded");
|
|
2180
|
+
const head = document.createElement("div");
|
|
2181
|
+
head.className = "rp-mac-disc-head";
|
|
2182
|
+
head.innerHTML = `<span class="rp-mac-disc-tri${expanded ? " open" : ""}">${icon("chevron-right", 12)}</span><span>${escapeHtml(label)}</span>`;
|
|
2183
|
+
this.appendChild(head);
|
|
2184
|
+
if (expanded) {
|
|
2185
|
+
const body = document.createElement("div");
|
|
2186
|
+
body.className = "rp-mac-disc-body";
|
|
2187
|
+
children.forEach((n) => body.appendChild(n));
|
|
2188
|
+
this.appendChild(body);
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
class MacTableElement extends HTMLElement {
|
|
2193
|
+
connectedCallback() {
|
|
2194
|
+
injectStyle();
|
|
2195
|
+
if (this.dataset.rpReady) return;
|
|
2196
|
+
this.dataset.rpReady = "true";
|
|
2197
|
+
const cols = csv(this, "columns", "名称,类型,大小");
|
|
2198
|
+
const rows = intAttr(this, "rows", 5);
|
|
2199
|
+
const head = `<div class="rp-mac-tr rp-mac-th">${cols.map((c, i) => `<span class="rp-mac-td">${escapeHtml(c)}${i === 0 ? icon("chevron-up", 10) : ""}</span>`).join("")}</div>`;
|
|
2200
|
+
const body = Array.from({ length: rows }, (_, r) => `<div class="rp-mac-tr${r % 2 ? " alt" : ""}">${cols.map((c, ci) => `<span class="rp-mac-td">${ci === 0 ? icon("file", 13) : ""}<span class="rp-mac-cell-bar" style="width:${50 + (r * 17 + ci * 23) % 40}%"></span></span>`).join("")}</div>`).join("");
|
|
2201
|
+
this.innerHTML = head + body;
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
class ChatElement extends HTMLElement {
|
|
2205
|
+
connectedCallback() {
|
|
2206
|
+
injectStyle();
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
class UserMessageElement extends HTMLElement {
|
|
2210
|
+
connectedCallback() {
|
|
2211
|
+
injectStyle();
|
|
2212
|
+
if (this.dataset.rpReady) return;
|
|
2213
|
+
this.dataset.rpReady = "true";
|
|
2214
|
+
const children = Array.from(this.childNodes);
|
|
2215
|
+
const text = attr(this, "text");
|
|
2216
|
+
const content = document.createElement("div");
|
|
2217
|
+
content.className = "rp-msg-content";
|
|
2218
|
+
if (text) content.textContent = text;
|
|
2219
|
+
else children.forEach((n) => content.appendChild(n));
|
|
2220
|
+
this.innerHTML = `<div class="rp-msg-role">You</div>`;
|
|
2221
|
+
this.appendChild(content);
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
class AssistantMessageElement extends HTMLElement {
|
|
2225
|
+
connectedCallback() {
|
|
2226
|
+
injectStyle();
|
|
2227
|
+
if (this.dataset.rpReady) return;
|
|
2228
|
+
this.dataset.rpReady = "true";
|
|
2229
|
+
const children = Array.from(this.childNodes);
|
|
2230
|
+
const text = attr(this, "text");
|
|
2231
|
+
const name = attr(this, "name", "Assistant");
|
|
2232
|
+
const content = document.createElement("div");
|
|
2233
|
+
content.className = "rp-msg-content";
|
|
2234
|
+
if (text) content.textContent = text;
|
|
2235
|
+
else children.forEach((n) => content.appendChild(n));
|
|
2236
|
+
this.innerHTML = `<div class="rp-msg-role">${escapeHtml(name)}</div>`;
|
|
2237
|
+
this.appendChild(content);
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
class SystemMessageElement extends HTMLElement {
|
|
2241
|
+
connectedCallback() {
|
|
2242
|
+
var _a;
|
|
2243
|
+
injectStyle();
|
|
2244
|
+
if (this.dataset.rpReady) return;
|
|
2245
|
+
this.dataset.rpReady = "true";
|
|
2246
|
+
const text = attr(this, "text", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "系统消息");
|
|
2247
|
+
this.innerHTML = `<span class="rp-sysmsg-line">${escapeHtml(text)}</span>`;
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
class ToolCallElement extends HTMLElement {
|
|
2251
|
+
connectedCallback() {
|
|
2252
|
+
injectStyle();
|
|
2253
|
+
if (this.dataset.rpReady) return;
|
|
2254
|
+
this.dataset.rpReady = "true";
|
|
2255
|
+
const children = Array.from(this.childNodes);
|
|
2256
|
+
const name = attr(this, "name", "tool");
|
|
2257
|
+
const state = attr(this, "state", "done");
|
|
2258
|
+
const glyph = state === "running" ? icon("loader", 13) : state === "error" ? icon("circle-x", 13) : icon("check", 13);
|
|
2259
|
+
const args = attr(this, "args");
|
|
2260
|
+
const head = `<div class="rp-tool-head"><span class="rp-tool-glyph ${state}">${glyph}</span><span class="rp-tool-name">${escapeHtml(name)}</span>${args ? `<span class="rp-tool-args-inline">${escapeHtml(args)}</span>` : ""}</div>`;
|
|
2261
|
+
const body = document.createElement("div");
|
|
2262
|
+
body.className = "rp-tool-body";
|
|
2263
|
+
children.forEach((n) => body.appendChild(n));
|
|
2264
|
+
this.innerHTML = head;
|
|
2265
|
+
if (children.length) this.appendChild(body);
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
class AgentOutputElement extends HTMLElement {
|
|
2269
|
+
connectedCallback() {
|
|
2270
|
+
injectStyle();
|
|
2271
|
+
if (this.dataset.rpReady) return;
|
|
2272
|
+
this.dataset.rpReady = "true";
|
|
2273
|
+
const children = Array.from(this.childNodes);
|
|
2274
|
+
const label = attr(this, "label");
|
|
2275
|
+
const head = label ? `<div class="rp-output-head">${escapeHtml(label)}</div>` : "";
|
|
2276
|
+
const body = document.createElement("div");
|
|
2277
|
+
body.className = "rp-output-body";
|
|
2278
|
+
const text = attr(this, "text");
|
|
2279
|
+
if (text) body.textContent = text;
|
|
2280
|
+
else children.forEach((n) => body.appendChild(n));
|
|
2281
|
+
this.innerHTML = head;
|
|
2282
|
+
this.appendChild(body);
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
class ReasoningElement extends HTMLElement {
|
|
2286
|
+
connectedCallback() {
|
|
2287
|
+
injectStyle();
|
|
2288
|
+
if (this.dataset.rpReady) return;
|
|
2289
|
+
this.dataset.rpReady = "true";
|
|
2290
|
+
const children = Array.from(this.childNodes);
|
|
2291
|
+
const expanded = this.hasAttribute("expanded");
|
|
2292
|
+
const head = `<div class="rp-reason-head">${icon(expanded ? "chevron-down" : "chevron-right", 13)}<span>Thought for a few seconds</span></div>`;
|
|
2293
|
+
this.innerHTML = head;
|
|
2294
|
+
if (expanded) {
|
|
2295
|
+
const body = document.createElement("div");
|
|
2296
|
+
body.className = "rp-reason-body";
|
|
2297
|
+
children.forEach((n) => body.appendChild(n));
|
|
2298
|
+
this.appendChild(body);
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
class MessageActionsElement extends HTMLElement {
|
|
2303
|
+
connectedCallback() {
|
|
2304
|
+
injectStyle();
|
|
2305
|
+
if (this.dataset.rpReady || this.children.length) return;
|
|
2306
|
+
this.dataset.rpReady = "true";
|
|
2307
|
+
const actions = csv(this, "actions", "copy,retry,up,down");
|
|
2308
|
+
const map = { copy: ["copy", "复制"], retry: ["refresh", "重试"], up: ["thumbs-up", "赞"], down: ["thumbs-down", "踩"], edit: ["edit", "编辑"], share: ["send", "分享"] };
|
|
2309
|
+
this.innerHTML = actions.map((a) => {
|
|
2310
|
+
const m = map[a] || ["circle", a];
|
|
2311
|
+
return `<span class="rp-msg-action" title="${escapeHtml(m[1])}">${icon(m[0], 14)}</span>`;
|
|
2312
|
+
}).join("");
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
class SuggestionsElement extends HTMLElement {
|
|
2316
|
+
connectedCallback() {
|
|
2317
|
+
injectStyle();
|
|
2318
|
+
if (this.dataset.rpReady) return;
|
|
2319
|
+
this.dataset.rpReady = "true";
|
|
2320
|
+
const items = csv(this, "items", "总结要点,继续,给个例子");
|
|
2321
|
+
this.innerHTML = items.map((t) => `<span class="rp-suggestion">${escapeHtml(t)}</span>`).join("");
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
class TypingElement extends HTMLElement {
|
|
2325
|
+
connectedCallback() {
|
|
2326
|
+
injectStyle();
|
|
2327
|
+
if (this.dataset.rpReady) return;
|
|
2328
|
+
this.dataset.rpReady = "true";
|
|
2329
|
+
this.innerHTML = `<span class="typing-el-dots"><span></span><span></span><span></span></span>`;
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
class ComposerElement extends HTMLElement {
|
|
2333
|
+
connectedCallback() {
|
|
2334
|
+
injectStyle();
|
|
2335
|
+
if (this.dataset.rpReady) return;
|
|
2336
|
+
this.dataset.rpReady = "true";
|
|
2337
|
+
const value = attr(this, "value");
|
|
2338
|
+
const state = attr(this, "state", "idle");
|
|
2339
|
+
const sendIcon = state === "streaming" ? icon("stop", 16) : icon("send", 16);
|
|
2340
|
+
this.innerHTML = `<span class="composer-el-attach">${icon("paperclip", 16)}</span><span class="composer-el-input ${value ? "rp-value" : "rp-placeholder"}">${escapeHtml(value || attr(this, "placeholder", "给助手发消息…"))}</span><span class="composer-el-send ${state}">${sendIcon}</span>`;
|
|
2341
|
+
}
|
|
2342
|
+
}
|
|
2343
|
+
class CitationElement extends HTMLElement {
|
|
2344
|
+
connectedCallback() {
|
|
2345
|
+
var _a;
|
|
2346
|
+
injectStyle();
|
|
2347
|
+
if (this.dataset.rpReady) return;
|
|
2348
|
+
this.dataset.rpReady = "true";
|
|
2349
|
+
const index = attr(this, "index", "1");
|
|
2350
|
+
const title = attr(this, "title", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "来源");
|
|
2351
|
+
this.innerHTML = `<span class="rp-cite-idx">${escapeHtml(index)}</span><span class="rp-cite-title">${escapeHtml(title)}</span>`;
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
class TokenUsageElement extends HTMLElement {
|
|
2355
|
+
connectedCallback() {
|
|
2356
|
+
injectStyle();
|
|
2357
|
+
if (this.dataset.rpReady) return;
|
|
2358
|
+
this.dataset.rpReady = "true";
|
|
2359
|
+
const used = intAttr(this, "used", 1840);
|
|
2360
|
+
const limit = intAttr(this, "limit", 8e3);
|
|
2361
|
+
const pct = limit ? Math.min(100, used / limit * 100) : 0;
|
|
2362
|
+
this.innerHTML = `<span>${used.toLocaleString()} / ${limit.toLocaleString()} tokens</span><span class="rp-token-track"><span class="rp-token-fill" style="width:${pct}%"></span></span>`;
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
function registerAll() {
|
|
2366
|
+
define("page-el", RpPage);
|
|
2367
|
+
define("main-view", RpMainView);
|
|
2368
|
+
define("annotation-el", RpAnnotation);
|
|
2369
|
+
define("enum-el", RpEnum);
|
|
2370
|
+
define("enum-item", RpEnumItem);
|
|
2371
|
+
const pairs = [
|
|
2372
|
+
// layout
|
|
2373
|
+
["viewport", ViewportElement],
|
|
2374
|
+
["layout", LayoutElement],
|
|
2375
|
+
["panel", PanelElement],
|
|
2376
|
+
["navigator", NavbarElement],
|
|
2377
|
+
["sidebar", SidebarElement],
|
|
2378
|
+
["logo", LogoElement],
|
|
2379
|
+
["split-pane", SplitPaneElement],
|
|
2380
|
+
["divider", DividerElement],
|
|
2381
|
+
["spacer", SpacerElement],
|
|
2382
|
+
// controls
|
|
2383
|
+
["search", FieldElement],
|
|
2384
|
+
["input", FieldElement],
|
|
2385
|
+
["textarea", TextareaElement],
|
|
2386
|
+
["select", SelectElement],
|
|
2387
|
+
["button", ButtonElement],
|
|
2388
|
+
["button-group", GenericElement],
|
|
2389
|
+
["checkbox", CheckboxElement],
|
|
2390
|
+
["radio", RadioElement],
|
|
2391
|
+
["toggle", ToggleElement],
|
|
2392
|
+
["form", FormElement],
|
|
2393
|
+
["form-item", FormItemElement],
|
|
2394
|
+
["date-picker", DatePickerElement],
|
|
2395
|
+
["upload", UploadElement],
|
|
2396
|
+
["image-placeholder", ImagePlaceholderElement],
|
|
2397
|
+
["progress", ProgressElement],
|
|
2398
|
+
["slider", SliderElement],
|
|
2399
|
+
["range", RangeElement],
|
|
2400
|
+
["number-input", NumberInputElement],
|
|
2401
|
+
["rating", RatingElement],
|
|
2402
|
+
["pin-input", PinInputElement],
|
|
2403
|
+
["color-swatch", ColorSwatchElement],
|
|
2404
|
+
["autocomplete", AutocompleteElement],
|
|
2405
|
+
// navigation
|
|
2406
|
+
["badge", BadgeElement],
|
|
2407
|
+
["avatar", AvatarElement],
|
|
2408
|
+
["list", ListElement],
|
|
2409
|
+
["list-item", ListItemElement],
|
|
2410
|
+
["tabs", TabsElement],
|
|
2411
|
+
["tab", TabElement],
|
|
2412
|
+
["pagination", PaginationElement],
|
|
2413
|
+
["steps", StepsElement],
|
|
2414
|
+
["breadcrumb", BreadcrumbElement],
|
|
2415
|
+
["segmented", SegmentedElement],
|
|
2416
|
+
["command-palette", CommandPaletteElement],
|
|
2417
|
+
["context-menu", ContextMenuElement],
|
|
2418
|
+
["menu", MenuElement],
|
|
2419
|
+
["menu-item", MenuItemElement],
|
|
2420
|
+
["toc", TocElement],
|
|
2421
|
+
["kbd", KbdElement],
|
|
2422
|
+
// data display
|
|
2423
|
+
["table", TableElement],
|
|
2424
|
+
["table-row", TableRowElement],
|
|
2425
|
+
["bulk-action-bar", BulkActionBarElement],
|
|
2426
|
+
["empty", EmptyElement],
|
|
2427
|
+
["loading", LoadingElement],
|
|
2428
|
+
["alert", AlertElement],
|
|
2429
|
+
["toast", AlertElement],
|
|
2430
|
+
["dropdown", OverlayElement],
|
|
2431
|
+
["popover", OverlayElement],
|
|
2432
|
+
["tooltip", TooltipElement],
|
|
2433
|
+
["modal", ModalElement],
|
|
2434
|
+
["drawer", DrawerElement],
|
|
2435
|
+
["card", CardElement],
|
|
2436
|
+
["stat-card", StatCardElement],
|
|
2437
|
+
["tag", TagElement],
|
|
2438
|
+
["chip", ChipElement],
|
|
2439
|
+
["tree", TreeElement],
|
|
2440
|
+
["tree-item", TreeItemElement],
|
|
2441
|
+
["timeline", TimelineElement],
|
|
2442
|
+
["timeline-item", TimelineItemElement],
|
|
2443
|
+
["calendar", CalendarElement],
|
|
2444
|
+
["kanban", KanbanElement],
|
|
2445
|
+
["kanban-column", KanbanColumnElement],
|
|
2446
|
+
["kanban-card", KanbanCardElement],
|
|
2447
|
+
["code-block", CodeBlockElement],
|
|
2448
|
+
["diff", DiffElement],
|
|
2449
|
+
["image-grid", ImageGridElement],
|
|
2450
|
+
["key-value", KeyValueElement],
|
|
2451
|
+
["kv-row", KvRowElement],
|
|
2452
|
+
["accordion", AccordionElement],
|
|
2453
|
+
["accordion-item", AccordionItemElement],
|
|
2454
|
+
["banner", BannerElement],
|
|
2455
|
+
["skeleton", SkeletonElement],
|
|
2456
|
+
["countdown", CountdownElement],
|
|
2457
|
+
["result", ResultElement],
|
|
2458
|
+
["permission-gate", PermissionGateElement],
|
|
2459
|
+
["quota-bar", QuotaBarElement],
|
|
2460
|
+
["api-key", ApiKeyElement],
|
|
2461
|
+
["audit-row", AuditRowElement],
|
|
2462
|
+
["workflow-node", WorkflowNodeElement],
|
|
2463
|
+
// iOS
|
|
2464
|
+
["ios-navbar", IosNavbarElement],
|
|
2465
|
+
["ios-tabbar", IosTabbarElement],
|
|
2466
|
+
["ios-list", IosListElement],
|
|
2467
|
+
["ios-list-item", IosListItemElement],
|
|
2468
|
+
["ios-action-sheet", IosActionSheetElement],
|
|
2469
|
+
["ios-alert", IosAlertElement],
|
|
2470
|
+
["ios-switch", IosSwitchElement],
|
|
2471
|
+
["ios-segmented", IosSegmentedElement],
|
|
2472
|
+
["ios-button", IosButtonElement],
|
|
2473
|
+
["ios-search", IosSearchElement],
|
|
2474
|
+
["ios-stepper", IosStepperElement],
|
|
2475
|
+
// macOS
|
|
2476
|
+
["macos-window", MacWindowElement],
|
|
2477
|
+
["macos-toolbar", MacToolbarElement],
|
|
2478
|
+
["macos-menubar", MacMenubarElement],
|
|
2479
|
+
["macos-sidebar", MacSidebarElement],
|
|
2480
|
+
["macos-source-item", MacSourceItemElement],
|
|
2481
|
+
["macos-segmented", MacSegmentedElement],
|
|
2482
|
+
["macos-popover", MacPopoverElement],
|
|
2483
|
+
["macos-sheet", MacSheetElement],
|
|
2484
|
+
["macos-stepper", MacStepperElement],
|
|
2485
|
+
["macos-disclosure", MacDisclosureElement],
|
|
2486
|
+
["macos-table", MacTableElement],
|
|
2487
|
+
// agent / conversational UI
|
|
2488
|
+
["chat", ChatElement],
|
|
2489
|
+
["user-message", UserMessageElement],
|
|
2490
|
+
["assistant-message", AssistantMessageElement],
|
|
2491
|
+
["system-message", SystemMessageElement],
|
|
2492
|
+
["tool-call", ToolCallElement],
|
|
2493
|
+
["agent-output", AgentOutputElement],
|
|
2494
|
+
["reasoning", ReasoningElement],
|
|
2495
|
+
["message-actions", MessageActionsElement],
|
|
2496
|
+
["suggestions", SuggestionsElement],
|
|
2497
|
+
["typing", TypingElement],
|
|
2498
|
+
["composer", ComposerElement],
|
|
2499
|
+
["citation", CitationElement],
|
|
2500
|
+
["token-usage", TokenUsageElement]
|
|
2501
|
+
];
|
|
2502
|
+
for (const [suffix] of pairs) {
|
|
2503
|
+
if (toComponentTag(suffix) === suffix && !suffix.includes("-"))
|
|
2504
|
+
console.warn(`[rpui] registry tag "${suffix}" missing from RPML vocabulary`);
|
|
2505
|
+
}
|
|
2506
|
+
for (const [suffix, ctor] of pairs) {
|
|
2507
|
+
define(toComponentTag(suffix), ctor);
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
registerAll();
|
|
2511
|
+
registerAll();
|
|
2512
|
+
const CHROME_CSS = `
|
|
2513
|
+
.rpml-gallery { display:grid; grid-template-columns:260px 1fr; height:100vh; font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; }
|
|
2514
|
+
.rpml-gallery.collapsed { grid-template-columns:1fr; }
|
|
2515
|
+
.rpml-gallery.collapsed .rpml-gx-side { display:none; }
|
|
2516
|
+
.rpml-gx-side { display:flex; flex-direction:column; border-right:1px solid #e5e7eb; background:#fff; min-height:0; }
|
|
2517
|
+
.rpml-gx-head { display:flex; align-items:flex-start; justify-content:space-between; gap:8px; padding:16px; border-bottom:1px solid #e5e7eb; font-size:14px; font-weight:700; color:#111827; }
|
|
2518
|
+
.rpml-gx-head small { display:block; margin-top:3px; font-size:11px; font-weight:400; color:#6b7280; }
|
|
2519
|
+
.rpml-gx-toggle { flex:none; display:flex; align-items:center; justify-content:center; width:26px; height:26px; margin:-3px -3px 0 0; padding:0; border:1px solid #e5e7eb; border-radius:7px; background:#fff; color:#6b7280; font-size:15px; line-height:1; cursor:pointer; }
|
|
2520
|
+
.rpml-gx-toggle:hover { background:#f3f4f6; color:#111827; }
|
|
2521
|
+
.rpml-gx-fab { position:fixed; top:12px; left:12px; z-index:50; display:none; align-items:center; justify-content:center; width:34px; height:34px; padding:0; border:1px solid #e5e7eb; border-radius:9px; background:#fff; color:#374151; font-size:17px; line-height:1; cursor:pointer; box-shadow:0 1px 3px rgba(0,0,0,.12); }
|
|
2522
|
+
.rpml-gx-fab:hover { background:#f3f4f6; color:#111827; }
|
|
2523
|
+
.rpml-gallery.collapsed .rpml-gx-fab { display:flex; }
|
|
2524
|
+
.rpml-gx-nav { flex:1; overflow-y:auto; padding:8px; }
|
|
2525
|
+
.rpml-gx-group { padding:10px 8px 3px; font-size:11px; font-weight:700; color:#9ca3af; text-transform:uppercase; letter-spacing:.04em; }
|
|
2526
|
+
.rpml-gx-item { display:block; padding:6px 10px; border-radius:7px; font-size:13px; color:#374151; text-decoration:none; cursor:pointer; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
|
2527
|
+
.rpml-gx-item:hover { background:#f3f4f6; }
|
|
2528
|
+
.rpml-gx-item.active { background:#eff6ff; color:#1d4ed8; font-weight:650; }
|
|
2529
|
+
.rpml-gx-indent { padding-left:22px; }
|
|
2530
|
+
.rpml-gx-main { overflow:auto; min-height:0; background:#f4f6f8; }
|
|
2531
|
+
.rpml-gx-err { padding:40px; color:#dc2626; font-family:ui-monospace,Menlo,monospace; }
|
|
2532
|
+
`;
|
|
2533
|
+
function injectChrome() {
|
|
2534
|
+
if (document.getElementById("rpml-gallery-style")) return;
|
|
2535
|
+
const s = document.createElement("style");
|
|
2536
|
+
s.id = "rpml-gallery-style";
|
|
2537
|
+
s.textContent = CHROME_CSS;
|
|
2538
|
+
document.head.appendChild(s);
|
|
2539
|
+
}
|
|
2540
|
+
function docTitle(source, fallback) {
|
|
2541
|
+
const m = source.match(/<page\b[^>]*\btitle="([^"]*)"/i);
|
|
2542
|
+
return (m == null ? void 0 : m[1]) || fallback;
|
|
2543
|
+
}
|
|
2544
|
+
function buildTree(docs) {
|
|
2545
|
+
const root = { name: "", children: /* @__PURE__ */ new Map() };
|
|
2546
|
+
for (const doc of docs) {
|
|
2547
|
+
const parts = doc.path.split("/").filter(Boolean);
|
|
2548
|
+
let node = root;
|
|
2549
|
+
for (let i = 0; i < parts.length; i++) {
|
|
2550
|
+
const part = parts[i];
|
|
2551
|
+
const isLeaf = i === parts.length - 1;
|
|
2552
|
+
if (!node.children.has(part)) node.children.set(part, { name: part, children: /* @__PURE__ */ new Map() });
|
|
2553
|
+
node = node.children.get(part);
|
|
2554
|
+
if (isLeaf) {
|
|
2555
|
+
node.path = doc.path;
|
|
2556
|
+
node.title = docTitle(doc.source, part.replace(/\.rpml$/i, ""));
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
return root;
|
|
2561
|
+
}
|
|
2562
|
+
function basename(path) {
|
|
2563
|
+
return path.split("/").pop() || path;
|
|
2564
|
+
}
|
|
2565
|
+
function mountGallery(docs, host = document.body) {
|
|
2566
|
+
injectChrome();
|
|
2567
|
+
const byPath = new Map(docs.map((d) => [d.path, d]));
|
|
2568
|
+
const tree = buildTree(docs);
|
|
2569
|
+
const root = document.createElement("div");
|
|
2570
|
+
root.className = "rpml-gallery";
|
|
2571
|
+
const side = document.createElement("aside");
|
|
2572
|
+
side.className = "rpml-gx-side";
|
|
2573
|
+
const count = docs.length;
|
|
2574
|
+
side.innerHTML = `<div class="rpml-gx-head"><span>RPML 文档<small>${count} 个文件</small></span><button class="rpml-gx-toggle" type="button" title="收起侧边栏" aria-label="收起侧边栏">«</button></div>`;
|
|
2575
|
+
const nav = document.createElement("nav");
|
|
2576
|
+
nav.className = "rpml-gx-nav";
|
|
2577
|
+
side.appendChild(nav);
|
|
2578
|
+
const main = document.createElement("div");
|
|
2579
|
+
main.className = "rpml-gx-main";
|
|
2580
|
+
const fab = document.createElement("button");
|
|
2581
|
+
fab.className = "rpml-gx-fab";
|
|
2582
|
+
fab.type = "button";
|
|
2583
|
+
fab.title = "展开侧边栏";
|
|
2584
|
+
fab.setAttribute("aria-label", "展开侧边栏");
|
|
2585
|
+
fab.textContent = "☰";
|
|
2586
|
+
root.append(side, main, fab);
|
|
2587
|
+
host.innerHTML = "";
|
|
2588
|
+
host.appendChild(root);
|
|
2589
|
+
side.querySelector(".rpml-gx-toggle").addEventListener("click", () => root.classList.add("collapsed"));
|
|
2590
|
+
fab.addEventListener("click", () => root.classList.remove("collapsed"));
|
|
2591
|
+
const links = /* @__PURE__ */ new Map();
|
|
2592
|
+
function renderNav(node, depth) {
|
|
2593
|
+
const entries = [...node.children.values()];
|
|
2594
|
+
const leaves = entries.filter((e) => e.path).sort((a, b) => a.name.localeCompare(b.name));
|
|
2595
|
+
const folders = entries.filter((e) => !e.path).sort((a, b) => a.name.localeCompare(b.name));
|
|
2596
|
+
for (const leaf of leaves) {
|
|
2597
|
+
const a = document.createElement("a");
|
|
2598
|
+
a.className = depth > 0 ? "rpml-gx-item rpml-gx-indent" : "rpml-gx-item";
|
|
2599
|
+
a.textContent = leaf.title || leaf.name;
|
|
2600
|
+
a.href = `#${leaf.path}`;
|
|
2601
|
+
links.set(leaf.path, a);
|
|
2602
|
+
nav.appendChild(a);
|
|
2603
|
+
}
|
|
2604
|
+
for (const folder of folders) {
|
|
2605
|
+
const g = document.createElement("div");
|
|
2606
|
+
g.className = "rpml-gx-group";
|
|
2607
|
+
g.textContent = folder.name;
|
|
2608
|
+
nav.appendChild(g);
|
|
2609
|
+
renderNav(folder, depth + 1);
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
renderNav(tree, 0);
|
|
2613
|
+
function pickDefault() {
|
|
2614
|
+
const idx = docs.find((d) => basename(d.path).replace(/\.rpml$/i, "").toLowerCase() === "index");
|
|
2615
|
+
return (idx ?? docs[0]).path;
|
|
2616
|
+
}
|
|
2617
|
+
function show(path) {
|
|
2618
|
+
const doc = byPath.get(path);
|
|
2619
|
+
if (!doc) {
|
|
2620
|
+
main.innerHTML = `<div class="rpml-gx-err">未找到文档:${path}</div>`;
|
|
2621
|
+
return;
|
|
2622
|
+
}
|
|
2623
|
+
try {
|
|
2624
|
+
main.innerHTML = "";
|
|
2625
|
+
main.appendChild(parseToPage(doc.source));
|
|
2626
|
+
} catch (e) {
|
|
2627
|
+
main.innerHTML = `<div class="rpml-gx-err">RPML 解析错误:${e.message}</div>`;
|
|
2628
|
+
}
|
|
2629
|
+
links.forEach((a, p) => a.classList.toggle("active", p === path));
|
|
2630
|
+
}
|
|
2631
|
+
function route() {
|
|
2632
|
+
const path = decodeURIComponent(location.hash.slice(1)) || pickDefault();
|
|
2633
|
+
show(path);
|
|
2634
|
+
}
|
|
2635
|
+
nav.addEventListener("click", (e) => {
|
|
2636
|
+
const a = e.target.closest("a.rpml-gx-item");
|
|
2637
|
+
if (!a) return;
|
|
2638
|
+
e.preventDefault();
|
|
2639
|
+
const path = decodeURIComponent(a.hash.slice(1));
|
|
2640
|
+
history.pushState(null, "", a.hash);
|
|
2641
|
+
show(path);
|
|
2642
|
+
});
|
|
2643
|
+
window.addEventListener("popstate", route);
|
|
2644
|
+
route();
|
|
2645
|
+
}
|
|
2646
|
+
const inlined = globalThis.__RPML_DOCS__;
|
|
2647
|
+
if (inlined && Array.isArray(inlined) && inlined.length) {
|
|
2648
|
+
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", () => mountGallery(inlined));
|
|
2649
|
+
else mountGallery(inlined);
|
|
2650
|
+
}
|
|
2651
|
+
export {
|
|
2652
|
+
mountGallery
|
|
2653
|
+
};
|
|
2654
|
+
//# sourceMappingURL=gallery.js.map
|