@theoremjs/react 0.0.0-stage → 0.3.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 (231) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +246 -2
  3. package/client/attachment-hover-preview.d.ts +11 -0
  4. package/client/attachment-hover-preview.js +36 -0
  5. package/client/audio-level.d.ts +5 -0
  6. package/client/audio-level.js +24 -0
  7. package/client/composer-attachments.d.ts +30 -0
  8. package/client/composer-attachments.js +33 -0
  9. package/client/composer-drawer.d.ts +19 -0
  10. package/client/composer-drawer.js +15 -0
  11. package/client/composer-hints.d.ts +25 -0
  12. package/client/composer-hints.js +20 -0
  13. package/client/composer-primary.d.ts +16 -0
  14. package/client/composer-primary.js +25 -0
  15. package/client/decision-transport.d.ts +48 -0
  16. package/client/decision-transport.js +102 -0
  17. package/client/decode-composer-draft.d.ts +11 -0
  18. package/client/decode-composer-draft.js +12 -0
  19. package/client/encode-composer-draft.d.ts +9 -0
  20. package/client/encode-composer-draft.js +34 -0
  21. package/client/encode-files.d.ts +18 -0
  22. package/client/encode-files.js +54 -0
  23. package/client/failure.d.ts +32 -0
  24. package/client/failure.js +34 -0
  25. package/client/generation-selection.d.ts +15 -0
  26. package/client/generation-selection.js +24 -0
  27. package/client/host-call.d.ts +51 -0
  28. package/client/host-call.js +42 -0
  29. package/client/host-transport.d.ts +68 -0
  30. package/client/host-transport.js +74 -0
  31. package/client/image-output.d.ts +6 -0
  32. package/client/image-output.js +13 -0
  33. package/client/index.d.ts +20 -0
  34. package/client/index.js +18 -0
  35. package/client/ink-waveform.d.ts +17 -0
  36. package/client/ink-waveform.js +69 -0
  37. package/client/live/apply-live-turn-tool-event.d.ts +14 -0
  38. package/client/live/apply-live-turn-tool-event.js +39 -0
  39. package/client/live/live-captions.d.ts +23 -0
  40. package/client/live/live-captions.js +70 -0
  41. package/client/live/live-mic-forward.d.ts +29 -0
  42. package/client/live/live-mic-forward.js +37 -0
  43. package/client/live/live-state.d.ts +11 -0
  44. package/client/live/live-state.js +20 -0
  45. package/client/live/live-tool.d.ts +11 -0
  46. package/client/live/live-tool.js +1 -0
  47. package/client/live/live-video.d.ts +10 -0
  48. package/client/live/live-video.js +71 -0
  49. package/client/live/run-live-tool-call.d.ts +17 -0
  50. package/client/live/run-live-tool-call.js +32 -0
  51. package/client/live-client.d.ts +141 -0
  52. package/client/live-client.js +638 -0
  53. package/client/live-errors.d.ts +2 -0
  54. package/client/live-errors.js +9 -0
  55. package/client/live-messages.d.ts +110 -0
  56. package/client/live-messages.js +67 -0
  57. package/client/mic-capture.d.ts +4 -0
  58. package/client/mic-capture.js +6 -0
  59. package/client/oauth-popup.d.ts +26 -0
  60. package/client/oauth-popup.js +30 -0
  61. package/client/pcm-downsample.d.ts +4 -0
  62. package/client/pcm-downsample.js +45 -0
  63. package/client/run-commit.d.ts +61 -0
  64. package/client/run-commit.js +124 -0
  65. package/client/run-session.d.ts +80 -0
  66. package/client/run-session.js +215 -0
  67. package/client/schema-fields.d.ts +63 -0
  68. package/client/schema-fields.js +178 -0
  69. package/client/shaped-data.d.ts +118 -0
  70. package/client/shaped-data.js +314 -0
  71. package/client/source-citations.d.ts +13 -0
  72. package/client/source-citations.js +56 -0
  73. package/client/state-fields.d.ts +16 -0
  74. package/client/state-fields.js +44 -0
  75. package/client/tool-result.d.ts +78 -0
  76. package/client/tool-result.js +275 -0
  77. package/client/tool-resume.d.ts +33 -0
  78. package/client/tool-resume.js +11 -0
  79. package/client/trace-feed.d.ts +13 -0
  80. package/client/trace-feed.js +18 -0
  81. package/client/trace-story.d.ts +163 -0
  82. package/client/trace-story.js +416 -0
  83. package/client/trace-view.d.ts +130 -0
  84. package/client/trace-view.js +293 -0
  85. package/client/transcript-groups.d.ts +114 -0
  86. package/client/transcript-groups.js +167 -0
  87. package/client/transcript-scroll.d.ts +7 -0
  88. package/client/transcript-scroll.js +6 -0
  89. package/client/transport.d.ts +176 -0
  90. package/client/transport.js +256 -0
  91. package/client/turn-client.d.ts +35 -0
  92. package/client/turn-client.js +93 -0
  93. package/client/voice-label.d.ts +2 -0
  94. package/client/voice-label.js +15 -0
  95. package/client/voice-recorder.d.ts +27 -0
  96. package/client/voice-recorder.js +165 -0
  97. package/client/walk-away.d.ts +34 -0
  98. package/client/walk-away.js +48 -0
  99. package/client/wire-line.d.ts +56 -0
  100. package/client/wire-line.js +90 -0
  101. package/client/worklets/mic-capture.js +16 -0
  102. package/components/InkWaveform.d.ts +10 -0
  103. package/components/InkWaveform.js +108 -0
  104. package/components/live/use-live-runner-controls.d.ts +48 -0
  105. package/components/live/use-live-runner-controls.js +100 -0
  106. package/components/live/use-live-runner-model.d.ts +45 -0
  107. package/components/live/use-live-runner-model.js +175 -0
  108. package/components/live/use-live-runner-ui.d.ts +65 -0
  109. package/components/live/use-live-runner-ui.js +159 -0
  110. package/components/live/use-live-session-client.d.ts +41 -0
  111. package/components/live/use-live-session-client.js +123 -0
  112. package/components/use-composer-voice.d.ts +28 -0
  113. package/components/use-composer-voice.js +90 -0
  114. package/components/use-editor-selection.d.ts +3 -0
  115. package/components/use-editor-selection.js +16 -0
  116. package/components/use-voice-playback.d.ts +16 -0
  117. package/components/use-voice-playback.js +68 -0
  118. package/hooks/use-described.d.ts +8 -0
  119. package/hooks/use-described.js +23 -0
  120. package/hooks/use-theorem-chat-actions.d.ts +75 -0
  121. package/hooks/use-theorem-chat-actions.js +265 -0
  122. package/hooks/use-theorem-chat-state.d.ts +66 -0
  123. package/hooks/use-theorem-chat-state.js +118 -0
  124. package/hooks/use-theorem-chat.d.ts +63 -0
  125. package/hooks/use-theorem-chat.js +340 -0
  126. package/hooks/use-theorem-decision.d.ts +23 -0
  127. package/hooks/use-theorem-decision.js +75 -0
  128. package/hooks/use-theorem-host.d.ts +44 -0
  129. package/hooks/use-theorem-host.js +117 -0
  130. package/hooks/use-theorem-interface.d.ts +19 -0
  131. package/hooks/use-theorem-interface.js +25 -0
  132. package/hooks/use-trace-records.d.ts +4 -0
  133. package/hooks/use-trace-records.js +7 -0
  134. package/index.d.ts +14 -0
  135. package/index.js +14 -0
  136. package/live.d.ts +8 -0
  137. package/live.js +10 -0
  138. package/package.json +73 -4
  139. package/server/credential-store.d.ts +24 -0
  140. package/server/credential-store.js +14 -0
  141. package/server/decision-handler.d.ts +34 -0
  142. package/server/decision-handler.js +55 -0
  143. package/server/handler.d.ts +114 -0
  144. package/server/handler.js +568 -0
  145. package/server/json-response.d.ts +2 -0
  146. package/server/json-response.js +7 -0
  147. package/server/mod.d.ts +16 -0
  148. package/server/mod.js +15 -0
  149. package/server/request-check.d.ts +16 -0
  150. package/server/request-check.js +34 -0
  151. package/server/session-store.d.ts +74 -0
  152. package/server/session-store.js +49 -0
  153. package/server/steer-inbox.d.ts +35 -0
  154. package/server/steer-inbox.js +52 -0
  155. package/server/walk-away.d.ts +22 -0
  156. package/server/walk-away.js +41 -0
  157. package/styles/ink-controls.css +134 -0
  158. package/ui/ChatComposerBar.d.ts +39 -0
  159. package/ui/ChatComposerBar.js +251 -0
  160. package/ui/ChatTranscript.d.ts +30 -0
  161. package/ui/ChatTranscript.js +474 -0
  162. package/ui/ConsoleFrame.d.ts +47 -0
  163. package/ui/ConsoleFrame.js +46 -0
  164. package/ui/DecisionAnswers.d.ts +15 -0
  165. package/ui/DecisionAnswers.js +102 -0
  166. package/ui/LiveRunner.d.ts +28 -0
  167. package/ui/LiveRunner.js +193 -0
  168. package/ui/SchemaFields.d.ts +10 -0
  169. package/ui/SchemaFields.js +122 -0
  170. package/ui/ShapedData.d.ts +11 -0
  171. package/ui/ShapedData.js +151 -0
  172. package/ui/SidePanel.d.ts +57 -0
  173. package/ui/SidePanel.js +50 -0
  174. package/ui/StateFields.d.ts +36 -0
  175. package/ui/StateFields.js +96 -0
  176. package/ui/TheoremChat.d.ts +71 -0
  177. package/ui/TheoremChat.js +146 -0
  178. package/ui/TheoremDecision.d.ts +38 -0
  179. package/ui/TheoremDecision.js +87 -0
  180. package/ui/TheoremHost.d.ts +38 -0
  181. package/ui/TheoremHost.js +150 -0
  182. package/ui/ToolGateCard.d.ts +28 -0
  183. package/ui/ToolGateCard.js +100 -0
  184. package/ui/ToolResult.d.ts +10 -0
  185. package/ui/ToolResult.js +60 -0
  186. package/ui/ToolResultCharts.d.ts +5 -0
  187. package/ui/ToolResultCharts.js +86 -0
  188. package/ui/TraceCharts.d.ts +13 -0
  189. package/ui/TraceCharts.js +235 -0
  190. package/ui/TraceGuardrails.d.ts +10 -0
  191. package/ui/TraceGuardrails.js +56 -0
  192. package/ui/TraceInspector.d.ts +6 -0
  193. package/ui/TraceInspector.js +189 -0
  194. package/ui/TraceInspectorPanel.d.ts +24 -0
  195. package/ui/TraceInspectorPanel.js +57 -0
  196. package/ui/TraceOverview.d.ts +34 -0
  197. package/ui/TraceOverview.js +96 -0
  198. package/ui/TraceSpanDetail.d.ts +10 -0
  199. package/ui/TraceSpanDetail.js +188 -0
  200. package/ui/TraceStory.d.ts +20 -0
  201. package/ui/TraceStory.js +107 -0
  202. package/ui/TraceValues.d.ts +36 -0
  203. package/ui/TraceValues.js +113 -0
  204. package/ui/TraceWaterfall.d.ts +13 -0
  205. package/ui/TraceWaterfall.js +132 -0
  206. package/ui/VoiceNote.d.ts +12 -0
  207. package/ui/VoiceNote.js +28 -0
  208. package/ui/built/theme.css +774 -0
  209. package/ui/built/theorem.d.ts +13 -0
  210. package/ui/built/theorem.js +631 -0
  211. package/ui/built/theorem.variants.d.ts +16 -0
  212. package/ui/disclosure-motion.d.ts +6 -0
  213. package/ui/disclosure-motion.js +163 -0
  214. package/ui/icons.d.ts +4 -0
  215. package/ui/icons.js +37 -0
  216. package/ui/index.d.ts +25 -0
  217. package/ui/index.js +29 -0
  218. package/ui/labels-provider.d.ts +16 -0
  219. package/ui/labels-provider.js +61 -0
  220. package/ui/labels.d.ts +1153 -0
  221. package/ui/labels.js +603 -0
  222. package/ui/theme.d.ts +10 -0
  223. package/ui/theme.js +13 -0
  224. package/ui/theorem-theme.d.ts +10 -0
  225. package/ui/theorem-theme.js +83 -0
  226. package/ui/trace-palette.d.ts +24 -0
  227. package/ui/trace-palette.js +24 -0
  228. package/ui/trace-patterns.d.ts +32 -0
  229. package/ui/trace-patterns.js +44 -0
  230. package/ui/transcript-copy-text.d.ts +4 -0
  231. package/ui/transcript-copy-text.js +39 -0
@@ -0,0 +1,163 @@
1
+ import { useEffect } from 'react';
2
+ /**
3
+ * Easing for disclosures whose panel mounts on open and unmounts on close
4
+ * (ChatToolCalls row details, TreeList branches): CSS can't ease an element
5
+ * that's already gone, so a close is held until the panel has eased shut,
6
+ * then replayed; an open eases the new panel up from nothing. Panels that
7
+ * carry their own transition (the themed Collapsible) are left alone.
8
+ */
9
+ /** The panel a disclosure trigger shows: its aria-controls target, or a tree item's group. */
10
+ function panelOf(trigger) {
11
+ const id = trigger.getAttribute('aria-controls');
12
+ if (id)
13
+ return document.getElementById(id);
14
+ return trigger.closest('[role="treeitem"]')?.querySelector(':scope > [role="group"]') ?? null;
15
+ }
16
+ function ownsMotion(panel) {
17
+ return getComputedStyle(panel).transitionDuration.split(',').some((d) => Number.parseFloat(d) > 0);
18
+ }
19
+ function isToggleKey(event) {
20
+ return !(event instanceof KeyboardEvent) || event.key === 'Enter' || event.key === ' ';
21
+ }
22
+ /**
23
+ * The element pressed and the disclosure trigger it sits in, when that trigger is under `root`. In a
24
+ * tree, the press is the row's own: a leaf's row toggles nothing, and a row with an action of its own
25
+ * (a label that selects it, a button at its end) toggles only at its chevron.
26
+ */
27
+ function pressedToggle(event, root) {
28
+ if (!(event.target instanceof Element))
29
+ return undefined;
30
+ const row = event.target.closest('[role="treeitem"]');
31
+ const trigger = row ? treeToggle(event.target, row) : event.target.closest('[aria-expanded]');
32
+ if (!trigger || !root.contains(trigger))
33
+ return undefined;
34
+ return { target: event.target, trigger };
35
+ }
36
+ /** The tree row a press toggles: none for a leaf, and for a row with an action of its own, only a press at its chevron. */
37
+ function treeToggle(target, row) {
38
+ if (!row.hasAttribute('aria-expanded'))
39
+ return undefined;
40
+ if (target.closest('[data-tree-toggle]') !== null)
41
+ return row;
42
+ const acts = row.querySelector(':scope > div :is(button:not([data-tree-toggle]), a[href])') !== null;
43
+ return acts ? undefined : row;
44
+ }
45
+ /** Stops the event: the component does not see it. */
46
+ function hold(event) {
47
+ event.stopPropagation();
48
+ event.preventDefault();
49
+ }
50
+ /** A copy of the pressed key or click, to send once the panel has eased shut. */
51
+ function replayOf(event) {
52
+ return event instanceof KeyboardEvent
53
+ ? new KeyboardEvent(event.type, { key: event.key, bubbles: true, cancelable: true })
54
+ : new MouseEvent(event.type, { bubbles: true, cancelable: true });
55
+ }
56
+ /** CSS time (`0.3s`, `300ms`) in milliseconds. */
57
+ function ms(time) {
58
+ const value = Number.parseFloat(time);
59
+ return time.trim().endsWith('ms') ? value : value * 1000;
60
+ }
61
+ /** Eases a panel's height between shut and its natural height, the theme's medium duration and standard curve. */
62
+ function ease(panel, direction) {
63
+ const style = getComputedStyle(panel);
64
+ const open = {
65
+ height: `${String(panel.getBoundingClientRect().height)}px`,
66
+ paddingTop: style.paddingTop,
67
+ paddingBottom: style.paddingBottom,
68
+ };
69
+ const shut = { height: '0px', paddingTop: '0px', paddingBottom: '0px' };
70
+ const frames = direction === 'open' ? [shut, open] : [open, shut];
71
+ for (const animation of panel.getAnimations())
72
+ animation.cancel();
73
+ return panel.animate(frames.map((frame) => ({ ...frame, boxSizing: 'border-box', overflow: 'clip' })), {
74
+ duration: ms(style.getPropertyValue('--duration-medium')),
75
+ easing: style.getPropertyValue('--ease-standard').trim(),
76
+ // A shut panel stays shut until its unmount; an open one hands back to its natural height.
77
+ fill: direction === 'close' ? 'forwards' : 'none',
78
+ });
79
+ }
80
+ /** Every animation on a panel, settled; a cancelled one rejects `finished`, so settle rather than await all. */
81
+ function settled(panel) {
82
+ return Promise.allSettled(panel.getAnimations().map((animation) => animation.finished));
83
+ }
84
+ /**
85
+ * Eases every disclosure under `ref` open and shut. `onOpened` runs once the
86
+ * new panel is in the DOM, with a promise for its motion finishing.
87
+ */
88
+ export function useDisclosureMotion(ref, onOpened) {
89
+ useEffect(() => {
90
+ const root = ref.current;
91
+ if (!root)
92
+ return;
93
+ const still = matchMedia('(prefers-reduced-motion: reduce)');
94
+ const closing = new WeakSet();
95
+ const replaying = new WeakSet();
96
+ // The trigger the reader just pressed to open; opens the page makes itself aren't eased or followed.
97
+ let opening;
98
+ /** The trigger the reader pressed opens: note it until the toggle commits, within this event. */
99
+ const noteOpening = (trigger) => {
100
+ opening = trigger;
101
+ // A stale note must not claim a later change.
102
+ setTimeout(() => {
103
+ if (opening === trigger)
104
+ opening = undefined;
105
+ });
106
+ };
107
+ /** The panel a close should ease shut first; none when motion is off or the panel eases itself. */
108
+ const panelToEase = (trigger) => {
109
+ const panel = panelOf(trigger);
110
+ return panel && !still.matches && !ownsMotion(panel) ? panel : undefined;
111
+ };
112
+ // Capture, before the component toggles: note what the trigger was, and hold a close.
113
+ const before = (event) => {
114
+ if (!isToggleKey(event) || replaying.has(event))
115
+ return;
116
+ const pressed = pressedToggle(event, root);
117
+ if (!pressed)
118
+ return;
119
+ const { target, trigger } = pressed;
120
+ if (closing.has(trigger)) {
121
+ hold(event);
122
+ return;
123
+ }
124
+ if (trigger.getAttribute('aria-expanded') !== 'true') {
125
+ noteOpening(trigger);
126
+ return;
127
+ }
128
+ const panel = panelToEase(trigger);
129
+ if (!panel)
130
+ return;
131
+ hold(event);
132
+ closing.add(trigger);
133
+ const replay = replayOf(event);
134
+ void ease(panel, 'close').finished.then(() => {
135
+ closing.delete(trigger);
136
+ replaying.add(replay);
137
+ target.dispatchEvent(replay);
138
+ });
139
+ };
140
+ // After the component commits the toggle (a component may stop the event, so
141
+ // watch the attribute rather than wait for the event to bubble): ease the new panel.
142
+ const opened = new MutationObserver(() => {
143
+ const trigger = opening;
144
+ if (!trigger || trigger.getAttribute('aria-expanded') !== 'true')
145
+ return;
146
+ opening = undefined;
147
+ const panel = panelOf(trigger);
148
+ if (!panel)
149
+ return;
150
+ if (!still.matches && !ownsMotion(panel))
151
+ ease(panel, 'open');
152
+ onOpened?.(trigger, panel, settled(panel));
153
+ });
154
+ opened.observe(root, { subtree: true, attributeFilter: ['aria-expanded'] });
155
+ root.addEventListener('click', before, true);
156
+ root.addEventListener('keydown', before, true);
157
+ return () => {
158
+ opened.disconnect();
159
+ root.removeEventListener('click', before, true);
160
+ root.removeEventListener('keydown', before, true);
161
+ };
162
+ }, [ref, onOpened]);
163
+ }
package/ui/icons.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { IconName } from '@astryxdesign/core/Icon';
2
+ import { type ReactNode } from 'react';
3
+ /** Astryx semantic icon registry drawn from Tabler (replaces neutral's lucide set). */
4
+ export declare const tablerIcons: Record<IconName, ReactNode>;
package/ui/icons.js ADDED
@@ -0,0 +1,37 @@
1
+ import { IconAlertTriangle, IconArrowDown, IconArrowsSort, IconArrowUp, IconCalendar, IconCheck, IconChecks, IconChevronDown, IconChevronLeft, IconChevronRight, IconChevronsLeft, IconChevronsRight, IconCircleCheck, IconCircleX, IconClock, IconColumns, IconCopy, IconDots, IconExternalLink, IconEyeOff, IconFilter, IconInfoCircle, IconMenu2, IconMicrophone, IconPlayerStopFilled, IconSearch, IconTool, IconX, } from '@tabler/icons-react';
2
+ import { createElement } from 'react';
3
+ const TABLER_BY_NAME = {
4
+ close: IconX,
5
+ chevronDown: IconChevronDown,
6
+ chevronLeft: IconChevronLeft,
7
+ chevronRight: IconChevronRight,
8
+ chevronsLeft: IconChevronsLeft,
9
+ chevronsRight: IconChevronsRight,
10
+ check: IconCheck,
11
+ success: IconCircleCheck,
12
+ error: IconCircleX,
13
+ warning: IconAlertTriangle,
14
+ info: IconInfoCircle,
15
+ calendar: IconCalendar,
16
+ clock: IconClock,
17
+ externalLink: IconExternalLink,
18
+ menu: IconMenu2,
19
+ moreHorizontal: IconDots,
20
+ search: IconSearch,
21
+ arrowUp: IconArrowUp,
22
+ arrowDown: IconArrowDown,
23
+ arrowsUpDown: IconArrowsSort,
24
+ funnel: IconFilter,
25
+ eyeSlash: IconEyeOff,
26
+ viewColumns: IconColumns,
27
+ copy: IconCopy,
28
+ checkDouble: IconChecks,
29
+ wrench: IconTool,
30
+ stop: IconPlayerStopFilled,
31
+ microphone: IconMicrophone,
32
+ };
33
+ /** Astryx semantic icon registry drawn from Tabler (replaces neutral's lucide set). */
34
+ export const tablerIcons = Object.fromEntries(Object.entries(TABLER_BY_NAME).map(([name, Glyph]) => [
35
+ name,
36
+ createElement(Glyph, { size: '1em', stroke: 1.75, 'aria-hidden': true }),
37
+ ]));
package/ui/index.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Astryx UI for Theorem — `<TheoremChat />` plus the pieces it is built from,
3
+ * `<TheoremDecision />` for decision profiles, and `<TheoremHost />` for host
4
+ * profiles.
5
+ *
6
+ * Styling is Astryx: pass `theme` (any `defineTheme` result, e.g. one that
7
+ * `extends: theoremTheme`) or wrap your app in your own `<Theme>`.
8
+ *
9
+ * @module
10
+ */
11
+ export type { InkWaveStatus } from '../client/ink-waveform.ts';
12
+ export { InkWaveform, type InkWaveformProps } from '../components/InkWaveform.tsx';
13
+ export { ChatComposerBar, type ChatComposerBarProps } from './ChatComposerBar.tsx';
14
+ export { ChatTranscript, type ChatTranscriptProps } from './ChatTranscript.tsx';
15
+ export { TheoremDecisionAnswers, type TheoremDecisionAnswersProps } from './DecisionAnswers.tsx';
16
+ export { TheoremDecision, type TheoremDecisionProps } from './TheoremDecision.tsx';
17
+ export { TheoremHost, type TheoremHostProps } from './TheoremHost.tsx';
18
+ export { DEFAULT_CHAT_MAX_WIDTH, TheoremChat, type TheoremChatHandle, type TheoremChatProps, } from './TheoremChat.tsx';
19
+ export { ApprovalCard, type ApprovalCardProps, AuthChallengeCard, type AuthChallengeCardProps, type ToolDecision, } from './ToolGateCard.tsx';
20
+ export { ToolResult } from './ToolResult.tsx';
21
+ export { tablerIcons, theoremTheme } from './built/theorem.js';
22
+ export { useDisclosureMotion } from './disclosure-motion.ts';
23
+ export { composerDrawerLabel, type LabelText, liveStateLabel, THEOREM_UI_CATALOG, type TheoremLabelKey, type TheoremLabelOverrides, type TheoremLabels, type TheoremLabelValues, type TheoremUiCatalog, voiceNoteName, workStatusLabel, } from './labels.ts';
24
+ export { TheoremLabelsProvider, type TheoremLabelsProviderProps, useLabels } from './labels-provider.tsx';
25
+ export { TheoremThemeProvider, type TheoremThemeProviderProps } from './theme.tsx';
package/ui/index.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Astryx UI for Theorem — `<TheoremChat />` plus the pieces it is built from,
3
+ * `<TheoremDecision />` for decision profiles, and `<TheoremHost />` for host
4
+ * profiles.
5
+ *
6
+ * Styling is Astryx: pass `theme` (any `defineTheme` result, e.g. one that
7
+ * `extends: theoremTheme`) or wrap your app in your own `<Theme>`.
8
+ *
9
+ * @module
10
+ */
11
+ // Astryx's documented order: reset → components → theme. The reset lives in
12
+ // `@layer reset`, so any unlayered host CSS still wins over it.
13
+ import '@astryxdesign/core/reset.css';
14
+ import '@astryxdesign/core/astryx.css';
15
+ import './built/theme.css';
16
+ export { InkWaveform } from "../components/InkWaveform.js";
17
+ export { ChatComposerBar } from "./ChatComposerBar.js";
18
+ export { ChatTranscript } from "./ChatTranscript.js";
19
+ export { TheoremDecisionAnswers } from "./DecisionAnswers.js";
20
+ export { TheoremDecision } from "./TheoremDecision.js";
21
+ export { TheoremHost } from "./TheoremHost.js";
22
+ export { DEFAULT_CHAT_MAX_WIDTH, TheoremChat, } from "./TheoremChat.js";
23
+ export { ApprovalCard, AuthChallengeCard, } from "./ToolGateCard.js";
24
+ export { ToolResult } from "./ToolResult.js";
25
+ export { tablerIcons, theoremTheme } from './built/theorem.js';
26
+ export { useDisclosureMotion } from "./disclosure-motion.js";
27
+ export { composerDrawerLabel, liveStateLabel, THEOREM_UI_CATALOG, voiceNoteName, workStatusLabel, } from "./labels.js";
28
+ export { TheoremLabelsProvider, useLabels } from "./labels-provider.js";
29
+ export { TheoremThemeProvider } from "./theme.js";
@@ -0,0 +1,16 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type LabelText, type TheoremLabels } from './labels.ts';
3
+ export type TheoremLabelsProviderProps = {
4
+ /** Replacements by locale for any `@theorem.*` or `@astryx.*` line; checked on mount. */
5
+ labels?: TheoremLabels;
6
+ children: ReactNode;
7
+ };
8
+ /**
9
+ * Makes Theorem's lines resolvable under the host's Astryx locale, messages
10
+ * and overrides (or Astryx's `en` default), adding `labels` on top. Every
11
+ * exported component renders one, so none shows a raw key; nested ones pass
12
+ * straight through.
13
+ */
14
+ export declare function TheoremLabelsProvider({ labels, children }: TheoremLabelsProviderProps): import("react").JSX.Element;
15
+ /** The default UI's words, from the nearest Theorem labels provider. */
16
+ export declare function useLabels(): LabelText;
@@ -0,0 +1,61 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import { InternationalizationContext, InternationalizationProvider, useTranslator, } from '@astryxdesign/core/i18n';
3
+ import { use, useMemo } from 'react';
4
+ import { assertLabelOverrides, THEOREM_UI_CATALOG } from "./labels.js";
5
+ /** Message tables this module built, by the base language their catalog sits under. */
6
+ const WITH_CATALOG = new WeakMap();
7
+ /** `en-GB` → `en`: the last step of Astryx's locale fallback chain. */
8
+ function baseLanguage(locale) {
9
+ try {
10
+ return new Intl.Locale(locale).language;
11
+ }
12
+ catch {
13
+ return locale.split('-')[0] ?? locale;
14
+ }
15
+ }
16
+ /**
17
+ * The host's messages with Theorem's catalog under the locale's base language,
18
+ * beneath the host's own entries there — so a host translation wins and a
19
+ * missing one falls back to the default line, never to the raw key.
20
+ */
21
+ function withCatalog(messages, locale) {
22
+ const base = baseLanguage(locale);
23
+ if (WITH_CATALOG.get(messages) === base)
24
+ return messages;
25
+ const next = { ...messages, [base]: { ...THEOREM_UI_CATALOG, ...messages[base] } };
26
+ WITH_CATALOG.set(next, base);
27
+ return next;
28
+ }
29
+ /** The host's overrides, then `labels` over them, locale by locale. */
30
+ function withLabels(host, labels) {
31
+ if (!labels)
32
+ return host;
33
+ const merged = {};
34
+ for (const [locale, table] of [...Object.entries(host ?? {}), ...Object.entries(labels)]) {
35
+ merged[locale] = { ...merged[locale], ...table };
36
+ }
37
+ return merged;
38
+ }
39
+ /**
40
+ * Makes Theorem's lines resolvable under the host's Astryx locale, messages
41
+ * and overrides (or Astryx's `en` default), adding `labels` on top. Every
42
+ * exported component renders one, so none shows a raw key; nested ones pass
43
+ * straight through.
44
+ */
45
+ export function TheoremLabelsProvider({ labels, children }) {
46
+ const host = use(InternationalizationContext);
47
+ const messages = useMemo(() => withCatalog(host.messages, host.locale), [host.messages, host.locale]);
48
+ const overrides = useMemo(() => {
49
+ assertLabelOverrides(host.overrides ?? {}, false);
50
+ if (labels)
51
+ assertLabelOverrides(labels, true);
52
+ return withLabels(host.overrides, labels);
53
+ }, [host.overrides, labels]);
54
+ if (messages === host.messages && overrides === host.overrides)
55
+ return _jsx(_Fragment, { children: children });
56
+ return (_jsx(InternationalizationProvider, { locale: host.locale, dir: host.direction, messages: messages, overrides: overrides, children: children }));
57
+ }
58
+ /** The default UI's words, from the nearest Theorem labels provider. */
59
+ export function useLabels() {
60
+ return useTranslator();
61
+ }