@21stware/rpui 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/rpui.js CHANGED
@@ -82,9 +82,11 @@ rp-annotation rp-annotation, proto-annotation proto-annotation, rp-annotation pr
82
82
  .rp-annotation-marker { display:inline-grid; place-items:center; flex:0 0 auto; color:#fff; font-size:10px; font-weight:700; line-height:1; }
83
83
  .rp-annotation-marker.drop { width:22px; height:22px; background:var(--rp-primary); border-radius:50% 50% 50% 0; transform:rotate(-45deg); }
84
84
  .rp-annotation-marker.drop > span { transform:rotate(45deg); }
85
- .rp-annotation-marker.circle { width:13px; height:13px; background:var(--rp-purple); border-radius:50%; }
86
- .rp-annotation-marker.triangle { width:0; height:0; border-left:7px solid transparent; border-right:7px solid transparent; border-bottom:13px solid var(--rp-success); }
87
- .rp-annotation-body { display:block; width:fit-content; max-width:920px; }
85
+ .rp-annotation-marker.circle { width:16px; height:16px; background:var(--rp-purple); border-radius:50%; }
86
+ .rp-annotation-marker.triangle { width:18px; height:16px; background:var(--rp-success); clip-path:polygon(50% 0, 100% 100%, 0 100%); }
87
+ .rp-annotation-marker.triangle > span { transform:translateY(2px); font-size:9px; }
88
+ .rp-annotation-body { display:block; position:relative; width:fit-content; max-width:920px; }
89
+ .rp-pin-slice { width:18px; height:18px; font-size:10px; box-shadow:0 1px 5px rgba(37,99,235,.3); }
88
90
  .rp-annotation-body > :not(rp-annotation):not(proto-annotation):not(rp-enum):not(proto-enum) { max-width:820px; }
89
91
  .rp-annotation-pane rp-annotation, .rp-annotation-pane proto-annotation { max-width:none; }
90
92
  .rp-annotation-pane .rp-annotation-body { max-width:none; }
@@ -201,7 +203,7 @@ snap-card, rp-card { display:block; width:auto; min-width:220px; padding:14px; b
201
203
  .rp-card-image { display:grid; place-items:center; height:120px; margin:-14px -14px 12px; border-radius:10px 10px 0 0; background:#f3f4f6; color:#6b7280; }
202
204
  .rp-card-title { display:block; color:#111827; font-weight:750; }
203
205
  .rp-card-subtitle { display:block; margin-top:4px; color:#6b7280; font-size:13px; }
204
- .rp-card-footer { margin:12px -14px -14px; padding:10px 14px; border-top:1px solid var(--rp-border); background:#f9fafb; }
206
+ .rp-card-footer { display:block; margin:12px -14px -14px; padding:10px 14px; border-top:1px solid var(--rp-border); background:#f9fafb; }
205
207
  snap-stat-card, rp-stat-card { display:grid; gap:6px; width:auto; min-width:0; padding:16px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; }
206
208
  .rp-stat-label { color:#6b7280; font-size:12px; font-weight:650; }
207
209
  .rp-stat-value { color:#111827; font-size:26px; font-weight:800; }
@@ -218,8 +220,8 @@ snap-checkbox[state="checked"] .rp-box, rp-checkbox[state="checked"] .rp-box, sn
218
220
  snap-checkbox[state="disabled"], rp-checkbox[state="disabled"], snap-radio[state="disabled"], rp-radio[state="disabled"] { opacity:.5; }
219
221
  snap-radio .rp-box, rp-radio .rp-box { border-radius:999px; }
220
222
  snap-toggle, rp-toggle { display:inline-flex; align-items:center; gap:8px; font-size:13px; }
221
- .rp-toggle-track { width:34px; height:20px; border-radius:999px; background:#d1d5db; padding:2px; }
222
- .rp-toggle-dot { width:16px; height:16px; border-radius:999px; background:#fff; transition:none; }
223
+ .rp-toggle-track { display:flex; align-items:center; width:34px; height:20px; border-radius:999px; background:#d1d5db; padding:2px; }
224
+ .rp-toggle-dot { display:block; width:16px; height:16px; border-radius:999px; background:#fff; box-shadow:0 1px 2px rgba(0,0,0,.2); transition:none; }
223
225
  snap-toggle[state="on"] .rp-toggle-track, rp-toggle[state="on"] .rp-toggle-track { background:var(--rp-primary); }
224
226
  snap-toggle[state="on"] .rp-toggle-dot, rp-toggle[state="on"] .rp-toggle-dot { margin-left:14px; }
225
227
  snap-toggle[state="disabled"], rp-toggle[state="disabled"] { opacity:.5; }
@@ -250,6 +252,295 @@ snap-steps, rp-steps { display:flex; align-items:center; gap:8px; width:fit-cont
250
252
  .rp-step-sep { width:28px; height:1px; background:var(--rp-border); }
251
253
  snap-breadcrumb, rp-breadcrumb { display:inline-flex; align-items:center; gap:6px; color:#6b7280; font-size:13px; }
252
254
  .rp-breadcrumb-current { color:#111827; font-weight:650; }
255
+
256
+ /* --- data input --- */
257
+ snap-slider, rp-slider { display:inline-flex; align-items:center; gap:10px; width:220px; }
258
+ .rp-slider-track { position:relative; flex:1; height:4px; border-radius:999px; background:#e5e7eb; }
259
+ .rp-slider-fill { position:absolute; height:100%; border-radius:999px; background:var(--rp-primary); }
260
+ .rp-slider-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); box-shadow:0 1px 3px rgba(0,0,0,.2); }
261
+ .rp-slider-value { font-size:12px; color:#374151; min-width:24px; }
262
+ snap-range, rp-range { display:inline-flex; align-items:center; width:220px; }
263
+ snap-number-input, rp-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; }
264
+ .rp-num-value { flex:1; font-size:13px; }
265
+ .rp-num-steppers { display:flex; flex-direction:column; }
266
+ .rp-num-step { display:grid; place-items:center; width:20px; height:15px; color:#6b7280; cursor:pointer; }
267
+ snap-rating, rp-rating { display:inline-flex; gap:2px; color:#d1d5db; }
268
+ .rp-star.filled { color:#f59e0b; }
269
+ snap-pin-input, rp-pin-input { display:inline-flex; gap:8px; }
270
+ .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; }
271
+ .rp-pin-cell.active { border-color:var(--rp-primary); box-shadow:0 0 0 3px rgba(37,99,235,.12); }
272
+ snap-color-swatch, rp-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; }
273
+ .rp-swatch-chip { width:24px; height:24px; border-radius:6px; border:1px solid rgba(0,0,0,.1); }
274
+ .rp-swatch-hex { font-family:ui-monospace,Menlo,monospace; font-size:12px; color:#374151; }
275
+ snap-autocomplete, rp-autocomplete { display:inline-block; width:280px; }
276
+ .rp-ac-options { display:grid; gap:1px; 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); }
277
+ .rp-ac-option { padding:7px 8px; border-radius:6px; font-size:13px; color:#374151; }
278
+ .rp-ac-option:first-child { background:#eff6ff; color:#1d4ed8; }
279
+
280
+ /* --- data display additions --- */
281
+ snap-chip, rp-chip { 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; }
282
+ snap-tree, rp-tree { display:flex; flex-direction:column; gap:1px; width:fit-content; min-width:240px; }
283
+ .rp-tree-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); }
284
+ .rp-tree-row.selected { background:#eff6ff; color:#1d4ed8; font-weight:650; }
285
+ .rp-tree-spacer { display:inline-block; width:12px; }
286
+ .rp-tree-label { flex:1; }
287
+ snap-timeline, rp-timeline { display:flex; flex-direction:column; width:fit-content; min-width:260px; }
288
+ snap-timeline-item, rp-timeline-item { display:flex; gap:12px; padding-bottom:16px; position:relative; }
289
+ snap-timeline-item:not(:last-child)::before, rp-timeline-item:not(:last-child)::before { content:''; position:absolute; left:6px; top:16px; bottom:0; width:2px; background:var(--rp-border); }
290
+ .rp-timeline-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; }
291
+ .rp-timeline-dot.active { border-color:var(--rp-primary); background:var(--rp-primary); }
292
+ .rp-timeline-dot.done { border-color:var(--rp-success); background:var(--rp-success); }
293
+ .rp-timeline-dot.error { border-color:var(--rp-danger); background:var(--rp-danger); }
294
+ .rp-timeline-main { flex:1; }
295
+ .rp-timeline-head { display:flex; align-items:baseline; gap:8px; }
296
+ .rp-timeline-label { font-weight:650; color:#111827; font-size:13px; }
297
+ .rp-timeline-time { font-size:12px; color:#9ca3af; }
298
+ .rp-timeline-content { font-size:13px; color:#6b7280; margin-top:2px; }
299
+ snap-calendar, rp-calendar { display:inline-block; width:280px; padding:12px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; }
300
+ .rp-cal-head { text-align:center; font-weight:700; font-size:14px; margin-bottom:10px; }
301
+ .rp-cal-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:2px; }
302
+ .rp-cal-dow { display:grid; place-items:center; height:24px; font-size:11px; color:#9ca3af; }
303
+ .rp-cal-cell { display:grid; place-items:center; height:32px; border-radius:6px; font-size:13px; color:#374151; }
304
+ .rp-cal-cell.selected { background:var(--rp-primary); color:#fff; font-weight:700; }
305
+ .rp-cal-cell.muted { color:transparent; }
306
+ snap-kanban, rp-kanban { display:flex; gap:12px; width:fit-content; align-items:flex-start; }
307
+ snap-kanban-column, rp-kanban-column { display:flex; flex-direction:column; width:200px; padding:10px; border-radius:10px; background:#f3f4f6; }
308
+ .rp-kanban-head { display:flex; align-items:center; justify-content:space-between; font-weight:650; font-size:13px; margin-bottom:8px; color:#374151; }
309
+ .rp-kanban-count { display:grid; place-items:center; min-width:18px; height:18px; padding:0 5px; border-radius:999px; background:#e5e7eb; font-size:11px; }
310
+ .rp-kanban-body { display:flex; flex-direction:column; gap:8px; }
311
+ snap-kanban-card, rp-kanban-card { display:block; padding:10px; border-radius:8px; background:#fff; border:1px solid var(--rp-border); }
312
+ .rp-kanban-card-title { display:block; font-size:13px; color:#111827; }
313
+ .rp-kanban-card-tag { display:inline-block; margin-top:6px; padding:1px 7px; border-radius:999px; background:#eef2ff; color:#3730a3; font-size:11px; }
314
+ snap-code-block, rp-code-block { display:block; width:fit-content; min-width:320px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; background:#0f172a; }
315
+ .rp-code-head { padding:6px 12px; font-family:ui-monospace,Menlo,monospace; font-size:11px; color:#94a3b8; background:#1e293b; }
316
+ .rp-code-body { padding:10px 0; }
317
+ .rp-code-line { display:flex; align-items:center; gap:12px; padding:1px 12px; }
318
+ .rp-code-ln { width:20px; text-align:right; color:#475569; font-family:ui-monospace,Menlo,monospace; font-size:11px; }
319
+ .rp-code-bar { height:8px; border-radius:3px; background:#334155; }
320
+ snap-diff, rp-diff { 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; }
321
+ .rp-diff-line { display:flex; align-items:center; gap:10px; padding:2px 10px; }
322
+ .rp-diff-line.add { background:#dcfce7; }
323
+ .rp-diff-line.del { background:#fee2e2; }
324
+ .rp-diff-sign { width:10px; color:#6b7280; }
325
+ .rp-diff-line.add .rp-code-bar { background:#86efac; }
326
+ .rp-diff-line.del .rp-code-bar { background:#fca5a5; }
327
+ .rp-diff-line.ctx .rp-code-bar { background:#e5e7eb; }
328
+ snap-image-grid, rp-image-grid { display:grid; grid-template-columns:repeat(var(--grid-cols,3),1fr); gap:8px; width:fit-content; }
329
+ .rp-grid-cell { display:grid; place-items:center; width:80px; height:80px; border-radius:8px; background:#f3f4f6; color:#9ca3af; }
330
+ snap-key-value, rp-key-value { display:flex; flex-direction:column; width:fit-content; min-width:240px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
331
+ snap-kv-row, rp-kv-row { display:flex; border-bottom:1px solid var(--rp-border); }
332
+ snap-kv-row:last-child, rp-kv-row:last-child { border-bottom:0; }
333
+ .rp-kv-key { width:120px; padding:8px 12px; background:#f9fafb; color:#6b7280; font-size:13px; }
334
+ .rp-kv-val { flex:1; padding:8px 12px; color:#111827; font-size:13px; }
335
+ snap-accordion, rp-accordion { display:flex; flex-direction:column; width:fit-content; min-width:320px; border:1px solid var(--rp-border); border-radius:8px; overflow:hidden; }
336
+ snap-accordion-item, rp-accordion-item { display:block; border-bottom:1px solid var(--rp-border); }
337
+ snap-accordion-item:last-child, rp-accordion-item:last-child { border-bottom:0; }
338
+ .rp-accordion-head { display:flex; align-items:center; gap:8px; padding:11px 14px; font-weight:650; font-size:13px; color:#111827; }
339
+ .rp-accordion-body { padding:0 14px 14px 36px; font-size:13px; color:#6b7280; }
340
+ snap-banner, rp-banner { 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; }
341
+ snap-banner[type="success"], rp-banner[type="success"] { background:#f0fdf4; color:#166534; border-color:#bbf7d0; }
342
+ snap-banner[type="warning"], rp-banner[type="warning"] { background:#fffbeb; color:#92400e; border-color:#fde68a; }
343
+ snap-banner[type="error"], rp-banner[type="error"] { background:#fef2f2; color:#991b1b; border-color:#fecaca; }
344
+ .rp-banner-text { flex:1; }
345
+ snap-skeleton, rp-skeleton { display:flex; flex-direction:column; gap:8px; width:fit-content; min-width:240px; }
346
+ .rp-skel { border-radius:8px; background:linear-gradient(90deg,#f3f4f6,#e5e7eb,#f3f4f6); }
347
+ .rp-skel-block { height:120px; }
348
+ .rp-skel-avatar { width:40px; height:40px; border-radius:50%; }
349
+ .rp-skel-avatar.sm { width:28px; height:28px; }
350
+ .rp-skel-row { display:flex; align-items:center; gap:10px; }
351
+ snap-countdown, rp-countdown { 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; }
352
+ snap-result, rp-result { display:grid; justify-items:center; gap:8px; width:fit-content; min-width:280px; padding:32px; text-align:center; }
353
+ .rp-result-icon.success { color:var(--rp-success); }
354
+ .rp-result-icon.error { color:var(--rp-danger); }
355
+ .rp-result-icon.empty { color:#9ca3af; }
356
+ .rp-result-title { font-size:16px; font-weight:700; color:#111827; }
357
+ .rp-result-desc { font-size:13px; color:#6b7280; }
358
+ snap-permission-gate, rp-permission-gate { display:block; position:relative; width:fit-content; }
359
+ .rp-gate-content { opacity:.4; filter:grayscale(1); pointer-events:none; }
360
+ .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; }
361
+ snap-quota-bar, rp-quota-bar { display:block; width:fit-content; min-width:240px; }
362
+ .rp-quota-head { display:flex; justify-content:space-between; font-size:12px; color:#374151; margin-bottom:5px; }
363
+ .rp-quota-num.danger { color:var(--rp-danger); font-weight:700; }
364
+ .rp-quota-track { display:block; height:8px; border-radius:999px; background:#e5e7eb; overflow:hidden; }
365
+ .rp-quota-fill { display:block; height:100%; background:var(--rp-primary); }
366
+ .rp-quota-fill.danger { background:var(--rp-danger); }
367
+ snap-api-key, rp-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; }
368
+ .rp-apikey-val { font-family:ui-monospace,Menlo,monospace; font-size:12px; color:#374151; }
369
+ .rp-apikey-copy { display:grid; place-items:center; width:26px; height:26px; border-radius:6px; color:#6b7280; }
370
+ snap-audit-row, rp-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; }
371
+ .rp-audit-actor { font-weight:650; color:#111827; }
372
+ .rp-audit-action { flex:1; color:#6b7280; }
373
+ .rp-audit-time { color:#9ca3af; font-size:12px; }
374
+ snap-workflow-node, rp-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; }
375
+ .rp-wf-icon.done { color:var(--rp-success); }
376
+ .rp-wf-icon.active { color:var(--rp-primary); }
377
+ .rp-wf-icon.error { color:var(--rp-danger); }
378
+ .rp-wf-icon.default { color:#9ca3af; }
379
+
380
+ /* --- navigation & layout additions --- */
381
+ snap-segmented, rp-segmented { display:inline-flex; padding:2px; border-radius:8px; background:#f3f4f6; gap:2px; }
382
+ .rp-seg-item { padding:5px 14px; border-radius:6px; font-size:13px; color:#6b7280; }
383
+ .rp-seg-item.active { background:#fff; color:#111827; font-weight:650; box-shadow:0 1px 3px rgba(0,0,0,.08); }
384
+ snap-command-palette, rp-command-palette { display:block; width:520px; border:1px solid var(--rp-border); border-radius:12px; background:#fff; box-shadow:0 24px 48px rgba(15,23,42,.18); overflow:hidden; }
385
+ .rp-cmdk-input { display:flex; align-items:center; gap:10px; padding:14px 16px; border-bottom:1px solid var(--rp-border); }
386
+ .rp-cmdk-list { padding:6px; }
387
+ .rp-cmdk-item { display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:8px; font-size:13px; color:#374151; }
388
+ .rp-cmdk-item.active { background:#eff6ff; color:#1d4ed8; }
389
+ snap-context-menu, rp-context-menu, snap-menu, rp-menu { display:inline-flex; flex-direction:column; min-width:180px; padding:5px; border:1px solid var(--rp-border); border-radius:10px; background:#fff; box-shadow:0 12px 24px rgba(15,23,42,.12); }
390
+ .rp-menu-item, snap-menu-item, rp-menu-item { display:flex; align-items:center; gap:8px; padding:7px 10px; border-radius:6px; font-size:13px; color:#374151; }
391
+ .rp-menu-item.danger, snap-menu-item.danger, rp-menu-item.danger { color:var(--rp-danger); }
392
+ .rp-menu-item.disabled, snap-menu-item.disabled, rp-menu-item.disabled { opacity:.45; }
393
+ .rp-menu-label { flex:1; }
394
+ .rp-menu-shortcut { color:#9ca3af; font-size:12px; }
395
+ snap-toc, rp-toc { display:flex; flex-direction:column; gap:2px; width:fit-content; min-width:160px; border-left:2px solid var(--rp-border); }
396
+ .rp-toc-item { padding:4px 12px; font-size:13px; color:#6b7280; border-left:2px solid transparent; margin-left:-2px; }
397
+ .rp-toc-item.active { color:var(--rp-primary); border-left-color:var(--rp-primary); font-weight:650; }
398
+ snap-kbd, rp-kbd { display:inline-flex; align-items:center; gap:3px; }
399
+ .rp-kbd-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; }
400
+ .rp-kbd-plus { color:#9ca3af; font-size:11px; }
401
+ snap-split-pane, rp-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; }
402
+ snap-split-pane > *, rp-split-pane > * { padding:14px; }
403
+ snap-split-pane > *:not(:last-child), rp-split-pane > *:not(:last-child) { border-right:1px solid var(--rp-border); }
404
+ snap-divider, rp-divider { display:block; height:1px; background:var(--rp-border); margin:12px 0; }
405
+ snap-divider.rp-divider-v, rp-divider.rp-divider-v { display:inline-block; width:1px; height:auto; align-self:stretch; margin:0 12px; }
406
+ snap-spacer, rp-spacer { display:block; height:var(--snap-size,16px); }
407
+
408
+ /* --- iOS --- */
409
+ snap-ios-navbar, rp-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; }
410
+ .rp-ios-navbar-row { display:grid; grid-template-columns:1fr auto 1fr; align-items:center; min-height:36px; }
411
+ .rp-ios-nav-leading { display:flex; align-items:center; gap:2px; color:#007aff; font-size:15px; }
412
+ .rp-ios-nav-title { text-align:center; font-weight:600; font-size:16px; color:#000; }
413
+ .rp-ios-nav-trailing { text-align:right; color:#007aff; font-size:15px; }
414
+ .rp-ios-nav-large { font-size:30px; font-weight:700; color:#000; padding:2px 2px 6px; }
415
+ snap-ios-tabbar, rp-ios-tabbar { display:flex; background:rgba(249,249,249,.94); border-top:1px solid #d8d8dc; padding:6px 0 4px; }
416
+ .rp-ios-tab { flex:1; display:flex; flex-direction:column; align-items:center; gap:2px; color:#8e8e93; font-size:10px; }
417
+ .rp-ios-tab.active { color:#007aff; }
418
+ .rp-ios-tab-label { font-size:10px; }
419
+ snap-ios-list, rp-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; }
420
+ .rp-ios-list-header { padding:6px 16px; font-size:13px; color:#6d6d72; background:#f2f2f7; text-transform:none; }
421
+ snap-ios-list-item, rp-ios-list-item { display:flex; align-items:center; gap:10px; padding:11px 16px; border-bottom:1px solid #e5e5ea; font-size:15px; color:#000; }
422
+ snap-ios-list-item:last-child, rp-ios-list-item:last-child { border-bottom:0; }
423
+ .rp-ios-li-icon { display:grid; place-items:center; width:28px; height:28px; border-radius:6px; background:#007aff; color:#fff; }
424
+ .rp-ios-li-label { flex:1; }
425
+ .rp-ios-li-detail { color:#8e8e93; }
426
+ .rp-ios-li-chevron { color:#c7c7cc; }
427
+ snap-ios-action-sheet, rp-ios-action-sheet { display:flex; flex-direction:column; gap:8px; width:fit-content; min-width:320px; padding:8px; font-family:-apple-system,sans-serif; }
428
+ .rp-ios-as-group { border-radius:14px; overflow:hidden; background:rgba(255,255,255,.82); backdrop-filter:blur(20px); }
429
+ .rp-ios-as-title { padding:14px; text-align:center; font-size:13px; color:#8e8e93; border-bottom:1px solid #d1d1d6; }
430
+ .rp-ios-as-action { padding:16px; text-align:center; font-size:18px; color:#007aff; border-bottom:1px solid #d1d1d6; }
431
+ .rp-ios-as-action:last-child { border-bottom:0; }
432
+ .rp-ios-as-action.destructive { color:#ff3b30; }
433
+ .rp-ios-as-action.cancel { font-weight:600; }
434
+ snap-ios-alert, rp-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; }
435
+ .rp-ios-alert-body { padding:18px 16px 14px; text-align:center; }
436
+ .rp-ios-alert-title { font-size:17px; font-weight:600; color:#000; }
437
+ .rp-ios-alert-msg { margin-top:3px; font-size:13px; color:#000; }
438
+ .rp-ios-alert-actions { display:flex; border-top:1px solid #d1d1d6; }
439
+ .rp-ios-alert-btn { flex:1; padding:11px; text-align:center; font-size:17px; color:#007aff; }
440
+ .rp-ios-alert-btn.primary { font-weight:600; }
441
+ .rp-ios-alert-btn:not(:last-child) { border-right:1px solid #d1d1d6; }
442
+ snap-ios-switch, rp-ios-switch { display:inline-flex; align-items:center; gap:8px; font-family:-apple-system,sans-serif; font-size:15px; }
443
+ .rp-ios-switch-track { width:51px; height:31px; border-radius:999px; background:#34c759; padding:2px; }
444
+ .rp-ios-switch-dot { display:block; width:27px; height:27px; border-radius:50%; background:#fff; margin-left:20px; box-shadow:0 2px 4px rgba(0,0,0,.2); }
445
+ snap-ios-segmented, rp-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; }
446
+ .rp-ios-seg-item { padding:6px 16px; border-radius:7px; font-size:13px; color:#000; }
447
+ .rp-ios-seg-item.active { background:#fff; font-weight:600; box-shadow:0 1px 3px rgba(0,0,0,.12); }
448
+ snap-ios-button, rp-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; }
449
+ snap-ios-button[variant="tinted"], rp-ios-button[variant="tinted"] { background:rgba(0,122,255,.15); color:#007aff; }
450
+ snap-ios-button[variant="plain"], rp-ios-button[variant="plain"] { background:transparent; color:#007aff; }
451
+ snap-ios-search, rp-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; }
452
+ snap-ios-stepper, rp-ios-stepper { display:inline-flex; align-items:center; border-radius:8px; background:rgba(118,118,128,.12); }
453
+ .rp-ios-step { display:grid; place-items:center; width:46px; height:32px; color:#000; }
454
+ .rp-ios-step-div { width:1px; height:18px; background:rgba(0,0,0,.15); }
455
+
456
+ /* --- macOS --- */
457
+ snap-macos-window, rp-macos-window { display:block; width:fit-content; min-width:480px; border-radius:10px; overflow:hidden; border:1px solid #d1d1d6; background:#fff; box-shadow:0 20px 60px rgba(0,0,0,.25); font-family:-apple-system,sans-serif; }
458
+ .rp-mac-titlebar { display:flex; align-items:center; gap:10px; height:38px; padding:0 14px; background:#ececec; border-bottom:1px solid #d1d1d6; }
459
+ .rp-mac-lights { display:flex; gap:8px; }
460
+ .rp-mac-light { width:12px; height:12px; border-radius:50%; }
461
+ .rp-mac-light.close { background:#ff5f57; }
462
+ .rp-mac-light.min { background:#febc2e; }
463
+ .rp-mac-light.max { background:#28c840; }
464
+ .rp-mac-title { flex:1; text-align:center; font-size:13px; font-weight:600; color:#3c3c43; }
465
+ .rp-mac-window-body { padding:0; }
466
+ snap-macos-toolbar, rp-macos-toolbar { display:flex; align-items:center; gap:10px; padding:8px 14px; background:#f6f6f6; border-bottom:1px solid #d1d1d6; }
467
+ snap-macos-menubar, rp-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; }
468
+ .rp-mac-menubar-apple { color:#000; }
469
+ .rp-mac-menu-title { color:#000; }
470
+ .rp-mac-menu-title.active { background:#007aff; color:#fff; padding:1px 7px; border-radius:4px; }
471
+ snap-macos-sidebar, rp-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; }
472
+ snap-macos-source-item, rp-macos-source-item { display:flex; align-items:center; gap:7px; padding:5px 8px; border-radius:6px; font-size:13px; color:#3c3c43; }
473
+ snap-macos-source-item.selected, rp-macos-source-item.selected { background:#007aff; color:#fff; }
474
+ .rp-mac-source-group { padding:8px 8px 3px; font-size:11px; font-weight:700; color:#8e8e93; text-transform:uppercase; }
475
+ snap-macos-segmented, rp-macos-segmented { display:inline-flex; border:1px solid #c4c4c7; border-radius:6px; overflow:hidden; font-family:-apple-system,sans-serif; }
476
+ .rp-mac-seg-item { padding:4px 14px; font-size:13px; color:#000; background:#fff; border-right:1px solid #c4c4c7; }
477
+ .rp-mac-seg-item:last-child { border-right:0; }
478
+ .rp-mac-seg-item.active { background:#007aff; color:#fff; }
479
+ snap-macos-popover, rp-macos-popover { display:inline-block; position:relative; }
480
+ .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; }
481
+ .rp-mac-pop-body { min-width:220px; padding:12px; border-radius:10px; border:1px solid #d1d1d6; background:#fff; box-shadow:0 12px 40px rgba(0,0,0,.2); }
482
+ .rp-mac-pop-title { font-weight:600; font-size:13px; margin-bottom:8px; }
483
+ snap-macos-sheet, rp-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; }
484
+ .rp-mac-sheet-title { font-size:15px; font-weight:700; margin-bottom:12px; }
485
+ .rp-mac-sheet-actions { display:flex; justify-content:flex-end; gap:8px; margin-top:16px; }
486
+ snap-macos-stepper, rp-macos-stepper { display:inline-flex; flex-direction:column; border:1px solid #c4c4c7; border-radius:5px; overflow:hidden; }
487
+ .rp-mac-step { display:grid; place-items:center; width:22px; height:13px; background:#fff; color:#3c3c43; }
488
+ .rp-mac-step.up { border-bottom:1px solid #c4c4c7; }
489
+ snap-macos-disclosure, rp-macos-disclosure { display:block; font-family:-apple-system,sans-serif; }
490
+ .rp-mac-disc-head { display:flex; align-items:center; gap:5px; font-size:13px; font-weight:600; color:#000; }
491
+ .rp-mac-disc-tri { display:inline-flex; transition:none; }
492
+ .rp-mac-disc-tri.open { transform:rotate(90deg); }
493
+ .rp-mac-disc-body { padding:8px 0 0 18px; font-size:13px; color:#3c3c43; }
494
+ snap-macos-table, rp-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; }
495
+ .rp-mac-tr { display:flex; }
496
+ .rp-mac-tr.rp-mac-th { background:#f6f6f6; border-bottom:1px solid #d1d1d6; font-size:12px; font-weight:600; color:#3c3c43; }
497
+ .rp-mac-tr.alt { background:#f5f8ff; }
498
+ .rp-mac-td { flex:1; display:flex; align-items:center; gap:6px; padding:6px 12px; font-size:13px; color:#3c3c43; }
499
+ .rp-mac-cell-bar { height:8px; border-radius:3px; background:#e5e7eb; }
500
+
501
+ /* --- agent / conversational UI (Codex-style: single column, de-bubbled) --- */
502
+ snap-chat, rp-chat { display:flex; flex-direction:column; gap:24px; width:fit-content; min-width:520px; max-width:680px; }
503
+ snap-user-message, rp-user-message, snap-assistant-message, rp-assistant-message { display:block; }
504
+ .rp-msg-role { font-size:12px; font-weight:700; color:#9ca3af; letter-spacing:.02em; margin:0 0 6px; }
505
+ .rp-msg-content { display:flex; flex-direction:column; gap:12px; font-size:14px; line-height:1.7; color:#1f2937; }
506
+ snap-user-message .rp-msg-content, rp-user-message .rp-msg-content { color:#111827; }
507
+ snap-system-message, rp-system-message { display:flex; justify-content:center; }
508
+ .rp-sysmsg-line { padding:3px 12px; border-radius:999px; background:#f3f4f6; color:#6b7280; font-size:12px; }
509
+ snap-tool-call, rp-tool-call { display:block; width:fit-content; min-width:280px; max-width:600px; }
510
+ .rp-tool-head { display:flex; align-items:center; gap:8px; font-size:13px; color:#6b7280; }
511
+ .rp-tool-glyph { display:inline-flex; }
512
+ .rp-tool-glyph.done { color:var(--rp-success); }
513
+ .rp-tool-glyph.running { color:var(--rp-primary); }
514
+ .rp-tool-glyph.error { color:var(--rp-danger); }
515
+ .rp-tool-name { font-family:ui-monospace,Menlo,monospace; font-weight:650; color:#374151; }
516
+ .rp-tool-args-inline { font-family:ui-monospace,Menlo,monospace; color:#9ca3af; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
517
+ .rp-tool-body { margin-top:8px; padding-left:21px; }
518
+ snap-agent-output, rp-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; }
519
+ .rp-output-head { padding:6px 12px; font-size:12px; color:#6b7280; border-bottom:1px solid var(--rp-border); font-family:ui-monospace,Menlo,monospace; }
520
+ .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; }
521
+ snap-reasoning, rp-reasoning { display:block; width:fit-content; min-width:280px; max-width:600px; }
522
+ .rp-reason-head { display:flex; align-items:center; gap:6px; font-size:13px; color:#9ca3af; }
523
+ .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; }
524
+ snap-message-actions, rp-message-actions { display:inline-flex; gap:2px; }
525
+ .rp-msg-action { display:grid; place-items:center; width:28px; height:28px; border-radius:6px; color:#9ca3af; cursor:pointer; }
526
+ .rp-msg-action:hover { background:#f3f4f6; color:#374151; }
527
+ snap-suggestions, rp-suggestions { display:flex; flex-wrap:wrap; gap:8px; }
528
+ .rp-suggestion { padding:7px 13px; border:1px solid var(--rp-border); border-radius:8px; font-size:13px; color:#374151; background:#fff; cursor:pointer; }
529
+ .rp-suggestion:hover { border-color:var(--rp-border-strong); background:#f9fafb; }
530
+ snap-typing, rp-typing { display:flex; align-items:center; }
531
+ .rp-typing-dots { display:inline-flex; gap:4px; }
532
+ .rp-typing-dots > span { width:7px; height:7px; border-radius:50%; background:#c7c7cc; }
533
+ snap-composer, rp-composer { 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; }
534
+ .rp-composer-attach { display:inline-flex; color:#9ca3af; }
535
+ .rp-composer-input { flex:1; font-size:14px; }
536
+ .rp-composer-send { display:grid; place-items:center; width:32px; height:32px; border-radius:8px; background:#111827; color:#fff; }
537
+ .rp-composer-send.streaming { background:var(--rp-danger); }
538
+ snap-citation, rp-citation { 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; }
539
+ .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; }
540
+ .rp-cite-title { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
541
+ snap-token-usage, rp-token-usage { display:inline-flex; align-items:center; gap:7px; font-size:12px; color:#9ca3af; }
542
+ .rp-token-track { width:90px; height:5px; border-radius:999px; background:#e5e7eb; overflow:hidden; }
543
+ .rp-token-fill { display:block; height:100%; background:#9ca3af; }
253
544
  `;
254
545
  function injectStyle() {
255
546
  if (document.getElementById(RPUI_STYLE_ID)) return;
@@ -259,10 +550,18 @@ function injectStyle() {
259
550
  document.head.appendChild(el);
260
551
  }
261
552
  class RpAnnotation extends HTMLElement {
553
+ constructor() {
554
+ super(...arguments);
555
+ __publicField(this, "ro");
556
+ __publicField(this, "frame", 0);
557
+ }
262
558
  connectedCallback() {
263
559
  var _a;
264
560
  injectStyle();
265
- if (this.dataset.rpReady) return;
561
+ if (this.dataset.rpReady) {
562
+ this.setupSlicePins();
563
+ return;
564
+ }
266
565
  this.dataset.rpReady = "true";
267
566
  const existing = Array.from(this.childNodes);
268
567
  const depth = this.annotationDepth();
@@ -283,7 +582,8 @@ class RpAnnotation extends HTMLElement {
283
582
  const marker = document.createElement("span");
284
583
  const kind = id ? "drop" : depth <= 1 ? "circle" : "triangle";
285
584
  marker.className = `rp-annotation-marker ${kind}`;
286
- marker.innerHTML = kind === "drop" ? `<span>${escapeHtml(id)}</span>` : "";
585
+ const localIndex = id || sectionPath.split("-").pop() || "";
586
+ marker.innerHTML = `<span>${escapeHtml(localIndex)}</span>`;
287
587
  const head = document.createElement("div");
288
588
  head.className = "rp-annotation-head";
289
589
  head.append(marker);
@@ -301,6 +601,47 @@ class RpAnnotation extends HTMLElement {
301
601
  body.className = "rp-annotation-body";
302
602
  existing.forEach((n) => body.appendChild(n));
303
603
  this.append(head, body);
604
+ this.setupSlicePins();
605
+ }
606
+ disconnectedCallback() {
607
+ var _a;
608
+ (_a = this.ro) == null ? void 0 : _a.disconnect();
609
+ if (this.frame) cancelAnimationFrame(this.frame);
610
+ }
611
+ // A UI slice inside this annotation may carry data-pin markers on sub-regions.
612
+ // Render pins on those slices so their numbers connect to the deeper annotations
613
+ // that explain them — mirroring how rp-main-view pins top-level regions.
614
+ setupSlicePins() {
615
+ var _a;
616
+ const body = this.querySelector(":scope > .rp-annotation-body");
617
+ if (!body || !body.querySelector("[data-pin]")) return;
618
+ (_a = this.ro) == null ? void 0 : _a.disconnect();
619
+ this.scheduleSlicePins(body);
620
+ this.ro = new ResizeObserver(() => this.scheduleSlicePins(body));
621
+ this.ro.observe(this);
622
+ }
623
+ scheduleSlicePins(body) {
624
+ if (this.frame) return;
625
+ this.frame = requestAnimationFrame(() => {
626
+ this.frame = 0;
627
+ this.renderSlicePins(body);
628
+ });
629
+ }
630
+ renderSlicePins(body) {
631
+ body.querySelectorAll(":scope > .rp-pin").forEach((p) => p.remove());
632
+ const bodyRect = body.getBoundingClientRect();
633
+ body.querySelectorAll("[data-pin]").forEach((target) => {
634
+ if (target.closest("rp-annotation, proto-annotation") !== this) return;
635
+ const pinId = target.dataset.pin;
636
+ if (!pinId) return;
637
+ const r = target.getBoundingClientRect();
638
+ const pin = document.createElement("span");
639
+ pin.className = "rp-pin rp-pin-slice";
640
+ pin.style.left = `${r.left - bodyRect.left}px`;
641
+ pin.style.top = `${r.top - bodyRect.top}px`;
642
+ pin.innerHTML = `<span>${escapeHtml(pinId)}</span>`;
643
+ body.appendChild(pin);
644
+ });
304
645
  }
305
646
  annotationDepth() {
306
647
  let d = 0;
@@ -542,6 +883,24 @@ class LogoElement extends HTMLElement {
542
883
  if (!this.innerHTML.trim()) this.textContent = attr(this, "label", "LOGO");
543
884
  }
544
885
  }
886
+ class SplitPaneElement extends HTMLElement {
887
+ connectedCallback() {
888
+ injectStyle();
889
+ this.style.setProperty("--snap-columns", attr(this, "columns", "1fr 1fr"));
890
+ }
891
+ }
892
+ class DividerElement extends HTMLElement {
893
+ connectedCallback() {
894
+ injectStyle();
895
+ if (this.hasAttribute("vertical")) this.classList.add("rp-divider-v");
896
+ }
897
+ }
898
+ class SpacerElement extends HTMLElement {
899
+ connectedCallback() {
900
+ injectStyle();
901
+ if (this.hasAttribute("size")) this.style.setProperty("--snap-size", `${attr(this, "size", "16")}px`);
902
+ }
903
+ }
545
904
  const iconPaths = {
546
905
  search: '<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>',
547
906
  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"/>',
@@ -572,7 +931,39 @@ const iconPaths = {
572
931
  "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"/>',
573
932
  info: '<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>',
574
933
  "circle-check": '<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>',
575
- circle: '<circle cx="12" cy="12" r="10"/>'
934
+ circle: '<circle cx="12" cy="12" r="10"/>',
935
+ "chevron-up": '<path d="m18 15-6-6-6 6"/>',
936
+ 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"/>',
937
+ 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"/>',
938
+ lock: '<rect width="18" height="11" x="3" y="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>',
939
+ "circle-x": '<circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',
940
+ "more-horizontal": '<circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/>',
941
+ "more-vertical": '<circle cx="12" cy="12" r="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/>',
942
+ 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"/>',
943
+ 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"/>',
944
+ "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"/>',
945
+ "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"/>',
946
+ clock: '<circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/>',
947
+ 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"/>',
948
+ 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"/>',
949
+ 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"/>',
950
+ 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"/>',
951
+ bookmark: '<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>',
952
+ 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"/>',
953
+ 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"/>',
954
+ 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"/>',
955
+ filter: '<polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/>',
956
+ 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"/>',
957
+ 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"/>',
958
+ 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"/>',
959
+ 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"/>',
960
+ terminal: '<polyline points="4 17 10 11 4 5"/><line x1="12" x2="20" y1="19" y2="19"/>',
961
+ "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"/>',
962
+ "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"/>',
963
+ send: '<path d="M14.5 9.5 21 3l-6.5 18-2.5-7-7-2.5z"/>',
964
+ stop: '<rect width="14" height="14" x="5" y="5" rx="2"/>',
965
+ 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"/>',
966
+ 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"/>'
576
967
  };
577
968
  function icon(name, size = 16) {
578
969
  const key = name || "file";
@@ -709,6 +1100,83 @@ class ProgressElement extends HTMLElement {
709
1100
  this.innerHTML = kind === "circle" ? `${escapeHtml(value)}%` : '<span class="rp-progress-bar"></span>';
710
1101
  }
711
1102
  }
1103
+ class SliderElement extends HTMLElement {
1104
+ connectedCallback() {
1105
+ injectStyle();
1106
+ if (this.dataset.rpReady) return;
1107
+ this.dataset.rpReady = "true";
1108
+ const min = intAttr(this, "min", 0);
1109
+ const max = intAttr(this, "max", 100);
1110
+ const value = intAttr(this, "value", 40);
1111
+ const pct = max > min ? Math.max(0, Math.min(100, (value - min) / (max - min) * 100)) : 0;
1112
+ const label = attr(this, "label");
1113
+ this.innerHTML = `${label ? `<span class="rp-field-label">${escapeHtml(label)}</span>` : ""}<span class="rp-slider-track"><span class="rp-slider-fill" style="width:${pct}%"></span><span class="rp-slider-thumb" style="left:${pct}%"></span></span>${this.hasAttribute("show-value") ? `<span class="rp-slider-value">${value}</span>` : ""}`;
1114
+ }
1115
+ }
1116
+ class RangeElement extends HTMLElement {
1117
+ connectedCallback() {
1118
+ injectStyle();
1119
+ if (this.dataset.rpReady) return;
1120
+ this.dataset.rpReady = "true";
1121
+ const min = intAttr(this, "min", 0);
1122
+ const max = intAttr(this, "max", 100);
1123
+ const low = intAttr(this, "low", 25);
1124
+ const high = intAttr(this, "high", 75);
1125
+ const span = max - min || 1;
1126
+ const l = (low - min) / span * 100;
1127
+ const h = (high - min) / span * 100;
1128
+ this.innerHTML = `<span class="rp-slider-track"><span class="rp-slider-fill" style="left:${l}%;width:${h - l}%"></span><span class="rp-slider-thumb" style="left:${l}%"></span><span class="rp-slider-thumb" style="left:${h}%"></span></span>`;
1129
+ }
1130
+ }
1131
+ class NumberInputElement extends HTMLElement {
1132
+ connectedCallback() {
1133
+ injectStyle();
1134
+ if (this.dataset.rpReady) return;
1135
+ this.dataset.rpReady = "true";
1136
+ const value = attr(this, "value", "0");
1137
+ 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>`;
1138
+ }
1139
+ }
1140
+ class RatingElement extends HTMLElement {
1141
+ connectedCallback() {
1142
+ injectStyle();
1143
+ if (this.dataset.rpReady) return;
1144
+ this.dataset.rpReady = "true";
1145
+ const max = intAttr(this, "max", 5);
1146
+ const value = intAttr(this, "value", 3);
1147
+ this.innerHTML = Array.from({ length: max }, (_, i) => `<span class="rp-star${i < value ? " filled" : ""}">${icon("star", 16)}</span>`).join("");
1148
+ }
1149
+ }
1150
+ class PinInputElement extends HTMLElement {
1151
+ connectedCallback() {
1152
+ injectStyle();
1153
+ if (this.dataset.rpReady) return;
1154
+ this.dataset.rpReady = "true";
1155
+ const len = intAttr(this, "length", 4);
1156
+ const value = attr(this, "value", "");
1157
+ const chars = value.split("");
1158
+ this.innerHTML = Array.from({ length: len }, (_, i) => `<span class="rp-pin-cell${i === chars.length ? " active" : ""}">${escapeHtml(chars[i] || "")}</span>`).join("");
1159
+ }
1160
+ }
1161
+ class ColorSwatchElement extends HTMLElement {
1162
+ connectedCallback() {
1163
+ injectStyle();
1164
+ if (this.dataset.rpReady) return;
1165
+ this.dataset.rpReady = "true";
1166
+ const value = attr(this, "value", "#2563eb");
1167
+ this.innerHTML = `<span class="rp-swatch-chip" style="background:${escapeHtml(value)}"></span><span class="rp-swatch-hex">${escapeHtml(attr(this, "label", value))}</span>`;
1168
+ }
1169
+ }
1170
+ class AutocompleteElement extends HTMLElement {
1171
+ connectedCallback() {
1172
+ injectStyle();
1173
+ if (this.dataset.rpReady) return;
1174
+ this.dataset.rpReady = "true";
1175
+ const value = attr(this, "value");
1176
+ const options = csv(this, "options", "选项一,选项二,选项三");
1177
+ 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>` : ""}`;
1178
+ }
1179
+ }
712
1180
  class BadgeElement extends HTMLElement {
713
1181
  connectedCallback() {
714
1182
  injectStyle();
@@ -806,6 +1274,73 @@ class BreadcrumbElement extends HTMLElement {
806
1274
  this.innerHTML = items.map((item, i) => `<span class="${i === items.length - 1 ? "rp-breadcrumb-current" : ""}">${escapeHtml(item)}</span>${i < items.length - 1 ? "<span>/</span>" : ""}`).join("");
807
1275
  }
808
1276
  }
1277
+ class SegmentedElement extends HTMLElement {
1278
+ connectedCallback() {
1279
+ injectStyle();
1280
+ if (this.dataset.rpReady) return;
1281
+ this.dataset.rpReady = "true";
1282
+ const options = csv(this, "options", "日,周,月");
1283
+ const active = attr(this, "active", "0");
1284
+ const idx = Number(active);
1285
+ this.innerHTML = options.map((o, i) => `<span class="rp-seg-item${(Number.isFinite(idx) ? i === idx : o === active) ? " active" : ""}">${escapeHtml(o)}</span>`).join("");
1286
+ }
1287
+ }
1288
+ class CommandPaletteElement extends HTMLElement {
1289
+ connectedCallback() {
1290
+ injectStyle();
1291
+ if (this.dataset.rpReady) return;
1292
+ this.dataset.rpReady = "true";
1293
+ const query = attr(this, "query");
1294
+ const results = csv(this, "results", "新建文件,打开设置,搜索工单,切换主题");
1295
+ 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>`;
1296
+ }
1297
+ }
1298
+ class ContextMenuElement extends HTMLElement {
1299
+ connectedCallback() {
1300
+ injectStyle();
1301
+ if (this.dataset.rpReady || this.children.length) return;
1302
+ this.dataset.rpReady = "true";
1303
+ const items = csv(this, "items", "复制,重命名,移动到,删除");
1304
+ this.innerHTML = items.map((it) => `<div class="rp-menu-item${it === "删除" ? " danger" : ""}"><span>${escapeHtml(it)}</span></div>`).join("");
1305
+ }
1306
+ }
1307
+ class MenuElement extends HTMLElement {
1308
+ connectedCallback() {
1309
+ injectStyle();
1310
+ }
1311
+ }
1312
+ class MenuItemElement extends HTMLElement {
1313
+ connectedCallback() {
1314
+ var _a;
1315
+ injectStyle();
1316
+ if (this.dataset.rpReady) return;
1317
+ this.dataset.rpReady = "true";
1318
+ const label = attr(this, "label", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "菜单项");
1319
+ const ic = attr(this, "icon");
1320
+ const shortcut = attr(this, "shortcut");
1321
+ const disabled = attr(this, "state") === "disabled";
1322
+ this.innerHTML = `${ic ? icon(ic, 14) : ""}<span class="rp-menu-label">${escapeHtml(label)}</span>${shortcut ? `<span class="rp-menu-shortcut">${escapeHtml(shortcut)}</span>` : ""}`;
1323
+ if (disabled) this.classList.add("disabled");
1324
+ }
1325
+ }
1326
+ class TocElement extends HTMLElement {
1327
+ connectedCallback() {
1328
+ injectStyle();
1329
+ if (this.dataset.rpReady || this.children.length) return;
1330
+ this.dataset.rpReady = "true";
1331
+ const items = csv(this, "items", "概述,安装,用法,API,常见问题");
1332
+ this.innerHTML = items.map((it, i) => `<span class="rp-toc-item${i === 0 ? " active" : ""}">${escapeHtml(it)}</span>`).join("");
1333
+ }
1334
+ }
1335
+ class KbdElement extends HTMLElement {
1336
+ connectedCallback() {
1337
+ injectStyle();
1338
+ if (this.dataset.rpReady) return;
1339
+ this.dataset.rpReady = "true";
1340
+ const keys = csv(this, "keys", "⌘,K");
1341
+ this.innerHTML = keys.map((k) => `<kbd class="rp-kbd-key">${escapeHtml(k)}</kbd>`).join('<span class="rp-kbd-plus">+</span>');
1342
+ }
1343
+ }
809
1344
  function sampleCell(c, j, i) {
810
1345
  const lower = c.toLowerCase();
811
1346
  if (c.includes("发件") || lower.includes("name")) return ["张三", "李四", "系统通知", "运营助手", "王五", "安全团队"][i % 6];
@@ -958,6 +1493,691 @@ class TagElement extends HTMLElement {
958
1493
  this.innerHTML = `<span>${escapeHtml(label)}</span>${this.hasAttribute("closable") ? icon("x", 12) : ""}`;
959
1494
  }
960
1495
  }
1496
+ class ChipElement 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()) || "Chip");
1503
+ const ic = attr(this, "icon");
1504
+ this.innerHTML = `${ic ? icon(ic, 12) : ""}<span>${escapeHtml(label)}</span>${this.hasAttribute("closable") ? icon("x", 11) : ""}`;
1505
+ }
1506
+ }
1507
+ class TreeElement extends HTMLElement {
1508
+ connectedCallback() {
1509
+ injectStyle();
1510
+ }
1511
+ }
1512
+ class TreeItemElement extends HTMLElement {
1513
+ connectedCallback() {
1514
+ injectStyle();
1515
+ if (this.dataset.rpReady) return;
1516
+ this.dataset.rpReady = "true";
1517
+ const level = intAttr(this, "level", 0);
1518
+ const label = attr(this, "label", "Node");
1519
+ const ic = attr(this, "icon");
1520
+ const expandable = this.hasAttribute("expanded") || this.hasAttribute("collapsed");
1521
+ const expanded = this.hasAttribute("expanded");
1522
+ const caret = expandable ? icon(expanded ? "chevron-down" : "chevron-right", 12) : '<span class="rp-tree-spacer"></span>';
1523
+ this.style.setProperty("--tree-level", String(level));
1524
+ this.innerHTML = `<span class="rp-tree-row${attr(this, "state") === "selected" ? " selected" : ""}">${caret}${icon(ic || (expandable ? "folder" : "file"), 14)}<span class="rp-tree-label">${escapeHtml(label)}</span></span>`;
1525
+ }
1526
+ }
1527
+ class TimelineElement extends HTMLElement {
1528
+ connectedCallback() {
1529
+ injectStyle();
1530
+ }
1531
+ }
1532
+ class TimelineItemElement extends HTMLElement {
1533
+ connectedCallback() {
1534
+ injectStyle();
1535
+ if (this.dataset.rpReady) return;
1536
+ this.dataset.rpReady = "true";
1537
+ const children = Array.from(this.childNodes);
1538
+ const label = attr(this, "label");
1539
+ const time = attr(this, "time");
1540
+ const state = attr(this, "state", "default");
1541
+ const dot = `<span class="rp-timeline-dot ${state}"></span>`;
1542
+ const head = `<div class="rp-timeline-head"><span class="rp-timeline-label">${escapeHtml(label)}</span>${time ? `<span class="rp-timeline-time">${escapeHtml(time)}</span>` : ""}</div>`;
1543
+ const body = document.createElement("div");
1544
+ body.className = "rp-timeline-content";
1545
+ children.forEach((n) => body.appendChild(n));
1546
+ this.innerHTML = `${dot}<div class="rp-timeline-main">${head}</div>`;
1547
+ this.querySelector(".rp-timeline-main").appendChild(body);
1548
+ }
1549
+ }
1550
+ class CalendarElement extends HTMLElement {
1551
+ connectedCallback() {
1552
+ injectStyle();
1553
+ if (this.dataset.rpReady) return;
1554
+ this.dataset.rpReady = "true";
1555
+ const month = attr(this, "month", "2026 年 6 月");
1556
+ const selected = intAttr(this, "selected", 15);
1557
+ const dows = ["一", "二", "三", "四", "五", "六", "日"];
1558
+ const cells = Array.from({ length: 35 }, (_, i) => {
1559
+ const day = i - 1;
1560
+ const valid = day >= 1 && day <= 30;
1561
+ return `<span class="rp-cal-cell${valid && day === selected ? " selected" : ""}${valid ? "" : " muted"}">${valid ? day : ""}</span>`;
1562
+ }).join("");
1563
+ 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>`;
1564
+ }
1565
+ }
1566
+ class KanbanElement extends HTMLElement {
1567
+ connectedCallback() {
1568
+ injectStyle();
1569
+ }
1570
+ }
1571
+ class KanbanColumnElement extends HTMLElement {
1572
+ connectedCallback() {
1573
+ injectStyle();
1574
+ if (this.dataset.rpReady) return;
1575
+ this.dataset.rpReady = "true";
1576
+ const children = Array.from(this.childNodes);
1577
+ const title = attr(this, "title", "列");
1578
+ const count = attr(this, "count");
1579
+ const head = document.createElement("div");
1580
+ head.className = "rp-kanban-head";
1581
+ head.innerHTML = `<span>${escapeHtml(title)}</span>${count ? `<span class="rp-kanban-count">${escapeHtml(count)}</span>` : ""}`;
1582
+ const body = document.createElement("div");
1583
+ body.className = "rp-kanban-body";
1584
+ children.forEach((n) => body.appendChild(n));
1585
+ this.append(head, body);
1586
+ }
1587
+ }
1588
+ class KanbanCardElement extends HTMLElement {
1589
+ connectedCallback() {
1590
+ injectStyle();
1591
+ if (this.dataset.rpReady) return;
1592
+ this.dataset.rpReady = "true";
1593
+ const label = attr(this, "label", "卡片");
1594
+ const tag = attr(this, "tag");
1595
+ this.innerHTML = `<span class="rp-kanban-card-title">${escapeHtml(label)}</span>${tag ? `<span class="rp-kanban-card-tag">${escapeHtml(tag)}</span>` : ""}`;
1596
+ }
1597
+ }
1598
+ class CodeBlockElement extends HTMLElement {
1599
+ connectedCallback() {
1600
+ injectStyle();
1601
+ if (this.dataset.rpReady) return;
1602
+ this.dataset.rpReady = "true";
1603
+ const lines = intAttr(this, "lines", 5);
1604
+ const lang = attr(this, "lang", "ts");
1605
+ 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("");
1606
+ this.innerHTML = `<div class="rp-code-head">${escapeHtml(lang)}</div><div class="rp-code-body">${body}</div>`;
1607
+ }
1608
+ }
1609
+ class DiffElement extends HTMLElement {
1610
+ connectedCallback() {
1611
+ injectStyle();
1612
+ if (this.dataset.rpReady) return;
1613
+ this.dataset.rpReady = "true";
1614
+ const rows = intAttr(this, "rows", 4);
1615
+ const body = Array.from({ length: rows }, (_, i) => {
1616
+ const kind = i % 3 === 0 ? "add" : i % 3 === 1 ? "del" : "ctx";
1617
+ const sign = kind === "add" ? "+" : kind === "del" ? "-" : " ";
1618
+ return `<span class="rp-diff-line ${kind}"><span class="rp-diff-sign">${sign}</span><span class="rp-code-bar" style="width:${45 + i * 29 % 45}%"></span></span>`;
1619
+ }).join("");
1620
+ this.innerHTML = body;
1621
+ }
1622
+ }
1623
+ class ImageGridElement extends HTMLElement {
1624
+ connectedCallback() {
1625
+ injectStyle();
1626
+ if (this.dataset.rpReady) return;
1627
+ this.dataset.rpReady = "true";
1628
+ const count = intAttr(this, "count", 6);
1629
+ const cols = intAttr(this, "columns", 3);
1630
+ this.style.setProperty("--grid-cols", String(cols));
1631
+ this.innerHTML = Array.from({ length: count }, () => `<span class="rp-grid-cell">${icon("image", 20)}</span>`).join("");
1632
+ }
1633
+ }
1634
+ class KeyValueElement extends HTMLElement {
1635
+ connectedCallback() {
1636
+ injectStyle();
1637
+ }
1638
+ }
1639
+ class KvRowElement extends HTMLElement {
1640
+ connectedCallback() {
1641
+ injectStyle();
1642
+ if (this.dataset.rpReady) return;
1643
+ this.dataset.rpReady = "true";
1644
+ this.innerHTML = `<span class="rp-kv-key">${escapeHtml(attr(this, "label", "键"))}</span><span class="rp-kv-val">${escapeHtml(attr(this, "value", "值"))}</span>`;
1645
+ }
1646
+ }
1647
+ class AccordionElement extends HTMLElement {
1648
+ connectedCallback() {
1649
+ injectStyle();
1650
+ }
1651
+ }
1652
+ class AccordionItemElement extends HTMLElement {
1653
+ connectedCallback() {
1654
+ injectStyle();
1655
+ if (this.dataset.rpReady) return;
1656
+ this.dataset.rpReady = "true";
1657
+ const children = Array.from(this.childNodes);
1658
+ const label = attr(this, "label", "分节");
1659
+ const expanded = this.hasAttribute("expanded");
1660
+ const head = document.createElement("div");
1661
+ head.className = "rp-accordion-head";
1662
+ head.innerHTML = `${icon(expanded ? "chevron-down" : "chevron-right", 14)}<span>${escapeHtml(label)}</span>`;
1663
+ this.appendChild(head);
1664
+ if (expanded) {
1665
+ const body = document.createElement("div");
1666
+ body.className = "rp-accordion-body";
1667
+ children.forEach((n) => body.appendChild(n));
1668
+ this.appendChild(body);
1669
+ }
1670
+ }
1671
+ }
1672
+ class BannerElement extends HTMLElement {
1673
+ connectedCallback() {
1674
+ injectStyle();
1675
+ if (this.dataset.rpReady) return;
1676
+ this.dataset.rpReady = "true";
1677
+ const type = attr(this, "type", "info");
1678
+ const ic = type === "error" ? "circle-alert" : type === "warning" ? "alert-triangle" : type === "success" ? "circle-check" : "info";
1679
+ this.innerHTML = `${icon(ic)}<span class="rp-banner-text"><strong>${escapeHtml(attr(this, "title", "通知"))}</strong>${attr(this, "message") ? ` ${escapeHtml(attr(this, "message"))}` : ""}</span>${this.hasAttribute("has-action") ? '<snap-button label="查看" variant="link"></snap-button>' : ""}${this.hasAttribute("closable") ? icon("x", 14) : ""}`;
1680
+ }
1681
+ }
1682
+ class SkeletonElement extends HTMLElement {
1683
+ connectedCallback() {
1684
+ injectStyle();
1685
+ if (this.dataset.rpReady) return;
1686
+ this.dataset.rpReady = "true";
1687
+ const shape = attr(this, "shape", "line");
1688
+ if (shape === "avatar") this.innerHTML = '<span class="rp-skel rp-skel-avatar"></span>';
1689
+ else if (shape === "card") this.innerHTML = '<span class="rp-skel rp-skel-block"></span><span class="rp-skeleton-line" style="width:70%"></span><span class="rp-skeleton-line" style="width:50%"></span>';
1690
+ 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="rp-skeleton-line" style="width:60%"></span></span>').join("");
1691
+ else this.innerHTML = '<span class="rp-skeleton-line"></span>';
1692
+ }
1693
+ }
1694
+ class CountdownElement extends HTMLElement {
1695
+ connectedCallback() {
1696
+ injectStyle();
1697
+ if (this.dataset.rpReady) return;
1698
+ this.dataset.rpReady = "true";
1699
+ this.innerHTML = `${icon("clock", 13)}<span>${escapeHtml(attr(this, "value", "02:45:18"))}</span>`;
1700
+ }
1701
+ }
1702
+ class ResultElement extends HTMLElement {
1703
+ connectedCallback() {
1704
+ injectStyle();
1705
+ if (this.dataset.rpReady) return;
1706
+ this.dataset.rpReady = "true";
1707
+ const status = attr(this, "status", "success");
1708
+ const ic = status === "error" ? "circle-x" : status === "empty" ? "empty" : "circle-check";
1709
+ this.innerHTML = `<span class="rp-result-icon ${status}">${icon(ic, 40)}</span><span class="rp-result-title">${escapeHtml(attr(this, "title", "操作成功"))}</span><span class="rp-result-desc">${escapeHtml(attr(this, "description", ""))}</span>${this.hasAttribute("has-action") ? '<snap-button label="返回" variant="primary"></snap-button>' : ""}`;
1710
+ }
1711
+ }
1712
+ class PermissionGateElement extends HTMLElement {
1713
+ connectedCallback() {
1714
+ injectStyle();
1715
+ if (this.dataset.rpReady) return;
1716
+ this.dataset.rpReady = "true";
1717
+ const children = Array.from(this.childNodes);
1718
+ const wrap = document.createElement("div");
1719
+ wrap.className = "rp-gate-content";
1720
+ children.forEach((n) => wrap.appendChild(n));
1721
+ const overlay = document.createElement("div");
1722
+ overlay.className = "rp-gate-overlay";
1723
+ overlay.innerHTML = `${icon("lock", 16)}<span>${escapeHtml(attr(this, "reason", "无权限"))}</span>`;
1724
+ this.append(wrap, overlay);
1725
+ }
1726
+ }
1727
+ class QuotaBarElement extends HTMLElement {
1728
+ connectedCallback() {
1729
+ injectStyle();
1730
+ if (this.dataset.rpReady) return;
1731
+ this.dataset.rpReady = "true";
1732
+ const used = intAttr(this, "used", 70);
1733
+ const limit = intAttr(this, "limit", 100);
1734
+ const pct = limit ? Math.min(100, used / limit * 100) : 0;
1735
+ const danger = pct >= 90;
1736
+ 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>`;
1737
+ }
1738
+ }
1739
+ class ApiKeyElement extends HTMLElement {
1740
+ connectedCallback() {
1741
+ injectStyle();
1742
+ if (this.dataset.rpReady) return;
1743
+ this.dataset.rpReady = "true";
1744
+ const value = attr(this, "value", "sk_live_••••••••••••3f9a");
1745
+ this.innerHTML = `<span class="rp-apikey-val">${escapeHtml(value)}</span><span class="rp-apikey-copy">${icon("copy", 14)}</span>`;
1746
+ }
1747
+ }
1748
+ class AuditRowElement extends HTMLElement {
1749
+ connectedCallback() {
1750
+ injectStyle();
1751
+ if (this.dataset.rpReady) return;
1752
+ this.dataset.rpReady = "true";
1753
+ 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>`;
1754
+ }
1755
+ }
1756
+ class WorkflowNodeElement extends HTMLElement {
1757
+ connectedCallback() {
1758
+ injectStyle();
1759
+ if (this.dataset.rpReady) return;
1760
+ this.dataset.rpReady = "true";
1761
+ const state = attr(this, "state", "default");
1762
+ const ic = state === "done" ? "circle-check" : state === "active" ? "circle" : state === "error" ? "circle-x" : "circle";
1763
+ this.innerHTML = `<span class="rp-wf-icon ${state}">${icon(ic, 16)}</span><span class="rp-wf-label">${escapeHtml(attr(this, "label", "节点"))}</span>`;
1764
+ }
1765
+ }
1766
+ class IosNavbarElement extends HTMLElement {
1767
+ connectedCallback() {
1768
+ injectStyle();
1769
+ if (this.dataset.rpReady) return;
1770
+ this.dataset.rpReady = "true";
1771
+ const title = attr(this, "title", "标题");
1772
+ const large = this.hasAttribute("large");
1773
+ const back = attr(this, "back");
1774
+ const trailing = attr(this, "trailing");
1775
+ this.innerHTML = `<div class="rp-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>` : ""}`;
1776
+ }
1777
+ }
1778
+ class IosTabbarElement extends HTMLElement {
1779
+ connectedCallback() {
1780
+ injectStyle();
1781
+ if (this.dataset.rpReady) return;
1782
+ this.dataset.rpReady = "true";
1783
+ const items = csv(this, "items", "首页,搜索,通知,我的");
1784
+ const icons = csv(this, "icons", "home,search,bell,user");
1785
+ const active = intAttr(this, "active", 0);
1786
+ 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("");
1787
+ }
1788
+ }
1789
+ class IosListElement extends HTMLElement {
1790
+ connectedCallback() {
1791
+ injectStyle();
1792
+ if (this.dataset.rpReady) return;
1793
+ this.dataset.rpReady = "true";
1794
+ const header = attr(this, "header");
1795
+ if (header) {
1796
+ const h = document.createElement("div");
1797
+ h.className = "rp-ios-list-header";
1798
+ h.textContent = header;
1799
+ this.insertBefore(h, this.firstChild);
1800
+ }
1801
+ }
1802
+ }
1803
+ class IosListItemElement extends HTMLElement {
1804
+ connectedCallback() {
1805
+ injectStyle();
1806
+ if (this.dataset.rpReady) return;
1807
+ this.dataset.rpReady = "true";
1808
+ const label = attr(this, "label", "项");
1809
+ const detail = attr(this, "detail");
1810
+ const ic = attr(this, "icon");
1811
+ const chevron = this.hasAttribute("chevron");
1812
+ 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>` : ""}`;
1813
+ }
1814
+ }
1815
+ class IosActionSheetElement extends HTMLElement {
1816
+ connectedCallback() {
1817
+ injectStyle();
1818
+ if (this.dataset.rpReady) return;
1819
+ this.dataset.rpReady = "true";
1820
+ const title = attr(this, "title");
1821
+ const actions = csv(this, "actions", "拍照,从相册选择,选择文件");
1822
+ const destructive = attr(this, "destructive");
1823
+ 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>`;
1824
+ const cancel = `<div class="rp-ios-as-group"><div class="rp-ios-as-action cancel">取消</div></div>`;
1825
+ this.innerHTML = group + cancel;
1826
+ }
1827
+ }
1828
+ class IosAlertElement extends HTMLElement {
1829
+ connectedCallback() {
1830
+ injectStyle();
1831
+ if (this.dataset.rpReady) return;
1832
+ this.dataset.rpReady = "true";
1833
+ const title = attr(this, "title", "提示");
1834
+ const message = attr(this, "message", "");
1835
+ const actions = csv(this, "actions", "取消,确定");
1836
+ this.innerHTML = `<div class="rp-ios-alert-body"><div class="rp-ios-alert-title">${escapeHtml(title)}</div>${message ? `<div class="rp-ios-alert-msg">${escapeHtml(message)}</div>` : ""}</div><div class="rp-ios-alert-actions">${actions.map((a, i) => `<span class="rp-ios-alert-btn${i === actions.length - 1 ? " primary" : ""}">${escapeHtml(a)}</span>`).join("")}</div>`;
1837
+ }
1838
+ }
1839
+ class IosSwitchElement extends HTMLElement {
1840
+ connectedCallback() {
1841
+ injectStyle();
1842
+ if (this.dataset.rpReady) return;
1843
+ this.dataset.rpReady = "true";
1844
+ const label = attr(this, "label");
1845
+ this.innerHTML = `${label ? `<span class="rp-ios-switch-label">${escapeHtml(label)}</span>` : ""}<span class="rp-ios-switch-track"><span class="rp-ios-switch-dot"></span></span>`;
1846
+ }
1847
+ }
1848
+ class IosSegmentedElement extends HTMLElement {
1849
+ connectedCallback() {
1850
+ injectStyle();
1851
+ if (this.dataset.rpReady) return;
1852
+ this.dataset.rpReady = "true";
1853
+ const options = csv(this, "options", "第一,第二,第三");
1854
+ const active = intAttr(this, "active", 0);
1855
+ this.innerHTML = options.map((o, i) => `<span class="rp-ios-seg-item${i === active ? " active" : ""}">${escapeHtml(o)}</span>`).join("");
1856
+ }
1857
+ }
1858
+ class IosButtonElement extends HTMLElement {
1859
+ connectedCallback() {
1860
+ var _a;
1861
+ injectStyle();
1862
+ if (this.dataset.rpReady) return;
1863
+ this.dataset.rpReady = "true";
1864
+ this.innerHTML = `<span>${escapeHtml(attr(this, "label", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "按钮"))}</span>`;
1865
+ }
1866
+ }
1867
+ class IosSearchElement extends HTMLElement {
1868
+ connectedCallback() {
1869
+ injectStyle();
1870
+ if (this.dataset.rpReady) return;
1871
+ this.dataset.rpReady = "true";
1872
+ const value = attr(this, "value");
1873
+ this.innerHTML = `${icon("search", 15)}<span class="${value ? "rp-value" : "rp-placeholder"}">${escapeHtml(value || attr(this, "placeholder", "搜索"))}</span>`;
1874
+ }
1875
+ }
1876
+ class IosStepperElement extends HTMLElement {
1877
+ connectedCallback() {
1878
+ injectStyle();
1879
+ if (this.dataset.rpReady) return;
1880
+ this.dataset.rpReady = "true";
1881
+ 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>`;
1882
+ }
1883
+ }
1884
+ class MacWindowElement extends HTMLElement {
1885
+ connectedCallback() {
1886
+ injectStyle();
1887
+ if (this.dataset.rpReady) return;
1888
+ this.dataset.rpReady = "true";
1889
+ const children = Array.from(this.childNodes);
1890
+ const title = attr(this, "title", "窗口");
1891
+ 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>`;
1892
+ const body = document.createElement("div");
1893
+ body.className = "rp-mac-window-body";
1894
+ children.forEach((n) => body.appendChild(n));
1895
+ this.innerHTML = titlebar;
1896
+ this.appendChild(body);
1897
+ }
1898
+ }
1899
+ class MacToolbarElement extends HTMLElement {
1900
+ connectedCallback() {
1901
+ injectStyle();
1902
+ }
1903
+ }
1904
+ class MacMenubarElement extends HTMLElement {
1905
+ connectedCallback() {
1906
+ injectStyle();
1907
+ if (this.dataset.rpReady) return;
1908
+ this.dataset.rpReady = "true";
1909
+ const items = csv(this, "items", "文件,编辑,显示,窗口,帮助");
1910
+ 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("");
1911
+ }
1912
+ }
1913
+ class MacSidebarElement extends HTMLElement {
1914
+ connectedCallback() {
1915
+ injectStyle();
1916
+ }
1917
+ }
1918
+ class MacSourceItemElement extends HTMLElement {
1919
+ connectedCallback() {
1920
+ injectStyle();
1921
+ if (this.dataset.rpReady) return;
1922
+ this.dataset.rpReady = "true";
1923
+ const label = attr(this, "label", "项");
1924
+ const ic = attr(this, "icon");
1925
+ if (this.hasAttribute("group")) {
1926
+ this.classList.add("rp-mac-source-group");
1927
+ this.textContent = label;
1928
+ return;
1929
+ }
1930
+ this.innerHTML = `${ic ? icon(ic, 15) : ""}<span class="rp-mac-source-label">${escapeHtml(label)}</span>`;
1931
+ if (attr(this, "state") === "selected") this.classList.add("selected");
1932
+ }
1933
+ }
1934
+ class MacSegmentedElement extends HTMLElement {
1935
+ connectedCallback() {
1936
+ injectStyle();
1937
+ if (this.dataset.rpReady) return;
1938
+ this.dataset.rpReady = "true";
1939
+ const options = csv(this, "options", "全部,未读,标记");
1940
+ const active = intAttr(this, "active", 0);
1941
+ this.innerHTML = options.map((o, i) => `<span class="rp-mac-seg-item${i === active ? " active" : ""}">${escapeHtml(o)}</span>`).join("");
1942
+ }
1943
+ }
1944
+ class MacPopoverElement extends HTMLElement {
1945
+ connectedCallback() {
1946
+ injectStyle();
1947
+ if (this.dataset.rpReady) return;
1948
+ this.dataset.rpReady = "true";
1949
+ const children = Array.from(this.childNodes);
1950
+ const title = attr(this, "title");
1951
+ const arrow = '<span class="rp-mac-pop-arrow"></span>';
1952
+ const body = document.createElement("div");
1953
+ body.className = "rp-mac-pop-body";
1954
+ if (title) {
1955
+ const h = document.createElement("div");
1956
+ h.className = "rp-mac-pop-title";
1957
+ h.textContent = title;
1958
+ body.appendChild(h);
1959
+ }
1960
+ children.forEach((n) => body.appendChild(n));
1961
+ this.innerHTML = arrow;
1962
+ this.appendChild(body);
1963
+ }
1964
+ }
1965
+ class MacSheetElement extends HTMLElement {
1966
+ connectedCallback() {
1967
+ injectStyle();
1968
+ if (this.dataset.rpReady) return;
1969
+ this.dataset.rpReady = "true";
1970
+ const children = Array.from(this.childNodes);
1971
+ const title = attr(this, "title", "操作");
1972
+ const body = document.createElement("div");
1973
+ body.className = "rp-mac-sheet-body";
1974
+ children.forEach((n) => body.appendChild(n));
1975
+ this.innerHTML = `<div class="rp-mac-sheet-title">${escapeHtml(title)}</div>`;
1976
+ this.appendChild(body);
1977
+ this.insertAdjacentHTML("beforeend", '<div class="rp-mac-sheet-actions"><snap-button label="取消"></snap-button><snap-button label="完成" variant="primary"></snap-button></div>');
1978
+ }
1979
+ }
1980
+ class MacStepperElement extends HTMLElement {
1981
+ connectedCallback() {
1982
+ injectStyle();
1983
+ if (this.dataset.rpReady) return;
1984
+ this.dataset.rpReady = "true";
1985
+ this.innerHTML = `<span class="rp-mac-step up">${icon("chevron-up", 11)}</span><span class="rp-mac-step down">${icon("chevron-down", 11)}</span>`;
1986
+ }
1987
+ }
1988
+ class MacDisclosureElement extends HTMLElement {
1989
+ connectedCallback() {
1990
+ injectStyle();
1991
+ if (this.dataset.rpReady) return;
1992
+ this.dataset.rpReady = "true";
1993
+ const children = Array.from(this.childNodes);
1994
+ const label = attr(this, "label", "详情");
1995
+ const expanded = this.hasAttribute("expanded");
1996
+ const head = document.createElement("div");
1997
+ head.className = "rp-mac-disc-head";
1998
+ head.innerHTML = `<span class="rp-mac-disc-tri${expanded ? " open" : ""}">${icon("chevron-right", 12)}</span><span>${escapeHtml(label)}</span>`;
1999
+ this.appendChild(head);
2000
+ if (expanded) {
2001
+ const body = document.createElement("div");
2002
+ body.className = "rp-mac-disc-body";
2003
+ children.forEach((n) => body.appendChild(n));
2004
+ this.appendChild(body);
2005
+ }
2006
+ }
2007
+ }
2008
+ class MacTableElement extends HTMLElement {
2009
+ connectedCallback() {
2010
+ injectStyle();
2011
+ if (this.dataset.rpReady) return;
2012
+ this.dataset.rpReady = "true";
2013
+ const cols = csv(this, "columns", "名称,类型,大小");
2014
+ const rows = intAttr(this, "rows", 5);
2015
+ 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>`;
2016
+ 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("");
2017
+ this.innerHTML = head + body;
2018
+ }
2019
+ }
2020
+ class ChatElement extends HTMLElement {
2021
+ connectedCallback() {
2022
+ injectStyle();
2023
+ }
2024
+ }
2025
+ class UserMessageElement extends HTMLElement {
2026
+ connectedCallback() {
2027
+ injectStyle();
2028
+ if (this.dataset.rpReady) return;
2029
+ this.dataset.rpReady = "true";
2030
+ const children = Array.from(this.childNodes);
2031
+ const text = attr(this, "text");
2032
+ const content = document.createElement("div");
2033
+ content.className = "rp-msg-content";
2034
+ if (text) content.textContent = text;
2035
+ else children.forEach((n) => content.appendChild(n));
2036
+ this.innerHTML = `<div class="rp-msg-role">You</div>`;
2037
+ this.appendChild(content);
2038
+ }
2039
+ }
2040
+ class AssistantMessageElement extends HTMLElement {
2041
+ connectedCallback() {
2042
+ injectStyle();
2043
+ if (this.dataset.rpReady) return;
2044
+ this.dataset.rpReady = "true";
2045
+ const children = Array.from(this.childNodes);
2046
+ const text = attr(this, "text");
2047
+ const name = attr(this, "name", "Assistant");
2048
+ const content = document.createElement("div");
2049
+ content.className = "rp-msg-content";
2050
+ if (text) content.textContent = text;
2051
+ else children.forEach((n) => content.appendChild(n));
2052
+ this.innerHTML = `<div class="rp-msg-role">${escapeHtml(name)}</div>`;
2053
+ this.appendChild(content);
2054
+ }
2055
+ }
2056
+ class SystemMessageElement extends HTMLElement {
2057
+ connectedCallback() {
2058
+ var _a;
2059
+ injectStyle();
2060
+ if (this.dataset.rpReady) return;
2061
+ this.dataset.rpReady = "true";
2062
+ const text = attr(this, "text", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "系统消息");
2063
+ this.innerHTML = `<span class="rp-sysmsg-line">${escapeHtml(text)}</span>`;
2064
+ }
2065
+ }
2066
+ class ToolCallElement extends HTMLElement {
2067
+ connectedCallback() {
2068
+ injectStyle();
2069
+ if (this.dataset.rpReady) return;
2070
+ this.dataset.rpReady = "true";
2071
+ const children = Array.from(this.childNodes);
2072
+ const name = attr(this, "name", "tool");
2073
+ const state = attr(this, "state", "done");
2074
+ const glyph = state === "running" ? icon("loader", 13) : state === "error" ? icon("circle-x", 13) : icon("check", 13);
2075
+ const args = attr(this, "args");
2076
+ 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>`;
2077
+ const body = document.createElement("div");
2078
+ body.className = "rp-tool-body";
2079
+ children.forEach((n) => body.appendChild(n));
2080
+ this.innerHTML = head;
2081
+ if (children.length) this.appendChild(body);
2082
+ }
2083
+ }
2084
+ class AgentOutputElement extends HTMLElement {
2085
+ connectedCallback() {
2086
+ injectStyle();
2087
+ if (this.dataset.rpReady) return;
2088
+ this.dataset.rpReady = "true";
2089
+ const children = Array.from(this.childNodes);
2090
+ const label = attr(this, "label");
2091
+ const head = label ? `<div class="rp-output-head">${escapeHtml(label)}</div>` : "";
2092
+ const body = document.createElement("div");
2093
+ body.className = "rp-output-body";
2094
+ const text = attr(this, "text");
2095
+ if (text) body.textContent = text;
2096
+ else children.forEach((n) => body.appendChild(n));
2097
+ this.innerHTML = head;
2098
+ this.appendChild(body);
2099
+ }
2100
+ }
2101
+ class ReasoningElement extends HTMLElement {
2102
+ connectedCallback() {
2103
+ injectStyle();
2104
+ if (this.dataset.rpReady) return;
2105
+ this.dataset.rpReady = "true";
2106
+ const children = Array.from(this.childNodes);
2107
+ const expanded = this.hasAttribute("expanded");
2108
+ const head = `<div class="rp-reason-head">${icon(expanded ? "chevron-down" : "chevron-right", 13)}<span>Thought for a few seconds</span></div>`;
2109
+ this.innerHTML = head;
2110
+ if (expanded) {
2111
+ const body = document.createElement("div");
2112
+ body.className = "rp-reason-body";
2113
+ children.forEach((n) => body.appendChild(n));
2114
+ this.appendChild(body);
2115
+ }
2116
+ }
2117
+ }
2118
+ class MessageActionsElement extends HTMLElement {
2119
+ connectedCallback() {
2120
+ injectStyle();
2121
+ if (this.dataset.rpReady || this.children.length) return;
2122
+ this.dataset.rpReady = "true";
2123
+ const actions = csv(this, "actions", "copy,retry,up,down");
2124
+ const map = { copy: ["copy", "复制"], retry: ["refresh", "重试"], up: ["thumbs-up", "赞"], down: ["thumbs-down", "踩"], edit: ["edit", "编辑"], share: ["send", "分享"] };
2125
+ this.innerHTML = actions.map((a) => {
2126
+ const m = map[a] || ["circle", a];
2127
+ return `<span class="rp-msg-action" title="${escapeHtml(m[1])}">${icon(m[0], 14)}</span>`;
2128
+ }).join("");
2129
+ }
2130
+ }
2131
+ class SuggestionsElement extends HTMLElement {
2132
+ connectedCallback() {
2133
+ injectStyle();
2134
+ if (this.dataset.rpReady) return;
2135
+ this.dataset.rpReady = "true";
2136
+ const items = csv(this, "items", "总结要点,继续,给个例子");
2137
+ this.innerHTML = items.map((t) => `<span class="rp-suggestion">${escapeHtml(t)}</span>`).join("");
2138
+ }
2139
+ }
2140
+ class TypingElement extends HTMLElement {
2141
+ connectedCallback() {
2142
+ injectStyle();
2143
+ if (this.dataset.rpReady) return;
2144
+ this.dataset.rpReady = "true";
2145
+ this.innerHTML = `<span class="rp-typing-dots"><span></span><span></span><span></span></span>`;
2146
+ }
2147
+ }
2148
+ class ComposerElement extends HTMLElement {
2149
+ connectedCallback() {
2150
+ injectStyle();
2151
+ if (this.dataset.rpReady) return;
2152
+ this.dataset.rpReady = "true";
2153
+ const value = attr(this, "value");
2154
+ const state = attr(this, "state", "idle");
2155
+ const sendIcon = state === "streaming" ? icon("stop", 16) : icon("send", 16);
2156
+ this.innerHTML = `<span class="rp-composer-attach">${icon("paperclip", 16)}</span><span class="rp-composer-input ${value ? "rp-value" : "rp-placeholder"}">${escapeHtml(value || attr(this, "placeholder", "给助手发消息…"))}</span><span class="rp-composer-send ${state}">${sendIcon}</span>`;
2157
+ }
2158
+ }
2159
+ class CitationElement extends HTMLElement {
2160
+ connectedCallback() {
2161
+ var _a;
2162
+ injectStyle();
2163
+ if (this.dataset.rpReady) return;
2164
+ this.dataset.rpReady = "true";
2165
+ const index = attr(this, "index", "1");
2166
+ const title = attr(this, "title", ((_a = this.textContent) == null ? void 0 : _a.trim()) || "来源");
2167
+ this.innerHTML = `<span class="rp-cite-idx">${escapeHtml(index)}</span><span class="rp-cite-title">${escapeHtml(title)}</span>`;
2168
+ }
2169
+ }
2170
+ class TokenUsageElement extends HTMLElement {
2171
+ connectedCallback() {
2172
+ injectStyle();
2173
+ if (this.dataset.rpReady) return;
2174
+ this.dataset.rpReady = "true";
2175
+ const used = intAttr(this, "used", 1840);
2176
+ const limit = intAttr(this, "limit", 8e3);
2177
+ const pct = limit ? Math.min(100, used / limit * 100) : 0;
2178
+ this.innerHTML = `<span>${used.toLocaleString()} / ${limit.toLocaleString()} tokens</span><span class="rp-token-track"><span class="rp-token-fill" style="width:${pct}%"></span></span>`;
2179
+ }
2180
+ }
961
2181
  function registerAll() {
962
2182
  define("rp-page", RpPage);
963
2183
  define("proto-page", RpPage);
@@ -969,7 +2189,137 @@ function registerAll() {
969
2189
  define("proto-enum", RpEnum);
970
2190
  define("rp-enum-item", RpEnumItem);
971
2191
  define("proto-enum-item", RpEnumItem);
972
- const pairs = [["viewport", ViewportElement], ["layout", LayoutElement], ["panel", PanelElement], ["navbar", NavbarElement], ["sidebar", SidebarElement], ["logo", LogoElement], ["search", FieldElement], ["input", FieldElement], ["textarea", TextareaElement], ["select", SelectElement], ["badge", BadgeElement], ["avatar", AvatarElement], ["list", ListElement], ["list-item", ListItemElement], ["tabs", TabsElement], ["tab", TabElement], ["button", ButtonElement], ["button-group", GenericElement], ["table", TableElement], ["table-row", TableRowElement], ["bulk-action-bar", BulkActionBarElement], ["empty", EmptyElement], ["loading", LoadingElement], ["alert", AlertElement], ["toast", AlertElement], ["dropdown", OverlayElement], ["popover", OverlayElement], ["tooltip", TooltipElement], ["modal", ModalElement], ["drawer", DrawerElement], ["card", CardElement], ["stat-card", StatCardElement], ["tag", TagElement], ["checkbox", CheckboxElement], ["radio", RadioElement], ["toggle", ToggleElement], ["form", FormElement], ["form-item", FormItemElement], ["date-picker", DatePickerElement], ["upload", UploadElement], ["image-placeholder", ImagePlaceholderElement], ["progress", ProgressElement], ["pagination", PaginationElement], ["steps", StepsElement], ["breadcrumb", BreadcrumbElement]];
2192
+ const pairs = [
2193
+ // layout
2194
+ ["viewport", ViewportElement],
2195
+ ["layout", LayoutElement],
2196
+ ["panel", PanelElement],
2197
+ ["navbar", NavbarElement],
2198
+ ["sidebar", SidebarElement],
2199
+ ["logo", LogoElement],
2200
+ ["split-pane", SplitPaneElement],
2201
+ ["divider", DividerElement],
2202
+ ["spacer", SpacerElement],
2203
+ // controls
2204
+ ["search", FieldElement],
2205
+ ["input", FieldElement],
2206
+ ["textarea", TextareaElement],
2207
+ ["select", SelectElement],
2208
+ ["button", ButtonElement],
2209
+ ["button-group", GenericElement],
2210
+ ["checkbox", CheckboxElement],
2211
+ ["radio", RadioElement],
2212
+ ["toggle", ToggleElement],
2213
+ ["form", FormElement],
2214
+ ["form-item", FormItemElement],
2215
+ ["date-picker", DatePickerElement],
2216
+ ["upload", UploadElement],
2217
+ ["image-placeholder", ImagePlaceholderElement],
2218
+ ["progress", ProgressElement],
2219
+ ["slider", SliderElement],
2220
+ ["range", RangeElement],
2221
+ ["number-input", NumberInputElement],
2222
+ ["rating", RatingElement],
2223
+ ["pin-input", PinInputElement],
2224
+ ["color-swatch", ColorSwatchElement],
2225
+ ["autocomplete", AutocompleteElement],
2226
+ // navigation
2227
+ ["badge", BadgeElement],
2228
+ ["avatar", AvatarElement],
2229
+ ["list", ListElement],
2230
+ ["list-item", ListItemElement],
2231
+ ["tabs", TabsElement],
2232
+ ["tab", TabElement],
2233
+ ["pagination", PaginationElement],
2234
+ ["steps", StepsElement],
2235
+ ["breadcrumb", BreadcrumbElement],
2236
+ ["segmented", SegmentedElement],
2237
+ ["command-palette", CommandPaletteElement],
2238
+ ["context-menu", ContextMenuElement],
2239
+ ["menu", MenuElement],
2240
+ ["menu-item", MenuItemElement],
2241
+ ["toc", TocElement],
2242
+ ["kbd", KbdElement],
2243
+ // data display
2244
+ ["table", TableElement],
2245
+ ["table-row", TableRowElement],
2246
+ ["bulk-action-bar", BulkActionBarElement],
2247
+ ["empty", EmptyElement],
2248
+ ["loading", LoadingElement],
2249
+ ["alert", AlertElement],
2250
+ ["toast", AlertElement],
2251
+ ["dropdown", OverlayElement],
2252
+ ["popover", OverlayElement],
2253
+ ["tooltip", TooltipElement],
2254
+ ["modal", ModalElement],
2255
+ ["drawer", DrawerElement],
2256
+ ["card", CardElement],
2257
+ ["stat-card", StatCardElement],
2258
+ ["tag", TagElement],
2259
+ ["chip", ChipElement],
2260
+ ["tree", TreeElement],
2261
+ ["tree-item", TreeItemElement],
2262
+ ["timeline", TimelineElement],
2263
+ ["timeline-item", TimelineItemElement],
2264
+ ["calendar", CalendarElement],
2265
+ ["kanban", KanbanElement],
2266
+ ["kanban-column", KanbanColumnElement],
2267
+ ["kanban-card", KanbanCardElement],
2268
+ ["code-block", CodeBlockElement],
2269
+ ["diff", DiffElement],
2270
+ ["image-grid", ImageGridElement],
2271
+ ["key-value", KeyValueElement],
2272
+ ["kv-row", KvRowElement],
2273
+ ["accordion", AccordionElement],
2274
+ ["accordion-item", AccordionItemElement],
2275
+ ["banner", BannerElement],
2276
+ ["skeleton", SkeletonElement],
2277
+ ["countdown", CountdownElement],
2278
+ ["result", ResultElement],
2279
+ ["permission-gate", PermissionGateElement],
2280
+ ["quota-bar", QuotaBarElement],
2281
+ ["api-key", ApiKeyElement],
2282
+ ["audit-row", AuditRowElement],
2283
+ ["workflow-node", WorkflowNodeElement],
2284
+ // iOS
2285
+ ["ios-navbar", IosNavbarElement],
2286
+ ["ios-tabbar", IosTabbarElement],
2287
+ ["ios-list", IosListElement],
2288
+ ["ios-list-item", IosListItemElement],
2289
+ ["ios-action-sheet", IosActionSheetElement],
2290
+ ["ios-alert", IosAlertElement],
2291
+ ["ios-switch", IosSwitchElement],
2292
+ ["ios-segmented", IosSegmentedElement],
2293
+ ["ios-button", IosButtonElement],
2294
+ ["ios-search", IosSearchElement],
2295
+ ["ios-stepper", IosStepperElement],
2296
+ // macOS
2297
+ ["macos-window", MacWindowElement],
2298
+ ["macos-toolbar", MacToolbarElement],
2299
+ ["macos-menubar", MacMenubarElement],
2300
+ ["macos-sidebar", MacSidebarElement],
2301
+ ["macos-source-item", MacSourceItemElement],
2302
+ ["macos-segmented", MacSegmentedElement],
2303
+ ["macos-popover", MacPopoverElement],
2304
+ ["macos-sheet", MacSheetElement],
2305
+ ["macos-stepper", MacStepperElement],
2306
+ ["macos-disclosure", MacDisclosureElement],
2307
+ ["macos-table", MacTableElement],
2308
+ // agent / conversational UI
2309
+ ["chat", ChatElement],
2310
+ ["user-message", UserMessageElement],
2311
+ ["assistant-message", AssistantMessageElement],
2312
+ ["system-message", SystemMessageElement],
2313
+ ["tool-call", ToolCallElement],
2314
+ ["agent-output", AgentOutputElement],
2315
+ ["reasoning", ReasoningElement],
2316
+ ["message-actions", MessageActionsElement],
2317
+ ["suggestions", SuggestionsElement],
2318
+ ["typing", TypingElement],
2319
+ ["composer", ComposerElement],
2320
+ ["citation", CitationElement],
2321
+ ["token-usage", TokenUsageElement]
2322
+ ];
973
2323
  for (const [suffix, ctor] of pairs) {
974
2324
  define(`snap-${suffix}`, ctor);
975
2325
  define(`rp-${suffix}`, ctor);