@chai-ui/core 0.6.1 → 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 (42) hide show
  1. package/README.md +3 -2
  2. package/dist/composer-view.d.ts +93 -0
  3. package/dist/composer-view.d.ts.map +1 -0
  4. package/dist/composer-view.js +142 -0
  5. package/dist/composer-view.js.map +1 -0
  6. package/dist/edit-card.d.ts +53 -0
  7. package/dist/edit-card.d.ts.map +1 -0
  8. package/dist/edit-card.js +119 -0
  9. package/dist/edit-card.js.map +1 -0
  10. package/dist/index.d.ts +4 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +4 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/media-actions.d.ts +19 -0
  15. package/dist/media-actions.d.ts.map +1 -0
  16. package/dist/media-actions.js +57 -0
  17. package/dist/media-actions.js.map +1 -0
  18. package/dist/media-analyzer.d.ts +47 -1
  19. package/dist/media-analyzer.d.ts.map +1 -1
  20. package/dist/media-analyzer.js +91 -0
  21. package/dist/media-analyzer.js.map +1 -1
  22. package/dist/region-edit.d.ts +2 -0
  23. package/dist/region-edit.d.ts.map +1 -1
  24. package/dist/region-edit.js +6 -0
  25. package/dist/region-edit.js.map +1 -1
  26. package/dist/result-format.d.ts +11 -0
  27. package/dist/result-format.d.ts.map +1 -0
  28. package/dist/result-format.js +30 -0
  29. package/dist/result-format.js.map +1 -0
  30. package/dist/unique-id.d.ts +3 -0
  31. package/dist/unique-id.d.ts.map +1 -0
  32. package/dist/unique-id.js +7 -0
  33. package/dist/unique-id.js.map +1 -0
  34. package/package.json +2 -1
  35. package/src/composer-view.ts +222 -0
  36. package/src/edit-card.ts +138 -0
  37. package/src/index.ts +4 -0
  38. package/src/media-actions.ts +55 -0
  39. package/src/media-analyzer.ts +112 -1
  40. package/src/region-edit.ts +8 -0
  41. package/src/result-format.ts +34 -0
  42. package/src/unique-id.ts +6 -0
@@ -2,7 +2,7 @@ import { type GenerationEngine } from "./engine.js";
2
2
  import { type MediaAnalysisPromptLength } from "./media-analysis-prompts.js";
3
3
  import { type ModelRoutingInput, type ModelRoutingResult } from "./model-routing.js";
4
4
  import { type Reasoning } from "./reasoning.js";
5
- import type { DroppedMedia, ModelOption } from "./types.js";
5
+ import type { DroppedMedia, MediaKind, ModelOption } from "./types.js";
6
6
  export interface MediaAnalyzerAttachment extends DroppedMedia {
7
7
  id: string;
8
8
  }
@@ -52,4 +52,50 @@ export declare function createMediaAnalyzerStore(getOptions: () => MediaAnalyzer
52
52
  reset: () => void;
53
53
  };
54
54
  export type MediaAnalyzerStore = ReturnType<typeof createMediaAnalyzerStore>;
55
+ export declare const MEDIA_KIND_LABEL: Record<MediaKind, string>;
56
+ /** Clarifies what "Terse"/"Concise"/"Detailed" mean in the "Prompt length" menu's rows. UI copy, not sent to any model. */
57
+ export declare const PROMPT_LENGTH_HINT: Record<MediaAnalysisPromptLength, string>;
58
+ /**
59
+ * How many attachments of each kind an analysis can hold at once. Image
60
+ * defaults to 5 (a sequence/series reads as one analysis); video and audio
61
+ * default to 1. Only one *kind* is ever active per analysis — these caps only
62
+ * bound how many of that one kind can pile up before the drop zone stops
63
+ * accepting more. `text` is output, never dropped: present only so this
64
+ * stays a total map.
65
+ */
66
+ export declare const DEFAULT_MAX_ATTACHMENTS_BY_KIND: Record<MediaKind, number>;
67
+ /**
68
+ * Applies one newly-read file to the current attachment list. Only one media
69
+ * *kind* exists per analysis: a different kind replaces the whole list,
70
+ * never merges. Video and audio are single-slot (a same-kind drop replaces
71
+ * it); image fills up to `max`, then silently stops accepting more (the drop
72
+ * zone's "maximum added" look explains why).
73
+ */
74
+ export declare function nextMediaAnalyzerAttachments(current: MediaAnalyzerAttachment[], incoming: DroppedMedia, maxByKind?: Record<MediaKind, number>): MediaAnalyzerAttachment[];
75
+ /** True once a same-kind drop would be rejected: only ever for image, since video and audio replace. */
76
+ export declare function isMediaAnalyzerAtCap(current: MediaAnalyzerAttachment[], maxByKind?: Record<MediaKind, number>): boolean;
77
+ /**
78
+ * Reads image, video and audio files as data URLs, all of them before
79
+ * returning, so a caller applies them in drop order in one go (applying
80
+ * each as its reader finishes would stack them on a stale list).
81
+ * `unsupported` names the files of another type, or that couldn't be read.
82
+ */
83
+ export declare function readMediaFiles(files: Iterable<File>): Promise<{
84
+ media: DroppedMedia[];
85
+ unsupported: string[];
86
+ }>;
87
+ /** "Replaced 2 images with clip.wav.", or `null` when nothing was replaced. */
88
+ export declare function replacedNote(before: MediaAnalyzerAttachment[], after: MediaAnalyzerAttachment[]): string | null;
89
+ /**
90
+ * The "Select model" menu's sections: once a kind is attached, only its
91
+ * models (falling back to `models`); before that, all three kinds, each
92
+ * under its own header.
93
+ */
94
+ export declare function mediaAnalyzerModelSections(kind: MediaKind | undefined, modelsByKind: Partial<Record<MediaKind, ModelOption[]>>, models: ModelOption[]): {
95
+ label: string;
96
+ options: {
97
+ id: string;
98
+ label: string;
99
+ }[];
100
+ }[];
55
101
  //# sourceMappingURL=media-analyzer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"media-analyzer.d.ts","sourceRoot":"","sources":["../src/media-analyzer.ts"],"names":[],"mappings":"AASA,OAAO,EAA4D,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC9G,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAc,KAAK,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACjG,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,WAAW,uBAAwB,SAAQ,YAAY;IAC3D,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,uBAAuB,EAAE,CAAC;IACvC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,0FAA0F;IAC1F,eAAe,EAAE,OAAO,CAAC;IACzB,wDAAwD;IACxD,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,sIAAsI;IACtI,YAAY,EAAE,yBAAyB,GAAG,IAAI,CAAC;CAChD;AAED,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,oHAAoH;IACpH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,4HAA4H;IAC5H,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,oEAAoE;IACpE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,MAAM,CAAC;IACrD,iJAAiJ;IACjJ,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,kBAAkB,EAAE;QAAE,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC,KAAK,IAAI,CAAC;CAC3F;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAID;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,oBAAoB,EACtC,WAAW,GAAE,MAAM,SAAS,GAAG,SAA2B;;wBAyGpC,MAAM,IAAI;sBA3FP,0BAA0B;;;EAmGpD;AAED,MAAM,MAAM,kBAAkB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
1
+ {"version":3,"file":"media-analyzer.d.ts","sourceRoot":"","sources":["../src/media-analyzer.ts"],"names":[],"mappings":"AAUA,OAAO,EAA4D,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC9G,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAc,KAAK,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACjG,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvE,MAAM,WAAW,uBAAwB,SAAQ,YAAY;IAC3D,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,uBAAuB,EAAE,CAAC;IACvC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,0FAA0F;IAC1F,eAAe,EAAE,OAAO,CAAC;IACzB,wDAAwD;IACxD,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,sIAAsI;IACtI,YAAY,EAAE,yBAAyB,GAAG,IAAI,CAAC;CAChD;AAED,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,oHAAoH;IACpH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,4HAA4H;IAC5H,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,oEAAoE;IACpE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,MAAM,CAAC;IACrD,iJAAiJ;IACjJ,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,kBAAkB,EAAE;QAAE,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC,KAAK,IAAI,CAAC;CAC3F;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAID;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,oBAAoB,EACtC,WAAW,GAAE,MAAM,SAAS,GAAG,SAA2B;;wBAyGpC,MAAM,IAAI;sBA3FP,0BAA0B;;;EAmGpD;AAED,MAAM,MAAM,kBAAkB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAM7E,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAoE,CAAC;AAE5H,2HAA2H;AAC3H,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,yBAAyB,EAAE,MAAM,CAIxE,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAA6C,CAAC;AAEpH;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,uBAAuB,EAAE,EAClC,QAAQ,EAAE,YAAY,EACtB,SAAS,GAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAmC,GACrE,uBAAuB,EAAE,CAS3B;AAED,wGAAwG;AACxG,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,uBAAuB,EAAE,EAClC,SAAS,GAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAmC,GACrE,OAAO,CAGT;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAqBrH;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,MAAM,EAAE,uBAAuB,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,GAAG,MAAM,GAAG,IAAI,CAQ/G;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,SAAS,GAAG,SAAS,EAC3B,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC,EACvD,MAAM,EAAE,WAAW,EAAE,GACpB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,EAAE,CAK/D"}
@@ -6,6 +6,7 @@
6
6
  * (`getState` + `subscribe`) that `useMediaAnalyzer` (React) and the Vue
7
7
  * composable wrap.
8
8
  */
9
+ import { uniqueId } from "./unique-id.js";
9
10
  import { warnNoReasoningOnce } from "./composer.js";
10
11
  import { createMockEngine, isAbortError, normalizeGenerationError } from "./engine.js";
11
12
  import { DEFAULT_MEDIA_ANALYSIS_PROMPT_LENGTH, MEDIA_ANALYSIS_PROMPTS, } from "./media-analysis-prompts.js";
@@ -121,4 +122,94 @@ export function createMediaAnalyzerStore(getOptions, getProvided = () => undefin
121
122
  reset,
122
123
  };
123
124
  }
125
+ // --- Attachments and menus: what the MediaAnalyzer component shows, the same in every framework binding.
126
+ const ACCEPTED_KINDS = ["image", "video", "audio"];
127
+ export const MEDIA_KIND_LABEL = { image: "Image", video: "Video", audio: "Audio", text: "Text" };
128
+ /** Clarifies what "Terse"/"Concise"/"Detailed" mean in the "Prompt length" menu's rows. UI copy, not sent to any model. */
129
+ export const PROMPT_LENGTH_HINT = {
130
+ terse: "short",
131
+ concise: "moderate",
132
+ detailed: "long",
133
+ };
134
+ /**
135
+ * How many attachments of each kind an analysis can hold at once. Image
136
+ * defaults to 5 (a sequence/series reads as one analysis); video and audio
137
+ * default to 1. Only one *kind* is ever active per analysis — these caps only
138
+ * bound how many of that one kind can pile up before the drop zone stops
139
+ * accepting more. `text` is output, never dropped: present only so this
140
+ * stays a total map.
141
+ */
142
+ export const DEFAULT_MAX_ATTACHMENTS_BY_KIND = { image: 5, video: 1, audio: 1, text: 0 };
143
+ /**
144
+ * Applies one newly-read file to the current attachment list. Only one media
145
+ * *kind* exists per analysis: a different kind replaces the whole list,
146
+ * never merges. Video and audio are single-slot (a same-kind drop replaces
147
+ * it); image fills up to `max`, then silently stops accepting more (the drop
148
+ * zone's "maximum added" look explains why).
149
+ */
150
+ export function nextMediaAnalyzerAttachments(current, incoming, maxByKind = DEFAULT_MAX_ATTACHMENTS_BY_KIND) {
151
+ const existingKind = current[0]?.kind;
152
+ const withId = { ...incoming, id: uniqueId() };
153
+ if (!existingKind || existingKind !== incoming.kind)
154
+ return [withId];
155
+ if (incoming.kind === "image") {
156
+ if (current.length >= (maxByKind.image ?? DEFAULT_MAX_ATTACHMENTS_BY_KIND.image))
157
+ return current;
158
+ return [...current, withId];
159
+ }
160
+ return [withId];
161
+ }
162
+ /** True once a same-kind drop would be rejected: only ever for image, since video and audio replace. */
163
+ export function isMediaAnalyzerAtCap(current, maxByKind = DEFAULT_MAX_ATTACHMENTS_BY_KIND) {
164
+ if (current[0]?.kind !== "image")
165
+ return false;
166
+ return current.length >= (maxByKind.image ?? DEFAULT_MAX_ATTACHMENTS_BY_KIND.image);
167
+ }
168
+ /**
169
+ * Reads image, video and audio files as data URLs, all of them before
170
+ * returning, so a caller applies them in drop order in one go (applying
171
+ * each as its reader finishes would stack them on a stale list).
172
+ * `unsupported` names the files of another type, or that couldn't be read.
173
+ */
174
+ export async function readMediaFiles(files) {
175
+ const unsupported = [];
176
+ const read = await Promise.all([...files].map((file) => {
177
+ const kind = ACCEPTED_KINDS.find((k) => k === file.type.split("/")[0]);
178
+ if (!kind) {
179
+ unsupported.push(file.name);
180
+ return null;
181
+ }
182
+ return new Promise((resolve) => {
183
+ const reader = new FileReader();
184
+ reader.onload = () => resolve({ src: String(reader.result), kind, name: file.name, size: file.size });
185
+ reader.onerror = () => {
186
+ unsupported.push(file.name);
187
+ resolve(null);
188
+ };
189
+ reader.readAsDataURL(file);
190
+ });
191
+ }));
192
+ return { media: read.filter((m) => m !== null), unsupported };
193
+ }
194
+ /** "Replaced 2 images with clip.wav.", or `null` when nothing was replaced. */
195
+ export function replacedNote(before, after) {
196
+ const removed = before.filter((a) => !after.some((n) => n.id === a.id));
197
+ const added = after.filter((n) => !before.some((a) => a.id === n.id));
198
+ if (removed.length === 0 || added.length === 0)
199
+ return null;
200
+ const name = (a) => a.name ?? MEDIA_KIND_LABEL[a.kind].toLowerCase();
201
+ const describe = (list) => list.length === 1 ? name(list[0]) : `${list.length} ${MEDIA_KIND_LABEL[list[0].kind].toLowerCase()}s`;
202
+ return `Replaced ${describe(removed)} with ${describe(added)}.`;
203
+ }
204
+ /**
205
+ * The "Select model" menu's sections: once a kind is attached, only its
206
+ * models (falling back to `models`); before that, all three kinds, each
207
+ * under its own header.
208
+ */
209
+ export function mediaAnalyzerModelSections(kind, modelsByKind, models) {
210
+ const options = (list = []) => list.map((m) => ({ id: m.id, label: m.label }));
211
+ return kind
212
+ ? [{ label: MEDIA_KIND_LABEL[kind], options: options(modelsByKind[kind] ?? models) }]
213
+ : ["image", "video", "audio"].map((k) => ({ label: MEDIA_KIND_LABEL[k], options: options(modelsByKind[k]) }));
214
+ }
124
215
  //# sourceMappingURL=media-analyzer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"media-analyzer.js","sourceRoot":"","sources":["../src/media-analyzer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"media-analyzer.js","sourceRoot":"","sources":["../src/media-analyzer.ts"],"names":[],"mappings":"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"}
@@ -47,4 +47,6 @@ export declare function buildRegionEditPrompt({ prompt, regions, format, }: {
47
47
  regions: EditRegion[];
48
48
  format?: RegionFormat;
49
49
  }): string;
50
+ /** The color token for a region number. Numbers past the last color start over at the first. */
51
+ export declare function regionColor(number: number): string;
50
52
  //# sourceMappingURL=region-edit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"region-edit.d.ts","sourceRoot":"","sources":["../src/region-edit.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE5D,iHAAiH;AACjH,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,gEAAgE;AAChE,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,kHAAkH;IAClH,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,SAAS,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,kFAAkF;AAClF,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,EAS5C,CAAC;AAmBF;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,MAAM,EACN,OAAO,EACP,MAAe,GAChB,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,GAAG,MAAM,CA8BT"}
1
+ {"version":3,"file":"region-edit.d.ts","sourceRoot":"","sources":["../src/region-edit.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE5D,iHAAiH;AACjH,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,gEAAgE;AAChE,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,kHAAkH;IAClH,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,SAAS,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,kFAAkF;AAClF,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,EAS5C,CAAC;AAmBF;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,MAAM,EACN,OAAO,EACP,MAAe,GAChB,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,GAAG,MAAM,CA8BT;AAKD,gGAAgG;AAChG,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD"}
@@ -75,4 +75,10 @@ export function buildRegionEditPrompt({ prompt, regions, format = "text", }) {
75
75
  .filter(Boolean)
76
76
  .join(" ");
77
77
  }
78
+ /** How many region colors the tokens define (`--chai-color-semantic-region-1` to `-6`). */
79
+ const REGION_COLOR_COUNT = 6;
80
+ /** The color token for a region number. Numbers past the last color start over at the first. */
81
+ export function regionColor(number) {
82
+ return `var(--chai-color-semantic-region-${((Math.max(1, number) - 1) % REGION_COLOR_COUNT) + 1})`;
83
+ }
78
84
  //# sourceMappingURL=region-edit.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"region-edit.js","sourceRoot":"","sources":["../src/region-edit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"region-edit.js","sourceRoot":"","sources":["../src/region-edit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /** How `ResultCard` shows a result's details, the same in every framework binding. */
2
+ import { type Result } from "./run.js";
3
+ import type { ModelOption } from "./types.js";
4
+ export declare function formatDuration(ms: number | undefined): string | undefined;
5
+ export declare function formatCost(usd: number | undefined): string | undefined;
6
+ export declare function formatTokens(total: number | undefined): string | undefined;
7
+ /** A real, exactly-reduced ratio (e.g. 1024×768 → "4:3", 1920×1080 → "16:9") from the media's own measured dimensions — not a guess at the nearest "named" ratio, so an unusual crop just shows its own honest (if less familiar) reduced fraction instead of a misleading rounded one. */
8
+ export declare function formatAspectRatio(width: number, height: number): string | undefined;
9
+ /** The model's label from `models`, falling back to its raw id; "Choosing model…" while auto-select is still picking. */
10
+ export declare function resultModelLabel(result: Result, models?: ModelOption[]): string;
11
+ //# sourceMappingURL=result-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result-format.d.ts","sourceRoot":"","sources":["../src/result-format.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,OAAO,EAAoB,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAEzE;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAEtE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAE1E;AAMD,2RAA2R;AAC3R,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMnF;AAED,yHAAyH;AACzH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,GAAG,MAAM,CAG/E"}
@@ -0,0 +1,30 @@
1
+ /** How `ResultCard` shows a result's details, the same in every framework binding. */
2
+ import { ROUTING_MODEL_ID } from "./run.js";
3
+ export function formatDuration(ms) {
4
+ return ms == null ? undefined : `${(ms / 1000).toFixed(2)}s`;
5
+ }
6
+ export function formatCost(usd) {
7
+ return usd == null ? undefined : `$${usd.toFixed(2)}`;
8
+ }
9
+ export function formatTokens(total) {
10
+ return total == null ? undefined : `${total.toLocaleString()} tokens`;
11
+ }
12
+ function gcd(a, b) {
13
+ return b === 0 ? a : gcd(b, a % b);
14
+ }
15
+ /** A real, exactly-reduced ratio (e.g. 1024×768 → "4:3", 1920×1080 → "16:9") from the media's own measured dimensions — not a guess at the nearest "named" ratio, so an unusual crop just shows its own honest (if less familiar) reduced fraction instead of a misleading rounded one. */
16
+ export function formatAspectRatio(width, height) {
17
+ if (!width || !height)
18
+ return undefined;
19
+ const w = Math.round(width);
20
+ const h = Math.round(height);
21
+ const divisor = gcd(w, h);
22
+ return `${w / divisor}:${h / divisor}`;
23
+ }
24
+ /** The model's label from `models`, falling back to its raw id; "Choosing model…" while auto-select is still picking. */
25
+ export function resultModelLabel(result, models) {
26
+ if (result.modelId === ROUTING_MODEL_ID)
27
+ return "Choosing model…";
28
+ return models?.find((m) => m.id === result.modelId)?.label ?? result.modelId;
29
+ }
30
+ //# sourceMappingURL=result-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result-format.js","sourceRoot":"","sources":["../src/result-format.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,OAAO,EAAE,gBAAgB,EAAe,MAAM,UAAU,CAAC;AAGzD,MAAM,UAAU,cAAc,CAAC,EAAsB;IACnD,OAAO,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAuB;IAChD,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAyB;IACpD,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,cAAc,EAAE,SAAS,CAAC;AACxE,CAAC;AAED,SAAS,GAAG,CAAC,CAAS,EAAE,CAAS;IAC/B,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,2RAA2R;AAC3R,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,MAAc;IAC7D,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAM,OAAO,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1B,OAAO,GAAG,CAAC,GAAG,OAAO,IAAI,CAAC,GAAG,OAAO,EAAE,CAAC;AACzC,CAAC;AAED,yHAAyH;AACzH,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,MAAsB;IACrE,IAAI,MAAM,CAAC,OAAO,KAAK,gBAAgB;QAAE,OAAO,iBAAiB,CAAC;IAClE,OAAO,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,IAAI,MAAM,CAAC,OAAO,CAAC;AAC/E,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** A unique id for an attachment or region. Internal: not exported from the package. */
2
+ export declare function uniqueId(): string;
3
+ //# sourceMappingURL=unique-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unique-id.d.ts","sourceRoot":"","sources":["../src/unique-id.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,wBAAgB,QAAQ,IAAI,MAAM,CAIjC"}
@@ -0,0 +1,7 @@
1
+ /** A unique id for an attachment or region. Internal: not exported from the package. */
2
+ export function uniqueId() {
3
+ return typeof crypto !== "undefined" && "randomUUID" in crypto
4
+ ? crypto.randomUUID()
5
+ : `id-${Date.now()}-${Math.random().toString(36).slice(2)}`;
6
+ }
7
+ //# sourceMappingURL=unique-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unique-id.js","sourceRoot":"","sources":["../src/unique-id.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,MAAM,UAAU,QAAQ;IACtB,OAAO,OAAO,MAAM,KAAK,WAAW,IAAI,YAAY,IAAI,MAAM;QAC5D,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE;QACrB,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAChE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chai-ui/core",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "CHAI UI headless core — the Request/Run/Result data model and pluggable generation engines (Fal.ai, OpenRouter, mock). No framework, no rendering.",
5
5
  "license": "MIT",
6
6
  "author": "kazarazat",
@@ -44,6 +44,7 @@
44
44
  ],
45
45
  "devDependencies": {
46
46
  "@vitest/coverage-v8": "3.2.7",
47
+ "jsdom": "^25.0.1",
47
48
  "rimraf": "^6.0.1",
48
49
  "typescript": "^5.6.3",
49
50
  "vitest": "^3.2.7"
@@ -0,0 +1,222 @@
1
+ /**
2
+ * What the Composer component shows and submits, worked out from its props:
3
+ * the same in every framework binding. Pure; nothing here renders.
4
+ */
5
+ import type { ComposerAttachment, ComposerSelection, ComposerSubmitPayload, ComposerUseCase } from "./composer.js";
6
+ import { uniqueId } from "./unique-id.js";
7
+ import { TEXT_USE_CASE } from "./composer.js";
8
+ import { readMediaFiles } from "./media-analyzer.js";
9
+ import type { EditRegion } from "./region-edit.js";
10
+ import { deriveGenerationUseCase } from "./run.js";
11
+ import { suggestedModels } from "./suggested-models.js";
12
+ import type { MediaKind, ModelOption, ParameterOption } from "./types.js";
13
+
14
+ export type ComposerAttachMenuAction = "add-media" | "create-image" | "create-video" | "edit-media";
15
+
16
+ /** The `+` menu, in order. "Add media" is the only item with a divider after it. */
17
+ export const COMPOSER_ATTACH_MENU_ITEMS: { action: ComposerAttachMenuAction; label: string; divider?: boolean }[] = [
18
+ { action: "add-media", label: "Add media", divider: true },
19
+ { action: "create-image", label: "Create image" },
20
+ { action: "create-video", label: "Create video" },
21
+ { action: "edit-media", label: "Edit image" },
22
+ ];
23
+
24
+ /**
25
+ * Past this length a rewritten prompt appears at once: a long reveal reads
26
+ * as sluggish, and a long prompt is when a person wants the result now.
27
+ */
28
+ export const MAX_ANIMATE_ENHANCE_LENGTH = 260;
29
+
30
+ /** How long the Enhance reveal takes: time-driven, between 300ms and 900ms. */
31
+ export function enhanceRevealDurationMs(charCount: number): number {
32
+ return Math.min(900, Math.max(300, charCount * 6));
33
+ }
34
+
35
+ /** The Composer props `composerView` reads. Callbacks only matter by being there. */
36
+ export interface ComposerViewInput {
37
+ value: string;
38
+ placeholder?: string;
39
+ attachments?: ComposerAttachment[];
40
+ useCase?: ComposerUseCase | null;
41
+ defaultUseCase?: ComposerUseCase;
42
+ multiSelectUseCases?: boolean;
43
+ useCases?: ComposerUseCase[];
44
+ modelsByKind?: Partial<Record<MediaKind, ModelOption[]>>;
45
+ multiSelectModels?: boolean;
46
+ modelIds?: string[];
47
+ models?: ModelOption[];
48
+ modelId?: string | null;
49
+ onModelChange?: unknown;
50
+ onModelIdsChange?: unknown;
51
+ autoSelectModel?: boolean;
52
+ aspectRatios?: ParameterOption<string>[];
53
+ aspectRatio?: string | null;
54
+ submitError?: string | null;
55
+ submitDisabled?: boolean;
56
+ submitting?: boolean;
57
+ onAbort?: unknown;
58
+ regions?: EditRegion[];
59
+ disabled?: boolean;
60
+ }
61
+
62
+ export function composerView(props: ComposerViewInput) {
63
+ const {
64
+ value,
65
+ attachments = [],
66
+ useCase = null,
67
+ defaultUseCase = TEXT_USE_CASE,
68
+ multiSelectUseCases = false,
69
+ useCases = [],
70
+ modelsByKind,
71
+ multiSelectModels = false,
72
+ modelIds = [],
73
+ models,
74
+ modelId = null,
75
+ autoSelectModel = false,
76
+ aspectRatios,
77
+ aspectRatio = null,
78
+ submitError = null,
79
+ submitting = false,
80
+ regions = [],
81
+ disabled = false,
82
+ } = props;
83
+
84
+ // What the person picked, and what actually runs: with nothing picked, the
85
+ // builder's default use case (a text request unless they chose otherwise).
86
+ const pickedUseCases = multiSelectUseCases ? useCases : useCase ? [useCase] : [];
87
+ const activeUseCases = pickedUseCases.length > 0 ? pickedUseCases : [defaultUseCase];
88
+ // An edit needs an image, then a change: a prompt for the whole image, a
89
+ // region with its own instruction, or both.
90
+ const editing = activeUseCases.some((u) => u.edit);
91
+ const hasImage = attachments.some((a) => a.kind === "image");
92
+ const hasContent = editing
93
+ ? hasImage && (value.trim().length > 0 || regions.length > 0)
94
+ : value.trim().length > 0 || attachments.length > 0;
95
+ const isSubmitDisabled = submitError ? disabled : (props.submitDisabled ?? (disabled || !hasContent));
96
+ const placeholder =
97
+ props.placeholder ??
98
+ (editing
99
+ ? hasImage
100
+ ? "Describe a change across the whole image, or leave this empty"
101
+ : "Attach an image to edit"
102
+ : "Describe media to create");
103
+ // The stop icon only appears with somewhere for its click to go.
104
+ const showStop = submitting && Boolean(props.onAbort);
105
+
106
+ const multiModel = multiSelectModels || multiSelectUseCases;
107
+ const rawPickedIds = multiModel ? modelIds : modelId ? [modelId] : [];
108
+ // The app's list for a use case, or Chai's suggested models when it gave none.
109
+ const rosterFor = (u: ComposerUseCase): { options: ModelOption[]; suggested: boolean } => {
110
+ const given = multiSelectUseCases ? modelsByKind?.[u.kind] : models;
111
+ if (given) return { options: given, suggested: false };
112
+ return { options: suggestedModels(u.edit ? "image-edit" : deriveGenerationUseCase(u, attachments)), suggested: true };
113
+ };
114
+ // One menu section per use case with multi-use-case select; otherwise one flat roster.
115
+ const modelSections = (multiSelectUseCases ? activeUseCases : activeUseCases.slice(0, 1))
116
+ .map((u) => ({ label: multiSelectUseCases ? u.label : "", kind: u.kind, ...rosterFor(u) }))
117
+ .filter((s) => s.options.length > 0);
118
+ const allModels = modelSections.flatMap((s) => s.options);
119
+ // A pick that isn't in the current list (e.g. the edit model after leaving
120
+ // edit mode) is shown as unpicked and never submitted. With no list at
121
+ // all, the app's pick is passed through as given. With nothing picked
122
+ // from a suggested list (and auto-select off), its first model is the pick.
123
+ const validPicks = allModels.length > 0 ? rawPickedIds.filter((id) => allModels.some((m) => m.id === id)) : rawPickedIds;
124
+ const pickedModelIds =
125
+ validPicks.length > 0 || autoSelectModel ? validPicks : modelSections.filter((s) => s.suggested).map((s) => s.options[0]!.id);
126
+ const pickedModels = allModels.filter((m) => pickedModelIds.includes(m.id));
127
+ // No menu that can't change anything: without its handler, the Model menu hides (the default pick still runs).
128
+ const canPickModel = Boolean(multiModel ? props.onModelIdsChange : props.onModelChange);
129
+ const modelTriggerLabel =
130
+ pickedModels.length > 1
131
+ ? `${pickedModels.length} models`
132
+ : (pickedModels[0]?.label ?? (autoSelectModel ? "Auto-select" : "Select models"));
133
+
134
+ // An edit keeps the source image's shape.
135
+ const showAspectRatio = activeUseCases.some((u) => !u.edit && (u.kind === "image" || u.kind === "video"));
136
+ // Only ratios every model that might run takes: the picked ones, or with
137
+ // none picked (or auto-select on) the whole list, so whichever runs can
138
+ // honor it. A model with no `aspectRatios` sets its own shape: no menu.
139
+ const ratioModels = pickedModels.length > 0 && !autoSelectModel ? pickedModels : allModels;
140
+ const sharedRatios =
141
+ ratioModels.reduce<string[] | null>((shared, m) => (shared ?? m.aspectRatios ?? []).filter((r) => m.aspectRatios?.includes(r)), null) ??
142
+ [];
143
+ const aspectOptions = aspectRatios
144
+ ? aspectRatios.filter((o) => sharedRatios.includes(o.value))
145
+ : sharedRatios.map((r) => ({ value: r, label: r }));
146
+ // A pick the current models don't take is shown as unpicked and never sent.
147
+ const offeredAspect = showAspectRatio && aspectOptions.some((o) => o.value === aspectRatio) ? aspectRatio : null;
148
+ const selectedAspect = aspectOptions.find((o) => o.value === offeredAspect) ?? null;
149
+
150
+ const selections = (): ComposerSelection[] =>
151
+ activeUseCases.map((u) => ({
152
+ useCase: u,
153
+ models: rosterFor(u).options,
154
+ modelIds: multiSelectUseCases ? pickedModelIds.filter((id) => rosterFor(u).options.some((m) => m.id === id)) : pickedModelIds,
155
+ }));
156
+
157
+ return {
158
+ pickedUseCases,
159
+ activeUseCases,
160
+ editing,
161
+ isSubmitDisabled,
162
+ placeholder,
163
+ showStop,
164
+ multiModel,
165
+ modelSections,
166
+ pickedModelIds,
167
+ canPickModel,
168
+ modelTriggerLabel,
169
+ showAspectRatio,
170
+ aspectOptions,
171
+ offeredAspect,
172
+ selectedAspect,
173
+ /** The model ids after a row click: the one picked, or with multi-select that one toggled. */
174
+ toggledModelIds: (id: string) => (modelIds.includes(id) ? modelIds.filter((m) => m !== id) : [...modelIds, id]),
175
+ /** Everything a submit sends. */
176
+ payload: (): ComposerSubmitPayload => ({
177
+ value,
178
+ attachments,
179
+ useCase: activeUseCases[0]!,
180
+ modelId: pickedModelIds[0] ?? null,
181
+ aspectRatio: offeredAspect,
182
+ selections: selections(),
183
+ autoSelectModel,
184
+ regions: editing ? regions : [],
185
+ }),
186
+ };
187
+ }
188
+
189
+ export type ComposerView = ReturnType<typeof composerView>;
190
+
191
+ /** The `+` menu items that can work: "Add media" needs somewhere to put files, the use-case items a handler. */
192
+ export function composerAttachMenuItems(
193
+ actions: ComposerAttachMenuAction[] | undefined,
194
+ { canAddMedia, canSelect }: { canAddMedia: boolean; canSelect: boolean }
195
+ ) {
196
+ return COMPOSER_ATTACH_MENU_ITEMS.filter(
197
+ (item) =>
198
+ (actions ?? COMPOSER_ATTACH_MENU_ITEMS.map((i) => i.action)).includes(item.action) &&
199
+ (item.action === "add-media" ? canAddMedia : canSelect)
200
+ );
201
+ }
202
+
203
+ /**
204
+ * The attachments after picking files: each image, video or audio file
205
+ * added in the order picked. Editing works on one image, so its first image
206
+ * replaces what's there (and with none, every file is unsupported).
207
+ */
208
+ export async function composerAttachmentsFromFiles(
209
+ files: Iterable<File>,
210
+ current: ComposerAttachment[],
211
+ editing: boolean
212
+ ): Promise<{ attachments: ComposerAttachment[] | null; unsupported: string[] }> {
213
+ const list = [...files];
214
+ if (editing) {
215
+ const image = list.find((f) => f.type.startsWith("image/"));
216
+ if (!image) return { attachments: null, unsupported: list.map((f) => f.name) };
217
+ const { media, unsupported } = await readMediaFiles([image]);
218
+ return { attachments: media.length > 0 ? media.map((m) => ({ ...m, id: uniqueId() })) : null, unsupported };
219
+ }
220
+ const { media, unsupported } = await readMediaFiles(list);
221
+ return { attachments: [...current, ...media.map((m) => ({ ...m, id: uniqueId() }))], unsupported };
222
+ }