@cjlapao/ui-kit-vue 0.2.0 → 0.2.3

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 (216) hide show
  1. package/dist/index.cjs +18 -25
  2. package/dist/index.css +37732 -13285
  3. package/dist/index.js +31192 -21036
  4. package/dist/types/common/chat/markdown.d.ts +8 -0
  5. package/dist/types/common/chat/storage.d.ts +48 -0
  6. package/dist/types/common/chat/stream.d.ts +43 -0
  7. package/dist/types/common/chat/types.d.ts +143 -0
  8. package/dist/types/common/connectionFlow/header.d.ts +56 -0
  9. package/dist/types/common/connectionFlow/icons.d.ts +15 -0
  10. package/dist/types/common/connectionFlow/index.d.ts +6 -0
  11. package/dist/types/common/connectionFlow/layout.d.ts +73 -0
  12. package/dist/types/common/connectionFlow/measure.d.ts +94 -0
  13. package/dist/types/common/connectionFlow/paint.d.ts +36 -0
  14. package/dist/types/common/connectionFlow/router.d.ts +131 -0
  15. package/dist/types/common/connectionFlow/tones.d.ts +79 -0
  16. package/dist/types/common/connectionFlow/types.d.ts +394 -0
  17. package/dist/types/common/gantt/drag.d.ts +221 -0
  18. package/dist/types/common/gantt/index.d.ts +11 -0
  19. package/dist/types/common/gantt/layout.d.ts +133 -0
  20. package/dist/types/common/gantt/sample.d.ts +15 -0
  21. package/dist/types/common/gantt/time.d.ts +77 -0
  22. package/dist/types/common/gantt/tokens.d.ts +73 -0
  23. package/dist/types/common/gantt/types.d.ts +216 -0
  24. package/dist/types/common/i18n/builtIn/de.d.ts +2 -0
  25. package/dist/types/common/i18n/builtIn/en.d.ts +2 -0
  26. package/dist/types/common/i18n/builtIn/es.d.ts +2 -0
  27. package/dist/types/common/i18n/builtIn/fr.d.ts +2 -0
  28. package/dist/types/common/i18n/builtIn/index.d.ts +15 -0
  29. package/dist/types/common/i18n/builtIn/pt.d.ts +2 -0
  30. package/dist/types/common/i18n/catalog.d.ts +32 -0
  31. package/dist/types/common/i18n/createI18n.d.ts +2 -0
  32. package/dist/types/common/i18n/dates.d.ts +12 -0
  33. package/dist/types/common/i18n/detect.d.ts +29 -0
  34. package/dist/types/common/i18n/icu.d.ts +36 -0
  35. package/dist/types/common/i18n/index.d.ts +10 -0
  36. package/dist/types/common/i18n/provider.d.ts +7 -0
  37. package/dist/types/common/i18n/storage.d.ts +8 -0
  38. package/dist/types/common/i18n/types.d.ts +64 -0
  39. package/dist/types/common/i18n/warn.d.ts +5 -0
  40. package/dist/types/common/theme/Theme.d.ts +941 -3
  41. package/dist/types/common/theme/glass.d.ts +90 -11
  42. package/dist/types/common/theme/randomThemeColor.d.ts +4 -4
  43. package/dist/types/common/tooltip/placement.d.ts +103 -0
  44. package/dist/types/common/tooltip/tokens.d.ts +40 -0
  45. package/dist/types/common/types/TableSettings.d.ts +15 -0
  46. package/dist/types/common/types/Variables.d.ts +71 -1
  47. package/dist/types/common/utils/dates.d.ts +113 -0
  48. package/dist/types/common/utils/gravatar.d.ts +0 -10
  49. package/dist/types/common/utils/safeStorage.d.ts +28 -0
  50. package/dist/types/common/utils/sanitizeSvg.d.ts +44 -0
  51. package/dist/types/common/utils/smartVariables.d.ts +74 -18
  52. package/dist/types/common/utils/tableStorage.d.ts +38 -0
  53. package/dist/types/vue/src/chat/index.d.ts +4 -0
  54. package/dist/types/vue/src/components/AccessMatrix.test.d.ts +1 -0
  55. package/dist/types/vue/src/components/AccessMatrix.vue.d.ts +23 -1
  56. package/dist/types/vue/src/components/Accordion.test.d.ts +1 -0
  57. package/dist/types/vue/src/components/Accordion.vue.d.ts +42 -28
  58. package/dist/types/vue/src/components/ActivityFeed.test.d.ts +1 -0
  59. package/dist/types/vue/src/components/ActivityFeed.vue.d.ts +141 -0
  60. package/dist/types/vue/src/components/Alert.test.d.ts +1 -0
  61. package/dist/types/vue/src/components/Alert.vue.d.ts +59 -2
  62. package/dist/types/vue/src/components/ApiErrorState.test.d.ts +1 -0
  63. package/dist/types/vue/src/components/ApiErrorState.vue.d.ts +28 -8
  64. package/dist/types/vue/src/components/AppDivider.vue.d.ts +53 -4
  65. package/dist/types/vue/src/components/Badge.vue.d.ts +45 -13
  66. package/dist/types/vue/src/components/BadgeIcon.vue.d.ts +1 -1
  67. package/dist/types/vue/src/components/BreakdownCard.test.d.ts +1 -0
  68. package/dist/types/vue/src/components/BreakdownCard.vue.d.ts +81 -0
  69. package/dist/types/vue/src/components/Button.vue.d.ts +22 -11
  70. package/dist/types/vue/src/components/Chat.test.d.ts +1 -0
  71. package/dist/types/vue/src/components/Chat.vue.d.ts +80 -0
  72. package/dist/types/vue/src/components/Checkbox.test.d.ts +1 -0
  73. package/dist/types/vue/src/components/Checkbox.vue.d.ts +44 -29
  74. package/dist/types/vue/src/components/CollapsiblePanel.vue.d.ts +5 -5
  75. package/dist/types/vue/src/components/ColorSwatches.test.d.ts +1 -0
  76. package/dist/types/vue/src/components/ColorSwatches.vue.d.ts +42 -0
  77. package/dist/types/vue/src/components/Combobox.test.d.ts +1 -0
  78. package/dist/types/vue/src/components/Combobox.vue.d.ts +61 -12
  79. package/dist/types/vue/src/components/ConnectionFlow/ConnectionFlow.vue.d.ts +153 -17
  80. package/dist/types/vue/src/components/ConnectionFlow/ConnectionFlowCanvas.vue.d.ts +28 -0
  81. package/dist/types/vue/src/components/ConnectionFlow/ConnectionFlowHeader.vue.d.ts +33 -0
  82. package/dist/types/vue/src/components/ConnectionFlow/ConnectionFlowNodeBody.vue.d.ts +32 -0
  83. package/dist/types/vue/src/components/ConnectionFlow/ConnectionFlowSkeleton.vue.d.ts +18 -0
  84. package/dist/types/vue/src/components/ConnectionFlow/ConnectionFlowSvg.vue.d.ts +52 -0
  85. package/dist/types/vue/src/components/ConnectionFlow/connectionFlow.test.d.ts +1 -0
  86. package/dist/types/vue/src/components/ConnectionFlow/index.d.ts +11 -4
  87. package/dist/types/vue/src/components/CustomIcon.vue.d.ts +35 -11
  88. package/dist/types/vue/src/components/DetailItemCard.vue.d.ts +37 -5
  89. package/dist/types/vue/src/components/DropdownButton.vue.d.ts +3 -3
  90. package/dist/types/vue/src/components/DropdownMenu.test.d.ts +1 -0
  91. package/dist/types/vue/src/components/DropdownMenu.vue.d.ts +1 -1
  92. package/dist/types/vue/src/components/DynamicFormField.test.d.ts +1 -0
  93. package/dist/types/vue/src/components/DynamicFormField.vue.d.ts +61 -5
  94. package/dist/types/vue/src/components/DynamicImg.vue.d.ts +28 -3
  95. package/dist/types/vue/src/components/EmptyState.test.d.ts +1 -0
  96. package/dist/types/vue/src/components/EmptyState.vue.d.ts +104 -24
  97. package/dist/types/vue/src/components/FormField.vue.d.ts +2 -1
  98. package/dist/types/vue/src/components/Gantt/Gantt.test.d.ts +1 -0
  99. package/dist/types/vue/src/components/Gantt/Gantt.vue.d.ts +160 -0
  100. package/dist/types/vue/src/components/Gantt/GanttBodyRow.vue.d.ts +78 -0
  101. package/dist/types/vue/src/components/Gantt/GanttCell.vue.d.ts +28 -0
  102. package/dist/types/vue/src/components/Gantt/GanttLinkLayer.vue.d.ts +22 -0
  103. package/dist/types/vue/src/components/Gantt/GanttScale.vue.d.ts +7 -0
  104. package/dist/types/vue/src/components/Gantt/GanttTaskBar.vue.d.ts +53 -0
  105. package/dist/types/vue/src/components/Gantt/GanttToolbar.vue.d.ts +22 -0
  106. package/dist/types/vue/src/components/Gantt/index.d.ts +18 -0
  107. package/dist/types/vue/src/components/Gantt/labels.d.ts +3 -0
  108. package/dist/types/vue/src/components/Gantt/types.d.ts +11 -0
  109. package/dist/types/vue/src/components/Gantt/useGanttDrag.d.ts +105 -0
  110. package/dist/types/vue/src/components/GlassBackground.vue.d.ts +4 -3
  111. package/dist/types/vue/src/components/GlassPanel.vue.d.ts +2 -2
  112. package/dist/types/vue/src/components/HeaderGroup.vue.d.ts +19 -1
  113. package/dist/types/vue/src/components/HelpButton.test.d.ts +1 -0
  114. package/dist/types/vue/src/components/HelpButton.vue.d.ts +15 -6
  115. package/dist/types/vue/src/components/Hero.test.d.ts +1 -0
  116. package/dist/types/vue/src/components/Hero.vue.d.ts +52 -31
  117. package/dist/types/vue/src/components/IconButton.vue.d.ts +12 -6
  118. package/dist/types/vue/src/components/InfiniteScrollPanel.vue.d.ts +61 -14
  119. package/dist/types/vue/src/components/InfoRow.test.d.ts +1 -0
  120. package/dist/types/vue/src/components/InfoRow.vue.d.ts +67 -37
  121. package/dist/types/vue/src/components/InlinePanel.vue.d.ts +12 -18
  122. package/dist/types/vue/src/components/Input.test.d.ts +1 -0
  123. package/dist/types/vue/src/components/Input.vue.d.ts +42 -13
  124. package/dist/types/vue/src/components/InputGroup.test.d.ts +1 -0
  125. package/dist/types/vue/src/components/InputGroup.vue.d.ts +20 -5
  126. package/dist/types/vue/src/components/Loader.test.d.ts +1 -0
  127. package/dist/types/vue/src/components/Loader.vue.d.ts +30 -11
  128. package/dist/types/vue/src/components/MarkdownEditor.vue.d.ts +1 -1
  129. package/dist/types/vue/src/components/MetricBar.test.d.ts +1 -0
  130. package/dist/types/vue/src/components/MetricBar.vue.d.ts +16 -5
  131. package/dist/types/vue/src/components/Modal.vue.d.ts +18 -19
  132. package/dist/types/vue/src/components/MultiProgressBar.vue.d.ts +15 -2
  133. package/dist/types/vue/src/components/MultiSelectPills.test.d.ts +1 -0
  134. package/dist/types/vue/src/components/MultiSelectPills.vue.d.ts +47 -43
  135. package/dist/types/vue/src/components/MultiToggle.test.d.ts +1 -0
  136. package/dist/types/vue/src/components/MultiToggle.vue.d.ts +33 -6
  137. package/dist/types/vue/src/components/NotificationModal.test.d.ts +1 -0
  138. package/dist/types/vue/src/components/NotificationModal.vue.d.ts +19 -2
  139. package/dist/types/vue/src/components/PageHeader.test.d.ts +1 -0
  140. package/dist/types/vue/src/components/PageHeader.vue.d.ts +18 -0
  141. package/dist/types/vue/src/components/PagedPanel.test.d.ts +1 -0
  142. package/dist/types/vue/src/components/PagedPanel.vue.d.ts +39 -11
  143. package/dist/types/vue/src/components/Panel.vue.d.ts +18 -9
  144. package/dist/types/vue/src/components/PasswordInput.test.d.ts +1 -0
  145. package/dist/types/vue/src/components/PasswordInput.vue.d.ts +20 -3
  146. package/dist/types/vue/src/components/Picker.test.d.ts +1 -0
  147. package/dist/types/vue/src/components/Picker.vue.d.ts +3 -3
  148. package/dist/types/vue/src/components/Pill.vue.d.ts +63 -5
  149. package/dist/types/vue/src/components/Progress.test.d.ts +1 -0
  150. package/dist/types/vue/src/components/Progress.vue.d.ts +60 -11
  151. package/dist/types/vue/src/components/ProgressSpinner.test.d.ts +1 -0
  152. package/dist/types/vue/src/components/ProgressSpinner.vue.d.ts +46 -0
  153. package/dist/types/vue/src/components/ScrollArea.test.d.ts +1 -0
  154. package/dist/types/vue/src/components/ScrollArea.vue.d.ts +52 -0
  155. package/dist/types/vue/src/components/SearchBar.vue.d.ts +2 -3
  156. package/dist/types/vue/src/components/Section.vue.d.ts +1 -1
  157. package/dist/types/vue/src/components/SectionCard.vue.d.ts +2 -2
  158. package/dist/types/vue/src/components/Select.test.d.ts +1 -0
  159. package/dist/types/vue/src/components/Select.vue.d.ts +41 -16
  160. package/dist/types/vue/src/components/SidePanel.vue.d.ts +1 -1
  161. package/dist/types/vue/src/components/SmartInput.vue.d.ts +49 -18
  162. package/dist/types/vue/src/components/SmartValue.vue.d.ts +20 -13
  163. package/dist/types/vue/src/components/SmartVariableBadge.vue.d.ts +17 -0
  164. package/dist/types/vue/src/components/Spinner.test.d.ts +1 -0
  165. package/dist/types/vue/src/components/Spinner.vue.d.ts +12 -5
  166. package/dist/types/vue/src/components/SplitView.vue.d.ts +6 -6
  167. package/dist/types/vue/src/components/StartupStageStepper.vue.d.ts +1 -1
  168. package/dist/types/vue/src/components/StatChartTile.vue.d.ts +5 -0
  169. package/dist/types/vue/src/components/StatCountTile.vue.d.ts +5 -1
  170. package/dist/types/vue/src/components/StatGraphTile.vue.d.ts +1 -1
  171. package/dist/types/vue/src/components/StatTile.test.d.ts +1 -0
  172. package/dist/types/vue/src/components/StatTile.vue.d.ts +5 -1
  173. package/dist/types/vue/src/components/StatusSpinner.test.d.ts +1 -0
  174. package/dist/types/vue/src/components/StatusSpinner.vue.d.ts +10 -5
  175. package/dist/types/vue/src/components/Stepper.test.d.ts +1 -0
  176. package/dist/types/vue/src/components/Stepper.vue.d.ts +62 -25
  177. package/dist/types/vue/src/components/Table.test.d.ts +1 -0
  178. package/dist/types/vue/src/components/Table.vue.d.ts +67 -14
  179. package/dist/types/vue/src/components/Tabs.vue.d.ts +20 -3
  180. package/dist/types/vue/src/components/TagPicker.vue.d.ts +3 -3
  181. package/dist/types/vue/src/components/Textarea.vue.d.ts +8 -5
  182. package/dist/types/vue/src/components/TimelinePanel/TimelinePanel.vue.d.ts +4 -4
  183. package/dist/types/vue/src/components/Toggle.vue.d.ts +4 -4
  184. package/dist/types/vue/src/components/Toolbar.test.d.ts +1 -0
  185. package/dist/types/vue/src/components/Toolbar.vue.d.ts +62 -0
  186. package/dist/types/vue/src/components/Tooltip.test.d.ts +1 -0
  187. package/dist/types/vue/src/components/Tooltip.vue.d.ts +20 -3
  188. package/dist/types/vue/src/components/TooltipWrapper.vue.d.ts +24 -3
  189. package/dist/types/vue/src/components/TreeView/TreeFlowSvg.vue.d.ts +5 -5
  190. package/dist/types/vue/src/components/TreeView/TreeItemRow.vue.d.ts +2 -2
  191. package/dist/types/vue/src/components/TreeView/TreeView.vue.d.ts +4 -4
  192. package/dist/types/vue/src/components/UserAvatar.test.d.ts +1 -0
  193. package/dist/types/vue/src/components/UserAvatar.vue.d.ts +56 -6
  194. package/dist/types/vue/src/components/VariablePicker.vue.d.ts +23 -6
  195. package/dist/types/vue/src/components/__dbg.test.d.ts +1 -0
  196. package/dist/types/vue/src/components/index.d.ts +50 -31
  197. package/dist/types/vue/src/components/internal/InfoRowContent.vue.d.ts +52 -0
  198. package/dist/types/vue/src/components/internal/PagedPanelContent.vue.d.ts +47 -0
  199. package/dist/types/vue/src/connectionFlow/index.d.ts +1 -0
  200. package/dist/types/vue/src/contexts/IconContext.d.ts +8 -3
  201. package/dist/types/vue/src/i18n/I18nContext.d.ts +14 -0
  202. package/dist/types/vue/src/i18n/I18nProvider.test.d.ts +2 -0
  203. package/dist/types/vue/src/i18n/I18nProvider.vue.d.ts +35 -0
  204. package/dist/types/vue/src/i18n/index.d.ts +8 -0
  205. package/dist/types/vue/src/i18n/kit-components-spot.test.d.ts +1 -0
  206. package/dist/types/vue/src/i18n/useI18n.d.ts +44 -0
  207. package/dist/types/vue/src/index.d.ts +2 -2
  208. package/dist/types/vue/src/test-setup.d.ts +5 -0
  209. package/dist/types/vue/src/types/Icon.d.ts +11 -2
  210. package/dist/types/vue/src/types/TableSettings.d.ts +1 -0
  211. package/dist/types/vue/src/types/index.d.ts +1 -0
  212. package/dist/types/vue/src/utils/index.d.ts +1 -0
  213. package/dist/types/vue/src/utils/sanitizeSvg.d.ts +1 -0
  214. package/dist/types/vue/src/utils/tableStorage.d.ts +1 -0
  215. package/dist/ui-kit-vue.css +1 -1
  216. package/package.json +8 -3
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Dependency-free, XSS-safe markdown for chat content: fenced code, GFM
3
+ * tables, headings, lists, rules, links, inline code/bold/italic. User
4
+ * text is HTML-escaped before any markup exists, so the only HTML in the
5
+ * output is ours. Classes are literal Tailwind — the renderer styles its
6
+ * own output, and both kits get it identically.
7
+ */
8
+ export declare function renderChatMarkdown(src: string): string;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The two built-in storage adapters. Both honour the same OData-flavoured
3
+ * paging contract; the REST one talks `$top`/`$skip`/`$count` to a
4
+ * `/chats`-shaped API, the local one keeps an index of metas plus one
5
+ * transcript per chat in localStorage.
6
+ */
7
+ import type { ChatMessage, ChatPage, ChatStorage } from "./types";
8
+ export declare const newId: () => string;
9
+ /** Slice a list OData-style and report the whole total. */
10
+ export declare function paginate<T>(items: T[], skip?: number, top?: number): ChatPage<T>;
11
+ export interface LocalChatStorageOptions {
12
+ /** Key prefix for every stored key. @default "uikit.chat.v1" */
13
+ prefix?: string;
14
+ /** Injectable storage object (tests pass a memory map). */
15
+ storage?: Pick<Storage, "getItem" | "setItem" | "removeItem">;
16
+ /** Messages stored per chat before the oldest are dropped. @default 1000 */
17
+ maxStoredMessages?: number;
18
+ }
19
+ /**
20
+ * localStorage adapter. The transcript of a chat lives under its own key
21
+ * and the rail reads only the index — one big JSON blob is never parsed to
22
+ * draw a list.
23
+ */
24
+ export declare function createLocalChatStorage(options?: LocalChatStorageOptions): ChatStorage;
25
+ export interface RestChatStorageOptions {
26
+ /** API root, e.g. `https://host/api` — endpoints hang below it. */
27
+ baseUrl: string;
28
+ /** Extra headers (auth) for every call. */
29
+ headers?: Record<string, string> | (() => Record<string, string>);
30
+ /** @default 50 */
31
+ top?: number;
32
+ fetch?: typeof fetch;
33
+ }
34
+ /**
35
+ * REST adapter. Chat metas live at `{base}/chats`, transcripts at
36
+ * `{base}/chats/{id}/messages`, folders at `{base}/folders`; paging is
37
+ * `$top`/`$skip` with `$count=true`, ordering is server-side.
38
+ */
39
+ export declare function createRestChatStorage(options: RestChatStorageOptions): ChatStorage;
40
+ /** Totals over stored usage, for the footer. */
41
+ export interface ChatUsageTotals {
42
+ promptTokens: number;
43
+ completionTokens: number;
44
+ totalTokens: number;
45
+ cost: number;
46
+ requests: number;
47
+ }
48
+ export declare function usageTotals(messages: ChatMessage[]): ChatUsageTotals;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The streaming transport: an OpenAI-compatible `/chat/completions`
3
+ * endpoint, SSE deltas in, tokens out. Framework-free — both kits wrap it
4
+ * in their own reactivity.
5
+ */
6
+ import type { ChatMessage, ChatModel, ChatRole, ChatUsage } from "./types";
7
+ export interface StreamRequestMessage {
8
+ role: ChatRole;
9
+ content: string;
10
+ }
11
+ export interface StreamChatCompletionParams {
12
+ baseUrl: string;
13
+ apiKey?: string;
14
+ model: string;
15
+ messages: StreamRequestMessage[];
16
+ signal: AbortSignal;
17
+ temperature?: number;
18
+ maxTokens?: number;
19
+ onToken: (token: string) => void;
20
+ onReasoning?: (token: string) => void;
21
+ onUsage?: (usage: ChatUsage) => void;
22
+ fetch?: typeof fetch;
23
+ }
24
+ export type StreamResult = {
25
+ status: "done";
26
+ } | {
27
+ status: "aborted";
28
+ } | {
29
+ status: "error";
30
+ error: string;
31
+ };
32
+ export declare function streamChatCompletion(params: StreamChatCompletionParams): Promise<StreamResult>;
33
+ /**
34
+ * `GET {base}/models`, tolerant of the shapes in the wild. The result
35
+ * feeds the model picker; failures resolve to an empty list, never throw —
36
+ * a chat with a dead models endpoint is still a chat.
37
+ */
38
+ export declare function fetchChatModels(baseUrl: string, options?: {
39
+ apiKey?: string;
40
+ fetch?: typeof fetch;
41
+ }): Promise<ChatModel[]>;
42
+ /** The transcript as the wire wants it — finished turns only. */
43
+ export declare const toRequestMessages: (messages: ChatMessage[]) => StreamRequestMessage[];
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Chat domain types shared by both kits. The storage layer speaks in pages
3
+ * (OData-shaped) so a localStorage adapter and a REST adapter are the same
4
+ * contract — the component never learns which one it has.
5
+ */
6
+ import type { TrueColor } from "../theme/Theme";
7
+ export type ChatRole = "system" | "user" | "assistant";
8
+ /** A message's place in the conversation. */
9
+ export type ChatMessageStatus = "streaming" | "done" | "error";
10
+ /** Token accounting as the models report it. */
11
+ export interface ChatUsage {
12
+ prompt_tokens?: number;
13
+ completion_tokens?: number;
14
+ total_tokens?: number;
15
+ /** Only when the gateway prices the call. */
16
+ cost?: number;
17
+ }
18
+ export interface ChatMessage {
19
+ id: string;
20
+ chatId: string;
21
+ role: ChatRole;
22
+ content: string;
23
+ /** Chain-of-thought surfaced by reasoning models, kept separate. */
24
+ reasoning?: string;
25
+ /** ISO timestamp — storage's clock is the source of truth. */
26
+ createdAt: string;
27
+ status: ChatMessageStatus;
28
+ usage?: ChatUsage;
29
+ /** Which model answered, for mixed-model chats. */
30
+ model?: string;
31
+ /** Set when status is "error". */
32
+ error?: string;
33
+ }
34
+ /** The rail's row: everything about a chat except the transcript. */
35
+ export interface ChatMeta {
36
+ id: string;
37
+ title: string;
38
+ /** null/undefined is the Unfiled shelf. */
39
+ folderId?: string | null;
40
+ createdAt: string;
41
+ updatedAt: string;
42
+ model?: string;
43
+ /** First-line teaser for the rail. */
44
+ preview?: string;
45
+ /** All messages, known to storage — the in-memory window may hold fewer. */
46
+ messageTotal?: number;
47
+ }
48
+ /** A chat with its (windowed) transcript. */
49
+ export interface ChatRecord extends ChatMeta {
50
+ messages: ChatMessage[];
51
+ }
52
+ /** Chat folders are first-class: their own rows, their own CRUD. */
53
+ export interface ChatFolder {
54
+ id: string;
55
+ name: string;
56
+ /** @default "blue" */
57
+ tone?: TrueColor;
58
+ createdAt: string;
59
+ }
60
+ /** One page of results; `total` is the whole count, OData-style. */
61
+ export interface ChatPage<T> {
62
+ items: T[];
63
+ total: number;
64
+ }
65
+ export interface ChatListQuery {
66
+ /** A string scopes to that folder; null means Unfiled only. */
67
+ folderId?: string | null;
68
+ search?: string;
69
+ skip?: number;
70
+ top?: number;
71
+ }
72
+ export interface MessageListQuery {
73
+ skip?: number;
74
+ top?: number;
75
+ }
76
+ /**
77
+ * The persistence contract. `skip`/`top` paging is OData-flavoured
78
+ * throughout; REST implementations map it onto `$skip`/`$top`.
79
+ */
80
+ export interface ChatStorage {
81
+ listChats(query?: ChatListQuery): Promise<ChatPage<ChatMeta>>;
82
+ getChat(id: string): Promise<ChatRecord | null>;
83
+ createChat(init?: {
84
+ folderId?: string | null;
85
+ model?: string;
86
+ }): Promise<ChatRecord>;
87
+ updateChat(patch: {
88
+ id: string;
89
+ title?: string;
90
+ /** Passing the key moves the chat; null moves it to Unfiled. */
91
+ folderId?: string | null;
92
+ model?: string;
93
+ }): Promise<void>;
94
+ deleteChat(id: string): Promise<void>;
95
+ /** Oldest-first pages — "load earlier" asks for the page before the window. */
96
+ listMessages(chatId: string, query?: MessageListQuery): Promise<ChatPage<ChatMessage>>;
97
+ appendMessage(chatId: string, message: ChatMessage): Promise<void>;
98
+ /** Replace the whole transcript of one chat (streaming commit). */
99
+ replaceMessages(chatId: string, messages: ChatMessage[]): Promise<void>;
100
+ listFolders(): Promise<ChatFolder[]>;
101
+ /** Upsert: an `id` updates, its absence creates. */
102
+ saveFolder(folder: {
103
+ id?: string;
104
+ name: string;
105
+ tone?: TrueColor;
106
+ }): Promise<ChatFolder>;
107
+ deleteFolder(id: string): Promise<void>;
108
+ }
109
+ /** The component's observable life — the extensibility seam. */
110
+ export type ChatEvent = {
111
+ type: "chat-created";
112
+ chat: ChatMeta;
113
+ } | {
114
+ type: "chat-selected";
115
+ id: string;
116
+ } | {
117
+ type: "chat-deleted";
118
+ id: string;
119
+ } | {
120
+ type: "chat-moved";
121
+ id: string;
122
+ folderId: string | null;
123
+ } | {
124
+ type: "message-sent";
125
+ message: ChatMessage;
126
+ } | {
127
+ type: "message-received";
128
+ message: ChatMessage;
129
+ } | {
130
+ type: "stream-aborted";
131
+ } | {
132
+ type: "stream-error";
133
+ error: string;
134
+ } | {
135
+ type: "storage-error";
136
+ error: string;
137
+ };
138
+ /** A model row: `id` is what the endpoint takes, `label` what the picker shows. */
139
+ export interface ChatModel {
140
+ id: string;
141
+ label?: string;
142
+ contextWindow?: number;
143
+ }
@@ -0,0 +1,56 @@
1
+ import type { SurfaceVariant } from "../theme/Theme";
2
+ import type { ConnectionFlowNode, ConnectionFlowProgressType } from "./types";
3
+ /**
4
+ * The frame around the graph: an eyebrow, an icon, a title, a tag and the
5
+ * flow's own progress, sitting above a scrolling canvas.
6
+ *
7
+ * Everything the header *decides* lives here rather than in either renderer.
8
+ * The two kits draw the same block, and every divergence in this component so
9
+ * far has come from letting each of them work something out for itself.
10
+ */
11
+ export interface HeaderSurface {
12
+ translucent: boolean;
13
+ /** Hairline between the header and the graph. */
14
+ divider: string;
15
+ /** The tiny uppercase line above the title. */
16
+ eyebrow: string;
17
+ /** Subtitle, and the caption beside the progress bar. */
18
+ muted: string;
19
+ /** Fill behind the icon chip. */
20
+ chip: string;
21
+ }
22
+ export declare const getHeaderSurface: (variant: SurfaceVariant) => HeaderSurface;
23
+ /** What occupies the header's icon slot right now. */
24
+ export type HeaderGlyph = {
25
+ kind: "spinner";
26
+ value: number;
27
+ } | {
28
+ kind: "icon";
29
+ } | {
30
+ kind: "none";
31
+ };
32
+ /**
33
+ * A spinner takes the icon's place while the flow is running and gives it back
34
+ * at 100% — the same rule an item's glyph follows, so the two read as one
35
+ * idea rather than two similar ones.
36
+ */
37
+ export declare const headerGlyph: (hasIcon: boolean, progressType: ConnectionFlowProgressType, progress: number | undefined) => HeaderGlyph;
38
+ /**
39
+ * Whether the slot is held open. Reserved for a spinner even with no icon
40
+ * behind it, so the title does not step sideways the moment the flow finishes.
41
+ */
42
+ export declare const headerReservesGlyph: (hasIcon: boolean, progressType: ConnectionFlowProgressType) => boolean;
43
+ /**
44
+ * A node's completion: its own if it declares one, else the mean of whatever
45
+ * its items report. A card built from items has no `progress` of its own, and
46
+ * before this it simply did not count towards the flow's total.
47
+ */
48
+ export declare const nodeProgress: (node: ConnectionFlowNode) => number | undefined;
49
+ /**
50
+ * The flow's completion, 0–1.
51
+ *
52
+ * The mean of the nodes that report one, unless the caller states it outright
53
+ * — which it usually should: a pipeline knows its own progress better than the
54
+ * average of its cards does.
55
+ */
56
+ export declare const flowProgress: (nodes: ConnectionFlowNode[], override?: number) => number | undefined;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Canvas cannot mount an `<svg>`. A registry icon is markup, so to draw one
3
+ * into a 2D context its path data has to be lifted out and turned into a
4
+ * `Path2D`. The result is cached — building a `Path2D` per frame would be a
5
+ * parse per icon per frame.
6
+ */
7
+ /**
8
+ * Extracts every `d` attribute from SVG markup and merges them into one path.
9
+ *
10
+ * Returns `null` for markup with no paths — a circle-only or rect-only icon —
11
+ * rather than an empty `Path2D`, so the caller can fall back to drawing
12
+ * nothing instead of silently painting an invisible glyph.
13
+ */
14
+ export declare const pathFromSvgMarkup: (key: string, markup: string) => Path2D | null;
15
+ export declare const clearIconPathCache: () => void;
@@ -0,0 +1,6 @@
1
+ export * from "./types";
2
+ export * from "./measure";
3
+ export * from "./header";
4
+ export * from "./tones";
5
+ export * from "./router";
6
+ export * from "./layout";
@@ -0,0 +1,73 @@
1
+ import { type ConnectionFlowLayout, type ConnectionFlowLayoutOptions, type ConnectionFlowNode, type ConnectionState, type LaidOutNode } from "./types";
2
+ /**
3
+ * A column on the main track: one `step`/`branch` node, or a stack of
4
+ * consecutive `parallel` ones.
5
+ */
6
+ interface Column {
7
+ nodes: ConnectionFlowNode[];
8
+ parallel: boolean;
9
+ }
10
+ /**
11
+ * Groups consecutive `parallel` nodes into one column. The old implementation
12
+ * did this three separate times per render — once for the groups, once for the
13
+ * auto-skipped set and once for the bypass arcs — from the same input, so the
14
+ * three could disagree if any of the three copies were edited. It happens once
15
+ * here and the result is threaded through.
16
+ */
17
+ export declare const buildColumns: (nodes: ConnectionFlowNode[]) => Column[];
18
+ /**
19
+ * Which columns are bypassed.
20
+ *
21
+ * A column is skipped when it says so, or — under `autoSkip` — when it is
22
+ * untouched (neutral) but something after it has run. An explicit
23
+ * `skipped: false` always wins: a node that executed but happens to be neutral
24
+ * must not be arched over.
25
+ */
26
+ export declare const resolveSkipped: (columns: Column[], autoSkip: boolean) => Set<number>;
27
+ export interface LayoutInput {
28
+ nodes: ConnectionFlowNode[];
29
+ options?: Partial<ConnectionFlowLayoutOptions>;
30
+ /** Fallback state for edges that do not declare one. */
31
+ flowState?: ConnectionState;
32
+ /** Derive edge state and bypasses from tone alone. */
33
+ autoState?: boolean;
34
+ /**
35
+ * Nodes whose item list is fully expanded.
36
+ *
37
+ * Expanding changes a card's height, and so its ports, its silhouette and
38
+ * every route touching it — so it belongs to the layout rather than to the
39
+ * renderer that draws the button.
40
+ */
41
+ expanded?: ReadonlySet<string>;
42
+ animated?: boolean;
43
+ }
44
+ /**
45
+ * Turns a node list into absolute geometry.
46
+ *
47
+ * Deliberately pure: no measuring, no DOM, no framework. The previous
48
+ * implementation derived every edge from `getBoundingClientRect()` inside a
49
+ * `ResizeObserver`, which meant the arcs could only be computed *after* a
50
+ * paint, needed a second paint to appear, and were re-measured on every
51
+ * scroll. Geometry that can be computed should not be measured.
52
+ */
53
+ export declare const layoutConnectionFlow: (input: LayoutInput) => ConnectionFlowLayout;
54
+ /**
55
+ * Every node on the path from the first node to `targetId`, walking the edge
56
+ * list backwards. Drives the GitHub-Actions-style highlight: the ancestry of
57
+ * the node under the pointer stays lit and everything else dims.
58
+ */
59
+ export declare const tracePathTo: (layout: ConnectionFlowLayout, targetId: string) => {
60
+ nodes: Set<string>;
61
+ edges: Set<string>;
62
+ };
63
+ /** The node whose box contains the point, or `null`. Topmost wins. */
64
+ export declare const hitTestNode: (layout: ConnectionFlowLayout, x: number, y: number) => LaidOutNode | null;
65
+ /** Scale and offset that fit the whole graph into a viewport. */
66
+ export declare const fitToViewport: (layout: ConnectionFlowLayout, viewportWidth: number, viewportHeight: number, maxScale?: number) => {
67
+ scale: number;
68
+ offsetX: number;
69
+ offsetY: number;
70
+ };
71
+ /** True when the layout contains anything that needs to keep moving. */
72
+ export declare const layoutIsAnimated: (layout: ConnectionFlowLayout) => boolean;
73
+ export {};
@@ -0,0 +1,94 @@
1
+ import { type ConnectionFlowItemProgress, type ConnectionFlowLayoutOptions, type ConnectionFlowNode, type ConnectionFlowNodeItem, type NodeMetrics, type TrueColorLike } from "./types";
2
+ /** The node's own title/subtitle line, when it has one. */
3
+ export declare const measureHeader: (node: ConnectionFlowNode, metrics: NodeMetrics) => number;
4
+ /** What occupies an item's leading slot right now. */
5
+ export type ItemGlyph = {
6
+ kind: "spinner";
7
+ value: number;
8
+ } | {
9
+ kind: "icon";
10
+ name: string;
11
+ } | {
12
+ kind: "none";
13
+ };
14
+ /**
15
+ * The leading slot of an item.
16
+ *
17
+ * A spinner takes the icon's place rather than sitting beside it, and gives it
18
+ * back at 100% — so a row shows what is happening while it happens and what
19
+ * happened once it has. The slot is the same size either way, which is why the
20
+ * glyph metrics are pinned to the range where `CustomIcon` and
21
+ * `ProgressSpinner` render identically.
22
+ */
23
+ export declare const itemGlyph: (item: ConnectionFlowNodeItem, fallbackProgress: ConnectionFlowItemProgress) => ItemGlyph;
24
+ /**
25
+ * An item's tone: its own if set, else its status's, else the card's.
26
+ *
27
+ * Resolved here rather than in each renderer — the first version fell through
28
+ * to the node's tone unconditionally, so a `failed` row inside a `succeeded`
29
+ * card came out green.
30
+ */
31
+ export declare const itemTone: (item: ConnectionFlowNodeItem, fallback: TrueColorLike) => TrueColorLike;
32
+ /** Whether an item draws a full-width bar under its text. */
33
+ export declare const itemHasBar: (item: ConnectionFlowNodeItem, fallbackProgress: ConnectionFlowItemProgress) => boolean;
34
+ /**
35
+ * Whether the list reserves a leading column.
36
+ *
37
+ * Decided for the whole list, not per row: with it per row, a list where only
38
+ * some items carry a glyph had its titles stepping in and out, and a row whose
39
+ * spinner finished would shift sideways as the slot vanished.
40
+ */
41
+ export declare const itemsReserveGlyph: (items: ConnectionFlowNodeItem[], fallbackProgress: ConnectionFlowItemProgress) => boolean;
42
+ export declare const measureItem: (item: ConnectionFlowNodeItem, metrics: NodeMetrics, fallbackProgress: ConnectionFlowItemProgress, reserveGlyph: boolean) => number;
43
+ export interface VisibleItems {
44
+ items: ConnectionFlowNodeItem[];
45
+ /** Rows folded away behind the "show more" row. */
46
+ hidden: number;
47
+ }
48
+ /**
49
+ * The rows a card actually shows. Expanding changes the card's height, and so
50
+ * the ports, the silhouette and every route — which is why the expanded set is
51
+ * an input to the layout rather than state the renderer keeps to itself.
52
+ */
53
+ export declare const visibleItems: (node: ConnectionFlowNode, options: ConnectionFlowLayoutOptions, expanded?: ReadonlySet<string>) => VisibleItems;
54
+ export declare const measureItems: (node: ConnectionFlowNode, options: ConnectionFlowLayoutOptions, expanded?: ReadonlySet<string>) => number;
55
+ export declare const measureNodeBody: (node: ConnectionFlowNode, metrics: NodeMetrics) => number;
56
+ /**
57
+ * Height of a node box.
58
+ *
59
+ * A node that declares its own `height` gets exactly that: a caller-supplied
60
+ * template cannot be measured, so it says how much room it needs and scrolls
61
+ * inside it.
62
+ */
63
+ export declare const measureNode: (node: ConnectionFlowNode, options: ConnectionFlowLayoutOptions, expanded?: ReadonlySet<string>) => number;
64
+ /**
65
+ * Whether a card's body scrolls: explicit if stated, otherwise whenever the
66
+ * card has been capped below what its contents need.
67
+ */
68
+ export declare const nodeScrolls: (node: ConnectionFlowNode, options: ConnectionFlowLayoutOptions, expanded?: ReadonlySet<string>) => boolean;
69
+ /** Total vertical space a node needs, including its child sub-tree. */
70
+ export declare const measureBranch: (node: ConnectionFlowNode, options: ConnectionFlowLayoutOptions, expanded?: ReadonlySet<string>) => number;
71
+ /**
72
+ * When a dot leaves, how long it is in flight, and how long until the next
73
+ * one leaves the same source.
74
+ *
75
+ * Every dot in the graph moves at the same speed, so its flight time comes
76
+ * from the route's own length. Before this every edge used a fixed 2.4s
77
+ * whatever its length, which made a short track hop crawl while a long bypass
78
+ * arc raced — the two read as unrelated animations rather than one flow.
79
+ */
80
+ export interface DotTiming {
81
+ /** Seconds for one full cycle of this edge's dot. */
82
+ cycle: number;
83
+ /** Where in that cycle the dot arrives, 0–1. */
84
+ arrival: number;
85
+ /** Seconds of phase offset, negative so the cycle is already under way. */
86
+ begin: number;
87
+ }
88
+ export declare const dotTiming: (length: number,
89
+ /** Position in its source's round-robin, how many share it, and its span. */
90
+ emitIndex: number, emitCount: number, emitSpan: number,
91
+ /** Px per second. */
92
+ speed: number,
93
+ /** Seconds between one dot leaving a source and the next. */
94
+ interval: number) => DotTiming;
@@ -0,0 +1,36 @@
1
+ import { type ColorScheme } from "./tones";
2
+ import type { ConnectionFlowLayout } from "./types";
3
+ export interface PaintOptions {
4
+ scheme: ColorScheme;
5
+ /** Corner radius of a node box, in px. */
6
+ radius: number;
7
+ /** Font sizes, from the node metrics for the current control size. */
8
+ titleSize: number;
9
+ bodySize: number;
10
+ padding: number;
11
+ /** Milliseconds since the animation started — drives dot travel and pulse. */
12
+ time: number;
13
+ /** Target px between travelling dots. */
14
+ dotSpacing: number;
15
+ /** Node ids to keep lit. Empty means "no highlight, draw everything lit". */
16
+ highlightNodes: Set<string>;
17
+ /** Edge ids to keep lit. */
18
+ highlightEdges: Set<string>;
19
+ hoveredId: string | null;
20
+ selectedId: string | null;
21
+ /** Draws each node's progress indicator. */
22
+ showProgress: boolean;
23
+ /** Device pixel ratio the context was scaled by. */
24
+ dpr: number;
25
+ /** Resolved icon glyphs, keyed by registry name. */
26
+ icons?: Map<string, Path2D>;
27
+ fontFamily: string;
28
+ }
29
+ /**
30
+ * Paints one frame. The context is expected to be already scaled for the
31
+ * device pixel ratio and translated/scaled for pan and zoom — the painter
32
+ * works purely in layout coordinates.
33
+ */
34
+ export declare const paintConnectionFlow: (ctx: CanvasRenderingContext2D, layout: ConnectionFlowLayout, options: PaintOptions) => void;
35
+ /** True when the layout contains anything that needs a new frame. */
36
+ export declare const layoutIsAnimated: (layout: ConnectionFlowLayout) => boolean;
@@ -0,0 +1,131 @@
1
+ import type { ConnectionFlowEdgeStyle } from "./types";
2
+ /**
3
+ * Every edge in the graph is routed by this module and nothing else.
4
+ *
5
+ * The old code grew a bespoke point-list per edge kind — a mid-X elbow for the
6
+ * main track, a hard-coded L for children, a four-point lift for bypasses — so
7
+ * `edgeStyle: "curved"` curved the main track and left the children as square
8
+ * elbows, and a bypass ignored the style entirely. Anything with its own
9
+ * routing code is an edge style waiting to be forgotten.
10
+ *
11
+ * The model is two ports and a shape. A port is a point on a node's border
12
+ * plus the direction a line must *leave* it in; the router turns any pair of
13
+ * ports into a path in the requested style. Adding a style means adding one
14
+ * branch here, and every edge in the graph gets it at once.
15
+ */
16
+ export type PortSide = "top" | "right" | "bottom" | "left";
17
+ export interface Port {
18
+ x: number;
19
+ y: number;
20
+ side: PortSide;
21
+ /** Outward unit normal — the direction a line leaves this port in. */
22
+ dx: number;
23
+ dy: number;
24
+ }
25
+ export interface Box {
26
+ x: number;
27
+ y: number;
28
+ width: number;
29
+ height: number;
30
+ }
31
+ /** The outward direction of each border, as a unit vector. */
32
+ export declare const PORT_NORMALS: Record<PortSide, {
33
+ dx: number;
34
+ dy: number;
35
+ }>;
36
+ /**
37
+ * A point on one side of a box. `t` slides along that side from 0 to 1, which
38
+ * is what lets a fan-out give each lane its own port instead of stacking every
39
+ * line on the same pixel.
40
+ */
41
+ export declare const port: (box: Box, side: PortSide, t?: number) => Port;
42
+ /** A port at an absolute offset along a side rather than a fraction of it. */
43
+ export declare const portAt: (box: Box, side: PortSide, offset: number) => Port;
44
+ /**
45
+ * Picks the pair of sides that gives the shortest, least-crossing route.
46
+ *
47
+ * Purely geometric: whichever axis the two boxes are actually separated on
48
+ * wins, and the ports face each other across that gap. This is what makes a
49
+ * child edge leave its parent's *bottom* and a track edge leave its *right*
50
+ * without either being special-cased.
51
+ */
52
+ export declare const selectSides: (source: Box, target: Box) => {
53
+ from: PortSide;
54
+ to: PortSide;
55
+ };
56
+ export interface RouteOptions {
57
+ style: ConnectionFlowEdgeStyle;
58
+ /** How far a line runs straight out of a port before it may turn. */
59
+ stub?: number;
60
+ /** Corner radius on an orthogonal path. */
61
+ radius?: number;
62
+ /**
63
+ * Forces the turn onto a specific coordinate — used by a bypass, which must
64
+ * clear the cards it arches over rather than turning halfway.
65
+ */
66
+ via?: {
67
+ x?: number;
68
+ y?: number;
69
+ };
70
+ /**
71
+ * Stops the line this far short of each port, along that port's own normal.
72
+ *
73
+ * A terminal ring is drawn centred on the port, so an untrimmed line runs
74
+ * under the ring and out the far side. Trimming here rather than in the
75
+ * renderer keeps the travelling dots honest: they follow this same path, so
76
+ * they stop where the line stops instead of sliding into the card.
77
+ */
78
+ trim?: number;
79
+ }
80
+ export interface Route {
81
+ /** Waypoints, for label placement and measurement. */
82
+ points: {
83
+ x: number;
84
+ y: number;
85
+ }[];
86
+ /** The SVG path. Also what the travelling dots follow, so the dots and the
87
+ * line can never disagree about the route. */
88
+ d: string;
89
+ }
90
+ export declare const routePorts: (fromPort: Port, toPort: Port, options: RouteOptions) => Route;
91
+ /** Total length of a waypoint list. */
92
+ export declare const routeLength: (points: {
93
+ x: number;
94
+ y: number;
95
+ }[]) => number;
96
+ /** A port the node's outline detours around. */
97
+ export interface OutlineBulge {
98
+ side: PortSide;
99
+ /** Position along that side: an x for top/bottom, a y for left/right. */
100
+ at: number;
101
+ radius: number;
102
+ }
103
+ /**
104
+ * The node's outline: a rounded rectangle that detours around each of its
105
+ * ports.
106
+ *
107
+ * The terminal is not a marker drawn on top of the card — it *is* the card,
108
+ * bulging. So there is no chord across the bulge and its interior takes the
109
+ * same fill as the rest of the node, which only works if the whole silhouette
110
+ * is one path. A CSS border cannot do this, which is why the card is painted
111
+ * here and the DOM element above it carries only content.
112
+ *
113
+ * Traversed clockwise, so every arc — corners and bulges alike — is a
114
+ * sweep-1 turn.
115
+ */
116
+ export declare const nodeOutline: (box: Box, cornerRadius: number, bulges: OutlineBulge[]) => string;
117
+ /**
118
+ * Where a caption sits on a route: the middle of its longest straight run.
119
+ *
120
+ * Halfway *along the route* lands wherever the arithmetic puts it — on a
121
+ * corner, or hard against a card — because a route's midpoint has nothing to
122
+ * do with where there is room to write. The longest run is the one stretch
123
+ * guaranteed to have some.
124
+ */
125
+ export declare const labelAnchor: (points: {
126
+ x: number;
127
+ y: number;
128
+ }[]) => {
129
+ x: number;
130
+ y: number;
131
+ };