@kohryan/moodui 0.0.1 → 0.0.2
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.
- package/dist/index.d.mts +29 -1
- package/dist/index.d.ts +29 -1
- package/dist/index.js +25 -2
- package/dist/index.mjs +24 -2
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -159,4 +159,32 @@ type GenerateSpecResult = {
|
|
|
159
159
|
};
|
|
160
160
|
declare function generateMoodUISpec(llm: LLMChatClient, options: GenerateSpecOptions): Promise<GenerateSpecResult>;
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
type Common = {
|
|
163
|
+
prompt: string;
|
|
164
|
+
componentName?: string;
|
|
165
|
+
temperature?: number;
|
|
166
|
+
maxAttempts?: number;
|
|
167
|
+
};
|
|
168
|
+
type GenerateReactFromPromptOptions = (Common & {
|
|
169
|
+
provider: "gemini";
|
|
170
|
+
apiKey: string;
|
|
171
|
+
model: string;
|
|
172
|
+
baseUrl?: string;
|
|
173
|
+
}) | (Common & {
|
|
174
|
+
provider: "ollama";
|
|
175
|
+
model: string;
|
|
176
|
+
baseUrl?: string;
|
|
177
|
+
}) | (Common & {
|
|
178
|
+
provider: "openai-compatible";
|
|
179
|
+
apiKey: string;
|
|
180
|
+
model: string;
|
|
181
|
+
baseUrl: string;
|
|
182
|
+
});
|
|
183
|
+
type GenerateReactFromPromptResult = {
|
|
184
|
+
spec: MoodUISpec;
|
|
185
|
+
raw: string;
|
|
186
|
+
code: string;
|
|
187
|
+
};
|
|
188
|
+
declare function generateReactFromPrompt(options: GenerateReactFromPromptOptions): Promise<GenerateReactFromPromptResult>;
|
|
189
|
+
|
|
190
|
+
export { type GeminiClientOptions, type GenerateReactFromPromptOptions, type GenerateReactFromPromptResult, type GenerateSpecOptions, type GenerateSpecResult, type LLMChatClient, type LLMChatRequest, type LLMMessage, type MoodUIBoxNode, type MoodUIButtonNode, type MoodUIColor, type MoodUICommonProps, type MoodUIImageNode, type MoodUIInputNode, type MoodUINode, type MoodUIRadius, type MoodUISpace, type MoodUISpacerNode, type MoodUISpec, type MoodUISpecVersion, type MoodUITextNode, type MoodUITheme, type OllamaClientOptions, type OpenAICompatibleClientOptions, type RenderReactOptions, type ValidationResult, type _InternalNodeTypes, type _RenderReactExports, assertMoodUISpec, createGeminiClient, createOllamaClient, createOpenAICompatibleClient, generateMoodUISpec, generateReactFromPrompt, renderReact, renderReactJSX, validateMoodUISpec };
|
package/dist/index.d.ts
CHANGED
|
@@ -159,4 +159,32 @@ type GenerateSpecResult = {
|
|
|
159
159
|
};
|
|
160
160
|
declare function generateMoodUISpec(llm: LLMChatClient, options: GenerateSpecOptions): Promise<GenerateSpecResult>;
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
type Common = {
|
|
163
|
+
prompt: string;
|
|
164
|
+
componentName?: string;
|
|
165
|
+
temperature?: number;
|
|
166
|
+
maxAttempts?: number;
|
|
167
|
+
};
|
|
168
|
+
type GenerateReactFromPromptOptions = (Common & {
|
|
169
|
+
provider: "gemini";
|
|
170
|
+
apiKey: string;
|
|
171
|
+
model: string;
|
|
172
|
+
baseUrl?: string;
|
|
173
|
+
}) | (Common & {
|
|
174
|
+
provider: "ollama";
|
|
175
|
+
model: string;
|
|
176
|
+
baseUrl?: string;
|
|
177
|
+
}) | (Common & {
|
|
178
|
+
provider: "openai-compatible";
|
|
179
|
+
apiKey: string;
|
|
180
|
+
model: string;
|
|
181
|
+
baseUrl: string;
|
|
182
|
+
});
|
|
183
|
+
type GenerateReactFromPromptResult = {
|
|
184
|
+
spec: MoodUISpec;
|
|
185
|
+
raw: string;
|
|
186
|
+
code: string;
|
|
187
|
+
};
|
|
188
|
+
declare function generateReactFromPrompt(options: GenerateReactFromPromptOptions): Promise<GenerateReactFromPromptResult>;
|
|
189
|
+
|
|
190
|
+
export { type GeminiClientOptions, type GenerateReactFromPromptOptions, type GenerateReactFromPromptResult, type GenerateSpecOptions, type GenerateSpecResult, type LLMChatClient, type LLMChatRequest, type LLMMessage, type MoodUIBoxNode, type MoodUIButtonNode, type MoodUIColor, type MoodUICommonProps, type MoodUIImageNode, type MoodUIInputNode, type MoodUINode, type MoodUIRadius, type MoodUISpace, type MoodUISpacerNode, type MoodUISpec, type MoodUISpecVersion, type MoodUITextNode, type MoodUITheme, type OllamaClientOptions, type OpenAICompatibleClientOptions, type RenderReactOptions, type ValidationResult, type _InternalNodeTypes, type _RenderReactExports, assertMoodUISpec, createGeminiClient, createOllamaClient, createOpenAICompatibleClient, generateMoodUISpec, generateReactFromPrompt, renderReact, renderReactJSX, validateMoodUISpec };
|
package/dist/index.js
CHANGED
|
@@ -25,6 +25,7 @@ __export(index_exports, {
|
|
|
25
25
|
createOllamaClient: () => createOllamaClient,
|
|
26
26
|
createOpenAICompatibleClient: () => createOpenAICompatibleClient,
|
|
27
27
|
generateMoodUISpec: () => generateMoodUISpec,
|
|
28
|
+
generateReactFromPrompt: () => generateReactFromPrompt,
|
|
28
29
|
renderReact: () => renderReact,
|
|
29
30
|
renderReactJSX: () => renderReactJSX,
|
|
30
31
|
validateMoodUISpec: () => validateMoodUISpec
|
|
@@ -215,7 +216,9 @@ function buildProps(tag, node, extraProps) {
|
|
|
215
216
|
if (props.alt) out.push(`alt=${serializeJsxAttrValue(props.alt)}`);
|
|
216
217
|
if (props.fit) mergedStyle.objectFit = props.fit;
|
|
217
218
|
}
|
|
218
|
-
if (Object.keys(mergedStyle).length > 0)
|
|
219
|
+
if (Object.keys(mergedStyle).length > 0) {
|
|
220
|
+
out.push(`style={(${serializeJsValue(mergedStyle)} as React.CSSProperties)}`);
|
|
221
|
+
}
|
|
219
222
|
if (extraProps) {
|
|
220
223
|
for (const [k, v] of Object.entries(extraProps)) out.push(`${k}={${v}}`);
|
|
221
224
|
}
|
|
@@ -232,7 +235,7 @@ function computeStyle(tag, node) {
|
|
|
232
235
|
applySpacing(style, "padding", props.padding);
|
|
233
236
|
if (node.type === "box") {
|
|
234
237
|
style.display = "flex";
|
|
235
|
-
style.flexDirection = props.direction ?? "column";
|
|
238
|
+
style.flexDirection = normalizeFlexDirection(props.direction) ?? "column";
|
|
236
239
|
if (props.gap != null) style.gap = normalizeCssValue(props.gap);
|
|
237
240
|
if (props.align != null) style.alignItems = props.align;
|
|
238
241
|
if (props.justify != null) style.justifyContent = props.justify;
|
|
@@ -314,6 +317,12 @@ function normalizeCssValue(value) {
|
|
|
314
317
|
if (typeof value === "string") return value;
|
|
315
318
|
return value;
|
|
316
319
|
}
|
|
320
|
+
function normalizeFlexDirection(value) {
|
|
321
|
+
if (value === "row" || value === "column") return value;
|
|
322
|
+
if (value === "horizontal") return "row";
|
|
323
|
+
if (value === "vertical") return "column";
|
|
324
|
+
return void 0;
|
|
325
|
+
}
|
|
317
326
|
function serializeJsxAttrValue(value) {
|
|
318
327
|
return `{${serializeJsValue(value)}}`;
|
|
319
328
|
}
|
|
@@ -568,6 +577,19 @@ function parseFirstJsonObject(text) {
|
|
|
568
577
|
}
|
|
569
578
|
throw new Error("Unterminated JSON object");
|
|
570
579
|
}
|
|
580
|
+
|
|
581
|
+
// src/ai/generateReactFromPrompt.ts
|
|
582
|
+
async function generateReactFromPrompt(options) {
|
|
583
|
+
const llm = options.provider === "gemini" ? createGeminiClient({ apiKey: options.apiKey, baseUrl: options.baseUrl }) : options.provider === "ollama" ? createOllamaClient({ baseUrl: options.baseUrl }) : createOpenAICompatibleClient({ apiKey: options.apiKey, baseUrl: options.baseUrl });
|
|
584
|
+
const { spec, raw } = await generateMoodUISpec(llm, {
|
|
585
|
+
model: options.model,
|
|
586
|
+
prompt: options.prompt,
|
|
587
|
+
temperature: options.temperature,
|
|
588
|
+
maxAttempts: options.maxAttempts
|
|
589
|
+
});
|
|
590
|
+
const code = renderReact(spec, { componentName: options.componentName });
|
|
591
|
+
return { spec, raw, code };
|
|
592
|
+
}
|
|
571
593
|
// Annotate the CommonJS export names for ESM import in node:
|
|
572
594
|
0 && (module.exports = {
|
|
573
595
|
assertMoodUISpec,
|
|
@@ -575,6 +597,7 @@ function parseFirstJsonObject(text) {
|
|
|
575
597
|
createOllamaClient,
|
|
576
598
|
createOpenAICompatibleClient,
|
|
577
599
|
generateMoodUISpec,
|
|
600
|
+
generateReactFromPrompt,
|
|
578
601
|
renderReact,
|
|
579
602
|
renderReactJSX,
|
|
580
603
|
validateMoodUISpec
|
package/dist/index.mjs
CHANGED
|
@@ -182,7 +182,9 @@ function buildProps(tag, node, extraProps) {
|
|
|
182
182
|
if (props.alt) out.push(`alt=${serializeJsxAttrValue(props.alt)}`);
|
|
183
183
|
if (props.fit) mergedStyle.objectFit = props.fit;
|
|
184
184
|
}
|
|
185
|
-
if (Object.keys(mergedStyle).length > 0)
|
|
185
|
+
if (Object.keys(mergedStyle).length > 0) {
|
|
186
|
+
out.push(`style={(${serializeJsValue(mergedStyle)} as React.CSSProperties)}`);
|
|
187
|
+
}
|
|
186
188
|
if (extraProps) {
|
|
187
189
|
for (const [k, v] of Object.entries(extraProps)) out.push(`${k}={${v}}`);
|
|
188
190
|
}
|
|
@@ -199,7 +201,7 @@ function computeStyle(tag, node) {
|
|
|
199
201
|
applySpacing(style, "padding", props.padding);
|
|
200
202
|
if (node.type === "box") {
|
|
201
203
|
style.display = "flex";
|
|
202
|
-
style.flexDirection = props.direction ?? "column";
|
|
204
|
+
style.flexDirection = normalizeFlexDirection(props.direction) ?? "column";
|
|
203
205
|
if (props.gap != null) style.gap = normalizeCssValue(props.gap);
|
|
204
206
|
if (props.align != null) style.alignItems = props.align;
|
|
205
207
|
if (props.justify != null) style.justifyContent = props.justify;
|
|
@@ -281,6 +283,12 @@ function normalizeCssValue(value) {
|
|
|
281
283
|
if (typeof value === "string") return value;
|
|
282
284
|
return value;
|
|
283
285
|
}
|
|
286
|
+
function normalizeFlexDirection(value) {
|
|
287
|
+
if (value === "row" || value === "column") return value;
|
|
288
|
+
if (value === "horizontal") return "row";
|
|
289
|
+
if (value === "vertical") return "column";
|
|
290
|
+
return void 0;
|
|
291
|
+
}
|
|
284
292
|
function serializeJsxAttrValue(value) {
|
|
285
293
|
return `{${serializeJsValue(value)}}`;
|
|
286
294
|
}
|
|
@@ -535,12 +543,26 @@ function parseFirstJsonObject(text) {
|
|
|
535
543
|
}
|
|
536
544
|
throw new Error("Unterminated JSON object");
|
|
537
545
|
}
|
|
546
|
+
|
|
547
|
+
// src/ai/generateReactFromPrompt.ts
|
|
548
|
+
async function generateReactFromPrompt(options) {
|
|
549
|
+
const llm = options.provider === "gemini" ? createGeminiClient({ apiKey: options.apiKey, baseUrl: options.baseUrl }) : options.provider === "ollama" ? createOllamaClient({ baseUrl: options.baseUrl }) : createOpenAICompatibleClient({ apiKey: options.apiKey, baseUrl: options.baseUrl });
|
|
550
|
+
const { spec, raw } = await generateMoodUISpec(llm, {
|
|
551
|
+
model: options.model,
|
|
552
|
+
prompt: options.prompt,
|
|
553
|
+
temperature: options.temperature,
|
|
554
|
+
maxAttempts: options.maxAttempts
|
|
555
|
+
});
|
|
556
|
+
const code = renderReact(spec, { componentName: options.componentName });
|
|
557
|
+
return { spec, raw, code };
|
|
558
|
+
}
|
|
538
559
|
export {
|
|
539
560
|
assertMoodUISpec,
|
|
540
561
|
createGeminiClient,
|
|
541
562
|
createOllamaClient,
|
|
542
563
|
createOpenAICompatibleClient,
|
|
543
564
|
generateMoodUISpec,
|
|
565
|
+
generateReactFromPrompt,
|
|
544
566
|
renderReact,
|
|
545
567
|
renderReactJSX,
|
|
546
568
|
validateMoodUISpec
|