kaplay-ui 1.0.0-alpha.13 → 1.0.0-alpha.15
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 +108 -83
- package/dist/uiplugin.d.ts +1 -0
- package/dist/uiplugin.js +207 -75
- package/dist/uiplugin.umd.cjs +1 -1
- package/package.json +15 -3
- package/docs/_config.yml +0 -4
- package/docs/_layouts/default.html +0 -23
- package/docs/design-decisions/_layout/default.html +0 -23
- package/docs/design-decisions/design-decisions.md +0 -6
- package/docs/design-decisions/label/label-defaults.md +0 -219
- package/docs/design-decisions/text-button/text-button-defaults.md +0 -0
- package/docs/faq.md +0 -72
- package/docs/index.md +0 -126
- package/docs/release/release.md +0 -19
- package/src/index.ts +0 -146
package/README.md
CHANGED
|
@@ -17,6 +17,19 @@ For now it helps you build Game Objects like text buttons and labels — without
|
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
+
## ✨ _What this plugin currently provides_
|
|
21
|
+
|
|
22
|
+
When installed, this plugin extends the KAPLAY context (`k`) with:
|
|
23
|
+
|
|
24
|
+
- `k.addTextButton()` – interactive buttons with centered text
|
|
25
|
+
- `k.addLabel()` – lightweight, non-interactive text labels
|
|
26
|
+
|
|
27
|
+
Each helper returns a regular KAPLAY game object enhanced with
|
|
28
|
+
**convenience methods** for changing size, position, colors, text, and more
|
|
29
|
+
after creation.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
20
33
|
## 📦 Installation
|
|
21
34
|
|
|
22
35
|
### Prerelease (new v1 work)
|
|
@@ -29,11 +42,9 @@ This gives you the latest `1.0.0‑alpha.*` builds.
|
|
|
29
42
|
|
|
30
43
|
---
|
|
31
44
|
|
|
32
|
-
## 🚀
|
|
45
|
+
## 🚀 Quick start (_1.0.0-alpha.\*_)
|
|
33
46
|
|
|
34
|
-
**Kaplay
|
|
35
|
-
|
|
36
|
-
The `kaplayUI` plugin is exported from the package root:
|
|
47
|
+
The **Kaplay-UI** plugin is exported as `kaplayUI` from the package root:
|
|
37
48
|
|
|
38
49
|
```ts
|
|
39
50
|
import kaplay from "kaplay";
|
|
@@ -47,130 +58,144 @@ const k = kaplay({
|
|
|
47
58
|
You now have access to the UI helpers via your `k` instance:
|
|
48
59
|
|
|
49
60
|
```ts
|
|
50
|
-
const btn = k.addTextButton("
|
|
51
|
-
|
|
61
|
+
const btn = k.addTextButton("Start");
|
|
62
|
+
btn.onClick(() => {
|
|
63
|
+
k.go("game");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const lbl = k.addLabel("Score: 0");
|
|
67
|
+
lbl.setLabelText("Score: 1");
|
|
52
68
|
```
|
|
53
69
|
|
|
54
70
|
---
|
|
55
71
|
|
|
56
72
|
## 🧩 Game Objects (_**1.0.0‑alpha.\***_)
|
|
57
73
|
|
|
58
|
-
### 🔤
|
|
59
|
-
|
|
60
|
-
Creates a button-like GameObj with centered text and some convenient defaults.
|
|
74
|
+
### 🔤 Text Button — `addTextButton()`
|
|
61
75
|
|
|
62
|
-
|
|
76
|
+
Creates a clickable button with centered text and default visuals.
|
|
63
77
|
|
|
64
78
|
```ts
|
|
65
|
-
addTextButton(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
)
|
|
79
|
+
const btn = k.addTextButton("Start", {
|
|
80
|
+
width: 200,
|
|
81
|
+
height: 80,
|
|
82
|
+
});
|
|
69
83
|
```
|
|
70
84
|
|
|
71
|
-
|
|
85
|
+
Buttons support runtime updates such as:
|
|
72
86
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
| `posY` | `0` |
|
|
80
|
-
| `outline` | `3` |
|
|
81
|
-
| `txtSize` | `22` |
|
|
87
|
+
```ts
|
|
88
|
+
btn.setSize(300, 100);
|
|
89
|
+
btn.setButtonColor([255, 120, 120]);
|
|
90
|
+
btn.setButtonText("Go!");
|
|
91
|
+
btn.setButtonTextSize(24);
|
|
92
|
+
```
|
|
82
93
|
|
|
83
|
-
|
|
94
|
+
Perfect for menus, dialogs, and in‑game actions.
|
|
95
|
+
|
|
96
|
+
---
|
|
84
97
|
|
|
85
|
-
|
|
86
|
-
| ---------------------- | :-------------- |
|
|
87
|
-
| `button anchor` | `"topleft"` |
|
|
88
|
-
| `button color` | `200, 200, 200` |
|
|
89
|
-
| `button outline color` | `92, 91, 91` |
|
|
90
|
-
| `text anchor` | `"center"` |
|
|
91
|
-
| `text color` | `0, 0, 0` |
|
|
98
|
+
### 🏷️ Label — `addLabel()`
|
|
92
99
|
|
|
93
|
-
|
|
100
|
+
Creates a lightweight background + text container for HUD elements or titles.
|
|
94
101
|
|
|
95
102
|
```ts
|
|
96
|
-
|
|
97
|
-
|
|
103
|
+
const label = k.addLabel("Score: 0");
|
|
104
|
+
```
|
|
98
105
|
|
|
99
|
-
|
|
100
|
-
const btn2 = k.addTextButton("Play!", { posX: 300, posY: 200 });
|
|
106
|
+
Update it dynamically:
|
|
101
107
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
```ts
|
|
109
|
+
label.setLabelText("Score: 10");
|
|
110
|
+
label.setLabelTextColor([255, 255, 0]);
|
|
111
|
+
label.setOpacity(0.9);
|
|
106
112
|
```
|
|
107
113
|
|
|
114
|
+
Ideal for HUDs, counters, status text, and overlays.
|
|
115
|
+
|
|
108
116
|
---
|
|
109
117
|
|
|
110
|
-
|
|
118
|
+
## 🎨 Customization
|
|
111
119
|
|
|
112
|
-
|
|
120
|
+
kaplay-ui is designed to be **customized imperatively**, without hiding
|
|
121
|
+
or abstracting away KAPLAY’s core APIs.
|
|
113
122
|
|
|
114
|
-
|
|
123
|
+
### ✅ Option-based customization (at creation)
|
|
124
|
+
|
|
125
|
+
Both helpers accept an optional `opts` object for common configuration:
|
|
115
126
|
|
|
116
127
|
```ts
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
128
|
+
const btn = k.addTextButton("Options", {
|
|
129
|
+
width: 250,
|
|
130
|
+
height: 70,
|
|
131
|
+
posX: 100,
|
|
132
|
+
posY: 200,
|
|
133
|
+
radius: 8,
|
|
134
|
+
});
|
|
121
135
|
```
|
|
122
136
|
|
|
123
|
-
|
|
137
|
+
---
|
|
124
138
|
|
|
125
|
-
|
|
126
|
-
| --------- | ------- |
|
|
127
|
-
| `width` | `160` |
|
|
128
|
-
| `height` | `96` |
|
|
129
|
-
| `txtSize` | `22` |
|
|
139
|
+
### ✅ Runtime customization (after creation)
|
|
130
140
|
|
|
131
|
-
|
|
141
|
+
Each UI element exposes helper methods for updating its appearance and layout:
|
|
132
142
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
| `label anchor` | `"topleft"` |
|
|
139
|
-
| `text color` | `255, 255, 255` |
|
|
140
|
-
| `text anchor` | `"center"` |
|
|
143
|
+
```ts
|
|
144
|
+
btn.setPosition(150, 220);
|
|
145
|
+
btn.setButtonColor([80, 160, 255]);
|
|
146
|
+
btn.setButtonTextColor([255, 255, 255]);
|
|
147
|
+
```
|
|
141
148
|
|
|
142
|
-
|
|
149
|
+
This makes it easy to animate, react to state changes, or reuse UI elements.
|
|
143
150
|
|
|
144
|
-
|
|
145
|
-
// Basic label
|
|
146
|
-
const lbl2 = k.addLabel("Score: 0");
|
|
151
|
+
---
|
|
147
152
|
|
|
148
|
-
|
|
149
|
-
const lbl3 = k.addLabel("Start", { width: 100, height: 50 });
|
|
153
|
+
### ✅ Full KAPLAY access
|
|
150
154
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const scoreLabel = k.addLabel(`Score: ${score}`);
|
|
155
|
+
UI elements are **regular KAPLAY game objects**, so you can still use all
|
|
156
|
+
standard KAPLAY features:
|
|
154
157
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
```ts
|
|
159
|
+
btn.use(k.opacity(0.8));
|
|
160
|
+
btn.onHover(() => btn.setScale(1.1));
|
|
161
|
+
label.use(k.rotate(5));
|
|
159
162
|
```
|
|
160
163
|
|
|
161
|
-
|
|
164
|
+
kaplay-ui never locks you into a restricted UI model.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 🧠 Design philosophy
|
|
169
|
+
|
|
170
|
+
kaplay-ui is intentionally simple:
|
|
171
|
+
|
|
172
|
+
- ✅ No retained UI trees
|
|
173
|
+
- ✅ No layout engine
|
|
174
|
+
- ✅ No reactive framework
|
|
175
|
+
- ✅ Just KAPLAY game objects + helpers
|
|
176
|
+
|
|
177
|
+
You stay in control of how and when UI updates happen.
|
|
162
178
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
-
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 📚 Documentation
|
|
182
|
+
|
|
183
|
+
- Full API documentation is available via **JSDocs**
|
|
184
|
+
- All helpers are strongly typed and editor-friendly
|
|
185
|
+
- Hover over methods in your editor to explore options
|
|
168
186
|
|
|
169
187
|
---
|
|
170
188
|
|
|
171
189
|
## 🛣️ Roadmap
|
|
172
190
|
|
|
173
|
-
|
|
191
|
+
Future components may include:
|
|
192
|
+
|
|
193
|
+
- Toggles
|
|
194
|
+
- Sliders
|
|
195
|
+
- Panels / containers
|
|
196
|
+
|
|
197
|
+
See the roadmap here:
|
|
198
|
+
👉 <https://github.com/jbakchr/kaplay-ui/blob/v1/ROADMAP.md>
|
|
174
199
|
|
|
175
200
|
---
|
|
176
201
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { }
|
package/dist/uiplugin.js
CHANGED
|
@@ -1,62 +1,48 @@
|
|
|
1
|
-
//#region src/
|
|
1
|
+
//#region src/helpers/color-utils.ts
|
|
2
2
|
function e(e, t, n) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
e.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
3
|
+
if (Array.isArray(n)) {
|
|
4
|
+
t.use(e.color([
|
|
5
|
+
n[0],
|
|
6
|
+
n[1],
|
|
7
|
+
n[2]
|
|
8
|
+
]));
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (typeof n == "string") {
|
|
12
|
+
t.use(e.color(n));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (typeof n == "object" && "r" in n) {
|
|
16
|
+
t.use(e.color(e.rgb(n.r, n.g, n.b)));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
t.use(e.color(n));
|
|
20
20
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
e.rect(n, r),
|
|
31
|
-
e.pos(0, 0),
|
|
32
|
-
e.color(0, 0, 0),
|
|
33
|
-
e.opacity(.7),
|
|
34
|
-
e.anchor("topleft")
|
|
35
|
-
]);
|
|
21
|
+
function t(e, t, n, r) {
|
|
22
|
+
if (typeof r == "string") {
|
|
23
|
+
t.use(e.outline(n, e.rgb(r)));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (Array.isArray(r)) {
|
|
27
|
+
t.use(e.outline(n, e.rgb(r[0], r[1], r[2])));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
36
30
|
}
|
|
37
31
|
//#endregion
|
|
38
|
-
//#region src/
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
...n
|
|
43
|
-
};
|
|
44
|
-
return e.make([
|
|
45
|
-
e.text(t, { size: o }),
|
|
46
|
-
e.color(0, 0, 0),
|
|
47
|
-
e.pos(r, i),
|
|
48
|
-
e.anchor(a)
|
|
49
|
-
]);
|
|
32
|
+
//#region src/helpers/layout-utils.ts
|
|
33
|
+
var n = new Set(["anchor", "rect"]);
|
|
34
|
+
function r(e) {
|
|
35
|
+
return n.has(e);
|
|
50
36
|
}
|
|
51
37
|
//#endregion
|
|
52
38
|
//#region src/helpers/pos-utils.ts
|
|
53
|
-
function
|
|
39
|
+
function i(e) {
|
|
54
40
|
return {
|
|
55
41
|
cX: e.width / 2,
|
|
56
42
|
cY: e.height / 2
|
|
57
43
|
};
|
|
58
44
|
}
|
|
59
|
-
function
|
|
45
|
+
function a(e, t, n, r, i) {
|
|
60
46
|
switch (t.anchor) {
|
|
61
47
|
case "bot":
|
|
62
48
|
n.use(e.pos(0 * r, -1 * i));
|
|
@@ -89,43 +75,189 @@ function i(e, t, n, r, i) {
|
|
|
89
75
|
}
|
|
90
76
|
}
|
|
91
77
|
//#endregion
|
|
92
|
-
//#region src/
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
78
|
+
//#region src/components/label.ts
|
|
79
|
+
function o(t, n) {
|
|
80
|
+
let { width: r, height: o, radius: s, posX: c, posY: l, opacity: u, lblColor: d } = {
|
|
81
|
+
width: 160,
|
|
82
|
+
height: 96,
|
|
83
|
+
radius: 0,
|
|
84
|
+
posX: 0,
|
|
85
|
+
posY: 0,
|
|
86
|
+
opacity: .7,
|
|
87
|
+
lblColor: [
|
|
88
|
+
0,
|
|
89
|
+
0,
|
|
90
|
+
0
|
|
91
|
+
],
|
|
92
|
+
...n
|
|
93
|
+
}, f = t.make([
|
|
94
|
+
t.rect(r, o, { radius: s }),
|
|
95
|
+
t.pos(c, l),
|
|
96
|
+
t.opacity(u),
|
|
97
|
+
t.anchor("topleft"),
|
|
98
|
+
{
|
|
99
|
+
setSize(e, n) {
|
|
100
|
+
f.width = e, f.height = n;
|
|
101
|
+
let { cX: r, cY: o } = i(f);
|
|
102
|
+
a(t, f, f.children[0], r, o);
|
|
103
|
+
},
|
|
104
|
+
setRadius(e) {
|
|
105
|
+
f.radius = e;
|
|
106
|
+
},
|
|
107
|
+
setPosition(e, t) {
|
|
108
|
+
f.pos.x = e, f.pos.y = t;
|
|
109
|
+
},
|
|
110
|
+
setOpacity(e) {
|
|
111
|
+
f.opacity = e;
|
|
112
|
+
},
|
|
113
|
+
setLabelColor(n) {
|
|
114
|
+
e(t, f, n);
|
|
115
|
+
},
|
|
116
|
+
setLabelText(e) {
|
|
117
|
+
let t = f.children[0];
|
|
118
|
+
t.text = e;
|
|
119
|
+
},
|
|
120
|
+
setLabelTextColor(n) {
|
|
121
|
+
let r = f.children[0];
|
|
122
|
+
e(t, r, n);
|
|
123
|
+
},
|
|
124
|
+
setLabelTextSize(e) {
|
|
125
|
+
let t = f.children[0];
|
|
126
|
+
t.textSize = e;
|
|
127
|
+
},
|
|
128
|
+
setLabelAnchor(e) {
|
|
129
|
+
f.anchor = e;
|
|
130
|
+
let { cX: n, cY: r } = i(f);
|
|
131
|
+
a(t, f, f.children[0], n, r);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
]);
|
|
135
|
+
return e(t, f, d), f;
|
|
100
136
|
}
|
|
101
137
|
//#endregion
|
|
102
|
-
//#region src/
|
|
103
|
-
function s(
|
|
104
|
-
let
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
138
|
+
//#region src/components/button.ts
|
|
139
|
+
function s(n, r, o) {
|
|
140
|
+
let { width: s, height: c, posX: l, posY: u, radius: d, outline: f, btnColor: p, outlineColor: m } = {
|
|
141
|
+
width: 150,
|
|
142
|
+
height: 60,
|
|
143
|
+
posX: 0,
|
|
144
|
+
posY: 0,
|
|
145
|
+
radius: 10,
|
|
146
|
+
outline: 3,
|
|
147
|
+
btnColor: [
|
|
148
|
+
200,
|
|
149
|
+
200,
|
|
150
|
+
200
|
|
151
|
+
],
|
|
152
|
+
outlineColor: "#5c5b5b",
|
|
153
|
+
...r
|
|
154
|
+
}, h = n.make([
|
|
155
|
+
n.rect(s, c, { radius: d }),
|
|
156
|
+
n.pos(l, u),
|
|
157
|
+
n.anchor(o),
|
|
158
|
+
n.area(),
|
|
159
|
+
{
|
|
160
|
+
setSize(e, t) {
|
|
161
|
+
h.width = e, h.height = t;
|
|
162
|
+
let { cX: r, cY: o } = i(h);
|
|
163
|
+
a(n, h, h.children[0], r, o);
|
|
164
|
+
},
|
|
165
|
+
setPosition(e, t) {
|
|
166
|
+
h.pos.x = e, h.pos.y = t;
|
|
167
|
+
},
|
|
168
|
+
setRadius(e) {
|
|
169
|
+
h.radius = e;
|
|
170
|
+
},
|
|
171
|
+
setOutline(e) {
|
|
172
|
+
t(n, h, e, m);
|
|
173
|
+
},
|
|
174
|
+
setButtonText(e) {
|
|
175
|
+
let t = h.children[0];
|
|
176
|
+
t.text = e;
|
|
177
|
+
},
|
|
178
|
+
setButtonTextSize(e) {
|
|
179
|
+
let t = h.children[0];
|
|
180
|
+
t.textSize = e;
|
|
181
|
+
},
|
|
182
|
+
setButtonColor(t) {
|
|
183
|
+
e(n, h, t);
|
|
184
|
+
},
|
|
185
|
+
setButtonOutlineColor(e) {
|
|
186
|
+
t(n, h, f, e);
|
|
187
|
+
},
|
|
188
|
+
setAnchor(e) {
|
|
189
|
+
h.anchor = e;
|
|
190
|
+
let { cX: t, cY: r } = i(h);
|
|
191
|
+
a(n, h, h.children[0], t, r);
|
|
192
|
+
},
|
|
193
|
+
setButtonTextColor(t) {
|
|
194
|
+
let r = h.children[0];
|
|
195
|
+
e(n, r, t);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
]);
|
|
199
|
+
return e(n, h, p), t(n, h, f, m), h;
|
|
200
|
+
}
|
|
201
|
+
//#endregion
|
|
202
|
+
//#region src/components/text.ts
|
|
203
|
+
function c(t, n, r, i, a, o) {
|
|
204
|
+
let { txtSize: s, txtColor: c } = {
|
|
205
|
+
txtSize: 22,
|
|
206
|
+
...r
|
|
207
|
+
}, l = t.make([
|
|
208
|
+
t.text(n, { size: s }),
|
|
209
|
+
t.pos(i, a),
|
|
210
|
+
t.anchor(o)
|
|
211
|
+
]);
|
|
212
|
+
return e(t, l, c), l;
|
|
213
|
+
}
|
|
214
|
+
//#endregion
|
|
215
|
+
//#region src/elements/label.ts
|
|
216
|
+
function l(e, t, n) {
|
|
217
|
+
let s = {
|
|
218
|
+
txtColor: [
|
|
219
|
+
255,
|
|
220
|
+
255,
|
|
221
|
+
255
|
|
222
|
+
],
|
|
223
|
+
...n
|
|
224
|
+
}, l = o(e, s), { cX: u, cY: d } = i(l), f = c(e, t, s, u, d, "center");
|
|
225
|
+
return l.add(f), e.add(l), l.onUse((t) => {
|
|
226
|
+
if (r(t)) {
|
|
227
|
+
let { cX: t, cY: n } = i(l);
|
|
228
|
+
a(e, l, f, t, n);
|
|
109
229
|
}
|
|
110
|
-
}),
|
|
111
|
-
t.setCursor("pointer");
|
|
112
|
-
}), c.onHoverEnd(() => {
|
|
113
|
-
t.setCursor("default");
|
|
114
|
-
}), c;
|
|
230
|
+
}), l;
|
|
115
231
|
}
|
|
116
232
|
//#endregion
|
|
117
|
-
//#region src/elements/
|
|
118
|
-
function
|
|
119
|
-
let o =
|
|
120
|
-
|
|
233
|
+
//#region src/elements/text-button.ts
|
|
234
|
+
function u(e, t, n) {
|
|
235
|
+
let o = {
|
|
236
|
+
txtColor: [
|
|
237
|
+
0,
|
|
238
|
+
0,
|
|
239
|
+
0
|
|
240
|
+
],
|
|
241
|
+
...n
|
|
242
|
+
}, l = s(e, o, "topleft"), { cX: u, cY: d } = i(l), f = c(e, t, o, u, d, "center");
|
|
243
|
+
return l.add(f), e.add(l), l.onUse((t) => {
|
|
244
|
+
if (r(t)) {
|
|
245
|
+
let { cX: t, cY: n } = i(l);
|
|
246
|
+
a(e, l, f, t, n);
|
|
247
|
+
}
|
|
248
|
+
}), l.onHover(() => {
|
|
249
|
+
e.setCursor("pointer");
|
|
250
|
+
}), l.onHoverEnd(() => {
|
|
251
|
+
e.setCursor("default");
|
|
252
|
+
}), l;
|
|
121
253
|
}
|
|
122
254
|
//#endregion
|
|
123
255
|
//#region src/index.ts
|
|
124
|
-
function
|
|
256
|
+
function d(e) {
|
|
125
257
|
return {
|
|
126
|
-
addTextButton: (t, n = {}) =>
|
|
127
|
-
addLabel: (t, n = {}) =>
|
|
258
|
+
addTextButton: (t, n = {}) => u(e, t, n),
|
|
259
|
+
addLabel: (t, n = {}) => l(e, t, n)
|
|
128
260
|
};
|
|
129
261
|
}
|
|
130
262
|
//#endregion
|
|
131
|
-
export {
|
|
263
|
+
export { d as default };
|
package/dist/uiplugin.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?module.exports=t():typeof define==`function`&&define.amd?define([],t):(e=typeof globalThis<`u`?globalThis:e||self,e.uiPlugin=t())})(this,function(){function e(e,t,n){
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?module.exports=t():typeof define==`function`&&define.amd?define([],t):(e=typeof globalThis<`u`?globalThis:e||self,e.uiPlugin=t())})(this,function(){function e(e,t,n){if(Array.isArray(n)){t.use(e.color([n[0],n[1],n[2]]));return}if(typeof n==`string`){t.use(e.color(n));return}if(typeof n==`object`&&`r`in n){t.use(e.color(e.rgb(n.r,n.g,n.b)));return}t.use(e.color(n))}function t(e,t,n,r){if(typeof r==`string`){t.use(e.outline(n,e.rgb(r)));return}if(Array.isArray(r)){t.use(e.outline(n,e.rgb(r[0],r[1],r[2])));return}}var n=new Set([`anchor`,`rect`]);function r(e){return n.has(e)}function i(e){return{cX:e.width/2,cY:e.height/2}}function a(e,t,n,r,i){switch(t.anchor){case`bot`:n.use(e.pos(0*r,-1*i));break;case`botleft`:n.use(e.pos(1*r,-1*i));break;case`botright`:n.use(e.pos(-1*r,-1*i));break;case`center`:n.use(e.pos(0*r,0*i));break;case`left`:n.use(e.pos(1*r,0*i));break;case`right`:n.use(e.pos(-1*r,0*i));break;case`top`:n.use(e.pos(0*r,1*i));break;case`topleft`:n.use(e.pos(1*r,1*i));break;case`topright`:n.use(e.pos(-1*r,1*i));break;default:break}}function o(t,n){let{width:r,height:o,radius:s,posX:c,posY:l,opacity:u,lblColor:d}={width:160,height:96,radius:0,posX:0,posY:0,opacity:.7,lblColor:[0,0,0],...n},f=t.make([t.rect(r,o,{radius:s}),t.pos(c,l),t.opacity(u),t.anchor(`topleft`),{setSize(e,n){f.width=e,f.height=n;let{cX:r,cY:o}=i(f);a(t,f,f.children[0],r,o)},setRadius(e){f.radius=e},setPosition(e,t){f.pos.x=e,f.pos.y=t},setOpacity(e){f.opacity=e},setLabelColor(n){e(t,f,n)},setLabelText(e){let t=f.children[0];t.text=e},setLabelTextColor(n){let r=f.children[0];e(t,r,n)},setLabelTextSize(e){let t=f.children[0];t.textSize=e},setLabelAnchor(e){f.anchor=e;let{cX:n,cY:r}=i(f);a(t,f,f.children[0],n,r)}}]);return e(t,f,d),f}function s(n,r,o){let{width:s,height:c,posX:l,posY:u,radius:d,outline:f,btnColor:p,outlineColor:m}={width:150,height:60,posX:0,posY:0,radius:10,outline:3,btnColor:[200,200,200],outlineColor:`#5c5b5b`,...r},h=n.make([n.rect(s,c,{radius:d}),n.pos(l,u),n.anchor(o),n.area(),{setSize(e,t){h.width=e,h.height=t;let{cX:r,cY:o}=i(h);a(n,h,h.children[0],r,o)},setPosition(e,t){h.pos.x=e,h.pos.y=t},setRadius(e){h.radius=e},setOutline(e){t(n,h,e,m)},setButtonText(e){let t=h.children[0];t.text=e},setButtonTextSize(e){let t=h.children[0];t.textSize=e},setButtonColor(t){e(n,h,t)},setButtonOutlineColor(e){t(n,h,f,e)},setAnchor(e){h.anchor=e;let{cX:t,cY:r}=i(h);a(n,h,h.children[0],t,r)},setButtonTextColor(t){let r=h.children[0];e(n,r,t)}}]);return e(n,h,p),t(n,h,f,m),h}function c(t,n,r,i,a,o){let{txtSize:s,txtColor:c}={txtSize:22,...r},l=t.make([t.text(n,{size:s}),t.pos(i,a),t.anchor(o)]);return e(t,l,c),l}function l(e,t,n){let s={txtColor:[255,255,255],...n},l=o(e,s),{cX:u,cY:d}=i(l),f=c(e,t,s,u,d,`center`);return l.add(f),e.add(l),l.onUse(t=>{if(r(t)){let{cX:t,cY:n}=i(l);a(e,l,f,t,n)}}),l}function u(e,t,n){let o={txtColor:[0,0,0],...n},l=s(e,o,`topleft`),{cX:u,cY:d}=i(l),f=c(e,t,o,u,d,`center`);return l.add(f),e.add(l),l.onUse(t=>{if(r(t)){let{cX:t,cY:n}=i(l);a(e,l,f,t,n)}}),l.onHover(()=>{e.setCursor(`pointer`)}),l.onHoverEnd(()=>{e.setCursor(`default`)}),l}function d(e){return{addTextButton:(t,n={})=>u(e,t,n),addLabel:(t,n={})=>l(e,t,n)}}return d});
|
package/package.json
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kaplay-ui",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.15",
|
|
4
4
|
"description": "UI components for KAPLAY",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "
|
|
6
|
+
"main": "./dist/uiplugin.js",
|
|
7
|
+
"types": "./dist/uiplugin.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/uiplugin.js",
|
|
11
|
+
"require": "./dist/uiplugin.umd.cjs",
|
|
12
|
+
"types": "./dist/uiplugin.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
7
18
|
"scripts": {
|
|
8
19
|
"dev": "vite dev",
|
|
9
|
-
"build": "vite build"
|
|
20
|
+
"build": "vite build",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
10
22
|
},
|
|
11
23
|
"repository": {
|
|
12
24
|
"type": "git",
|
package/docs/_config.yml
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
|
|
8
|
-
<title>{{ page.title }} - {{ site.title }}</title>
|
|
9
|
-
|
|
10
|
-
<!-- Load custom stylesheet -->
|
|
11
|
-
<link rel="stylesheet" href="{{ '/assets/style.css' | relative_url }}" />
|
|
12
|
-
</head>
|
|
13
|
-
|
|
14
|
-
<body>
|
|
15
|
-
<!-- KAPLAY-style header -->
|
|
16
|
-
<header class="kaplay-header">
|
|
17
|
-
<img src="{{ '/assets/logo.png' | relative_url }}" class="kaplay-logo" />
|
|
18
|
-
</header>
|
|
19
|
-
|
|
20
|
-
<!-- Main content -->
|
|
21
|
-
<main class="page-content">{{ content }}</main>
|
|
22
|
-
</body>
|
|
23
|
-
</html>
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
|
|
8
|
-
<title>{{ page.title }} - {{ site.title }}</title>
|
|
9
|
-
|
|
10
|
-
<!-- Load custom stylesheet -->
|
|
11
|
-
<link rel="stylesheet" href="{{ '/assets/style.css' | relative_url }}" />
|
|
12
|
-
</head>
|
|
13
|
-
|
|
14
|
-
<body>
|
|
15
|
-
<!-- KAPLAY-style header -->
|
|
16
|
-
<header class="kaplay-header">
|
|
17
|
-
<img src="{{ '/assets/logo.png' | relative_url }}" class="kaplay-logo" />
|
|
18
|
-
</header>
|
|
19
|
-
|
|
20
|
-
<!-- Main content -->
|
|
21
|
-
<main class="page-content">{{ content }}</main>
|
|
22
|
-
</body>
|
|
23
|
-
</html>
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
# Design Decisions
|
|
2
|
-
|
|
3
|
-
This md and the subfolders below it documents to design decision defaults of:
|
|
4
|
-
|
|
5
|
-
- [Label](https://github.com/jbakchr/kaplay-ui/blob/v1/docs/design-decisions/label/label-defaults.md)
|
|
6
|
-
- [Text Button](https://github.com/jbakchr/kaplay-ui/blob/v1/docs/design-decisions/text-button/text-button-defaults.md)
|
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
# Label Design Decisions
|
|
2
|
-
|
|
3
|
-
This document provides why the current defaults for the `addLabel()` Game Objects are what they are for:
|
|
4
|
-
|
|
5
|
-
1. [Background color](#-most-common-background-colors-for-labels-in-games)
|
|
6
|
-
2. [Width and Height](#-the-most-common-label-sizes-in-games)
|
|
7
|
-
|
|
8
|
-
## 🎨 Most Common Background Colors for Labels in Games
|
|
9
|
-
|
|
10
|
-
### **1. Dark, Semi-Transparent Background (Most Common Overall)**
|
|
11
|
-
|
|
12
|
-
Examples:
|
|
13
|
-
|
|
14
|
-
- `rgba(0, 0, 0, 0.5)`
|
|
15
|
-
- `rgba(0, 0, 0, 0.7)`
|
|
16
|
-
|
|
17
|
-
Why it's common:
|
|
18
|
-
|
|
19
|
-
- Works on almost every scene background (bright, dark, colorful).
|
|
20
|
-
- Makes white or light text extremely readable.
|
|
21
|
-
- Gives a “HUD” feel found in many genres.
|
|
22
|
-
|
|
23
|
-
Where it's used:
|
|
24
|
-
|
|
25
|
-
- Health bars
|
|
26
|
-
- Tooltips
|
|
27
|
-
- HUD counters
|
|
28
|
-
- Inventory labels
|
|
29
|
-
|
|
30
|
-
This is the single most widely used choice in modern 2D games.
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
### **2. Solid Black or Near‑Black Background**
|
|
35
|
-
|
|
36
|
-
Examples:
|
|
37
|
-
|
|
38
|
-
- `rgb(0, 0, 0)`
|
|
39
|
-
- `rgb(20, 20, 20)`
|
|
40
|
-
|
|
41
|
-
Why:
|
|
42
|
-
|
|
43
|
-
- Maximum contrast
|
|
44
|
-
- Minimalistic
|
|
45
|
-
- Fits sci-fi, retro, and clean UI styles
|
|
46
|
-
|
|
47
|
-
Often used for:
|
|
48
|
-
|
|
49
|
-
- Menu labels
|
|
50
|
-
- Title bars
|
|
51
|
-
- Status text
|
|
52
|
-
|
|
53
|
-
Good when opacity effects aren’t needed.
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
### **3. Light Background With Dark Text**
|
|
58
|
-
|
|
59
|
-
Examples:
|
|
60
|
-
|
|
61
|
-
- `rgb(255, 255, 255)` with black text
|
|
62
|
-
- `rgb(240, 240, 240)` for softer look
|
|
63
|
-
|
|
64
|
-
Why:
|
|
65
|
-
|
|
66
|
-
- Works well for “window”-style UI
|
|
67
|
-
- Mimics desktop/UI patterns
|
|
68
|
-
- Very readable for high-contrast HUDs
|
|
69
|
-
|
|
70
|
-
Used in:
|
|
71
|
-
|
|
72
|
-
- Casual games
|
|
73
|
-
- Puzzle games
|
|
74
|
-
- Mobile UX-inspired UI
|
|
75
|
-
|
|
76
|
-
This is less common than dark backgrounds but still widely used.
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
### **4. Colored Background Matching the Game’s Theme**
|
|
81
|
-
|
|
82
|
-
Examples:
|
|
83
|
-
|
|
84
|
-
- Blue, red, or green surfaces
|
|
85
|
-
- Faded color fills like `rgba(50, 100, 200, 0.8)`
|
|
86
|
-
|
|
87
|
-
Why:
|
|
88
|
-
|
|
89
|
-
- Looks more “stylized” or thematic
|
|
90
|
-
- Helps differentiate label purposes (e.g., warning = red)
|
|
91
|
-
- Used in highly themed menus and fantasy games
|
|
92
|
-
|
|
93
|
-
Common in:
|
|
94
|
-
|
|
95
|
-
- JRPG-style menus
|
|
96
|
-
- Crafting systems
|
|
97
|
-
- Quest logs
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
### **5. No Background (Text Only)**
|
|
102
|
-
|
|
103
|
-
While not literally a “background color,” this is a very common choice:
|
|
104
|
-
|
|
105
|
-
- Pure text HUD
|
|
106
|
-
- Floating damage numbers
|
|
107
|
-
- Dialogue text overlays
|
|
108
|
-
|
|
109
|
-
Games often use this when:
|
|
110
|
-
|
|
111
|
-
- Text doesn’t compete with backgrounds
|
|
112
|
-
- The look should be minimal
|
|
113
|
-
|
|
114
|
-
You can easily support this in `addLabel()` by letting `background: null`.
|
|
115
|
-
|
|
116
|
-
---
|
|
117
|
-
|
|
118
|
-
## ⭐ If you want the safest, most universal choice…
|
|
119
|
-
|
|
120
|
-
#### → **Use a dark semi-transparent background with light text.**
|
|
121
|
-
|
|
122
|
-
Something like:
|
|
123
|
-
|
|
124
|
-
```ts
|
|
125
|
-
background: rgba(0, 0, 0, 0.5),
|
|
126
|
-
color: rgb(255, 255, 255)
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
This works cleanly on:
|
|
130
|
-
|
|
131
|
-
- Dark levels
|
|
132
|
-
- Bright levels
|
|
133
|
-
- High-motion action scenes
|
|
134
|
-
- Stylized or pixel art environments
|
|
135
|
-
|
|
136
|
-
And it's easy for players to read instantly.
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
## 🎮 The Most Common Label Sizes in Games
|
|
141
|
-
|
|
142
|
-
Even though no source gives explicit “standard label dimensions,” we _can_ derive the common ranges from:
|
|
143
|
-
|
|
144
|
-
- Typical **pixel-art game resolutions** such as **320×180**, **640×360**, **1280×720** (all frequently used) [\[screwloose....github.io\]](https://screwloose-games.github.io/documentation/content/guides/art/pixel_art/pixel_art_guide.html)
|
|
145
|
-
- Common **sprite and tile sizes** (16×16, 32×32, 64×64) which UI assets usually align to [\[aipixelart.net\]](https://aipixelart.net/node/267)
|
|
146
|
-
- Observed dimensions in **pixel-art UI packs** on itch.io (buttons, panels, labels etc. typically in the 32–128px height range) [\[itch.io\]](https://itch.io/game-assets/tag-gui/tag-pixel-art)
|
|
147
|
-
|
|
148
|
-
From these, we can determine practical label sizes used in real games.
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
### 📐 **Typical Label Widths**
|
|
153
|
-
|
|
154
|
-
#### **Small labels (HUD counters, score, ammo):**
|
|
155
|
-
|
|
156
|
-
- **96px – 160px** wide
|
|
157
|
-
- Fits single short text like “SCORE: 0”, “HP”, “XP”, “TIME”
|
|
158
|
-
|
|
159
|
-
#### **Medium labels (section titles, longer stat text):**
|
|
160
|
-
|
|
161
|
-
- **160px – 256px** wide
|
|
162
|
-
- Fits text strings like “OBJECTIVE COMPLETE”, “CURRENT QUEST”
|
|
163
|
-
|
|
164
|
-
#### **Large labels (UI titles, menu headings):**
|
|
165
|
-
|
|
166
|
-
- **256px – 384px** wide
|
|
167
|
-
- Used for things like “INVENTORY”, “SETTINGS”, “PAUSED”
|
|
168
|
-
|
|
169
|
-
These sizes map cleanly into 16px/32px multiples recommended for pixel-art alignment.
|
|
170
|
-
|
|
171
|
-
---
|
|
172
|
-
|
|
173
|
-
### 📏 **Typical Label Heights**
|
|
174
|
-
|
|
175
|
-
Based on common UI asset proportions:
|
|
176
|
-
|
|
177
|
-
- **Text-only HUD label:**
|
|
178
|
-
**24–32px** tall (for 8–16px font sizes)
|
|
179
|
-
|
|
180
|
-
- **Label with padding + background panel:**
|
|
181
|
-
**32–48px** tall is most standard
|
|
182
|
-
|
|
183
|
-
- **Chunkier RPG or fantasy labels:**
|
|
184
|
-
**48–64px** tall in many itch.io GUI packs [\[itch.io\]](https://itch.io/game-assets/tag-gui/tag-pixel-art)
|
|
185
|
-
|
|
186
|
-
These heights align with the commonly used sprite grids of **16×16**, **32×32**, and **64×64** pixels from pixel-art standards. [\[aipixelart.net\]](https://aipixelart.net/node/267)
|
|
187
|
-
|
|
188
|
-
---
|
|
189
|
-
|
|
190
|
-
### 🧩 **Putting It All Together (Practical Defaults)**
|
|
191
|
-
|
|
192
|
-
For a game using a common base pixel-art resolution like **640×360** (widely recommended), typical label sizes look like this: [\[screwloose....github.io\]](https://screwloose-games.github.io/documentation/content/guides/art/pixel_art/pixel_art_guide.html)
|
|
193
|
-
|
|
194
|
-
| Label Type | Width | Height |
|
|
195
|
-
| ------------------- | ------------- | ----------- |
|
|
196
|
-
| Small HUD label | **120–160px** | **24–32px** |
|
|
197
|
-
| Medium UI label | **160–256px** | **32–48px** |
|
|
198
|
-
| Large heading label | **256–384px** | **48–64px** |
|
|
199
|
-
|
|
200
|
-
These fit cleanly into standard pixel-art grids and look correct across the common 320×180, 640×360, and 1280×720 style pixel resolutions.
|
|
201
|
-
|
|
202
|
-
---
|
|
203
|
-
|
|
204
|
-
### 🎯 **Recommended Defaults for kaplay-ui**
|
|
205
|
-
|
|
206
|
-
If you want to provide sensible defaults for your Label component:
|
|
207
|
-
|
|
208
|
-
- **Width:** Automatically sized based on text
|
|
209
|
-
- **Height:**
|
|
210
|
-
- **32px** for simple HUD labels
|
|
211
|
-
- **48px** for background panels
|
|
212
|
-
|
|
213
|
-
This keeps things aligned with the pixel-art norms and avoids awkward scaling.
|
|
214
|
-
|
|
215
|
-
---
|
|
216
|
-
|
|
217
|
-
_**See next decisions about `Text Button` here:**_
|
|
218
|
-
|
|
219
|
-
- [Text Button](https://github.com/jbakchr/kaplay-ui/blob/v1/docs/design-decisions/text-button/text-button-defaults.md)
|
|
File without changes
|
package/docs/faq.md
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# ❓ KAPLAY UI — FAQ
|
|
2
|
-
|
|
3
|
-
_Frequently asked questions about the KAPLAY UI plugin._
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 📚 Table of Contents
|
|
8
|
-
|
|
9
|
-
- [General](#-general)
|
|
10
|
-
- [Installation](#-installation)
|
|
11
|
-
- [Usage](#-usage)
|
|
12
|
-
- [Licensing](#-licensing)
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## 🧠 General
|
|
17
|
-
|
|
18
|
-
**Q:** _**What is this plugin for?**_
|
|
19
|
-
|
|
20
|
-
**A:** KAPLAY UI provides lightweight, composable UI helpers — such as text‑based buttons and labels — built using familiar **KAPLAY primitives**.
|
|
21
|
-
|
|
22
|
-
<div class="block">
|
|
23
|
-
It reduces boilerplate, keeps UI consistent, and helps you build menus, HUDs, overlays, and interactive UI faster.
|
|
24
|
-
</div>
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## 📦 Installation
|
|
29
|
-
|
|
30
|
-
### **Q:** _**How do I install KAPLAY UI?**_
|
|
31
|
-
|
|
32
|
-
**A:** Install from your project root using your preferred package manager:
|
|
33
|
-
|
|
34
|
-
```sh
|
|
35
|
-
npm install kaplay-ui@next
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## 🚀 Usage
|
|
41
|
-
|
|
42
|
-
### **Q:** _**How do I use the `kaplay-ui` plugin?**_
|
|
43
|
-
|
|
44
|
-
**A:** Import and enable the plugin when creating your KAPLAY instance:
|
|
45
|
-
|
|
46
|
-
```ts
|
|
47
|
-
import kaplay from "kaplay";
|
|
48
|
-
import kaplayUI from "kaplay-ui";
|
|
49
|
-
|
|
50
|
-
const k = kaplay({
|
|
51
|
-
plugins: [kaplayUI],
|
|
52
|
-
});
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Now you can create UI components such as:
|
|
56
|
-
|
|
57
|
-
```ts
|
|
58
|
-
k.addTextButton("Play");
|
|
59
|
-
k.addLabel("Score: 0");
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
## 📄 Licensing
|
|
65
|
-
|
|
66
|
-
### **Q:** _**How may I use `kaplay-ui` ?**_
|
|
67
|
-
|
|
68
|
-
The **MIT License** allows full personal and commercial use with virtually no restrictions.
|
|
69
|
-
|
|
70
|
-
<div class="block">
|
|
71
|
-
🔓 **In short:** You can use, modify, distribute, and even sell projects using KAPLAY UI.
|
|
72
|
-
</div>
|
package/docs/index.md
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
# 🦖 KAPLAY-UI 🧩
|
|
2
|
-
|
|
3
|
-
_A lightweight and flexible **UI plugin for KAPLAY**, built to feel like a natural extension of the engine._
|
|
4
|
-
|
|
5
|
-
Create UI elements quickly using familiar KAPLAY primitives — buttons, labels, HUD elements, menus, and more.
|
|
6
|
-
|
|
7
|
-
<div class="block">
|
|
8
|
-
|
|
9
|
-
✨ KAPLAY UI helps you build game-ready user interfaces with almost no setup.
|
|
10
|
-
|
|
11
|
-
Perfect for menus, HUDs, mobile UI, prototypes, and small-to-medium games.
|
|
12
|
-
|
|
13
|
-
</div>
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## 🚀 Why KAPLAY UI?
|
|
18
|
-
|
|
19
|
-
- 🧩 Works exactly like native KAPLAY
|
|
20
|
-
- 🎛️ Easy, declarative API
|
|
21
|
-
- ✨ Sensible styling defaults
|
|
22
|
-
- 🎨 Fully customizable
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## 📦 Installation _(v1.0.0-alpha\*)_
|
|
27
|
-
|
|
28
|
-
```sh
|
|
29
|
-
npm install kaplay-ui@next
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## 🧰 Getting Started
|
|
35
|
-
|
|
36
|
-
Add the plugin when creating your KAPLAY instance:
|
|
37
|
-
|
|
38
|
-
```ts
|
|
39
|
-
import kaplay from "kaplay";
|
|
40
|
-
import kaplayUI from "kaplay-ui";
|
|
41
|
-
|
|
42
|
-
const k = kaplay({
|
|
43
|
-
plugins: [kaplayUI],
|
|
44
|
-
});
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
Now create a UI element:
|
|
48
|
-
|
|
49
|
-
```ts
|
|
50
|
-
const tb = k.addTextButton("Play");
|
|
51
|
-
const sl = k.addLabel("Score: 0");
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
_**That’s it** — you’re ready to build UI!_
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## 🧱 Core Components
|
|
59
|
-
|
|
60
|
-
### 🔤 Text Button
|
|
61
|
-
|
|
62
|
-
Create an interactive button with centered text and built‑in outline & area detection.
|
|
63
|
-
|
|
64
|
-
```ts
|
|
65
|
-
const tb = k.addTextButton("Play");
|
|
66
|
-
|
|
67
|
-
tb.onClick(() => {
|
|
68
|
-
console.log("Let's play!");
|
|
69
|
-
});
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### 🏷️ Label
|
|
73
|
-
|
|
74
|
-
A small, flexible text element — perfect for HUDs.
|
|
75
|
-
|
|
76
|
-
```ts
|
|
77
|
-
const lbl = k.addLabel("Score: 0");
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
_More components are being added soon as the plugin grows._ 🎉
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
## 📚 Documentation
|
|
85
|
-
|
|
86
|
-
_Soon_ .. you can find more details here:
|
|
87
|
-
|
|
88
|
-
- 📄 **faq.md** — _Questions and answers_
|
|
89
|
-
- 🧠 **design-decisions** — _The Whys?_
|
|
90
|
-
- 🔘 **API Pages** — _The What & How_
|
|
91
|
-
- 🧪 **Examples** — _Learn by doing_
|
|
92
|
-
- 🪧 **Demos** — _See it in action_
|
|
93
|
-
|
|
94
|
-
## 🗺️ Roadmap (WIP)
|
|
95
|
-
|
|
96
|
-
- **⏳ More component types**
|
|
97
|
-
_(sliders, toggles, panels)_
|
|
98
|
-
|
|
99
|
-
- **🎨 Theme presets**
|
|
100
|
-
_(built-in light/dark UI packs)_
|
|
101
|
-
|
|
102
|
-
- **🎛️ Complex layout helpers**
|
|
103
|
-
_(stacks, grids)_
|
|
104
|
-
|
|
105
|
-
- **📘 Full documentation site**
|
|
106
|
-
_(getting started, faq and .. more)_
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
|
|
110
|
-
## 🤝 Contributing
|
|
111
|
-
|
|
112
|
-
Contributions and feature ideas are warmly welcome!
|
|
113
|
-
|
|
114
|
-
Feel free to submit issues or PRs on GitHub — or share ideas in the discussions tab.
|
|
115
|
-
|
|
116
|
-
---
|
|
117
|
-
|
|
118
|
-
## 📜 License
|
|
119
|
-
|
|
120
|
-
MIT © 2026 [Jonas Bak Phillipson](https://github.com/jbakchr)
|
|
121
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
<div class="block" style="text-align:center;font-weight:bold;">
|
|
125
|
-
<p>Made with 💚 + 🦖 by:<p>
|
|
126
|
-
<p style="font-style:italic;"><span style="color:#ffde86;">The</span> <span style="color:#f2ae99;">KAPLAY </span><span style="color:#CF9FFF;">Community</span></p>
|
package/docs/release/release.md
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# About releases
|
|
2
|
-
|
|
3
|
-
## Alpha releases
|
|
4
|
-
|
|
5
|
-
### Before release
|
|
6
|
-
Before releasing a new alpha.* version remember to:
|
|
7
|
-
|
|
8
|
-
- Update v* branch JSDocs
|
|
9
|
-
- Update main branch README.md
|
|
10
|
-
- Update ROADMAP.md
|
|
11
|
-
- Update main branch docs for website
|
|
12
|
-
|
|
13
|
-
### Steps to release alpha version to npm
|
|
14
|
-
|
|
15
|
-
1. run `npm login``
|
|
16
|
-
2. npm version prerelease --preid=alpha
|
|
17
|
-
3. npm run build
|
|
18
|
-
4. git push
|
|
19
|
-
5. npm publish --tag next
|
package/src/index.ts
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import type { KAPLAYCtx } from "kaplay";
|
|
2
|
-
|
|
3
|
-
// Types
|
|
4
|
-
import {
|
|
5
|
-
LabelComponent,
|
|
6
|
-
LabelOptions,
|
|
7
|
-
TextButtonElement,
|
|
8
|
-
TextButtonOptions,
|
|
9
|
-
} from "./types";
|
|
10
|
-
|
|
11
|
-
// Text Button
|
|
12
|
-
import { createLabel, createTextButton } from "./elements";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* # KAPLAY UI Plugin
|
|
16
|
-
*
|
|
17
|
-
* A small UI helper plugin that adds convenience functions for creating
|
|
18
|
-
* common UI components such as buttons and labels within a KAPLAY game.
|
|
19
|
-
*
|
|
20
|
-
* ## Available UI Creation Helpers
|
|
21
|
-
*
|
|
22
|
-
* @returns {object} An object exposing UI creation helpers on `k`:
|
|
23
|
-
* - `addTextButton(txt, opts?) → TextButtonElement`
|
|
24
|
-
* - `addLabel(txt, opts?) → LabelComponent`
|
|
25
|
-
*
|
|
26
|
-
* ## Examples
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* import kaplay from "kaplay";
|
|
30
|
-
* import kaplayUI from "kaplay-ui"
|
|
31
|
-
*
|
|
32
|
-
* const k = kaplay({
|
|
33
|
-
* plugins: [kaplayUI]
|
|
34
|
-
* })
|
|
35
|
-
*
|
|
36
|
-
* const button = k.addTextButton("Start");
|
|
37
|
-
* const label = k.addLabel("Hello!");
|
|
38
|
-
*/
|
|
39
|
-
|
|
40
|
-
export default function kaplayUI(k: KAPLAYCtx): {
|
|
41
|
-
/**
|
|
42
|
-
* # Text Button
|
|
43
|
-
* Creates a clickable UI button with centered text.
|
|
44
|
-
*
|
|
45
|
-
* This helper provides sensible defaults for size, layout, and styling<br>
|
|
46
|
-
* so you can quickly add text-based buttons to your KAPLAY game or UI.
|
|
47
|
-
*
|
|
48
|
-
* ## Parameters
|
|
49
|
-
*
|
|
50
|
-
* ### Required Paramters
|
|
51
|
-
* - `txt` {string}
|
|
52
|
-
*
|
|
53
|
-
* ### Default Parameter Values for 'opts'
|
|
54
|
-
* - `opts.width`: `150`
|
|
55
|
-
* - `opts.height`: `60`
|
|
56
|
-
* - `opts.radius`: `10`
|
|
57
|
-
* - `opts.posX`: `0`
|
|
58
|
-
* - `opts.posY`: `0`
|
|
59
|
-
* - `opts.outline`: `3`
|
|
60
|
-
*
|
|
61
|
-
* ## Default Styling
|
|
62
|
-
* The button object is created with:
|
|
63
|
-
* - `k.anchor("topleft")`
|
|
64
|
-
* - `k.color(200, 200, 200)`
|
|
65
|
-
* - `k.outline(opts.outline, k.rgb(92, 91, 91))`
|
|
66
|
-
* - `k.area()`
|
|
67
|
-
*
|
|
68
|
-
* @param {string} [txt]
|
|
69
|
-
* Required text label to be displayed at the center of the button.
|
|
70
|
-
*
|
|
71
|
-
* @param {TextButtonOptions} [opts={}]
|
|
72
|
-
* Optional configuration object used to customize the button.
|
|
73
|
-
*
|
|
74
|
-
* @returns {TextButtonElement}
|
|
75
|
-
* A KAPLAY Game Object representing the button with centered text.
|
|
76
|
-
*
|
|
77
|
-
* @example
|
|
78
|
-
* // Basic usage (uses default width/height)
|
|
79
|
-
* const playBtn = addTextButton("Play");
|
|
80
|
-
* playBtn.onClick(() => console.log("Play clicked!"));
|
|
81
|
-
*
|
|
82
|
-
* @example
|
|
83
|
-
* // Custom sizing
|
|
84
|
-
* const bigBtn = addTextButton("Start", { width: 300, height: 120 });
|
|
85
|
-
*
|
|
86
|
-
* @example
|
|
87
|
-
* // Override only one dimension
|
|
88
|
-
* const tallBtn = addTextButton("Options", { radius: 2 });
|
|
89
|
-
*/
|
|
90
|
-
addTextButton(txt: string, opts?: TextButtonOptions): TextButtonElement;
|
|
91
|
-
/**
|
|
92
|
-
* # Label
|
|
93
|
-
*
|
|
94
|
-
* Creates a simple text container with a background and layout box.
|
|
95
|
-
*
|
|
96
|
-
* Labels are lightweight UI elements used to display non-interactive text
|
|
97
|
-
* such as titles, descriptions, or dynamic info (scores, status, etc.).
|
|
98
|
-
*
|
|
99
|
-
* ## Parameters
|
|
100
|
-
*
|
|
101
|
-
* ### Required Paramters
|
|
102
|
-
* - `txt` {string}
|
|
103
|
-
*
|
|
104
|
-
* ### Default Parameter Values for 'opts'
|
|
105
|
-
* - `opts.width`: `160`
|
|
106
|
-
* - `opts.height`: `96`
|
|
107
|
-
* - `opts.txtSize`: `22`
|
|
108
|
-
*
|
|
109
|
-
* ## Default Styling
|
|
110
|
-
*
|
|
111
|
-
* A labels base (its 'background' surface) includes:
|
|
112
|
-
* - `k.pos(0, 0)`
|
|
113
|
-
* - `k.color(0, 0, 0)`
|
|
114
|
-
* - `k.opacity(0.7)`
|
|
115
|
-
* - `k.anchor("topleft")`
|
|
116
|
-
*
|
|
117
|
-
* A label centered text includes:
|
|
118
|
-
* - `k.anchor("center"))
|
|
119
|
-
* - `k.color(255, 255, 255))
|
|
120
|
-
*
|
|
121
|
-
* @param {LabelOptions} [opts={}]
|
|
122
|
-
* Optional configuration object used to customize the button.
|
|
123
|
-
*
|
|
124
|
-
* @returns {LabelElement}
|
|
125
|
-
* A KAPLAY game object representing a text label.
|
|
126
|
-
*
|
|
127
|
-
* @example
|
|
128
|
-
* let score = 0
|
|
129
|
-
* const scoreLabel = addLabel(`Score: ${score}`);
|
|
130
|
-
*
|
|
131
|
-
* k.wait(2, () => {
|
|
132
|
-
* score++;
|
|
133
|
-
* scoreLabel.children[0].text = `Score: ${score}`;
|
|
134
|
-
* })
|
|
135
|
-
*/
|
|
136
|
-
addLabel(txt: string, opts?: LabelOptions): LabelComponent;
|
|
137
|
-
} {
|
|
138
|
-
return {
|
|
139
|
-
addTextButton: (
|
|
140
|
-
txt: string,
|
|
141
|
-
opts: TextButtonOptions = {},
|
|
142
|
-
): TextButtonElement => createTextButton(k, txt, opts),
|
|
143
|
-
addLabel: (txt, opts: LabelOptions = {}): LabelComponent =>
|
|
144
|
-
createLabel(k, txt, opts),
|
|
145
|
-
};
|
|
146
|
-
}
|