@kanyun-ai-infra/band-plugin-react 0.1.1 → 0.2.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.
@@ -1,6 +1,6 @@
1
1
  /* band:inject-css */ /* @kanyun-ai-infra/band-plugin-react/components 的样式(scripts/tsup-inject-css.ts) */
2
2
  if (typeof document !== "undefined" && document.head) {
3
- const css = "/* src/ui.css */\n.band-plugin-react-error {\n font-size: var(--fs-ui);\n padding: 7px 10px;\n border-radius: 8px;\n background: var(--bad-soft);\n color: var(--bad);\n font-family: var(--mono);\n}\n.band-plugin-react-info {\n font-size: var(--fs-ui);\n padding: 7px 10px;\n border-radius: 8px;\n background: var(--panel);\n color: var(--muted);\n}\n.band-plugin-react-retry {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 10px;\n}\n.band-plugin-react-failed {\n display: grid;\n gap: 6px;\n justify-items: start;\n margin: auto;\n padding: 8px 10px;\n border-radius: var(--r);\n background: var(--bad-soft);\n color: var(--bad);\n font-size: var(--fs-ui);\n}\n.band-plugin-react-failed p {\n margin: 0;\n}\n.band-plugin-react-failed-title {\n font-weight: 600;\n}\n.band-plugin-react-failed-reason {\n overflow-wrap: anywhere;\n}\n.band-plugin-react-pane-head {\n padding: 6px 14px 6px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n min-height: 36px;\n}\n.band-plugin-react-pane-title {\n margin: 0;\n font-size: var(--fs-dense);\n color: var(--muted);\n font-weight: 500;\n letter-spacing: 0.02em;\n}\n.band-plugin-react-wsicon {\n flex: none;\n display: block;\n}\n.band-plugin-react-wstile {\n --band-wstile: 16px;\n width: var(--band-wstile);\n height: var(--band-wstile);\n display: inline-grid;\n place-items: center;\n flex: none;\n border-radius: calc(var(--band-wstile) * 0.26);\n background: var(--panel);\n box-shadow: var(--shadow-card);\n}\n.band-plugin-react-wstile > :where(.band-plugin-react-wsicon) {\n width: 82%;\n height: 82%;\n}\n.band-plugin-react-wstile:where(.is-large) {\n border-radius: var(--r-xl);\n}\n.band-plugin-react-wstile:where(.is-large) > :where(.band-plugin-react-wsicon) {\n width: 76%;\n height: 76%;\n}\n.band-plugin-react-instrument {\n width: 72%;\n height: 72%;\n background: currentColor;\n -webkit-mask: var(--band-instrument) center / contain no-repeat;\n mask: var(--band-instrument) center / contain no-repeat;\n}\n.band-plugin-react-model-hint {\n margin: 0;\n}\n.band-plugin-react-target-repo {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin: 0;\n font-size: var(--fs-meta);\n line-height: 1.5;\n color: var(--muted);\n}\n.band-plugin-react-target-repo code {\n font-family: var(--mono);\n color: var(--ink);\n}\n.band-plugin-react-target-repo a {\n color: var(--accent-text);\n}\n.band-plugin-react-target-repo-request {\n align-self: flex-start;\n}\n.band-plugin-react-target-repo-err {\n color: var(--bad);\n}\n.band-plugin-react-first-delivery {\n display: flex;\n flex-direction: column;\n gap: 8px;\n flex-basis: 100%;\n padding: 12px;\n border: 1px solid var(--rule);\n border-radius: var(--r-lg);\n background: var(--panel);\n margin: 0;\n min-width: 0;\n}\n.band-plugin-react-first-delivery-slot {\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: var(--fs-meta);\n}\n.band-plugin-react-first-delivery-pick,\n.band-plugin-react-first-delivery-file {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n}\n.band-plugin-react-first-delivery-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.band-plugin-react-first-delivery-name {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n.band-plugin-react-first-delivery-size {\n color: var(--muted);\n}\n.band-plugin-react-first-delivery-missing {\n margin: 0;\n font-size: var(--fs-meta);\n color: var(--muted);\n}\n.band-plugin-react-first-delivery .btn {\n align-self: flex-start;\n}\n.band-plugin-react-no-key {\n margin: 0;\n font-size: var(--fs-ui);\n color: var(--bad);\n}\n";
3
+ const css = "/* src/ui.css */\n.band-plugin-react-error {\n font-size: var(--fs-ui);\n padding: 7px 10px;\n border-radius: 8px;\n background: var(--bad-soft);\n color: var(--bad);\n font-family: var(--mono);\n}\n.band-plugin-react-info {\n font-size: var(--fs-ui);\n padding: 7px 10px;\n border-radius: 8px;\n background: var(--panel);\n color: var(--muted);\n}\n.band-plugin-react-retry {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 10px;\n}\n.band-plugin-react-failed {\n display: grid;\n gap: 6px;\n justify-items: start;\n margin: auto;\n padding: 8px 10px;\n border-radius: var(--r);\n background: var(--bad-soft);\n color: var(--bad);\n font-size: var(--fs-ui);\n}\n.band-plugin-react-failed p {\n margin: 0;\n}\n.band-plugin-react-failed-title {\n font-weight: 600;\n}\n.band-plugin-react-failed-reason {\n overflow-wrap: anywhere;\n}\n.band-plugin-react-pane-head {\n padding: 6px 14px 6px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n min-height: 36px;\n}\n.band-plugin-react-pane-title {\n margin: 0;\n font-size: var(--fs-dense);\n color: var(--muted);\n font-weight: 500;\n letter-spacing: 0.02em;\n}\n.band-plugin-react-wsicon {\n flex: none;\n display: block;\n}\n.band-plugin-react-wstile {\n --band-wstile: 16px;\n width: var(--band-wstile);\n height: var(--band-wstile);\n display: inline-grid;\n place-items: center;\n flex: none;\n border-radius: calc(var(--band-wstile) * 0.26);\n background: var(--panel);\n box-shadow: var(--shadow-card);\n}\n.band-plugin-react-wstile > :where(.band-plugin-react-wsicon) {\n width: 82%;\n height: 82%;\n}\n.band-plugin-react-wstile:where(.is-large) {\n border-radius: var(--r-xl);\n}\n.band-plugin-react-wstile:where(.is-large) > :where(.band-plugin-react-wsicon) {\n width: 76%;\n height: 76%;\n}\n.band-plugin-react-instrument {\n width: 72%;\n height: 72%;\n background: currentColor;\n -webkit-mask: var(--band-instrument) center / contain no-repeat;\n mask: var(--band-instrument) center / contain no-repeat;\n}\n.band-plugin-react-model-hint {\n margin: 0;\n}\n.band-plugin-react-target-repo {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin: 0;\n font-size: var(--fs-meta);\n line-height: 1.5;\n color: var(--muted);\n}\n.band-plugin-react-target-repo code {\n font-family: var(--mono);\n color: var(--ink);\n}\n.band-plugin-react-target-repo a {\n color: var(--accent-text);\n}\n.band-plugin-react-target-repo-request {\n align-self: flex-start;\n}\n.band-plugin-react-target-repo-err {\n color: var(--bad);\n}\n.band-plugin-react-first-delivery {\n display: flex;\n flex-direction: column;\n gap: 8px;\n flex-basis: 100%;\n padding: 12px;\n border: 1px solid var(--rule);\n border-radius: var(--r-lg);\n background: var(--panel);\n margin: 0;\n min-width: 0;\n}\n.band-plugin-react-first-delivery-slot {\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: var(--fs-meta);\n}\n.band-plugin-react-first-delivery-pick,\n.band-plugin-react-first-delivery-file {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n}\n.band-plugin-react-first-delivery-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.band-plugin-react-first-delivery-name {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n.band-plugin-react-first-delivery-size {\n color: var(--muted);\n}\n.band-plugin-react-first-delivery-missing {\n margin: 0;\n font-size: var(--fs-meta);\n color: var(--muted);\n}\n.band-plugin-react-first-delivery .btn {\n align-self: flex-start;\n}\n.band-plugin-react-no-key {\n margin: 0;\n font-size: var(--fs-ui);\n color: var(--bad);\n}\n\n/* src/settings/settings.css */\n.band-sf {\n display: grid;\n grid-template-columns: 216px minmax(0, 1fr);\n min-height: 0;\n height: 100%;\n}\n.band-sf-nav {\n min-height: 0;\n overflow: auto;\n overscroll-behavior: contain;\n padding: 24px 12px 24px 20px;\n display: grid;\n gap: 16px;\n align-content: start;\n}\n.band-sf-head {\n display: grid;\n gap: 2px;\n min-width: 0;\n padding: 0 8px;\n}\n.band-sf-title {\n font-size: var(--fs-title);\n font-weight: 600;\n line-height: 1.3;\n}\n.band-sf-obj {\n font-size: var(--fs-ui);\n color: var(--muted);\n}\n.band-sf-grp {\n display: grid;\n gap: 1px;\n}\n.band-sf-grp > span {\n padding: 2px 8px;\n color: var(--muted);\n font-size: var(--fs-dense);\n}\n.band-sf-grp a {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 6px 8px;\n border-radius: var(--r);\n color: var(--ink);\n text-decoration: none;\n font-size: var(--fs-row);\n}\n.band-sf-grp a:hover {\n background: var(--fill);\n}\n.band-sf-grp a[aria-current=page] {\n background: var(--fill-2);\n font-weight: 500;\n}\n.band-sf-grp a:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--accent);\n}\n.band-sf-grp a .band-sf-chev {\n display: none;\n color: var(--muted);\n}\n.band-sf-scroll {\n min-height: 0;\n overflow: auto;\n overscroll-behavior: contain;\n}\n.band-sf-main {\n box-sizing: border-box;\n width: 100%;\n max-width: 824px;\n padding: 32px 32px 64px;\n display: grid;\n gap: 20px;\n align-content: start;\n}\n.band-sf-crumb {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px;\n min-width: 0;\n color: var(--muted);\n font-size: var(--fs-dense);\n}\n.band-sf-crumb-in {\n display: inline-flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px;\n min-width: 0;\n}\n.band-sf-crumb-ws {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n white-space: nowrap;\n}\n.band-sf-crumb-ws > span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.band-sf-crumb a,\n.band-sf-crumb button {\n min-width: 0;\n border: 0;\n padding: 0;\n background: none;\n color: var(--muted);\n font: inherit;\n text-decoration: none;\n border-radius: 4px;\n overflow-wrap: anywhere;\n cursor: pointer;\n}\n.band-sf-crumb button {\n text-align: start;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.band-sf-crumb a:hover,\n.band-sf-crumb button:hover {\n color: var(--ink);\n}\n.band-sf-crumb a:focus-visible,\n.band-sf-crumb button:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--accent);\n}\n.band-sf-back {\n display: inline-flex;\n align-self: start;\n justify-self: start;\n gap: 4px;\n color: var(--muted);\n text-decoration: none;\n font-size: var(--fs-ui);\n border-radius: 4px;\n}\n.band-sf-back-m {\n display: none;\n}\n.band-sf-back:hover {\n color: var(--ink);\n}\n.band-sf-back:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--accent);\n}\n.band-sf-h {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n}\n.band-sf-h > div {\n display: grid;\n gap: 4px;\n min-width: 0;\n}\n.band-sf-h h1 {\n margin: 0;\n font-size: var(--fs-h2);\n font-weight: 600;\n line-height: 1.3;\n}\n.band-sf-h p {\n margin: 0;\n color: var(--muted);\n font-size: var(--fs-ui);\n max-width: 560px;\n}\n.band-sf-h-a {\n flex: none;\n}\n.band-sf-sec {\n display: grid;\n gap: 10px;\n}\n.band-sf-sec h2 {\n margin: 0;\n font-size: var(--fs-lead);\n font-weight: 600;\n}\n.band-sf-sec > p {\n margin: 0;\n color: var(--muted);\n font-size: var(--fs-ui);\n}\n.band-sf-rows {\n display: grid;\n gap: 2px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.band-sf-row {\n position: relative;\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 2px 12px;\n align-items: center;\n padding: 10px 12px;\n margin: 0 -12px;\n border-radius: var(--r-lg);\n}\n.band-sf-row:hover {\n background: var(--fill);\n}\n.band-sf-row.is-new,\n.band-sf-row.is-new:hover {\n background: var(--ok-soft);\n}\n.band-sf-row-t {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px 8px;\n min-width: 0;\n}\n.band-sf-row-t b {\n font-weight: 600;\n overflow-wrap: anywhere;\n}\n.band-sf-row-link {\n color: inherit;\n text-decoration: none;\n border-radius: 4px;\n}\n.band-sf-row-link::after {\n content: \"\";\n position: absolute;\n inset: 0;\n border-radius: var(--r-lg);\n}\n.band-sf-row-a {\n position: relative;\n z-index: 1;\n}\n.band-sf-row-link:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--accent);\n}\n.band-sf-row-m {\n grid-column: 1;\n display: flex;\n flex-wrap: wrap;\n gap: 2px 14px;\n color: var(--muted);\n font-size: var(--fs-dense);\n min-width: 0;\n}\n.band-sf-row-m > span {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n.band-sf-row-a {\n grid-column: 2;\n grid-row: 1 / span 2;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.band-sf-row-a .btn {\n position: relative;\n z-index: 1;\n}\n.band-sf-chev {\n color: var(--muted);\n}\n.band-sf-mono {\n font-family: var(--mono);\n font-size: 0.92em;\n}\n.band-sf-facts {\n display: grid;\n gap: 6px 16px;\n margin: 0;\n font-size: var(--fs-ui);\n}\n.band-sf-fact {\n display: grid;\n grid-template-columns: 112px minmax(0, 1fr);\n gap: 16px;\n}\n.band-sf-facts dt {\n color: var(--muted);\n}\n.band-sf-facts dd {\n margin: 0;\n min-width: 0;\n overflow-wrap: anywhere;\n}\n.band-sf-dz {\n display: grid;\n gap: 10px;\n padding-top: 8px;\n}\n.band-sf-dz h2 {\n margin: 0;\n font-size: var(--fs-lead);\n font-weight: 600;\n}\n.band-sf-dz-r {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n}\n.band-sf-dz-r > div {\n display: grid;\n gap: 2px;\n min-width: 0;\n}\n.band-sf-dz-r span {\n color: var(--muted);\n font-size: var(--fs-dense);\n}\n.band-sf-dz-r .btn {\n flex: none;\n}\n.band-sf-empty,\n.band-sf .band-sf-empty.rest {\n display: grid;\n justify-items: start;\n text-align: start;\n gap: 10px;\n padding: 24px 0;\n max-width: 480px;\n}\n.band-sf-empty p {\n margin: 0;\n color: var(--muted);\n}\n.band-sf-error {\n min-width: 0;\n}\n.band-sf-load {\n padding: 40px 0;\n display: grid;\n justify-items: start;\n}\n.band-sf-ok {\n margin: 0;\n color: var(--ok);\n font-size: var(--fs-ui);\n}\n.band-sf-muted {\n margin: 0;\n color: var(--muted);\n font-size: var(--fs-ui);\n}\n.band-sf-banner {\n margin: 0;\n padding: 10px 12px;\n border-radius: var(--r-lg);\n background: var(--fill);\n font-size: var(--fs-ui);\n}\n.band-sf-banner.is-warn {\n display: flex;\n align-items: center;\n gap: 8px;\n background: var(--warn-soft);\n}\n.band-sf-form {\n display: grid;\n gap: 16px;\n max-width: 560px;\n min-width: 0;\n}\n.band-sf-form code {\n overflow-wrap: anywhere;\n}\n.band-sf-fld {\n display: grid;\n gap: 6px;\n min-width: 0;\n}\n.band-sf-fld > label {\n font-size: var(--fs-ui);\n font-weight: 500;\n}\n.band-sf-fld .field {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n}\n.band-sf-fld textarea.field {\n resize: vertical;\n line-height: 1.5;\n}\n.band-sf-req {\n margin-left: 6px;\n color: var(--muted);\n font-weight: 400;\n}\n.band-sf-optional {\n margin-left: 6px;\n color: var(--muted);\n font-weight: 400;\n}\n.band-sf-one {\n display: grid;\n gap: 10px;\n min-width: 0;\n}\n.band-sf-one fieldset {\n margin: 0;\n padding: 0;\n border: 0;\n min-width: 0;\n display: grid;\n gap: 10px;\n}\n.band-sf-choices {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px 12px;\n}\n.band-sf-blks-l {\n font-size: var(--fs-ui);\n font-weight: 600;\n}\n.band-sf-blks {\n display: grid;\n gap: 8px;\n}\n.band-sf-blks-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n.band-sf-blks-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n.band-sf-blk {\n display: grid;\n gap: 4px;\n align-content: start;\n padding: 12px 14px;\n border-radius: var(--r-lg);\n background: var(--fill);\n cursor: pointer;\n min-width: 0;\n}\n.band-sf-blk > b {\n font-weight: 600;\n font-size: var(--fs-ui);\n overflow-wrap: anywhere;\n}\n.band-sf-blk > small {\n color: var(--muted);\n font-size: var(--fs-dense);\n overflow-wrap: anywhere;\n}\n.band-sf-blk.is-on {\n background: var(--accent-soft);\n box-shadow: inset 0 0 0 2px var(--accent);\n}\n.band-sf-blk.is-on > b {\n color: var(--accent-text);\n}\n.band-sf-blk:has(:focus-visible) {\n box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--accent);\n}\n.band-sf-blk:has(:disabled) {\n cursor: default;\n}\n@media (max-width: 600px) {\n .band-sf-blks-3,\n .band-sf-blks-2 {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n.band-sf-hint {\n color: var(--muted);\n font-size: var(--fs-dense);\n}\n.band-sf-hint a,\n.band-sf-fld .field-note a,\n.band-sf-muted a {\n color: var(--accent-text);\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.band-sf-err {\n margin: 0;\n color: var(--bad);\n font-size: var(--fs-ui);\n}\n.band-sf-fail {\n grid-column: 1 / -1;\n display: flex;\n align-items: flex-start;\n gap: 8px;\n overflow-wrap: anywhere;\n}\n.band-sf-given {\n margin: 0;\n padding: 10px 12px;\n border-radius: var(--r-lg);\n background: var(--fill);\n font-size: var(--fs-ui);\n}\ndl.band-sf-given {\n display: grid;\n grid-template-columns: 56px minmax(0, 1fr);\n gap: 2px 12px;\n}\ndl.band-sf-given dt {\n color: var(--muted);\n}\ndl.band-sf-given dd {\n margin: 0;\n min-width: 0;\n}\ndl.band-sf-given p {\n grid-column: 1 / -1;\n margin: 0;\n color: var(--muted);\n font-size: var(--fs-dense);\n}\n.band-sf-stepback {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n align-self: start;\n justify-self: start;\n padding: 0;\n border: 0;\n background: none;\n color: var(--muted);\n font: inherit;\n font-size: var(--fs-ui);\n cursor: pointer;\n border-radius: 4px;\n}\n.band-sf-stepback:hover {\n color: var(--ink);\n}\n.band-sf-stepback:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--accent);\n}\n.band-sf-acts {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px 12px;\n}\n.band-sf-acts-end {\n justify-content: flex-end;\n}\n.band-sf-state {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--muted);\n font-size: var(--fs-ui);\n}\n.band-settings-no-access {\n display: grid;\n gap: 10px;\n justify-items: start;\n max-width: 560px;\n padding-top: 8px;\n}\n.band-settings-no-access h2 {\n margin: 0;\n font-size: var(--fs-title);\n}\n.band-settings-no-access p {\n margin: 0;\n color: var(--muted);\n}\n.band-sf-dialog {\n box-sizing: border-box;\n width: min(460px, calc(100vw - 32px));\n max-height: calc(100dvh - 32px);\n overflow: auto;\n overscroll-behavior: contain;\n border: 0;\n border-radius: var(--r-xl);\n box-shadow: var(--shadow-pop);\n background: var(--panel);\n color: var(--ink);\n padding: 22px 24px;\n}\n.band-sf-dialog[open] {\n display: grid;\n gap: 14px;\n}\n.band-sf-dialog::backdrop {\n background: var(--scrim);\n}\n.band-sf-dialog h2 {\n margin: 0;\n font-size: var(--fs-title);\n overflow-wrap: anywhere;\n}\n.band-sf-dialog ul {\n margin: 0;\n padding-left: 18px;\n display: grid;\n gap: 4px;\n}\n.band-sf-row-x {\n grid-column: 1 / -1;\n margin-top: 8px;\n min-width: 0;\n}\n.band-sf-row.has-lead {\n grid-template-columns: auto minmax(0, 1fr) auto;\n}\n.band-sf-row-l {\n grid-column: 1;\n grid-row: 1 / span 2;\n display: flex;\n align-items: center;\n}\n.band-sf-row.has-lead .band-sf-row-t,\n.band-sf-row.has-lead .band-sf-row-m {\n grid-column: 2;\n}\n.band-sf-row.has-lead .band-sf-row-a {\n grid-column: 3;\n}\n@media (max-width: 600px) {\n .band-sf {\n grid-template-columns: minmax(0, 1fr);\n }\n .band-sf[data-view=page] .band-sf-nav {\n display: none;\n }\n .band-sf[data-view=index] .band-sf-scroll {\n display: none;\n }\n .band-sf-nav {\n padding: 16px;\n }\n .band-sf-grp a {\n padding: 10px 8px;\n font-size: var(--fs-body);\n }\n .band-sf-grp a .band-sf-chev {\n display: inline;\n }\n .band-sf-grp a[aria-current=page] {\n background: none;\n font-weight: 400;\n }\n .band-sf-main {\n padding: 12px 16px 48px;\n gap: 16px;\n }\n .band-sf-back-m {\n display: inline-flex;\n }\n .band-sf-h {\n display: grid;\n gap: 10px;\n }\n .band-sf-h-a .btn {\n justify-self: start;\n }\n .band-sf-row-a {\n grid-column: 1 / -1;\n grid-row: auto;\n justify-content: flex-start;\n margin-top: 4px;\n }\n .band-sf-row-a .band-sf-chev {\n margin-left: auto;\n }\n .band-sf-row-a:has(.band-sf-chev:only-child) {\n grid-column: 2;\n grid-row: 1 / span 2;\n justify-content: flex-end;\n margin-top: 0;\n }\n .band-sf-row > .band-sf-acts {\n grid-column: 1 / -1;\n justify-content: flex-start;\n margin-top: 4px;\n }\n .band-sf-fact {\n grid-template-columns: 88px minmax(0, 1fr);\n gap: 12px;\n }\n .band-sf-dz-r {\n display: grid;\n gap: 8px;\n }\n .band-sf-dz-r .btn {\n justify-self: start;\n }\n .band-sf-dialog {\n padding: 18px 16px;\n }\n .band-sf-row.has-lead .band-sf-row-a {\n grid-column: 2 / -1;\n }\n}\n\n/* src/controls.css */\n.band-plugin-react-combo-field,\n.band-plugin-react-tags {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n gap: 5px;\n align-items: center;\n padding: 5px 8px;\n border-radius: var(--r);\n background: var(--panel);\n box-shadow: inset 0 0 0 1px var(--control-edge);\n}\n.band-plugin-react-combo-field > :where(.field),\n.band-plugin-react-tags > :where(.field) {\n flex: 1 1 90px;\n min-width: 90px;\n width: auto;\n}\n.band-plugin-react-combo-picked {\n list-style: none;\n margin: 0 0 7px;\n padding: 0;\n display: flex;\n flex-wrap: wrap;\n gap: 5px;\n}\n.band-plugin-react-combo-chip,\n.band-plugin-react-filter-chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n height: 22px;\n padding: 0 4px 0 8px;\n border-radius: 999px;\n background: var(--fill-2);\n color: var(--ink);\n font-size: var(--fs-meta);\n white-space: nowrap;\n}\n.band-plugin-react-filter-chip {\n background: var(--accent-soft);\n color: var(--accent-text);\n}\n.band-plugin-react-combo-chip > button,\n.band-plugin-react-filter-chip > button {\n border: 0;\n background: none;\n color: inherit;\n font: inherit;\n line-height: 1;\n padding: 0 3px;\n border-radius: 999px;\n opacity: 0.85;\n}\n.band-plugin-react-combo-chip > button:where(:focus-visible),\n.band-plugin-react-filter-chip > button:where(:focus-visible) {\n outline: none;\n box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--accent);\n opacity: 1;\n}\n.band-plugin-react-combo-pop {\n position: absolute;\n left: 0;\n right: 0;\n top: calc(100% + 6px);\n z-index: var(--layer-pop);\n display: grid;\n gap: 1px;\n max-height: 236px;\n overflow: auto;\n overscroll-behavior: contain;\n padding: 5px;\n border-radius: var(--r-lg);\n background: var(--panel);\n box-shadow: var(--shadow-pop);\n}\n.band-plugin-react-combo-group {\n padding: 6px 8px 3px;\n font-size: var(--fs-badge);\n color: var(--muted);\n}\n.band-plugin-react-combo-opt {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 6px 8px;\n border: 0;\n border-radius: var(--r-sm);\n background: none;\n color: var(--ink);\n font: inherit;\n font-size: var(--fs-row);\n text-align: left;\n}\n.band-plugin-react-combo-opt:where(.is-active) {\n background: var(--fill-2);\n}\n.band-plugin-react-combo-opt:where(:focus-visible) {\n outline: none;\n box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--accent);\n}\n.band-plugin-react-combo-label {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.band-plugin-react-combo-label > mark {\n background: var(--accent-soft);\n color: var(--ink);\n border-radius: 2px;\n}\n.band-plugin-react-combo-meta {\n margin-left: auto;\n flex: none;\n font-family: var(--mono);\n font-size: var(--fs-badge);\n color: var(--muted);\n}\n.band-plugin-react-combo-plus {\n display: inline-grid;\n place-items: center;\n width: 20px;\n height: 20px;\n flex: none;\n border-radius: 50%;\n background: var(--fill-3);\n color: var(--muted);\n font-size: var(--fs-badge);\n}\n.band-plugin-react-combo-empty {\n padding: 8px;\n text-align: center;\n font-size: var(--fs-meta);\n color: var(--muted);\n}\n.band-plugin-react-tag {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n height: 22px;\n padding: 0 4px 0 8px;\n border-radius: 999px;\n background: var(--fill-2);\n color: var(--ink);\n font-size: var(--fs-meta);\n white-space: nowrap;\n}\n.band-plugin-react-tag:where([data-dup]) {\n background: var(--bad-soft);\n color: var(--bad);\n}\n.band-plugin-react-tag > button {\n border: 0;\n background: none;\n color: inherit;\n font: inherit;\n line-height: 1;\n padding: 0 3px;\n border-radius: 999px;\n opacity: 0.85;\n}\n.band-plugin-react-tag > button:where(:focus-visible) {\n outline: none;\n box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--accent);\n opacity: 1;\n}\n.band-plugin-react-tag-hint {\n margin: 5px 0 0;\n min-height: 16px;\n font-size: var(--fs-badge);\n color: var(--muted);\n}\n.band-plugin-react-tag-hint:where([data-err]) {\n color: var(--bad);\n}\n.band-plugin-react-filter {\n display: grid;\n gap: 2px;\n min-width: 0;\n}\n.band-plugin-react-filter-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n align-items: center;\n margin-bottom: 8px;\n}\n.band-plugin-react-filter-clear {\n margin-left: auto;\n border: 0;\n background: none;\n padding: 0 2px;\n color: var(--muted);\n font: inherit;\n font-size: var(--fs-meta);\n text-decoration: underline;\n}\n.band-plugin-react-filter-clear:where(:focus-visible) {\n outline: none;\n box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--accent);\n border-radius: 4px;\n}\n.band-plugin-react-filter-group {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n padding: 7px 8px 3px;\n border: 0;\n border-radius: var(--r-sm);\n background: none;\n color: var(--muted);\n font: inherit;\n font-size: var(--fs-badge);\n text-align: left;\n}\n.band-plugin-react-filter-group:where(:focus-visible) {\n outline: none;\n box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--accent);\n}\n.band-plugin-react-filter-group::before {\n content: \"\\25b8\";\n width: 11px;\n flex: none;\n font-size: var(--fs-meta);\n line-height: 1;\n}\n.band-plugin-react-filter-group[aria-expanded=true]::before {\n content: \"\\25be\";\n}\n.band-plugin-react-filter-group-count {\n margin-left: auto;\n font-family: var(--mono);\n}\n.band-plugin-react-filter-opt {\n padding: 4px 8px;\n border-radius: var(--r-sm);\n}\n.band-plugin-react-filter-opt:where(:hover) {\n background: var(--fill);\n}\n.band-plugin-react-filter-count {\n margin-left: auto;\n font-family: var(--mono);\n font-size: var(--fs-badge);\n color: var(--muted);\n}\n.band-plugin-react-filter-empty {\n padding: 8px;\n font-size: var(--fs-meta);\n color: var(--muted);\n}\n\n/* src/toast/toast.css */\n.band-plugin-react-toast-stack {\n position: fixed;\n right: 20px;\n bottom: calc(60px + env(safe-area-inset-bottom, 0px));\n z-index: var(--layer-pop);\n width: min(340px, calc(100vw - 40px));\n display: grid;\n gap: 8px;\n}\n.band-plugin-react-toast {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr) auto;\n gap: 10px;\n align-items: center;\n padding: 10px 12px;\n border-radius: var(--r-lg);\n background: var(--panel);\n box-shadow: var(--shadow-pop);\n font-size: var(--fs-row);\n color: var(--ink);\n animation: band-plugin-react-toast-in var(--eighth) var(--ease);\n}\n@keyframes band-plugin-react-toast-in {\n from {\n opacity: 0;\n transform: translateY(6px);\n }\n to {\n opacity: 1;\n transform: none;\n }\n}\n.band-plugin-react-toast-again {\n animation: none;\n}\n.band-plugin-react-toast-icon {\n width: 16px;\n height: 16px;\n display: grid;\n place-items: center;\n border-radius: 50%;\n font-size: 10px;\n color: var(--panel);\n}\n.band-plugin-react-toast-icon:where(.ok) {\n background: var(--ok);\n}\n.band-plugin-react-toast-icon:where(.bad) {\n background: var(--bad);\n}\n.band-plugin-react-toast-icon:where(.busy) {\n border: 1.6px solid var(--accent);\n border-top-color: transparent;\n color: transparent;\n background: none;\n animation: band-plugin-react-toast-spin 900ms linear infinite;\n}\n@keyframes band-plugin-react-toast-spin {\n to {\n transform: rotate(360deg);\n }\n}\n.band-plugin-react-toast-text {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n.band-plugin-react-toast-detail {\n display: block;\n color: var(--muted);\n font-size: var(--fs-meta);\n overflow-wrap: anywhere;\n}\n.band-plugin-react-toast-act {\n font-size: var(--fs-meta);\n color: var(--ink);\n background: none;\n border: 0;\n font-family: inherit;\n text-decoration: underline;\n padding: 2px 4px;\n border-radius: 4px;\n}\n.band-plugin-react-toast-act:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--accent);\n}\n@media (prefers-reduced-motion: reduce) {\n .band-plugin-react-toast,\n .band-plugin-react-toast-icon:where(.busy) {\n animation: none;\n }\n}\n\n/* src/person-picker.css */\n.band-plugin-react-pp-picker {\n display: grid;\n gap: 8px;\n min-width: 0;\n}\n.band-plugin-react-pp-people {\n list-style: none;\n margin: 0;\n padding: 0;\n display: grid;\n gap: 2px;\n}\n.band-plugin-react-pp-person {\n display: flex;\n align-items: center;\n gap: 10px;\n min-height: 44px;\n padding: 4px 6px;\n border-radius: var(--r-sm);\n}\n.band-plugin-react-pp-person:where(:hover) {\n background: var(--fill);\n}\n.band-plugin-react-pp-empty {\n padding: 10px 6px;\n color: var(--muted);\n font-size: var(--fs-row);\n}\n.band-plugin-react-pp-confirm {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: var(--fs-dense);\n color: var(--ink);\n white-space: nowrap;\n}\n.band-plugin-react-pp-count {\n font-size: var(--fs-meta);\n color: var(--muted);\n}\n.band-plugin-react-pp {\n position: relative;\n min-width: 0;\n}\n.band-plugin-react-pp-field {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 3px 8px;\n border-radius: var(--r);\n background: var(--panel);\n box-shadow: inset 0 0 0 1px var(--control-edge);\n}\n.band-plugin-react-pp-field > :where(.field) {\n flex: 1 1 auto;\n min-width: 0;\n}\n.band-plugin-react-pp-icon {\n width: 14px;\n height: 14px;\n flex: none;\n fill: none;\n stroke: var(--muted);\n stroke-width: 1.5;\n stroke-linecap: round;\n}\n.band-plugin-react-pp-notice {\n display: block;\n margin-top: 6px;\n font-size: var(--fs-meta);\n color: var(--muted);\n}\n.band-plugin-react-pp-pop {\n position: absolute;\n left: 0;\n right: 0;\n top: calc(100% + 6px);\n z-index: var(--layer-pop);\n display: grid;\n gap: 4px;\n padding: 5px;\n border-radius: var(--r-lg);\n background: var(--panel);\n box-shadow: var(--shadow-pop);\n}\n.band-plugin-react-pp-list {\n display: grid;\n gap: 1px;\n max-height: 320px;\n overflow: auto;\n overscroll-behavior: contain;\n}\n.band-plugin-react-pp-fallback {\n padding: 7px 8px;\n border-radius: var(--r-sm);\n background: var(--sunk);\n color: var(--muted);\n font-size: var(--fs-meta);\n}\n.band-plugin-react-pp-trail {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 2px 4px;\n padding: 4px 6px 2px;\n font-size: var(--fs-meta);\n color: var(--muted);\n}\n.band-plugin-react-pp-trail > span {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n.band-plugin-react-pp-trail button {\n border: 0;\n background: none;\n padding: 1px 3px;\n border-radius: 5px;\n font: inherit;\n color: var(--muted);\n}\n.band-plugin-react-pp-trail button:where(:hover) {\n background: var(--fill);\n color: var(--ink);\n}\n.band-plugin-react-pp-trail button:where([aria-current]) {\n color: var(--ink);\n font-weight: 500;\n}\n.band-plugin-react-pp-row {\n display: flex;\n align-items: center;\n gap: 9px;\n min-height: 36px;\n padding: 5px 8px;\n border-radius: var(--r-sm);\n color: var(--ink);\n font-size: var(--fs-row);\n cursor: pointer;\n}\n.band-plugin-react-pp-row:where(.is-active) {\n background: var(--fill-2);\n}\n.band-plugin-react-pp-row:where(.is-off) {\n cursor: default;\n}\n.band-plugin-react-pp-row:where(.is-off) > :where(:not(.band-plugin-react-pp-main)) {\n opacity: 0.42;\n}\n.band-plugin-react-pp-main {\n display: grid;\n min-width: 0;\n flex: 1 1 auto;\n}\n.band-plugin-react-pp-name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.band-plugin-react-pp-name > :where(mark),\n.band-plugin-react-pp-id > :where(mark) {\n background: var(--accent-soft);\n color: inherit;\n border-radius: 2px;\n}\n.band-plugin-react-pp-id {\n font-family: var(--mono);\n font-size: var(--fs-meta);\n color: var(--muted);\n}\n.band-plugin-react-pp-sub {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--fs-meta);\n color: var(--muted);\n}\n.band-plugin-react-pp-meta {\n flex: none;\n font-size: var(--fs-meta);\n color: var(--muted);\n}\n.band-plugin-react-pp-chev {\n flex: none;\n width: 14px;\n text-align: center;\n color: var(--muted);\n}\n.band-plugin-react-pp-dept,\n.band-plugin-react-pp-all {\n flex: none;\n display: inline-grid;\n place-items: center;\n width: 20px;\n height: 20px;\n border-radius: 6px;\n background: var(--fill-2);\n color: var(--muted);\n font-size: var(--fs-meta);\n}\n.band-plugin-react-pp-dept > svg {\n width: 13px;\n height: 13px;\n fill: none;\n stroke: currentColor;\n stroke-width: 1.4;\n}\n.band-plugin-react-pp-state {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 18px 8px;\n color: var(--muted);\n font-size: var(--fs-row);\n text-align: center;\n}\n.band-plugin-react-pp-tuning > svg {\n width: 40px;\n height: 28px;\n}\n.band-plugin-react-pp-foot {\n padding: 4px 8px 2px;\n}\n@media (pointer: coarse), (max-width: 599px) {\n .band-plugin-react-pp-person {\n flex-wrap: wrap;\n }\n .band-plugin-react-pp-list {\n max-height: min(56vh, 420px);\n }\n}\n.band-plugin-react-pp-row:where(.is-off) .band-plugin-react-pp-name {\n color: var(--muted);\n}\n.band-plugin-react-pp-chosen {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n flex: none;\n max-width: 70%;\n height: 24px;\n padding: 0 4px 0 4px;\n border-radius: 999px;\n background: var(--fill-2);\n font-size: var(--fs-dense);\n white-space: nowrap;\n}\n.band-plugin-react-pp-chosen > button {\n border: 0;\n background: none;\n color: var(--muted);\n font: inherit;\n line-height: 1;\n padding: 0 4px;\n border-radius: 999px;\n}\n.band-plugin-react-pp-chosen > button:where(:focus-visible) {\n outline: none;\n box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--accent);\n}\n";
4
4
  let el = document.head.querySelector("style[data-band-style=\"@kanyun-ai-infra/band-plugin-react/components\"]");
5
5
  if (!el) {
6
6
  el = document.createElement("style");
@@ -14,35 +14,110 @@ import {
14
14
  AgentAvatar,
15
15
  Avatar,
16
16
  BandMark,
17
+ Combobox,
17
18
  ErrorNote,
19
+ FilterMenu,
18
20
  Glyph,
19
21
  INSTRUMENTS,
20
22
  InfoNote,
21
23
  LogoLockup,
22
24
  PaneHeader,
25
+ PersonPicker,
26
+ PersonSearch,
27
+ SettingsActions,
28
+ SettingsBack,
29
+ SettingsChoices,
30
+ SettingsDanger,
31
+ SettingsDangerRow,
32
+ SettingsDialog,
33
+ SettingsEmpty,
34
+ SettingsFacts,
35
+ SettingsField,
36
+ SettingsForm,
37
+ SettingsHead,
38
+ SettingsLayout,
39
+ SettingsLoading,
40
+ SettingsNoAccess,
41
+ SettingsNotice,
42
+ SettingsPicks,
43
+ SettingsReadError,
44
+ SettingsRow,
45
+ SettingsRows,
46
+ SettingsSaveState,
47
+ SettingsSaved,
48
+ SettingsSection,
49
+ SettingsSingle,
50
+ TagInput,
51
+ ToastHost,
23
52
  WorkshopEmblem,
24
53
  WorkshopIcon,
25
54
  agentInstrument,
26
55
  avatarInitial,
27
56
  avatarTone,
57
+ dismissAllToasts,
58
+ dismissToast,
59
+ facetedCount,
60
+ filterRows,
28
61
  instrumentOf,
29
- memberOrder
30
- } from "./chunk-ULDBT77D.js";
62
+ memberOrder,
63
+ peopleDirectory,
64
+ settingsLinkHandler,
65
+ splitTags,
66
+ toast
67
+ } from "./chunk-ER2ITOG5.js";
68
+ import "./chunk-VKASR4EL.js";
31
69
  export {
32
70
  AgentAvatar,
33
71
  Avatar,
34
72
  BandMark,
73
+ Combobox,
35
74
  ErrorNote,
75
+ FilterMenu,
36
76
  Glyph,
37
77
  INSTRUMENTS,
38
78
  InfoNote,
39
79
  LogoLockup,
40
80
  PaneHeader,
81
+ PersonPicker,
82
+ PersonSearch,
83
+ SettingsActions,
84
+ SettingsBack,
85
+ SettingsChoices,
86
+ SettingsDanger,
87
+ SettingsDangerRow,
88
+ SettingsDialog,
89
+ SettingsEmpty,
90
+ SettingsFacts,
91
+ SettingsField,
92
+ SettingsForm,
93
+ SettingsHead,
94
+ SettingsLayout,
95
+ SettingsLoading,
96
+ SettingsNoAccess,
97
+ SettingsNotice,
98
+ SettingsPicks,
99
+ SettingsReadError,
100
+ SettingsRow,
101
+ SettingsRows,
102
+ SettingsSaveState,
103
+ SettingsSaved,
104
+ SettingsSection,
105
+ SettingsSingle,
106
+ TagInput,
107
+ ToastHost,
41
108
  WorkshopEmblem,
42
109
  WorkshopIcon,
43
110
  agentInstrument,
44
111
  avatarInitial,
45
112
  avatarTone,
113
+ dismissAllToasts,
114
+ dismissToast,
115
+ facetedCount,
116
+ filterRows,
46
117
  instrumentOf,
47
- memberOrder
118
+ memberOrder,
119
+ peopleDirectory,
120
+ settingsLinkHandler,
121
+ splitTags,
122
+ toast
48
123
  };
package/dist/index.d.ts CHANGED
@@ -8,7 +8,8 @@ export { FIRST_DELIVERY_LABEL, FIRST_DELIVERY_PICK, FIRST_DELIVERY_REMOVE, FIRST
8
8
  import * as react from 'react';
9
9
  import { ReactNode, CompositionEvent, RefObject, KeyboardEvent } from 'react';
10
10
  export { FORBIDDEN_CODE, NETWORK_LOST, NETWORK_LOST_CODE, errorText, failedBecause, isForbidden, isNetworkLost } from './errors.js';
11
- export { AgentAvatar, Avatar, BandMark, ErrorNote, Glyph, GlyphKind, INSTRUMENTS, InfoNote, Instrument, LogoLockup, PaneHeader, WorkshopEmblem, WorkshopIcon, agentInstrument, avatarInitial, avatarTone, instrumentOf, memberOrder } from './components.js';
11
+ import { SettingsGroup, SettingsBackTarget, SettingsTarget } from './components.js';
12
+ export { AgentAvatar, Avatar, BandMark, BlockedPerson, Combobox, ComboboxItem, DirectoryPage, ErrorNote, FilterGroup, FilterMenu, FilterOption, FilterRow, FilterSelection, Glyph, GlyphKind, INSTRUMENTS, InfoNote, Instrument, LogoLockup, PaneHeader, PersonDirectory, PersonPicker, PersonPickerProps, PersonSearch, PersonSearchProps, PickerOrg, PickerPerson, SettingsActions, SettingsBack, SettingsChoices, SettingsDanger, SettingsDangerRow, SettingsDialog, SettingsEmpty, SettingsFact, SettingsFacts, SettingsField, SettingsFieldProps, SettingsForm, SettingsHead, SettingsLayout, SettingsLoading, SettingsNavItem, SettingsNoAccess, SettingsNotice, SettingsPick, SettingsPicks, SettingsReadError, SettingsRow, SettingsRows, SettingsSaveState, SettingsSaved, SettingsSection, SettingsSingle, TagInput, ToastAction, ToastHost, ToastItem, ToastKind, ToastOptions, WorkshopEmblem, WorkshopIcon, agentInstrument, avatarInitial, avatarTone, dismissAllToasts, dismissToast, facetedCount, filterRows, instrumentOf, memberOrder, peopleDirectory, settingsLinkHandler, splitTags, toast } from './components.js';
12
13
  import { ModelCredential, ProjectAgentModels } from '@kanyun-ai-infra/band-contracts/api';
13
14
  export { MODEL_CREDENTIAL_CHANGED, MODEL_NOT_CONFIGURED, MODEL_PROJECT_CONSENT_PENDING, MODEL_SELECTION_REQUIRED, MODEL_SERVICE_NOT_FOUND } from '@kanyun-ai-infra/band-contracts/api';
14
15
  export { scrollIntoPanel } from './scroll.js';
@@ -342,106 +343,6 @@ declare function useComposition(onEnd: (el: HTMLInputElement | HTMLTextAreaEleme
342
343
  };
343
344
  };
344
345
 
345
- /** 下拉里的一项。`group` 相同的排在一段,段的顺序按它第一次出现的顺序。 */
346
- interface ComboboxItem {
347
- value: string;
348
- label: string;
349
- group?: string;
350
- /** 行尾的补充说明(部门、类型),用等宽字体。 */
351
- meta?: string;
352
- /** label 之外用来搜索的文字(部门、拼音备注),不进占位提示。 */
353
- keywords?: string;
354
- }
355
- /**
356
- * 可搜索的单选 / 多选(样张 §2「Combobox」)。键盘:↑↓ 移动、回车选中、「空格」在多选里切换选中、
357
- * Esc 关闭、输入过滤;退格在空输入时删掉最后一个已选。
358
- *
359
- * 空格只在查询为空时切换选中:查询里带了字时空格照常输入,否则「Wang Min」这种名字搜不了
360
- * (样张只演示了空查询下的多选,这一点按能打字优先定)。
361
- */
362
- declare function Combobox({ label, items, value, onChange, multiple, placeholder, emptyText, onCreate, createLabel, disabled, }: {
363
- /** 输入框的无障碍名,也是空结果那句「没有匹配的<label>」里的名字。 */
364
- label: string;
365
- items: readonly ComboboxItem[];
366
- /** 受控:已选的值,按选中的先后。 */
367
- value: readonly string[];
368
- onChange(next: readonly string[]): void;
369
- /** 多选:回车与空格切换选中、列表不关;单选:回车选中并关闭。 */
370
- multiple?: boolean;
371
- placeholder?: string;
372
- /** 空结果那一行的整句,缺省「没有匹配的<label>」。 */
373
- emptyText?: string;
374
- /**
375
- * 查询非空、且没有名字正好相同的候选时,列表末尾多一行「新建」。选中它时把这句查询交回调用方
376
- * (建完由调用方把新值放进 `value`)。
377
- */
378
- onCreate?(name: string): void;
379
- /** 「新建」那行的写法,缺省「新建「<查询>」」。 */
380
- createLabel?(name: string): string;
381
- disabled?: boolean;
382
- }): react.JSX.Element;
383
- /**
384
- * 一段文字拆成标签:按逗号(半角、全角)、换行、制表符拆,去掉首尾空白与空串,**不去重**
385
- * (重复要提示,不能悄悄吃掉)。纯函数,单测与 TagInput 共用。
386
- */
387
- declare function splitTags(text: string): string[];
388
- /**
389
- * 数组值(样张 §2「Tag Input」):值受控,回车或逗号确认一个,粘贴带分隔符时整段拆开;重复的值不加入,
390
- * 已有的那个闪一下红底并在下面写一句(「「x」重复了,已跳过」,1.8 秒后退回);输入框空着时退格删最后一个。
391
- *
392
- * 输入法:回车、退格都经 `withImeGuard`——组字中选字的回车不能当成「加一个标签」。
393
- */
394
- declare function TagInput({ label, value, onChange, placeholder, hint, disabled, id, }: {
395
- /** 输入框的无障碍名。 */
396
- label: string;
397
- /** 受控:标签,按加入的先后。 */
398
- value: readonly string[];
399
- onChange(next: readonly string[]): void;
400
- placeholder?: string;
401
- /** 常态那句说明(「粘贴「五年级, 分数」会拆成两个」);重复时换成提示,1.8 秒后退回这句。 */
402
- hint?: string;
403
- disabled?: boolean;
404
- id?: string;
405
- }): react.JSX.Element;
406
- /** 筛选项:一段里的一个值。 */
407
- interface FilterOption {
408
- value: string;
409
- label: string;
410
- }
411
- /** 一段筛选:`key` 是行数据里的字段名。 */
412
- interface FilterGroup {
413
- key: string;
414
- label: string;
415
- options: readonly FilterOption[];
416
- }
417
- /** 一行在各分组上的取值(`row[group.key]`)。 */
418
- type FilterRow = Readonly<Record<string, string>>;
419
- /** 已选:分组 key → 选中的值(段内是「或」)。 */
420
- type FilterSelection = Readonly<Record<string, readonly string[]>>;
421
- /**
422
- * 计数(样张 §2「Filter Menu」的 faceted 口径):某个选项的计数 = 在**其他**分组的已选条件下还剩多少行,
423
- * 也带自己这一段——和产物库的「勾了别的组,这一段的数跟着缩」同一口径。纯函数,单测与 FilterMenu 共用。
424
- */
425
- declare function facetedCount(rows: readonly FilterRow[], groups: readonly FilterGroup[], selection: FilterSelection, groupKey: string, value: string): number;
426
- /** 按已选筛行:每组内是「或」,组之间是「且」。纯函数。 */
427
- declare function filterRows(rows: readonly FilterRow[], groups: readonly FilterGroup[], selection: FilterSelection): readonly FilterRow[];
428
- /**
429
- * 分组筛选(样张 §2「Filter Menu」)。分组可折叠(组标题是按钮,`aria-expanded`),计数按当前其他分组
430
- * 的已选算(`facetedCount`),已选的做成 chip 可单个移除,右端「清空」。值受控。
431
- *
432
- * 键盘:组标题与每个勾选框都在正常的 Tab 顺序里(勾选框是原生 `<input type="checkbox">`),空格切换;
433
- * 点组标题只折叠/展开,不改筛选。
434
- */
435
- declare function FilterMenu({ groups, rows, value, onChange, emptyText, }: {
436
- groups: readonly FilterGroup[];
437
- /** 用来算计数的行(通常是未筛选的全量;传筛过的会让计数越筛越小)。 */
438
- rows: readonly FilterRow[];
439
- value: FilterSelection;
440
- onChange(next: FilterSelection): void;
441
- /** 一段里一个选项都没有时那一行,缺省「没有可筛的」。 */
442
- emptyText?: string;
443
- }): react.JSX.Element;
444
-
445
346
  /** 重跑上一回合没做成或停下的阶段 `stage`(宿主给的 `retryStage`);没有 submit-change 的人置灰(服务端照旧逐动作判)。 */
446
347
  declare function Retry({ ctx, stage }: {
447
348
  ctx: ProjectCtx;
@@ -953,7 +854,7 @@ declare function useReactionPatches(ctx: Pick<ProjectCtx, "events" | "threads">,
953
854
  * 消息间移动,`Home` `End` 到头尾。返回值挂在列表容器上。
954
855
  */
955
856
  declare function useMessageList<T extends HTMLElement>(): {
956
- ref: RefObject<T>;
857
+ ref: RefObject<T | null>;
957
858
  onKeyDown: (e: KeyboardEvent<T>) => void;
958
859
  onFocus: (e: React.FocusEvent<T>) => void;
959
860
  };
@@ -1023,56 +924,6 @@ declare function MemoryNote({ ctx, turnId }: {
1023
924
  turnId: string;
1024
925
  }): react.JSX.Element | null;
1025
926
 
1026
- /**
1027
- * 页面里的 toast(backlog #5):刚做完一件事的即时回执。宿主(外壳)画唯一一层容器 `ToastHost`,
1028
- * 插件与锁定插件只 import 这里的 `toast()` 入队,不自己画容器——两个插件同时弹也落进同一摞,不会各画一层。
1029
- *
1030
- * 模块级 store 是有意为之:`@kanyun-ai-infra/band-plugin-react` 是宿主提供的共享模块,宿主与每个插件拿到同一个
1031
- * 实例;而每个插件各开一个 React root,React context 跨不过去,ctx 也没有这个能力(加它要改协议)。
1032
- *
1033
- * 规则照样张(docs/design/specimens/band-design-components.html §5,本卡按它实现):
1034
- * - 成功 4 秒自己收;鼠标停在上面时不收,移开后 2 秒再收;
1035
- * - 错误不自己走,要么点「重试」要么关掉(没给动作时容器补一个「关闭」);
1036
- * - 进行中做完在同一条里变成勾(用同一个 id 再调一次 `toast`),不新弹一条;
1037
- * - 同时最多三条,第四条挤掉最早的一条(进行中的先留着)。
1038
- *
1039
- * 模块级状态跟着页面活:测试要清干净用 `dismissAllToasts`。
1040
- */
1041
- type ToastKind = "ok" | "bad" | "busy";
1042
- /** toast 上的一个动作(错误一般是「重试」)。 */
1043
- interface ToastAction {
1044
- label: string;
1045
- onClick: () => void;
1046
- }
1047
- interface ToastOptions {
1048
- /** 缺省 `ok`。 */
1049
- kind?: ToastKind;
1050
- /** 一行说明。 */
1051
- text: string;
1052
- /** 第二行小字。 */
1053
- detail?: string;
1054
- /** 一个动作;错误的「重试」放这里。 */
1055
- action?: ToastAction;
1056
- /** 传已有的 id:改那一条(进行中做完变成勾),不新弹一条。 */
1057
- id?: string;
1058
- }
1059
- interface ToastItem {
1060
- id: string;
1061
- kind: ToastKind;
1062
- text: string;
1063
- detail?: string;
1064
- action?: ToastAction;
1065
- }
1066
- /** 弹一条;传 `id` 就是改那一条。返回它的 id。 */
1067
- declare function toast(opts: ToastOptions): string;
1068
- /** 收起一条(动作、Esc、关掉都走这里)。 */
1069
- declare function dismissToast(id: string): void;
1070
- /** 全部收掉(换身份、测试收尾)。 */
1071
- declare function dismissAllToasts(): void;
1072
-
1073
- /** 宿主画的一次性容器;一页只有一个(`band-shell`)。插件调 `toast()`,不自己画。 */
1074
- declare function ToastHost(): react.JSX.Element;
1075
-
1076
927
  /**
1077
928
  * Rondo 状态消息与回执页脚的写法([note](../../../../.agents/notes/proposed/feature/2026-10-28-agent-presence-in-thread.md)
1078
929
  * §3、§7):用时怎么念、回执页脚那一句怎么拼。纯函数,`band-chat`、`band-comment`、`band-turn-bar` 共用。
@@ -1245,4 +1096,66 @@ declare function Markdown({ text, breaks }: {
1245
1096
  breaks?: boolean;
1246
1097
  }): react.JSX.Element;
1247
1098
 
1248
- export { type AddableItem, type AttachSource, Combobox, type ComboboxItem, type Draft, type DraftItem, ExternalImportPanel, type ExternalImportSource, type FileCheck, type FileItem, type FileLimits, type FilterGroup, FilterMenu, type FilterOption, type FilterRow, type FilterSelection, FirstDeliveryAction, type FirstTurnEnd, MODELS_FOR_PAGE, MODEL_NEEDS_PERSONAL, MODEL_NEEDS_SETTINGS, MODEL_PROVISION_REASON, MODEL_REQUIRED_REASON, Markdown, type MemoNote, MemoryNote, Message, MessageAttachments, type MessageAttachmentsProps, type MessageProps, ModelHint, Mount, NO_KEY_BUTTON, NO_KEY_TEXT, NoKeyNotice, PASTE_FOLD_CHARS, PERSONAL_MODELS_PAGE, PROJECT_MODEL_HEADING, PROJECT_MODEL_NEEDS_ME, PROJECT_MODEL_SPEND, type PendingReaction, type PluginState, type ProjectModelNeeds, PromptInput, type PromptInputProps, QUOTE_DRAW, REACTION_MEANING, REPO_URL_EXAMPLE, RESUME_PAGE, type RefCandidate, type RefItem, Retry, STAGE_EVENTS, STATUS_CHIP, STOPPED_UNDONE, STOP_COST, type SelectedEntity, type ShownReaction, type StallView, StatusMessage, StopTurn, TARGET_REPO_DOCS, THREAD_EVENTS, TURN_STATUS_ATTR, TagInput, TargetRepoNote, type ToastAction, ToastHost, type ToastItem, type ToastKind, type ToastOptions, type Trigger, TurnStopped, type TurnStoppedEvent, type Uploader, VersionReference, type VersionReferenceInfo, type VersionReferences, afterSend, agentIn, agentLabel, alreadyHandedText, anchorLabel, anchorQuote, canRestoreProject, checkFiles, composerSpendLine, createState, credentialOptionLabel, defaultOf, deletedProjectText, dismissAllToasts, dismissToast, draftFileBytes, durationText, emptyDraft, entriesFor, errorRepo, errorRequestAccessUrl, estimateMinutesText, facetedCount, failed, failureReason, fileExt, filterByQuery, filterRows, firstTurnEnd, flushAllDrafts, formatBytes, gateRule, gateWho, hasContent, importConnector, importFrom, inline, isModelRequired, isProvisionFailure, isThreadTail, itemKey, loadVersionReferences, localDay, markdownOf, memberName, memoNote, memoryItem, mentionCandidates, mentionQuery, mentionsIn, mergeReactions, modelHintText, parseDraft, parseMemoryItem, persistable, personalImportSource, personalImportSources, plainText, popoverLeft, projectModelNeedsOf, projectModelNeedsText, projectModelNote, provisionConsentText, queuePosition, queueSlot, queuedMessages, quoteFace, quoteLine, reactMount, reactedBy, reactionLabel, reactionWho, readComments, receiptFileNames, receiptFooter, refTargets, registerDraftFlusher, rejectionText, replaceRange, repoFieldHint, roleLabel, saveDraft, settledPending, shortTime, shortWhen, splitTags, stallNoteOf, statusText, stopQueuedNote, takeDraft, targetRepoErrorId, threadConfirmation, threadPath, toMessageExtras, toast, triggerAt, turnEndWord, turnStoppedOf, uploadFailureLines, uploading, useAppData, useArtifactRole, useComposition, useCtxData, useDraft, useElapsed, useHandToAgent, useMembers, useMessageList, useNow, useProjectAttachments, useReactionPatches, useRoute, useSelectedArtifact, useSelectedEntity, useSettledText, useSlotEntries, useStateOf, useTurnStatusOnPage, useUnsavedGuard, useVersionReferences, usualDurationText, versionLabel, versionReferenceLabel, versionReferenceText, wasStopped };
1099
+ /** 宿主跳转的最小面:AppCtx 与 ProjectCtx 的 `app` 都有。 */
1100
+ type Navigator = Pick<AppCtx, "app">;
1101
+ /** 先过未保存守卫再跳:设置里所有页内链接都走这里。 */
1102
+ declare function settingsNavigate(ctx: Navigator, target: SettingsTarget): void;
1103
+ /** 链接的点击处理:只在主键上点(没按修饰键)时走页内跳转;其余交给浏览器(新标签页)。 */
1104
+ declare function settingsLink(ctx: Navigator, page: string, params?: Record<string, string>): (e: react.MouseEvent<HTMLAnchorElement>) => void;
1105
+ /**
1106
+ * 现在是不是手机宽度。目录页(`/settings` 与项目设置的根地址)据此二选一:窄屏导航自成一页,
1107
+ * 宽屏旁边就是导航,内容区直接画第一个分区。
1108
+ */
1109
+ declare function useNarrow(): boolean;
1110
+ /**
1111
+ * 骨架在内容区上挂一次:给表单控件记初始值,离开前比一次。
1112
+ *
1113
+ * 上一页的卸载是**推迟一拍**做的(`reactMount` 的清理在 setTimeout 里):换地址时新页先挂上、旧页后卸,
1114
+ * 旧页的清理不能把新页刚装好的那份探针抹掉,所以清理前先认一下是不是自己那份。
1115
+ */
1116
+ declare function useLeaveGuard(root: RefObject<HTMLElement | null>): void;
1117
+ /**
1118
+ * 离开这一页:填过东西就先问({@link SettingsLeaveDialog}),没填过就直接走。
1119
+ * 表单的「取消」也走这里,免得只有导航链接被拦住、取消照旧一走了之。
1120
+ */
1121
+ declare function leaveThen(go: () => void): void;
1122
+ /**
1123
+ * 四个作用域共用的外框:{@link SettingsLayout} 加上按 ctx 跳转、未保存离开的守卫与确认弹窗。
1124
+ * 作用域只决定导航头与分区名单。
1125
+ */
1126
+ declare function SettingsFrame({ ctx, navLabel, title, obj, crumb, groups, current, view, back, backMobile, children, }: {
1127
+ ctx: Navigator;
1128
+ navLabel: string;
1129
+ title: string;
1130
+ obj?: ReactNode;
1131
+ crumb?: ReactNode;
1132
+ groups: readonly SettingsGroup[];
1133
+ current?: string | undefined;
1134
+ view?: "page" | "index";
1135
+ back?: SettingsBackTarget | undefined;
1136
+ backMobile?: SettingsBackTarget | undefined;
1137
+ children: ReactNode;
1138
+ }): react.JSX.Element;
1139
+ /** 记下「刚存的那一条」:目标分区的列表挂上时那一行垫 `--ok-soft` 标出来。 */
1140
+ declare function markFresh(slug: string, id: string): void;
1141
+ /** 一次建了几条时全标出来。 */
1142
+ declare function markFreshMany(slug: string, ids: readonly string[]): void;
1143
+ /** 分区页挂上来时报到:挂上来的不是写下它的那个分区(目录页也算「不是」),槽里的东西一律作废。 */
1144
+ declare function enterSection(slug: string | null): void;
1145
+ /** 读「刚存的那一条」,不清(清在挂上之后:StrictMode 会重放初始化器)。 */
1146
+ declare function peekFresh(slug: string): string | null;
1147
+ declare function peekFreshAll(slug: string): readonly string[];
1148
+ declare function clearFresh(): void;
1149
+ /** 记下一句跨页的提示(「已保存」「已删除」「已撤销」),写明它要给哪个分区。 */
1150
+ declare function markNotice(slug: string, text: string): void;
1151
+ /** 取走那句提示:只给一次,且只给它写明的那个分区。 */
1152
+ declare function takeNotice(slug: string): string | null;
1153
+ /** 列表页的「刚存的那一条」:挂上后读一次并在这一帧之后清掉。 */
1154
+ declare function useFreshRow(slug: string): string | null;
1155
+ declare function useFreshRows(slug: string): readonly string[];
1156
+ /** 「已保存」停四拍(2s)就走:一句话加一个计时器,`flash` 一调用就重新计时。 */
1157
+ declare function useSavedNote(): [string, (text: string) => void];
1158
+ /** 跨页提示落到本页:挂上后取一次(放在 effect 里:`aria-live` 只在内容变化时播报)。 */
1159
+ declare function useCrossPageNotice(slug: string): [string, (text: string) => void];
1160
+
1161
+ export { type AddableItem, type AttachSource, type Draft, type DraftItem, ExternalImportPanel, type ExternalImportSource, type FileCheck, type FileItem, type FileLimits, FirstDeliveryAction, type FirstTurnEnd, MODELS_FOR_PAGE, MODEL_NEEDS_PERSONAL, MODEL_NEEDS_SETTINGS, MODEL_PROVISION_REASON, MODEL_REQUIRED_REASON, Markdown, type MemoNote, MemoryNote, Message, MessageAttachments, type MessageAttachmentsProps, type MessageProps, ModelHint, Mount, NO_KEY_BUTTON, NO_KEY_TEXT, NoKeyNotice, PASTE_FOLD_CHARS, PERSONAL_MODELS_PAGE, PROJECT_MODEL_HEADING, PROJECT_MODEL_NEEDS_ME, PROJECT_MODEL_SPEND, type PendingReaction, type PluginState, type ProjectModelNeeds, PromptInput, type PromptInputProps, QUOTE_DRAW, REACTION_MEANING, REPO_URL_EXAMPLE, RESUME_PAGE, type RefCandidate, type RefItem, Retry, STAGE_EVENTS, STATUS_CHIP, STOPPED_UNDONE, STOP_COST, type SelectedEntity, SettingsBackTarget, SettingsFrame, SettingsGroup, SettingsTarget, type ShownReaction, type StallView, StatusMessage, StopTurn, TARGET_REPO_DOCS, THREAD_EVENTS, TURN_STATUS_ATTR, TargetRepoNote, type Trigger, TurnStopped, type TurnStoppedEvent, type Uploader, VersionReference, type VersionReferenceInfo, type VersionReferences, afterSend, agentIn, agentLabel, alreadyHandedText, anchorLabel, anchorQuote, canRestoreProject, checkFiles, clearFresh, composerSpendLine, createState, credentialOptionLabel, defaultOf, deletedProjectText, draftFileBytes, durationText, emptyDraft, enterSection, entriesFor, errorRepo, errorRequestAccessUrl, estimateMinutesText, failed, failureReason, fileExt, filterByQuery, firstTurnEnd, flushAllDrafts, formatBytes, gateRule, gateWho, hasContent, importConnector, importFrom, inline, isModelRequired, isProvisionFailure, isThreadTail, itemKey, leaveThen, loadVersionReferences, localDay, markFresh, markFreshMany, markNotice, markdownOf, memberName, memoNote, memoryItem, mentionCandidates, mentionQuery, mentionsIn, mergeReactions, modelHintText, parseDraft, parseMemoryItem, peekFresh, peekFreshAll, persistable, personalImportSource, personalImportSources, plainText, popoverLeft, projectModelNeedsOf, projectModelNeedsText, projectModelNote, provisionConsentText, queuePosition, queueSlot, queuedMessages, quoteFace, quoteLine, reactMount, reactedBy, reactionLabel, reactionWho, readComments, receiptFileNames, receiptFooter, refTargets, registerDraftFlusher, rejectionText, replaceRange, repoFieldHint, roleLabel, saveDraft, settingsLink, settingsNavigate, settledPending, shortTime, shortWhen, stallNoteOf, statusText, stopQueuedNote, takeDraft, takeNotice, targetRepoErrorId, threadConfirmation, threadPath, toMessageExtras, triggerAt, turnEndWord, turnStoppedOf, uploadFailureLines, uploading, useAppData, useArtifactRole, useComposition, useCrossPageNotice, useCtxData, useDraft, useElapsed, useFreshRow, useFreshRows, useHandToAgent, useLeaveGuard, useMembers, useMessageList, useNarrow, useNow, useProjectAttachments, useReactionPatches, useRoute, useSavedNote, useSelectedArtifact, useSelectedEntity, useSettledText, useSlotEntries, useStateOf, useTurnStatusOnPage, useUnsavedGuard, useVersionReferences, usualDurationText, versionLabel, versionReferenceLabel, versionReferenceText, wasStopped };