@agent-native/toolkit 0.6.0 → 0.7.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.
Files changed (173) hide show
  1. package/README.md +17 -1
  2. package/dist/chat-history/ChatHistoryList.d.ts +103 -0
  3. package/dist/chat-history/ChatHistoryList.d.ts.map +1 -0
  4. package/dist/chat-history/ChatHistoryList.js +109 -0
  5. package/dist/chat-history/ChatHistoryList.js.map +1 -0
  6. package/dist/chat-history/ChatHistoryList.spec.d.ts +2 -0
  7. package/dist/chat-history/ChatHistoryList.spec.d.ts.map +1 -0
  8. package/dist/chat-history/ChatHistoryList.spec.js +283 -0
  9. package/dist/chat-history/ChatHistoryList.spec.js.map +1 -0
  10. package/dist/chat-history/index.d.ts +2 -0
  11. package/dist/chat-history/index.d.ts.map +1 -0
  12. package/dist/chat-history/index.js +2 -0
  13. package/dist/chat-history/index.js.map +1 -0
  14. package/dist/chat-history.css +314 -0
  15. package/package.json +17 -1
  16. package/src/app-shell/header-actions.tsx +84 -0
  17. package/src/app-shell/index.ts +1 -0
  18. package/src/chat-history/ChatHistoryList.spec.tsx +453 -0
  19. package/src/chat-history/ChatHistoryList.tsx +469 -0
  20. package/src/chat-history/index.ts +7 -0
  21. package/src/chat-history.css +314 -0
  22. package/src/collab-ui/AgentPresenceChip.tsx +69 -0
  23. package/src/collab-ui/LiveCursorOverlay.tsx +241 -0
  24. package/src/collab-ui/PresenceBar.tsx +346 -0
  25. package/src/collab-ui/RecentEditHighlights.tsx +225 -0
  26. package/src/collab-ui/RemoteSelectionRings.tsx +227 -0
  27. package/src/collab-ui/agent-identity.ts +16 -0
  28. package/src/collab-ui/index.ts +39 -0
  29. package/src/collab-ui/lead-client.ts +32 -0
  30. package/src/collab-ui/types.spec.ts +18 -0
  31. package/src/collab-ui/types.ts +96 -0
  32. package/src/composer/AgentComposerFrame.tsx +59 -0
  33. package/src/composer/ComposerPlusMenu.tsx +983 -0
  34. package/src/composer/MentionPopover.tsx +412 -0
  35. package/src/composer/PastedTextChip.tsx +150 -0
  36. package/src/composer/PromptComposer.spec.ts +73 -0
  37. package/src/composer/PromptComposer.tsx +718 -0
  38. package/src/composer/RealtimeVoiceMode.spec.tsx +771 -0
  39. package/src/composer/RealtimeVoiceMode.tsx +856 -0
  40. package/src/composer/TiptapComposer.spec.ts +390 -0
  41. package/src/composer/TiptapComposer.tsx +2936 -0
  42. package/src/composer/VoiceButton.spec.ts +33 -0
  43. package/src/composer/VoiceButton.tsx +255 -0
  44. package/src/composer/asset-picker-url.spec.ts +56 -0
  45. package/src/composer/asset-picker-url.ts +80 -0
  46. package/src/composer/attachment-accept.spec.ts +22 -0
  47. package/src/composer/attachment-accept.ts +71 -0
  48. package/src/composer/draft-key.spec.ts +19 -0
  49. package/src/composer/draft-key.ts +7 -0
  50. package/src/composer/extensions/FileReference.tsx +55 -0
  51. package/src/composer/extensions/MentionReference.tsx +93 -0
  52. package/src/composer/extensions/SkillReference.tsx +56 -0
  53. package/src/composer/index.ts +79 -0
  54. package/src/composer/pasted-text.spec.ts +162 -0
  55. package/src/composer/pasted-text.ts +160 -0
  56. package/src/composer/prompt-attachments.spec.ts +80 -0
  57. package/src/composer/prompt-attachments.ts +93 -0
  58. package/src/composer/realtime-voice-audio-level.spec.ts +32 -0
  59. package/src/composer/realtime-voice-audio-level.ts +64 -0
  60. package/src/composer/realtime-voice-transcript.spec.ts +95 -0
  61. package/src/composer/realtime-voice-transcript.ts +134 -0
  62. package/src/composer/runtime-adapters.tsx +343 -0
  63. package/src/composer/types.ts +66 -0
  64. package/src/composer/use-file-search.ts +64 -0
  65. package/src/composer/use-mention-search.ts +90 -0
  66. package/src/composer/use-skills.ts +45 -0
  67. package/src/composer/useRealtimeVoiceMode.spec.ts +818 -0
  68. package/src/composer/useRealtimeVoiceMode.tsx +2117 -0
  69. package/src/composer/useVoiceDictation.spec.ts +45 -0
  70. package/src/composer/useVoiceDictation.ts +1191 -0
  71. package/src/context-ui/ContextMeter.tsx +101 -0
  72. package/src/context-ui/ContextSegmentRow.tsx +184 -0
  73. package/src/context-ui/ContextTreemap.tsx +125 -0
  74. package/src/context-ui/ContextXRayPanel.tsx +377 -0
  75. package/src/context-ui/format.ts +42 -0
  76. package/src/context-ui/index.ts +15 -0
  77. package/src/context-ui/types.ts +43 -0
  78. package/src/design-tweaks/index.ts +1 -0
  79. package/src/design-tweaks/visual-style-controls.tsx +1084 -0
  80. package/src/editor/BubbleToolbar.tsx +253 -0
  81. package/src/editor/CodeBlockNode.tsx +254 -0
  82. package/src/editor/DragHandle.spec.ts +588 -0
  83. package/src/editor/DragHandle.ts +1437 -0
  84. package/src/editor/ImageExtension.roundtrip.spec.ts +117 -0
  85. package/src/editor/ImageExtension.ts +306 -0
  86. package/src/editor/RegistryBlockContext.tsx +107 -0
  87. package/src/editor/RegistryBlockNode.spec.ts +279 -0
  88. package/src/editor/RegistryBlockNode.tsx +652 -0
  89. package/src/editor/RichMarkdownEditor.collab.spec.ts +79 -0
  90. package/src/editor/RichMarkdownEditor.roundtrip.spec.ts +226 -0
  91. package/src/editor/RichMarkdownEditor.tsx +81 -0
  92. package/src/editor/RunId.ts +61 -0
  93. package/src/editor/SharedRichEditor.tsx +321 -0
  94. package/src/editor/SlashCommandMenu.tsx +310 -0
  95. package/src/editor/disableHistory.spec.ts +85 -0
  96. package/src/editor/extensions.ts +402 -0
  97. package/src/editor/gfmDoc.spec.ts +230 -0
  98. package/src/editor/gfmDoc.ts +92 -0
  99. package/src/editor/index.ts +93 -0
  100. package/src/editor/registrySlashCommands.ts +131 -0
  101. package/src/editor/structuralReorderUndo.spec.ts +144 -0
  102. package/src/editor/surgical-apply.spec.ts +279 -0
  103. package/src/editor/surgical-apply.ts +192 -0
  104. package/src/editor/useCollabReconcile.concurrent.spec.ts +422 -0
  105. package/src/editor/useCollabReconcile.idempotent.spec.ts +324 -0
  106. package/src/editor/useCollabReconcile.ts +589 -0
  107. package/src/editor.css +510 -0
  108. package/src/hooks/index.ts +2 -0
  109. package/src/hooks/use-mobile.tsx +21 -0
  110. package/src/hooks/use-toast.ts +188 -0
  111. package/src/index.ts +8 -0
  112. package/src/onboarding/index.ts +1 -0
  113. package/src/provider.tsx +47 -0
  114. package/src/sharing/VisibilityBadge.spec.ts +96 -0
  115. package/src/sharing/VisibilityBadge.tsx +37 -0
  116. package/src/sharing/index.ts +4 -0
  117. package/src/styles.css +21 -0
  118. package/src/ui/accordion.tsx +56 -0
  119. package/src/ui/alert-dialog.tsx +141 -0
  120. package/src/ui/alert.tsx +59 -0
  121. package/src/ui/aspect-ratio.tsx +5 -0
  122. package/src/ui/avatar.tsx +48 -0
  123. package/src/ui/badge.tsx +37 -0
  124. package/src/ui/breadcrumb.tsx +115 -0
  125. package/src/ui/button.tsx +78 -0
  126. package/src/ui/calendar.tsx +214 -0
  127. package/src/ui/card.tsx +86 -0
  128. package/src/ui/carousel.tsx +260 -0
  129. package/src/ui/chart.tsx +375 -0
  130. package/src/ui/checkbox.tsx +28 -0
  131. package/src/ui/collapsible.tsx +9 -0
  132. package/src/ui/command.spec.tsx +51 -0
  133. package/src/ui/command.tsx +174 -0
  134. package/src/ui/context-menu.tsx +202 -0
  135. package/src/ui/date-picker.tsx +64 -0
  136. package/src/ui/dialog.spec.tsx +43 -0
  137. package/src/ui/dialog.tsx +146 -0
  138. package/src/ui/drawer.tsx +126 -0
  139. package/src/ui/dropdown-menu.tsx +218 -0
  140. package/src/ui/form.tsx +177 -0
  141. package/src/ui/hover-card.tsx +27 -0
  142. package/src/ui/index.ts +52 -0
  143. package/src/ui/input-otp.tsx +69 -0
  144. package/src/ui/input.tsx +22 -0
  145. package/src/ui/label.tsx +24 -0
  146. package/src/ui/logo.tsx +36 -0
  147. package/src/ui/menubar.tsx +235 -0
  148. package/src/ui/navigation-menu.tsx +128 -0
  149. package/src/ui/pagination.tsx +121 -0
  150. package/src/ui/popover.tsx +44 -0
  151. package/src/ui/progress.tsx +26 -0
  152. package/src/ui/radio-group.tsx +42 -0
  153. package/src/ui/resizable.tsx +43 -0
  154. package/src/ui/scroll-area.tsx +46 -0
  155. package/src/ui/select.tsx +158 -0
  156. package/src/ui/separator.tsx +29 -0
  157. package/src/ui/sheet.tsx +160 -0
  158. package/src/ui/sidebar.tsx +777 -0
  159. package/src/ui/skeleton.tsx +18 -0
  160. package/src/ui/slider.tsx +26 -0
  161. package/src/ui/sonner.tsx +58 -0
  162. package/src/ui/spinner.tsx +17 -0
  163. package/src/ui/switch.tsx +27 -0
  164. package/src/ui/table.tsx +117 -0
  165. package/src/ui/tabs.tsx +53 -0
  166. package/src/ui/textarea.tsx +23 -0
  167. package/src/ui/toast.tsx +127 -0
  168. package/src/ui/toaster.tsx +33 -0
  169. package/src/ui/toggle-group.tsx +59 -0
  170. package/src/ui/toggle.tsx +43 -0
  171. package/src/ui/tooltip.tsx +53 -0
  172. package/src/ui/use-toast.ts +3 -0
  173. package/src/utils.ts +8 -0
@@ -0,0 +1,314 @@
1
+ /*
2
+ * Shared chat history list — used by Core's `HistoryPopover`
3
+ * (MultiTabAssistantChat.tsx) and by Agent-Native Code's run rail
4
+ * (code-agents-ui CodeAgentsApp.tsx). Stable, prefixed class names (not
5
+ * Tailwind utilities) so the same visual language works in both a Tailwind
6
+ * host (core/templates) and a plain-CSS host (code-agents-ui), matching the
7
+ * approach used by agent-conversation.css. All colors resolve through the
8
+ * shared `hsl(var(--token))` variables so light/dark both work in either
9
+ * host's theme.
10
+ *
11
+ * Two density variants:
12
+ * .an-chat-history default — compact popover list (core)
13
+ * .an-chat-history--rail denser rail list with solid active state
14
+ */
15
+
16
+ .an-chat-history {
17
+ display: flex;
18
+ flex-direction: column;
19
+ min-height: 0;
20
+ }
21
+
22
+ .an-chat-history__search {
23
+ display: flex;
24
+ align-items: center;
25
+ gap: 8px;
26
+ padding: 8px 12px;
27
+ border-bottom: 1px solid hsl(var(--border));
28
+ color: hsl(var(--muted-foreground));
29
+ flex-shrink: 0;
30
+ }
31
+
32
+ .an-chat-history__search-icon {
33
+ flex-shrink: 0;
34
+ }
35
+
36
+ .an-chat-history__search-input {
37
+ flex: 1;
38
+ min-width: 0;
39
+ background: transparent;
40
+ border: 0;
41
+ outline: none;
42
+ font-size: 12px;
43
+ color: hsl(var(--foreground));
44
+ }
45
+
46
+ .an-chat-history__search-input::placeholder {
47
+ color: hsl(var(--muted-foreground));
48
+ }
49
+
50
+ .an-chat-history__list {
51
+ overflow-y: auto;
52
+ padding: 4px 0;
53
+ max-height: 16rem;
54
+ }
55
+
56
+ .an-chat-history--rail .an-chat-history__list {
57
+ max-height: none;
58
+ flex: 1;
59
+ min-height: 0;
60
+ }
61
+
62
+ .an-chat-history__state {
63
+ padding: 16px 12px;
64
+ text-align: center;
65
+ font-size: 12px;
66
+ color: hsl(var(--muted-foreground));
67
+ }
68
+
69
+ .an-chat-history__state--error {
70
+ /* Matches the amber-500 warning tone historically used for the
71
+ HistoryPopover load-error state (Tailwind's `text-amber-500`). */
72
+ color: hsl(38 92% 50%);
73
+ }
74
+
75
+ .an-chat-history__section-label {
76
+ padding: 6px 12px 4px;
77
+ font-size: 10px;
78
+ text-transform: uppercase;
79
+ letter-spacing: 0.04em;
80
+ color: hsl(var(--muted-foreground) / 0.7);
81
+ }
82
+
83
+ .an-chat-history--rail .an-chat-history__section {
84
+ display: grid;
85
+ gap: 1px;
86
+ }
87
+
88
+ /* ── Row ──────────────────────────────────────────────────────────────── */
89
+
90
+ .an-chat-history-row {
91
+ position: relative;
92
+ }
93
+
94
+ .an-chat-history--rail .an-chat-history-row {
95
+ border-radius: calc(var(--radius) - 2px);
96
+ margin: 0 4px;
97
+ }
98
+
99
+ .an-chat-history-row__button {
100
+ display: block;
101
+ width: 100%;
102
+ padding: 8px 12px;
103
+ border: 0;
104
+ background: transparent;
105
+ color: inherit;
106
+ text-align: start;
107
+ cursor: pointer;
108
+ }
109
+
110
+ .an-chat-history-row--disabled .an-chat-history-row__button {
111
+ cursor: default;
112
+ opacity: 0.6;
113
+ }
114
+
115
+ .an-chat-history-row:hover .an-chat-history-row__button {
116
+ background: hsl(var(--accent) / 0.5);
117
+ }
118
+
119
+ .an-chat-history-row--active .an-chat-history-row__button {
120
+ background: hsl(var(--accent) / 0.3);
121
+ }
122
+
123
+ .an-chat-history--rail .an-chat-history-row__button {
124
+ min-height: 32px;
125
+ padding-block: 6px;
126
+ padding-inline: 10px 36px;
127
+ border-radius: inherit;
128
+ color: hsl(var(--muted-foreground));
129
+ }
130
+
131
+ .an-chat-history--rail
132
+ .an-chat-history-row--active
133
+ .an-chat-history-row__button {
134
+ background: hsl(var(--accent));
135
+ color: hsl(var(--accent-foreground));
136
+ }
137
+
138
+ .an-chat-history-row__topline {
139
+ display: flex;
140
+ align-items: baseline;
141
+ justify-content: space-between;
142
+ gap: 8px;
143
+ min-width: 0;
144
+ }
145
+
146
+ .an-chat-history-row__title {
147
+ min-width: 0;
148
+ overflow: hidden;
149
+ text-overflow: ellipsis;
150
+ white-space: nowrap;
151
+ font-size: 12px;
152
+ font-weight: 500;
153
+ color: hsl(var(--foreground));
154
+ }
155
+
156
+ .an-chat-history-row--active .an-chat-history-row__title {
157
+ color: hsl(var(--foreground));
158
+ }
159
+
160
+ .an-chat-history--rail
161
+ .an-chat-history-row--active
162
+ .an-chat-history-row__title {
163
+ color: hsl(var(--accent-foreground));
164
+ }
165
+
166
+ .an-chat-history--rail
167
+ .an-chat-history-row--pinned:not(.an-chat-history-row--active)
168
+ .an-chat-history-row__title {
169
+ color: hsl(var(--foreground));
170
+ }
171
+
172
+ .an-chat-history-row__timestamp {
173
+ flex-shrink: 0;
174
+ font-size: 10px;
175
+ color: hsl(var(--muted-foreground));
176
+ }
177
+
178
+ .an-chat-history--rail .an-chat-history-row__timestamp {
179
+ font-size: 11px;
180
+ color: hsl(var(--muted-foreground) / 0.62);
181
+ }
182
+
183
+ .an-chat-history--rail
184
+ .an-chat-history-row--active
185
+ .an-chat-history-row__timestamp {
186
+ color: hsl(var(--accent-foreground));
187
+ }
188
+
189
+ .an-chat-history-row__subtitle {
190
+ margin-top: 2px;
191
+ overflow: hidden;
192
+ text-overflow: ellipsis;
193
+ white-space: nowrap;
194
+ font-size: 11px;
195
+ color: hsl(var(--muted-foreground));
196
+ }
197
+
198
+ .an-chat-history-row__detail {
199
+ margin-top: 2px;
200
+ overflow: hidden;
201
+ text-overflow: ellipsis;
202
+ white-space: nowrap;
203
+ font-size: 10px;
204
+ color: hsl(var(--muted-foreground) / 0.7);
205
+ }
206
+
207
+ /* ── Inline rename ────────────────────────────────────────────────────── */
208
+
209
+ .an-chat-history-row__rename {
210
+ display: flex;
211
+ align-items: center;
212
+ padding: 6px 12px;
213
+ }
214
+
215
+ .an-chat-history-row__rename-input {
216
+ width: 100%;
217
+ min-width: 0;
218
+ padding: 2px 6px;
219
+ border: 1px solid hsl(var(--ring));
220
+ border-radius: calc(var(--radius) - 3px);
221
+ background: hsl(var(--background));
222
+ color: hsl(var(--foreground));
223
+ font-size: 12px;
224
+ font-weight: 500;
225
+ line-height: 1.4;
226
+ outline: none;
227
+ box-shadow: 0 0 0 2px hsl(var(--ring) / 0.25);
228
+ }
229
+
230
+ .an-chat-history-row__rename-input:focus {
231
+ box-shadow: 0 0 0 2px hsl(var(--ring) / 0.35);
232
+ }
233
+
234
+ /* ── Row action menu ──────────────────────────────────────────────────── */
235
+
236
+ .an-chat-history-row__menu {
237
+ position: absolute;
238
+ top: 4px;
239
+ inset-inline-end: 4px;
240
+ }
241
+
242
+ .an-chat-history-row__menu-trigger {
243
+ display: inline-flex;
244
+ align-items: center;
245
+ justify-content: center;
246
+ width: 24px;
247
+ height: 24px;
248
+ border: 0;
249
+ border-radius: calc(var(--radius) - 3px);
250
+ background: transparent;
251
+ color: hsl(var(--muted-foreground) / 0.72);
252
+ opacity: 0;
253
+ cursor: pointer;
254
+ transition:
255
+ background 100ms ease,
256
+ color 100ms ease,
257
+ opacity 100ms ease;
258
+ }
259
+
260
+ .an-chat-history-row:hover .an-chat-history-row__menu-trigger,
261
+ .an-chat-history-row:focus-within .an-chat-history-row__menu-trigger,
262
+ .an-chat-history-row__menu-trigger[aria-expanded="true"],
263
+ .an-chat-history-row__menu-trigger--pinned {
264
+ opacity: 1;
265
+ }
266
+
267
+ .an-chat-history-row__menu-trigger:hover,
268
+ .an-chat-history-row__menu-trigger[aria-expanded="true"] {
269
+ background: hsl(var(--accent));
270
+ color: hsl(var(--foreground));
271
+ }
272
+
273
+ .an-chat-history-row__menu-content {
274
+ position: absolute;
275
+ top: calc(100% + 4px);
276
+ inset-inline-end: 0;
277
+ z-index: 30;
278
+ min-width: 160px;
279
+ padding: 4px;
280
+ border: 1px solid hsl(var(--border));
281
+ border-radius: var(--radius);
282
+ background: hsl(var(--popover));
283
+ color: hsl(var(--popover-foreground));
284
+ box-shadow: 0 10px 30px hsl(var(--background) / 0.28);
285
+ }
286
+
287
+ .an-chat-history-row__menu-item {
288
+ display: flex;
289
+ align-items: center;
290
+ gap: 8px;
291
+ width: 100%;
292
+ padding: 6px 8px;
293
+ border: 0;
294
+ border-radius: calc(var(--radius) - 4px);
295
+ background: transparent;
296
+ color: inherit;
297
+ font-size: 12px;
298
+ text-align: start;
299
+ cursor: pointer;
300
+ }
301
+
302
+ .an-chat-history-row__menu-item:hover {
303
+ background: hsl(var(--accent));
304
+ color: hsl(var(--accent-foreground));
305
+ }
306
+
307
+ .an-chat-history-row__menu-item--danger {
308
+ color: hsl(var(--destructive));
309
+ }
310
+
311
+ .an-chat-history-row__menu-item--danger:hover {
312
+ background: hsl(var(--destructive) / 0.12);
313
+ color: hsl(var(--destructive));
314
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/toolkit",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Reusable app-building UI and helpers for Agent-Native apps.",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -14,6 +14,7 @@
14
14
  },
15
15
  "files": [
16
16
  "dist",
17
+ "src",
17
18
  "migration-manifest.json",
18
19
  "README.md"
19
20
  ],
@@ -59,6 +60,20 @@
59
60
  "import": "./dist/collab-ui/*.js",
60
61
  "default": "./dist/collab-ui/*.js"
61
62
  },
63
+ "./chat-history": {
64
+ "types": "./dist/chat-history/index.d.ts",
65
+ "browser": "./dist/chat-history/index.js",
66
+ "development": "./dist/chat-history/index.js",
67
+ "import": "./dist/chat-history/index.js",
68
+ "default": "./dist/chat-history/index.js"
69
+ },
70
+ "./chat-history/*": {
71
+ "types": "./dist/chat-history/*.d.ts",
72
+ "browser": "./dist/chat-history/*.js",
73
+ "development": "./dist/chat-history/*.js",
74
+ "import": "./dist/chat-history/*.js",
75
+ "default": "./dist/chat-history/*.js"
76
+ },
62
77
  "./composer": {
63
78
  "types": "./dist/composer/index.d.ts",
64
79
  "browser": "./dist/composer/index.js",
@@ -173,6 +188,7 @@
173
188
  },
174
189
  "./migration-manifest.json": "./migration-manifest.json",
175
190
  "./styles.css": "./dist/styles.css",
191
+ "./chat-history.css": "./dist/chat-history.css",
176
192
  "./editor.css": "./dist/editor.css"
177
193
  },
178
194
  "publishConfig": {
@@ -0,0 +1,84 @@
1
+ import {
2
+ useEffect,
3
+ useSyncExternalStore,
4
+ type ReactNode,
5
+ type FC,
6
+ } from "react";
7
+
8
+ /**
9
+ * External store for the page's header title + actions. We use an external
10
+ * store (not React context) so that pages can inject ReactNode without
11
+ * subscribing to the header state themselves — subscribing would trigger a
12
+ * re-render on every update, which in turn creates new JSX, which updates
13
+ * the store again, which re-renders… an infinite loop.
14
+ *
15
+ * Only <Header /> reads the store via useSyncExternalStore; pages only write.
16
+ */
17
+
18
+ type Listener = () => void;
19
+
20
+ let currentTitle: ReactNode = null;
21
+ let currentActions: ReactNode = null;
22
+ const listeners = new Set<Listener>();
23
+
24
+ function notify() {
25
+ for (const l of listeners) l();
26
+ }
27
+
28
+ function subscribe(l: Listener): () => void {
29
+ listeners.add(l);
30
+ return () => {
31
+ listeners.delete(l);
32
+ };
33
+ }
34
+
35
+ /** Consumed only by <Header /> — returns the current title. */
36
+ export function useHeaderTitle(): ReactNode {
37
+ return useSyncExternalStore(
38
+ subscribe,
39
+ () => currentTitle,
40
+ () => currentTitle,
41
+ );
42
+ }
43
+
44
+ /** Consumed only by <Header /> — returns the current actions slot. */
45
+ export function useHeaderActions(): ReactNode {
46
+ return useSyncExternalStore(
47
+ subscribe,
48
+ () => currentActions,
49
+ () => currentActions,
50
+ );
51
+ }
52
+
53
+ /**
54
+ * Provider is now a no-op wrapper for backwards compatibility — the state
55
+ * lives in the module-level store above. Kept as a component so callers of
56
+ * <HeaderActionsProvider> don't need to change.
57
+ */
58
+ export const HeaderActionsProvider: FC<{ children: ReactNode }> = ({
59
+ children,
60
+ }) => <>{children}</>;
61
+
62
+ /** Mount a custom title into the app header. Cleans up on unmount. */
63
+ export function useSetPageTitle(node: ReactNode) {
64
+ useEffect(() => {
65
+ currentTitle = node;
66
+ notify();
67
+ return () => {
68
+ currentTitle = null;
69
+ notify();
70
+ };
71
+ });
72
+ }
73
+
74
+ /** Mount ReactNode into the header's actions slot. Cleans up on unmount. */
75
+ export function useSetHeaderActions(node: ReactNode) {
76
+ useEffect(() => {
77
+ currentActions = node;
78
+ notify();
79
+ return () => {
80
+ currentActions = null;
81
+ notify();
82
+ };
83
+ });
84
+ }
@@ -0,0 +1 @@
1
+ export * from "./header-actions.js";