@teaflask/assistant 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/README.md +1 -1
  2. package/custom-elements.json +264 -0
  3. package/dist/affordances/aria-dropdowns.js +315 -0
  4. package/dist/affordances/aria-toggles.js +39 -0
  5. package/dist/affordances/dropdown-display.js +129 -0
  6. package/dist/affordances/page-gestures.js +91 -0
  7. package/dist/affordances/prefill-reasons.js +75 -0
  8. package/dist/affordances/prefill.js +113 -62
  9. package/dist/appearance/theme.d.ts +138 -0
  10. package/dist/components/approval-card.js +3 -3
  11. package/dist/components/approval-context.d.ts +20 -0
  12. package/dist/components/assistant-companion.d.ts +15 -0
  13. package/dist/components/assistant-page.d.ts +61 -0
  14. package/dist/components/assistant-palette.d.ts +12 -0
  15. package/dist/components/assistant-palette.js +2 -2
  16. package/dist/components/child-transcript.js +1 -1
  17. package/dist/components/companion-header-disclosure.js +1 -1
  18. package/dist/components/companion-history-menu.js +1 -1
  19. package/dist/components/composer.js +11 -65
  20. package/dist/components/conversation-context.d.ts +6 -0
  21. package/dist/components/conversation-gate-card.js +1 -1
  22. package/dist/components/conversation-view.d.ts +11 -0
  23. package/dist/components/elicitation-context.d.ts +39 -0
  24. package/dist/components/model-picker-chip.js +4 -2
  25. package/dist/components/primitives/button.js +25 -17
  26. package/dist/components/primitives/floating-panel.js +1 -1
  27. package/dist/components/provider-chip.js +8 -1
  28. package/dist/components/question-panel-footer.js +1 -1
  29. package/dist/components/react-tool-view.d.ts +7 -0
  30. package/dist/components/subagent-count-pill.js +2 -2
  31. package/dist/components/subagent-group-row.js +1 -26
  32. package/dist/components/subagent-preview-popover.js +1 -1
  33. package/dist/components/subscription-connect-arms.js +6 -4
  34. package/dist/components/subscription-connect-flow.js +30 -45
  35. package/dist/components/subscription-connected-standing.js +9 -6
  36. package/dist/components/subscription-plan-notice.js +4 -2
  37. package/dist/components/teaflask-assistant-provider.d.ts +99 -0
  38. package/dist/components/teaflask-assistant.d.ts +33 -0
  39. package/dist/components/tool-views/action-view.js +1 -1
  40. package/dist/components/tool-views/parts-classes.d.ts +5 -5
  41. package/dist/components/tool-views/parts-classes.js +5 -5
  42. package/dist/components/tool-views/parts.d.ts +44 -0
  43. package/dist/components/tool-views/questions-view.js +2 -2
  44. package/dist/components/tool-views/view-dom.d.ts +76 -0
  45. package/dist/components/transcript.js +2 -2
  46. package/dist/components/use-assistant-activity.d.ts +5 -0
  47. package/dist/components/use-assistant-conversation.d.ts +99 -2
  48. package/dist/components/use-store-cell.d.ts +5 -0
  49. package/dist/components/use-thread-dispatches.js +8 -366
  50. package/dist/components/use-transcript-folds.js +2 -1
  51. package/dist/components/use-transcript.d.ts +55 -2
  52. package/dist/components/use-transcript.js +7 -2
  53. package/dist/contract/actions-adapter.d.ts +78 -0
  54. package/dist/contract/errors.d.ts +6 -1
  55. package/dist/contract/events.d.ts +1 -3
  56. package/dist/contract/identity.d.ts +1 -1
  57. package/dist/contract/subscriptions.d.ts +2 -2
  58. package/dist/contract/subscriptions.js +1 -1
  59. package/dist/contract/telemetry.d.ts +45 -0
  60. package/dist/contract/threads.d.ts +5 -1
  61. package/dist/core/activity.d.ts +44 -0
  62. package/dist/core/approval-inbox.d.ts +69 -0
  63. package/dist/core/assistant-session-registry.js +15 -0
  64. package/dist/core/composer-attachments.js +82 -0
  65. package/dist/core/composer-input-state.js +1 -0
  66. package/dist/core/composer-policy.d.ts +20 -0
  67. package/dist/core/connection-epoch.d.ts +65 -2
  68. package/dist/core/conversation-adoption.js +3 -0
  69. package/dist/core/conversation-contract.d.ts +112 -1
  70. package/dist/core/conversation-publish.js +1 -0
  71. package/dist/core/conversation-store.d.ts +3 -0
  72. package/dist/core/conversation-store.js +7 -0
  73. package/dist/core/dispatch-poll.js +81 -0
  74. package/dist/core/elicitation-answers.js +12 -0
  75. package/dist/core/elicitation-cards.d.ts +14 -0
  76. package/dist/core/elicitation-pickers.d.ts +16 -0
  77. package/dist/core/execution-handlers.js +3 -3
  78. package/dist/core/memory-provenance-anchors.d.ts +16 -0
  79. package/dist/core/observable-cell.d.ts +12 -0
  80. package/dist/core/pending-decision-gap.d.ts +9 -0
  81. package/dist/core/question-drafts.d.ts +59 -0
  82. package/dist/core/receipt-anchors.d.ts +9 -0
  83. package/dist/core/segment-timing.d.ts +23 -0
  84. package/dist/core/subagent-delivery-anchors.d.ts +7 -0
  85. package/dist/core/subagent-ledger-join.js +176 -0
  86. package/dist/core/subagent-rows.d.ts +68 -0
  87. package/dist/core/thread-dispatch-ledger.js +303 -0
  88. package/dist/core/tool-call-display.d.ts +71 -0
  89. package/dist/core/tool-call-presentation.d.ts +34 -1
  90. package/dist/core/tool-call-presentation.js +0 -1
  91. package/dist/core/tool-schema-anchors.d.ts +6 -0
  92. package/dist/core/tool-view.d.ts +174 -1
  93. package/dist/core/transcript-rows.d.ts +138 -3
  94. package/dist/core/turn-failed-anchors.d.ts +4 -0
  95. package/dist/core/user-turn-ledger.d.ts +3 -0
  96. package/dist/generated/models/apiErrorCode.d.ts +1 -0
  97. package/dist/generated/models/apiErrorCode.js +1 -0
  98. package/dist/generated/models/assistantTurnStatus.d.ts +16 -0
  99. package/dist/generated/models/servingAssistantThreadResponse.d.ts +23 -0
  100. package/dist/generated/models/servingAttachmentResponse.d.ts +29 -0
  101. package/dist/generated/models/servingErrorCode.d.ts +18 -0
  102. package/dist/generated/models/servingTurnAttachmentResponse.d.ts +12 -0
  103. package/dist/generated/models/siteTheme.d.ts +1 -0
  104. package/dist/generated/models/thinkingEffort.d.ts +10 -0
  105. package/dist/generated/models/threadModelPickResponse.d.ts +12 -0
  106. package/dist/headless.d.ts +9 -4
  107. package/dist/index.d.ts +2 -6
  108. package/dist/index.js +0 -3
  109. package/dist/persistence/stored-thread.d.ts +5 -0
  110. package/dist/reader/render.js +7 -4
  111. package/dist/reader/roles.js +28 -1
  112. package/dist/reader/snapshot-node.js +2 -29
  113. package/dist/reader/snapshot-root.js +14 -8
  114. package/dist/reader/snapshot.js +6 -1
  115. package/dist/styles.css +1 -1
  116. package/dist/transport/serving-error.d.ts +21 -0
  117. package/package.json +6 -25
  118. package/dist/affordances/highlight.d.ts +0 -3
  119. package/dist/affordances/prefill.d.ts +0 -14
  120. package/dist/components/activity-rail.d.ts +0 -12
  121. package/dist/components/activity-shelf.d.ts +0 -7
  122. package/dist/components/agent-identity-mark.d.ts +0 -7
  123. package/dist/components/appearance-context.d.ts +0 -14
  124. package/dist/components/approval-card.d.ts +0 -7
  125. package/dist/components/assistant-palette-body.d.ts +0 -3
  126. package/dist/components/assistant-transcript.d.ts +0 -47
  127. package/dist/components/attachment-chips.d.ts +0 -4
  128. package/dist/components/child-transcript.d.ts +0 -22
  129. package/dist/components/companion-drawer-body.d.ts +0 -1
  130. package/dist/components/companion-drawer.d.ts +0 -10
  131. package/dist/components/companion-header-disclosure.d.ts +0 -20
  132. package/dist/components/companion-history-menu.d.ts +0 -15
  133. package/dist/components/companion-mark-image.d.ts +0 -3
  134. package/dist/components/companion-mark-image.js +0 -18
  135. package/dist/components/companion-mark.d.ts +0 -1
  136. package/dist/components/companion-mode-menu.d.ts +0 -15
  137. package/dist/components/composer-attachment-chip.d.ts +0 -7
  138. package/dist/components/composer-banner.d.ts +0 -4
  139. package/dist/components/composer.d.ts +0 -4
  140. package/dist/components/conversation-gate-card.d.ts +0 -8
  141. package/dist/components/conversation-surfaces-provider.d.ts +0 -6
  142. package/dist/components/copy-text-button.d.ts +0 -5
  143. package/dist/components/elicitation-receipt-row.d.ts +0 -4
  144. package/dist/components/human-file-size.d.ts +0 -1
  145. package/dist/components/icons.d.ts +0 -15
  146. package/dist/components/lazy-body.d.ts +0 -4
  147. package/dist/components/markdown/assistant-markdown.d.ts +0 -3
  148. package/dist/components/markdown/code-block.d.ts +0 -4
  149. package/dist/components/markdown/highlight.d.ts +0 -1
  150. package/dist/components/markdown/markdown-structure.d.ts +0 -16
  151. package/dist/components/markdown/memoized-blocks.d.ts +0 -6
  152. package/dist/components/markdown/paced-assistant-markdown.d.ts +0 -4
  153. package/dist/components/markdown/reveal-pacer.d.ts +0 -20
  154. package/dist/components/markdown/shiki-highlighter.d.ts +0 -1
  155. package/dist/components/markdown/streaming-repair.d.ts +0 -1
  156. package/dist/components/markdown/use-highlighted-html.d.ts +0 -1
  157. package/dist/components/markdown/use-paced-reveal.d.ts +0 -5
  158. package/dist/components/memory-updated-footer.d.ts +0 -4
  159. package/dist/components/message-list-row.d.ts +0 -13
  160. package/dist/components/message-list-slots.d.ts +0 -25
  161. package/dist/components/message-list-slots.js +0 -1
  162. package/dist/components/message-list.d.ts +0 -23
  163. package/dist/components/model-picker-chip.d.ts +0 -1
  164. package/dist/components/model-picker-effort.d.ts +0 -4
  165. package/dist/components/model-picker-panels.d.ts +0 -22
  166. package/dist/components/notice-banner.d.ts +0 -8
  167. package/dist/components/operation-icons.d.ts +0 -19
  168. package/dist/components/pretty-print.d.ts +0 -1
  169. package/dist/components/primitives/autofocus.d.ts +0 -1
  170. package/dist/components/primitives/button.d.ts +0 -10
  171. package/dist/components/primitives/cx.d.ts +0 -1
  172. package/dist/components/primitives/dialog.d.ts +0 -7
  173. package/dist/components/primitives/disclosure.d.ts +0 -22
  174. package/dist/components/primitives/file-input.d.ts +0 -5
  175. package/dist/components/primitives/floating-panel.d.ts +0 -15
  176. package/dist/components/primitives/kbd.d.ts +0 -2
  177. package/dist/components/primitives/sheet.d.ts +0 -11
  178. package/dist/components/primitives/sheet.js +0 -18
  179. package/dist/components/primitives/textarea.d.ts +0 -7
  180. package/dist/components/primitives/use-dock-reflow.d.ts +0 -2
  181. package/dist/components/primitives/use-swipe-dismiss.d.ts +0 -17
  182. package/dist/components/provider-chip.d.ts +0 -8
  183. package/dist/components/question-panel-answers.d.ts +0 -29
  184. package/dist/components/question-panel-footer.d.ts +0 -9
  185. package/dist/components/question-panel.d.ts +0 -4
  186. package/dist/components/reasoning-row.d.ts +0 -4
  187. package/dist/components/receipt-rows.d.ts +0 -3
  188. package/dist/components/run-status-announcer.d.ts +0 -5
  189. package/dist/components/scroll-follow-guards.d.ts +0 -1
  190. package/dist/components/served-suggestions.d.ts +0 -3
  191. package/dist/components/slot-boundary.d.ts +0 -11
  192. package/dist/components/standing-poll.d.ts +0 -1
  193. package/dist/components/streaming-states.d.ts +0 -12
  194. package/dist/components/subagent-count-pill.d.ts +0 -8
  195. package/dist/components/subagent-current-work.d.ts +0 -6
  196. package/dist/components/subagent-delegation-surface.d.ts +0 -9
  197. package/dist/components/subagent-delivery-divider.d.ts +0 -5
  198. package/dist/components/subagent-drill-in.d.ts +0 -8
  199. package/dist/components/subagent-execution-work.d.ts +0 -3
  200. package/dist/components/subagent-group-row.d.ts +0 -26
  201. package/dist/components/subagent-preview-popover.d.ts +0 -8
  202. package/dist/components/subscription-connect-arms.d.ts +0 -25
  203. package/dist/components/subscription-connect-flow.d.ts +0 -60
  204. package/dist/components/subscription-connected-standing.d.ts +0 -16
  205. package/dist/components/subscription-plan-notice.d.ts +0 -1
  206. package/dist/components/subscription-recheck.d.ts +0 -10
  207. package/dist/components/surface-boundary.d.ts +0 -8
  208. package/dist/components/suspension-surfaces.d.ts +0 -3
  209. package/dist/components/thread-list.d.ts +0 -16
  210. package/dist/components/tool-arguments-summary.d.ts +0 -2
  211. package/dist/components/tool-call-rows.d.ts +0 -10
  212. package/dist/components/tool-row.d.ts +0 -7
  213. package/dist/components/tool-view-registry-context.d.ts +0 -3
  214. package/dist/components/tool-view-slot.d.ts +0 -11
  215. package/dist/components/tool-views/action-view.d.ts +0 -1
  216. package/dist/components/tool-views/command-view.d.ts +0 -1
  217. package/dist/components/tool-views/docs-search-view.d.ts +0 -10
  218. package/dist/components/tool-views/file-edit-view.d.ts +0 -1
  219. package/dist/components/tool-views/questions-view.d.ts +0 -1
  220. package/dist/components/transcript.d.ts +0 -3
  221. package/dist/components/use-agent-subscriber.d.ts +0 -3
  222. package/dist/components/use-agent-subscriber.js +0 -13
  223. package/dist/components/use-answer-list-fold.d.ts +0 -6
  224. package/dist/components/use-assistant-surface-presence.d.ts +0 -2
  225. package/dist/components/use-child-replay-stream.d.ts +0 -20
  226. package/dist/components/use-latest-ref.d.ts +0 -2
  227. package/dist/components/use-member-toggle-outrank.d.ts +0 -6
  228. package/dist/components/use-perch-clearance.d.ts +0 -2
  229. package/dist/components/use-question-panel-keys.d.ts +0 -32
  230. package/dist/components/use-register-assistant-surface.d.ts +0 -2
  231. package/dist/components/use-resolved-theme-mode.d.ts +0 -3
  232. package/dist/components/use-roster-disclosure.d.ts +0 -20
  233. package/dist/components/use-roster-preview.d.ts +0 -24
  234. package/dist/components/use-thread-dispatches.d.ts +0 -8
  235. package/dist/components/use-transcript-folds.d.ts +0 -26
  236. package/dist/components/user-message.d.ts +0 -6
  237. package/dist/contract/actions-adapter.js +0 -1
  238. package/dist/contract/assistant-config.js +0 -1
  239. package/dist/contract/dispatches.d.ts +0 -15
  240. package/dist/contract/errors.js +0 -1
  241. package/dist/contract/identity.js +0 -1
  242. package/dist/core/activity-title.d.ts +0 -1
  243. package/dist/core/agent-identity.d.ts +0 -2
  244. package/dist/core/approval-decision.d.ts +0 -6
  245. package/dist/core/approval-resolved.d.ts +0 -7
  246. package/dist/core/assistant-prose.d.ts +0 -2
  247. package/dist/core/assistant-session-registry.d.ts +0 -51
  248. package/dist/core/attachment-uploads.d.ts +0 -5
  249. package/dist/core/block-timing-anchors.d.ts +0 -5
  250. package/dist/core/companion-drawer-flag.d.ts +0 -4
  251. package/dist/core/companion-presence.d.ts +0 -7
  252. package/dist/core/composer-input-state.d.ts +0 -8
  253. package/dist/core/connection-driver.d.ts +0 -3
  254. package/dist/core/conversation-adoption.d.ts +0 -13
  255. package/dist/core/conversation-contract.js +0 -1
  256. package/dist/core/conversation-publish.d.ts +0 -8
  257. package/dist/core/conversation-refresh.d.ts +0 -4
  258. package/dist/core/conversation-send.d.ts +0 -6
  259. package/dist/core/disposable-subscriber.d.ts +0 -6
  260. package/dist/core/disposable-subscriber.js +0 -18
  261. package/dist/core/dock-reflow.d.ts +0 -5
  262. package/dist/core/elicitation-answers.d.ts +0 -7
  263. package/dist/core/epoch-sync.d.ts +0 -12
  264. package/dist/core/error-copy.d.ts +0 -3
  265. package/dist/core/execution-driver.d.ts +0 -37
  266. package/dist/core/host-fill.d.ts +0 -1
  267. package/dist/core/hotkey.d.ts +0 -18
  268. package/dist/core/identity-pair.d.ts +0 -14
  269. package/dist/core/idle-recheck.d.ts +0 -3
  270. package/dist/core/messages-cell.d.ts +0 -11
  271. package/dist/core/perch-clearance.d.ts +0 -19
  272. package/dist/core/question-receipt.d.ts +0 -11
  273. package/dist/core/reasoning-copy.d.ts +0 -2
  274. package/dist/core/run-folds.d.ts +0 -43
  275. package/dist/core/run-status.d.ts +0 -4
  276. package/dist/core/settle-refresh.d.ts +0 -9
  277. package/dist/core/step-caption.d.ts +0 -2
  278. package/dist/core/stop-copy.d.ts +0 -1
  279. package/dist/core/stop-settle.d.ts +0 -5
  280. package/dist/core/stream-trouble.d.ts +0 -5
  281. package/dist/core/subagent-brief.d.ts +0 -3
  282. package/dist/core/subagent-presence.d.ts +0 -10
  283. package/dist/core/subagent-roster.d.ts +0 -35
  284. package/dist/core/surface-registry.d.ts +0 -16
  285. package/dist/core/suspension-queue.d.ts +0 -14
  286. package/dist/core/tail-slot-pool.d.ts +0 -13
  287. package/dist/core/time-labels.d.ts +0 -7
  288. package/dist/core/tool-call-display-anchors.d.ts +0 -11
  289. package/dist/core/tool-cancel-anchors.d.ts +0 -5
  290. package/dist/core/tool-decision-anchors.d.ts +0 -6
  291. package/dist/core/tool-error-anchors.d.ts +0 -5
  292. package/dist/core/tool-flag-anchors.d.ts +0 -9
  293. package/dist/core/tool-offload-anchors.d.ts +0 -5
  294. package/dist/core/tool-outcome.d.ts +0 -9
  295. package/dist/core/tool-refusal-anchors.d.ts +0 -5
  296. package/dist/core/tool-result-envelope.d.ts +0 -3
  297. package/dist/core/tool-sentence-anchors.d.ts +0 -11
  298. package/dist/core/transcript-lease.d.ts +0 -2
  299. package/dist/core/turn-failure-copy.d.ts +0 -4
  300. package/dist/core/turns-backfill.d.ts +0 -14
  301. package/dist/core/wire-sentence-cap.d.ts +0 -1
  302. package/dist/generated/serving.d.ts +0 -38
  303. package/dist/markdown.d.ts +0 -4
  304. package/dist/markdown.js +0 -4
  305. package/dist/persistence/execution-ledger.d.ts +0 -7
  306. package/dist/persistence/panel-mode.d.ts +0 -6
  307. package/dist/persistence/plan-notice.d.ts +0 -3
  308. package/dist/reader/accessible-name.d.ts +0 -3
  309. package/dist/reader/interactivity.d.ts +0 -11
  310. package/dist/reader/layout-probe.d.ts +0 -29
  311. package/dist/reader/line-diff.d.ts +0 -1
  312. package/dist/reader/read-page.d.ts +0 -12
  313. package/dist/reader/redaction.d.ts +0 -3
  314. package/dist/reader/render.d.ts +0 -3
  315. package/dist/reader/roles.d.ts +0 -8
  316. package/dist/reader/snapshot-compaction.d.ts +0 -5
  317. package/dist/reader/snapshot-node.d.ts +0 -4
  318. package/dist/reader/snapshot-root.d.ts +0 -15
  319. package/dist/reader/snapshot.d.ts +0 -60
  320. package/dist/reader/visibility.d.ts +0 -8
  321. package/dist/scroll.d.ts +0 -1
  322. package/dist/scroll.js +0 -1
  323. package/dist/transcript-ui.d.ts +0 -15
  324. package/dist/transcript-ui.js +0 -8
  325. package/dist/transcript.d.ts +0 -43
  326. package/dist/transcript.js +0 -38
  327. package/dist/transport/actions-adapter.d.ts +0 -4
  328. package/dist/transport/door-budget.d.ts +0 -4
  329. package/dist/transport/serving-api.d.ts +0 -33
  330. package/dist/transport/serving-fetch.d.ts +0 -11
package/README.md CHANGED
@@ -156,7 +156,7 @@ Next, [connect actions to your API](https://docs.teaflask.com/adapters), [identi
156
156
  - [Assistant UI](https://docs.teaflask.com/assistant-ui)
157
157
  - [Trust](https://docs.teaflask.com/trust)
158
158
 
159
- Requires `react` and `react-dom` 18.3 or 19, and `use-stick-to-bottom` (npm installs peers for you; the script tag needs none of them). The package is pre-1.0: a breaking change bumps the minor version, and the [changelog](https://github.com/teaflask/assistant/blob/main/CHANGELOG.md) lists what changed in every release. You can inspect the published code on [npm](https://www.npmjs.com/package/@teaflask/assistant?activeTab=code) or [unpkg](https://unpkg.com/@teaflask/assistant/).
159
+ Requires `react` and `react-dom` 18.3 or 19 (the script tag needs neither). The package is pre-1.0: a breaking change bumps the minor version, and the [changelog](https://github.com/teaflask/assistant/blob/main/CHANGELOG.md) lists what changed in every release. Every public export and field is described in the package's types, and the script tag's attributes and properties in its `custom-elements.json`, so your editor and coding agent can read what each one means. You can inspect the published code on [npm](https://www.npmjs.com/package/@teaflask/assistant?activeTab=code) or [unpkg](https://unpkg.com/@teaflask/assistant/).
160
160
 
161
161
  ## License
162
162
 
@@ -0,0 +1,264 @@
1
+ {
2
+ "schemaVersion": "2.1.0",
3
+ "modules": [
4
+ {
5
+ "kind": "javascript-module",
6
+ "path": "https://app.teaflask.com/assistant/v1/assistant.js",
7
+ "declarations": [
8
+ {
9
+ "kind": "class",
10
+ "name": "TeaflaskAssistantPageElement",
11
+ "customElement": true,
12
+ "tagName": "teaflask-assistant-page",
13
+ "description": "The full-page assistant for any page, loaded with a script tag: the conversation with a header, a history menu and a new-conversation button. It fills its container, so give the element a height.",
14
+ "attributes": [
15
+ {
16
+ "name": "publishable-key",
17
+ "type": {
18
+ "text": "string"
19
+ },
20
+ "description": "Your agent's publishable key from Teaflask. Nothing renders until it is set, and requests are accepted only from your allowed origins. Changing it starts a separate session."
21
+ },
22
+ {
23
+ "name": "base-url",
24
+ "type": {
25
+ "text": "string"
26
+ },
27
+ "description": "The Teaflask API origin, which defaults to https://api.teaflask.com. Changing it starts a separate session."
28
+ },
29
+ {
30
+ "name": "mode",
31
+ "type": {
32
+ "text": "string"
33
+ },
34
+ "description": "The color palette: \"light\", \"dark\", or \"auto\" to follow the visitor's operating-system setting. Any other value warns in the console and uses the default."
35
+ },
36
+ {
37
+ "name": "heading",
38
+ "type": {
39
+ "text": "string"
40
+ },
41
+ "description": "The name shown in the page's header, which defaults to \"Assistant\". It is called heading, not title, so it doesn't show a native tooltip over the page."
42
+ },
43
+ {
44
+ "name": "frameless",
45
+ "type": {
46
+ "text": "string"
47
+ },
48
+ "description": "Removes the page's own border and rounded corners so it sits flush inside a frame you already draw. Present with no value, or \"true\", turns it on; \"false\" turns it off."
49
+ }
50
+ ],
51
+ "members": [
52
+ {
53
+ "kind": "field",
54
+ "name": "onNavigate",
55
+ "type": {
56
+ "text": "((path: string) => void | Promise<void>) | null | undefined"
57
+ },
58
+ "description": "Called with an app-relative path when the agent takes the user to a page. Leave it unset and the page does a full-page load to that path; set a function to use your own router, or null to tell the agent this page cannot navigate."
59
+ },
60
+ {
61
+ "kind": "field",
62
+ "name": "userId",
63
+ "type": {
64
+ "text": "string | null | undefined"
65
+ },
66
+ "description": "Your stable id for the signed-in user, set together with getEndUserToken. It must equal the user_id claim in the token; setting only one of the two runs the session anonymously, with a console warning."
67
+ },
68
+ {
69
+ "kind": "field",
70
+ "name": "getEndUserToken",
71
+ "type": {
72
+ "text": "(() => string | Promise<string | null> | null) | null | undefined"
73
+ },
74
+ "description": "Returns a short-lived token from your backend proving who the user is: an HS256 JWT with user_id and exp (and optionally email), signed with the JWT secret from Settings → Keys in Teaflask. Set it together with userId; returning null continues anonymously."
75
+ },
76
+ {
77
+ "kind": "field",
78
+ "name": "actionsAdapter",
79
+ "type": {
80
+ "text": "ActionsAdapter | null | undefined"
81
+ },
82
+ "description": "How this page calls your API when the agent runs an action: { kind: \"cookies\", baseUrl }, { kind: \"headers\", baseUrl, getHeaders }, or { kind: \"request\", execute }. Without one, or with an unrecognized kind (which warns), the agent cannot run actions here and tells the user to do the step themselves."
83
+ },
84
+ {
85
+ "kind": "field",
86
+ "name": "onError",
87
+ "type": {
88
+ "text": "((error: Error) => void) | null | undefined"
89
+ },
90
+ "description": "Called with errors for your error reporting, such as a failed send, a dropped stream or a failed session-token request."
91
+ },
92
+ {
93
+ "kind": "field",
94
+ "name": "theme",
95
+ "type": {
96
+ "text": "AssistantTheme | null | undefined"
97
+ },
98
+ "description": "Theme tokens and dark-mode overrides, the same object as the React theme prop. Under a strict Content Security Policy this needs inline styles allowed; otherwise set the --tf- CSS variables in your own CSS."
99
+ },
100
+ {
101
+ "kind": "field",
102
+ "name": "suggestions",
103
+ "type": {
104
+ "text": "readonly AssistantSuggestionInput[] | null | undefined"
105
+ },
106
+ "description": "Opening prompts shown under the message box before the first message, as strings or { prompt, kind } objects. The full-page assistant shows none unless you set them."
107
+ },
108
+ {
109
+ "kind": "field",
110
+ "name": "toolViews",
111
+ "type": {
112
+ "text": "Readonly<Record<string, ToolViewRegistration>> | null | undefined"
113
+ },
114
+ "description": "Your own components for displaying specific tools and actions, keyed by tool name (action__<slug> for an action), the same registry as the React toolViews prop. It can be set before or after the element loads and reaches calls already on screen; keys starting with teaflask. and malformed entries are dropped one by one with a console warning."
115
+ }
116
+ ]
117
+ },
118
+ {
119
+ "kind": "class",
120
+ "name": "TeaflaskAssistantElement",
121
+ "customElement": true,
122
+ "tagName": "teaflask-assistant",
123
+ "description": "The all-in-one assistant for any page, loaded with a script tag: the corner widget, which opens the chat drawer, and the ⌘K palette. React is bundled inside. Use one per page, in markup that every page shares.",
124
+ "attributes": [
125
+ {
126
+ "name": "publishable-key",
127
+ "type": {
128
+ "text": "string"
129
+ },
130
+ "description": "Your agent's publishable key from Teaflask. Nothing renders until it is set, and requests are accepted only from your allowed origins. Changing it starts a separate session."
131
+ },
132
+ {
133
+ "name": "base-url",
134
+ "type": {
135
+ "text": "string"
136
+ },
137
+ "description": "The Teaflask API origin, which defaults to https://api.teaflask.com. Changing it starts a separate session."
138
+ },
139
+ {
140
+ "name": "mode",
141
+ "type": {
142
+ "text": "string"
143
+ },
144
+ "description": "The color palette: \"light\", \"dark\", or \"auto\" to follow the visitor's operating-system setting. Any other value warns in the console and uses the default."
145
+ },
146
+ {
147
+ "name": "corner",
148
+ "type": {
149
+ "text": "string"
150
+ },
151
+ "description": "The screen corner where the widget and its drawer sit: \"bottom-right\" (the default) or \"bottom-left\"."
152
+ },
153
+ {
154
+ "name": "hotkey",
155
+ "type": {
156
+ "text": "string"
157
+ },
158
+ "description": "The keyboard shortcut that toggles the palette, which defaults to \"mod+k\" (⌘ on macOS, Ctrl elsewhere); for example \"mod+j\" or \"ctrl+shift+p\". Set \"false\" to disable it; an unrecognized value also disables it, with a console warning."
159
+ },
160
+ {
161
+ "name": "companion-mark-src",
162
+ "type": {
163
+ "text": "string"
164
+ },
165
+ "description": "The URL of your own logo or mascot image, shown on the corner widget and on the drawer's welcome screen. If the image fails to load, the Teaflask flask is shown instead."
166
+ }
167
+ ],
168
+ "members": [
169
+ {
170
+ "kind": "method",
171
+ "name": "openPalette",
172
+ "return": {
173
+ "type": {
174
+ "text": "void"
175
+ }
176
+ },
177
+ "description": "Opens the ⌘K palette, even when the hotkey is disabled or rebound. Does nothing before the element has a publishable key."
178
+ },
179
+ {
180
+ "kind": "field",
181
+ "name": "onNavigate",
182
+ "type": {
183
+ "text": "((path: string) => void | Promise<void>) | null | undefined"
184
+ },
185
+ "description": "Called with an app-relative path when the agent takes the user to a page. Leave it unset and the page does a full-page load to that path; set a function to use your own router, or null to tell the agent this page cannot navigate."
186
+ },
187
+ {
188
+ "kind": "field",
189
+ "name": "userId",
190
+ "type": {
191
+ "text": "string | null | undefined"
192
+ },
193
+ "description": "Your stable id for the signed-in user, set together with getEndUserToken. It must equal the user_id claim in the token; setting only one of the two runs the session anonymously, with a console warning."
194
+ },
195
+ {
196
+ "kind": "field",
197
+ "name": "getEndUserToken",
198
+ "type": {
199
+ "text": "(() => string | Promise<string | null> | null) | null | undefined"
200
+ },
201
+ "description": "Returns a short-lived token from your backend proving who the user is: an HS256 JWT with user_id and exp (and optionally email), signed with the JWT secret from Settings → Keys in Teaflask. Set it together with userId; returning null continues anonymously."
202
+ },
203
+ {
204
+ "kind": "field",
205
+ "name": "actionsAdapter",
206
+ "type": {
207
+ "text": "ActionsAdapter | null | undefined"
208
+ },
209
+ "description": "How this page calls your API when the agent runs an action: { kind: \"cookies\", baseUrl }, { kind: \"headers\", baseUrl, getHeaders }, or { kind: \"request\", execute }. Without one, or with an unrecognized kind (which warns), the agent cannot run actions here and tells the user to do the step themselves."
210
+ },
211
+ {
212
+ "kind": "field",
213
+ "name": "onError",
214
+ "type": {
215
+ "text": "((error: Error) => void) | null | undefined"
216
+ },
217
+ "description": "Called with errors for your error reporting, such as a failed send, a dropped stream or a failed session-token request."
218
+ },
219
+ {
220
+ "kind": "field",
221
+ "name": "theme",
222
+ "type": {
223
+ "text": "AssistantTheme | null | undefined"
224
+ },
225
+ "description": "Theme tokens and dark-mode overrides, the same object as the React theme prop. Under a strict Content Security Policy this needs inline styles allowed; otherwise set the --tf- CSS variables in your own CSS."
226
+ },
227
+ {
228
+ "kind": "field",
229
+ "name": "suggestions",
230
+ "type": {
231
+ "text": "readonly AssistantSuggestionInput[] | null | undefined"
232
+ },
233
+ "description": "Opening prompts for the drawer's welcome screen, as strings or { prompt, kind } objects. Leave it unset to use the prompts configured for your agent in Teaflask; any value, even an empty list, replaces them."
234
+ },
235
+ {
236
+ "kind": "field",
237
+ "name": "toolViews",
238
+ "type": {
239
+ "text": "Readonly<Record<string, ToolViewRegistration>> | null | undefined"
240
+ },
241
+ "description": "Your own components for displaying specific tools and actions, keyed by tool name (action__<slug> for an action), the same registry as the React toolViews prop. It can be set before or after the element loads and reaches calls already on screen; keys starting with teaflask. and malformed entries are dropped one by one with a console warning."
242
+ }
243
+ ]
244
+ }
245
+ ],
246
+ "exports": [
247
+ {
248
+ "kind": "custom-element-definition",
249
+ "name": "teaflask-assistant-page",
250
+ "declaration": {
251
+ "name": "TeaflaskAssistantPageElement"
252
+ }
253
+ },
254
+ {
255
+ "kind": "custom-element-definition",
256
+ "name": "teaflask-assistant",
257
+ "declaration": {
258
+ "name": "TeaflaskAssistantElement"
259
+ }
260
+ }
261
+ ]
262
+ }
263
+ ]
264
+ }
@@ -0,0 +1,315 @@
1
+ import { CLOSE_SETTLE_MS, clicked, OPEN_SETTLE_MS, PICK_SETTLE_MS, pressKey, pressLikeAPointer, settledReading, theClickWouldSubmitOrLeaveThePage, theControlIsInert, } from "./page-gestures.js";
2
+ import { CONTROL_REDRAWN_REASON, CURATED_OPTIONS_REASON, DROPDOWN_NEVER_OPENED_REASON, DROPDOWN_PICK_DID_NOT_LAND_REASON, INERT_FIELD_REASON, MULTI_CHOICE_REASON, NO_OPTIONS_SHOWN_REASON, noMatchingOptionReasonListing, SUBMITTING_CONTROL_REASON, unavailableOptionReason, } from "./prefill-reasons.js";
3
+ import { accessibleNameOf, } from "../reader/accessible-name.js";
4
+ import { ariaBooleanOf, roleOf, theControlIsDisabled, } from "../reader/roles.js";
5
+ import { alreadyShowsTheValue, comboboxOwnerOf, confirmsLabel, displayNamesTheMatch, ownDisplayIsReliable, ownerShowsThePick, shownTextOf, } from "./dropdown-display.js";
6
+ import { _normalizedNodeName } from "../reader/snapshot-node.js";
7
+ import { lastReadIgnoreSelectors } from "../reader/snapshot.js";
8
+ import { theElementSitsInACuratedSubtree } from "../reader/snapshot-root.js";
9
+ import { visibilityOracleOf } from "../reader/visibility.js";
10
+ export async function customDropdownRefusalOf(element, value, probe, listingBudget, whenNoListOpens) {
11
+ const entryRefusal = _dropdownEntryRefusalOf(element);
12
+ if (entryRefusal !== null) {
13
+ return entryRefusal;
14
+ }
15
+ const want = value.trim();
16
+ if (ownDisplayIsReliable(element) &&
17
+ alreadyShowsTheValue(element, want, probe, null)) {
18
+ return null;
19
+ }
20
+ if (!(element instanceof HTMLInputElement) &&
21
+ theClickWouldSubmitOrLeaveThePage(element)) {
22
+ return SUBMITTING_CONTROL_REASON;
23
+ }
24
+ const found = await _openedListboxFor(element, probe);
25
+ const listbox = found.listbox;
26
+ const closedIfOurs = async () => {
27
+ if (found.provenance === "ours") {
28
+ await _closedPopup(element, listbox, probe);
29
+ }
30
+ };
31
+ if (listbox === null) {
32
+ if (!element.isConnected) {
33
+ return CONTROL_REDRAWN_REASON;
34
+ }
35
+ if (found.gesturesWereDispatched) {
36
+ await _closedPopup(element, listbox, probe);
37
+ }
38
+ return whenNoListOpens !== undefined
39
+ ? whenNoListOpens(DROPDOWN_NEVER_OPENED_REASON)
40
+ : DROPDOWN_NEVER_OPENED_REASON;
41
+ }
42
+ if (!element.isConnected) {
43
+ return CONTROL_REDRAWN_REASON;
44
+ }
45
+ if (!ownDisplayIsReliable(element) &&
46
+ alreadyShowsTheValue(element, want, probe, listbox)) {
47
+ await closedIfOurs();
48
+ return null;
49
+ }
50
+ if (theElementSitsInACuratedSubtree(listbox, lastReadIgnoreSelectors())) {
51
+ await closedIfOurs();
52
+ return CURATED_OPTIONS_REASON;
53
+ }
54
+ if (ariaBooleanOf(listbox.getAttribute("aria-multiselectable")) === true) {
55
+ await closedIfOurs();
56
+ return MULTI_CHOICE_REASON;
57
+ }
58
+ const options = _visibleOptionsOf(listbox, probe);
59
+ if (options.length === 0) {
60
+ await closedIfOurs();
61
+ return whenNoListOpens !== undefined
62
+ ? whenNoListOpens(NO_OPTIONS_SHOWN_REASON)
63
+ : NO_OPTIONS_SHOWN_REASON;
64
+ }
65
+ const cache = new Map();
66
+ const nameOf = (option) => accessibleNameOf(option, probe, cache).trim();
67
+ const match = _optionMatching(options, want, value, nameOf);
68
+ if (match === null) {
69
+ await closedIfOurs();
70
+ return _noMatchRefusalOf(element, options, nameOf, listingBudget);
71
+ }
72
+ const label = nameOf(match) !== "" ? nameOf(match) : want;
73
+ if (match.getAttribute("aria-selected") === "true" &&
74
+ displayNamesTheMatch(shownTextOf(element, probe, listbox), label, options, nameOf)) {
75
+ await closedIfOurs();
76
+ return null;
77
+ }
78
+ if (theControlIsDisabled(match, "option")) {
79
+ await closedIfOurs();
80
+ return unavailableOptionReason(label);
81
+ }
82
+ if (theClickWouldSubmitOrLeaveThePage(match)) {
83
+ await closedIfOurs();
84
+ return SUBMITTING_CONTROL_REASON;
85
+ }
86
+ return _confirmedPickRefusalOf(element, listbox, match, label, probe);
87
+ }
88
+ async function _confirmedPickRefusalOf(element, listbox, match, label, probe) {
89
+ const beforeText = shownTextOf(element, probe, listbox);
90
+ clicked(match);
91
+ const after = await settledReading(() => shownTextOf(element, probe, listbox), (text) => !element.isConnected ||
92
+ (text !== beforeText && confirmsLabel(text, label)), PICK_SETTLE_MS);
93
+ await _closedPopup(element, listbox, probe);
94
+ if (!element.isConnected) {
95
+ return CONTROL_REDRAWN_REASON;
96
+ }
97
+ const landed = after !== beforeText && confirmsLabel(after, label);
98
+ return landed ? null : DROPDOWN_PICK_DID_NOT_LAND_REASON;
99
+ }
100
+ export async function listboxPickRefusalOf(element, value, probe, listingBudget) {
101
+ if (theControlIsInert(element)) {
102
+ return INERT_FIELD_REASON;
103
+ }
104
+ if (ariaBooleanOf(element.getAttribute("aria-multiselectable")) === true) {
105
+ return MULTI_CHOICE_REASON;
106
+ }
107
+ const options = _visibleOptionsOf(element, probe);
108
+ if (options.length === 0) {
109
+ return NO_OPTIONS_SHOWN_REASON;
110
+ }
111
+ const cache = new Map();
112
+ const nameOf = (option) => accessibleNameOf(option, probe, cache).trim();
113
+ const want = value.trim();
114
+ const match = _optionMatching(options, want, value, nameOf);
115
+ if (match === null) {
116
+ return _noMatchRefusalOf(element, options, nameOf, listingBudget);
117
+ }
118
+ if (match.getAttribute("aria-selected") === "true") {
119
+ return null;
120
+ }
121
+ const label = nameOf(match) !== "" ? nameOf(match) : want;
122
+ if (theControlIsDisabled(match, "option")) {
123
+ return unavailableOptionReason(label);
124
+ }
125
+ if (theClickWouldSubmitOrLeaveThePage(match)) {
126
+ return SUBMITTING_CONTROL_REASON;
127
+ }
128
+ const owner = comboboxOwnerOf(element);
129
+ const ownerBefore = owner === null ? "" : shownTextOf(owner, probe, element);
130
+ clicked(match);
131
+ const selected = await settledReading(() => match.getAttribute("aria-selected"), (state) => state === "true" || !element.isConnected || !match.isConnected, PICK_SETTLE_MS);
132
+ if (element.isConnected && match.isConnected) {
133
+ return selected === "true" ? null : DROPDOWN_PICK_DID_NOT_LAND_REASON;
134
+ }
135
+ if (owner !== null) {
136
+ return (await ownerShowsThePick(owner, ownerBefore, label, probe))
137
+ ? null
138
+ : DROPDOWN_PICK_DID_NOT_LAND_REASON;
139
+ }
140
+ return CONTROL_REDRAWN_REASON;
141
+ }
142
+ async function _openedListboxFor(element, probe) {
143
+ if (element.getAttribute("aria-expanded") === "true") {
144
+ const alreadyOpen = _openedListboxOf(element, probe, new Set(), (candidate) => _popupBelongsToTrigger(candidate, element, probe));
145
+ return {
146
+ listbox: alreadyOpen,
147
+ provenance: alreadyOpen !== null ? "users" : "unattributed",
148
+ gesturesWereDispatched: false,
149
+ };
150
+ }
151
+ const alreadyShowing = visibilityOracleOf(probe);
152
+ const before = new Set(Array.from(document.querySelectorAll('[role="listbox"]')).filter((candidate) => alreadyShowing.isVisible(candidate)));
153
+ if (element instanceof HTMLElement) {
154
+ element.focus();
155
+ }
156
+ pressKey(element, "ArrowDown");
157
+ const viaKeyboard = await settledReading(() => _openedListboxOf(element, probe, before, () => true), (listbox) => listbox !== null || !element.isConnected, OPEN_SETTLE_MS);
158
+ if (viaKeyboard !== null) {
159
+ return {
160
+ listbox: viaKeyboard,
161
+ provenance: "ours",
162
+ gesturesWereDispatched: true,
163
+ };
164
+ }
165
+ if (!element.isConnected ||
166
+ theClickWouldSubmitOrLeaveThePage(element) ||
167
+ element.getAttribute("aria-expanded") === "true") {
168
+ return {
169
+ listbox: null,
170
+ provenance: "unattributed",
171
+ gesturesWereDispatched: true,
172
+ };
173
+ }
174
+ pressLikeAPointer(element);
175
+ const viaPointer = await settledReading(() => _openedListboxOf(element, probe, before, () => true), (listbox) => listbox !== null || !element.isConnected, OPEN_SETTLE_MS);
176
+ return {
177
+ listbox: viaPointer,
178
+ provenance: viaPointer !== null ? "ours" : "unattributed",
179
+ gesturesWereDispatched: true,
180
+ };
181
+ }
182
+ const KINSHIP_CLIMB_MAX = 5;
183
+ function _popupBelongsToTrigger(candidate, trigger, probe) {
184
+ if (candidate.contains(trigger) || trigger.contains(candidate)) {
185
+ return true;
186
+ }
187
+ const oracle = visibilityOracleOf(probe);
188
+ const body = trigger.ownerDocument.body;
189
+ let current = trigger.parentElement;
190
+ for (let depth = 0; depth < KINSHIP_CLIMB_MAX && current !== null && current !== body; depth++) {
191
+ const visibleInside = Array.from(current.querySelectorAll('[role="listbox"]')).filter((listbox) => oracle.isVisible(listbox));
192
+ if (visibleInside.length > 0) {
193
+ return visibleInside.length === 1 && visibleInside[0] === candidate;
194
+ }
195
+ current = current.parentElement;
196
+ }
197
+ return false;
198
+ }
199
+ function _openedListboxOf(trigger, probe, before, unlinkedIsOurs) {
200
+ const oracle = visibilityOracleOf(probe);
201
+ const byId = _idReferencedListboxOf(trigger, "aria-controls") ??
202
+ _idReferencedListboxOf(trigger, "aria-owns");
203
+ if (byId !== null && oracle.isVisible(byId)) {
204
+ return byId;
205
+ }
206
+ const active = _resolvedIdNear(trigger, trigger.getAttribute("aria-activedescendant"));
207
+ const viaActive = active?.closest('[role="listbox"]') ?? null;
208
+ if (viaActive !== null && oracle.isVisible(viaActive)) {
209
+ return viaActive;
210
+ }
211
+ for (const candidate of Array.from(document.querySelectorAll('[role="listbox"]'))) {
212
+ if (!before.has(candidate) &&
213
+ oracle.isVisible(candidate) &&
214
+ unlinkedIsOurs(candidate)) {
215
+ return candidate;
216
+ }
217
+ }
218
+ return null;
219
+ }
220
+ function _idReferencedListboxOf(trigger, attribute) {
221
+ const ids = (trigger.getAttribute(attribute) ?? "")
222
+ .split(/\s+/)
223
+ .filter((id) => id !== "");
224
+ for (const id of ids) {
225
+ const hit = _resolvedIdNear(trigger, id);
226
+ if (hit === null) {
227
+ continue;
228
+ }
229
+ if (roleOf(hit) === "listbox") {
230
+ return hit;
231
+ }
232
+ const inner = hit.querySelector('[role="listbox"]');
233
+ if (inner !== null) {
234
+ return inner;
235
+ }
236
+ }
237
+ return null;
238
+ }
239
+ function _resolvedIdNear(trigger, id) {
240
+ if (id === null || id === "") {
241
+ return null;
242
+ }
243
+ const root = trigger.getRootNode();
244
+ if (root instanceof Document || root instanceof ShadowRoot) {
245
+ return root.getElementById(id);
246
+ }
247
+ return document.getElementById(id);
248
+ }
249
+ function _optionMatching(options, want, rawValue, nameOf) {
250
+ if (want === "") {
251
+ return null;
252
+ }
253
+ return (options.find((option) => nameOf(option) === want) ??
254
+ options.find((option) => nameOf(option).toLowerCase() === want.toLowerCase()) ??
255
+ options.find((option) => {
256
+ const shownToTheModel = _normalizedNodeName(nameOf(option));
257
+ const comparable = shownToTheModel.trimEnd();
258
+ return (shownToTheModel !== nameOf(option) &&
259
+ (comparable === want || comparable.toLowerCase() === want.toLowerCase()));
260
+ }) ??
261
+ options.find((option) => option.getAttribute("data-value") === rawValue) ??
262
+ null);
263
+ }
264
+ function _visibleOptionsOf(listbox, probe) {
265
+ const oracle = visibilityOracleOf(probe);
266
+ const ignoreSelectors = lastReadIgnoreSelectors();
267
+ return Array.from(listbox.querySelectorAll('[role="option"]')).filter((option) => oracle.isVisible(option) &&
268
+ !theElementSitsInACuratedSubtree(option, ignoreSelectors));
269
+ }
270
+ async function _closedPopup(control, listbox, probe) {
271
+ if (_popupLooksClosed(control, listbox, probe)) {
272
+ return;
273
+ }
274
+ const active = control.ownerDocument.activeElement;
275
+ const focused = active !== null &&
276
+ (control.contains(active) || (listbox?.contains(active) ?? false))
277
+ ? active
278
+ : null;
279
+ if (focused instanceof HTMLInputElement) {
280
+ focused.blur();
281
+ }
282
+ else if (control instanceof HTMLInputElement) {
283
+ control.blur();
284
+ }
285
+ else {
286
+ pressKey(focused ?? control, "Escape");
287
+ }
288
+ await settledReading(() => _popupLooksClosed(control, listbox, probe), (closed) => closed, CLOSE_SETTLE_MS);
289
+ }
290
+ function _popupLooksClosed(control, listbox, probe) {
291
+ if (!control.isConnected) {
292
+ return true;
293
+ }
294
+ if (control.hasAttribute("aria-expanded")) {
295
+ return control.getAttribute("aria-expanded") !== "true";
296
+ }
297
+ return !_popupShowing(listbox, probe);
298
+ }
299
+ function _popupShowing(listbox, probe) {
300
+ return (listbox !== null &&
301
+ listbox.isConnected &&
302
+ visibilityOracleOf(probe).isVisible(listbox));
303
+ }
304
+ function _dropdownEntryRefusalOf(element) {
305
+ if (theControlIsInert(element) || theControlIsDisabled(element, "combobox")) {
306
+ return INERT_FIELD_REASON;
307
+ }
308
+ return null;
309
+ }
310
+ function _noMatchRefusalOf(element, options, nameOf, listingBudget) {
311
+ const labels = options
312
+ .filter((option) => !theControlIsDisabled(option, "option"))
313
+ .map(nameOf);
314
+ return noMatchingOptionReasonListing(labels, listingBudget, element instanceof HTMLInputElement && !element.readOnly);
315
+ }
@@ -0,0 +1,39 @@
1
+ import { clicked, settledReading, theClickWouldSubmitOrLeaveThePage, theControlIsInert, TOGGLE_SETTLE_MS, } from "./page-gestures.js";
2
+ import { CHECKBOX_VALUE_REASON, CHECKED_STATE_UNKNOWN_REASON, CONTROL_REDRAWN_REASON, INERT_FIELD_REASON, RADIO_VALUE_REASON, SUBMITTING_CONTROL_REASON, VALUE_DID_NOT_LAND_REASON, } from "./prefill-reasons.js";
3
+ import { roleOf } from "../reader/roles.js";
4
+ export async function ariaToggleRefusalOf(element, value) {
5
+ if (roleOf(element) === "radio" && value !== "true") {
6
+ return RADIO_VALUE_REASON;
7
+ }
8
+ if (value !== "true" && value !== "false") {
9
+ return CHECKBOX_VALUE_REASON;
10
+ }
11
+ if (theControlIsInert(element)) {
12
+ return INERT_FIELD_REASON;
13
+ }
14
+ const state = _rawCheckedOf(element);
15
+ if (state === null) {
16
+ return CHECKED_STATE_UNKNOWN_REASON;
17
+ }
18
+ if (state === value) {
19
+ return null;
20
+ }
21
+ if (theClickWouldSubmitOrLeaveThePage(element)) {
22
+ return SUBMITTING_CONTROL_REASON;
23
+ }
24
+ for (let attempt = 0; attempt < 2; attempt++) {
25
+ const before = _rawCheckedOf(element);
26
+ clicked(element);
27
+ const after = await settledReading(() => _rawCheckedOf(element), (read) => read === value || !element.isConnected, TOGGLE_SETTLE_MS);
28
+ if (after === value || after === before) {
29
+ break;
30
+ }
31
+ }
32
+ if (!element.isConnected) {
33
+ return CONTROL_REDRAWN_REASON;
34
+ }
35
+ return _rawCheckedOf(element) === value ? null : VALUE_DID_NOT_LAND_REASON;
36
+ }
37
+ function _rawCheckedOf(element) {
38
+ return element.getAttribute("aria-checked")?.toLowerCase() ?? null;
39
+ }