@rpgjs/client 5.0.0-beta.23 → 5.0.0-beta.25
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/CHANGELOG.md +29 -0
- package/dist/Game/Object.d.ts +5 -0
- package/dist/Game/Object.js +48 -2
- package/dist/Game/Object.js.map +1 -1
- package/dist/Gui/Gui.js +5 -0
- package/dist/Gui/Gui.js.map +1 -1
- package/dist/components/character.ce.js +9 -2
- package/dist/components/character.ce.js.map +1 -1
- package/dist/components/gui/dialogbox/index.ce.js +54 -4
- package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
- package/dist/components/gui/hud/hud.ce.js +2 -2
- package/dist/components/gui/hud/hud.ce.js.map +1 -1
- package/dist/components/gui/index.d.ts +3 -1
- package/dist/components/gui/index.js +2 -0
- package/dist/components/gui/input-field.ce.js +123 -0
- package/dist/components/gui/input-field.ce.js.map +1 -0
- package/dist/components/gui/input.ce.js +40 -0
- package/dist/components/gui/input.ce.js.map +1 -0
- package/dist/components/gui/menu/items-menu.ce.js +27 -4
- package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/main-menu.ce.js +210 -155
- package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
- package/dist/components/gui/save-load.ce.js +33 -4
- package/dist/components/gui/save-load.ce.js.map +1 -1
- package/dist/components/gui/shop/shop.ce.js +47 -4
- package/dist/components/gui/shop/shop.ce.js.map +1 -1
- package/dist/i18n.d.ts +11 -0
- package/dist/i18n.js +11 -0
- package/dist/i18n.js.map +1 -1
- package/dist/index.js +13 -11
- package/package.json +4 -4
- package/src/Game/Object.spec.ts +26 -2
- package/src/Game/Object.ts +71 -2
- package/src/Gui/Gui.spec.ts +5 -0
- package/src/Gui/Gui.ts +5 -1
- package/src/components/character.ce +12 -6
- package/src/components/gui/dialogbox/index.ce +82 -41
- package/src/components/gui/hud/hud.ce +2 -2
- package/src/components/gui/index.ts +5 -1
- package/src/components/gui/input-field.ce +106 -0
- package/src/components/gui/input.ce +26 -0
- package/src/components/gui/menu/items-menu.ce +12 -2
- package/src/components/gui/menu/main-menu.ce +37 -6
- package/src/components/gui/save-load.ce +48 -32
- package/src/components/gui/shop/shop.ce +28 -3
- package/src/i18n.ts +11 -0
- package/vite.config.ts +5 -2
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { inject } from "../../core/inject.js";
|
|
2
|
+
import { RpgClientEngine } from "../../RpgClientEngine.js";
|
|
3
|
+
import { DOMElement, computed, cond, effect, h, signal, useDefineEmits, useDefineProps, useProps } from "canvasengine";
|
|
4
|
+
//#region src/components/gui/input-field.ce
|
|
5
|
+
function component($$props) {
|
|
6
|
+
useProps($$props);
|
|
7
|
+
const defineProps = useDefineProps($$props);
|
|
8
|
+
const defineEmits = useDefineEmits($$props);
|
|
9
|
+
const { t } = inject(RpgClientEngine).i18n();
|
|
10
|
+
const { data, layout, showMessage } = defineProps({
|
|
11
|
+
layout: "standalone",
|
|
12
|
+
showMessage: true
|
|
13
|
+
});
|
|
14
|
+
const { submit, cancel } = defineEmits();
|
|
15
|
+
const formData = computed(() => data() || {});
|
|
16
|
+
const value = signal(String(formData().defaultValue ?? ""));
|
|
17
|
+
const fieldId = computed(() => `rpg-input-value-${layout()}`);
|
|
18
|
+
const errorText = computed(() => formData().errorKey ? t(formData().errorKey, formData().errorParams || {}) : "");
|
|
19
|
+
const showCancelButton = computed(() => formData().cancelButton !== false);
|
|
20
|
+
let focused = false;
|
|
21
|
+
function submitForm(event, collectedData) {
|
|
22
|
+
const submittedValue = collectedData && Object.prototype.hasOwnProperty.call(collectedData, "value") ? collectedData.value : event?.currentTarget?.elements?.value?.value ?? value();
|
|
23
|
+
value.set(String(submittedValue ?? ""));
|
|
24
|
+
submit({ value: submittedValue ?? "" });
|
|
25
|
+
}
|
|
26
|
+
function cancelForm() {
|
|
27
|
+
cancel();
|
|
28
|
+
}
|
|
29
|
+
function handleKeydown(event) {
|
|
30
|
+
if (event?.key !== "Escape") return;
|
|
31
|
+
event.preventDefault?.();
|
|
32
|
+
event.stopPropagation?.();
|
|
33
|
+
cancelForm();
|
|
34
|
+
}
|
|
35
|
+
effect(() => {
|
|
36
|
+
if (focused) return;
|
|
37
|
+
focused = true;
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
document.getElementById(fieldId())?.focus?.();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
return h(DOMElement, {
|
|
43
|
+
element: "form",
|
|
44
|
+
attrs: {
|
|
45
|
+
class: "rpg-ui-input-form",
|
|
46
|
+
"data-layout": computed(() => layout()),
|
|
47
|
+
submit: submitForm,
|
|
48
|
+
keydown: handleKeydown
|
|
49
|
+
}
|
|
50
|
+
}, [
|
|
51
|
+
cond(computed(() => showMessage()), () => h(DOMElement, {
|
|
52
|
+
element: "label",
|
|
53
|
+
attrs: {
|
|
54
|
+
class: "rpg-ui-input-message",
|
|
55
|
+
for: computed(() => fieldId())
|
|
56
|
+
},
|
|
57
|
+
textContent: computed(() => formData().message)
|
|
58
|
+
})),
|
|
59
|
+
cond(computed(() => formData().control === "textarea"), () => h(DOMElement, {
|
|
60
|
+
element: "textarea",
|
|
61
|
+
attrs: {
|
|
62
|
+
id: computed(() => fieldId()),
|
|
63
|
+
class: "rpg-ui-input rpg-ui-input-dialog-field",
|
|
64
|
+
name: "value",
|
|
65
|
+
value,
|
|
66
|
+
placeholder: computed(() => formData().placeholder || ""),
|
|
67
|
+
rows: computed(() => formData().rows || 4),
|
|
68
|
+
minlength: computed(() => formData().minLength),
|
|
69
|
+
maxlength: computed(() => formData().maxLength),
|
|
70
|
+
"aria-required": computed(() => formData().required ? "true" : "false")
|
|
71
|
+
}
|
|
72
|
+
}), () => h(DOMElement, {
|
|
73
|
+
element: "input",
|
|
74
|
+
attrs: {
|
|
75
|
+
id: computed(() => fieldId()),
|
|
76
|
+
class: "rpg-ui-input rpg-ui-input-dialog-field",
|
|
77
|
+
name: "value",
|
|
78
|
+
type: computed(() => formData().type || "text"),
|
|
79
|
+
value,
|
|
80
|
+
placeholder: computed(() => formData().placeholder || ""),
|
|
81
|
+
min: computed(() => formData().min),
|
|
82
|
+
max: computed(() => formData().max),
|
|
83
|
+
step: computed(() => formData().step),
|
|
84
|
+
minlength: computed(() => formData().minLength),
|
|
85
|
+
maxlength: computed(() => formData().maxLength),
|
|
86
|
+
"aria-required": computed(() => formData().required ? "true" : "false")
|
|
87
|
+
}
|
|
88
|
+
})),
|
|
89
|
+
cond(computed(() => errorText()), () => h(DOMElement, {
|
|
90
|
+
element: "div",
|
|
91
|
+
attrs: {
|
|
92
|
+
class: "rpg-ui-input-error",
|
|
93
|
+
role: "alert"
|
|
94
|
+
},
|
|
95
|
+
textContent: computed(() => errorText())
|
|
96
|
+
})),
|
|
97
|
+
h(DOMElement, {
|
|
98
|
+
element: "div",
|
|
99
|
+
attrs: { class: "rpg-ui-input-actions" }
|
|
100
|
+
}, [cond(computed(() => showCancelButton()), () => h(DOMElement, {
|
|
101
|
+
element: "button",
|
|
102
|
+
attrs: {
|
|
103
|
+
class: "rpg-ui-btn rpg-ui-input-button rpg-ui-input-button-cancel",
|
|
104
|
+
type: "button",
|
|
105
|
+
click: cancelForm
|
|
106
|
+
},
|
|
107
|
+
textContent: computed(() => formData().cancelText || t("rpg.input.cancel"))
|
|
108
|
+
})), h(DOMElement, {
|
|
109
|
+
element: "button",
|
|
110
|
+
attrs: {
|
|
111
|
+
class: "rpg-ui-btn rpg-ui-input-button rpg-ui-input-button-confirm",
|
|
112
|
+
"data-variant": "primary",
|
|
113
|
+
type: "submit"
|
|
114
|
+
},
|
|
115
|
+
textContent: computed(() => formData().confirmText || t("rpg.input.confirm"))
|
|
116
|
+
})])
|
|
117
|
+
]);
|
|
118
|
+
}
|
|
119
|
+
var __ce_component = component;
|
|
120
|
+
//#endregion
|
|
121
|
+
export { __ce_component as default };
|
|
122
|
+
|
|
123
|
+
//# sourceMappingURL=input-field.ce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-field.ce.js","names":[],"sources":["../../../src/components/gui/input-field.ce"],"sourcesContent":["<form\n class=\"rpg-ui-input-form\"\n data-layout={layout()}\n submit={submitForm}\n keydown={handleKeydown}\n>\n @if (showMessage()) {\n <label class=\"rpg-ui-input-message\" for={fieldId()}>{formData().message}</label>\n }\n @if (formData().control === \"textarea\") {\n <textarea\n id={fieldId()}\n class=\"rpg-ui-input rpg-ui-input-dialog-field\"\n name=\"value\"\n value={value}\n placeholder={formData().placeholder || \"\"}\n rows={formData().rows || 4}\n minlength={formData().minLength}\n maxlength={formData().maxLength}\n aria-required={formData().required ? \"true\" : \"false\"}\n ></textarea>\n }\n @else {\n <input\n id={fieldId()}\n class=\"rpg-ui-input rpg-ui-input-dialog-field\"\n name=\"value\"\n type={formData().type || \"text\"}\n value={value}\n placeholder={formData().placeholder || \"\"}\n min={formData().min}\n max={formData().max}\n step={formData().step}\n minlength={formData().minLength}\n maxlength={formData().maxLength}\n aria-required={formData().required ? \"true\" : \"false\"}\n />\n }\n @if (errorText()) {\n <div class=\"rpg-ui-input-error\" role=\"alert\">{errorText()}</div>\n }\n <div class=\"rpg-ui-input-actions\">\n @if (showCancelButton()) {\n <button class=\"rpg-ui-btn rpg-ui-input-button rpg-ui-input-button-cancel\" type=\"button\" click={cancelForm}>\n {formData().cancelText || t(\"rpg.input.cancel\")}\n </button>\n }\n <button\n class=\"rpg-ui-btn rpg-ui-input-button rpg-ui-input-button-confirm\"\n data-variant=\"primary\"\n type=\"submit\"\n >\n {formData().confirmText || t(\"rpg.input.confirm\")}\n </button>\n </div>\n</form>\n\n<script>\n import { computed, effect, signal } from \"canvasengine\";\n import { inject } from \"../../core/inject\";\n import { RpgClientEngine } from \"../../RpgClientEngine\";\n\n const engine = inject(RpgClientEngine);\n const { t } = engine.i18n();\n const { data, layout, showMessage } = defineProps({\n layout: \"standalone\",\n showMessage: true,\n });\n const { submit, cancel } = defineEmits();\n const formData = computed(() => data() || {});\n const value = signal(String(formData().defaultValue ?? \"\"));\n const fieldId = computed(() => `rpg-input-value-${layout()}`);\n const errorText = computed(() => formData().errorKey\n ? t(formData().errorKey, formData().errorParams || {})\n : \"\"\n );\n const showCancelButton = computed(() => formData().cancelButton !== false);\n let focused = false;\n\n function submitForm(event, collectedData) {\n const submittedValue = collectedData && Object.prototype.hasOwnProperty.call(collectedData, \"value\")\n ? collectedData.value\n : event?.currentTarget?.elements?.value?.value ?? value();\n value.set(String(submittedValue ?? \"\"));\n submit({ value: submittedValue ?? \"\" });\n }\n\n function cancelForm() {\n cancel();\n }\n\n function handleKeydown(event) {\n if (event?.key !== \"Escape\") return;\n event.preventDefault?.();\n event.stopPropagation?.();\n cancelForm();\n }\n\n effect(() => {\n if (focused) return;\n focused = true;\n setTimeout(() => {\n document.getElementById(fieldId())?.focus?.();\n });\n });\n</script>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import __ce_component$1 from "./input-field.ce.js";
|
|
2
|
+
import { DOMContainer, DOMElement, computed, cond, h, useDefineEmits, useDefineProps, useProps } from "canvasengine";
|
|
3
|
+
//#region src/components/gui/input.ce
|
|
4
|
+
function component($$props) {
|
|
5
|
+
useProps($$props);
|
|
6
|
+
const defineProps = useDefineProps($$props);
|
|
7
|
+
useDefineEmits($$props);
|
|
8
|
+
const { data, onInteraction } = defineProps();
|
|
9
|
+
const title = computed(() => data().title || "");
|
|
10
|
+
function submit(payload) {
|
|
11
|
+
onInteraction?.("submit", payload);
|
|
12
|
+
}
|
|
13
|
+
function cancel() {
|
|
14
|
+
onInteraction?.("cancel");
|
|
15
|
+
}
|
|
16
|
+
return h(DOMContainer, {
|
|
17
|
+
width: "100%",
|
|
18
|
+
height: "100%"
|
|
19
|
+
}, h(DOMElement, {
|
|
20
|
+
element: "div",
|
|
21
|
+
attrs: { class: "rpg-ui-input-layer" }
|
|
22
|
+
}, h(DOMElement, {
|
|
23
|
+
element: "div",
|
|
24
|
+
attrs: { class: "rpg-ui-input-dialog rpg-ui-window rpg-anim-fade-in" }
|
|
25
|
+
}, [cond(computed(() => title()), () => h(DOMElement, {
|
|
26
|
+
element: "div",
|
|
27
|
+
attrs: { class: "rpg-ui-window-title" },
|
|
28
|
+
textContent: computed(() => title())
|
|
29
|
+
})), h(__ce_component$1, {
|
|
30
|
+
data,
|
|
31
|
+
layout: "standalone",
|
|
32
|
+
submit,
|
|
33
|
+
cancel
|
|
34
|
+
})])));
|
|
35
|
+
}
|
|
36
|
+
var __ce_component = component;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { __ce_component as default };
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=input.ce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.ce.js","names":[],"sources":["../../../src/components/gui/input.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\">\n <div class=\"rpg-ui-input-layer\">\n <div class=\"rpg-ui-input-dialog rpg-ui-window rpg-anim-fade-in\">\n @if (title()) {\n <div class=\"rpg-ui-window-title\">{title()}</div>\n }\n <InputField data={data} layout=\"standalone\" submit={submit} cancel={cancel} />\n </div>\n </div>\n</DOMContainer>\n\n<script>\n import { computed } from \"canvasengine\";\n import InputField from \"./input-field.ce\";\n\n const { data, onInteraction } = defineProps();\n const title = computed(() => data().title || \"\");\n\n function submit(payload) {\n onInteraction?.(\"submit\", payload);\n }\n\n function cancel() {\n onInteraction?.(\"cancel\");\n }\n</script>\n"],"mappings":";;;AAQI,SAAG,UAAA,SAAA;CACO,SAAA,OAAA;;CAEP,eAAA,OAAA;CACC,MAAG,EAAA,MAAW,kBAAkB,YAAC;CACzC,MAAE,QAAO,eAAmB,KAAM,EAAA,SAAS,EAAA;;EAEzC,gBAAc,UAAc,OAAI;CAClC;;EAEE,gBAAgB,QAAS;CAC3B;QACE,EAAA,cAAA;EAAA,OAAA;EAAA,QAAA;CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,qBAAA;CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,qDAAA;CAAA,GAAA,CAAA,KAAA,eAAA,MAAA,CAAA,SAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,sBAAA;EAAA,aAAA,eAAA,MAAA,CAAA;CAAA,CAAA,CAAA,GAAA,EAAA,kBAAA;EAAA;EAAA,QAAA;EAAA;EAAA;CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAEA;AAEA,IAAA,iBAAA"}
|
|
@@ -105,6 +105,13 @@ function component($$props) {
|
|
|
105
105
|
confirmItem.set(null);
|
|
106
106
|
});
|
|
107
107
|
};
|
|
108
|
+
const stopEvent = (event) => {
|
|
109
|
+
event?.stopPropagation?.();
|
|
110
|
+
};
|
|
111
|
+
const cancelConfirmFromPointer = (event) => {
|
|
112
|
+
stopEvent(event);
|
|
113
|
+
cancelConfirm();
|
|
114
|
+
};
|
|
108
115
|
function confirmSelect(index) {
|
|
109
116
|
return function() {
|
|
110
117
|
selectedConfirm.set(index);
|
|
@@ -296,10 +303,26 @@ function component($$props) {
|
|
|
296
303
|
})])))])]),
|
|
297
304
|
cond(confirmOpen, () => h(DOMElement, {
|
|
298
305
|
element: "div",
|
|
299
|
-
attrs: {
|
|
300
|
-
|
|
306
|
+
attrs: {
|
|
307
|
+
class: "rpg-ui-menu-confirm",
|
|
308
|
+
click: cancelConfirmFromPointer
|
|
309
|
+
}
|
|
310
|
+
}, [h(DOMElement, {
|
|
311
|
+
element: "button",
|
|
312
|
+
attrs: {
|
|
313
|
+
class: "rpg-ui-close-button",
|
|
314
|
+
type: "button",
|
|
315
|
+
title: "Close",
|
|
316
|
+
"aria-label": "Close confirmation",
|
|
317
|
+
click: cancelConfirmFromPointer
|
|
318
|
+
},
|
|
319
|
+
textContent: "x"
|
|
320
|
+
}), h(DOMElement, {
|
|
301
321
|
element: "div",
|
|
302
|
-
attrs: {
|
|
322
|
+
attrs: {
|
|
323
|
+
class: "rpg-ui-menu-confirm-card",
|
|
324
|
+
click: stopEvent
|
|
325
|
+
}
|
|
303
326
|
}, [h(DOMElement, {
|
|
304
327
|
element: "div",
|
|
305
328
|
attrs: { class: "rpg-ui-menu-confirm-title" },
|
|
@@ -319,7 +342,7 @@ function component($$props) {
|
|
|
319
342
|
click: confirmSelect(index)
|
|
320
343
|
},
|
|
321
344
|
textContent: option.label
|
|
322
|
-
}))))])))
|
|
345
|
+
}))))])]))
|
|
323
346
|
]));
|
|
324
347
|
}
|
|
325
348
|
var __ce_component = component;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"items-menu.ce.js","names":[],"sources":["../../../../src/components/gui/menu/items-menu.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\">\n <div class=\"rpg-ui-menu-panel rpg-ui-panel\">\n <div class=\"rpg-ui-menu-panel-header\">{t(\"rpg.menu.items\")}</div>\n <div class=\"rpg-ui-menu-panel-body rpg-ui-menu-panel-body-stacked\">\n <div>\n @if (currentItem) {\n <div class=\"rpg-ui-menu-panel-details rpg-ui-panel\">\n <div class=\"rpg-ui-menu-panel-hero\">\n <div class=\"rpg-ui-menu-panel-hero-icon\">\n <DOMSprite \n sheet={iconSheet(currentItem()?.icon)} \n playing=\"default\" \n width=\"48px\"\n height=\"48px\"\n objectFit=\"contain\"\n />\n </div>\n <div>\n <div class=\"rpg-ui-menu-panel-details-title\">{currentItem()?.name}</div>\n <div class=\"rpg-ui-menu-panel-details-desc\">{currentItem()?.description || \"\"}</div>\n </div>\n </div>\n </div>\n }\n </div>\n \n <div class=\"rpg-ui-menu-panel-list rpg-ui-menu rpg-ui-menu-panel-list-full\">\n <div class=\"rpg-ui-menu-tabs\">\n @for ((tab,tabIndex) of tabs) {\n <div\n class=\"rpg-ui-menu-tab\"\n class={{active: selectedTab() === tabIndex}}\n tabindex={tabIndex}\n click={selectTab(tabIndex)}\n >{tab.label}</div>\n }\n </div>\n <Navigation tabindex={selectedItem} controls={controls}>\n @for ((item,index) of filteredItems) {\n <div\n class=\"rpg-ui-menu-item rpg-ui-menu-row\"\n class={{disabled: !item.usable}}\n data-selected={selectedItem() === index ? \"true\" : \"false\"}\n tabindex={index}\n click={selectItem(index)}\n >\n <div class=\"rpg-ui-menu-row-main\">\n <div class=\"rpg-ui-menu-row-icon\">\n <DOMSprite \n sheet={iconSheet(item.icon)} \n playing=\"default\" \n width=\"28px\"\n height=\"28px\"\n objectFit=\"contain\"\n />\n </div>\n <span>{item.name}</span>\n </div>\n <span class=\"rpg-ui-menu-row-end\">x{item.quantity ?? 1}</span>\n </div>\n }\n </Navigation>\n </div>\n </div>\n @if (confirmOpen) {\n <div class=\"rpg-ui-menu-confirm\">\n <div class=\"rpg-ui-menu-confirm-card\">\n <div class=\"rpg-ui-menu-confirm-title\">{t(\"rpg.menu.use\")} {confirmItem()?.name}?</div>\n <Navigation tabindex={selectedConfirm} controls={confirmControls}>\n <div class=\"rpg-ui-menu-confirm-actions\">\n @for ((option,index) of confirmOptions) {\n <button\n class=\"rpg-ui-menu-confirm-btn\"\n class={{\"rpg-ui-menu-confirm-btn-secondary\": option.id === \"cancel\"}}\n data-selected={selectedConfirm() === index ? \"true\" : \"false\"}\n tabindex={index}\n click={confirmSelect(index)}\n >{option.label}</button>\n }\n </div>\n </Navigation>\n </div>\n </div>\n }\n </div>\n</DOMContainer>\n\n<script>\n import { signal, computed, createTabindexNavigator, effect } from \"canvasengine\";\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import { delay } from \"@rpgjs/common\";\n import { getKeyboardControlBind } from \"../../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const { t } = engine.i18n();\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n const selectedItem = signal(0);\n const selectedTab = signal(0);\n const selectedConfirm = signal(0);\n const confirmOpen = signal(false);\n const confirmItem = signal(null);\n\n const { data, onInteraction, onBack } = defineProps();\n\n const items = computed(() => data().items);\n\n const tabs = [\n { id: \"item\", label: t(\"rpg.menu.items\") },\n { id: \"weapon\", label: t(\"rpg.menu.weapons\") },\n { id: \"armor\", label: t(\"rpg.menu.armor\") }\n ];\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const safeItems = computed(() => {\n const value = resolveProp(items);\n return Array.isArray(value) ? value : [];\n });\n\n const filteredItems = computed(() => {\n const items = safeItems();\n const tab = tabs[selectedTab()];\n if (!tab) return [];\n return items.filter((item) => item.type === tab.id && (item.quantity ?? 1) > 0);\n });\n\n const confirmOptions = [\n { id: \"use\", label: t(\"rpg.menu.use\") },\n { id: \"cancel\", label: t(\"rpg.menu.cancel\") }\n ];\n\n const nav = createTabindexNavigator(selectedItem, { count: () => filteredItems().length }, \"wrap\");\n const navConfirm = createTabindexNavigator(selectedConfirm, { count: () => confirmOptions.length }, \"wrap\");\n const currentItem = computed(() => filteredItems()[selectedItem()]);\n const iconSheet = (iconId) => ({\n definition: engine.getSpriteSheet(iconId)\n });\n\n const clampSelection = () => {\n const count = filteredItems().length;\n if (count === 0) {\n selectedItem.set(0);\n return;\n }\n if (selectedItem() >= count) {\n selectedItem.set(count - 1);\n }\n };\n\n function selectItem(index) {\n return function() {\n selectedItem.set(index);\n requestUseItem(index);\n }\n }\n\n function selectTab(index) {\n return function() {\n selectedItem.set(0);\n selectedTab.set(index);\n }\n }\n\n const useItem = (index) => {\n const item = filteredItems()[index];\n if (!item || !item.usable) return;\n if (onInteraction) onInteraction(\"useItem\", { id: item.id });\n };\n\n const requestUseItem = (index) => {\n const item = filteredItems()[index];\n if (!item || !item.usable) return;\n if (item.consumable) {\n confirmItem.set(item);\n confirmOpen.set(true);\n selectedConfirm.set(0);\n return;\n }\n useItem(index);\n };\n\n const confirmUse = () => {\n const item = confirmItem();\n if (!item) return;\n delay(() => {\n if (onInteraction) onInteraction(\"useItem\", { id: item.id });\n confirmOpen.set(false);\n confirmItem.set(null);\n });\n };\n\n const cancelConfirm = () => {\n delay(() => {\n confirmOpen.set(false);\n confirmItem.set(null);\n });\n };\n\n function confirmSelect(index) {\n return function() {\n selectedConfirm.set(index);\n if (index === 0) {\n confirmUse();\n return;\n }\n cancelConfirm();\n }\n }\n\n const confirmControls = signal({\n left: {\n repeat: true,\n bind: keyboardControls.left,\n throttle: 150,\n keyDown() {\n if (!confirmOpen()) return;\n navConfirm.next(-1);\n }\n },\n right: {\n repeat: true,\n bind: keyboardControls.right,\n throttle: 150,\n keyDown() {\n if (!confirmOpen()) return;\n navConfirm.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (!confirmOpen()) return;\n confirmSelect(selectedConfirm())();\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (!confirmOpen()) return;\n cancelConfirm();\n }\n }\n });\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n if (confirmOpen()) {\n return;\n }\n nav.next(-1);\n }\n },\n left: {\n repeat: true,\n bind: keyboardControls.left,\n throttle: 150,\n keyDown() {\n if (confirmOpen()) {\n return;\n }\n selectedTab.update((value) => (value - 1 + tabs.length) % tabs.length);\n selectedItem.set(0);\n }\n },\n right: {\n repeat: true,\n bind: keyboardControls.right,\n throttle: 150,\n keyDown() {\n if (confirmOpen()) {\n return;\n }\n selectedTab.update((value) => (value + 1) % tabs.length);\n selectedItem.set(0);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n if (confirmOpen()) {\n return;\n }\n nav.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (confirmOpen()) {\n confirmSelect(selectedConfirm())();\n return;\n }\n requestUseItem(selectedItem());\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (confirmOpen()) {\n cancelConfirm();\n return;\n }\n if (onBack) onBack();\n }\n },\n gamepad: {\n enabled: true\n }\n });\n\n clampSelection();\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"items-menu.ce.js","names":[],"sources":["../../../../src/components/gui/menu/items-menu.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\">\n <div class=\"rpg-ui-menu-panel rpg-ui-panel\">\n <div class=\"rpg-ui-menu-panel-header\">{t(\"rpg.menu.items\")}</div>\n <div class=\"rpg-ui-menu-panel-body rpg-ui-menu-panel-body-stacked\">\n <div>\n @if (currentItem) {\n <div class=\"rpg-ui-menu-panel-details rpg-ui-panel\">\n <div class=\"rpg-ui-menu-panel-hero\">\n <div class=\"rpg-ui-menu-panel-hero-icon\">\n <DOMSprite \n sheet={iconSheet(currentItem()?.icon)} \n playing=\"default\" \n width=\"48px\"\n height=\"48px\"\n objectFit=\"contain\"\n />\n </div>\n <div>\n <div class=\"rpg-ui-menu-panel-details-title\">{currentItem()?.name}</div>\n <div class=\"rpg-ui-menu-panel-details-desc\">{currentItem()?.description || \"\"}</div>\n </div>\n </div>\n </div>\n }\n </div>\n \n <div class=\"rpg-ui-menu-panel-list rpg-ui-menu rpg-ui-menu-panel-list-full\">\n <div class=\"rpg-ui-menu-tabs\">\n @for ((tab,tabIndex) of tabs) {\n <div\n class=\"rpg-ui-menu-tab\"\n class={{active: selectedTab() === tabIndex}}\n tabindex={tabIndex}\n click={selectTab(tabIndex)}\n >{tab.label}</div>\n }\n </div>\n <Navigation tabindex={selectedItem} controls={controls}>\n @for ((item,index) of filteredItems) {\n <div\n class=\"rpg-ui-menu-item rpg-ui-menu-row\"\n class={{disabled: !item.usable}}\n data-selected={selectedItem() === index ? \"true\" : \"false\"}\n tabindex={index}\n click={selectItem(index)}\n >\n <div class=\"rpg-ui-menu-row-main\">\n <div class=\"rpg-ui-menu-row-icon\">\n <DOMSprite \n sheet={iconSheet(item.icon)} \n playing=\"default\" \n width=\"28px\"\n height=\"28px\"\n objectFit=\"contain\"\n />\n </div>\n <span>{item.name}</span>\n </div>\n <span class=\"rpg-ui-menu-row-end\">x{item.quantity ?? 1}</span>\n </div>\n }\n </Navigation>\n </div>\n </div>\n @if (confirmOpen) {\n <div class=\"rpg-ui-menu-confirm\" click={cancelConfirmFromPointer}>\n <button class=\"rpg-ui-close-button\" type=\"button\" title=\"Close\" aria-label=\"Close confirmation\" click={cancelConfirmFromPointer}>x</button>\n <div class=\"rpg-ui-menu-confirm-card\" click={stopEvent}>\n <div class=\"rpg-ui-menu-confirm-title\">{t(\"rpg.menu.use\")} {confirmItem()?.name}?</div>\n <Navigation tabindex={selectedConfirm} controls={confirmControls}>\n <div class=\"rpg-ui-menu-confirm-actions\">\n @for ((option,index) of confirmOptions) {\n <button\n class=\"rpg-ui-menu-confirm-btn\"\n class={{\"rpg-ui-menu-confirm-btn-secondary\": option.id === \"cancel\"}}\n data-selected={selectedConfirm() === index ? \"true\" : \"false\"}\n tabindex={index}\n click={confirmSelect(index)}\n >{option.label}</button>\n }\n </div>\n </Navigation>\n </div>\n </div>\n }\n </div>\n</DOMContainer>\n\n<script>\n import { signal, computed, createTabindexNavigator, effect } from \"canvasengine\";\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import { delay } from \"@rpgjs/common\";\n import { getKeyboardControlBind } from \"../../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const { t } = engine.i18n();\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n const selectedItem = signal(0);\n const selectedTab = signal(0);\n const selectedConfirm = signal(0);\n const confirmOpen = signal(false);\n const confirmItem = signal(null);\n\n const { data, onInteraction, onBack } = defineProps();\n\n const items = computed(() => data().items);\n\n const tabs = [\n { id: \"item\", label: t(\"rpg.menu.items\") },\n { id: \"weapon\", label: t(\"rpg.menu.weapons\") },\n { id: \"armor\", label: t(\"rpg.menu.armor\") }\n ];\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const safeItems = computed(() => {\n const value = resolveProp(items);\n return Array.isArray(value) ? value : [];\n });\n\n const filteredItems = computed(() => {\n const items = safeItems();\n const tab = tabs[selectedTab()];\n if (!tab) return [];\n return items.filter((item) => item.type === tab.id && (item.quantity ?? 1) > 0);\n });\n\n const confirmOptions = [\n { id: \"use\", label: t(\"rpg.menu.use\") },\n { id: \"cancel\", label: t(\"rpg.menu.cancel\") }\n ];\n\n const nav = createTabindexNavigator(selectedItem, { count: () => filteredItems().length }, \"wrap\");\n const navConfirm = createTabindexNavigator(selectedConfirm, { count: () => confirmOptions.length }, \"wrap\");\n const currentItem = computed(() => filteredItems()[selectedItem()]);\n const iconSheet = (iconId) => ({\n definition: engine.getSpriteSheet(iconId)\n });\n\n const clampSelection = () => {\n const count = filteredItems().length;\n if (count === 0) {\n selectedItem.set(0);\n return;\n }\n if (selectedItem() >= count) {\n selectedItem.set(count - 1);\n }\n };\n\n function selectItem(index) {\n return function() {\n selectedItem.set(index);\n requestUseItem(index);\n }\n }\n\n function selectTab(index) {\n return function() {\n selectedItem.set(0);\n selectedTab.set(index);\n }\n }\n\n const useItem = (index) => {\n const item = filteredItems()[index];\n if (!item || !item.usable) return;\n if (onInteraction) onInteraction(\"useItem\", { id: item.id });\n };\n\n const requestUseItem = (index) => {\n const item = filteredItems()[index];\n if (!item || !item.usable) return;\n if (item.consumable) {\n confirmItem.set(item);\n confirmOpen.set(true);\n selectedConfirm.set(0);\n return;\n }\n useItem(index);\n };\n\n const confirmUse = () => {\n const item = confirmItem();\n if (!item) return;\n delay(() => {\n if (onInteraction) onInteraction(\"useItem\", { id: item.id });\n confirmOpen.set(false);\n confirmItem.set(null);\n });\n };\n\n const cancelConfirm = () => {\n delay(() => {\n confirmOpen.set(false);\n confirmItem.set(null);\n });\n };\n\n const stopEvent = (event) => {\n event?.stopPropagation?.();\n };\n\n const cancelConfirmFromPointer = (event) => {\n stopEvent(event);\n cancelConfirm();\n };\n\n function confirmSelect(index) {\n return function() {\n selectedConfirm.set(index);\n if (index === 0) {\n confirmUse();\n return;\n }\n cancelConfirm();\n }\n }\n\n const confirmControls = signal({\n left: {\n repeat: true,\n bind: keyboardControls.left,\n throttle: 150,\n keyDown() {\n if (!confirmOpen()) return;\n navConfirm.next(-1);\n }\n },\n right: {\n repeat: true,\n bind: keyboardControls.right,\n throttle: 150,\n keyDown() {\n if (!confirmOpen()) return;\n navConfirm.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (!confirmOpen()) return;\n confirmSelect(selectedConfirm())();\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (!confirmOpen()) return;\n cancelConfirm();\n }\n }\n });\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n if (confirmOpen()) {\n return;\n }\n nav.next(-1);\n }\n },\n left: {\n repeat: true,\n bind: keyboardControls.left,\n throttle: 150,\n keyDown() {\n if (confirmOpen()) {\n return;\n }\n selectedTab.update((value) => (value - 1 + tabs.length) % tabs.length);\n selectedItem.set(0);\n }\n },\n right: {\n repeat: true,\n bind: keyboardControls.right,\n throttle: 150,\n keyDown() {\n if (confirmOpen()) {\n return;\n }\n selectedTab.update((value) => (value + 1) % tabs.length);\n selectedItem.set(0);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n if (confirmOpen()) {\n return;\n }\n nav.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (confirmOpen()) {\n confirmSelect(selectedConfirm())();\n return;\n }\n requestUseItem(selectedItem());\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (confirmOpen()) {\n cancelConfirm();\n return;\n }\n if (onBack) onBack();\n }\n },\n gamepad: {\n enabled: true\n }\n });\n\n clampSelection();\n</script>\n"],"mappings":"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"}
|