kaplay-plugin-ui 1.0.0 → 1.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/README.md +61 -24
- package/dist/plugin.cjs +50 -131
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +185 -66
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.mts +185 -66
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +51 -130
- package/dist/plugin.mjs.map +1 -1
- package/dist/plugin.umd.js +50 -131
- package/dist/plugin.umd.js.map +1 -1
- package/dist/plugin.umd.min.js +1 -1
- package/dist/plugin.umd.min.js.map +1 -1
- package/global.d.ts +53 -2
- package/package.json +2 -2
package/dist/plugin.mjs
CHANGED
|
@@ -1,92 +1,35 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const comp = {
|
|
12
|
-
id: "button",
|
|
13
|
-
get text() {
|
|
14
|
-
return currentText;
|
|
15
|
-
},
|
|
16
|
-
set text(value) {
|
|
17
|
-
currentText = value;
|
|
18
|
-
},
|
|
19
|
-
get width() {
|
|
20
|
-
return readWidth();
|
|
21
|
-
},
|
|
22
|
-
set width(value) {
|
|
23
|
-
currentOpt.width = value;
|
|
24
|
-
},
|
|
25
|
-
get height() {
|
|
26
|
-
return readHeight();
|
|
27
|
-
},
|
|
28
|
-
set height(value) {
|
|
29
|
-
currentOpt.height = value;
|
|
30
|
-
},
|
|
31
|
-
renderArea() {
|
|
32
|
-
return new k.Rect(k.vec2(), comp.width, comp.height);
|
|
33
|
-
},
|
|
34
|
-
setStyle(next) {
|
|
35
|
-
currentOpt = {
|
|
36
|
-
...currentOpt,
|
|
37
|
-
...next
|
|
38
|
-
};
|
|
39
|
-
},
|
|
40
|
-
add() {},
|
|
41
|
-
draw() {
|
|
42
|
-
const width = comp.width;
|
|
43
|
-
const height = comp.height;
|
|
44
|
-
const radius = currentOpt.radius ?? theme.shape.borderRadius;
|
|
45
|
-
const fill = currentOpt.fill ?? theme.palette.primary;
|
|
46
|
-
const textColor = currentOpt.textColor ?? theme.palette.text;
|
|
47
|
-
const size = currentOpt.size ?? theme.typography.fontSize;
|
|
48
|
-
const font = currentOpt.font ?? theme.typography.fontFamily;
|
|
49
|
-
const drawRect = k.drawRect;
|
|
50
|
-
drawRect?.({
|
|
51
|
-
pos: k.vec2(),
|
|
52
|
-
width,
|
|
53
|
-
height,
|
|
54
|
-
color: fill,
|
|
55
|
-
radius
|
|
56
|
-
});
|
|
57
|
-
const drawText = k.drawText;
|
|
58
|
-
drawText?.({
|
|
59
|
-
text: currentText,
|
|
60
|
-
pos: k.vec2(width / 2, height / 2),
|
|
61
|
-
size,
|
|
62
|
-
font,
|
|
63
|
-
color: textColor,
|
|
64
|
-
anchor: "center"
|
|
65
|
-
});
|
|
66
|
-
},
|
|
67
|
-
destroy() {}
|
|
68
|
-
};
|
|
69
|
-
return comp;
|
|
1
|
+
// src/utils.ts
|
|
2
|
+
/**
|
|
3
|
+
* Convert hex string to color or return color.
|
|
4
|
+
*
|
|
5
|
+
* @param k - The Kaplay context.
|
|
6
|
+
* @param color - The hex string or color.
|
|
7
|
+
* @returns The color.
|
|
8
|
+
*/
|
|
9
|
+
function toColor(k, color) {
|
|
10
|
+
return typeof color === "string" ? k.rgb(color) : color;
|
|
70
11
|
}
|
|
71
|
-
|
|
12
|
+
// src/button.ts
|
|
13
|
+
function createButton(k, theme, text, opt) {
|
|
72
14
|
const width = opt.width ?? theme.components.button.width;
|
|
73
15
|
const height = opt.height ?? theme.components.button.height;
|
|
74
16
|
const radius = opt.radius ?? theme.shape.borderRadius;
|
|
75
|
-
const baseColor = opt.color ?? opt.fill ?? theme.palette.primary;
|
|
76
|
-
const hoverColor = opt.hoverColor ?? theme.palette.hover;
|
|
77
|
-
const pressedColor = opt.pressedColor ?? theme.palette.pressed;
|
|
78
|
-
const textColor = opt.textColor ?? theme.palette.text;
|
|
17
|
+
const baseColor = toColor(k, opt.color ?? opt.fill ?? theme.palette.primary);
|
|
18
|
+
const hoverColor = toColor(k, opt.hoverColor ?? theme.palette.hover);
|
|
19
|
+
const pressedColor = toColor(k, opt.pressedColor ?? theme.palette.pressed);
|
|
20
|
+
const textColor = toColor(k, opt.textColor ?? theme.palette.text);
|
|
79
21
|
const size = opt.size ?? theme.typography.fontSize;
|
|
80
22
|
const font = opt.font ?? theme.typography.fontFamily;
|
|
81
23
|
const pos = opt.pos ?? k.vec2();
|
|
82
|
-
const
|
|
24
|
+
const button = k.add([
|
|
83
25
|
k.rect(width, height, radius > 0 ? { radius } : void 0),
|
|
84
26
|
k.pos(pos),
|
|
85
27
|
k.area(),
|
|
28
|
+
k.scale(),
|
|
86
29
|
k.color(baseColor),
|
|
87
30
|
k.anchor("center")
|
|
88
31
|
]);
|
|
89
|
-
const label =
|
|
32
|
+
const label = button.add([
|
|
90
33
|
k.text(text, {
|
|
91
34
|
size,
|
|
92
35
|
font
|
|
@@ -94,57 +37,39 @@ function createButtonObject(k, theme, text, opt) {
|
|
|
94
37
|
k.color(textColor),
|
|
95
38
|
k.anchor("center")
|
|
96
39
|
]);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
obj.onClick(() => {
|
|
100
|
-
obj.color = pressedColor;
|
|
40
|
+
button.onClick(() => {
|
|
41
|
+
button.color = toColor(k, pressedColor);
|
|
101
42
|
opt.onClick?.();
|
|
102
43
|
});
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
44
|
+
button.onHover(() => {
|
|
45
|
+
button.color = toColor(k, hoverColor);
|
|
46
|
+
button.scale = k.vec2(1.05, 1.05);
|
|
106
47
|
k.setCursor("pointer");
|
|
107
48
|
});
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
49
|
+
button.onHoverEnd(() => {
|
|
50
|
+
button.color = baseColor;
|
|
51
|
+
button.scale = k.vec2(1, 1);
|
|
111
52
|
k.setCursor("default");
|
|
112
53
|
});
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
};
|
|
117
|
-
obj.setButtonColor = (color) => {
|
|
118
|
-
currentColor = color;
|
|
119
|
-
obj.color = color;
|
|
120
|
-
};
|
|
121
|
-
obj.setButtonText = (value) => {
|
|
122
|
-
currentText = value;
|
|
123
|
-
label.text = value;
|
|
124
|
-
};
|
|
125
|
-
obj.setButtonTextSize = (value) => {
|
|
126
|
-
label.textSize = value;
|
|
127
|
-
};
|
|
128
|
-
obj.setPosition = (x, y) => {
|
|
129
|
-
obj.pos = k.vec2(x, y);
|
|
54
|
+
return {
|
|
55
|
+
...button,
|
|
56
|
+
label
|
|
130
57
|
};
|
|
131
|
-
label.text = currentText;
|
|
132
|
-
return obj;
|
|
133
58
|
}
|
|
134
59
|
// src/theme.ts
|
|
135
|
-
const
|
|
136
|
-
const
|
|
137
|
-
/** Default theme
|
|
138
|
-
const
|
|
60
|
+
const PRIMARY = "#4f8cff";
|
|
61
|
+
const TEXT = "#ffffff";
|
|
62
|
+
/** Default theme. */
|
|
63
|
+
const theme = {
|
|
139
64
|
palette: {
|
|
140
|
-
primary:
|
|
141
|
-
secondary:
|
|
65
|
+
primary: PRIMARY,
|
|
66
|
+
secondary: PRIMARY,
|
|
142
67
|
background: "#111827",
|
|
143
68
|
surface: "#1f2937",
|
|
144
|
-
text:
|
|
145
|
-
textSecondary:
|
|
146
|
-
hover:
|
|
147
|
-
pressed:
|
|
69
|
+
text: TEXT,
|
|
70
|
+
textSecondary: TEXT,
|
|
71
|
+
hover: PRIMARY,
|
|
72
|
+
pressed: PRIMARY,
|
|
148
73
|
disabled: "#6b7280",
|
|
149
74
|
error: "#ef4444"
|
|
150
75
|
},
|
|
@@ -171,7 +96,7 @@ const defaultTheme = {
|
|
|
171
96
|
},
|
|
172
97
|
tooltip: {
|
|
173
98
|
background: "#111827",
|
|
174
|
-
textColor:
|
|
99
|
+
textColor: TEXT,
|
|
175
100
|
delay: 300
|
|
176
101
|
}
|
|
177
102
|
}
|
|
@@ -180,30 +105,30 @@ const defaultTheme = {
|
|
|
180
105
|
function resolveTheme(input) {
|
|
181
106
|
return {
|
|
182
107
|
palette: {
|
|
183
|
-
...
|
|
108
|
+
...theme.palette,
|
|
184
109
|
...input?.palette
|
|
185
110
|
},
|
|
186
111
|
typography: {
|
|
187
|
-
...
|
|
112
|
+
...theme.typography,
|
|
188
113
|
...input?.typography
|
|
189
114
|
},
|
|
190
115
|
shape: {
|
|
191
|
-
...
|
|
116
|
+
...theme.shape,
|
|
192
117
|
...input?.shape
|
|
193
118
|
},
|
|
194
|
-
spacing: input?.spacing ??
|
|
119
|
+
spacing: input?.spacing ?? theme.spacing,
|
|
195
120
|
components: {
|
|
196
121
|
button: {
|
|
197
|
-
...
|
|
122
|
+
...theme.components.button,
|
|
198
123
|
...input?.components?.button,
|
|
199
|
-
width: input?.components?.button?.width ?? input?.components?.button?.minWidth ??
|
|
124
|
+
width: input?.components?.button?.width ?? input?.components?.button?.minWidth ?? theme.components.button.width
|
|
200
125
|
},
|
|
201
126
|
modal: {
|
|
202
|
-
...
|
|
127
|
+
...theme.components.modal,
|
|
203
128
|
...input?.components?.modal
|
|
204
129
|
},
|
|
205
130
|
tooltip: {
|
|
206
|
-
...
|
|
131
|
+
...theme.components.tooltip,
|
|
207
132
|
...input?.components?.tooltip
|
|
208
133
|
}
|
|
209
134
|
}
|
|
@@ -222,19 +147,15 @@ function uiPlugin(k, theme = {}) {
|
|
|
222
147
|
};
|
|
223
148
|
currentTheme = resolveTheme(userTheme);
|
|
224
149
|
};
|
|
225
|
-
const button = (text = "", opt = {}) => {
|
|
226
|
-
return createButtonComponent(k, currentTheme, text, opt);
|
|
227
|
-
};
|
|
228
150
|
const addButton = (text = "", opt = {}) => {
|
|
229
|
-
return
|
|
151
|
+
return createButton(k, currentTheme, text, opt);
|
|
230
152
|
};
|
|
231
153
|
return {
|
|
232
|
-
button,
|
|
233
154
|
addButton,
|
|
234
155
|
setTheme,
|
|
235
156
|
getTheme
|
|
236
157
|
};
|
|
237
158
|
}
|
|
238
|
-
export {
|
|
159
|
+
export { uiPlugin };
|
|
239
160
|
|
|
240
161
|
//# sourceMappingURL=plugin.mjs.map
|
package/dist/plugin.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.mjs","names":[],"sources":["../src/button.ts","../src/theme.ts","../src/plugin.ts"],"sourcesContent":["import type { Comp, GameObj, KAPLAYCtx, Vec2 } from 'kaplay';\n\nimport type { ButtonComp, ButtonCompOpt, Color, Theme } from './types';\n\nexport function createButtonComponent(\n k: KAPLAYCtx,\n theme: Theme,\n text: string,\n opt: ButtonCompOpt,\n): ButtonComp {\n let currentText = text;\n let currentOpt: ButtonCompOpt = { ...opt };\n\n const readWidth = (): number => {\n return currentOpt.width ?? theme.components.button.width;\n };\n\n const readHeight = (): number => {\n return currentOpt.height ?? theme.components.button.height;\n };\n\n const comp: ButtonComp = {\n id: 'button',\n get text() {\n return currentText;\n },\n set text(value: string) {\n currentText = value;\n },\n get width() {\n return readWidth();\n },\n set width(value: number) {\n currentOpt.width = value;\n },\n get height() {\n return readHeight();\n },\n set height(value: number) {\n currentOpt.height = value;\n },\n renderArea() {\n return new k.Rect(k.vec2(), comp.width, comp.height);\n },\n setStyle(next: Partial<ButtonCompOpt>): void {\n currentOpt = { ...currentOpt, ...next };\n },\n add(): void {\n // No-op: rendering is handled in draw().\n },\n draw(): void {\n const width = comp.width;\n const height = comp.height;\n const radius = currentOpt.radius ?? theme.shape.borderRadius;\n const fill = currentOpt.fill ?? theme.palette.primary;\n const textColor = currentOpt.textColor ?? theme.palette.text;\n const size = currentOpt.size ?? theme.typography.fontSize;\n const font = currentOpt.font ?? theme.typography.fontFamily;\n\n const drawRect = k.drawRect as unknown as\n ((opt: Record<string, unknown>) => void) | undefined;\n drawRect?.({\n pos: k.vec2(),\n width,\n height,\n color: fill,\n radius,\n });\n\n const drawText = k.drawText as unknown as\n ((opt: Record<string, unknown>) => void) | undefined;\n drawText?.({\n text: currentText,\n pos: k.vec2(width / 2, height / 2),\n size,\n font,\n color: textColor,\n anchor: 'center',\n });\n },\n destroy(): void {\n // No resources to release.\n },\n };\n\n return comp;\n}\n\nexport function createButtonObject(\n k: KAPLAYCtx,\n theme: Theme,\n text: string,\n opt: ButtonCompOpt & {\n pos?: Vec2;\n onClick?: () => void;\n color?: Color;\n hoverColor?: Color;\n pressedColor?: Color;\n textColor?: Color;\n },\n): GameObj {\n const width = opt.width ?? theme.components.button.width;\n const height = opt.height ?? theme.components.button.height;\n const radius = opt.radius ?? theme.shape.borderRadius;\n const baseColor = opt.color ?? opt.fill ?? theme.palette.primary;\n const hoverColor = opt.hoverColor ?? theme.palette.hover;\n const pressedColor = opt.pressedColor ?? theme.palette.pressed;\n const textColor = opt.textColor ?? theme.palette.text;\n const size = opt.size ?? theme.typography.fontSize;\n const font = opt.font ?? theme.typography.fontFamily;\n const pos = opt.pos ?? k.vec2();\n\n interface ButtonGameObj {\n add: (comps: Comp[]) => { text: string; textSize: number };\n onClick: (cb: () => void) => void;\n onHover: (cb: () => void) => void;\n onHoverEnd: (cb: () => void) => void;\n width: number;\n height: number;\n color: unknown;\n scale: { x: number; y: number };\n pos: { x: number; y: number };\n setSize: (w: number, h: number) => void;\n setButtonColor: (color: Color) => void;\n setButtonText: (value: string) => void;\n setButtonTextSize: (value: number) => void;\n setPosition: (x: number, y: number) => void;\n }\n\n const obj = k.add([\n k.rect(width, height, radius > 0 ? { radius } : undefined),\n k.pos(pos as never),\n k.area(),\n k.color(baseColor as never),\n k.anchor('center'),\n ]) as unknown as ButtonGameObj;\n\n const label = obj.add([\n k.text(text, { size, font }),\n k.color(textColor as never),\n k.anchor('center'),\n ]) as GameObj & { text: string; textSize: number };\n\n let currentText = text;\n let currentColor: Color = baseColor;\n\n obj.onClick(() => {\n obj.color = pressedColor;\n opt.onClick?.();\n });\n obj.onHover(() => {\n obj.color = hoverColor;\n obj.scale = k.vec2(1.05, 1.05);\n k.setCursor('pointer');\n });\n obj.onHoverEnd(() => {\n obj.color = currentColor;\n obj.scale = k.vec2(1, 1);\n k.setCursor('default');\n });\n\n obj.setSize = (w: number, h: number): void => {\n obj.width = w;\n obj.height = h;\n };\n\n obj.setButtonColor = (color: Color): void => {\n currentColor = color;\n obj.color = color;\n };\n\n obj.setButtonText = (value: string): void => {\n currentText = value;\n label.text = value;\n };\n\n obj.setButtonTextSize = (value: number): void => {\n label.textSize = value;\n };\n\n obj.setPosition = (x: number, y: number): void => {\n obj.pos = k.vec2(x, y);\n };\n\n label.text = currentText;\n\n return obj as unknown as GameObj;\n}\n","import type { DeepPartial, Theme } from './types';\n\nconst DEFAULT_PRIMARY = '#4f8cff';\nconst DEFAULT_TEXT = '#ffffff';\n\n/** Default theme used when no theme is provided. */\nexport const defaultTheme: Theme = {\n palette: {\n primary: DEFAULT_PRIMARY,\n secondary: DEFAULT_PRIMARY,\n background: '#111827',\n surface: '#1f2937',\n text: DEFAULT_TEXT,\n textSecondary: DEFAULT_TEXT,\n hover: DEFAULT_PRIMARY,\n pressed: DEFAULT_PRIMARY,\n disabled: '#6b7280',\n error: '#ef4444',\n },\n typography: {\n fontFamily: 'sans-serif',\n fontSize: 18,\n fontWeight: 400,\n lineHeight: 1.2,\n },\n shape: {\n borderRadius: 0,\n },\n spacing: 8,\n components: {\n button: {\n width: 120,\n height: 40,\n minWidth: 120,\n paddingX: 12,\n paddingY: 8,\n textTransform: 'none',\n },\n modal: {\n backdropOpacity: 0.5,\n borderRadius: 8,\n },\n tooltip: {\n background: '#111827',\n textColor: DEFAULT_TEXT,\n delay: 300,\n },\n },\n};\n\n/** Resolve a partial theme into a fully resolved theme. */\nexport function resolveTheme(input?: DeepPartial<Theme>): Theme {\n return {\n palette: { ...defaultTheme.palette, ...input?.palette },\n typography: { ...defaultTheme.typography, ...input?.typography },\n shape: { ...defaultTheme.shape, ...input?.shape },\n spacing: input?.spacing ?? defaultTheme.spacing,\n components: {\n button: {\n ...defaultTheme.components.button,\n ...input?.components?.button,\n width:\n input?.components?.button?.width ??\n input?.components?.button?.minWidth ??\n defaultTheme.components.button.width,\n },\n modal: {\n ...defaultTheme.components.modal,\n ...input?.components?.modal,\n },\n tooltip: {\n ...defaultTheme.components.tooltip,\n ...input?.components?.tooltip,\n },\n },\n };\n}\n","import type { GameObj, KAPLAYCtx, Vec2 } from 'kaplay';\n\nimport { createButtonComponent, createButtonObject } from './button';\nimport { resolveTheme } from './theme';\nimport type {\n ButtonComp,\n ButtonCompOpt,\n Color,\n DeepPartial,\n Theme,\n} from './types';\n\nexport { createButtonComponent, createButtonObject } from './button';\nexport type { ButtonComp, ButtonCompOpt, Color, Theme } from './types';\n\ndeclare module 'kaplay' {\n interface KAPLAYCtx {\n button: (text?: string, opt?: ButtonCompOpt) => ButtonComp;\n addButton: (\n text?: string,\n opt?: ButtonCompOpt & {\n pos?: Vec2;\n onClick?: () => void;\n color?: Color;\n hoverColor?: Color;\n pressedColor?: Color;\n textColor?: Color;\n },\n ) => GameObj;\n setTheme: (theme: DeepPartial<Theme>) => void;\n getTheme: () => Theme;\n }\n}\n\n/** KAPLAY UI plugin. */\nexport function uiPlugin(k: KAPLAYCtx, theme: DeepPartial<Theme> = {}) {\n let userTheme: DeepPartial<Theme> = theme;\n let currentTheme: Theme = resolveTheme(userTheme);\n\n const getTheme = (): Theme => currentTheme;\n\n const setTheme = (next: DeepPartial<Theme>): void => {\n userTheme = { ...userTheme, ...next };\n currentTheme = resolveTheme(userTheme);\n };\n\n const button = (text = '', opt: ButtonCompOpt = {}): ButtonComp => {\n return createButtonComponent(k, currentTheme, text, opt);\n };\n\n const addButton = (\n text = '',\n opt: ButtonCompOpt & {\n pos?: Vec2;\n onClick?: () => void;\n color?: Color;\n hoverColor?: Color;\n pressedColor?: Color;\n textColor?: Color;\n } = {},\n ): GameObj => {\n return createButtonObject(k, currentTheme, text, opt);\n };\n\n return {\n button,\n addButton,\n setTheme,\n getTheme,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin.mjs","names":[],"sources":["../src/utils.ts","../src/button.ts","../src/theme.ts","../src/plugin.ts"],"sourcesContent":["import type { Color, KAPLAYCtx } from 'kaplay';\n\n/**\n * Convert hex string to color or return color.\n *\n * @param k - The Kaplay context.\n * @param color - The hex string or color.\n * @returns The color.\n */\nexport function toColor(k: KAPLAYCtx, color: string | Color): Color {\n return typeof color === 'string' ? k.rgb(color) : color;\n}\n","import type { Color, KAPLAYCtx, Vec2 } from 'kaplay';\n\nimport type { ButtonOpt, Theme } from './types';\nimport { toColor } from './utils';\n\nexport function createButton(\n k: KAPLAYCtx,\n theme: Theme,\n text: string,\n opt: ButtonOpt & {\n pos?: Vec2;\n onClick?: () => void;\n color?: string | Color;\n hoverColor?: string | Color;\n pressedColor?: string | Color;\n textColor?: string | Color;\n },\n) {\n const width = opt.width ?? theme.components.button.width;\n const height = opt.height ?? theme.components.button.height;\n const radius = opt.radius ?? theme.shape.borderRadius;\n const baseColor = toColor(k, opt.color ?? opt.fill ?? theme.palette.primary);\n const hoverColor = toColor(k, opt.hoverColor ?? theme.palette.hover);\n const pressedColor = toColor(k, opt.pressedColor ?? theme.palette.pressed);\n const textColor = toColor(k, opt.textColor ?? theme.palette.text);\n const size = opt.size ?? theme.typography.fontSize;\n const font = opt.font ?? theme.typography.fontFamily;\n const pos = opt.pos ?? k.vec2();\n\n const button = k.add([\n k.rect(width, height, radius > 0 ? { radius } : undefined),\n k.pos(pos),\n k.area(),\n k.scale(),\n k.color(baseColor),\n k.anchor('center'),\n ]);\n\n const label = button.add([\n k.text(text, { size, font }),\n k.color(textColor as never),\n k.anchor('center'),\n ]);\n\n button.onClick(() => {\n button.color = toColor(k, pressedColor);\n opt.onClick?.();\n });\n\n button.onHover(() => {\n button.color = toColor(k, hoverColor);\n button.scale = k.vec2(1.05, 1.05);\n k.setCursor('pointer');\n });\n\n button.onHoverEnd(() => {\n button.color = baseColor;\n button.scale = k.vec2(1, 1);\n k.setCursor('default');\n });\n\n return {\n ...button,\n label,\n };\n}\n","import type { DeepPartial, Theme } from './types';\n\nconst PRIMARY = '#4f8cff';\nconst TEXT = '#ffffff';\n\n/** Default theme. */\nconst theme: Theme = {\n palette: {\n primary: PRIMARY,\n secondary: PRIMARY,\n background: '#111827',\n surface: '#1f2937',\n text: TEXT,\n textSecondary: TEXT,\n hover: PRIMARY,\n pressed: PRIMARY,\n disabled: '#6b7280',\n error: '#ef4444',\n },\n typography: {\n fontFamily: 'sans-serif',\n fontSize: 18,\n fontWeight: 400,\n lineHeight: 1.2,\n },\n shape: {\n borderRadius: 0,\n },\n spacing: 8,\n components: {\n button: {\n width: 120,\n height: 40,\n minWidth: 120,\n paddingX: 12,\n paddingY: 8,\n textTransform: 'none',\n },\n modal: {\n backdropOpacity: 0.5,\n borderRadius: 8,\n },\n tooltip: {\n background: '#111827',\n textColor: TEXT,\n delay: 300,\n },\n },\n};\n\n/** Resolve a partial theme into a fully resolved theme. */\nexport function resolveTheme(input?: DeepPartial<Theme>): Theme {\n return {\n palette: { ...theme.palette, ...input?.palette },\n typography: { ...theme.typography, ...input?.typography },\n shape: { ...theme.shape, ...input?.shape },\n spacing: input?.spacing ?? theme.spacing,\n components: {\n button: {\n ...theme.components.button,\n ...input?.components?.button,\n width:\n input?.components?.button?.width ??\n input?.components?.button?.minWidth ??\n theme.components.button.width,\n },\n modal: {\n ...theme.components.modal,\n ...input?.components?.modal,\n },\n tooltip: {\n ...theme.components.tooltip,\n ...input?.components?.tooltip,\n },\n },\n };\n}\n","import type { KAPLAYCtx } from 'kaplay';\n\nimport { createButton } from './button';\nimport { resolveTheme } from './theme';\nimport type {\n AddButton,\n DeepPartial,\n GetTheme,\n SetTheme,\n Theme,\n} from './types';\n\n/** KAPLAY UI plugin. */\nexport function uiPlugin(k: KAPLAYCtx, theme: DeepPartial<Theme> = {}) {\n let userTheme: DeepPartial<Theme> = theme;\n let currentTheme: Theme = resolveTheme(userTheme);\n\n const getTheme: GetTheme = () => currentTheme;\n\n const setTheme: SetTheme = (next) => {\n userTheme = { ...userTheme, ...next };\n currentTheme = resolveTheme(userTheme);\n };\n\n const addButton: AddButton = (text = '', opt = {}) => {\n return createButton(k, currentTheme, text, opt);\n };\n\n return {\n addButton,\n setTheme,\n getTheme,\n };\n}\n"],"mappings":"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"}
|
package/dist/plugin.umd.js
CHANGED
|
@@ -2,95 +2,38 @@
|
|
|
2
2
|
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.KaplayPluginUI = {}));
|
|
3
3
|
})(this, function(exports) {
|
|
4
4
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
5
|
-
// src/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const comp = {
|
|
16
|
-
id: "button",
|
|
17
|
-
get text() {
|
|
18
|
-
return currentText;
|
|
19
|
-
},
|
|
20
|
-
set text(value) {
|
|
21
|
-
currentText = value;
|
|
22
|
-
},
|
|
23
|
-
get width() {
|
|
24
|
-
return readWidth();
|
|
25
|
-
},
|
|
26
|
-
set width(value) {
|
|
27
|
-
currentOpt.width = value;
|
|
28
|
-
},
|
|
29
|
-
get height() {
|
|
30
|
-
return readHeight();
|
|
31
|
-
},
|
|
32
|
-
set height(value) {
|
|
33
|
-
currentOpt.height = value;
|
|
34
|
-
},
|
|
35
|
-
renderArea() {
|
|
36
|
-
return new k.Rect(k.vec2(), comp.width, comp.height);
|
|
37
|
-
},
|
|
38
|
-
setStyle(next) {
|
|
39
|
-
currentOpt = {
|
|
40
|
-
...currentOpt,
|
|
41
|
-
...next
|
|
42
|
-
};
|
|
43
|
-
},
|
|
44
|
-
add() {},
|
|
45
|
-
draw() {
|
|
46
|
-
const width = comp.width;
|
|
47
|
-
const height = comp.height;
|
|
48
|
-
const radius = currentOpt.radius ?? theme.shape.borderRadius;
|
|
49
|
-
const fill = currentOpt.fill ?? theme.palette.primary;
|
|
50
|
-
const textColor = currentOpt.textColor ?? theme.palette.text;
|
|
51
|
-
const size = currentOpt.size ?? theme.typography.fontSize;
|
|
52
|
-
const font = currentOpt.font ?? theme.typography.fontFamily;
|
|
53
|
-
const drawRect = k.drawRect;
|
|
54
|
-
drawRect?.({
|
|
55
|
-
pos: k.vec2(),
|
|
56
|
-
width,
|
|
57
|
-
height,
|
|
58
|
-
color: fill,
|
|
59
|
-
radius
|
|
60
|
-
});
|
|
61
|
-
const drawText = k.drawText;
|
|
62
|
-
drawText?.({
|
|
63
|
-
text: currentText,
|
|
64
|
-
pos: k.vec2(width / 2, height / 2),
|
|
65
|
-
size,
|
|
66
|
-
font,
|
|
67
|
-
color: textColor,
|
|
68
|
-
anchor: "center"
|
|
69
|
-
});
|
|
70
|
-
},
|
|
71
|
-
destroy() {}
|
|
72
|
-
};
|
|
73
|
-
return comp;
|
|
5
|
+
// src/utils.ts
|
|
6
|
+
/**
|
|
7
|
+
* Convert hex string to color or return color.
|
|
8
|
+
*
|
|
9
|
+
* @param k - The Kaplay context.
|
|
10
|
+
* @param color - The hex string or color.
|
|
11
|
+
* @returns The color.
|
|
12
|
+
*/
|
|
13
|
+
function toColor(k, color) {
|
|
14
|
+
return typeof color === "string" ? k.rgb(color) : color;
|
|
74
15
|
}
|
|
75
|
-
|
|
16
|
+
// src/button.ts
|
|
17
|
+
function createButton(k, theme, text, opt) {
|
|
76
18
|
const width = opt.width ?? theme.components.button.width;
|
|
77
19
|
const height = opt.height ?? theme.components.button.height;
|
|
78
20
|
const radius = opt.radius ?? theme.shape.borderRadius;
|
|
79
|
-
const baseColor = opt.color ?? opt.fill ?? theme.palette.primary;
|
|
80
|
-
const hoverColor = opt.hoverColor ?? theme.palette.hover;
|
|
81
|
-
const pressedColor = opt.pressedColor ?? theme.palette.pressed;
|
|
82
|
-
const textColor = opt.textColor ?? theme.palette.text;
|
|
21
|
+
const baseColor = toColor(k, opt.color ?? opt.fill ?? theme.palette.primary);
|
|
22
|
+
const hoverColor = toColor(k, opt.hoverColor ?? theme.palette.hover);
|
|
23
|
+
const pressedColor = toColor(k, opt.pressedColor ?? theme.palette.pressed);
|
|
24
|
+
const textColor = toColor(k, opt.textColor ?? theme.palette.text);
|
|
83
25
|
const size = opt.size ?? theme.typography.fontSize;
|
|
84
26
|
const font = opt.font ?? theme.typography.fontFamily;
|
|
85
27
|
const pos = opt.pos ?? k.vec2();
|
|
86
|
-
const
|
|
28
|
+
const button = k.add([
|
|
87
29
|
k.rect(width, height, radius > 0 ? { radius } : void 0),
|
|
88
30
|
k.pos(pos),
|
|
89
31
|
k.area(),
|
|
32
|
+
k.scale(),
|
|
90
33
|
k.color(baseColor),
|
|
91
34
|
k.anchor("center")
|
|
92
35
|
]);
|
|
93
|
-
const label =
|
|
36
|
+
const label = button.add([
|
|
94
37
|
k.text(text, {
|
|
95
38
|
size,
|
|
96
39
|
font
|
|
@@ -98,57 +41,39 @@
|
|
|
98
41
|
k.color(textColor),
|
|
99
42
|
k.anchor("center")
|
|
100
43
|
]);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
obj.onClick(() => {
|
|
104
|
-
obj.color = pressedColor;
|
|
44
|
+
button.onClick(() => {
|
|
45
|
+
button.color = toColor(k, pressedColor);
|
|
105
46
|
opt.onClick?.();
|
|
106
47
|
});
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
48
|
+
button.onHover(() => {
|
|
49
|
+
button.color = toColor(k, hoverColor);
|
|
50
|
+
button.scale = k.vec2(1.05, 1.05);
|
|
110
51
|
k.setCursor("pointer");
|
|
111
52
|
});
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
53
|
+
button.onHoverEnd(() => {
|
|
54
|
+
button.color = baseColor;
|
|
55
|
+
button.scale = k.vec2(1, 1);
|
|
115
56
|
k.setCursor("default");
|
|
116
57
|
});
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
};
|
|
121
|
-
obj.setButtonColor = (color) => {
|
|
122
|
-
currentColor = color;
|
|
123
|
-
obj.color = color;
|
|
124
|
-
};
|
|
125
|
-
obj.setButtonText = (value) => {
|
|
126
|
-
currentText = value;
|
|
127
|
-
label.text = value;
|
|
128
|
-
};
|
|
129
|
-
obj.setButtonTextSize = (value) => {
|
|
130
|
-
label.textSize = value;
|
|
131
|
-
};
|
|
132
|
-
obj.setPosition = (x, y) => {
|
|
133
|
-
obj.pos = k.vec2(x, y);
|
|
58
|
+
return {
|
|
59
|
+
...button,
|
|
60
|
+
label
|
|
134
61
|
};
|
|
135
|
-
label.text = currentText;
|
|
136
|
-
return obj;
|
|
137
62
|
}
|
|
138
63
|
// src/theme.ts
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
/** Default theme
|
|
142
|
-
const
|
|
64
|
+
const PRIMARY = "#4f8cff";
|
|
65
|
+
const TEXT = "#ffffff";
|
|
66
|
+
/** Default theme. */
|
|
67
|
+
const theme = {
|
|
143
68
|
palette: {
|
|
144
|
-
primary:
|
|
145
|
-
secondary:
|
|
69
|
+
primary: PRIMARY,
|
|
70
|
+
secondary: PRIMARY,
|
|
146
71
|
background: "#111827",
|
|
147
72
|
surface: "#1f2937",
|
|
148
|
-
text:
|
|
149
|
-
textSecondary:
|
|
150
|
-
hover:
|
|
151
|
-
pressed:
|
|
73
|
+
text: TEXT,
|
|
74
|
+
textSecondary: TEXT,
|
|
75
|
+
hover: PRIMARY,
|
|
76
|
+
pressed: PRIMARY,
|
|
152
77
|
disabled: "#6b7280",
|
|
153
78
|
error: "#ef4444"
|
|
154
79
|
},
|
|
@@ -175,7 +100,7 @@
|
|
|
175
100
|
},
|
|
176
101
|
tooltip: {
|
|
177
102
|
background: "#111827",
|
|
178
|
-
textColor:
|
|
103
|
+
textColor: TEXT,
|
|
179
104
|
delay: 300
|
|
180
105
|
}
|
|
181
106
|
}
|
|
@@ -184,30 +109,30 @@
|
|
|
184
109
|
function resolveTheme(input) {
|
|
185
110
|
return {
|
|
186
111
|
palette: {
|
|
187
|
-
...
|
|
112
|
+
...theme.palette,
|
|
188
113
|
...input?.palette
|
|
189
114
|
},
|
|
190
115
|
typography: {
|
|
191
|
-
...
|
|
116
|
+
...theme.typography,
|
|
192
117
|
...input?.typography
|
|
193
118
|
},
|
|
194
119
|
shape: {
|
|
195
|
-
...
|
|
120
|
+
...theme.shape,
|
|
196
121
|
...input?.shape
|
|
197
122
|
},
|
|
198
|
-
spacing: input?.spacing ??
|
|
123
|
+
spacing: input?.spacing ?? theme.spacing,
|
|
199
124
|
components: {
|
|
200
125
|
button: {
|
|
201
|
-
...
|
|
126
|
+
...theme.components.button,
|
|
202
127
|
...input?.components?.button,
|
|
203
|
-
width: input?.components?.button?.width ?? input?.components?.button?.minWidth ??
|
|
128
|
+
width: input?.components?.button?.width ?? input?.components?.button?.minWidth ?? theme.components.button.width
|
|
204
129
|
},
|
|
205
130
|
modal: {
|
|
206
|
-
...
|
|
131
|
+
...theme.components.modal,
|
|
207
132
|
...input?.components?.modal
|
|
208
133
|
},
|
|
209
134
|
tooltip: {
|
|
210
|
-
...
|
|
135
|
+
...theme.components.tooltip,
|
|
211
136
|
...input?.components?.tooltip
|
|
212
137
|
}
|
|
213
138
|
}
|
|
@@ -226,21 +151,15 @@
|
|
|
226
151
|
};
|
|
227
152
|
currentTheme = resolveTheme(userTheme);
|
|
228
153
|
};
|
|
229
|
-
const button = (text = "", opt = {}) => {
|
|
230
|
-
return createButtonComponent(k, currentTheme, text, opt);
|
|
231
|
-
};
|
|
232
154
|
const addButton = (text = "", opt = {}) => {
|
|
233
|
-
return
|
|
155
|
+
return createButton(k, currentTheme, text, opt);
|
|
234
156
|
};
|
|
235
157
|
return {
|
|
236
|
-
button,
|
|
237
158
|
addButton,
|
|
238
159
|
setTheme,
|
|
239
160
|
getTheme
|
|
240
161
|
};
|
|
241
162
|
}
|
|
242
|
-
exports.createButtonComponent = createButtonComponent;
|
|
243
|
-
exports.createButtonObject = createButtonObject;
|
|
244
163
|
exports.uiPlugin = uiPlugin;
|
|
245
164
|
});
|
|
246
165
|
|
package/dist/plugin.umd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.umd.js","names":[],"sources":["../src/button.ts","../src/theme.ts","../src/plugin.ts"],"sourcesContent":["import type { Comp, GameObj, KAPLAYCtx, Vec2 } from 'kaplay';\n\nimport type { ButtonComp, ButtonCompOpt, Color, Theme } from './types';\n\nexport function createButtonComponent(\n k: KAPLAYCtx,\n theme: Theme,\n text: string,\n opt: ButtonCompOpt,\n): ButtonComp {\n let currentText = text;\n let currentOpt: ButtonCompOpt = { ...opt };\n\n const readWidth = (): number => {\n return currentOpt.width ?? theme.components.button.width;\n };\n\n const readHeight = (): number => {\n return currentOpt.height ?? theme.components.button.height;\n };\n\n const comp: ButtonComp = {\n id: 'button',\n get text() {\n return currentText;\n },\n set text(value: string) {\n currentText = value;\n },\n get width() {\n return readWidth();\n },\n set width(value: number) {\n currentOpt.width = value;\n },\n get height() {\n return readHeight();\n },\n set height(value: number) {\n currentOpt.height = value;\n },\n renderArea() {\n return new k.Rect(k.vec2(), comp.width, comp.height);\n },\n setStyle(next: Partial<ButtonCompOpt>): void {\n currentOpt = { ...currentOpt, ...next };\n },\n add(): void {\n // No-op: rendering is handled in draw().\n },\n draw(): void {\n const width = comp.width;\n const height = comp.height;\n const radius = currentOpt.radius ?? theme.shape.borderRadius;\n const fill = currentOpt.fill ?? theme.palette.primary;\n const textColor = currentOpt.textColor ?? theme.palette.text;\n const size = currentOpt.size ?? theme.typography.fontSize;\n const font = currentOpt.font ?? theme.typography.fontFamily;\n\n const drawRect = k.drawRect as unknown as\n ((opt: Record<string, unknown>) => void) | undefined;\n drawRect?.({\n pos: k.vec2(),\n width,\n height,\n color: fill,\n radius,\n });\n\n const drawText = k.drawText as unknown as\n ((opt: Record<string, unknown>) => void) | undefined;\n drawText?.({\n text: currentText,\n pos: k.vec2(width / 2, height / 2),\n size,\n font,\n color: textColor,\n anchor: 'center',\n });\n },\n destroy(): void {\n // No resources to release.\n },\n };\n\n return comp;\n}\n\nexport function createButtonObject(\n k: KAPLAYCtx,\n theme: Theme,\n text: string,\n opt: ButtonCompOpt & {\n pos?: Vec2;\n onClick?: () => void;\n color?: Color;\n hoverColor?: Color;\n pressedColor?: Color;\n textColor?: Color;\n },\n): GameObj {\n const width = opt.width ?? theme.components.button.width;\n const height = opt.height ?? theme.components.button.height;\n const radius = opt.radius ?? theme.shape.borderRadius;\n const baseColor = opt.color ?? opt.fill ?? theme.palette.primary;\n const hoverColor = opt.hoverColor ?? theme.palette.hover;\n const pressedColor = opt.pressedColor ?? theme.palette.pressed;\n const textColor = opt.textColor ?? theme.palette.text;\n const size = opt.size ?? theme.typography.fontSize;\n const font = opt.font ?? theme.typography.fontFamily;\n const pos = opt.pos ?? k.vec2();\n\n interface ButtonGameObj {\n add: (comps: Comp[]) => { text: string; textSize: number };\n onClick: (cb: () => void) => void;\n onHover: (cb: () => void) => void;\n onHoverEnd: (cb: () => void) => void;\n width: number;\n height: number;\n color: unknown;\n scale: { x: number; y: number };\n pos: { x: number; y: number };\n setSize: (w: number, h: number) => void;\n setButtonColor: (color: Color) => void;\n setButtonText: (value: string) => void;\n setButtonTextSize: (value: number) => void;\n setPosition: (x: number, y: number) => void;\n }\n\n const obj = k.add([\n k.rect(width, height, radius > 0 ? { radius } : undefined),\n k.pos(pos as never),\n k.area(),\n k.color(baseColor as never),\n k.anchor('center'),\n ]) as unknown as ButtonGameObj;\n\n const label = obj.add([\n k.text(text, { size, font }),\n k.color(textColor as never),\n k.anchor('center'),\n ]) as GameObj & { text: string; textSize: number };\n\n let currentText = text;\n let currentColor: Color = baseColor;\n\n obj.onClick(() => {\n obj.color = pressedColor;\n opt.onClick?.();\n });\n obj.onHover(() => {\n obj.color = hoverColor;\n obj.scale = k.vec2(1.05, 1.05);\n k.setCursor('pointer');\n });\n obj.onHoverEnd(() => {\n obj.color = currentColor;\n obj.scale = k.vec2(1, 1);\n k.setCursor('default');\n });\n\n obj.setSize = (w: number, h: number): void => {\n obj.width = w;\n obj.height = h;\n };\n\n obj.setButtonColor = (color: Color): void => {\n currentColor = color;\n obj.color = color;\n };\n\n obj.setButtonText = (value: string): void => {\n currentText = value;\n label.text = value;\n };\n\n obj.setButtonTextSize = (value: number): void => {\n label.textSize = value;\n };\n\n obj.setPosition = (x: number, y: number): void => {\n obj.pos = k.vec2(x, y);\n };\n\n label.text = currentText;\n\n return obj as unknown as GameObj;\n}\n","import type { DeepPartial, Theme } from './types';\n\nconst DEFAULT_PRIMARY = '#4f8cff';\nconst DEFAULT_TEXT = '#ffffff';\n\n/** Default theme used when no theme is provided. */\nexport const defaultTheme: Theme = {\n palette: {\n primary: DEFAULT_PRIMARY,\n secondary: DEFAULT_PRIMARY,\n background: '#111827',\n surface: '#1f2937',\n text: DEFAULT_TEXT,\n textSecondary: DEFAULT_TEXT,\n hover: DEFAULT_PRIMARY,\n pressed: DEFAULT_PRIMARY,\n disabled: '#6b7280',\n error: '#ef4444',\n },\n typography: {\n fontFamily: 'sans-serif',\n fontSize: 18,\n fontWeight: 400,\n lineHeight: 1.2,\n },\n shape: {\n borderRadius: 0,\n },\n spacing: 8,\n components: {\n button: {\n width: 120,\n height: 40,\n minWidth: 120,\n paddingX: 12,\n paddingY: 8,\n textTransform: 'none',\n },\n modal: {\n backdropOpacity: 0.5,\n borderRadius: 8,\n },\n tooltip: {\n background: '#111827',\n textColor: DEFAULT_TEXT,\n delay: 300,\n },\n },\n};\n\n/** Resolve a partial theme into a fully resolved theme. */\nexport function resolveTheme(input?: DeepPartial<Theme>): Theme {\n return {\n palette: { ...defaultTheme.palette, ...input?.palette },\n typography: { ...defaultTheme.typography, ...input?.typography },\n shape: { ...defaultTheme.shape, ...input?.shape },\n spacing: input?.spacing ?? defaultTheme.spacing,\n components: {\n button: {\n ...defaultTheme.components.button,\n ...input?.components?.button,\n width:\n input?.components?.button?.width ??\n input?.components?.button?.minWidth ??\n defaultTheme.components.button.width,\n },\n modal: {\n ...defaultTheme.components.modal,\n ...input?.components?.modal,\n },\n tooltip: {\n ...defaultTheme.components.tooltip,\n ...input?.components?.tooltip,\n },\n },\n };\n}\n","import type { GameObj, KAPLAYCtx, Vec2 } from 'kaplay';\n\nimport { createButtonComponent, createButtonObject } from './button';\nimport { resolveTheme } from './theme';\nimport type {\n ButtonComp,\n ButtonCompOpt,\n Color,\n DeepPartial,\n Theme,\n} from './types';\n\nexport { createButtonComponent, createButtonObject } from './button';\nexport type { ButtonComp, ButtonCompOpt, Color, Theme } from './types';\n\ndeclare module 'kaplay' {\n interface KAPLAYCtx {\n button: (text?: string, opt?: ButtonCompOpt) => ButtonComp;\n addButton: (\n text?: string,\n opt?: ButtonCompOpt & {\n pos?: Vec2;\n onClick?: () => void;\n color?: Color;\n hoverColor?: Color;\n pressedColor?: Color;\n textColor?: Color;\n },\n ) => GameObj;\n setTheme: (theme: DeepPartial<Theme>) => void;\n getTheme: () => Theme;\n }\n}\n\n/** KAPLAY UI plugin. */\nexport function uiPlugin(k: KAPLAYCtx, theme: DeepPartial<Theme> = {}) {\n let userTheme: DeepPartial<Theme> = theme;\n let currentTheme: Theme = resolveTheme(userTheme);\n\n const getTheme = (): Theme => currentTheme;\n\n const setTheme = (next: DeepPartial<Theme>): void => {\n userTheme = { ...userTheme, ...next };\n currentTheme = resolveTheme(userTheme);\n };\n\n const button = (text = '', opt: ButtonCompOpt = {}): ButtonComp => {\n return createButtonComponent(k, currentTheme, text, opt);\n };\n\n const addButton = (\n text = '',\n opt: ButtonCompOpt & {\n pos?: Vec2;\n onClick?: () => void;\n color?: Color;\n hoverColor?: Color;\n pressedColor?: Color;\n textColor?: Color;\n } = {},\n ): GameObj => {\n return createButtonObject(k, currentTheme, text, opt);\n };\n\n return {\n button,\n addButton,\n setTheme,\n getTheme,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin.umd.js","names":[],"sources":["../src/utils.ts","../src/button.ts","../src/theme.ts","../src/plugin.ts"],"sourcesContent":["import type { Color, KAPLAYCtx } from 'kaplay';\n\n/**\n * Convert hex string to color or return color.\n *\n * @param k - The Kaplay context.\n * @param color - The hex string or color.\n * @returns The color.\n */\nexport function toColor(k: KAPLAYCtx, color: string | Color): Color {\n return typeof color === 'string' ? k.rgb(color) : color;\n}\n","import type { Color, KAPLAYCtx, Vec2 } from 'kaplay';\n\nimport type { ButtonOpt, Theme } from './types';\nimport { toColor } from './utils';\n\nexport function createButton(\n k: KAPLAYCtx,\n theme: Theme,\n text: string,\n opt: ButtonOpt & {\n pos?: Vec2;\n onClick?: () => void;\n color?: string | Color;\n hoverColor?: string | Color;\n pressedColor?: string | Color;\n textColor?: string | Color;\n },\n) {\n const width = opt.width ?? theme.components.button.width;\n const height = opt.height ?? theme.components.button.height;\n const radius = opt.radius ?? theme.shape.borderRadius;\n const baseColor = toColor(k, opt.color ?? opt.fill ?? theme.palette.primary);\n const hoverColor = toColor(k, opt.hoverColor ?? theme.palette.hover);\n const pressedColor = toColor(k, opt.pressedColor ?? theme.palette.pressed);\n const textColor = toColor(k, opt.textColor ?? theme.palette.text);\n const size = opt.size ?? theme.typography.fontSize;\n const font = opt.font ?? theme.typography.fontFamily;\n const pos = opt.pos ?? k.vec2();\n\n const button = k.add([\n k.rect(width, height, radius > 0 ? { radius } : undefined),\n k.pos(pos),\n k.area(),\n k.scale(),\n k.color(baseColor),\n k.anchor('center'),\n ]);\n\n const label = button.add([\n k.text(text, { size, font }),\n k.color(textColor as never),\n k.anchor('center'),\n ]);\n\n button.onClick(() => {\n button.color = toColor(k, pressedColor);\n opt.onClick?.();\n });\n\n button.onHover(() => {\n button.color = toColor(k, hoverColor);\n button.scale = k.vec2(1.05, 1.05);\n k.setCursor('pointer');\n });\n\n button.onHoverEnd(() => {\n button.color = baseColor;\n button.scale = k.vec2(1, 1);\n k.setCursor('default');\n });\n\n return {\n ...button,\n label,\n };\n}\n","import type { DeepPartial, Theme } from './types';\n\nconst PRIMARY = '#4f8cff';\nconst TEXT = '#ffffff';\n\n/** Default theme. */\nconst theme: Theme = {\n palette: {\n primary: PRIMARY,\n secondary: PRIMARY,\n background: '#111827',\n surface: '#1f2937',\n text: TEXT,\n textSecondary: TEXT,\n hover: PRIMARY,\n pressed: PRIMARY,\n disabled: '#6b7280',\n error: '#ef4444',\n },\n typography: {\n fontFamily: 'sans-serif',\n fontSize: 18,\n fontWeight: 400,\n lineHeight: 1.2,\n },\n shape: {\n borderRadius: 0,\n },\n spacing: 8,\n components: {\n button: {\n width: 120,\n height: 40,\n minWidth: 120,\n paddingX: 12,\n paddingY: 8,\n textTransform: 'none',\n },\n modal: {\n backdropOpacity: 0.5,\n borderRadius: 8,\n },\n tooltip: {\n background: '#111827',\n textColor: TEXT,\n delay: 300,\n },\n },\n};\n\n/** Resolve a partial theme into a fully resolved theme. */\nexport function resolveTheme(input?: DeepPartial<Theme>): Theme {\n return {\n palette: { ...theme.palette, ...input?.palette },\n typography: { ...theme.typography, ...input?.typography },\n shape: { ...theme.shape, ...input?.shape },\n spacing: input?.spacing ?? theme.spacing,\n components: {\n button: {\n ...theme.components.button,\n ...input?.components?.button,\n width:\n input?.components?.button?.width ??\n input?.components?.button?.minWidth ??\n theme.components.button.width,\n },\n modal: {\n ...theme.components.modal,\n ...input?.components?.modal,\n },\n tooltip: {\n ...theme.components.tooltip,\n ...input?.components?.tooltip,\n },\n },\n };\n}\n","import type { KAPLAYCtx } from 'kaplay';\n\nimport { createButton } from './button';\nimport { resolveTheme } from './theme';\nimport type {\n AddButton,\n DeepPartial,\n GetTheme,\n SetTheme,\n Theme,\n} from './types';\n\n/** KAPLAY UI plugin. */\nexport function uiPlugin(k: KAPLAYCtx, theme: DeepPartial<Theme> = {}) {\n let userTheme: DeepPartial<Theme> = theme;\n let currentTheme: Theme = resolveTheme(userTheme);\n\n const getTheme: GetTheme = () => currentTheme;\n\n const setTheme: SetTheme = (next) => {\n userTheme = { ...userTheme, ...next };\n currentTheme = resolveTheme(userTheme);\n };\n\n const addButton: AddButton = (text = '', opt = {}) => {\n return createButton(k, currentTheme, text, opt);\n };\n\n return {\n addButton,\n setTheme,\n getTheme,\n };\n}\n"],"mappings":"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"}
|
package/dist/plugin.umd.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.KaplayPluginUI={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e,t
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.KaplayPluginUI={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e,t){return typeof t==`string`?e.rgb(t):t}function n(e,n,r,i){let a=i.width??n.components.button.width,o=i.height??n.components.button.height,s=i.radius??n.shape.borderRadius,c=t(e,i.color??i.fill??n.palette.primary),l=t(e,i.hoverColor??n.palette.hover),u=t(e,i.pressedColor??n.palette.pressed),d=t(e,i.textColor??n.palette.text),f=i.size??n.typography.fontSize,p=i.font??n.typography.fontFamily,m=i.pos??e.vec2(),h=e.add([e.rect(a,o,s>0?{radius:s}:void 0),e.pos(m),e.area(),e.scale(),e.color(c),e.anchor(`center`)]),g=h.add([e.text(r,{size:f,font:p}),e.color(d),e.anchor(`center`)]);return h.onClick(()=>{h.color=t(e,u),i.onClick?.()}),h.onHover(()=>{h.color=t(e,l),h.scale=e.vec2(1.05,1.05),e.setCursor(`pointer`)}),h.onHoverEnd(()=>{h.color=c,h.scale=e.vec2(1,1),e.setCursor(`default`)}),{...h,label:g}}let r=`#4f8cff`,i=`#ffffff`,a={palette:{primary:r,secondary:r,background:`#111827`,surface:`#1f2937`,text:i,textSecondary:i,hover:r,pressed:r,disabled:`#6b7280`,error:`#ef4444`},typography:{fontFamily:`sans-serif`,fontSize:18,fontWeight:400,lineHeight:1.2},shape:{borderRadius:0},spacing:8,components:{button:{width:120,height:40,minWidth:120,paddingX:12,paddingY:8,textTransform:`none`},modal:{backdropOpacity:.5,borderRadius:8},tooltip:{background:`#111827`,textColor:i,delay:300}}};function o(e){return{palette:{...a.palette,...e?.palette},typography:{...a.typography,...e?.typography},shape:{...a.shape,...e?.shape},spacing:e?.spacing??a.spacing,components:{button:{...a.components.button,...e?.components?.button,width:e?.components?.button?.width??e?.components?.button?.minWidth??a.components.button.width},modal:{...a.components.modal,...e?.components?.modal},tooltip:{...a.components.tooltip,...e?.components?.tooltip}}}}function s(e,t={}){let r=t,i=o(r);return{addButton:(t=``,r={})=>n(e,i,t,r),setTheme:e=>{r={...r,...e},i=o(r)},getTheme:()=>i}}e.uiPlugin=s});
|
|
2
2
|
//# sourceMappingURL=plugin.umd.min.js.map
|