@npmjsdnt/turn-reply 0.0.0-stage → 0.1.0

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/tr.css ADDED
@@ -0,0 +1,83 @@
1
+ .trw{
2
+ --c-bg:var(--surface-2);--c-sunken:var(--surface-1);
3
+ --c-hover:var(--fill-ghost-hover,var(--surface-1));--c-soft:var(--fill-ghost-selected,var(--surface-1));
4
+ --c-solid:var(--fill-primary,var(--text-primary));--c-on-solid:var(--on-primary,var(--surface-2));
5
+ --c-line:var(--border);--c-line-s:var(--border-strong);--c-line-x:var(--border-stronger,var(--border-strong));
6
+ --c-ink1:var(--text-primary);--c-ink2:var(--text-secondary);--c-ink3:var(--text-muted);--c-ink4:var(--text-disabled,var(--text-muted));
7
+ --c-attn:var(--text-warning);--c-ok:var(--text-success);--c-focus:var(--border-accent,var(--text-accent));--c-r:6px;
8
+ --c-track:color-mix(in srgb,var(--c-ink1,currentColor) 5%,transparent);--c-lift:var(--surface-3,var(--surface-2));--c-hov:color-mix(in srgb,var(--c-ink1,currentColor) 4%,transparent);
9
+ container-type:inline-size;position:relative;box-sizing:border-box;
10
+ font-family:var(--font-sans);font-size:13px;line-height:20px;font-weight:400;
11
+ font-variant-numeric:tabular-nums;-webkit-font-smoothing:antialiased;
12
+ color:var(--c-ink1);background:transparent;border:0;border-radius:0;padding:0
13
+ }
14
+ .trw.dark{--c-lift:color-mix(in srgb,var(--c-ink1,currentColor) 15%,transparent);--c-hov:color-mix(in srgb,var(--c-ink1,currentColor) 8%,transparent)}
15
+ .trw *,.trw *::before,.trw *::after{box-sizing:border-box}
16
+ .trw [hidden]{display:none!important}
17
+ .trw .mono{font-family:var(--font-mono);font-size:12px}
18
+ .trw .grp{display:flex;align-items:flex-start;padding:6px 0;border-top:0.5px solid var(--c-line)}
19
+ .trw .bd>.grp:first-child{border-top:0}
20
+ .trw .gl{flex:0 0 60px;padding-top:6px;font-size:11px;line-height:16px;color:var(--c-ink2);white-space:nowrap;cursor:default}
21
+ .trw .rs{flex:1 1 auto;min-width:0}
22
+ .trw .it{margin:0 -6px;padding:0 6px;border-radius:0}
23
+ .trw .it:hover,.trw.kb .it:focus-within{background:var(--c-hover)}
24
+ .trw .ln{display:flex;flex-wrap:wrap;align-items:center;gap:2px 8px;min-height:28px}
25
+ .trw .bd>.grp:first-child .it:first-child .ln{padding-right:40px}
26
+ .trw .q{flex:0 0 var(--qw,240px);min-width:0;display:flex;align-items:center;gap:6px;white-space:nowrap;overflow:hidden}
27
+ .trw.measuring .q{flex:none!important;width:max-content!important}
28
+ .trw .qt{min-width:0;overflow:hidden;text-overflow:ellipsis}
29
+ .trw .n{flex:none;min-width:14px;color:var(--c-ink2)}
30
+ .trw .it.core .qt{font-weight:500}
31
+ .trw .q.info .qt{font-size:12px;color:var(--c-ink2)}
32
+ .trw a.tk{font-family:var(--font-mono);font-size:12px;color:var(--c-ink1);text-decoration:underline;text-decoration-color:var(--c-line-x);text-underline-offset:2px}
33
+ .trw .ctl{flex:none;display:flex;flex-wrap:wrap;align-items:center;gap:4px 6px;padding:0 4px;margin:0 -4px}
34
+ .trw .cb{flex:none;width:9px;height:9px;background:var(--c-attn);clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%)}
35
+ .trw .seg{display:inline-flex;align-items:center;gap:2px;height:26px;padding:2px;border:0;border-radius:7px;background:var(--c-track)}
36
+ .trw button.sg{position:relative;font-family:inherit!important;font-size:12px!important;font-weight:400!important;line-height:20px!important;height:22px!important;min-height:0!important;margin:0!important;padding:0 9px!important;border:0!important;border-radius:5px!important;background:transparent!important;color:var(--c-ink2)!important;box-shadow:none!important;cursor:pointer;white-space:nowrap;text-align:center;justify-content:center}
37
+ .trw button.sg[aria-checked="false"]:hover{background:var(--c-hov)!important;color:var(--c-ink1)!important}
38
+ .trw .ck.rec>span::before{content:"";display:inline-block;width:4px;height:4px;border-radius:50%;background:currentColor;margin-right:5px;vertical-align:2px}
39
+ .trw button.sg.rec{padding:0 4px 0 14px!important}
40
+ .trw button.sg.rec::before{content:"";position:absolute;left:6px;top:50%;width:4px;height:4px;margin-top:-2px;border-radius:50%;background:currentColor;opacity:.4}
41
+ .trw button.sg.sk{color:var(--c-ink3)!important}
42
+ .trw button.sg[aria-checked="true"]{background:var(--c-lift)!important;color:var(--c-ink1)!important;box-shadow:none!important}
43
+ .trw .dseg button.sg[aria-checked="true"]:hover::before{content:"×";position:absolute;left:4px;top:0;width:8px;height:auto;margin:0;border-radius:0;background:none;line-height:22px;text-align:center;opacity:1;color:var(--c-ink3)}
44
+ .trw .k{display:none;position:absolute;top:-8px;right:-4px;font:11px/14px var(--font-mono);padding:0 3px;border-radius:4px;background:var(--c-bg);color:var(--c-ink3);border:0.5px solid var(--c-line-s);pointer-events:none;z-index:1}
45
+ .trw.kb .it:focus-within .k{display:block}
46
+ .trw .ck{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 6px;border-radius:var(--c-r);font-size:12px;color:var(--c-ink2);cursor:pointer;white-space:nowrap;user-select:none}
47
+ .trw .ck:hover{background:var(--c-hover);color:var(--c-ink1)}
48
+ .trw .ck input{width:13px;height:13px;margin:0;accent-color:var(--c-solid);cursor:pointer}
49
+ .trw .ck:has(input:checked){color:var(--c-ink1)}
50
+ .trw button.gh{display:inline-flex;align-items:center;gap:5px;font-family:inherit!important;font-size:12px!important;font-weight:500!important;line-height:20px!important;height:26px!important;min-height:0!important;margin:0!important;padding:0 8px!important;border:0.5px solid transparent!important;border-radius:var(--c-r)!important;background:transparent!important;color:var(--c-ink2)!important;box-shadow:none!important;cursor:pointer;white-space:nowrap}
51
+ .trw button.gh:hover{background:var(--c-hover)!important;color:var(--c-ink1)!important}
52
+ .trw svg.i{width:14px;height:14px;flex:none;fill:none;stroke:currentColor;stroke-width:1.3;stroke-linecap:round;stroke-linejoin:round}
53
+ .trw .ed{display:flex;padding:4px 0 8px calc(var(--qw,240px) + 8px)}
54
+ .trw .it:last-child>.ed{padding-bottom:4px}
55
+ .trw .ed textarea,.trw textarea.ask{display:block;flex:1;min-width:0;min-height:28px;height:28px;resize:none!important;overflow:hidden;margin:0!important;padding:4px 10px!important;font:12px/18px var(--font-sans,system-ui)!important;white-space:pre-wrap;overflow-wrap:anywhere;border:0.5px solid var(--c-line-s)!important;border-radius:var(--c-r)!important;background:var(--c-bg)!important;color:var(--c-ink1)!important;box-shadow:none!important}
56
+ .trw .ed textarea::placeholder,.trw textarea.ask::placeholder{color:var(--c-ink3)}
57
+ .trw textarea.ask{flex:1 1 160px;min-height:26px;height:26px;padding:3px 10px!important}
58
+ .trw .ln.top{align-items:flex-start}
59
+ .trw .ln.top .q{min-height:26px}
60
+ .trw .foot{display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;padding:8px 0 2px;border-top:0.5px solid var(--c-line)}
61
+ .trw .sum{flex:1 1 auto;display:inline-flex;align-items:center;gap:8px;font-size:12px;line-height:18px;color:var(--c-ink3);white-space:nowrap}
62
+ .trw .sum b{font-weight:500;color:var(--c-ink2)}
63
+ .trw button.lk{font-family:inherit!important;font-size:12px!important;font-weight:400!important;line-height:18px!important;height:auto!important;min-height:0!important;margin:0!important;padding:0 2px!important;border:0!important;border-radius:4px!important;background:transparent!important;color:var(--c-ink2)!important;box-shadow:none!important;cursor:pointer;text-decoration:underline;text-decoration-color:var(--c-line-x);text-underline-offset:3px}
64
+ .trw button.btn{display:inline-flex;align-items:center;gap:6px;font-family:inherit!important;font-size:12px!important;font-weight:500!important;line-height:20px!important;height:28px!important;min-height:0!important;margin:0!important;padding:0 12px!important;border:0.5px solid transparent!important;border-radius:var(--c-r)!important;background:transparent!important;color:var(--c-ink2)!important;box-shadow:none!important;cursor:pointer;white-space:nowrap}
65
+ .trw button.btn:hover{background:var(--c-hover)!important;color:var(--c-ink1)!important}
66
+ .trw button.btn.pri{border-color:var(--c-line-x)!important;color:var(--c-ink1)!important}
67
+ .trw button.btn:disabled,.trw button.gh:disabled{color:var(--c-ink4)!important;background:transparent!important;cursor:default}
68
+ .trw pre.pv{font:12px/18px var(--font-mono);white-space:pre-wrap;overflow-wrap:anywhere;background:var(--c-sunken);padding:8px 10px;border-radius:var(--c-r);margin:0 0 8px;color:var(--c-ink2)}
69
+ .trw .fold{display:none;align-items:center;gap:6px;min-height:34px;font-size:12px;color:var(--c-ink2);cursor:pointer;padding:0 40px 0 6px;margin:0 -6px}
70
+ .trw .fold .fs{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
71
+ .trw .mk-ok{flex:none;width:10px;height:8px;background:var(--c-ok);clip-path:polygon(0 56%,15% 38%,38% 62%,85% 0,100% 19%,38% 100%)}
72
+ .trw.folded .fold{display:flex}
73
+ .trw.folded>:not(.fold){display:none!important}
74
+ .trw.folded:hover{background:var(--c-hover);border-radius:0}
75
+ .trw button:focus-visible{outline:2px solid var(--c-focus)!important;outline-offset:-2px}
76
+ .trw .ed textarea:focus,.trw textarea.ask:focus{outline:none!important;border-color:var(--c-focus)!important;box-shadow:inset 0 0 0 1px var(--c-focus)!important}
77
+ @container (max-width:480px){
78
+ .trw .grp{display:block}
79
+ .trw .ln{flex-wrap:wrap;row-gap:2px;padding-bottom:2px}
80
+ .trw .q{flex:1 1 auto;white-space:normal}
81
+ .trw .ed{padding-left:0}
82
+ }
83
+ .trw .err{padding:6px 0;font-size:12px;line-height:18px;color:var(--c-attn);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
package/dist/tr.js ADDED
@@ -0,0 +1,932 @@
1
+ /*! @npmjsdnt/turn-reply@0.1.0 turn-reply panel */
2
+ (() => {
3
+ // trw:css
4
+ var css_default = `.trw{
5
+ --c-bg:var(--surface-2);--c-sunken:var(--surface-1);
6
+ --c-hover:var(--fill-ghost-hover,var(--surface-1));--c-soft:var(--fill-ghost-selected,var(--surface-1));
7
+ --c-solid:var(--fill-primary,var(--text-primary));--c-on-solid:var(--on-primary,var(--surface-2));
8
+ --c-line:var(--border);--c-line-s:var(--border-strong);--c-line-x:var(--border-stronger,var(--border-strong));
9
+ --c-ink1:var(--text-primary);--c-ink2:var(--text-secondary);--c-ink3:var(--text-muted);--c-ink4:var(--text-disabled,var(--text-muted));
10
+ --c-attn:var(--text-warning);--c-ok:var(--text-success);--c-focus:var(--border-accent,var(--text-accent));--c-r:6px;
11
+ --c-track:color-mix(in srgb,var(--c-ink1,currentColor) 5%,transparent);--c-lift:var(--surface-3,var(--surface-2));--c-hov:color-mix(in srgb,var(--c-ink1,currentColor) 4%,transparent);
12
+ container-type:inline-size;position:relative;box-sizing:border-box;
13
+ font-family:var(--font-sans);font-size:13px;line-height:20px;font-weight:400;
14
+ font-variant-numeric:tabular-nums;-webkit-font-smoothing:antialiased;
15
+ color:var(--c-ink1);background:transparent;border:0;border-radius:0;padding:0
16
+ }
17
+ .trw.dark{--c-lift:color-mix(in srgb,var(--c-ink1,currentColor) 15%,transparent);--c-hov:color-mix(in srgb,var(--c-ink1,currentColor) 8%,transparent)}
18
+ .trw *,.trw *::before,.trw *::after{box-sizing:border-box}
19
+ .trw [hidden]{display:none!important}
20
+ .trw .mono{font-family:var(--font-mono);font-size:12px}
21
+ .trw .grp{display:flex;align-items:flex-start;padding:6px 0;border-top:0.5px solid var(--c-line)}
22
+ .trw .bd>.grp:first-child{border-top:0}
23
+ .trw .gl{flex:0 0 60px;padding-top:6px;font-size:11px;line-height:16px;color:var(--c-ink2);white-space:nowrap;cursor:default}
24
+ .trw .rs{flex:1 1 auto;min-width:0}
25
+ .trw .it{margin:0 -6px;padding:0 6px;border-radius:0}
26
+ .trw .it:hover,.trw.kb .it:focus-within{background:var(--c-hover)}
27
+ .trw .ln{display:flex;flex-wrap:wrap;align-items:center;gap:2px 8px;min-height:28px}
28
+ .trw .bd>.grp:first-child .it:first-child .ln{padding-right:40px}
29
+ .trw .q{flex:0 0 var(--qw,240px);min-width:0;display:flex;align-items:center;gap:6px;white-space:nowrap;overflow:hidden}
30
+ .trw.measuring .q{flex:none!important;width:max-content!important}
31
+ .trw .qt{min-width:0;overflow:hidden;text-overflow:ellipsis}
32
+ .trw .n{flex:none;min-width:14px;color:var(--c-ink2)}
33
+ .trw .it.core .qt{font-weight:500}
34
+ .trw .q.info .qt{font-size:12px;color:var(--c-ink2)}
35
+ .trw a.tk{font-family:var(--font-mono);font-size:12px;color:var(--c-ink1);text-decoration:underline;text-decoration-color:var(--c-line-x);text-underline-offset:2px}
36
+ .trw .ctl{flex:none;display:flex;flex-wrap:wrap;align-items:center;gap:4px 6px;padding:0 4px;margin:0 -4px}
37
+ .trw .cb{flex:none;width:9px;height:9px;background:var(--c-attn);clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%)}
38
+ .trw .seg{display:inline-flex;align-items:center;gap:2px;height:26px;padding:2px;border:0;border-radius:7px;background:var(--c-track)}
39
+ .trw button.sg{position:relative;font-family:inherit!important;font-size:12px!important;font-weight:400!important;line-height:20px!important;height:22px!important;min-height:0!important;margin:0!important;padding:0 9px!important;border:0!important;border-radius:5px!important;background:transparent!important;color:var(--c-ink2)!important;box-shadow:none!important;cursor:pointer;white-space:nowrap;text-align:center;justify-content:center}
40
+ .trw button.sg[aria-checked="false"]:hover{background:var(--c-hov)!important;color:var(--c-ink1)!important}
41
+ .trw .ck.rec>span::before{content:"";display:inline-block;width:4px;height:4px;border-radius:50%;background:currentColor;margin-right:5px;vertical-align:2px}
42
+ .trw button.sg.rec{padding:0 4px 0 14px!important}
43
+ .trw button.sg.rec::before{content:"";position:absolute;left:6px;top:50%;width:4px;height:4px;margin-top:-2px;border-radius:50%;background:currentColor;opacity:.4}
44
+ .trw button.sg.sk{color:var(--c-ink3)!important}
45
+ .trw button.sg[aria-checked="true"]{background:var(--c-lift)!important;color:var(--c-ink1)!important;box-shadow:none!important}
46
+ .trw .dseg button.sg[aria-checked="true"]:hover::before{content:"×";position:absolute;left:4px;top:0;width:8px;height:auto;margin:0;border-radius:0;background:none;line-height:22px;text-align:center;opacity:1;color:var(--c-ink3)}
47
+ .trw .k{display:none;position:absolute;top:-8px;right:-4px;font:11px/14px var(--font-mono);padding:0 3px;border-radius:4px;background:var(--c-bg);color:var(--c-ink3);border:0.5px solid var(--c-line-s);pointer-events:none;z-index:1}
48
+ .trw.kb .it:focus-within .k{display:block}
49
+ .trw .ck{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 6px;border-radius:var(--c-r);font-size:12px;color:var(--c-ink2);cursor:pointer;white-space:nowrap;user-select:none}
50
+ .trw .ck:hover{background:var(--c-hover);color:var(--c-ink1)}
51
+ .trw .ck input{width:13px;height:13px;margin:0;accent-color:var(--c-solid);cursor:pointer}
52
+ .trw .ck:has(input:checked){color:var(--c-ink1)}
53
+ .trw button.gh{display:inline-flex;align-items:center;gap:5px;font-family:inherit!important;font-size:12px!important;font-weight:500!important;line-height:20px!important;height:26px!important;min-height:0!important;margin:0!important;padding:0 8px!important;border:0.5px solid transparent!important;border-radius:var(--c-r)!important;background:transparent!important;color:var(--c-ink2)!important;box-shadow:none!important;cursor:pointer;white-space:nowrap}
54
+ .trw button.gh:hover{background:var(--c-hover)!important;color:var(--c-ink1)!important}
55
+ .trw svg.i{width:14px;height:14px;flex:none;fill:none;stroke:currentColor;stroke-width:1.3;stroke-linecap:round;stroke-linejoin:round}
56
+ .trw .ed{display:flex;padding:4px 0 8px calc(var(--qw,240px) + 8px)}
57
+ .trw .it:last-child>.ed{padding-bottom:4px}
58
+ .trw .ed textarea,.trw textarea.ask{display:block;flex:1;min-width:0;min-height:28px;height:28px;resize:none!important;overflow:hidden;margin:0!important;padding:4px 10px!important;font:12px/18px var(--font-sans,system-ui)!important;white-space:pre-wrap;overflow-wrap:anywhere;border:0.5px solid var(--c-line-s)!important;border-radius:var(--c-r)!important;background:var(--c-bg)!important;color:var(--c-ink1)!important;box-shadow:none!important}
59
+ .trw .ed textarea::placeholder,.trw textarea.ask::placeholder{color:var(--c-ink3)}
60
+ .trw textarea.ask{flex:1 1 160px;min-height:26px;height:26px;padding:3px 10px!important}
61
+ .trw .ln.top{align-items:flex-start}
62
+ .trw .ln.top .q{min-height:26px}
63
+ .trw .foot{display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;padding:8px 0 2px;border-top:0.5px solid var(--c-line)}
64
+ .trw .sum{flex:1 1 auto;display:inline-flex;align-items:center;gap:8px;font-size:12px;line-height:18px;color:var(--c-ink3);white-space:nowrap}
65
+ .trw .sum b{font-weight:500;color:var(--c-ink2)}
66
+ .trw button.lk{font-family:inherit!important;font-size:12px!important;font-weight:400!important;line-height:18px!important;height:auto!important;min-height:0!important;margin:0!important;padding:0 2px!important;border:0!important;border-radius:4px!important;background:transparent!important;color:var(--c-ink2)!important;box-shadow:none!important;cursor:pointer;text-decoration:underline;text-decoration-color:var(--c-line-x);text-underline-offset:3px}
67
+ .trw button.btn{display:inline-flex;align-items:center;gap:6px;font-family:inherit!important;font-size:12px!important;font-weight:500!important;line-height:20px!important;height:28px!important;min-height:0!important;margin:0!important;padding:0 12px!important;border:0.5px solid transparent!important;border-radius:var(--c-r)!important;background:transparent!important;color:var(--c-ink2)!important;box-shadow:none!important;cursor:pointer;white-space:nowrap}
68
+ .trw button.btn:hover{background:var(--c-hover)!important;color:var(--c-ink1)!important}
69
+ .trw button.btn.pri{border-color:var(--c-line-x)!important;color:var(--c-ink1)!important}
70
+ .trw button.btn:disabled,.trw button.gh:disabled{color:var(--c-ink4)!important;background:transparent!important;cursor:default}
71
+ .trw pre.pv{font:12px/18px var(--font-mono);white-space:pre-wrap;overflow-wrap:anywhere;background:var(--c-sunken);padding:8px 10px;border-radius:var(--c-r);margin:0 0 8px;color:var(--c-ink2)}
72
+ .trw .fold{display:none;align-items:center;gap:6px;min-height:34px;font-size:12px;color:var(--c-ink2);cursor:pointer;padding:0 40px 0 6px;margin:0 -6px}
73
+ .trw .fold .fs{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
74
+ .trw .mk-ok{flex:none;width:10px;height:8px;background:var(--c-ok);clip-path:polygon(0 56%,15% 38%,38% 62%,85% 0,100% 19%,38% 100%)}
75
+ .trw.folded .fold{display:flex}
76
+ .trw.folded>:not(.fold){display:none!important}
77
+ .trw.folded:hover{background:var(--c-hover);border-radius:0}
78
+ .trw button:focus-visible{outline:2px solid var(--c-focus)!important;outline-offset:-2px}
79
+ .trw .ed textarea:focus,.trw textarea.ask:focus{outline:none!important;border-color:var(--c-focus)!important;box-shadow:inset 0 0 0 1px var(--c-focus)!important}
80
+ @container (max-width:480px){
81
+ .trw .grp{display:block}
82
+ .trw .ln{flex-wrap:wrap;row-gap:2px;padding-bottom:2px}
83
+ .trw .q{flex:1 1 auto;white-space:normal}
84
+ .trw .ed{padding-left:0}
85
+ }
86
+ .trw .err{padding:6px 0;font-size:12px;line-height:18px;color:var(--c-attn);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
87
+ `;
88
+
89
+ // ../schema/validate.ts
90
+ var isStr = (x, max = Infinity, min = 1) => typeof x === "string" && x.length >= min && x.length <= max;
91
+ var only = (o, keys, at, e) => {
92
+ for (const k of Object.keys(o))
93
+ if (!keys.includes(k))
94
+ e.push(`${at}.${k} 未定义的字段`);
95
+ };
96
+ function validate(s) {
97
+ const e = [];
98
+ if (!s || typeof s !== "object" || Array.isArray(s))
99
+ return ["$ 不是对象"];
100
+ only(s, ["v", "turn", "ticketUrl", "decisions", "actions", "delivery", "optional"], "$", e);
101
+ if (s.v !== 1)
102
+ e.push("$.v 必须为 1");
103
+ if (!isStr(s.turn, 40) || !/^[\w.:-]+$/.test(s.turn))
104
+ e.push("$.turn 缺失或含非法字符");
105
+ if (s.ticketUrl !== undefined && !(isStr(s.ticketUrl) && s.ticketUrl.startsWith("https://")))
106
+ e.push("$.ticketUrl 须为 https:// 前缀");
107
+ const seen = new Set;
108
+ (s.decisions ?? []).forEach((d, i) => {
109
+ const at = `$.decisions[${i}]`;
110
+ if (!d || typeof d !== "object")
111
+ return e.push(`${at} 不是对象`);
112
+ only(d, ["n", "group", "core", "q", "opts", "rec", "def", "multi", "ask", "ph"], at, e);
113
+ if (!Number.isInteger(d.n) || d.n < 1)
114
+ e.push(`${at}.n 须为正整数`);
115
+ else if (seen.has(d.n))
116
+ e.push(`${at}.n=${d.n} 重复`);
117
+ else
118
+ seen.add(d.n);
119
+ if (!["now", "defaulted", "pending"].includes(d.group))
120
+ e.push(`${at}.group 非法`);
121
+ if (!isStr(d.q, 40))
122
+ e.push(`${at}.q 须为 1–40 字`);
123
+ if (d.core !== undefined && typeof d.core !== "boolean")
124
+ e.push(`${at}.core 须为布尔`);
125
+ if (d.def !== undefined && !isStr(d.def, 60))
126
+ e.push(`${at}.def 须为 ≤60 字`);
127
+ if (d.multi !== undefined && d.multi !== true)
128
+ e.push(`${at}.multi 只能为 true`);
129
+ if (d.ask !== undefined && d.ask !== true)
130
+ e.push(`${at}.ask 只能为 true`);
131
+ const opts = d.opts;
132
+ if (opts !== undefined && !(Array.isArray(opts) && opts.every((o) => isStr(o, 12))))
133
+ e.push(`${at}.opts 须为 1–12 字的字符串数组`);
134
+ const n = Array.isArray(opts) ? opts.length : 0;
135
+ const kind = d.group === "defaulted" ? "defaulted" : d.ask ? "ask" : d.multi ? "multi" : "one";
136
+ if (d.ask && d.multi)
137
+ e.push(`${at} ask 与 multi 不能同时出现`);
138
+ if (kind === "defaulted" && (opts || d.rec !== undefined || d.ask || d.multi))
139
+ e.push(`${at} defaulted 条目只有「推翻」,不带 opts/rec/ask/multi`);
140
+ if (kind === "ask" && (opts || d.rec !== undefined))
141
+ e.push(`${at} ask 条目不带 opts/rec`);
142
+ if (d.ph !== undefined && (kind !== "ask" || !isStr(d.ph, 40)))
143
+ e.push(`${at}.ph 只用于 ask,≤40 字`);
144
+ if (kind === "one" && (n < 2 || n > 4))
145
+ e.push(`${at} 单选须有 2–4 个 opts(现 ${n})`);
146
+ if (kind === "multi" && (n < 2 || n > 8))
147
+ e.push(`${at} 多选须有 2–8 个 opts(现 ${n})`);
148
+ if (kind === "one" && d.rec !== undefined && !(Number.isInteger(d.rec) && d.rec >= 0 && d.rec < n))
149
+ e.push(`${at}.rec 须为 opts 下标`);
150
+ if (kind === "multi" && d.rec !== undefined && !(Array.isArray(d.rec) && d.rec.every((r) => Number.isInteger(r) && r >= 0 && r < n) && new Set(d.rec).size === d.rec.length))
151
+ e.push(`${at}.rec 须为不重复的 opts 下标数组`);
152
+ if (Array.isArray(opts) && new Set(opts).size !== n)
153
+ e.push(`${at}.opts 有重复`);
154
+ });
155
+ const ns = [...seen].sort((a, b) => a - b);
156
+ if (ns.length && ns.some((x, k) => k && x !== ns[k - 1] + 1))
157
+ e.push(`$.decisions 编号不连续:${ns.join(",")}`);
158
+ (s.actions ?? []).forEach((a, i) => {
159
+ const at = `$.actions[${i}]`;
160
+ if (!a || typeof a !== "object")
161
+ return e.push(`${at} 不是对象`);
162
+ only(a, ["text", "short", "cmd"], at, e);
163
+ if (!isStr(a.text, 120))
164
+ e.push(`${at}.text 须为 1–120 字`);
165
+ if (!isStr(a.short, 24))
166
+ e.push(`${at}.short 须为 1–24 字`);
167
+ if (a.cmd !== undefined && !isStr(a.cmd))
168
+ e.push(`${at}.cmd 须为非空字符串`);
169
+ });
170
+ if (s.delivery !== undefined) {
171
+ const d = s.delivery;
172
+ if (!d || typeof d !== "object")
173
+ e.push("$.delivery 不是对象");
174
+ else {
175
+ only(d, ["info", "toggles"], "$.delivery", e);
176
+ if (d.info !== undefined && !isStr(d.info, 120))
177
+ e.push("$.delivery.info 须为 ≤120 字");
178
+ (d.toggles ?? []).forEach((t, i) => {
179
+ only(t ?? {}, ["label", "rec"], `$.delivery.toggles[${i}]`, e);
180
+ if (!isStr(t?.label, 20))
181
+ e.push(`$.delivery.toggles[${i}].label 须为 1–20 字`);
182
+ if (t?.rec !== undefined && typeof t.rec !== "boolean")
183
+ e.push(`$.delivery.toggles[${i}].rec 须为布尔`);
184
+ });
185
+ }
186
+ }
187
+ (s.optional ?? []).forEach((o, i) => {
188
+ only(o ?? {}, ["text"], `$.optional[${i}]`, e);
189
+ if (!isStr(o?.text, 120))
190
+ e.push(`$.optional[${i}].text 须为 1–120 字`);
191
+ });
192
+ for (const k of ["decisions", "actions", "optional"])
193
+ if (s[k] !== undefined && !Array.isArray(s[k]))
194
+ e.push(`$.${k} 须为数组`);
195
+ return e;
196
+ }
197
+ if (false) {}
198
+
199
+ // src/panel.js
200
+ var renderPanel = (() => {
201
+ const el = (t, a = {}, ...k) => {
202
+ const e = document.createElement(t);
203
+ for (const [x, v] of Object.entries(a)) {
204
+ if (v == null || v === false)
205
+ continue;
206
+ if (x === "cls")
207
+ e.className = v;
208
+ else
209
+ e.setAttribute(x, v);
210
+ }
211
+ k.flat().forEach((c) => {
212
+ if (c != null && c !== false)
213
+ e.append(c);
214
+ });
215
+ return e;
216
+ };
217
+ const ICON = {
218
+ copy: '<rect x="5.5" y="5.5" width="7.5" height="7.5" rx="1.2"/><path d="M10.5 3.5V3a.5.5 0 0 0-.5-.5H3a.5.5 0 0 0-.5.5v7a.5.5 0 0 0 .5.5h.5"/>',
219
+ reset: '<path d="M3.2 8a4.8 4.8 0 1 0 1.4-3.4"/><path d="M3.2 2.6v2.6h2.6"/>'
220
+ };
221
+ const icon = (n) => {
222
+ const s = document.createElementNS("http://www.w3.org/2000/svg", "svg");
223
+ s.setAttribute("viewBox", "0 0 16 16");
224
+ s.setAttribute("class", "i");
225
+ s.setAttribute("aria-hidden", "true");
226
+ s.innerHTML = ICON[n];
227
+ return s;
228
+ };
229
+ let LIN = null;
230
+ const linkify = (s) => {
231
+ if (!s)
232
+ return [];
233
+ const out = [];
234
+ let last = 0;
235
+ s.replace(/\b[A-Z]{2,6}-\d+\b|\b[0-9a-f]{7,40}\b/g, (m, i) => {
236
+ const tk = /^[A-Z]/.test(m);
237
+ if (!tk && !(/\d/.test(m) && /[a-f]/.test(m)))
238
+ return m;
239
+ if (tk && !LIN)
240
+ return m;
241
+ out.push(s.slice(last, i), tk ? el("a", { cls: "tk", href: LIN + m, target: "_blank", rel: "noopener" }, m) : el("span", { cls: "mono" }, m.slice(0, 7)));
242
+ last = i + m.length;
243
+ return m;
244
+ });
245
+ out.push(s.slice(last));
246
+ return out;
247
+ };
248
+ const copyText = (t) => {
249
+ const fb = () => {
250
+ const a = el("textarea", { style: "position:absolute;left:-9999px;top:0", "aria-hidden": "true" });
251
+ a.value = t;
252
+ document.body.append(a);
253
+ a.select();
254
+ try {
255
+ document.execCommand("copy");
256
+ } catch (_) {}
257
+ a.remove();
258
+ };
259
+ try {
260
+ navigator.clipboard.writeText(t).catch(fb);
261
+ } catch (_) {
262
+ fb();
263
+ }
264
+ };
265
+ const flash = (lb, t) => {
266
+ if (!lb.dataset.l)
267
+ lb.dataset.l = lb.textContent;
268
+ lb.textContent = t;
269
+ clearTimeout(lb._t);
270
+ lb._t = setTimeout(() => {
271
+ lb.textContent = lb.dataset.l;
272
+ }, 1400);
273
+ };
274
+ const count = (t) => t ? t.split(`
275
+ `).filter(Boolean).length : 0;
276
+ const cut = (s, n) => s.length > n ? s.slice(0, n) + "…" : s;
277
+ const sameSet = (a, b) => a.size === b.size && [...a].every((v) => b.has(v));
278
+ const LAB = { done: "已做", issue: "有问题", no: "没做", you: "你来做" };
279
+ function render(root, spec) {
280
+ root.replaceChildren();
281
+ root.classList.remove("folded", "kb");
282
+ {
283
+ const c = (getComputedStyle(root).color.match(/\d+/g) || [0, 0, 0]).slice(0, 3).map(Number);
284
+ root.classList.toggle("dark", (c[0] * 299 + c[1] * 587 + c[2] * 114) / 1000 > 140);
285
+ }
286
+ LIN = spec.ticketUrl || null;
287
+ const TURN = spec.turn ? String(spec.turn).replace(/[^\w.:-]/g, "") : "";
288
+ const hasSend = typeof sendPrompt === "function";
289
+ const S = { dec: [], act: [], del: [], opt: [] };
290
+ const items = [];
291
+ const bd = el("div", { cls: "bd" });
292
+ const group = (label, hint) => {
293
+ const rs = el("div", { cls: "rs" });
294
+ bd.append(el("div", { cls: "grp" }, el("div", { cls: "gl", title: hint || null }, label), rs));
295
+ return rs;
296
+ };
297
+ const item = (rs, ln, extra) => {
298
+ const it = el("div", { cls: "it" }, ln, ...extra || []);
299
+ rs.append(it);
300
+ items.push(it);
301
+ return it;
302
+ };
303
+ const qcell = (d, text) => {
304
+ const qt = el("span", { cls: "qt" }, ...linkify(text));
305
+ const q = el("div", { cls: "q", title: text || null }, d && d.n != null ? el("span", { cls: "n" }, d.n + ".") : null, d && d.core ? el("span", { cls: "cb", role: "img", "aria-label": "核心决策", title: "核心决策" }) : null, qt);
306
+ return { q, qt };
307
+ };
308
+ const grow = (t) => {
309
+ if (!t.value) {
310
+ t.style.removeProperty("height");
311
+ return;
312
+ }
313
+ t.style.setProperty("height", "auto", "important");
314
+ t.style.setProperty("height", t.scrollHeight + (t.offsetHeight - t.clientHeight) + "px", "important");
315
+ };
316
+ const area = (ph, cls) => {
317
+ const t = el("textarea", { rows: "1", cls: cls || null, placeholder: ph, "aria-label": ph });
318
+ t.addEventListener("input", () => grow(t));
319
+ return t;
320
+ };
321
+ const editor = (st, ph) => {
322
+ const box = el("div", { cls: "ed" });
323
+ const i = area(ph);
324
+ i.addEventListener("input", () => {
325
+ st.text = i.value;
326
+ upd();
327
+ });
328
+ box.append(i);
329
+ box.hidden = true;
330
+ st.ed = box;
331
+ return { box, i, show(on, focus) {
332
+ box.hidden = !on;
333
+ if (on) {
334
+ grow(i);
335
+ if (focus)
336
+ i.focus();
337
+ }
338
+ upd();
339
+ } };
340
+ };
341
+ const txt = (st) => st.ed && !st.ed.hidden ? (st.text || "").trim() : "";
342
+ const seg = (opts, st, o = {}) => {
343
+ const init = o.init === undefined ? null : o.init;
344
+ const w = el("div", { cls: "seg" + (o.cls ? " " + o.cls : ""), role: "radiogroup", "aria-label": o.label || null, title: o.title || null });
345
+ const bs = opts.map((op, i) => el("button", { type: "button", role: "radio", cls: "sg" + (op.rec ? " rec" : ""), "data-col": String(i), title: op.title || null }, op.label, el("span", { cls: "k", "aria-hidden": "true" }, String(i + 1))));
346
+ const paint = () => {
347
+ const idx = opts.findIndex((x) => x.v === st.pick);
348
+ const chg = st.pick !== init;
349
+ bs.forEach((b, i) => {
350
+ b.setAttribute("aria-checked", String(i === idx));
351
+ b.classList.toggle("chg", i === idx && chg);
352
+ b.tabIndex = i === (idx < 0 ? 0 : idx) ? 0 : -1;
353
+ });
354
+ };
355
+ const set = (v, kb) => {
356
+ st.pick = v;
357
+ paint();
358
+ if (o.onChange)
359
+ o.onChange(kb);
360
+ upd();
361
+ };
362
+ const choose = (i, kb) => {
363
+ if (opts[i])
364
+ set(o.toggle && st.pick === opts[i].v ? null : opts[i].v, kb);
365
+ };
366
+ bs.forEach((b, i) => b.addEventListener("click", () => choose(i, false)));
367
+ w.addEventListener("keydown", (e) => {
368
+ if (e.key !== "ArrowRight" && e.key !== "ArrowLeft")
369
+ return;
370
+ e.preventDefault();
371
+ const c = Math.max(0, bs.indexOf(document.activeElement));
372
+ const n = (c + (e.key === "ArrowRight" ? 1 : -1) + bs.length) % bs.length;
373
+ set(opts[n].v, true);
374
+ bs[n].focus();
375
+ });
376
+ paint();
377
+ w.append(...bs);
378
+ return { w, set, choose, focus: () => (bs.find((b) => b.tabIndex === 0) || bs[0]).focus() };
379
+ };
380
+ const check = (label, on, o = {}) => {
381
+ const i = el("input", { type: "checkbox" });
382
+ i.checked = !!on;
383
+ const lb = el("label", { cls: "ck" + (o.rec ? " rec" : ""), title: o.title || null }, i, el("span", {}, label));
384
+ return { lb, i };
385
+ };
386
+ const multi = (labels, recs, st, initOn) => {
387
+ const w = el("div", { cls: "ctl", role: "group" });
388
+ const cs = labels.map((l, i) => check(l, initOn.has(i), { rec: recs.includes(i), title: recs.includes(i) ? "建议" : null }));
389
+ const paint = () => cs.forEach((c, i) => c.lb.classList.toggle("chg", st.sel.has(i) !== initOn.has(i)));
390
+ cs.forEach((c, i) => c.i.addEventListener("change", () => {
391
+ c.i.checked ? st.sel.add(i) : st.sel.delete(i);
392
+ paint();
393
+ upd();
394
+ }));
395
+ w.append(...cs.map((c) => c.lb));
396
+ return { w, set: (s) => {
397
+ st.sel = new Set(s);
398
+ cs.forEach((c, i) => {
399
+ c.i.checked = st.sel.has(i);
400
+ });
401
+ paint();
402
+ upd();
403
+ }, toggle: (i) => {
404
+ if (cs[i])
405
+ cs[i].i.click();
406
+ }, focus: () => cs[0] && cs[0].i.focus() };
407
+ };
408
+ const ghost = (label, o = {}) => el("button", { type: "button", cls: "gh", title: o.title || null }, o.icon ? icon(o.icon) : null, label ? el("span", {}, label) : null);
409
+ const groups = [["本轮拍板", "需要你拍板", (d) => d.group === "now"], ["早前", "上轮按默认处理(勾「推翻」才回复)与早前尚未决策(默认不回复)", (d) => d.group !== "now"]];
410
+ groups.forEach(([label, hint, f]) => {
411
+ const ds = (spec.decisions || []).filter(f).sort((a, b) => a.n - b.n);
412
+ if (!ds.length)
413
+ return;
414
+ const rs = group(label, hint);
415
+ ds.forEach((d) => {
416
+ const st = { pick: null, text: "" };
417
+ const x = { d, st };
418
+ S.dec.push(x);
419
+ const { q } = qcell(d, d.q);
420
+ const extra = [];
421
+ let ctl, pick, focus, note = null;
422
+ if (d.group === "defaulted") {
423
+ const ed = editor(st, "改成什么");
424
+ const c = check("推翻", false, { title: "推翻上轮的默认处理" });
425
+ c.i.addEventListener("change", () => {
426
+ st.pick = c.i.checked ? "over" : null;
427
+ c.lb.classList.toggle("chg", c.i.checked);
428
+ ed.show(c.i.checked, true);
429
+ });
430
+ ctl = el("div", { cls: "ctl" }, c.lb);
431
+ extra.push(ed.box);
432
+ pick = (i) => {
433
+ if (i === 0)
434
+ c.i.click();
435
+ };
436
+ focus = () => c.i.focus();
437
+ ed.i.__esc = () => c.i.focus();
438
+ x.changed = () => st.pick === "over";
439
+ x.sum = () => "推翻";
440
+ } else if (d.ask) {
441
+ const inp = area(d.ph || "填写;要附文件就留空,到输入框里附", "ask");
442
+ inp.addEventListener("input", () => {
443
+ st.text = inp.value;
444
+ upd();
445
+ });
446
+ ctl = inp;
447
+ x.top = true;
448
+ pick = () => {};
449
+ focus = () => inp.focus();
450
+ x.changed = () => !!(st.text || "").trim();
451
+ x.sum = () => "已填";
452
+ } else if (d.multi) {
453
+ const os = d.opts || [];
454
+ const recs = Array.isArray(d.rec) ? d.rec : d.rec != null ? [d.rec] : [];
455
+ const initOn = new Set(d.group === "now" ? recs : []);
456
+ st.sel = new Set(initOn);
457
+ x.init = initOn;
458
+ const m = multi(os, recs, st, initOn);
459
+ const ed = editor(st, "附一句;不勾选项时即为你的回复");
460
+ note = () => {
461
+ const on = ed.box.hidden;
462
+ ed.show(on, true);
463
+ if (!on)
464
+ m.focus();
465
+ };
466
+ ctl = m.w;
467
+ extra.push(ed.box);
468
+ x.reset = () => m.set(initOn);
469
+ pick = (i) => m.toggle(i);
470
+ focus = m.focus;
471
+ ed.i.__esc = () => {
472
+ ed.show(false);
473
+ m.focus();
474
+ };
475
+ x.changed = () => !sameSet(st.sel, initOn) || !!txt(st);
476
+ x.sum = () => {
477
+ const s = [...st.sel].sort((a, b) => a - b).map((i) => os[i]);
478
+ return (s.length ? s.join("、") : "都不选") + (txt(st) ? "(附言)" : "");
479
+ };
480
+ } else {
481
+ const os = d.opts || [];
482
+ const opts = os.map((l, i) => ({ v: "o" + i, label: l, rec: i === d.rec, title: i === d.rec ? "建议;再点一次即不回复" : "再点一次即不回复" }));
483
+ st.pick = d.group === "now" && os[d.rec] != null ? "o" + d.rec : null;
484
+ x.init = st.pick;
485
+ const sg = seg(opts, st, { label: d.q, init: x.init, toggle: true, cls: "dseg", title: d.def || null });
486
+ const ed = editor(st, "附一句;不选选项时即为你的回复");
487
+ note = () => {
488
+ const on = ed.box.hidden;
489
+ ed.show(on, true);
490
+ if (!on)
491
+ sg.focus();
492
+ };
493
+ ctl = el("div", { cls: "ctl" }, sg.w);
494
+ extra.push(ed.box);
495
+ x.reset = () => sg.set(x.init);
496
+ pick = (i) => sg.choose(i, false);
497
+ focus = sg.focus;
498
+ ed.i.__esc = () => {
499
+ ed.show(false);
500
+ sg.focus();
501
+ };
502
+ x.changed = () => st.pick !== x.init || !!txt(st);
503
+ x.sum = () => (st.pick ? os[+st.pick.slice(1)] : "不回复") + (txt(st) ? "(附言)" : "");
504
+ }
505
+ const ln = el("div", { cls: "ln" + (x.top ? " top" : "") }, q, ctl);
506
+ const it = item(rs, ln, extra);
507
+ if (note) {
508
+ ln.addEventListener("click", (e) => {
509
+ if (e.target.closest("button,input,textarea,label,a,.ctl"))
510
+ return;
511
+ note();
512
+ });
513
+ it.__note = note;
514
+ }
515
+ if (d.core)
516
+ it.classList.add("core");
517
+ it.__pick = pick;
518
+ it.__focus = focus;
519
+ x.it = it;
520
+ });
521
+ });
522
+ if (spec.actions && spec.actions.length) {
523
+ const rs = group("你要做的", "做完后在这里回执");
524
+ spec.actions.forEach((a) => {
525
+ const st = { pick: null, text: "" };
526
+ const ed = editor(st, "贴结果、报错或原因");
527
+ const opts = [["done", "已做"], ["issue", "有问题"], ["no", "没做"], ["you", "你来做"]].map(([v, label]) => ({ v, label }));
528
+ const sg = seg(opts, st, { toggle: true, init: null, label: a.short || a.text, onChange: (kb) => {
529
+ const on = st.pick === "issue" || st.pick === "no";
530
+ ed.box.hidden = !on;
531
+ if (on) {
532
+ grow(ed.i);
533
+ if (!kb)
534
+ ed.i.focus();
535
+ }
536
+ } });
537
+ let cp = null;
538
+ if (a.cmd) {
539
+ cp = ghost("复制命令", { icon: "copy", title: a.cmd });
540
+ const lb = cp.querySelector("span");
541
+ cp.addEventListener("click", () => {
542
+ copyText(a.cmd);
543
+ flash(lb, "已复制");
544
+ });
545
+ }
546
+ const { q } = qcell(null, a.text);
547
+ const it = item(rs, el("div", { cls: "ln" }, q, el("div", { cls: "ctl" }, sg.w, cp)), [ed.box]);
548
+ it.__pick = (i) => sg.choose(i, false);
549
+ it.__focus = sg.focus;
550
+ ed.i.__esc = sg.focus;
551
+ S.act.push({ a, st, it });
552
+ });
553
+ }
554
+ const dl = spec.delivery;
555
+ const optl = spec.optional || [];
556
+ if (dl || optl.length) {
557
+ const rs = group("收尾");
558
+ if (dl) {
559
+ const cs = [];
560
+ (dl.toggles || []).forEach((t) => {
561
+ const x = { t, init: !!t.rec, st: { on: !!t.rec } };
562
+ const c = check(t.label, x.init, { rec: t.rec, title: t.rec ? "建议;取消勾选即不表态" : "勾选才表态" });
563
+ c.i.addEventListener("change", () => {
564
+ x.st.on = c.i.checked;
565
+ c.lb.classList.toggle("chg", x.st.on !== x.init);
566
+ upd();
567
+ });
568
+ S.del.push(x);
569
+ cs.push(c);
570
+ });
571
+ const { q } = qcell(null, dl.info || "");
572
+ q.classList.add("info");
573
+ const it = item(rs, el("div", { cls: "ln" }, q, el("div", { cls: "ctl" }, ...cs.map((c) => c.lb))));
574
+ it.__pick = (i) => {
575
+ if (cs[i])
576
+ cs[i].i.click();
577
+ };
578
+ it.__focus = () => {
579
+ if (cs[0])
580
+ cs[0].i.focus();
581
+ };
582
+ S.delIt = it;
583
+ }
584
+ optl.forEach((o) => {
585
+ const st = { on: false };
586
+ const c = check("也做", false);
587
+ c.i.addEventListener("change", () => {
588
+ st.on = c.i.checked;
589
+ c.lb.classList.toggle("chg", st.on);
590
+ upd();
591
+ });
592
+ const { q } = qcell(null, o.text);
593
+ const it = item(rs, el("div", { cls: "ln" }, q, el("div", { cls: "ctl" }, c.lb)));
594
+ it.__pick = (i) => {
595
+ if (i === 0)
596
+ c.i.click();
597
+ };
598
+ it.__focus = () => c.i.focus();
599
+ S.opt.push({ o, st, it });
600
+ });
601
+ }
602
+ const fmt = (head, t, ind) => {
603
+ let ls = String(t).split(`
604
+ `).map((l) => l.replace(/\s+$/, ""));
605
+ while (ls.length && !ls[0])
606
+ ls.shift();
607
+ while (ls.length && !ls[ls.length - 1])
608
+ ls.pop();
609
+ ls = ls.filter((l, k) => l || ls[k - 1]);
610
+ if (ls.length <= 1)
611
+ return head + (ls[0] || "");
612
+ const pad = " ".repeat(ind);
613
+ return head + ls[0] + `
614
+ ` + ls.slice(1).map((l) => pad + l).join(`
615
+ `);
616
+ };
617
+ const line = (x) => {
618
+ const { d, st } = x, t = txt(st), h = d.n + ". ", w = h.length;
619
+ if (d.ask) {
620
+ const v = (st.text || "").trim();
621
+ return v ? fmt(h, v, w) : null;
622
+ }
623
+ if (d.group === "defaulted")
624
+ return st.pick === "over" ? fmt(h + "推翻:", t || "(待补充)", w) : null;
625
+ if (d.multi) {
626
+ const s = [...st.sel].sort((a, b) => a - b).map((i) => d.opts[i]);
627
+ if (s.length)
628
+ return fmt(h + s.join("、") + (t ? "," : ""), t, w);
629
+ if (x.init.size)
630
+ return fmt(h + "都不选" + (t ? "," : ""), t, w);
631
+ return t ? fmt(h, t, w) : null;
632
+ }
633
+ if (st.pick && st.pick[0] === "o")
634
+ return fmt(h + d.opts[+st.pick.slice(1)] + (t ? "," : ""), t, w);
635
+ return t ? fmt(h, t, w) : null;
636
+ };
637
+ const put = (L, arr) => {
638
+ const sep = arr.some((v) => v.includes(`
639
+ `));
640
+ arr.forEach((v, k) => {
641
+ if (sep && k)
642
+ L.push("");
643
+ L.push(v);
644
+ });
645
+ return sep;
646
+ };
647
+ function build() {
648
+ const L = [];
649
+ const now = S.dec.filter((x) => x.d.group !== "pending").map(line).filter(Boolean);
650
+ const pend = S.dec.filter((x) => x.d.group === "pending").map(line).filter(Boolean);
651
+ if (now.length || pend.length) {
652
+ L.push("决策:");
653
+ const sep = put(L, now);
654
+ if (pend.length) {
655
+ if (sep || pend.some((v) => v.includes(`
656
+ `)))
657
+ L.push("");
658
+ L.push("--早前尚未决策--");
659
+ put(L, pend);
660
+ }
661
+ }
662
+ const act = S.act.filter((x) => x.st.pick);
663
+ if (act.length) {
664
+ if (L.length)
665
+ L.push("");
666
+ L.push("反馈:");
667
+ put(L, act.map((x) => {
668
+ const t = txt(x.st);
669
+ return fmt("- " + x.a.short + ":" + LAB[x.st.pick] + (t ? ":" : ""), t, 2);
670
+ }));
671
+ }
672
+ const del = S.del.filter((x) => x.st.on).map((x) => x.t.label);
673
+ if (del.length) {
674
+ if (L.length)
675
+ L.push("");
676
+ L.push("交付:" + del.join(","));
677
+ }
678
+ const opt = S.opt.filter((x) => x.st.on);
679
+ if (opt.length) {
680
+ if (L.length)
681
+ L.push("");
682
+ opt.forEach((x) => L.push("也做:" + x.o.text));
683
+ }
684
+ return L.join(`
685
+ `);
686
+ }
687
+ const devs = () => {
688
+ const a = [];
689
+ S.dec.forEach((x) => {
690
+ if (x.changed())
691
+ a.push(x.d.n + " " + x.sum());
692
+ });
693
+ S.act.forEach((x) => {
694
+ if (x.st.pick)
695
+ a.push(x.a.short + ":" + LAB[x.st.pick]);
696
+ });
697
+ S.del.forEach((x) => {
698
+ if (x.st.on !== x.init)
699
+ a.push((x.st.on ? "" : "不") + x.t.label);
700
+ });
701
+ S.opt.forEach((x) => {
702
+ if (x.st.on)
703
+ a.push("也做 " + cut(x.o.text, 10));
704
+ });
705
+ return a;
706
+ };
707
+ const wrap = (t) => t ? "<turn-reply" + (TURN ? ' turn="' + TURN + '"' : "") + `>
708
+ ` + t + `
709
+ </turn-reply>` : t;
710
+ const nowDec = S.dec.filter((x) => x.reset && x.d.group === "now");
711
+ let allRec = null;
712
+ if (nowDec.length) {
713
+ allRec = ghost("全部按建议", { icon: "reset", title: "把本轮拍板恢复为建议项" });
714
+ allRec.addEventListener("click", () => nowDec.forEach((x) => x.reset()));
715
+ }
716
+ const cnt = el("span", {});
717
+ const pv = el("button", { type: "button", cls: "lk", "aria-expanded": "false" }, "预览");
718
+ const sum = el("span", { cls: "sum", "aria-live": "polite" }, cnt, pv);
719
+ const pre = el("pre", { cls: "pv" });
720
+ pre.hidden = true;
721
+ const closePre = () => {
722
+ pre.hidden = true;
723
+ pv.textContent = "预览";
724
+ pv.setAttribute("aria-expanded", "false");
725
+ };
726
+ pv.addEventListener("click", () => {
727
+ if (pre.hidden) {
728
+ pre.hidden = false;
729
+ pv.textContent = "收起";
730
+ pv.setAttribute("aria-expanded", "true");
731
+ } else
732
+ closePre();
733
+ });
734
+ const cpLb = el("span", {}, "复制");
735
+ const cp = el("button", { type: "button", cls: "btn" }, cpLb);
736
+ cp.addEventListener("click", () => {
737
+ const t = build();
738
+ if (t) {
739
+ copyText(wrap(t));
740
+ flash(cpLb, "已复制");
741
+ }
742
+ });
743
+ let go = null;
744
+ if (hasSend) {
745
+ go = el("button", { type: "button", cls: "btn pri" }, "填入输入框");
746
+ go.addEventListener("click", (e) => {
747
+ e.stopPropagation();
748
+ fill();
749
+ });
750
+ } else {
751
+ cp.classList.add("pri");
752
+ }
753
+ const foot = el("div", { cls: "foot" }, allRec, sum, cp, go);
754
+ const fsum = el("span", { cls: "fs" });
755
+ const fx = el("button", { type: "button", cls: "lk" }, "展开");
756
+ const fold = el("div", { cls: "fold" }, el("span", { cls: "mk-ok", "aria-hidden": "true" }), fsum, fx);
757
+ const setFold = (on) => {
758
+ root.classList.toggle("folded", on);
759
+ if (on)
760
+ closePre();
761
+ else if (root.classList.contains("kb") && items[0])
762
+ items[0].__focus();
763
+ };
764
+ fold.addEventListener("click", () => setFold(false));
765
+ function fill() {
766
+ const t = build();
767
+ if (!t)
768
+ return;
769
+ sendPrompt(wrap(t));
770
+ const dv = devs();
771
+ fsum.textContent = "已填入 · " + (dv.length ? dv.join(" · ") : "全部按建议");
772
+ fsum.title = fsum.textContent;
773
+ setFold(true);
774
+ }
775
+ const primary = () => {
776
+ if (hasSend)
777
+ fill();
778
+ else
779
+ cp.click();
780
+ };
781
+ root.addEventListener("mousedown", () => root.classList.remove("kb"));
782
+ root.addEventListener("keydown", (e) => {
783
+ if (e.key === "Tab" || e.key.startsWith("Arrow") || /^[0-9]$/.test(e.key))
784
+ root.classList.add("kb");
785
+ if (root.classList.contains("folded"))
786
+ return;
787
+ const tg = e.target;
788
+ if (tg.tagName === "TEXTAREA") {
789
+ if (e.isComposing || e.keyCode === 229)
790
+ return;
791
+ if (e.key === "Escape" && tg.__esc) {
792
+ e.preventDefault();
793
+ tg.__esc();
794
+ }
795
+ return;
796
+ }
797
+ if (e.metaKey || e.ctrlKey || e.altKey)
798
+ return;
799
+ const it = tg.closest && tg.closest(".it");
800
+ if (!it)
801
+ return;
802
+ if (e.key === "/" && it.__note) {
803
+ e.preventDefault();
804
+ it.__note();
805
+ return;
806
+ }
807
+ if (/^[1-9]$/.test(e.key) && it.__pick) {
808
+ e.preventDefault();
809
+ it.__pick(+e.key - 1);
810
+ return;
811
+ }
812
+ if (e.key === "ArrowDown" || e.key === "ArrowUp") {
813
+ const i = items.indexOf(it);
814
+ const nx = items[i + (e.key === "ArrowDown" ? 1 : -1)];
815
+ if (nx) {
816
+ e.preventDefault();
817
+ nx.__focus();
818
+ }
819
+ }
820
+ });
821
+ root.append(fold, bd, foot, pre);
822
+ function upd() {
823
+ const t = build();
824
+ const n = count(t);
825
+ const dv = devs();
826
+ S.dec.forEach((x) => x.it.classList.toggle("chg", x.changed()));
827
+ S.act.forEach((x) => x.it.classList.toggle("chg", !!x.st.pick));
828
+ if (S.delIt)
829
+ S.delIt.classList.toggle("chg", S.del.some((x) => x.st.on !== x.init));
830
+ S.opt.forEach((x) => x.it.classList.toggle("chg", x.st.on));
831
+ const parts = [];
832
+ parts.push(dv.length ? "改了 " : "全部按建议", ...dv.length ? [el("b", {}, String(dv.length)), " 项"] : []);
833
+ if (n)
834
+ parts.push(" · 将填入 ", el("b", {}, String(n)), " 行");
835
+ else
836
+ parts.push(" · 没有要回复的内容");
837
+ cnt.replaceChildren(...parts);
838
+ pre.textContent = wrap(t);
839
+ pv.hidden = !n;
840
+ if (!n)
841
+ closePre();
842
+ cp.disabled = !n;
843
+ if (go)
844
+ go.disabled = !n;
845
+ if (allRec)
846
+ allRec.disabled = nowDec.every((x) => !x.changed());
847
+ }
848
+ upd();
849
+ const cw = {};
850
+ const dbs = [...root.querySelectorAll(".dseg button.sg")];
851
+ dbs.forEach((b) => {
852
+ const c = b.dataset.col;
853
+ cw[c] = Math.max(cw[c] || 0, b.offsetWidth);
854
+ });
855
+ dbs.forEach((b) => {
856
+ b.style.setProperty("width", Math.ceil(cw[b.dataset.col]) + 12 + "px", "important");
857
+ });
858
+ root.classList.add("measuring");
859
+ let m = 0;
860
+ root.querySelectorAll(".q").forEach((q) => {
861
+ m = Math.max(m, q.offsetWidth);
862
+ });
863
+ root.classList.remove("measuring");
864
+ if (m > 0)
865
+ root.style.setProperty("--qw", Math.min(Math.ceil(m) + 2, 260) + "px");
866
+ }
867
+ return render;
868
+ })();
869
+
870
+ // src/index.js
871
+ var version = "0.1.0";
872
+ var STYLE_ID = "trw-style-" + version;
873
+ function injectCSS(root) {
874
+ const d = root.ownerDocument || document;
875
+ if (d.getElementById(STYLE_ID))
876
+ return;
877
+ const s = d.createElement("style");
878
+ s.id = STYLE_ID;
879
+ s.textContent = css_default;
880
+ (d.head || root.parentNode || d.documentElement).appendChild(s);
881
+ }
882
+ function fail(root, msg) {
883
+ root.replaceChildren();
884
+ root.classList.remove("folded", "kb");
885
+ const p = (root.ownerDocument || document).createElement("div");
886
+ p.className = "err";
887
+ p.setAttribute("role", "alert");
888
+ p.title = msg;
889
+ p.textContent = msg;
890
+ root.append(p);
891
+ }
892
+ var TAIL = ",请直接在输入框回复";
893
+ function render(root, spec) {
894
+ if (!root || typeof root.append !== "function") {
895
+ console.error("[turn-reply] root 不是元素");
896
+ return ["root 不是元素"];
897
+ }
898
+ root.classList.add("trw");
899
+ injectCSS(root);
900
+ let s = spec;
901
+ if (typeof s === "string") {
902
+ try {
903
+ s = JSON.parse(s);
904
+ } catch (x) {
905
+ fail(root, "面板数据不是合法 JSON" + TAIL);
906
+ return ["JSON 解析失败"];
907
+ }
908
+ }
909
+ const errs = validate(s);
910
+ if (errs.length) {
911
+ console.error(`[turn-reply] spec 不合法:
912
+ ` + errs.join(`
913
+ `));
914
+ fail(root, "面板数据不合法(" + errs.length + " 处,首处 " + errs[0] + ")" + TAIL);
915
+ return errs;
916
+ }
917
+ try {
918
+ renderPanel(root, s);
919
+ } catch (x) {
920
+ console.error("[turn-reply] 渲染出错", x);
921
+ const m = "面板渲染出错(" + (x && x.message || x) + ")" + TAIL;
922
+ fail(root, m);
923
+ return [m];
924
+ }
925
+ return [];
926
+ }
927
+
928
+ // src/entry.js
929
+ var g = typeof window !== "undefined" ? window : globalThis;
930
+ if (!g.TR || g.TR.version !== version)
931
+ g.TR = { render, validate, version, css: css_default };
932
+ })();
package/dist/tr.min.js ADDED
@@ -0,0 +1,13 @@
1
+ /*! @npmjsdnt/turn-reply@0.1.0 turn-reply panel */
2
+ (()=>{var nt=".trw{--c-bg:var(--surface-2);--c-sunken:var(--surface-1);--c-hover:var(--fill-ghost-hover,var(--surface-1));--c-soft:var(--fill-ghost-selected,var(--surface-1));--c-solid:var(--fill-primary,var(--text-primary));--c-on-solid:var(--on-primary,var(--surface-2));--c-line:var(--border);--c-line-s:var(--border-strong);--c-line-x:var(--border-stronger,var(--border-strong));--c-ink1:var(--text-primary);--c-ink2:var(--text-secondary);--c-ink3:var(--text-muted);--c-ink4:var(--text-disabled,var(--text-muted));--c-attn:var(--text-warning);--c-ok:var(--text-success);--c-focus:var(--border-accent,var(--text-accent));--c-r:6px;--c-track:color-mix(in srgb,var(--c-ink1,currentColor) 5%,transparent);--c-lift:var(--surface-3,var(--surface-2));--c-hov:color-mix(in srgb,var(--c-ink1,currentColor) 4%,transparent);container-type:inline-size;position:relative;box-sizing:border-box;font-family:var(--font-sans);font-size:13px;line-height:20px;font-weight:400;font-variant-numeric:tabular-nums;-webkit-font-smoothing:antialiased;color:var(--c-ink1);background:transparent;border:0;border-radius:0;padding:0}.trw.dark{--c-lift:color-mix(in srgb,var(--c-ink1,currentColor) 15%,transparent);--c-hov:color-mix(in srgb,var(--c-ink1,currentColor) 8%,transparent)}.trw *,.trw *::before,.trw *::after{box-sizing:border-box}.trw [hidden]{display:none!important}.trw .mono{font-family:var(--font-mono);font-size:12px}.trw .grp{display:flex;align-items:flex-start;padding:6px 0;border-top:0.5px solid var(--c-line)}.trw .bd>.grp:first-child{border-top:0}.trw .gl{flex:0 0 60px;padding-top:6px;font-size:11px;line-height:16px;color:var(--c-ink2);white-space:nowrap;cursor:default}.trw .rs{flex:1 1 auto;min-width:0}.trw .it{margin:0 -6px;padding:0 6px;border-radius:0}.trw .it:hover,.trw.kb .it:focus-within{background:var(--c-hover)}.trw .ln{display:flex;flex-wrap:wrap;align-items:center;gap:2px 8px;min-height:28px}.trw .bd>.grp:first-child .it:first-child .ln{padding-right:40px}.trw .q{flex:0 0 var(--qw,240px);min-width:0;display:flex;align-items:center;gap:6px;white-space:nowrap;overflow:hidden}.trw.measuring .q{flex:none!important;width:max-content!important}.trw .qt{min-width:0;overflow:hidden;text-overflow:ellipsis}.trw .n{flex:none;min-width:14px;color:var(--c-ink2)}.trw .it.core .qt{font-weight:500}.trw .q.info .qt{font-size:12px;color:var(--c-ink2)}.trw a.tk{font-family:var(--font-mono);font-size:12px;color:var(--c-ink1);text-decoration:underline;text-decoration-color:var(--c-line-x);text-underline-offset:2px}.trw .ctl{flex:none;display:flex;flex-wrap:wrap;align-items:center;gap:4px 6px;padding:0 4px;margin:0 -4px}.trw .cb{flex:none;width:9px;height:9px;background:var(--c-attn);clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%)}.trw .seg{display:inline-flex;align-items:center;gap:2px;height:26px;padding:2px;border:0;border-radius:7px;background:var(--c-track)}.trw button.sg{position:relative;font-family:inherit!important;font-size:12px!important;font-weight:400!important;line-height:20px!important;height:22px!important;min-height:0!important;margin:0!important;padding:0 9px!important;border:0!important;border-radius:5px!important;background:transparent!important;color:var(--c-ink2)!important;box-shadow:none!important;cursor:pointer;white-space:nowrap;text-align:center;justify-content:center}.trw button.sg[aria-checked=\"false\"]:hover{background:var(--c-hov)!important;color:var(--c-ink1)!important}.trw .ck.rec>span::before{content:\"\";display:inline-block;width:4px;height:4px;border-radius:50%;background:currentColor;margin-right:5px;vertical-align:2px}.trw button.sg.rec{padding:0 4px 0 14px!important}.trw button.sg.rec::before{content:\"\";position:absolute;left:6px;top:50%;width:4px;height:4px;margin-top:-2px;border-radius:50%;background:currentColor;opacity:.4}.trw button.sg.sk{color:var(--c-ink3)!important}.trw button.sg[aria-checked=\"true\"]{background:var(--c-lift)!important;color:var(--c-ink1)!important;box-shadow:none!important}.trw .dseg button.sg[aria-checked=\"true\"]:hover::before{content:\"×\";position:absolute;left:4px;top:0;width:8px;height:auto;margin:0;border-radius:0;background:none;line-height:22px;text-align:center;opacity:1;color:var(--c-ink3)}.trw .k{display:none;position:absolute;top:-8px;right:-4px;font:11px/14px var(--font-mono);padding:0 3px;border-radius:4px;background:var(--c-bg);color:var(--c-ink3);border:0.5px solid var(--c-line-s);pointer-events:none;z-index:1}.trw.kb .it:focus-within .k{display:block}.trw .ck{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 6px;border-radius:var(--c-r);font-size:12px;color:var(--c-ink2);cursor:pointer;white-space:nowrap;user-select:none}.trw .ck:hover{background:var(--c-hover);color:var(--c-ink1)}.trw .ck input{width:13px;height:13px;margin:0;accent-color:var(--c-solid);cursor:pointer}.trw .ck:has(input:checked){color:var(--c-ink1)}.trw button.gh{display:inline-flex;align-items:center;gap:5px;font-family:inherit!important;font-size:12px!important;font-weight:500!important;line-height:20px!important;height:26px!important;min-height:0!important;margin:0!important;padding:0 8px!important;border:0.5px solid transparent!important;border-radius:var(--c-r)!important;background:transparent!important;color:var(--c-ink2)!important;box-shadow:none!important;cursor:pointer;white-space:nowrap}.trw button.gh:hover{background:var(--c-hover)!important;color:var(--c-ink1)!important}.trw svg.i{width:14px;height:14px;flex:none;fill:none;stroke:currentColor;stroke-width:1.3;stroke-linecap:round;stroke-linejoin:round}.trw .ed{display:flex;padding:4px 0 8px calc(var(--qw,240px) + 8px)}.trw .it:last-child>.ed{padding-bottom:4px}.trw .ed textarea,.trw textarea.ask{display:block;flex:1;min-width:0;min-height:28px;height:28px;resize:none!important;overflow:hidden;margin:0!important;padding:4px 10px!important;font:12px/18px var(--font-sans,system-ui)!important;white-space:pre-wrap;overflow-wrap:anywhere;border:0.5px solid var(--c-line-s)!important;border-radius:var(--c-r)!important;background:var(--c-bg)!important;color:var(--c-ink1)!important;box-shadow:none!important}.trw .ed textarea::placeholder,.trw textarea.ask::placeholder{color:var(--c-ink3)}.trw textarea.ask{flex:1 1 160px;min-height:26px;height:26px;padding:3px 10px!important}.trw .ln.top{align-items:flex-start}.trw .ln.top .q{min-height:26px}.trw .foot{display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;padding:8px 0 2px;border-top:0.5px solid var(--c-line)}.trw .sum{flex:1 1 auto;display:inline-flex;align-items:center;gap:8px;font-size:12px;line-height:18px;color:var(--c-ink3);white-space:nowrap}.trw .sum b{font-weight:500;color:var(--c-ink2)}.trw button.lk{font-family:inherit!important;font-size:12px!important;font-weight:400!important;line-height:18px!important;height:auto!important;min-height:0!important;margin:0!important;padding:0 2px!important;border:0!important;border-radius:4px!important;background:transparent!important;color:var(--c-ink2)!important;box-shadow:none!important;cursor:pointer;text-decoration:underline;text-decoration-color:var(--c-line-x);text-underline-offset:3px}.trw button.btn{display:inline-flex;align-items:center;gap:6px;font-family:inherit!important;font-size:12px!important;font-weight:500!important;line-height:20px!important;height:28px!important;min-height:0!important;margin:0!important;padding:0 12px!important;border:0.5px solid transparent!important;border-radius:var(--c-r)!important;background:transparent!important;color:var(--c-ink2)!important;box-shadow:none!important;cursor:pointer;white-space:nowrap}.trw button.btn:hover{background:var(--c-hover)!important;color:var(--c-ink1)!important}.trw button.btn.pri{border-color:var(--c-line-x)!important;color:var(--c-ink1)!important}.trw button.btn:disabled,.trw button.gh:disabled{color:var(--c-ink4)!important;background:transparent!important;cursor:default}.trw pre.pv{font:12px/18px var(--font-mono);white-space:pre-wrap;overflow-wrap:anywhere;background:var(--c-sunken);padding:8px 10px;border-radius:var(--c-r);margin:0 0 8px;color:var(--c-ink2)}.trw .fold{display:none;align-items:center;gap:6px;min-height:34px;font-size:12px;color:var(--c-ink2);cursor:pointer;padding:0 40px 0 6px;margin:0 -6px}.trw .fold .fs{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trw .mk-ok{flex:none;width:10px;height:8px;background:var(--c-ok);clip-path:polygon(0 56%,15% 38%,38% 62%,85% 0,100% 19%,38% 100%)}.trw.folded .fold{display:flex}.trw.folded>:not(.fold){display:none!important}.trw.folded:hover{background:var(--c-hover);border-radius:0}.trw button:focus-visible{outline:2px solid var(--c-focus)!important;outline-offset:-2px}.trw .ed textarea:focus,.trw textarea.ask:focus{outline:none!important;border-color:var(--c-focus)!important;box-shadow:inset 0 0 0 1px var(--c-focus)!important}@container (max-width:480px){.trw .grp{display:block}.trw .ln{flex-wrap:wrap;row-gap:2px;padding-bottom:2px}.trw .q{flex:1 1 auto;white-space:normal}.trw .ed{padding-left:0}}.trw .err{padding:6px 0;font-size:12px;line-height:18px;color:var(--c-attn);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}";var z=(n,l=1/0,m=1)=>typeof n==="string"&&n.length>=m&&n.length<=l,H=(n,l,m,y)=>{for(let s of Object.keys(n))if(!l.includes(s))y.push(`${m}.${s} 未定义的字段`)};function rt(n){let l=[];if(!n||typeof n!=="object"||Array.isArray(n))return["$ 不是对象"];if(H(n,["v","turn","ticketUrl","decisions","actions","delivery","optional"],"$",l),n.v!==1)l.push("$.v 必须为 1");if(!z(n.turn,40)||!/^[\w.:-]+$/.test(n.turn))l.push("$.turn 缺失或含非法字符");if(n.ticketUrl!==void 0&&!(z(n.ticketUrl)&&n.ticketUrl.startsWith("https://")))l.push("$.ticketUrl 须为 https:// 前缀");let m=new Set;(n.decisions??[]).forEach((s,x)=>{let f=`$.decisions[${x}]`;if(!s||typeof s!=="object")return l.push(`${f} 不是对象`);if(H(s,["n","group","core","q","opts","rec","def","multi","ask","ph"],f,l),!Number.isInteger(s.n)||s.n<1)l.push(`${f}.n 须为正整数`);else if(m.has(s.n))l.push(`${f}.n=${s.n} 重复`);else m.add(s.n);if(!["now","defaulted","pending"].includes(s.group))l.push(`${f}.group 非法`);if(!z(s.q,40))l.push(`${f}.q 须为 1–40 字`);if(s.core!==void 0&&typeof s.core!=="boolean")l.push(`${f}.core 须为布尔`);if(s.def!==void 0&&!z(s.def,60))l.push(`${f}.def 须为 ≤60 字`);if(s.multi!==void 0&&s.multi!==!0)l.push(`${f}.multi 只能为 true`);if(s.ask!==void 0&&s.ask!==!0)l.push(`${f}.ask 只能为 true`);let N=s.opts;if(N!==void 0&&!(Array.isArray(N)&&N.every((P)=>z(P,12))))l.push(`${f}.opts 须为 1–12 字的字符串数组`);let j=Array.isArray(N)?N.length:0,T=s.group==="defaulted"?"defaulted":s.ask?"ask":s.multi?"multi":"one";if(s.ask&&s.multi)l.push(`${f} ask 与 multi 不能同时出现`);if(T==="defaulted"&&(N||s.rec!==void 0||s.ask||s.multi))l.push(`${f} defaulted 条目只有「推翻」,不带 opts/rec/ask/multi`);if(T==="ask"&&(N||s.rec!==void 0))l.push(`${f} ask 条目不带 opts/rec`);if(s.ph!==void 0&&(T!=="ask"||!z(s.ph,40)))l.push(`${f}.ph 只用于 ask,≤40 字`);if(T==="one"&&(j<2||j>4))l.push(`${f} 单选须有 2–4 个 opts(现 ${j})`);if(T==="multi"&&(j<2||j>8))l.push(`${f} 多选须有 2–8 个 opts(现 ${j})`);if(T==="one"&&s.rec!==void 0&&!(Number.isInteger(s.rec)&&s.rec>=0&&s.rec<j))l.push(`${f}.rec 须为 opts 下标`);if(T==="multi"&&s.rec!==void 0&&!(Array.isArray(s.rec)&&s.rec.every((P)=>Number.isInteger(P)&&P>=0&&P<j)&&new Set(s.rec).size===s.rec.length))l.push(`${f}.rec 须为不重复的 opts 下标数组`);if(Array.isArray(N)&&new Set(N).size!==j)l.push(`${f}.opts 有重复`)});let y=[...m].sort((s,x)=>s-x);if(y.length&&y.some((s,x)=>x&&s!==y[x-1]+1))l.push(`$.decisions 编号不连续:${y.join(",")}`);if((n.actions??[]).forEach((s,x)=>{let f=`$.actions[${x}]`;if(!s||typeof s!=="object")return l.push(`${f} 不是对象`);if(H(s,["text","short","cmd"],f,l),!z(s.text,120))l.push(`${f}.text 须为 1–120 字`);if(!z(s.short,24))l.push(`${f}.short 须为 1–24 字`);if(s.cmd!==void 0&&!z(s.cmd))l.push(`${f}.cmd 须为非空字符串`)}),n.delivery!==void 0){let s=n.delivery;if(!s||typeof s!=="object")l.push("$.delivery 不是对象");else{if(H(s,["info","toggles"],"$.delivery",l),s.info!==void 0&&!z(s.info,120))l.push("$.delivery.info 须为 ≤120 字");(s.toggles??[]).forEach((x,f)=>{if(H(x??{},["label","rec"],`$.delivery.toggles[${f}]`,l),!z(x?.label,20))l.push(`$.delivery.toggles[${f}].label 须为 1–20 字`);if(x?.rec!==void 0&&typeof x.rec!=="boolean")l.push(`$.delivery.toggles[${f}].rec 须为布尔`)})}}(n.optional??[]).forEach((s,x)=>{if(H(s??{},["text"],`$.optional[${x}]`,l),!z(s?.text,120))l.push(`$.optional[${x}].text 须为 1–120 字`)});for(let s of["decisions","actions","optional"])if(n[s]!==void 0&&!Array.isArray(n[s]))l.push(`$.${s} 须为数组`);return l}var zt=(()=>{let n=(p,h={},...E)=>{let b=document.createElement(p);for(let[g,_]of Object.entries(h)){if(_==null||_===!1)continue;if(g==="cls")b.className=_;else b.setAttribute(g,_)}return E.flat().forEach((g)=>{if(g!=null&&g!==!1)b.append(g)}),b},l={copy:'<rect x="5.5" y="5.5" width="7.5" height="7.5" rx="1.2"/><path d="M10.5 3.5V3a.5.5 0 0 0-.5-.5H3a.5.5 0 0 0-.5.5v7a.5.5 0 0 0 .5.5h.5"/>',reset:'<path d="M3.2 8a4.8 4.8 0 1 0 1.4-3.4"/><path d="M3.2 2.6v2.6h2.6"/>'},m=(p)=>{let h=document.createElementNS("http://www.w3.org/2000/svg","svg");return h.setAttribute("viewBox","0 0 16 16"),h.setAttribute("class","i"),h.setAttribute("aria-hidden","true"),h.innerHTML=l[p],h},y=null,s=(p)=>{if(!p)return[];let h=[],E=0;return p.replace(/\b[A-Z]{2,6}-\d+\b|\b[0-9a-f]{7,40}\b/g,(b,g)=>{let _=/^[A-Z]/.test(b);if(!_&&!(/\d/.test(b)&&/[a-f]/.test(b)))return b;if(_&&!y)return b;return h.push(p.slice(E,g),_?n("a",{cls:"tk",href:y+b,target:"_blank",rel:"noopener"},b):n("span",{cls:"mono"},b.slice(0,7))),E=g+b.length,b}),h.push(p.slice(E)),h},x=(p)=>{let h=()=>{let E=n("textarea",{style:"position:absolute;left:-9999px;top:0","aria-hidden":"true"});E.value=p,document.body.append(E),E.select();try{document.execCommand("copy")}catch(b){}E.remove()};try{navigator.clipboard.writeText(p).catch(h)}catch(E){h()}},f=(p,h)=>{if(!p.dataset.l)p.dataset.l=p.textContent;p.textContent=h,clearTimeout(p._t),p._t=setTimeout(()=>{p.textContent=p.dataset.l},1400)},N=(p)=>p?p.split(`
3
+ `).filter(Boolean).length:0,j=(p,h)=>p.length>h?p.slice(0,h)+"…":p,T=(p,h)=>p.size===h.size&&[...p].every((E)=>h.has(E)),P={done:"已做",issue:"有问题",no:"没做",you:"你来做"};function It(p,h){p.replaceChildren(),p.classList.remove("folded","kb");{let t=(getComputedStyle(p).color.match(/\d+/g)||[0,0,0]).slice(0,3).map(Number);p.classList.toggle("dark",(t[0]*299+t[1]*587+t[2]*114)/1000>140)}y=h.ticketUrl||null;let E=h.turn?String(h.turn).replace(/[^\w.:-]/g,""):"",b=typeof sendPrompt==="function",g={dec:[],act:[],del:[],opt:[]},_=[],xt=n("div",{cls:"bd"}),ot=(t,e)=>{let i=n("div",{cls:"rs"});return xt.append(n("div",{cls:"grp"},n("div",{cls:"gl",title:e||null},t),i)),i},Z=(t,e,i)=>{let r=n("div",{cls:"it"},e,...i||[]);return t.append(r),_.push(r),r},X=(t,e)=>{let i=n("span",{cls:"qt"},...s(e));return{q:n("div",{cls:"q",title:e||null},t&&t.n!=null?n("span",{cls:"n"},t.n+"."):null,t&&t.core?n("span",{cls:"cb",role:"img","aria-label":"核心决策",title:"核心决策"}):null,i),qt:i}},st=(t)=>{if(!t.value){t.style.removeProperty("height");return}t.style.setProperty("height","auto","important"),t.style.setProperty("height",t.scrollHeight+(t.offsetHeight-t.clientHeight)+"px","important")},vt=(t,e)=>{let i=n("textarea",{rows:"1",cls:e||null,placeholder:t,"aria-label":t});return i.addEventListener("input",()=>st(i)),i},Y=(t,e)=>{let i=n("div",{cls:"ed"}),r=vt(e);return r.addEventListener("input",()=>{t.text=r.value,D()}),i.append(r),i.hidden=!0,t.ed=i,{box:i,i:r,show(a,o){if(i.hidden=!a,a){if(st(r),o)r.focus()}D()}}},U=(t)=>t.ed&&!t.ed.hidden?(t.text||"").trim():"",wt=(t,e,i={})=>{let r=i.init===void 0?null:i.init,a=n("div",{cls:"seg"+(i.cls?" "+i.cls:""),role:"radiogroup","aria-label":i.label||null,title:i.title||null}),o=t.map((u,w)=>n("button",{type:"button",role:"radio",cls:"sg"+(u.rec?" rec":""),"data-col":String(w),title:u.title||null},u.label,n("span",{cls:"k","aria-hidden":"true"},String(w+1)))),c=()=>{let u=t.findIndex((L)=>L.v===e.pick),w=e.pick!==r;o.forEach((L,O)=>{L.setAttribute("aria-checked",String(O===u)),L.classList.toggle("chg",O===u&&w),L.tabIndex=O===(u<0?0:u)?0:-1})},d=(u,w)=>{if(e.pick=u,c(),i.onChange)i.onChange(w);D()},v=(u,w)=>{if(t[u])d(i.toggle&&e.pick===t[u].v?null:t[u].v,w)};return o.forEach((u,w)=>u.addEventListener("click",()=>v(w,!1))),a.addEventListener("keydown",(u)=>{if(u.key!=="ArrowRight"&&u.key!=="ArrowLeft")return;u.preventDefault();let L=(Math.max(0,o.indexOf(document.activeElement))+(u.key==="ArrowRight"?1:-1)+o.length)%o.length;d(t[L].v,!0),o[L].focus()}),c(),a.append(...o),{w:a,set:d,choose:v,focus:()=>(o.find((u)=>u.tabIndex===0)||o[0]).focus()}},G=(t,e,i={})=>{let r=n("input",{type:"checkbox"});return r.checked=!!e,{lb:n("label",{cls:"ck"+(i.rec?" rec":""),title:i.title||null},r,n("span",{},t)),i:r}},Tt=(t,e,i,r)=>{let a=n("div",{cls:"ctl",role:"group"}),o=t.map((d,v)=>G(d,r.has(v),{rec:e.includes(v),title:e.includes(v)?"建议":null})),c=()=>o.forEach((d,v)=>d.lb.classList.toggle("chg",i.sel.has(v)!==r.has(v)));return o.forEach((d,v)=>d.i.addEventListener("change",()=>{d.i.checked?i.sel.add(v):i.sel.delete(v),c(),D()})),a.append(...o.map((d)=>d.lb)),{w:a,set:(d)=>{i.sel=new Set(d),o.forEach((v,u)=>{v.i.checked=i.sel.has(u)}),c(),D()},toggle:(d)=>{if(o[d])o[d].i.click()},focus:()=>o[0]&&o[0].i.focus()}},bt=(t,e={})=>n("button",{type:"button",cls:"gh",title:e.title||null},e.icon?m(e.icon):null,t?n("span",{},t):null);if([["本轮拍板","需要你拍板",(t)=>t.group==="now"],["早前","上轮按默认处理(勾「推翻」才回复)与早前尚未决策(默认不回复)",(t)=>t.group!=="now"]].forEach(([t,e,i])=>{let r=(h.decisions||[]).filter(i).sort((o,c)=>o.n-c.n);if(!r.length)return;let a=ot(t,e);r.forEach((o)=>{let c={pick:null,text:""},d={d:o,st:c};g.dec.push(d);let{q:v}=X(o,o.q),u=[],w,L,O,K=null;if(o.group==="defaulted"){let k=Y(c,"改成什么"),A=G("推翻",!1,{title:"推翻上轮的默认处理"});A.i.addEventListener("change",()=>{c.pick=A.i.checked?"over":null,A.lb.classList.toggle("chg",A.i.checked),k.show(A.i.checked,!0)}),w=n("div",{cls:"ctl"},A.lb),u.push(k.box),L=(S)=>{if(S===0)A.i.click()},O=()=>A.i.focus(),k.i.__esc=()=>A.i.focus(),d.changed=()=>c.pick==="over",d.sum=()=>"推翻"}else if(o.ask){let k=vt(o.ph||"填写;要附文件就留空,到输入框里附","ask");k.addEventListener("input",()=>{c.text=k.value,D()}),w=k,d.top=!0,L=()=>{},O=()=>k.focus(),d.changed=()=>!!(c.text||"").trim(),d.sum=()=>"已填"}else if(o.multi){let k=o.opts||[],A=Array.isArray(o.rec)?o.rec:o.rec!=null?[o.rec]:[],S=new Set(o.group==="now"?A:[]);c.sel=new Set(S),d.init=S;let C=Tt(k,A,c,S),q=Y(c,"附一句;不勾选项时即为你的回复");K=()=>{let I=q.box.hidden;if(q.show(I,!0),!I)C.focus()},w=C.w,u.push(q.box),d.reset=()=>C.set(S),L=(I)=>C.toggle(I),O=C.focus,q.i.__esc=()=>{q.show(!1),C.focus()},d.changed=()=>!T(c.sel,S)||!!U(c),d.sum=()=>{let I=[...c.sel].sort((ft,Mt)=>ft-Mt).map((ft)=>k[ft]);return(I.length?I.join("、"):"都不选")+(U(c)?"(附言)":"")}}else{let k=o.opts||[],A=k.map((q,I)=>({v:"o"+I,label:q,rec:I===o.rec,title:I===o.rec?"建议;再点一次即不回复":"再点一次即不回复"}));c.pick=o.group==="now"&&k[o.rec]!=null?"o"+o.rec:null,d.init=c.pick;let S=wt(A,c,{label:o.q,init:d.init,toggle:!0,cls:"dseg",title:o.def||null}),C=Y(c,"附一句;不选选项时即为你的回复");K=()=>{let q=C.box.hidden;if(C.show(q,!0),!q)S.focus()},w=n("div",{cls:"ctl"},S.w),u.push(C.box),d.reset=()=>S.set(d.init),L=(q)=>S.choose(q,!1),O=S.focus,C.i.__esc=()=>{C.show(!1),S.focus()},d.changed=()=>c.pick!==d.init||!!U(c),d.sum=()=>(c.pick?k[+c.pick.slice(1)]:"不回复")+(U(c)?"(附言)":"")}let qt=n("div",{cls:"ln"+(d.top?" top":"")},v,w),V=Z(a,qt,u);if(K)qt.addEventListener("click",(k)=>{if(k.target.closest("button,input,textarea,label,a,.ctl"))return;K()}),V.__note=K;if(o.core)V.classList.add("core");V.__pick=L,V.__focus=O,d.it=V})}),h.actions&&h.actions.length){let t=ot("你要做的","做完后在这里回执");h.actions.forEach((e)=>{let i={pick:null,text:""},r=Y(i,"贴结果、报错或原因"),a=[["done","已做"],["issue","有问题"],["no","没做"],["you","你来做"]].map(([u,w])=>({v:u,label:w})),o=wt(a,i,{toggle:!0,init:null,label:e.short||e.text,onChange:(u)=>{let w=i.pick==="issue"||i.pick==="no";if(r.box.hidden=!w,w){if(st(r.i),!u)r.i.focus()}}}),c=null;if(e.cmd){c=bt("复制命令",{icon:"copy",title:e.cmd});let u=c.querySelector("span");c.addEventListener("click",()=>{x(e.cmd),f(u,"已复制")})}let{q:d}=X(null,e.text),v=Z(t,n("div",{cls:"ln"},d,n("div",{cls:"ctl"},o.w,c)),[r.box]);v.__pick=(u)=>o.choose(u,!1),v.__focus=o.focus,r.i.__esc=o.focus,g.act.push({a:e,st:i,it:v})})}let Q=h.delivery,kt=h.optional||[];if(Q||kt.length){let t=ot("收尾");if(Q){let e=[];(Q.toggles||[]).forEach((a)=>{let o={t:a,init:!!a.rec,st:{on:!!a.rec}},c=G(a.label,o.init,{rec:a.rec,title:a.rec?"建议;取消勾选即不表态":"勾选才表态"});c.i.addEventListener("change",()=>{o.st.on=c.i.checked,c.lb.classList.toggle("chg",o.st.on!==o.init),D()}),g.del.push(o),e.push(c)});let{q:i}=X(null,Q.info||"");i.classList.add("info");let r=Z(t,n("div",{cls:"ln"},i,n("div",{cls:"ctl"},...e.map((a)=>a.lb))));r.__pick=(a)=>{if(e[a])e[a].i.click()},r.__focus=()=>{if(e[0])e[0].i.focus()},g.delIt=r}kt.forEach((e)=>{let i={on:!1},r=G("也做",!1);r.i.addEventListener("change",()=>{i.on=r.i.checked,r.lb.classList.toggle("chg",i.on),D()});let{q:a}=X(null,e.text),o=Z(t,n("div",{cls:"ln"},a,n("div",{cls:"ctl"},r.lb)));o.__pick=(c)=>{if(c===0)r.i.click()},o.__focus=()=>r.i.focus(),g.opt.push({o:e,st:i,it:o})})}let M=(t,e,i)=>{let r=String(e).split(`
4
+ `).map((o)=>o.replace(/\s+$/,""));while(r.length&&!r[0])r.shift();while(r.length&&!r[r.length-1])r.pop();if(r=r.filter((o,c)=>o||r[c-1]),r.length<=1)return t+(r[0]||"");let a=" ".repeat(i);return t+r[0]+`
5
+ `+r.slice(1).map((o)=>a+o).join(`
6
+ `)},yt=(t)=>{let{d:e,st:i}=t,r=U(i),a=e.n+". ",o=a.length;if(e.ask){let c=(i.text||"").trim();return c?M(a,c,o):null}if(e.group==="defaulted")return i.pick==="over"?M(a+"推翻:",r||"(待补充)",o):null;if(e.multi){let c=[...i.sel].sort((d,v)=>d-v).map((d)=>e.opts[d]);if(c.length)return M(a+c.join("、")+(r?",":""),r,o);if(t.init.size)return M(a+"都不选"+(r?",":""),r,o);return r?M(a,r,o):null}if(i.pick&&i.pick[0]==="o")return M(a+e.opts[+i.pick.slice(1)]+(r?",":""),r,o);return r?M(a,r,o):null},ct=(t,e)=>{let i=e.some((r)=>r.includes(`
7
+ `));return e.forEach((r,a)=>{if(i&&a)t.push("");t.push(r)}),i};function at(){let t=[],e=g.dec.filter((c)=>c.d.group!=="pending").map(yt).filter(Boolean),i=g.dec.filter((c)=>c.d.group==="pending").map(yt).filter(Boolean);if(e.length||i.length){t.push("决策:");let c=ct(t,e);if(i.length){if(c||i.some((d)=>d.includes(`
8
+ `)))t.push("");t.push("--早前尚未决策--"),ct(t,i)}}let r=g.act.filter((c)=>c.st.pick);if(r.length){if(t.length)t.push("");t.push("反馈:"),ct(t,r.map((c)=>{let d=U(c.st);return M("- "+c.a.short+":"+P[c.st.pick]+(d?":":""),d,2)}))}let a=g.del.filter((c)=>c.st.on).map((c)=>c.t.label);if(a.length){if(t.length)t.push("");t.push("交付:"+a.join(","))}let o=g.opt.filter((c)=>c.st.on);if(o.length){if(t.length)t.push("");o.forEach((c)=>t.push("也做:"+c.o.text))}return t.join(`
9
+ `)}let Et=()=>{let t=[];return g.dec.forEach((e)=>{if(e.changed())t.push(e.d.n+" "+e.sum())}),g.act.forEach((e)=>{if(e.st.pick)t.push(e.a.short+":"+P[e.st.pick])}),g.del.forEach((e)=>{if(e.st.on!==e.init)t.push((e.st.on?"":"不")+e.t.label)}),g.opt.forEach((e)=>{if(e.st.on)t.push("也做 "+j(e.o.text,10))}),t},lt=(t)=>t?"<turn-reply"+(E?' turn="'+E+'"':"")+`>
10
+ `+t+`
11
+ </turn-reply>`:t,pt=g.dec.filter((t)=>t.reset&&t.d.group==="now"),J=null;if(pt.length)J=bt("全部按建议",{icon:"reset",title:"把本轮拍板恢复为建议项"}),J.addEventListener("click",()=>pt.forEach((t)=>t.reset()));let $t=n("span",{}),R=n("button",{type:"button",cls:"lk","aria-expanded":"false"},"预览"),Dt=n("span",{cls:"sum","aria-live":"polite"},$t,R),B=n("pre",{cls:"pv"});B.hidden=!0;let dt=()=>{B.hidden=!0,R.textContent="预览",R.setAttribute("aria-expanded","false")};R.addEventListener("click",()=>{if(B.hidden)B.hidden=!1,R.textContent="收起",R.setAttribute("aria-expanded","true");else dt()});let _t=n("span",{},"复制"),F=n("button",{type:"button",cls:"btn"},_t);F.addEventListener("click",()=>{let t=at();if(t)x(lt(t)),f(_t,"已复制")});let W=null;if(b)W=n("button",{type:"button",cls:"btn pri"},"填入输入框"),W.addEventListener("click",(t)=>{t.stopPropagation(),St()});else F.classList.add("pri");let Ot=n("div",{cls:"foot"},J,Dt,F,W),tt=n("span",{cls:"fs"}),Pt=n("button",{type:"button",cls:"lk"},"展开"),Lt=n("div",{cls:"fold"},n("span",{cls:"mk-ok","aria-hidden":"true"}),tt,Pt),At=(t)=>{if(p.classList.toggle("folded",t),t)dt();else if(p.classList.contains("kb")&&_[0])_[0].__focus()};Lt.addEventListener("click",()=>At(!1));function St(){let t=at();if(!t)return;sendPrompt(lt(t));let e=Et();tt.textContent="已填入 · "+(e.length?e.join(" · "):"全部按建议"),tt.title=tt.textContent,At(!0)}let Bt=()=>{if(b)St();else F.click()};p.addEventListener("mousedown",()=>p.classList.remove("kb")),p.addEventListener("keydown",(t)=>{if(t.key==="Tab"||t.key.startsWith("Arrow")||/^[0-9]$/.test(t.key))p.classList.add("kb");if(p.classList.contains("folded"))return;let e=t.target;if(e.tagName==="TEXTAREA"){if(t.isComposing||t.keyCode===229)return;if(t.key==="Escape"&&e.__esc)t.preventDefault(),e.__esc();return}if(t.metaKey||t.ctrlKey||t.altKey)return;let i=e.closest&&e.closest(".it");if(!i)return;if(t.key==="/"&&i.__note){t.preventDefault(),i.__note();return}if(/^[1-9]$/.test(t.key)&&i.__pick){t.preventDefault(),i.__pick(+t.key-1);return}if(t.key==="ArrowDown"||t.key==="ArrowUp"){let r=_.indexOf(i),a=_[r+(t.key==="ArrowDown"?1:-1)];if(a)t.preventDefault(),a.__focus()}}),p.append(Lt,xt,Ot,B);function D(){let t=at(),e=N(t),i=Et();if(g.dec.forEach((a)=>a.it.classList.toggle("chg",a.changed())),g.act.forEach((a)=>a.it.classList.toggle("chg",!!a.st.pick)),g.delIt)g.delIt.classList.toggle("chg",g.del.some((a)=>a.st.on!==a.init));g.opt.forEach((a)=>a.it.classList.toggle("chg",a.st.on));let r=[];if(r.push(i.length?"改了 ":"全部按建议",...i.length?[n("b",{},String(i.length))," 项"]:[]),e)r.push(" · 将填入 ",n("b",{},String(e))," 行");else r.push(" · 没有要回复的内容");if($t.replaceChildren(...r),B.textContent=lt(t),R.hidden=!e,!e)dt();if(F.disabled=!e,W)W.disabled=!e;if(J)J.disabled=pt.every((a)=>!a.changed())}D();let ut={},Ct=[...p.querySelectorAll(".dseg button.sg")];Ct.forEach((t)=>{let e=t.dataset.col;ut[e]=Math.max(ut[e]||0,t.offsetWidth)}),Ct.forEach((t)=>{t.style.setProperty("width",Math.ceil(ut[t.dataset.col])+12+"px","important")}),p.classList.add("measuring");let et=0;if(p.querySelectorAll(".q").forEach((t)=>{et=Math.max(et,t.offsetWidth)}),p.classList.remove("measuring"),et>0)p.style.setProperty("--qw",Math.min(Math.ceil(et)+2,260)+"px")}return It})();var it="0.1.0",Nt="trw-style-"+it;function Rt(n){let l=n.ownerDocument||document;if(l.getElementById(Nt))return;let m=l.createElement("style");m.id=Nt,m.textContent=nt,(l.head||n.parentNode||l.documentElement).appendChild(m)}function ht(n,l){n.replaceChildren(),n.classList.remove("folded","kb");let m=(n.ownerDocument||document).createElement("div");m.className="err",m.setAttribute("role","alert"),m.title=l,m.textContent=l,n.append(m)}var gt=",请直接在输入框回复";function jt(n,l){if(!n||typeof n.append!=="function")return console.error("[turn-reply] root 不是元素"),["root 不是元素"];n.classList.add("trw"),Rt(n);let m=l;if(typeof m==="string")try{m=JSON.parse(m)}catch(s){return ht(n,"面板数据不是合法 JSON"+gt),["JSON 解析失败"]}let y=rt(m);if(y.length)return console.error(`[turn-reply] spec 不合法:
12
+ `+y.join(`
13
+ `)),ht(n,"面板数据不合法("+y.length+" 处,首处 "+y[0]+")"+gt),y;try{zt(n,m)}catch(s){console.error("[turn-reply] 渲染出错",s);let x="面板渲染出错("+(s&&s.message||s)+")"+gt;return ht(n,x),[x]}return[]}var mt=typeof window<"u"?window:globalThis;if(!mt.TR||mt.TR.version!==it)mt.TR={render:jt,validate:rt,version:it,css:nt};})();
package/package.json CHANGED
@@ -1,6 +1,21 @@
1
1
  {
2
2
  "name": "@npmjsdnt/turn-reply",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "turn-report 回复面板:TR.render(root, spec),供 show_widget 每轮只贴引导代码+spec",
5
+ "license": "UNLICENSED",
6
+ "main": "dist/tr.js",
7
+ "jsdelivr": "dist/tr.min.js",
8
+ "unpkg": "dist/tr.min.js",
9
+ "files": [
10
+ "dist/tr.js",
11
+ "dist/tr.min.js",
12
+ "dist/tr.css"
13
+ ],
14
+ "scripts": {
15
+ "build": "bun build.ts",
16
+ "test": "bun build.ts && bun test"
17
+ },
18
+ "devDependencies": {
19
+ "happy-dom": "^20"
20
+ }
21
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.