kaplay-plugin-ui 1.0.0 → 1.0.1
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 +180 -68
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.mts +180 -68
- 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 +51 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
[](https://github.com/remarkablegames/kaplay-plugin-ui/actions/workflows/build.yml)
|
|
7
7
|
[](https://codecov.io/gh/remarkablegames/kaplay-plugin-ui)
|
|
8
8
|
|
|
9
|
-
🦖 KAPLAY plugin UI:
|
|
9
|
+
🦖 KAPLAY plugin UI (see [API](#api)):
|
|
10
10
|
|
|
11
|
-
- `addButton
|
|
12
|
-
- `
|
|
13
|
-
- `setTheme
|
|
11
|
+
- `addButton`
|
|
12
|
+
- `getTheme`
|
|
13
|
+
- `setTheme`
|
|
14
14
|
|
|
15
15
|
## Prerequisites
|
|
16
16
|
|
|
@@ -47,28 +47,10 @@ const k = kaplay({
|
|
|
47
47
|
});
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
```ts
|
|
53
|
-
const button = k.addButton('Start', {
|
|
54
|
-
onClick: () => {
|
|
55
|
-
k.go('game');
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
Customize the theme:
|
|
50
|
+
Import the plugin's global TypeScript definitions:
|
|
61
51
|
|
|
62
52
|
```ts
|
|
63
|
-
|
|
64
|
-
palette: {
|
|
65
|
-
primary: k.rgb(80, 160, 255),
|
|
66
|
-
text: k.rgb(255, 255, 255),
|
|
67
|
-
},
|
|
68
|
-
shape: {
|
|
69
|
-
borderRadius: 8,
|
|
70
|
-
},
|
|
71
|
-
});
|
|
53
|
+
import 'kaplay-plugin-ui/global';
|
|
72
54
|
```
|
|
73
55
|
|
|
74
56
|
To load the plugin using a script:
|
|
@@ -86,6 +68,61 @@ To load the plugin using a script:
|
|
|
86
68
|
</script>
|
|
87
69
|
```
|
|
88
70
|
|
|
71
|
+
Use the plugin:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
k.setTheme({
|
|
75
|
+
shape: {
|
|
76
|
+
borderRadius: 8,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
k.addButton('Start', {
|
|
81
|
+
onClick: () => {
|
|
82
|
+
k.go('game');
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## API
|
|
88
|
+
|
|
89
|
+
### Button
|
|
90
|
+
|
|
91
|
+
Add button game object:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
addButton(text, opt);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Update button text:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
const button = addButton(text);
|
|
101
|
+
button.label.text = 'Hello';
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Theme
|
|
105
|
+
|
|
106
|
+
Retrieve theme:
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
getTheme();
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Customize theme:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
setTheme({
|
|
116
|
+
palette: {
|
|
117
|
+
primary: rgb(80, 160, 255),
|
|
118
|
+
text: rgb(255, 255, 255),
|
|
119
|
+
},
|
|
120
|
+
shape: {
|
|
121
|
+
borderRadius: 8,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
89
126
|
## Release
|
|
90
127
|
|
|
91
128
|
Release is automated with [Release Please](https://github.com/googleapis/release-please).
|
package/dist/plugin.cjs
CHANGED
|
@@ -1,93 +1,36 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
// src/
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const comp = {
|
|
13
|
-
id: "button",
|
|
14
|
-
get text() {
|
|
15
|
-
return currentText;
|
|
16
|
-
},
|
|
17
|
-
set text(value) {
|
|
18
|
-
currentText = value;
|
|
19
|
-
},
|
|
20
|
-
get width() {
|
|
21
|
-
return readWidth();
|
|
22
|
-
},
|
|
23
|
-
set width(value) {
|
|
24
|
-
currentOpt.width = value;
|
|
25
|
-
},
|
|
26
|
-
get height() {
|
|
27
|
-
return readHeight();
|
|
28
|
-
},
|
|
29
|
-
set height(value) {
|
|
30
|
-
currentOpt.height = value;
|
|
31
|
-
},
|
|
32
|
-
renderArea() {
|
|
33
|
-
return new k.Rect(k.vec2(), comp.width, comp.height);
|
|
34
|
-
},
|
|
35
|
-
setStyle(next) {
|
|
36
|
-
currentOpt = {
|
|
37
|
-
...currentOpt,
|
|
38
|
-
...next
|
|
39
|
-
};
|
|
40
|
-
},
|
|
41
|
-
add() {},
|
|
42
|
-
draw() {
|
|
43
|
-
const width = comp.width;
|
|
44
|
-
const height = comp.height;
|
|
45
|
-
const radius = currentOpt.radius ?? theme.shape.borderRadius;
|
|
46
|
-
const fill = currentOpt.fill ?? theme.palette.primary;
|
|
47
|
-
const textColor = currentOpt.textColor ?? theme.palette.text;
|
|
48
|
-
const size = currentOpt.size ?? theme.typography.fontSize;
|
|
49
|
-
const font = currentOpt.font ?? theme.typography.fontFamily;
|
|
50
|
-
const drawRect = k.drawRect;
|
|
51
|
-
drawRect?.({
|
|
52
|
-
pos: k.vec2(),
|
|
53
|
-
width,
|
|
54
|
-
height,
|
|
55
|
-
color: fill,
|
|
56
|
-
radius
|
|
57
|
-
});
|
|
58
|
-
const drawText = k.drawText;
|
|
59
|
-
drawText?.({
|
|
60
|
-
text: currentText,
|
|
61
|
-
pos: k.vec2(width / 2, height / 2),
|
|
62
|
-
size,
|
|
63
|
-
font,
|
|
64
|
-
color: textColor,
|
|
65
|
-
anchor: "center"
|
|
66
|
-
});
|
|
67
|
-
},
|
|
68
|
-
destroy() {}
|
|
69
|
-
};
|
|
70
|
-
return comp;
|
|
2
|
+
// src/utils.ts
|
|
3
|
+
/**
|
|
4
|
+
* Convert hex string to color or return color.
|
|
5
|
+
*
|
|
6
|
+
* @param k - The Kaplay context.
|
|
7
|
+
* @param color - The hex string or color.
|
|
8
|
+
* @returns The color.
|
|
9
|
+
*/
|
|
10
|
+
function toColor(k, color) {
|
|
11
|
+
return typeof color === "string" ? k.rgb(color) : color;
|
|
71
12
|
}
|
|
72
|
-
|
|
13
|
+
// src/button.ts
|
|
14
|
+
function createButton(k, theme, text, opt) {
|
|
73
15
|
const width = opt.width ?? theme.components.button.width;
|
|
74
16
|
const height = opt.height ?? theme.components.button.height;
|
|
75
17
|
const radius = opt.radius ?? theme.shape.borderRadius;
|
|
76
|
-
const baseColor = opt.color ?? opt.fill ?? theme.palette.primary;
|
|
77
|
-
const hoverColor = opt.hoverColor ?? theme.palette.hover;
|
|
78
|
-
const pressedColor = opt.pressedColor ?? theme.palette.pressed;
|
|
79
|
-
const textColor = opt.textColor ?? theme.palette.text;
|
|
18
|
+
const baseColor = toColor(k, opt.color ?? opt.fill ?? theme.palette.primary);
|
|
19
|
+
const hoverColor = toColor(k, opt.hoverColor ?? theme.palette.hover);
|
|
20
|
+
const pressedColor = toColor(k, opt.pressedColor ?? theme.palette.pressed);
|
|
21
|
+
const textColor = toColor(k, opt.textColor ?? theme.palette.text);
|
|
80
22
|
const size = opt.size ?? theme.typography.fontSize;
|
|
81
23
|
const font = opt.font ?? theme.typography.fontFamily;
|
|
82
24
|
const pos = opt.pos ?? k.vec2();
|
|
83
|
-
const
|
|
25
|
+
const button = k.add([
|
|
84
26
|
k.rect(width, height, radius > 0 ? { radius } : void 0),
|
|
85
27
|
k.pos(pos),
|
|
86
28
|
k.area(),
|
|
29
|
+
k.scale(),
|
|
87
30
|
k.color(baseColor),
|
|
88
31
|
k.anchor("center")
|
|
89
32
|
]);
|
|
90
|
-
const label =
|
|
33
|
+
const label = button.add([
|
|
91
34
|
k.text(text, {
|
|
92
35
|
size,
|
|
93
36
|
font
|
|
@@ -95,57 +38,39 @@ function createButtonObject(k, theme, text, opt) {
|
|
|
95
38
|
k.color(textColor),
|
|
96
39
|
k.anchor("center")
|
|
97
40
|
]);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
obj.onClick(() => {
|
|
101
|
-
obj.color = pressedColor;
|
|
41
|
+
button.onClick(() => {
|
|
42
|
+
button.color = toColor(k, pressedColor);
|
|
102
43
|
opt.onClick?.();
|
|
103
44
|
});
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
45
|
+
button.onHover(() => {
|
|
46
|
+
button.color = toColor(k, hoverColor);
|
|
47
|
+
button.scale = k.vec2(1.05, 1.05);
|
|
107
48
|
k.setCursor("pointer");
|
|
108
49
|
});
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
50
|
+
button.onHoverEnd(() => {
|
|
51
|
+
button.color = baseColor;
|
|
52
|
+
button.scale = k.vec2(1, 1);
|
|
112
53
|
k.setCursor("default");
|
|
113
54
|
});
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
};
|
|
118
|
-
obj.setButtonColor = (color) => {
|
|
119
|
-
currentColor = color;
|
|
120
|
-
obj.color = color;
|
|
121
|
-
};
|
|
122
|
-
obj.setButtonText = (value) => {
|
|
123
|
-
currentText = value;
|
|
124
|
-
label.text = value;
|
|
125
|
-
};
|
|
126
|
-
obj.setButtonTextSize = (value) => {
|
|
127
|
-
label.textSize = value;
|
|
128
|
-
};
|
|
129
|
-
obj.setPosition = (x, y) => {
|
|
130
|
-
obj.pos = k.vec2(x, y);
|
|
55
|
+
return {
|
|
56
|
+
...button,
|
|
57
|
+
label
|
|
131
58
|
};
|
|
132
|
-
label.text = currentText;
|
|
133
|
-
return obj;
|
|
134
59
|
}
|
|
135
60
|
// src/theme.ts
|
|
136
|
-
const
|
|
137
|
-
const
|
|
138
|
-
/** Default theme
|
|
139
|
-
const
|
|
61
|
+
const PRIMARY = "#4f8cff";
|
|
62
|
+
const TEXT = "#ffffff";
|
|
63
|
+
/** Default theme. */
|
|
64
|
+
const theme = {
|
|
140
65
|
palette: {
|
|
141
|
-
primary:
|
|
142
|
-
secondary:
|
|
66
|
+
primary: PRIMARY,
|
|
67
|
+
secondary: PRIMARY,
|
|
143
68
|
background: "#111827",
|
|
144
69
|
surface: "#1f2937",
|
|
145
|
-
text:
|
|
146
|
-
textSecondary:
|
|
147
|
-
hover:
|
|
148
|
-
pressed:
|
|
70
|
+
text: TEXT,
|
|
71
|
+
textSecondary: TEXT,
|
|
72
|
+
hover: PRIMARY,
|
|
73
|
+
pressed: PRIMARY,
|
|
149
74
|
disabled: "#6b7280",
|
|
150
75
|
error: "#ef4444"
|
|
151
76
|
},
|
|
@@ -172,7 +97,7 @@ const defaultTheme = {
|
|
|
172
97
|
},
|
|
173
98
|
tooltip: {
|
|
174
99
|
background: "#111827",
|
|
175
|
-
textColor:
|
|
100
|
+
textColor: TEXT,
|
|
176
101
|
delay: 300
|
|
177
102
|
}
|
|
178
103
|
}
|
|
@@ -181,30 +106,30 @@ const defaultTheme = {
|
|
|
181
106
|
function resolveTheme(input) {
|
|
182
107
|
return {
|
|
183
108
|
palette: {
|
|
184
|
-
...
|
|
109
|
+
...theme.palette,
|
|
185
110
|
...input?.palette
|
|
186
111
|
},
|
|
187
112
|
typography: {
|
|
188
|
-
...
|
|
113
|
+
...theme.typography,
|
|
189
114
|
...input?.typography
|
|
190
115
|
},
|
|
191
116
|
shape: {
|
|
192
|
-
...
|
|
117
|
+
...theme.shape,
|
|
193
118
|
...input?.shape
|
|
194
119
|
},
|
|
195
|
-
spacing: input?.spacing ??
|
|
120
|
+
spacing: input?.spacing ?? theme.spacing,
|
|
196
121
|
components: {
|
|
197
122
|
button: {
|
|
198
|
-
...
|
|
123
|
+
...theme.components.button,
|
|
199
124
|
...input?.components?.button,
|
|
200
|
-
width: input?.components?.button?.width ?? input?.components?.button?.minWidth ??
|
|
125
|
+
width: input?.components?.button?.width ?? input?.components?.button?.minWidth ?? theme.components.button.width
|
|
201
126
|
},
|
|
202
127
|
modal: {
|
|
203
|
-
...
|
|
128
|
+
...theme.components.modal,
|
|
204
129
|
...input?.components?.modal
|
|
205
130
|
},
|
|
206
131
|
tooltip: {
|
|
207
|
-
...
|
|
132
|
+
...theme.components.tooltip,
|
|
208
133
|
...input?.components?.tooltip
|
|
209
134
|
}
|
|
210
135
|
}
|
|
@@ -223,21 +148,15 @@ function uiPlugin(k, theme = {}) {
|
|
|
223
148
|
};
|
|
224
149
|
currentTheme = resolveTheme(userTheme);
|
|
225
150
|
};
|
|
226
|
-
const button = (text = "", opt = {}) => {
|
|
227
|
-
return createButtonComponent(k, currentTheme, text, opt);
|
|
228
|
-
};
|
|
229
151
|
const addButton = (text = "", opt = {}) => {
|
|
230
|
-
return
|
|
152
|
+
return createButton(k, currentTheme, text, opt);
|
|
231
153
|
};
|
|
232
154
|
return {
|
|
233
|
-
button,
|
|
234
155
|
addButton,
|
|
235
156
|
setTheme,
|
|
236
157
|
getTheme
|
|
237
158
|
};
|
|
238
159
|
}
|
|
239
|
-
exports.createButtonComponent = createButtonComponent;
|
|
240
|
-
exports.createButtonObject = createButtonObject;
|
|
241
160
|
exports.uiPlugin = uiPlugin;
|
|
242
161
|
|
|
243
162
|
//# sourceMappingURL=plugin.cjs.map
|
package/dist/plugin.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs","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.cjs","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 { Color, KAPLAYCtx, Vec2 } from 'kaplay';\n\nimport { createButton } from './button';\nimport { resolveTheme } from './theme';\nimport type { ButtonOpt, DeepPartial, Theme, UIPlugin } from './types';\n\nexport type { ButtonOpt, Theme, UIPlugin };\n\n/** KAPLAY UI plugin. */\nexport function uiPlugin(\n k: KAPLAYCtx,\n theme: DeepPartial<Theme> = {},\n): UIPlugin {\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 addButton = (\n text = '',\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 return createButton(k, currentTheme, text, opt);\n };\n\n return {\n addButton,\n setTheme,\n getTheme,\n };\n}\n"],"mappings":"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"}
|