@melony/ui-kit 0.1.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.
@@ -0,0 +1,41 @@
1
+ import { createContext, useContext } from 'react';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+
4
+ // src/context.tsx
5
+ var MelonyUIContext = createContext(null);
6
+ function MelonyUIProvider({ components, children }) {
7
+ return /* @__PURE__ */ jsx(MelonyUIContext.Provider, { value: { components }, children });
8
+ }
9
+ function useMelonyUI() {
10
+ const context = useContext(MelonyUIContext);
11
+ if (!context) {
12
+ throw new Error("useMelonyUI must be used within a MelonyUIProvider");
13
+ }
14
+ return context;
15
+ }
16
+ function MelonyRenderer({ node }) {
17
+ const { components } = useMelonyUI();
18
+ const { type, props, children } = node;
19
+ const Component = components[type];
20
+ if (!Component) {
21
+ return /* @__PURE__ */ jsxs("div", { style: {
22
+ color: "red",
23
+ fontStyle: "italic",
24
+ fontSize: "0.875rem",
25
+ padding: "0.5rem",
26
+ border: "1px dashed rgba(255, 0, 0, 0.5)",
27
+ borderRadius: "0.25rem",
28
+ backgroundColor: "rgba(255, 0, 0, 0.05)"
29
+ }, children: [
30
+ "[Unknown component: ",
31
+ type,
32
+ "]"
33
+ ] });
34
+ }
35
+ const renderedChildren = children?.map((child, i) => /* @__PURE__ */ jsx(MelonyRenderer, { node: child }, i));
36
+ return /* @__PURE__ */ jsx(Component, { ...props, children: renderedChildren });
37
+ }
38
+
39
+ export { MelonyRenderer, MelonyUIProvider, useMelonyUI };
40
+ //# sourceMappingURL=chunk-7YJBGUKN.js.map
41
+ //# sourceMappingURL=chunk-7YJBGUKN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context.tsx","../src/Renderer.tsx"],"names":["jsx"],"mappings":";;;;AAWA,IAAM,eAAA,GAAkB,cAA2C,IAAI,CAAA;AAOhE,SAAS,gBAAA,CAAiB,EAAE,UAAA,EAAY,QAAA,EAAS,EAA0B;AAChF,EAAA,uBACE,GAAA,CAAC,gBAAgB,QAAA,EAAhB,EAAyB,OAAO,EAAE,UAAA,IAChC,QAAA,EACH,CAAA;AAEJ;AAEO,SAAS,WAAA,GAAc;AAC5B,EAAA,MAAM,OAAA,GAAU,WAAW,eAAe,CAAA;AAC1C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,oDAAoD,CAAA;AAAA,EACtE;AACA,EAAA,OAAO,OAAA;AACT;ACvBO,SAAS,cAAA,CAAe,EAAE,IAAA,EAAK,EAAwB;AAC5D,EAAA,MAAM,EAAE,UAAA,EAAW,GAAI,WAAA,EAAY;AACnC,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,QAAA,EAAS,GAAI,IAAA;AAElC,EAAA,MAAM,SAAA,GAAY,WAAW,IAA+B,CAAA;AAE5D,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,uBACE,IAAA,CAAC,SAAI,KAAA,EAAO;AAAA,MACV,KAAA,EAAO,KAAA;AAAA,MACP,SAAA,EAAW,QAAA;AAAA,MACX,QAAA,EAAU,UAAA;AAAA,MACV,OAAA,EAAS,QAAA;AAAA,MACT,MAAA,EAAQ,iCAAA;AAAA,MACR,YAAA,EAAc,SAAA;AAAA,MACd,eAAA,EAAiB;AAAA,KACnB,EAAG,QAAA,EAAA;AAAA,MAAA,sBAAA;AAAA,MACoB,IAAA;AAAA,MAAK;AAAA,KAAA,EAC5B,CAAA;AAAA,EAEJ;AAGA,EAAA,MAAM,gBAAA,GAAmB,QAAA,EAAU,GAAA,CAAI,CAAC,KAAA,EAAO,CAAA,qBAC7CA,GAAAA,CAAC,cAAA,EAAA,EAAuB,IAAA,EAAM,KAAA,EAAA,EAAT,CAAgB,CACtC,CAAA;AAED,EAAA,uBAAOA,GAAAA,CAAC,SAAA,EAAA,EAAW,GAAI,OAAgB,QAAA,EAAA,gBAAA,EAAiB,CAAA;AAC1D","file":"chunk-7YJBGUKN.js","sourcesContent":["import React, { createContext, useContext, ReactNode } from \"react\";\nimport { UIContract } from \"./types\";\n\nexport type MelonyComponents = {\n [K in keyof UIContract]: React.ComponentType<UIContract[K] & { children?: ReactNode }>;\n};\n\nexport interface MelonyUIContextValue {\n components: Partial<MelonyComponents>;\n}\n\nconst MelonyUIContext = createContext<MelonyUIContextValue | null>(null);\n\nexport interface MelonyUIProviderProps {\n components: Partial<MelonyComponents>;\n children: ReactNode;\n}\n\nexport function MelonyUIProvider({ components, children }: MelonyUIProviderProps) {\n return (\n <MelonyUIContext.Provider value={{ components }}>\n {children}\n </MelonyUIContext.Provider>\n );\n}\n\nexport function useMelonyUI() {\n const context = useContext(MelonyUIContext);\n if (!context) {\n throw new Error(\"useMelonyUI must be used within a MelonyUIProvider\");\n }\n return context;\n}\n","'use client';\n\nimport { UINode } from \"./types\";\nimport { useMelonyUI } from \"./context\";\n\nexport interface MelonyRendererProps {\n node: UINode;\n}\n\nexport function MelonyRenderer({ node }: MelonyRendererProps) {\n const { components } = useMelonyUI();\n const { type, props, children } = node;\n\n const Component = components[type as keyof typeof components];\n\n if (!Component) {\n return (\n <div style={{\n color: \"red\",\n fontStyle: \"italic\",\n fontSize: \"0.875rem\",\n padding: \"0.5rem\",\n border: \"1px dashed rgba(255, 0, 0, 0.5)\",\n borderRadius: \"0.25rem\",\n backgroundColor: \"rgba(255, 0, 0, 0.05)\"\n }}>\n [Unknown component: {type}]\n </div>\n );\n }\n\n // Recursively render children\n const renderedChildren = children?.map((child, i) => (\n <MelonyRenderer key={i} node={child} />\n ));\n\n return <Component {...(props as any)}>{renderedChildren}</Component>;\n}\n"]}
@@ -0,0 +1,40 @@
1
+ // src/server.ts
2
+ var ui = {
3
+ /**
4
+ * Creates a UI node.
5
+ */
6
+ node: (type, props = {}, children = []) => ({
7
+ type,
8
+ props,
9
+ children
10
+ }),
11
+ /**
12
+ * Wraps a UI node in an event.
13
+ */
14
+ event: (node) => ({
15
+ type: "ui",
16
+ data: node
17
+ }),
18
+ card: (props = {}, children = []) => ui.node("card", props, children),
19
+ button: (props, children = []) => ui.node("button", props, children),
20
+ text: (value, props = {}) => ui.node("text", { value, ...props }),
21
+ heading: (value, level = 1, props = {}) => ui.node("heading", { value, level, ...props }),
22
+ row: (props = {}, children = []) => ui.node("row", props, children),
23
+ col: (props = {}, children = []) => ui.node("col", props, children),
24
+ badge: (label, variant = "primary", props = {}) => ui.node("badge", { label, variant, ...props }),
25
+ input: (name, label, props = {}) => ui.node("input", { name, label, ...props }),
26
+ textarea: (name, label, props = {}) => ui.node("textarea", { name, label, ...props }),
27
+ select: (name, options, label, props = {}) => ui.node("select", { name, options, label, ...props }),
28
+ checkbox: (name, label, props = {}) => ui.node("checkbox", { name, label, ...props }),
29
+ form: (props = {}, children = []) => ui.node("form", props, children),
30
+ icon: (name, props = {}) => ui.node("icon", { name, ...props }),
31
+ image: (src, alt, props = {}) => ui.node("image", { src, alt, ...props }),
32
+ spacer: (props = {}) => ui.node("spacer", props),
33
+ divider: (props = {}) => ui.node("divider", props),
34
+ list: (props = {}, children = []) => ui.node("list", props, children),
35
+ listItem: (props = {}, children = []) => ui.node("listItem", props, children)
36
+ };
37
+
38
+ export { ui };
39
+ //# sourceMappingURL=chunk-FAENZMHH.js.map
40
+ //# sourceMappingURL=chunk-FAENZMHH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts"],"names":[],"mappings":"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","file":"chunk-FAENZMHH.js","sourcesContent":["import { UIContract, UINode, UIEvent } from \"./types\";\n\nexport * from \"./types\";\n\n/**\n * Helper to create UI events in Melony actions.\n */\nexport const ui = {\n /**\n * Creates a UI node.\n */\n node: <T extends keyof UIContract>(\n type: T,\n props: UIContract[T] = {} as any,\n children: UINode<any>[] = []\n ): UINode<T> => ({\n type,\n props,\n children,\n }),\n\n /**\n * Wraps a UI node in an event.\n */\n event: (node: UINode): UIEvent => ({\n type: \"ui\",\n data: node,\n }),\n\n card: (props: UIContract[\"card\"] = {}, children: UINode[] = []) =>\n ui.node(\"card\", props, children),\n\n button: (props: UIContract[\"button\"], children: UINode[] = []) =>\n ui.node(\"button\", props, children),\n\n text: (value: string, props: Partial<UIContract[\"text\"]> = {}) =>\n ui.node(\"text\", { value, ...props }),\n\n heading: (value: string, level: UIContract[\"heading\"][\"level\"] = 1, props: Partial<UIContract[\"heading\"]> = {}) =>\n ui.node(\"heading\", { value, level, ...props }),\n\n row: (props: UIContract[\"row\"] = {}, children: UINode[] = []) =>\n ui.node(\"row\", props, children),\n\n col: (props: UIContract[\"col\"] = {}, children: UINode[] = []) =>\n ui.node(\"col\", props, children),\n\n badge: (label: string, variant: UIContract[\"badge\"][\"variant\"] = \"primary\", props: Partial<UIContract[\"badge\"]> = {}) =>\n ui.node(\"badge\", { label, variant, ...props }),\n\n input: (name: string, label?: string, props: Partial<UIContract[\"input\"]> = {}) =>\n ui.node(\"input\", { name, label, ...props }),\n\n textarea: (name: string, label?: string, props: Partial<UIContract[\"textarea\"]> = {}) =>\n ui.node(\"textarea\", { name, label, ...props }),\n\n select: (name: string, options: UIContract[\"select\"][\"options\"], label?: string, props: Partial<UIContract[\"select\"]> = {}) =>\n ui.node(\"select\", { name, options, label, ...props }),\n\n checkbox: (name: string, label?: string, props: Partial<UIContract[\"checkbox\"]> = {}) =>\n ui.node(\"checkbox\", { name, label, ...props }),\n\n form: (props: UIContract[\"form\"] = {}, children: UINode[] = []) =>\n ui.node(\"form\", props, children),\n\n icon: (name: string, props: Partial<UIContract[\"icon\"]> = {}) =>\n ui.node(\"icon\", { name, ...props }),\n\n image: (src: string, alt?: string, props: Partial<UIContract[\"image\"]> = {}) =>\n ui.node(\"image\", { src, alt, ...props }),\n\n spacer: (props: UIContract[\"spacer\"] = {}) =>\n ui.node(\"spacer\", props),\n\n divider: (props: UIContract[\"divider\"] = {}) =>\n ui.node(\"divider\", props),\n\n list: (props: UIContract[\"list\"] = {}, children: UINode[] = []) =>\n ui.node(\"list\", props, children),\n\n listItem: (props: UIContract[\"listItem\"] = {}, children: UINode[] = []) =>\n ui.node(\"listItem\", props, children),\n};\n"]}
@@ -0,0 +1,27 @@
1
+ import { j as UIContract, k as UINode } from './types-Dz90sNcc.js';
2
+ export { a as UIAlign, e as UIColor, l as UIEvent, b as UIJustify, d as UIOrientation, i as UIRadius, h as UIShadow, U as UISize, f as UISpacing, g as UIWidth, c as UIWrap } from './types-Dz90sNcc.js';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+ import React, { ReactNode } from 'react';
5
+ import 'melony';
6
+
7
+ type MelonyComponents = {
8
+ [K in keyof UIContract]: React.ComponentType<UIContract[K] & {
9
+ children?: ReactNode;
10
+ }>;
11
+ };
12
+ interface MelonyUIContextValue {
13
+ components: Partial<MelonyComponents>;
14
+ }
15
+ interface MelonyUIProviderProps {
16
+ components: Partial<MelonyComponents>;
17
+ children: ReactNode;
18
+ }
19
+ declare function MelonyUIProvider({ components, children }: MelonyUIProviderProps): react_jsx_runtime.JSX.Element;
20
+ declare function useMelonyUI(): MelonyUIContextValue;
21
+
22
+ interface MelonyRendererProps {
23
+ node: UINode;
24
+ }
25
+ declare function MelonyRenderer({ node }: MelonyRendererProps): react_jsx_runtime.JSX.Element;
26
+
27
+ export { type MelonyComponents, MelonyRenderer, type MelonyRendererProps, type MelonyUIContextValue, MelonyUIProvider, type MelonyUIProviderProps, UIContract, UINode, useMelonyUI };
package/dist/client.js ADDED
@@ -0,0 +1,3 @@
1
+ export { MelonyRenderer, MelonyUIProvider, useMelonyUI } from './chunk-7YJBGUKN.js';
2
+ //# sourceMappingURL=client.js.map
3
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"client.js"}
@@ -0,0 +1,6 @@
1
+ export { ui } from './server.js';
2
+ export { a as UIAlign, e as UIColor, j as UIContract, l as UIEvent, b as UIJustify, k as UINode, d as UIOrientation, i as UIRadius, h as UIShadow, U as UISize, f as UISpacing, g as UIWidth, c as UIWrap } from './types-Dz90sNcc.js';
3
+ export { MelonyComponents, MelonyRenderer, MelonyRendererProps, MelonyUIContextValue, MelonyUIProvider, MelonyUIProviderProps, useMelonyUI } from './client.js';
4
+ import 'melony';
5
+ import 'react/jsx-runtime';
6
+ import 'react';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { MelonyRenderer, MelonyUIProvider, useMelonyUI } from './chunk-7YJBGUKN.js';
2
+ export { ui } from './chunk-FAENZMHH.js';
3
+ //# sourceMappingURL=index.js.map
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,37 @@
1
+ import { j as UIContract, k as UINode, l as UIEvent } from './types-Dz90sNcc.js';
2
+ export { a as UIAlign, e as UIColor, b as UIJustify, d as UIOrientation, i as UIRadius, h as UIShadow, U as UISize, f as UISpacing, g as UIWidth, c as UIWrap } from './types-Dz90sNcc.js';
3
+ import 'melony';
4
+
5
+ /**
6
+ * Helper to create UI events in Melony actions.
7
+ */
8
+ declare const ui: {
9
+ /**
10
+ * Creates a UI node.
11
+ */
12
+ node: <T extends keyof UIContract>(type: T, props?: UIContract[T], children?: UINode<any>[]) => UINode<T>;
13
+ /**
14
+ * Wraps a UI node in an event.
15
+ */
16
+ event: (node: UINode) => UIEvent;
17
+ card: (props?: UIContract["card"], children?: UINode[]) => UINode<"card">;
18
+ button: (props: UIContract["button"], children?: UINode[]) => UINode<"button">;
19
+ text: (value: string, props?: Partial<UIContract["text"]>) => UINode<"text">;
20
+ heading: (value: string, level?: UIContract["heading"]["level"], props?: Partial<UIContract["heading"]>) => UINode<"heading">;
21
+ row: (props?: UIContract["row"], children?: UINode[]) => UINode<"row">;
22
+ col: (props?: UIContract["col"], children?: UINode[]) => UINode<"col">;
23
+ badge: (label: string, variant?: UIContract["badge"]["variant"], props?: Partial<UIContract["badge"]>) => UINode<"badge">;
24
+ input: (name: string, label?: string, props?: Partial<UIContract["input"]>) => UINode<"input">;
25
+ textarea: (name: string, label?: string, props?: Partial<UIContract["textarea"]>) => UINode<"textarea">;
26
+ select: (name: string, options: UIContract["select"]["options"], label?: string, props?: Partial<UIContract["select"]>) => UINode<"select">;
27
+ checkbox: (name: string, label?: string, props?: Partial<UIContract["checkbox"]>) => UINode<"checkbox">;
28
+ form: (props?: UIContract["form"], children?: UINode[]) => UINode<"form">;
29
+ icon: (name: string, props?: Partial<UIContract["icon"]>) => UINode<"icon">;
30
+ image: (src: string, alt?: string, props?: Partial<UIContract["image"]>) => UINode<"image">;
31
+ spacer: (props?: UIContract["spacer"]) => UINode<"spacer">;
32
+ divider: (props?: UIContract["divider"]) => UINode<"divider">;
33
+ list: (props?: UIContract["list"], children?: UINode[]) => UINode<"list">;
34
+ listItem: (props?: UIContract["listItem"], children?: UINode[]) => UINode<"listItem">;
35
+ };
36
+
37
+ export { UIContract, UIEvent, UINode, ui };
package/dist/server.js ADDED
@@ -0,0 +1,3 @@
1
+ export { ui } from './chunk-FAENZMHH.js';
2
+ //# sourceMappingURL=server.js.map
3
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"server.js"}
@@ -0,0 +1,269 @@
1
+ import { Event } from 'melony';
2
+
3
+ type UISize = "sm" | "md" | "lg";
4
+ type UIAlign = "start" | "center" | "end" | "stretch";
5
+ type UIJustify = "start" | "center" | "end" | "between" | "around";
6
+ type UIWrap = "nowrap" | "wrap" | "wrap-reverse";
7
+ type UIOrientation = "horizontal" | "vertical";
8
+ type UIColor = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "background" | "foreground" | "muted" | "mutedForeground" | "border" | "transparent";
9
+ type UISpacing = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
10
+ type UIWidth = "auto" | "full" | "min" | "max" | "1/2" | "1/3" | "2/3" | "1/4" | "3/4";
11
+ type UIShadow = "none" | "sm" | "md" | "lg" | "xl";
12
+ type UIRadius = "none" | "sm" | "md" | "lg" | "full";
13
+ /**
14
+ * UI Component Contracts
15
+ * This acts as the source of truth for the SDUI protocol.
16
+ */
17
+ interface UIContract {
18
+ card: {
19
+ title?: string;
20
+ subtitle?: string;
21
+ background?: UIColor;
22
+ padding?: UISpacing;
23
+ radius?: UIRadius;
24
+ shadow?: UIShadow;
25
+ streaming?: boolean;
26
+ group?: boolean;
27
+ };
28
+ row: {
29
+ align?: UIAlign;
30
+ justify?: UIJustify;
31
+ wrap?: UIWrap;
32
+ gap?: UISpacing;
33
+ padding?: UISpacing;
34
+ width?: UIWidth;
35
+ group?: boolean;
36
+ };
37
+ col: {
38
+ align?: UIAlign;
39
+ justify?: UIJustify;
40
+ gap?: UISpacing;
41
+ width?: UIWidth;
42
+ height?: "auto" | "full";
43
+ padding?: UISpacing;
44
+ background?: UIColor;
45
+ radius?: UIRadius;
46
+ group?: boolean;
47
+ };
48
+ box: {
49
+ padding?: UISpacing;
50
+ margin?: UISpacing;
51
+ background?: UIColor;
52
+ border?: boolean;
53
+ borderColor?: UIColor;
54
+ radius?: UIRadius;
55
+ width?: UIWidth;
56
+ height?: "auto" | "full";
57
+ shadow?: UIShadow;
58
+ group?: boolean;
59
+ };
60
+ spacer: {
61
+ size?: UISpacing;
62
+ direction?: UIOrientation;
63
+ };
64
+ divider: {
65
+ orientation?: UIOrientation;
66
+ color?: UIColor;
67
+ margin?: UISpacing;
68
+ };
69
+ text: {
70
+ value: string;
71
+ size?: UISpacing;
72
+ weight?: "normal" | "medium" | "semibold" | "bold";
73
+ color?: UIColor;
74
+ align?: UIAlign;
75
+ };
76
+ heading: {
77
+ value: string;
78
+ level?: 1 | 2 | 3 | 4 | 5 | 6;
79
+ color?: UIColor;
80
+ align?: UIAlign;
81
+ };
82
+ badge: {
83
+ label: string;
84
+ variant?: "primary" | "secondary" | "success" | "danger" | "warning" | "outline";
85
+ size?: UISize;
86
+ };
87
+ image: {
88
+ src: string;
89
+ alt?: string;
90
+ width?: UIWidth;
91
+ height?: string | number;
92
+ radius?: UIRadius;
93
+ objectFit?: "cover" | "contain" | "fill";
94
+ groupId?: string;
95
+ };
96
+ video: {
97
+ src: string;
98
+ poster?: string;
99
+ autoPlay?: boolean;
100
+ controls?: boolean;
101
+ loop?: boolean;
102
+ muted?: boolean;
103
+ aspectRatio?: "16/9" | "4/3" | "1/1" | "9/16";
104
+ width?: UIWidth;
105
+ height?: string | number;
106
+ radius?: UIRadius;
107
+ };
108
+ icon: {
109
+ name: string;
110
+ size?: UISize | number;
111
+ color?: UIColor;
112
+ };
113
+ chart: {
114
+ data: Array<{
115
+ label: string;
116
+ value: number;
117
+ color?: string;
118
+ }>;
119
+ chartType?: "bar" | "line" | "area" | "pie";
120
+ title?: string;
121
+ height?: number;
122
+ showValues?: boolean;
123
+ showGrid?: boolean;
124
+ showTooltips?: boolean;
125
+ };
126
+ list: {
127
+ padding?: UISpacing;
128
+ gap?: UISpacing;
129
+ };
130
+ listItem: {
131
+ onClickAction?: Event;
132
+ gap?: UISpacing;
133
+ padding?: UISpacing;
134
+ background?: UIColor;
135
+ radius?: UIRadius;
136
+ };
137
+ form: {
138
+ onSubmitAction?: Event | ((data: any) => Event);
139
+ gap?: UISpacing;
140
+ };
141
+ input: {
142
+ name: string;
143
+ label?: string;
144
+ placeholder?: string;
145
+ defaultValue?: string;
146
+ inputType?: "text" | "password" | "email" | "number" | "tel" | "url";
147
+ onChangeAction?: Event;
148
+ disabled?: boolean;
149
+ required?: boolean;
150
+ width?: UIWidth;
151
+ };
152
+ textarea: {
153
+ name: string;
154
+ label?: string;
155
+ placeholder?: string;
156
+ defaultValue?: string;
157
+ rows?: number;
158
+ onChangeAction?: Event;
159
+ disabled?: boolean;
160
+ required?: boolean;
161
+ width?: UIWidth;
162
+ };
163
+ select: {
164
+ name: string;
165
+ label?: string;
166
+ options: Array<{
167
+ label: string;
168
+ value: string;
169
+ }>;
170
+ defaultValue?: string;
171
+ placeholder?: string;
172
+ onChangeAction?: Event;
173
+ disabled?: boolean;
174
+ required?: boolean;
175
+ width?: UIWidth;
176
+ };
177
+ checkbox: {
178
+ name: string;
179
+ label?: string;
180
+ checked?: boolean;
181
+ onChangeAction?: Event;
182
+ disabled?: boolean;
183
+ };
184
+ hidden: {
185
+ name: string;
186
+ value: string;
187
+ };
188
+ radioGroup: {
189
+ name: string;
190
+ options: Array<{
191
+ label: string;
192
+ value: string;
193
+ disabled?: boolean;
194
+ }>;
195
+ label?: string;
196
+ defaultValue?: string;
197
+ orientation?: UIOrientation;
198
+ onChangeAction?: Event;
199
+ disabled?: boolean;
200
+ };
201
+ label: {
202
+ value: string;
203
+ htmlFor?: string;
204
+ required?: boolean;
205
+ size?: UISpacing;
206
+ color?: UIColor;
207
+ };
208
+ colorPicker: {
209
+ name: string;
210
+ label?: string;
211
+ defaultValue?: string;
212
+ onChangeAction?: Event;
213
+ disabled?: boolean;
214
+ };
215
+ upload: {
216
+ label?: string;
217
+ multiple?: boolean;
218
+ accept?: string;
219
+ initialFiles?: {
220
+ name: string;
221
+ url: string;
222
+ }[];
223
+ onUploadAction?: Event | ((data: any) => Event);
224
+ mode?: "append" | "replace";
225
+ disabled?: boolean;
226
+ };
227
+ button: {
228
+ type?: "button" | "submit" | "reset";
229
+ label: string;
230
+ variant?: "primary" | "secondary" | "success" | "danger" | "outline" | "ghost" | "link";
231
+ size?: UISize;
232
+ disabled?: boolean;
233
+ width?: UIWidth;
234
+ onClickAction?: Event;
235
+ };
236
+ float: {
237
+ position?: "top-left" | "top-right" | "top-center" | "bottom-left" | "bottom-right" | "bottom-center" | "center" | "left-center" | "right-center";
238
+ offsetX?: UISpacing;
239
+ offsetY?: UISpacing;
240
+ showOnHover?: boolean;
241
+ };
242
+ dropdown: {
243
+ items: Array<{
244
+ label: string;
245
+ icon?: string;
246
+ onClickAction?: Event;
247
+ }>;
248
+ className?: string;
249
+ triggerClassName?: string;
250
+ };
251
+ thread: {
252
+ placeholder?: string;
253
+ messages?: any[];
254
+ autoFocus?: boolean;
255
+ };
256
+ }
257
+ type UINode<T extends keyof UIContract = keyof UIContract> = {
258
+ type: T;
259
+ props?: UIContract[T];
260
+ children?: UINode<any>[];
261
+ };
262
+ /**
263
+ * Standard UI event type for Melony.
264
+ */
265
+ interface UIEvent extends Event<UINode> {
266
+ type: "ui";
267
+ }
268
+
269
+ export type { UISize as U, UIAlign as a, UIJustify as b, UIWrap as c, UIOrientation as d, UIColor as e, UISpacing as f, UIWidth as g, UIShadow as h, UIRadius as i, UIContract as j, UINode as k, UIEvent as l };
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@melony/ui-kit",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./server": {
15
+ "types": "./dist/server.d.ts",
16
+ "import": "./dist/server.js",
17
+ "default": "./dist/server.js"
18
+ },
19
+ "./client": {
20
+ "types": "./dist/client.d.ts",
21
+ "import": "./dist/client.js",
22
+ "default": "./dist/client.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "peerDependencies": {
29
+ "react": "^18.0.0 || ^19.0.0",
30
+ "react-dom": "^18.0.0 || ^19.0.0",
31
+ "melony": "0.2.3"
32
+ },
33
+ "devDependencies": {
34
+ "react": "^19.0.0",
35
+ "react-dom": "^19.0.0",
36
+ "@types/react": "^19.0.0",
37
+ "@types/react-dom": "^19.0.0",
38
+ "tsup": "^8.3.0",
39
+ "typescript": "^5.5.4",
40
+ "rimraf": "^5.0.10",
41
+ "@types/node": "^20.14.10",
42
+ "melony": "0.2.3"
43
+ },
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
47
+ "scripts": {
48
+ "build": "tsup",
49
+ "dev": "tsup --watch",
50
+ "clean": "rimraf dist",
51
+ "typecheck": "tsc --noEmit"
52
+ }
53
+ }