kaplay-plugin-ui 1.0.1 → 1.0.3

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 CHANGED
@@ -8,9 +8,9 @@
8
8
 
9
9
  🦖 KAPLAY plugin UI (see [API](#api)):
10
10
 
11
- - `addButton`
12
- - `getTheme`
13
- - `setTheme`
11
+ - [addButton](#addButton)
12
+ - [getTheme](#getTheme)
13
+ - [setTheme](#setTheme)
14
14
 
15
15
  ## Prerequisites
16
16
 
@@ -53,7 +53,7 @@ Import the plugin's global TypeScript definitions:
53
53
  import 'kaplay-plugin-ui/global';
54
54
  ```
55
55
 
56
- To load the plugin using a script:
56
+ Load the plugin using a script:
57
57
 
58
58
  ```html
59
59
  <script src="https://unpkg.com/kaplay@latest/dist/kaplay.js"></script>
@@ -86,7 +86,7 @@ k.addButton('Start', {
86
86
 
87
87
  ## API
88
88
 
89
- ### Button
89
+ ### addButton
90
90
 
91
91
  Add button game object:
92
92
 
@@ -94,6 +94,8 @@ Add button game object:
94
94
  addButton(text, opt);
95
95
  ```
96
96
 
97
+ Buttons auto-size to their label. Width uses `components.button.paddingX` and `components.button.minWidth`; height uses `components.button.paddingY`. Pass `width` or `height` to override either dimension.
98
+
97
99
  Update button text:
98
100
 
99
101
  ```ts
@@ -101,7 +103,9 @@ const button = addButton(text);
101
103
  button.label.text = 'Hello';
102
104
  ```
103
105
 
104
- ### Theme
106
+ The button resizes automatically when the label text or font changes.
107
+
108
+ ### getTheme
105
109
 
106
110
  Retrieve theme:
107
111
 
@@ -109,6 +113,8 @@ Retrieve theme:
109
113
  getTheme();
110
114
  ```
111
115
 
116
+ ### setTheme
117
+
112
118
  Customize theme:
113
119
 
114
120
  ```ts
package/dist/plugin.cjs CHANGED
@@ -12,9 +12,8 @@ function toColor(k, color) {
12
12
  }
13
13
  // src/button.ts
14
14
  function createButton(k, theme, text, opt) {
15
- const width = opt.width ?? theme.components.button.width;
16
- const height = opt.height ?? theme.components.button.height;
17
15
  const radius = opt.radius ?? theme.shape.borderRadius;
16
+ const { minWidth, paddingX, paddingY } = theme.components.button;
18
17
  const baseColor = toColor(k, opt.color ?? opt.fill ?? theme.palette.primary);
19
18
  const hoverColor = toColor(k, opt.hoverColor ?? theme.palette.hover);
20
19
  const pressedColor = toColor(k, opt.pressedColor ?? theme.palette.pressed);
@@ -22,6 +21,12 @@ function createButton(k, theme, text, opt) {
22
21
  const size = opt.size ?? theme.typography.fontSize;
23
22
  const font = opt.font ?? theme.typography.fontFamily;
24
23
  const pos = opt.pos ?? k.vec2();
24
+ const textComp = k.text(text, {
25
+ size,
26
+ font
27
+ });
28
+ const width = opt.width ?? Math.max(textComp.width + paddingX * 2, minWidth);
29
+ const height = opt.height ?? textComp.height + paddingY * 2;
25
30
  const button = k.add([
26
31
  k.rect(width, height, radius > 0 ? { radius } : void 0),
27
32
  k.pos(pos),
@@ -31,13 +36,18 @@ function createButton(k, theme, text, opt) {
31
36
  k.anchor("center")
32
37
  ]);
33
38
  const label = button.add([
34
- k.text(text, {
35
- size,
36
- font
37
- }),
39
+ textComp,
38
40
  k.color(textColor),
39
41
  k.anchor("center")
40
42
  ]);
43
+ function resize() {
44
+ const nextWidth = opt.width ?? Math.max(label.width + paddingX * 2, minWidth);
45
+ const nextHeight = opt.height ?? label.height + paddingY * 2;
46
+ if (button.width !== nextWidth) button.width = nextWidth;
47
+ if (button.height !== nextHeight) button.height = nextHeight;
48
+ }
49
+ resize();
50
+ if (opt.width === void 0 || opt.height === void 0) button.onUpdate(resize);
41
51
  button.onClick(() => {
42
52
  button.color = toColor(k, pressedColor);
43
53
  opt.onClick?.();
@@ -84,8 +94,6 @@ const theme = {
84
94
  spacing: 8,
85
95
  components: {
86
96
  button: {
87
- width: 120,
88
- height: 40,
89
97
  minWidth: 120,
90
98
  paddingX: 12,
91
99
  paddingY: 8,
@@ -121,8 +129,7 @@ function resolveTheme(input) {
121
129
  components: {
122
130
  button: {
123
131
  ...theme.components.button,
124
- ...input?.components?.button,
125
- width: input?.components?.button?.width ?? input?.components?.button?.minWidth ?? theme.components.button.width
132
+ ...input?.components?.button
126
133
  },
127
134
  modal: {
128
135
  ...theme.components.modal,
@@ -1 +1 @@
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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"}
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 radius = opt.radius ?? theme.shape.borderRadius;\n const { minWidth, paddingX, paddingY } = theme.components.button;\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 textComp = k.text(text, { size, font });\n const width = opt.width ?? Math.max(textComp.width + paddingX * 2, minWidth);\n const height = opt.height ?? textComp.height + paddingY * 2;\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 textComp,\n k.color(textColor as never),\n k.anchor('center'),\n ]);\n\n function resize() {\n const nextWidth =\n opt.width ?? Math.max(label.width + paddingX * 2, minWidth);\n const nextHeight = opt.height ?? label.height + paddingY * 2;\n\n if (button.width !== nextWidth) {\n button.width = nextWidth;\n }\n\n if (button.height !== nextHeight) {\n button.height = nextHeight;\n }\n }\n\n resize();\n\n if (opt.width === undefined || opt.height === undefined) {\n button.onUpdate(resize);\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 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 },\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.d.cts CHANGED
@@ -7,7 +7,7 @@ declare function createButton(k: KAPLAYCtx, theme: Theme, text: string, opt: But
7
7
  pressedColor?: string | Color;
8
8
  textColor?: string | Color;
9
9
  }): {
10
- label: import("kaplay").GameObj<import("kaplay").ColorComp | import("kaplay").AnchorComp | import("kaplay").TextComp>;
10
+ label: import("kaplay").GameObj<import("kaplay").TextComp | import("kaplay").ColorComp | import("kaplay").AnchorComp>;
11
11
  add<T>(comps?: import("kaplay").CompList<T> | import("kaplay").GameObj<T>): import("kaplay").GameObj<T>;
12
12
  readd<T>(obj: import("kaplay").GameObj<T>): import("kaplay").GameObj<T>;
13
13
  remove(obj: import("kaplay").GameObj): void;
@@ -143,23 +143,26 @@ declare function createButton(k: KAPLAYCtx, theme: Theme, text: string, opt: But
143
143
  color: Color;
144
144
  anchor: import("kaplay").Anchor | Vec2;
145
145
  };
146
- interface UIPlugin {
147
- addButton: (text?: string, opt?: ButtonOpt & {
148
- pos?: Vec2;
149
- onClick?: () => void;
150
- color?: string | Color;
151
- hoverColor?: string | Color;
152
- pressedColor?: string | Color;
153
- textColor?: string | Color;
154
- }) => ReturnType<typeof createButton>;
155
- getTheme: () => Theme;
156
- setTheme: (theme: DeepPartial<Theme>) => void;
157
- }
158
146
  declare module 'kaplay' {
159
- interface KAPLAYCtx extends UIPlugin {}
147
+ interface KAPLAYCtx {
148
+ addButton: AddButton;
149
+ getTheme: GetTheme;
150
+ setTheme: SetTheme;
151
+ }
160
152
  }
153
+ type AddButton = (text?: string, opt?: ButtonOpt & {
154
+ pos?: Vec2;
155
+ onClick?: () => void;
156
+ color?: string | Color;
157
+ hoverColor?: string | Color;
158
+ pressedColor?: string | Color;
159
+ textColor?: string | Color;
160
+ }) => ReturnType<typeof createButton>;
161
+ type GetTheme = () => Theme;
162
+ type SetTheme = (theme: DeepPartial<Theme>) => void;
161
163
  /** Recursively partial version of a type. */
162
164
  type DeepPartial<T> = { [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K]; };
165
+ /** Theme config. */
163
166
  interface Theme {
164
167
  palette: {
165
168
  primary: string | Color;
@@ -185,8 +188,6 @@ interface Theme {
185
188
  spacing: number;
186
189
  components: {
187
190
  button: {
188
- width: number;
189
- height: number;
190
191
  minWidth: number;
191
192
  paddingX: number;
192
193
  paddingY: number;
@@ -216,6 +217,10 @@ interface ButtonOpt {
216
217
  pressedFill?: string | Color;
217
218
  }
218
219
  /** KAPLAY UI plugin. */
219
- export declare function uiPlugin(k: KAPLAYCtx, theme?: DeepPartial<Theme>): UIPlugin;
220
- export type { ButtonOpt, Theme, UIPlugin };
220
+ export declare function uiPlugin(k: KAPLAYCtx, theme?: DeepPartial<Theme>): {
221
+ addButton: AddButton;
222
+ setTheme: SetTheme;
223
+ getTheme: GetTheme;
224
+ };
225
+ export {};
221
226
  //# sourceMappingURL=plugin.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.cts","names":[],"sources":["../src/button.ts","../src/types.ts","../src/plugin.ts"],"mappings":";iBAKgB,aACd,GAAG,WACH,OAAO,OACP,cACA,KAAK;EACH,MAAM;EACN;EACA,iBAAiB;EACjB,sBAAsB;EACtB,wBAAwB;EACxB,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;EAmDuj0M,GAAA,wBAAA,mCAAA,YAAG,sCAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAA34hJ,sBAAA,KAAA,IAAA,sBAAA,SAAA,uBAAC,sCAAA;KAA8K,IAAA,sBAAA,SAAA,uBAAC,sCAAA;;;KAAsN,sBAAA,KAAA,IAAA,sBAAA,SAAA,uBAAC,+BAAA,oCAAA;KAAuM,IAAA,sBAAA,SAAA,uBAAC,sCAAA;;;;;;;;;;;;;;;;;;;;;;;;;UC9DtwzD;EACf,YACE,eACA,MAAM;IACJ,MAAM;IACN;IACA,iBAAiB;IACjB,sBAAsB;IACtB,wBAAwB;IACxB,qBAAqB;QAEpB,kBAAkB;EAEvB,gBAAgB;EAEhB,WAAW,OAAO,YAAY;;;YAKpB,kBAAkB;;;KAIlB,YAAY,QACrB,WAAW,KAAK,EAAE,oBAAoB,YAAY,EAAE,MAAM,EAAE;UAG9C;EACf;IACE,kBAAkB;IAClB,oBAAoB;IACpB,qBAAqB;IACrB,kBAAkB;IAClB,eAAe;IACf,wBAAwB;IACxB,gBAAgB;IAChB,kBAAkB;IAClB,mBAAmB;IACnB,gBAAgB;;EAElB;IACE;IACA;IACA;IACA;;EAEF;IACE;;EAEF;EACA;IACE;MACE;MACA;MACA;MACA;MACA;MACA;;IAEF;MACE;MACA;;IAEF;MACE,qBAAqB;MACrB,oBAAoB;MACpB;;;;;UAMW;EACf;EACA;EACA;EACA;EACA,gBAAgB;EAChB,qBAAqB;EACrB;EACA,qBAAqB;EACrB,uBAAuB;;;wBC7ET,SACd,GAAG,WACH,QAAO,YAAY,SAClB"}
1
+ {"version":3,"file":"plugin.d.cts","names":[],"sources":["../src/button.ts","../src/types.ts","../src/plugin.ts"],"mappings":";iBAKgB,aACd,GAAG,WACH,OAAO,OACP,cACA,KAAK;EACH,MAAM;EACN;EACA,iBAAiB;EACjB,sBAAsB;EACtB,wBAAwB;EACxB,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;EA0EigzM,GAAA,wBAAA,mCAAA,YAAG,sCAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAA34hJ,sBAAA,KAAA,IAAA,sBAAA,SAAA,uBAAC,sCAAA;KAA8K,IAAA,sBAAA,SAAA,uBAAC,sCAAA;;;KAAsN,sBAAA,KAAA,IAAA,sBAAA,SAAA,uBAAC,+BAAA,oCAAA;KAAuM,IAAA,sBAAA,SAAA,uBAAC,sCAAA;;;;;;;;;;;;;;;;;;;;;;;;;;YCpFrtyD;IACR,WAAW;IACX,UAAU;IACV,UAAU;;;KAIF,aACV,eACA,MAAM;EACJ,MAAM;EACN;EACA,iBAAiB;EACjB,sBAAsB;EACtB,wBAAwB;EACxB,qBAAqB;MAEpB,kBAAkB;KAEX,iBAAiB;KAEjB,YAAY,OAAO,YAAY;;KAG/B,YAAY,QACrB,WAAW,KAAK,EAAE,oBAAoB,YAAY,EAAE,MAAM,EAAE;;UAI9C;EACf;IACE,kBAAkB;IAClB,oBAAoB;IACpB,qBAAqB;IACrB,kBAAkB;IAClB,eAAe;IACf,wBAAwB;IACxB,gBAAgB;IAChB,kBAAkB;IAClB,mBAAmB;IACnB,gBAAgB;;EAElB;IACE;IACA;IACA;IACA;;EAEF;IACE;;EAEF;EACA;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;MACA;;IAEF;MACE,qBAAqB;MACrB,oBAAoB;MACpB;;;;;UAMW;EACf;EACA;EACA;EACA;EACA,gBAAgB;EAChB,qBAAqB;EACrB;EACA,qBAAqB;EACrB,uBAAuB;;;wBCzET,SAAS,GAAG,WAAW,QAAO,YAAY"}
package/dist/plugin.d.mts CHANGED
@@ -7,7 +7,7 @@ declare function createButton(k: KAPLAYCtx, theme: Theme, text: string, opt: But
7
7
  pressedColor?: string | Color;
8
8
  textColor?: string | Color;
9
9
  }): {
10
- label: import("kaplay").GameObj<import("kaplay").ColorComp | import("kaplay").AnchorComp | import("kaplay").TextComp>;
10
+ label: import("kaplay").GameObj<import("kaplay").TextComp | import("kaplay").ColorComp | import("kaplay").AnchorComp>;
11
11
  add<T>(comps?: import("kaplay").CompList<T> | import("kaplay").GameObj<T>): import("kaplay").GameObj<T>;
12
12
  readd<T>(obj: import("kaplay").GameObj<T>): import("kaplay").GameObj<T>;
13
13
  remove(obj: import("kaplay").GameObj): void;
@@ -143,23 +143,26 @@ declare function createButton(k: KAPLAYCtx, theme: Theme, text: string, opt: But
143
143
  color: Color;
144
144
  anchor: import("kaplay").Anchor | Vec2;
145
145
  };
146
- interface UIPlugin {
147
- addButton: (text?: string, opt?: ButtonOpt & {
148
- pos?: Vec2;
149
- onClick?: () => void;
150
- color?: string | Color;
151
- hoverColor?: string | Color;
152
- pressedColor?: string | Color;
153
- textColor?: string | Color;
154
- }) => ReturnType<typeof createButton>;
155
- getTheme: () => Theme;
156
- setTheme: (theme: DeepPartial<Theme>) => void;
157
- }
158
146
  declare module 'kaplay' {
159
- interface KAPLAYCtx extends UIPlugin {}
147
+ interface KAPLAYCtx {
148
+ addButton: AddButton;
149
+ getTheme: GetTheme;
150
+ setTheme: SetTheme;
151
+ }
160
152
  }
153
+ type AddButton = (text?: string, opt?: ButtonOpt & {
154
+ pos?: Vec2;
155
+ onClick?: () => void;
156
+ color?: string | Color;
157
+ hoverColor?: string | Color;
158
+ pressedColor?: string | Color;
159
+ textColor?: string | Color;
160
+ }) => ReturnType<typeof createButton>;
161
+ type GetTheme = () => Theme;
162
+ type SetTheme = (theme: DeepPartial<Theme>) => void;
161
163
  /** Recursively partial version of a type. */
162
164
  type DeepPartial<T> = { [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K]; };
165
+ /** Theme config. */
163
166
  interface Theme {
164
167
  palette: {
165
168
  primary: string | Color;
@@ -185,8 +188,6 @@ interface Theme {
185
188
  spacing: number;
186
189
  components: {
187
190
  button: {
188
- width: number;
189
- height: number;
190
191
  minWidth: number;
191
192
  paddingX: number;
192
193
  paddingY: number;
@@ -216,6 +217,10 @@ interface ButtonOpt {
216
217
  pressedFill?: string | Color;
217
218
  }
218
219
  /** KAPLAY UI plugin. */
219
- export declare function uiPlugin(k: KAPLAYCtx, theme?: DeepPartial<Theme>): UIPlugin;
220
- export type { ButtonOpt, Theme, UIPlugin };
220
+ export declare function uiPlugin(k: KAPLAYCtx, theme?: DeepPartial<Theme>): {
221
+ addButton: AddButton;
222
+ setTheme: SetTheme;
223
+ getTheme: GetTheme;
224
+ };
225
+ export {};
221
226
  //# sourceMappingURL=plugin.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.mts","names":[],"sources":["../src/button.ts","../src/types.ts","../src/plugin.ts"],"mappings":";iBAKgB,aACd,GAAG,WACH,OAAO,OACP,cACA,KAAK;EACH,MAAM;EACN;EACA,iBAAiB;EACjB,sBAAsB;EACtB,wBAAwB;EACxB,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;EAmDuj0M,GAAA,wBAAA,mCAAA,YAAG,sCAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAA34hJ,sBAAA,KAAA,IAAA,sBAAA,SAAA,uBAAC,sCAAA;KAA8K,IAAA,sBAAA,SAAA,uBAAC,sCAAA;;;KAAsN,sBAAA,KAAA,IAAA,sBAAA,SAAA,uBAAC,+BAAA,oCAAA;KAAuM,IAAA,sBAAA,SAAA,uBAAC,sCAAA;;;;;;;;;;;;;;;;;;;;;;;;;UC9DtwzD;EACf,YACE,eACA,MAAM;IACJ,MAAM;IACN;IACA,iBAAiB;IACjB,sBAAsB;IACtB,wBAAwB;IACxB,qBAAqB;QAEpB,kBAAkB;EAEvB,gBAAgB;EAEhB,WAAW,OAAO,YAAY;;;YAKpB,kBAAkB;;;KAIlB,YAAY,QACrB,WAAW,KAAK,EAAE,oBAAoB,YAAY,EAAE,MAAM,EAAE;UAG9C;EACf;IACE,kBAAkB;IAClB,oBAAoB;IACpB,qBAAqB;IACrB,kBAAkB;IAClB,eAAe;IACf,wBAAwB;IACxB,gBAAgB;IAChB,kBAAkB;IAClB,mBAAmB;IACnB,gBAAgB;;EAElB;IACE;IACA;IACA;IACA;;EAEF;IACE;;EAEF;EACA;IACE;MACE;MACA;MACA;MACA;MACA;MACA;;IAEF;MACE;MACA;;IAEF;MACE,qBAAqB;MACrB,oBAAoB;MACpB;;;;;UAMW;EACf;EACA;EACA;EACA;EACA,gBAAgB;EAChB,qBAAqB;EACrB;EACA,qBAAqB;EACrB,uBAAuB;;;wBC7ET,SACd,GAAG,WACH,QAAO,YAAY,SAClB"}
1
+ {"version":3,"file":"plugin.d.mts","names":[],"sources":["../src/button.ts","../src/types.ts","../src/plugin.ts"],"mappings":";iBAKgB,aACd,GAAG,WACH,OAAO,OACP,cACA,KAAK;EACH,MAAM;EACN;EACA,iBAAiB;EACjB,sBAAsB;EACtB,wBAAwB;EACxB,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;EA0EigzM,GAAA,wBAAA,mCAAA,YAAG,sCAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAA34hJ,sBAAA,KAAA,IAAA,sBAAA,SAAA,uBAAC,sCAAA;KAA8K,IAAA,sBAAA,SAAA,uBAAC,sCAAA;;;KAAsN,sBAAA,KAAA,IAAA,sBAAA,SAAA,uBAAC,+BAAA,oCAAA;KAAuM,IAAA,sBAAA,SAAA,uBAAC,sCAAA;;;;;;;;;;;;;;;;;;;;;;;;;;YCpFrtyD;IACR,WAAW;IACX,UAAU;IACV,UAAU;;;KAIF,aACV,eACA,MAAM;EACJ,MAAM;EACN;EACA,iBAAiB;EACjB,sBAAsB;EACtB,wBAAwB;EACxB,qBAAqB;MAEpB,kBAAkB;KAEX,iBAAiB;KAEjB,YAAY,OAAO,YAAY;;KAG/B,YAAY,QACrB,WAAW,KAAK,EAAE,oBAAoB,YAAY,EAAE,MAAM,EAAE;;UAI9C;EACf;IACE,kBAAkB;IAClB,oBAAoB;IACpB,qBAAqB;IACrB,kBAAkB;IAClB,eAAe;IACf,wBAAwB;IACxB,gBAAgB;IAChB,kBAAkB;IAClB,mBAAmB;IACnB,gBAAgB;;EAElB;IACE;IACA;IACA;IACA;;EAEF;IACE;;EAEF;EACA;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;MACA;;IAEF;MACE,qBAAqB;MACrB,oBAAoB;MACpB;;;;;UAMW;EACf;EACA;EACA;EACA;EACA,gBAAgB;EAChB,qBAAqB;EACrB;EACA,qBAAqB;EACrB,uBAAuB;;;wBCzET,SAAS,GAAG,WAAW,QAAO,YAAY"}
package/dist/plugin.mjs CHANGED
@@ -11,9 +11,8 @@ function toColor(k, color) {
11
11
  }
12
12
  // src/button.ts
13
13
  function createButton(k, theme, text, opt) {
14
- const width = opt.width ?? theme.components.button.width;
15
- const height = opt.height ?? theme.components.button.height;
16
14
  const radius = opt.radius ?? theme.shape.borderRadius;
15
+ const { minWidth, paddingX, paddingY } = theme.components.button;
17
16
  const baseColor = toColor(k, opt.color ?? opt.fill ?? theme.palette.primary);
18
17
  const hoverColor = toColor(k, opt.hoverColor ?? theme.palette.hover);
19
18
  const pressedColor = toColor(k, opt.pressedColor ?? theme.palette.pressed);
@@ -21,6 +20,12 @@ function createButton(k, theme, text, opt) {
21
20
  const size = opt.size ?? theme.typography.fontSize;
22
21
  const font = opt.font ?? theme.typography.fontFamily;
23
22
  const pos = opt.pos ?? k.vec2();
23
+ const textComp = k.text(text, {
24
+ size,
25
+ font
26
+ });
27
+ const width = opt.width ?? Math.max(textComp.width + paddingX * 2, minWidth);
28
+ const height = opt.height ?? textComp.height + paddingY * 2;
24
29
  const button = k.add([
25
30
  k.rect(width, height, radius > 0 ? { radius } : void 0),
26
31
  k.pos(pos),
@@ -30,13 +35,18 @@ function createButton(k, theme, text, opt) {
30
35
  k.anchor("center")
31
36
  ]);
32
37
  const label = button.add([
33
- k.text(text, {
34
- size,
35
- font
36
- }),
38
+ textComp,
37
39
  k.color(textColor),
38
40
  k.anchor("center")
39
41
  ]);
42
+ function resize() {
43
+ const nextWidth = opt.width ?? Math.max(label.width + paddingX * 2, minWidth);
44
+ const nextHeight = opt.height ?? label.height + paddingY * 2;
45
+ if (button.width !== nextWidth) button.width = nextWidth;
46
+ if (button.height !== nextHeight) button.height = nextHeight;
47
+ }
48
+ resize();
49
+ if (opt.width === void 0 || opt.height === void 0) button.onUpdate(resize);
40
50
  button.onClick(() => {
41
51
  button.color = toColor(k, pressedColor);
42
52
  opt.onClick?.();
@@ -83,8 +93,6 @@ const theme = {
83
93
  spacing: 8,
84
94
  components: {
85
95
  button: {
86
- width: 120,
87
- height: 40,
88
96
  minWidth: 120,
89
97
  paddingX: 12,
90
98
  paddingY: 8,
@@ -120,8 +128,7 @@ function resolveTheme(input) {
120
128
  components: {
121
129
  button: {
122
130
  ...theme.components.button,
123
- ...input?.components?.button,
124
- width: input?.components?.button?.width ?? input?.components?.button?.minWidth ?? theme.components.button.width
131
+ ...input?.components?.button
125
132
  },
126
133
  modal: {
127
134
  ...theme.components.modal,
@@ -1 +1 @@
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 { 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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"}
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 radius = opt.radius ?? theme.shape.borderRadius;\n const { minWidth, paddingX, paddingY } = theme.components.button;\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 textComp = k.text(text, { size, font });\n const width = opt.width ?? Math.max(textComp.width + paddingX * 2, minWidth);\n const height = opt.height ?? textComp.height + paddingY * 2;\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 textComp,\n k.color(textColor as never),\n k.anchor('center'),\n ]);\n\n function resize() {\n const nextWidth =\n opt.width ?? Math.max(label.width + paddingX * 2, minWidth);\n const nextHeight = opt.height ?? label.height + paddingY * 2;\n\n if (button.width !== nextWidth) {\n button.width = nextWidth;\n }\n\n if (button.height !== nextHeight) {\n button.height = nextHeight;\n }\n }\n\n resize();\n\n if (opt.width === undefined || opt.height === undefined) {\n button.onUpdate(resize);\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 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 },\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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"}
@@ -15,9 +15,8 @@
15
15
  }
16
16
  // src/button.ts
17
17
  function createButton(k, theme, text, opt) {
18
- const width = opt.width ?? theme.components.button.width;
19
- const height = opt.height ?? theme.components.button.height;
20
18
  const radius = opt.radius ?? theme.shape.borderRadius;
19
+ const { minWidth, paddingX, paddingY } = theme.components.button;
21
20
  const baseColor = toColor(k, opt.color ?? opt.fill ?? theme.palette.primary);
22
21
  const hoverColor = toColor(k, opt.hoverColor ?? theme.palette.hover);
23
22
  const pressedColor = toColor(k, opt.pressedColor ?? theme.palette.pressed);
@@ -25,6 +24,12 @@
25
24
  const size = opt.size ?? theme.typography.fontSize;
26
25
  const font = opt.font ?? theme.typography.fontFamily;
27
26
  const pos = opt.pos ?? k.vec2();
27
+ const textComp = k.text(text, {
28
+ size,
29
+ font
30
+ });
31
+ const width = opt.width ?? Math.max(textComp.width + paddingX * 2, minWidth);
32
+ const height = opt.height ?? textComp.height + paddingY * 2;
28
33
  const button = k.add([
29
34
  k.rect(width, height, radius > 0 ? { radius } : void 0),
30
35
  k.pos(pos),
@@ -34,13 +39,18 @@
34
39
  k.anchor("center")
35
40
  ]);
36
41
  const label = button.add([
37
- k.text(text, {
38
- size,
39
- font
40
- }),
42
+ textComp,
41
43
  k.color(textColor),
42
44
  k.anchor("center")
43
45
  ]);
46
+ function resize() {
47
+ const nextWidth = opt.width ?? Math.max(label.width + paddingX * 2, minWidth);
48
+ const nextHeight = opt.height ?? label.height + paddingY * 2;
49
+ if (button.width !== nextWidth) button.width = nextWidth;
50
+ if (button.height !== nextHeight) button.height = nextHeight;
51
+ }
52
+ resize();
53
+ if (opt.width === void 0 || opt.height === void 0) button.onUpdate(resize);
44
54
  button.onClick(() => {
45
55
  button.color = toColor(k, pressedColor);
46
56
  opt.onClick?.();
@@ -87,8 +97,6 @@
87
97
  spacing: 8,
88
98
  components: {
89
99
  button: {
90
- width: 120,
91
- height: 40,
92
100
  minWidth: 120,
93
101
  paddingX: 12,
94
102
  paddingY: 8,
@@ -124,8 +132,7 @@
124
132
  components: {
125
133
  button: {
126
134
  ...theme.components.button,
127
- ...input?.components?.button,
128
- width: input?.components?.button?.width ?? input?.components?.button?.minWidth ?? theme.components.button.width
135
+ ...input?.components?.button
129
136
  },
130
137
  modal: {
131
138
  ...theme.components.modal,
@@ -1 +1 @@
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 { 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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"}
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 radius = opt.radius ?? theme.shape.borderRadius;\n const { minWidth, paddingX, paddingY } = theme.components.button;\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 textComp = k.text(text, { size, font });\n const width = opt.width ?? Math.max(textComp.width + paddingX * 2, minWidth);\n const height = opt.height ?? textComp.height + paddingY * 2;\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 textComp,\n k.color(textColor as never),\n k.anchor('center'),\n ]);\n\n function resize() {\n const nextWidth =\n opt.width ?? Math.max(label.width + paddingX * 2, minWidth);\n const nextHeight = opt.height ?? label.height + paddingY * 2;\n\n if (button.width !== nextWidth) {\n button.width = nextWidth;\n }\n\n if (button.height !== nextHeight) {\n button.height = nextHeight;\n }\n }\n\n resize();\n\n if (opt.width === undefined || opt.height === undefined) {\n button.onUpdate(resize);\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 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 },\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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"}
@@ -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){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});
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.radius??n.shape.borderRadius,{minWidth:o,paddingX:s,paddingY:c}=n.components.button,l=t(e,i.color??i.fill??n.palette.primary),u=t(e,i.hoverColor??n.palette.hover),d=t(e,i.pressedColor??n.palette.pressed),f=t(e,i.textColor??n.palette.text),p=i.size??n.typography.fontSize,m=i.font??n.typography.fontFamily,h=i.pos??e.vec2(),g=e.text(r,{size:p,font:m}),_=i.width??Math.max(g.width+s*2,o),v=i.height??g.height+c*2,y=e.add([e.rect(_,v,a>0?{radius:a}:void 0),e.pos(h),e.area(),e.scale(),e.color(l),e.anchor(`center`)]),b=y.add([g,e.color(f),e.anchor(`center`)]);function x(){let e=i.width??Math.max(b.width+s*2,o),t=i.height??b.height+c*2;y.width!==e&&(y.width=e),y.height!==t&&(y.height=t)}return x(),(i.width===void 0||i.height===void 0)&&y.onUpdate(x),y.onClick(()=>{y.color=t(e,d),i.onClick?.()}),y.onHover(()=>{y.color=t(e,u),y.scale=e.vec2(1.05,1.05),e.setCursor(`pointer`)}),y.onHoverEnd(()=>{y.color=l,y.scale=e.vec2(1,1),e.setCursor(`default`)}),{...y,label:b}}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:{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},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
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.umd.min.js","names":["factory","global","exports","toColor","color","k","createButton","width","opt","theme","height","radius","baseColor","hoverColor","pressedColor","textColor","size","font","pos","button","label","text","PRIMARY","TEXT","resolveTheme","input","uiPlugin","userTheme","currentTheme","next"],"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":"C,qRASA,SAAgBG,EAAQ,EAAc,EAA8B,CAClE,OAAO,OAAOC,GAAU,SAAWC,EAAE,IAAID,CAAK,EAAIA,CACpD,CCNA,SAAgBE,EACd,EACA,EACA,EACA,EAQA,CACA,IAAMC,EAAQC,EAAI,OAASC,EAAM,WAAW,OAAO,MAC7CC,EAASF,EAAI,QAAUC,EAAM,WAAW,OAAO,OAC/CE,EAASH,EAAI,QAAUC,EAAM,MAAM,aACnCG,EAAYT,EAAQE,EAAGG,EAAI,OAASA,EAAI,MAAQC,EAAM,QAAQ,OAAO,EACrEI,EAAaV,EAAQE,EAAGG,EAAI,YAAcC,EAAM,QAAQ,KAAK,EAC7DK,EAAeX,EAAQE,EAAGG,EAAI,cAAgBC,EAAM,QAAQ,OAAO,EACnEM,EAAYZ,EAAQE,EAAGG,EAAI,WAAaC,EAAM,QAAQ,IAAI,EAC1DO,EAAOR,EAAI,MAAQC,EAAM,WAAW,SACpCQ,EAAOT,EAAI,MAAQC,EAAM,WAAW,WACpCS,EAAMV,EAAI,KAAOH,EAAE,KAAK,EAExBc,EAASd,EAAE,IAAI,CACnBA,EAAE,KAAKE,EAAOG,EAAQC,EAAS,EAAI,CAAE,QAAO,EAAI,IAAA,EAAS,EACzDN,EAAE,IAAIa,CAAG,EACTb,EAAE,KAAK,EACPA,EAAE,MAAM,EACRA,EAAE,MAAMO,CAAS,EACjBP,EAAE,OAAO,QAAQ,CACnB,CAAC,EAEKe,EAAQD,EAAO,IAAI,CACvBd,EAAE,KAAKgB,EAAM,CAAE,OAAM,MAAK,CAAC,EAC3BhB,EAAE,MAAMU,CAAkB,EAC1BV,EAAE,OAAO,QAAQ,CACnB,CAAC,EAmBD,OAjBAc,EAAO,YAAc,CACnB,EAAO,MAAQhB,EAAQE,EAAGS,CAAY,EACtCN,EAAI,UAAU,CAChB,CAAC,EAEDW,EAAO,YAAc,CACnB,EAAO,MAAQhB,EAAQE,EAAGQ,CAAU,EACpC,EAAO,MAAQR,EAAE,KAAK,KAAM,IAAI,EAChCA,EAAE,UAAU,SAAS,CACvB,CAAC,EAEDc,EAAO,eAAiB,CACtB,EAAO,MAAQP,EACf,EAAO,MAAQP,EAAE,KAAK,EAAG,CAAC,EAC1BA,EAAE,UAAU,SAAS,CACvB,CAAC,EAEM,CACL,GAAGc,EACH,OACF,CACF,CC/DA,IAAMG,EAAU,UACVC,EAAO,UAGPd,EAAe,CACnB,QAAS,CACP,QAASa,EACT,UAAWA,EACX,WAAY,UACZ,QAAS,UACT,KAAMC,EACN,cAAeA,EACf,MAAOD,EACP,QAASA,EACT,SAAU,UACV,MAAO,SACT,EACA,WAAY,CACV,WAAY,aACZ,SAAU,GACV,WAAY,IACZ,WAAY,GACd,EACA,MAAO,CACL,aAAc,CAChB,EACA,QAAS,EACT,WAAY,CACV,OAAQ,CACN,MAAO,IACP,OAAQ,GACR,SAAU,IACV,SAAU,GACV,SAAU,EACV,cAAe,MACjB,EACA,MAAO,CACL,gBAAiB,GACjB,aAAc,CAChB,EACA,QAAS,CACP,WAAY,UACZ,UAAWC,EACX,MAAO,GACT,CACF,CACF,EAGA,SAAgBC,EAAa,EAAmC,CAC9D,MAAO,CACL,QAAS,CAAE,GAAGf,EAAM,QAAS,GAAGgB,GAAO,OAAQ,EAC/C,WAAY,CAAE,GAAGhB,EAAM,WAAY,GAAGgB,GAAO,UAAW,EACxD,MAAO,CAAE,GAAGhB,EAAM,MAAO,GAAGgB,GAAO,KAAM,EACzC,QAASA,GAAO,SAAWhB,EAAM,QACjC,WAAY,CACV,OAAQ,CACN,GAAGA,EAAM,WAAW,OACpB,GAAGgB,GAAO,YAAY,OACtB,MACEA,GAAO,YAAY,QAAQ,OAC3BA,GAAO,YAAY,QAAQ,UAC3BhB,EAAM,WAAW,OAAO,KAC5B,EACA,MAAO,CACL,GAAGA,EAAM,WAAW,MACpB,GAAGgB,GAAO,YAAY,KACxB,EACA,QAAS,CACP,GAAGhB,EAAM,WAAW,QACpB,GAAGgB,GAAO,YAAY,OACxB,CACF,CACF,CACF,CCnEA,SAAgBC,EACd,EACA,EAA4B,CAAC,EACnB,CACV,IAAIC,EAAgClB,EAChCmB,EAAsBJ,EAAaG,CAAS,EAuBhD,MAAO,CACL,WAdA,EAAO,GACP,EAOI,CAAC,IAEErB,EAAaD,EAAGuB,EAAcP,EAAMb,CAAG,EAK9C,SArBgB,GAAmC,CACnD,EAAY,CAAE,GAAGmB,EAAW,GAAGE,CAAK,EACpC,EAAeL,EAAaG,CAAS,CACvC,EAmBE,aAxB4BC,CAyB9B,CACF,C"}
1
+ {"version":3,"file":"plugin.umd.min.js","names":["factory","global","exports","toColor","color","k","createButton","radius","opt","theme","baseColor","hoverColor","pressedColor","textColor","size","font","pos","textComp","text","width","paddingX","minWidth","height","paddingY","button","label","resize","nextWidth","nextHeight","PRIMARY","TEXT","resolveTheme","input","uiPlugin","userTheme","currentTheme","next"],"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 radius = opt.radius ?? theme.shape.borderRadius;\n const { minWidth, paddingX, paddingY } = theme.components.button;\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 textComp = k.text(text, { size, font });\n const width = opt.width ?? Math.max(textComp.width + paddingX * 2, minWidth);\n const height = opt.height ?? textComp.height + paddingY * 2;\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 textComp,\n k.color(textColor as never),\n k.anchor('center'),\n ]);\n\n function resize() {\n const nextWidth =\n opt.width ?? Math.max(label.width + paddingX * 2, minWidth);\n const nextHeight = opt.height ?? label.height + paddingY * 2;\n\n if (button.width !== nextWidth) {\n button.width = nextWidth;\n }\n\n if (button.height !== nextHeight) {\n button.height = nextHeight;\n }\n }\n\n resize();\n\n if (opt.width === undefined || opt.height === undefined) {\n button.onUpdate(resize);\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 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 },\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/global.d.ts CHANGED
@@ -1,4 +1,6 @@
1
- import type { UIPlugin } from './dist/plugin.cjs';
1
+ import { uiPlugin } from './dist/plugin.cjs';
2
+
3
+ type Plugin = ReturnType<typeof uiPlugin>;
2
4
 
3
5
  declare global {
4
6
  /**
@@ -18,7 +20,7 @@ declare global {
18
20
  *
19
21
  * @returns The button object.
20
22
  */
21
- var addButton: UIPlugin['addButton'];
23
+ var addButton: Plugin['addButton'];
22
24
 
23
25
  /**
24
26
  * Retrieve the theme.
@@ -30,7 +32,7 @@ declare global {
30
32
  *
31
33
  * @returns The theme config.
32
34
  */
33
- var getTheme: UIPlugin['getTheme'];
35
+ var getTheme: Plugin['getTheme'];
34
36
 
35
37
  /**
36
38
  * Customize the theme.
@@ -50,7 +52,7 @@ declare global {
50
52
  * });
51
53
  * ```
52
54
  */
53
- var setTheme: UIPlugin['setTheme'];
55
+ var setTheme: Plugin['setTheme'];
54
56
  }
55
57
 
56
58
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kaplay-plugin-ui",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Kaplay plugin UI",
5
5
  "author": "Mark <mark@remarkablemark.org> (https://remarkablemark.org)",
6
6
  "main": "./dist/plugin.cjs",