@kohryan/moodui 0.0.15 → 0.0.16

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/cli.mjs CHANGED
@@ -586,13 +586,19 @@ function validateNode(input, path3) {
586
586
  else if (!isString(props.src)) errors.push(`${path3}.props.src must be a string`);
587
587
  break;
588
588
  }
589
+ case "icon": {
590
+ const props = input.props;
591
+ if (!isObject(props)) errors.push(`${path3}.props must be an object`);
592
+ else if (!isString(props.name)) errors.push(`${path3}.props.name must be a string`);
593
+ break;
594
+ }
589
595
  case "spacer": {
590
596
  const props = input.props;
591
597
  if (props != null && !isObject(props)) errors.push(`${path3}.props must be an object if provided`);
592
598
  break;
593
599
  }
594
600
  default:
595
- errors.push(`${path3}.type must be one of: box | text | button | input | image | spacer`);
601
+ errors.push(`${path3}.type must be one of: box | text | button | input | image | icon | spacer`);
596
602
  }
597
603
  if (errors.length > 0) return { ok: false, errors };
598
604
  return { ok: true, value: input };
@@ -661,14 +667,20 @@ function buildSystemPrompt() {
661
667
  "- button: { type:'button', props: { label: string, variant?, actionId?, disabled?, ...common } }",
662
668
  "- input: { type:'input', props?: { name?, placeholder?, defaultValue?, ...common } }",
663
669
  "- image: { type:'image', props: { src: string, alt?, fit?, ...common } }",
670
+ "- icon: { type:'icon', props: { name, size?, color?, strokeWidth?, ...common } }",
664
671
  "- spacer: { type:'spacer', props?: { size? } }",
665
672
  "",
666
673
  "common props:",
667
674
  "- id, testId, className, style(object), padding, margin, background, borderRadius, width, height",
668
675
  "",
676
+ "Reusable icon names:",
677
+ "- sparkles, search, settings, user, mail, heart, home, plus, check, arrow-right, calendar, bell, star, chart-bar, message-circle, shield",
678
+ "",
669
679
  "Rules:",
670
680
  "- root wajib ada",
671
681
  "- minimal pakai box sebagai container utama",
682
+ "- gunakan icon node bila UI membutuhkan icon navigasi, status, statistik, CTA, atau dekorasi ringan",
683
+ "- utamakan layout modern: card, section, spacing konsisten, hierarchy yang jelas",
672
684
  "- semua string pakai double quotes (JSON standard)",
673
685
  "- jangan pakai function / JS expression apa pun"
674
686
  ].join("\n");
@@ -712,9 +724,11 @@ function parseFirstJsonObject(text) {
712
724
  function renderReact(specInput, options = {}) {
713
725
  const spec = assertMoodUISpec(specInput);
714
726
  const componentName = options.componentName ?? "MoodUIScreen";
727
+ const hasIcons = containsIconNode(spec.root);
715
728
  const jsx = renderNode(spec.root, { indent: 2, onActionProp: "onAction" });
716
729
  return [
717
730
  'import * as React from "react";',
731
+ hasIcons ? 'import { MoodUIIcon } from "@kohryan/moodui";' : "",
718
732
  "",
719
733
  "export type MoodUIScreenActionHandler = (actionId: string) => void;",
720
734
  "",
@@ -759,6 +773,8 @@ function renderNode(node, ctx) {
759
773
  return renderSelfClosingElement("input", node, ctx);
760
774
  case "image":
761
775
  return renderSelfClosingElement("img", node, ctx);
776
+ case "icon":
777
+ return renderSelfClosingElement("MoodUIIcon", node, ctx);
762
778
  case "spacer": {
763
779
  const size = node.props?.size ?? 8;
764
780
  const style = { width: normalizeCssValue(size), height: normalizeCssValue(size) };
@@ -805,6 +821,12 @@ function buildProps(tag, node, extraProps) {
805
821
  if (props.alt) out.push(`alt=${serializeJsxAttrValue(props.alt)}`);
806
822
  if (props.fit) mergedStyle.objectFit = props.fit;
807
823
  }
824
+ if (tag === "MoodUIIcon") {
825
+ if (props.name) out.push(`name=${serializeJsxAttrValue(props.name)}`);
826
+ if (props.size != null) out.push(`size={${serializeJsValue(props.size)}}`);
827
+ if (props.color) out.push(`color=${serializeJsxAttrValue(props.color)}`);
828
+ if (props.strokeWidth != null) out.push(`strokeWidth={${serializeJsValue(props.strokeWidth)}}`);
829
+ }
808
830
  if (Object.keys(mergedStyle).length > 0) {
809
831
  out.push(`style={(${serializeJsValue(mergedStyle)} as React.CSSProperties)}`);
810
832
  }
@@ -934,6 +956,11 @@ function safeObjectKey(key) {
934
956
  function escapeText(value) {
935
957
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
936
958
  }
959
+ function containsIconNode(node) {
960
+ if (node.type === "icon") return true;
961
+ if (node.type !== "box") return false;
962
+ return (node.children ?? []).some((child) => containsIconNode(child));
963
+ }
937
964
  function indent(spaces) {
938
965
  return " ".repeat(spaces);
939
966
  }
package/dist/index.d.mts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
2
3
 
3
4
  type MoodUISpecVersion = 1;
4
5
  type MoodUISpec = {
@@ -37,7 +38,7 @@ type MoodUISpace = number | string | {
37
38
  };
38
39
  type MoodUIColor = string;
39
40
  type MoodUIRadius = number | string;
40
- type MoodUINode = MoodUIBoxNode | MoodUITextNode | MoodUIButtonNode | MoodUIInputNode | MoodUIImageNode | MoodUISpacerNode;
41
+ type MoodUINode = MoodUIBoxNode | MoodUITextNode | MoodUIButtonNode | MoodUIInputNode | MoodUIImageNode | MoodUIIconNode | MoodUISpacerNode;
41
42
  type MoodUIBoxNode = {
42
43
  type: "box";
43
44
  props?: MoodUICommonProps & {
@@ -85,6 +86,16 @@ type MoodUIImageNode = {
85
86
  fit?: "cover" | "contain" | "fill" | "none" | "scale-down";
86
87
  };
87
88
  };
89
+ type MoodUIIconName = "arrow-right" | "bell" | "calendar" | "chart-bar" | "check" | "heart" | "home" | "mail" | "message-circle" | "plus" | "search" | "settings" | "shield" | "sparkles" | "star" | "user";
90
+ type MoodUIIconNode = {
91
+ type: "icon";
92
+ props: MoodUICommonProps & {
93
+ name: MoodUIIconName;
94
+ size?: number | string;
95
+ color?: MoodUIColor;
96
+ strokeWidth?: number;
97
+ };
98
+ };
88
99
  type MoodUISpacerNode = {
89
100
  type: "spacer";
90
101
  props?: {
@@ -103,7 +114,7 @@ type Err = {
103
114
  type ValidationResult<T> = Ok<T> | Err;
104
115
  declare function validateMoodUISpec(input: unknown): ValidationResult<MoodUISpec>;
105
116
  declare function assertMoodUISpec(input: unknown): MoodUISpec;
106
- type _InternalNodeTypes = MoodUITextNode | MoodUIButtonNode | MoodUIInputNode | MoodUIImageNode | MoodUISpacerNode;
117
+ type _InternalNodeTypes = MoodUITextNode | MoodUIButtonNode | MoodUIIconNode | MoodUIInputNode | MoodUIImageNode | MoodUISpacerNode;
107
118
 
108
119
  type RenderReactOptions = {
109
120
  componentName?: string;
@@ -115,6 +126,18 @@ type _RenderReactExports = {
115
126
  renderReactJSX: typeof renderReactJSX;
116
127
  };
117
128
 
129
+ type MoodUIIconProps = {
130
+ name: MoodUIIconName;
131
+ size?: number | string;
132
+ color?: string;
133
+ strokeWidth?: number;
134
+ className?: string;
135
+ style?: React.CSSProperties;
136
+ title?: string;
137
+ };
138
+ declare const MOODUI_ICON_NAMES: MoodUIIconName[];
139
+ declare function MoodUIIcon(props: MoodUIIconProps): react_jsx_runtime.JSX.Element;
140
+
118
141
  type MoodUIRuntimeProps = {
119
142
  spec: MoodUISpec;
120
143
  onAction?: (actionId: string) => void;
@@ -205,4 +228,4 @@ type GenerateReactFromPromptResult = {
205
228
  };
206
229
  declare function generateReactFromPrompt(options: GenerateReactFromPromptOptions): Promise<GenerateReactFromPromptResult>;
207
230
 
208
- 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, MoodUIPromptPlayground, type MoodUIPromptPlaygroundProps, type MoodUIRadius, MoodUIRuntime, type MoodUIRuntimeProps, 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 };
231
+ export { type GeminiClientOptions, type GenerateReactFromPromptOptions, type GenerateReactFromPromptResult, type GenerateSpecOptions, type GenerateSpecResult, type LLMChatClient, type LLMChatRequest, type LLMMessage, MOODUI_ICON_NAMES, type MoodUIBoxNode, type MoodUIButtonNode, type MoodUIColor, type MoodUICommonProps, MoodUIIcon, type MoodUIIconName, type MoodUIIconNode, type MoodUIIconProps, type MoodUIImageNode, type MoodUIInputNode, type MoodUINode, MoodUIPromptPlayground, type MoodUIPromptPlaygroundProps, type MoodUIRadius, MoodUIRuntime, type MoodUIRuntimeProps, 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
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
2
3
 
3
4
  type MoodUISpecVersion = 1;
4
5
  type MoodUISpec = {
@@ -37,7 +38,7 @@ type MoodUISpace = number | string | {
37
38
  };
38
39
  type MoodUIColor = string;
39
40
  type MoodUIRadius = number | string;
40
- type MoodUINode = MoodUIBoxNode | MoodUITextNode | MoodUIButtonNode | MoodUIInputNode | MoodUIImageNode | MoodUISpacerNode;
41
+ type MoodUINode = MoodUIBoxNode | MoodUITextNode | MoodUIButtonNode | MoodUIInputNode | MoodUIImageNode | MoodUIIconNode | MoodUISpacerNode;
41
42
  type MoodUIBoxNode = {
42
43
  type: "box";
43
44
  props?: MoodUICommonProps & {
@@ -85,6 +86,16 @@ type MoodUIImageNode = {
85
86
  fit?: "cover" | "contain" | "fill" | "none" | "scale-down";
86
87
  };
87
88
  };
89
+ type MoodUIIconName = "arrow-right" | "bell" | "calendar" | "chart-bar" | "check" | "heart" | "home" | "mail" | "message-circle" | "plus" | "search" | "settings" | "shield" | "sparkles" | "star" | "user";
90
+ type MoodUIIconNode = {
91
+ type: "icon";
92
+ props: MoodUICommonProps & {
93
+ name: MoodUIIconName;
94
+ size?: number | string;
95
+ color?: MoodUIColor;
96
+ strokeWidth?: number;
97
+ };
98
+ };
88
99
  type MoodUISpacerNode = {
89
100
  type: "spacer";
90
101
  props?: {
@@ -103,7 +114,7 @@ type Err = {
103
114
  type ValidationResult<T> = Ok<T> | Err;
104
115
  declare function validateMoodUISpec(input: unknown): ValidationResult<MoodUISpec>;
105
116
  declare function assertMoodUISpec(input: unknown): MoodUISpec;
106
- type _InternalNodeTypes = MoodUITextNode | MoodUIButtonNode | MoodUIInputNode | MoodUIImageNode | MoodUISpacerNode;
117
+ type _InternalNodeTypes = MoodUITextNode | MoodUIButtonNode | MoodUIIconNode | MoodUIInputNode | MoodUIImageNode | MoodUISpacerNode;
107
118
 
108
119
  type RenderReactOptions = {
109
120
  componentName?: string;
@@ -115,6 +126,18 @@ type _RenderReactExports = {
115
126
  renderReactJSX: typeof renderReactJSX;
116
127
  };
117
128
 
129
+ type MoodUIIconProps = {
130
+ name: MoodUIIconName;
131
+ size?: number | string;
132
+ color?: string;
133
+ strokeWidth?: number;
134
+ className?: string;
135
+ style?: React.CSSProperties;
136
+ title?: string;
137
+ };
138
+ declare const MOODUI_ICON_NAMES: MoodUIIconName[];
139
+ declare function MoodUIIcon(props: MoodUIIconProps): react_jsx_runtime.JSX.Element;
140
+
118
141
  type MoodUIRuntimeProps = {
119
142
  spec: MoodUISpec;
120
143
  onAction?: (actionId: string) => void;
@@ -205,4 +228,4 @@ type GenerateReactFromPromptResult = {
205
228
  };
206
229
  declare function generateReactFromPrompt(options: GenerateReactFromPromptOptions): Promise<GenerateReactFromPromptResult>;
207
230
 
208
- 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, MoodUIPromptPlayground, type MoodUIPromptPlaygroundProps, type MoodUIRadius, MoodUIRuntime, type MoodUIRuntimeProps, 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 };
231
+ export { type GeminiClientOptions, type GenerateReactFromPromptOptions, type GenerateReactFromPromptResult, type GenerateSpecOptions, type GenerateSpecResult, type LLMChatClient, type LLMChatRequest, type LLMMessage, MOODUI_ICON_NAMES, type MoodUIBoxNode, type MoodUIButtonNode, type MoodUIColor, type MoodUICommonProps, MoodUIIcon, type MoodUIIconName, type MoodUIIconNode, type MoodUIIconProps, type MoodUIImageNode, type MoodUIInputNode, type MoodUINode, MoodUIPromptPlayground, type MoodUIPromptPlaygroundProps, type MoodUIRadius, MoodUIRuntime, type MoodUIRuntimeProps, 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 };