@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.
Files changed (47) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/Game/Object.d.ts +5 -0
  3. package/dist/Game/Object.js +48 -2
  4. package/dist/Game/Object.js.map +1 -1
  5. package/dist/Gui/Gui.js +5 -0
  6. package/dist/Gui/Gui.js.map +1 -1
  7. package/dist/components/character.ce.js +9 -2
  8. package/dist/components/character.ce.js.map +1 -1
  9. package/dist/components/gui/dialogbox/index.ce.js +54 -4
  10. package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
  11. package/dist/components/gui/hud/hud.ce.js +2 -2
  12. package/dist/components/gui/hud/hud.ce.js.map +1 -1
  13. package/dist/components/gui/index.d.ts +3 -1
  14. package/dist/components/gui/index.js +2 -0
  15. package/dist/components/gui/input-field.ce.js +123 -0
  16. package/dist/components/gui/input-field.ce.js.map +1 -0
  17. package/dist/components/gui/input.ce.js +40 -0
  18. package/dist/components/gui/input.ce.js.map +1 -0
  19. package/dist/components/gui/menu/items-menu.ce.js +27 -4
  20. package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
  21. package/dist/components/gui/menu/main-menu.ce.js +210 -155
  22. package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
  23. package/dist/components/gui/save-load.ce.js +33 -4
  24. package/dist/components/gui/save-load.ce.js.map +1 -1
  25. package/dist/components/gui/shop/shop.ce.js +47 -4
  26. package/dist/components/gui/shop/shop.ce.js.map +1 -1
  27. package/dist/i18n.d.ts +11 -0
  28. package/dist/i18n.js +11 -0
  29. package/dist/i18n.js.map +1 -1
  30. package/dist/index.js +13 -11
  31. package/package.json +4 -4
  32. package/src/Game/Object.spec.ts +26 -2
  33. package/src/Game/Object.ts +71 -2
  34. package/src/Gui/Gui.spec.ts +5 -0
  35. package/src/Gui/Gui.ts +5 -1
  36. package/src/components/character.ce +12 -6
  37. package/src/components/gui/dialogbox/index.ce +82 -41
  38. package/src/components/gui/hud/hud.ce +2 -2
  39. package/src/components/gui/index.ts +5 -1
  40. package/src/components/gui/input-field.ce +106 -0
  41. package/src/components/gui/input.ce +26 -0
  42. package/src/components/gui/menu/items-menu.ce +12 -2
  43. package/src/components/gui/menu/main-menu.ce +37 -6
  44. package/src/components/gui/save-load.ce +48 -32
  45. package/src/components/gui/shop/shop.ce +28 -3
  46. package/src/i18n.ts +11 -0
  47. package/vite.config.ts +5 -2
@@ -112,6 +112,24 @@ function component($$props) {
112
112
  view.set("menu");
113
113
  });
114
114
  };
115
+ const stopEvent = (event) => {
116
+ event?.stopPropagation?.();
117
+ };
118
+ const closeSaveOverlayFromPointer = (event) => {
119
+ stopEvent(event);
120
+ closeSaveOverlay();
121
+ };
122
+ const closeMenu = () => {
123
+ if (saveOverlay()) {
124
+ closeSaveOverlay();
125
+ return;
126
+ }
127
+ onFinish();
128
+ };
129
+ const closeMenuFromPointer = (event) => {
130
+ stopEvent(event);
131
+ closeMenu();
132
+ };
115
133
  const confirmExit = () => {
116
134
  if (onInteraction) onInteraction("exit");
117
135
  };
@@ -210,11 +228,18 @@ function component($$props) {
210
228
  gamepad: { enabled: true }
211
229
  });
212
230
  mount((element) => {
231
+ const inputLockToken = {};
232
+ const previousStopProcessingInput = engine.stopProcessingInput;
233
+ const previousGamePause = engine.gamePause();
234
+ engine.__rpgMainMenuInputLock = inputLockToken;
235
+ engine.stopProcessingInput = true;
213
236
  engine.gamePause.set(true);
214
237
  return () => {
215
238
  delay(() => {
216
- engine.stopProcessingInput = false;
217
- engine.gamePause.set(false);
239
+ if (engine.__rpgMainMenuInputLock !== inputLockToken) return;
240
+ engine.__rpgMainMenuInputLock = void 0;
241
+ engine.stopProcessingInput = previousStopProcessingInput;
242
+ engine.gamePause.set(previousGamePause);
218
243
  });
219
244
  };
220
245
  });
@@ -223,177 +248,207 @@ function component($$props) {
223
248
  height: "100%",
224
249
  controls: menuControls
225
250
  }, h(DOMElement, {
226
- element: "div",
227
- attrs: { class: "rpg-ui-main-menu rpg-anim-fade-in" }
228
- }, [h(DOMElement, {
229
- element: "div",
230
- attrs: { class: "rpg-ui-main-menu-layout" }
231
- }, [h(DOMElement, {
232
- element: "div",
233
- attrs: { class: "rpg-ui-main-menu-left rpg-ui-menu rpg-ui-panel" }
234
- }, [h(DOMElement, {
235
- element: "div",
236
- attrs: { class: "rpg-ui-menu-header" },
237
- textContent: computed(() => t("rpg.menu.title"))
238
- }), h(DOMElement, {
239
- element: "div",
240
- attrs: { class: "rpg-ui-main-menu-list" }
241
- }, loop(computed(() => menuEntries()), (entry, index) => h(DOMElement, {
242
251
  element: "div",
243
252
  attrs: {
244
- class: ["rpg-ui-menu-item", computed(() => ({ disabled: isMenuDisabled(entry) }))],
245
- "data-selected": computed(() => selectedMenu() === index ? "true" : "false"),
246
- tabindex: index,
247
- click: selectMenu(index)
248
- },
249
- textContent: entry.label
250
- })))]), h(DOMElement, {
251
- element: "div",
252
- attrs: { class: "rpg-ui-main-menu-right" }
253
+ class: "rpg-ui-main-menu rpg-anim-fade-in",
254
+ click: closeMenuFromPointer
255
+ }
253
256
  }, [
254
- cond(computed(() => view() === "menu"), () => h(DOMElement, {
257
+ h(DOMElement, {
255
258
  element: "div",
256
- attrs: { class: "rpg-ui-panel" }
259
+ attrs: { class: "rpg-ui-main-menu-backdrop" }
260
+ }),
261
+ h(DOMElement, {
262
+ element: "button",
263
+ attrs: {
264
+ class: "rpg-ui-close-button",
265
+ type: "button",
266
+ title: "Close",
267
+ "aria-label": "Close menu",
268
+ click: closeMenuFromPointer
269
+ },
270
+ textContent: "x"
271
+ }),
272
+ h(DOMElement, {
273
+ element: "div",
274
+ attrs: {
275
+ class: "rpg-ui-main-menu-layout",
276
+ click: stopEvent
277
+ }
278
+ }, [h(DOMElement, {
279
+ element: "div",
280
+ attrs: { class: "rpg-ui-main-menu-left rpg-ui-menu rpg-ui-panel" }
281
+ }, [h(DOMElement, {
282
+ element: "div",
283
+ attrs: { class: "rpg-ui-menu-header" },
284
+ textContent: computed(() => t("rpg.menu.title"))
285
+ }), h(DOMElement, {
286
+ element: "div",
287
+ attrs: { class: "rpg-ui-main-menu-list" }
288
+ }, loop(computed(() => menuEntries()), (entry, index) => h(DOMElement, {
289
+ element: "div",
290
+ attrs: {
291
+ class: ["rpg-ui-menu-item", computed(() => ({ disabled: isMenuDisabled(entry) }))],
292
+ "data-selected": computed(() => selectedMenu() === index ? "true" : "false"),
293
+ tabindex: index,
294
+ click: selectMenu(index)
295
+ },
296
+ textContent: entry.label
297
+ })))]), h(DOMElement, {
298
+ element: "div",
299
+ attrs: { class: "rpg-ui-main-menu-right" }
257
300
  }, [
258
- h(DOMElement, {
259
- element: "div",
260
- attrs: { class: "rpg-ui-main-menu-section-title" },
261
- textContent: computed(() => t("rpg.menu.status"))
262
- }),
263
- h(DOMElement, {
301
+ cond(computed(() => view() === "menu"), () => h(DOMElement, {
264
302
  element: "div",
265
- attrs: { class: "rpg-ui-main-menu-status-card" }
303
+ attrs: { class: "rpg-ui-panel" }
266
304
  }, [
267
305
  h(DOMElement, {
268
306
  element: "div",
269
- attrs: { class: "rpg-ui-main-menu-status-block" }
270
- }, [h(DOMElement, {
271
- element: "div",
272
- attrs: { class: "rpg-ui-main-menu-status-label" },
273
- textContent: computed(() => t("rpg.menu.level"))
274
- }), h(DOMElement, {
275
- element: "div",
276
- attrs: { class: "rpg-ui-main-menu-status-value" },
277
- textContent: computed(() => level())
278
- })]),
307
+ attrs: { class: "rpg-ui-main-menu-section-title" },
308
+ textContent: computed(() => t("rpg.menu.status"))
309
+ }),
279
310
  h(DOMElement, {
280
311
  element: "div",
281
- attrs: { class: "rpg-ui-main-menu-status-block" }
282
- }, [h(DOMElement, {
283
- element: "div",
284
- attrs: { class: "rpg-ui-main-menu-status-label" },
285
- textContent: computed(() => t("rpg.menu.gold"))
286
- }), h(DOMElement, {
287
- element: "div",
288
- attrs: { class: "rpg-ui-main-menu-status-value" },
289
- textContent: computed(() => gold())
290
- })]),
312
+ attrs: { class: "rpg-ui-main-menu-status-card" }
313
+ }, [
314
+ h(DOMElement, {
315
+ element: "div",
316
+ attrs: { class: "rpg-ui-main-menu-status-block" }
317
+ }, [h(DOMElement, {
318
+ element: "div",
319
+ attrs: { class: "rpg-ui-main-menu-status-label" },
320
+ textContent: computed(() => t("rpg.menu.level"))
321
+ }), h(DOMElement, {
322
+ element: "div",
323
+ attrs: { class: "rpg-ui-main-menu-status-value" },
324
+ textContent: computed(() => level())
325
+ })]),
326
+ h(DOMElement, {
327
+ element: "div",
328
+ attrs: { class: "rpg-ui-main-menu-status-block" }
329
+ }, [h(DOMElement, {
330
+ element: "div",
331
+ attrs: { class: "rpg-ui-main-menu-status-label" },
332
+ textContent: computed(() => t("rpg.menu.gold"))
333
+ }), h(DOMElement, {
334
+ element: "div",
335
+ attrs: { class: "rpg-ui-main-menu-status-value" },
336
+ textContent: computed(() => gold())
337
+ })]),
338
+ h(DOMElement, {
339
+ element: "div",
340
+ attrs: { class: "rpg-ui-main-menu-status-block" }
341
+ }, [h(DOMElement, {
342
+ element: "div",
343
+ attrs: { class: "rpg-ui-main-menu-status-label" },
344
+ textContent: computed(() => "HP " + hp() + "/" + hpMax())
345
+ }), h(DOMElement, {
346
+ element: "div",
347
+ attrs: { class: "rpg-ui-main-menu-status-bar" }
348
+ }, h(DOMElement, {
349
+ element: "div",
350
+ attrs: {
351
+ class: "rpg-ui-main-menu-status-bar-fill hp",
352
+ style: { width: hpPercent }
353
+ }
354
+ }))]),
355
+ h(DOMElement, {
356
+ element: "div",
357
+ attrs: { class: "rpg-ui-main-menu-status-block" }
358
+ }, [h(DOMElement, {
359
+ element: "div",
360
+ attrs: { class: "rpg-ui-main-menu-status-label" },
361
+ textContent: computed(() => "SP " + sp() + "/" + spMax())
362
+ }), h(DOMElement, {
363
+ element: "div",
364
+ attrs: { class: "rpg-ui-main-menu-status-bar" }
365
+ }, h(DOMElement, {
366
+ element: "div",
367
+ attrs: {
368
+ class: "rpg-ui-main-menu-status-bar-fill sp",
369
+ style: { width: spPercent }
370
+ }
371
+ }))]),
372
+ h(DOMElement, {
373
+ element: "div",
374
+ attrs: {
375
+ class: "rpg-ui-main-menu-status-block",
376
+ style: { gridColumn: "span 2" }
377
+ }
378
+ }, [h(DOMElement, {
379
+ element: "div",
380
+ attrs: { class: "rpg-ui-main-menu-status-label" },
381
+ textContent: computed(() => "EXP " + exp() + "/" + expForNextlevel())
382
+ }), h(DOMElement, {
383
+ element: "div",
384
+ attrs: { class: "rpg-ui-main-menu-status-bar" }
385
+ }, h(DOMElement, {
386
+ element: "div",
387
+ attrs: {
388
+ class: "rpg-ui-main-menu-status-bar-fill exp",
389
+ style: { width: expPercent }
390
+ }
391
+ }))])
392
+ ]),
291
393
  h(DOMElement, {
292
394
  element: "div",
293
- attrs: { class: "rpg-ui-main-menu-status-block" }
294
- }, [h(DOMElement, {
295
- element: "div",
296
- attrs: { class: "rpg-ui-main-menu-status-label" },
297
- textContent: computed(() => "HP " + hp() + "/" + hpMax())
298
- }), h(DOMElement, {
299
- element: "div",
300
- attrs: { class: "rpg-ui-main-menu-status-bar" }
301
- }, h(DOMElement, {
302
- element: "div",
303
- attrs: {
304
- class: "rpg-ui-main-menu-status-bar-fill hp",
305
- style: { width: hpPercent }
306
- }
307
- }))]),
395
+ attrs: { class: "rpg-ui-main-menu-section-title" },
396
+ textContent: computed(() => t("rpg.menu.parameters"))
397
+ }),
308
398
  h(DOMElement, {
309
399
  element: "div",
310
- attrs: { class: "rpg-ui-main-menu-status-block" }
311
- }, [h(DOMElement, {
312
- element: "div",
313
- attrs: { class: "rpg-ui-main-menu-status-label" },
314
- textContent: computed(() => "SP " + sp() + "/" + spMax())
315
- }), h(DOMElement, {
316
- element: "div",
317
- attrs: { class: "rpg-ui-main-menu-status-bar" }
318
- }, h(DOMElement, {
319
- element: "div",
320
- attrs: {
321
- class: "rpg-ui-main-menu-status-bar-fill sp",
322
- style: { width: spPercent }
323
- }
324
- }))]),
325
- h(DOMElement, {
400
+ attrs: { class: "rpg-ui-main-menu-params" }
401
+ }, loop(paramsList, (param, index) => h(DOMElement, {
326
402
  element: "div",
327
- attrs: {
328
- class: "rpg-ui-main-menu-status-block",
329
- style: { gridColumn: "span 2" }
330
- }
403
+ attrs: { class: "rpg-ui-main-menu-param" }
331
404
  }, [h(DOMElement, {
332
- element: "div",
333
- attrs: { class: "rpg-ui-main-menu-status-label" },
334
- textContent: computed(() => "EXP " + exp() + "/" + expForNextlevel())
405
+ element: "span",
406
+ textContent: param.label
335
407
  }), h(DOMElement, {
336
- element: "div",
337
- attrs: { class: "rpg-ui-main-menu-status-bar" }
338
- }, h(DOMElement, {
339
- element: "div",
340
- attrs: {
341
- class: "rpg-ui-main-menu-status-bar-fill exp",
342
- style: { width: expPercent }
343
- }
344
- }))])
345
- ]),
346
- h(DOMElement, {
347
- element: "div",
348
- attrs: { class: "rpg-ui-main-menu-section-title" },
349
- textContent: computed(() => t("rpg.menu.parameters"))
350
- }),
351
- h(DOMElement, {
352
- element: "div",
353
- attrs: { class: "rpg-ui-main-menu-params" }
354
- }, loop(paramsList, (param, index) => h(DOMElement, {
355
- element: "div",
356
- attrs: { class: "rpg-ui-main-menu-param" }
357
- }, [h(DOMElement, {
358
- element: "span",
359
- textContent: param.label
360
- }), h(DOMElement, {
361
- element: "span",
362
- textContent: param.value
363
- })])))
364
- ])),
365
- cond(computed(() => view() === "items"), () => h(__ce_component$2, {
366
- data,
367
- onInteraction,
368
- onBack: goBack
369
- })),
370
- cond(computed(() => view() === "skills"), () => h(__ce_component$3, {
371
- data,
372
- onBack: goBack
373
- })),
374
- cond(computed(() => view() === "equip"), () => h(__ce_component$4, {
375
- data,
376
- onInteraction,
377
- onBack: goBack
378
- })),
379
- cond(computed(() => view() === "options"), () => h(__ce_component$5, { onBack: goBack })),
380
- cond(computed(() => view() === "exit"), () => h(__ce_component$6, {
381
- onConfirm: confirmExit,
382
- onBack: goBack
383
- }))
384
- ])]), cond(saveOverlay, () => h(DOMElement, {
385
- element: "div",
386
- attrs: { class: "rpg-ui-main-menu-overlay" }
387
- }, [h(DOMElement, {
388
- element: "div",
389
- attrs: { class: "rpg-ui-main-menu-overlay-backdrop" }
390
- }), h(DOMElement, {
391
- element: "div",
392
- attrs: { class: "rpg-ui-main-menu-overlay-content" }
393
- }, h(__ce_component$1, {
394
- data: saveLoadData,
395
- onFinish: closeSaveOverlay
396
- }))]))]));
408
+ element: "span",
409
+ textContent: param.value
410
+ })])))
411
+ ])),
412
+ cond(computed(() => view() === "items"), () => h(__ce_component$2, {
413
+ data,
414
+ onInteraction,
415
+ onBack: goBack
416
+ })),
417
+ cond(computed(() => view() === "skills"), () => h(__ce_component$3, {
418
+ data,
419
+ onBack: goBack
420
+ })),
421
+ cond(computed(() => view() === "equip"), () => h(__ce_component$4, {
422
+ data,
423
+ onInteraction,
424
+ onBack: goBack
425
+ })),
426
+ cond(computed(() => view() === "options"), () => h(__ce_component$5, { onBack: goBack })),
427
+ cond(computed(() => view() === "exit"), () => h(__ce_component$6, {
428
+ onConfirm: confirmExit,
429
+ onBack: goBack
430
+ }))
431
+ ])]),
432
+ cond(saveOverlay, () => h(DOMElement, {
433
+ element: "div",
434
+ attrs: { class: "rpg-ui-main-menu-overlay" }
435
+ }, [h(DOMElement, {
436
+ element: "div",
437
+ attrs: {
438
+ class: "rpg-ui-main-menu-overlay-backdrop",
439
+ click: closeSaveOverlayFromPointer
440
+ }
441
+ }), h(DOMElement, {
442
+ element: "div",
443
+ attrs: {
444
+ class: "rpg-ui-main-menu-overlay-content",
445
+ click: stopEvent
446
+ }
447
+ }, h(__ce_component$1, {
448
+ data: saveLoadData,
449
+ onFinish: closeSaveOverlay
450
+ }))]))
451
+ ]));
397
452
  }
398
453
  var __ce_component = component;
399
454
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"main-menu.ce.js","names":[],"sources":["../../../../src/components/gui/menu/main-menu.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\" controls={menuControls}>\n <div class=\"rpg-ui-main-menu rpg-anim-fade-in\">\n <div class=\"rpg-ui-main-menu-layout\">\n <div class=\"rpg-ui-main-menu-left rpg-ui-menu rpg-ui-panel\">\n <div class=\"rpg-ui-menu-header\">{t(\"rpg.menu.title\")}</div>\n <div class=\"rpg-ui-main-menu-list\">\n @for ((entry,index) of menuEntries()) {\n <div\n class=\"rpg-ui-menu-item\"\n class={{disabled: isMenuDisabled(entry)}}\n data-selected={selectedMenu() === index ? \"true\" : \"false\"}\n tabindex={index}\n click={selectMenu(index)}\n >{entry.label}</div>\n }\n </div>\n </div>\n <div class=\"rpg-ui-main-menu-right\">\n @if (view() === \"menu\") {\n <div class=\"rpg-ui-panel\">\n <div class=\"rpg-ui-main-menu-section-title\">{t(\"rpg.menu.status\")}</div>\n <div class=\"rpg-ui-main-menu-status-card\">\n <div class=\"rpg-ui-main-menu-status-block\">\n <div class=\"rpg-ui-main-menu-status-label\">{t(\"rpg.menu.level\")}</div>\n <div class=\"rpg-ui-main-menu-status-value\">{level()}</div>\n </div>\n <div class=\"rpg-ui-main-menu-status-block\">\n <div class=\"rpg-ui-main-menu-status-label\">{t(\"rpg.menu.gold\")}</div>\n <div class=\"rpg-ui-main-menu-status-value\">{gold()}</div>\n </div>\n <div class=\"rpg-ui-main-menu-status-block\">\n <div class=\"rpg-ui-main-menu-status-label\">HP {hp()}/{hpMax()}</div>\n <div class=\"rpg-ui-main-menu-status-bar\">\n <div class=\"rpg-ui-main-menu-status-bar-fill hp\" style={{width: hpPercent}}></div>\n </div>\n </div>\n <div class=\"rpg-ui-main-menu-status-block\">\n <div class=\"rpg-ui-main-menu-status-label\">SP {sp()}/{spMax()}</div>\n <div class=\"rpg-ui-main-menu-status-bar\">\n <div class=\"rpg-ui-main-menu-status-bar-fill sp\" style={{width: spPercent}}></div>\n </div>\n </div>\n <div class=\"rpg-ui-main-menu-status-block\" style={{gridColumn: \"span 2\"}}>\n <div class=\"rpg-ui-main-menu-status-label\">EXP {exp()}/{expForNextlevel()}</div>\n <div class=\"rpg-ui-main-menu-status-bar\">\n <div class=\"rpg-ui-main-menu-status-bar-fill exp\" style={{width: expPercent}}></div>\n </div>\n </div>\n </div>\n <div class=\"rpg-ui-main-menu-section-title\">{t(\"rpg.menu.parameters\")}</div>\n <div class=\"rpg-ui-main-menu-params\">\n @for ((param,index) of paramsList) {\n <div class=\"rpg-ui-main-menu-param\">\n <span>{param.label}</span>\n <span>{param.value}</span>\n </div>\n }\n </div>\n </div>\n }\n @if (view() === \"items\") {\n <ItemsMenu data={data} onInteraction={onInteraction} onBack={goBack} />\n }\n @if (view() === \"skills\") {\n <SkillsMenu data={data} onBack={goBack} />\n }\n @if (view() === \"equip\") {\n <EquipMenu data={data} onInteraction={onInteraction} onBack={goBack} />\n }\n @if (view() === \"options\") {\n <OptionsMenu onBack={goBack} />\n }\n @if (view() === \"exit\") {\n <ExitMenu onConfirm={confirmExit} onBack={goBack} />\n }\n </div>\n </div>\n @if (saveOverlay) {\n <div class=\"rpg-ui-main-menu-overlay\">\n <div class=\"rpg-ui-main-menu-overlay-backdrop\"></div>\n <div class=\"rpg-ui-main-menu-overlay-content\">\n <SaveLoadComponent\n data={saveLoadData}\n onFinish={closeSaveOverlay}\n />\n </div>\n </div>\n }\n </div>\n</DOMContainer>\n\n<script>\n import { signal, computed, effect, mount } from \"canvasengine\";\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import SaveLoadComponent from \"../save-load.ce\";\n import ItemsMenu from \"./items-menu.ce\";\n import SkillsMenu from \"./skills-menu.ce\";\n import EquipMenu from \"./equip-menu.ce\";\n import OptionsMenu from \"./options-menu.ce\";\n import ExitMenu from \"./exit-menu.ce\";\n import { getEntityProp } from \"../../../utils/getEntityProp\";\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 currentPlayer = engine.scene.currentPlayer;\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n const { data, onFinish, onInteraction } = defineProps();\n const { menus, items, skills, equips, saveLoad } = data();\n\n const defaultMenus = [\n { id: \"items\", label: t(\"rpg.menu.items\") },\n { id: \"skills\", label: t(\"rpg.menu.skills\") },\n { id: \"equip\", label: t(\"rpg.menu.equip\") },\n { id: \"options\", label: t(\"rpg.menu.options\") },\n { id: \"save\", label: t(\"rpg.menu.save\") },\n { id: \"exit\", label: t(\"rpg.menu.exit\") }\n ];\n\n const menuEntries = computed(() => {\n if (menus && Array.isArray(menus) && menus.length) return menus;\n return defaultMenus;\n });\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const saveLoadData = computed(() => resolveProp(saveLoad) || {});\n const saveLoadMode = computed(() => saveLoadData().mode || \"load\");\n const saveLoadSlots = computed(() => saveLoadData().slots || []);\n const saveLoadCanSave = computed(() => saveLoadData().canSave !== false);\n\n const isMenuDisabled = (entry) => {\n if (!entry) return true;\n if (entry.disabled) return true;\n if (entry.enabled === false) return true;\n if (entry.id === \"save\" && !saveLoadCanSave()) return true;\n return false;\n };\n\n const selectedMenu = signal(0);\n const view = signal(\"menu\");\n const saveOverlay = signal(false);\n\n const selectableIndexes = computed(() => {\n const entries = menuEntries();\n return entries\n .map((entry, index) => (isMenuDisabled(entry) ? null : index))\n .filter((value) => value !== null);\n });\n\n effect(() => {\n const available = selectableIndexes();\n if (!available.length) return;\n const current = selectedMenu();\n if (!available.includes(current)) {\n selectedMenu.set(available[0]);\n }\n });\n\n const moveMenu = (delta) => {\n const available = selectableIndexes();\n if (!available.length) return;\n const current = selectedMenu();\n const currentIndex = Math.max(0, available.indexOf(current));\n const nextIndex = (currentIndex + delta + available.length) % available.length;\n selectedMenu.set(available[nextIndex]);\n };\n\n function selectMenu(index) {\n return function() {\n selectedMenu.set(index);\n openMenu();\n }\n }\n\n const openMenu = () => {\n const entry = menuEntries()[selectedMenu()];\n if (!entry || isMenuDisabled(entry)) return;\n if (entry.id === \"save\") {\n saveOverlay.set(true);\n return;\n }\n if (entry.id === \"exit\") {\n view.set(\"exit\");\n return;\n }\n view.set(entry.id);\n };\n\n const goBack = () => {\n delay(() => {\n view.set(\"menu\");\n });\n };\n\n const closeSaveOverlay = () => {\n delay(() => {\n saveOverlay.set(false);\n view.set(\"menu\");\n });\n };\n\n const confirmExit = () => {\n if (onInteraction) onInteraction(\"exit\");\n };\n\n const hp = getEntityProp(currentPlayer, \"hp\");\n const hpMax = getEntityProp(currentPlayer, \"params.maxHp\");\n const sp = getEntityProp(currentPlayer, \"sp\");\n const spMax = getEntityProp(currentPlayer, \"params.maxSp\");\n const level = getEntityProp(currentPlayer, \"level\");\n const exp = getEntityProp(currentPlayer, \"exp\");\n const gold = getEntityProp(currentPlayer, \"gold\");\n const expForNextlevel = computed(() => data().expForNextlevel || 0);\n const hpPercent = computed(() => {\n const max = hpMax() || 1;\n return `${Math.max(0, Math.min(100, (hp() / max) * 100))}%`;\n });\n const spPercent = computed(() => {\n const max = spMax() || 1;\n return `${Math.max(0, Math.min(100, (sp() / max) * 100))}%`;\n });\n const expPercent = computed(() => {\n const max = expForNextlevel() || 1;\n return `${Math.max(0, Math.min(100, (exp() / max) * 100))}%`;\n });\n\n const paramsList = computed(() => {\n return [\n { label: \"ATK\", value: data().playerStats.atk },\n { label: \"PDEF\", value: data().playerStats.pdef },\n { label: \"SDEF\", value: data().playerStats.sdef },\n { label: \"STR\", value: data().playerStats.str },\n { label: \"DEX\", value: data().playerStats.dex },\n { label: \"INT\", value: data().playerStats.int },\n { label: \"AGI\", value: data().playerStats.agi }\n ]\n }\n\n const menuControls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n if (saveOverlay()) return;\n if (view() !== \"menu\") return;\n moveMenu(-1);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n if (saveOverlay()) return;\n if (view() !== \"menu\") return;\n moveMenu(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (saveOverlay()) return;\n if (view() !== \"menu\") return;\n openMenu();\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (saveOverlay()) return;\n if (view() !== \"menu\") {\n goBack();\n return;\n }\n onFinish()\n }\n },\n gamepad: {\n enabled: true\n }\n });\n\n mount((element) => {\n engine.gamePause.set(true);\n return () => {\n delay(() => {\n engine.stopProcessingInput = false;\n engine.gamePause.set(false);\n });\n }\n });\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"main-menu.ce.js","names":[],"sources":["../../../../src/components/gui/menu/main-menu.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\" controls={menuControls}>\n <div class=\"rpg-ui-main-menu rpg-anim-fade-in\" click={closeMenuFromPointer}>\n <div class=\"rpg-ui-main-menu-backdrop\"></div>\n <button class=\"rpg-ui-close-button\" type=\"button\" title=\"Close\" aria-label=\"Close menu\" click={closeMenuFromPointer}>x</button>\n <div class=\"rpg-ui-main-menu-layout\" click={stopEvent}>\n <div class=\"rpg-ui-main-menu-left rpg-ui-menu rpg-ui-panel\">\n <div class=\"rpg-ui-menu-header\">{t(\"rpg.menu.title\")}</div>\n <div class=\"rpg-ui-main-menu-list\">\n @for ((entry,index) of menuEntries()) {\n <div\n class=\"rpg-ui-menu-item\"\n class={{disabled: isMenuDisabled(entry)}}\n data-selected={selectedMenu() === index ? \"true\" : \"false\"}\n tabindex={index}\n click={selectMenu(index)}\n >{entry.label}</div>\n }\n </div>\n </div>\n <div class=\"rpg-ui-main-menu-right\">\n @if (view() === \"menu\") {\n <div class=\"rpg-ui-panel\">\n <div class=\"rpg-ui-main-menu-section-title\">{t(\"rpg.menu.status\")}</div>\n <div class=\"rpg-ui-main-menu-status-card\">\n <div class=\"rpg-ui-main-menu-status-block\">\n <div class=\"rpg-ui-main-menu-status-label\">{t(\"rpg.menu.level\")}</div>\n <div class=\"rpg-ui-main-menu-status-value\">{level()}</div>\n </div>\n <div class=\"rpg-ui-main-menu-status-block\">\n <div class=\"rpg-ui-main-menu-status-label\">{t(\"rpg.menu.gold\")}</div>\n <div class=\"rpg-ui-main-menu-status-value\">{gold()}</div>\n </div>\n <div class=\"rpg-ui-main-menu-status-block\">\n <div class=\"rpg-ui-main-menu-status-label\">HP {hp()}/{hpMax()}</div>\n <div class=\"rpg-ui-main-menu-status-bar\">\n <div class=\"rpg-ui-main-menu-status-bar-fill hp\" style={{width: hpPercent}}></div>\n </div>\n </div>\n <div class=\"rpg-ui-main-menu-status-block\">\n <div class=\"rpg-ui-main-menu-status-label\">SP {sp()}/{spMax()}</div>\n <div class=\"rpg-ui-main-menu-status-bar\">\n <div class=\"rpg-ui-main-menu-status-bar-fill sp\" style={{width: spPercent}}></div>\n </div>\n </div>\n <div class=\"rpg-ui-main-menu-status-block\" style={{gridColumn: \"span 2\"}}>\n <div class=\"rpg-ui-main-menu-status-label\">EXP {exp()}/{expForNextlevel()}</div>\n <div class=\"rpg-ui-main-menu-status-bar\">\n <div class=\"rpg-ui-main-menu-status-bar-fill exp\" style={{width: expPercent}}></div>\n </div>\n </div>\n </div>\n <div class=\"rpg-ui-main-menu-section-title\">{t(\"rpg.menu.parameters\")}</div>\n <div class=\"rpg-ui-main-menu-params\">\n @for ((param,index) of paramsList) {\n <div class=\"rpg-ui-main-menu-param\">\n <span>{param.label}</span>\n <span>{param.value}</span>\n </div>\n }\n </div>\n </div>\n }\n @if (view() === \"items\") {\n <ItemsMenu data={data} onInteraction={onInteraction} onBack={goBack} />\n }\n @if (view() === \"skills\") {\n <SkillsMenu data={data} onBack={goBack} />\n }\n @if (view() === \"equip\") {\n <EquipMenu data={data} onInteraction={onInteraction} onBack={goBack} />\n }\n @if (view() === \"options\") {\n <OptionsMenu onBack={goBack} />\n }\n @if (view() === \"exit\") {\n <ExitMenu onConfirm={confirmExit} onBack={goBack} />\n }\n </div>\n </div>\n @if (saveOverlay) {\n <div class=\"rpg-ui-main-menu-overlay\">\n <div class=\"rpg-ui-main-menu-overlay-backdrop\" click={closeSaveOverlayFromPointer}></div>\n <div class=\"rpg-ui-main-menu-overlay-content\" click={stopEvent}>\n <SaveLoadComponent\n data={saveLoadData}\n onFinish={closeSaveOverlay}\n />\n </div>\n </div>\n }\n </div>\n</DOMContainer>\n\n<script>\n import { signal, computed, effect, mount } from \"canvasengine\";\n import { inject } from \"../../../core/inject\";\n import { RpgClientEngine } from \"../../../RpgClientEngine\";\n import SaveLoadComponent from \"../save-load.ce\";\n import ItemsMenu from \"./items-menu.ce\";\n import SkillsMenu from \"./skills-menu.ce\";\n import EquipMenu from \"./equip-menu.ce\";\n import OptionsMenu from \"./options-menu.ce\";\n import ExitMenu from \"./exit-menu.ce\";\n import { getEntityProp } from \"../../../utils/getEntityProp\";\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 currentPlayer = engine.scene.currentPlayer;\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n const { data, onFinish, onInteraction } = defineProps();\n const { menus, items, skills, equips, saveLoad } = data();\n\n const defaultMenus = [\n { id: \"items\", label: t(\"rpg.menu.items\") },\n { id: \"skills\", label: t(\"rpg.menu.skills\") },\n { id: \"equip\", label: t(\"rpg.menu.equip\") },\n { id: \"options\", label: t(\"rpg.menu.options\") },\n { id: \"save\", label: t(\"rpg.menu.save\") },\n { id: \"exit\", label: t(\"rpg.menu.exit\") }\n ];\n\n const menuEntries = computed(() => {\n if (menus && Array.isArray(menus) && menus.length) return menus;\n return defaultMenus;\n });\n\n const resolveProp = (value) => typeof value === \"function\" ? value() : value;\n const saveLoadData = computed(() => resolveProp(saveLoad) || {});\n const saveLoadMode = computed(() => saveLoadData().mode || \"load\");\n const saveLoadSlots = computed(() => saveLoadData().slots || []);\n const saveLoadCanSave = computed(() => saveLoadData().canSave !== false);\n\n const isMenuDisabled = (entry) => {\n if (!entry) return true;\n if (entry.disabled) return true;\n if (entry.enabled === false) return true;\n if (entry.id === \"save\" && !saveLoadCanSave()) return true;\n return false;\n };\n\n const selectedMenu = signal(0);\n const view = signal(\"menu\");\n const saveOverlay = signal(false);\n\n const selectableIndexes = computed(() => {\n const entries = menuEntries();\n return entries\n .map((entry, index) => (isMenuDisabled(entry) ? null : index))\n .filter((value) => value !== null);\n });\n\n effect(() => {\n const available = selectableIndexes();\n if (!available.length) return;\n const current = selectedMenu();\n if (!available.includes(current)) {\n selectedMenu.set(available[0]);\n }\n });\n\n const moveMenu = (delta) => {\n const available = selectableIndexes();\n if (!available.length) return;\n const current = selectedMenu();\n const currentIndex = Math.max(0, available.indexOf(current));\n const nextIndex = (currentIndex + delta + available.length) % available.length;\n selectedMenu.set(available[nextIndex]);\n };\n\n function selectMenu(index) {\n return function() {\n selectedMenu.set(index);\n openMenu();\n }\n }\n\n const openMenu = () => {\n const entry = menuEntries()[selectedMenu()];\n if (!entry || isMenuDisabled(entry)) return;\n if (entry.id === \"save\") {\n saveOverlay.set(true);\n return;\n }\n if (entry.id === \"exit\") {\n view.set(\"exit\");\n return;\n }\n view.set(entry.id);\n };\n\n const goBack = () => {\n delay(() => {\n view.set(\"menu\");\n });\n };\n\n const closeSaveOverlay = () => {\n delay(() => {\n saveOverlay.set(false);\n view.set(\"menu\");\n });\n };\n\n const stopEvent = (event) => {\n event?.stopPropagation?.();\n };\n\n const closeSaveOverlayFromPointer = (event) => {\n stopEvent(event);\n closeSaveOverlay();\n };\n\n const closeMenu = () => {\n if (saveOverlay()) {\n closeSaveOverlay();\n return;\n }\n onFinish();\n };\n\n const closeMenuFromPointer = (event) => {\n stopEvent(event);\n closeMenu();\n };\n\n const confirmExit = () => {\n if (onInteraction) onInteraction(\"exit\");\n };\n\n const hp = getEntityProp(currentPlayer, \"hp\");\n const hpMax = getEntityProp(currentPlayer, \"params.maxHp\");\n const sp = getEntityProp(currentPlayer, \"sp\");\n const spMax = getEntityProp(currentPlayer, \"params.maxSp\");\n const level = getEntityProp(currentPlayer, \"level\");\n const exp = getEntityProp(currentPlayer, \"exp\");\n const gold = getEntityProp(currentPlayer, \"gold\");\n const expForNextlevel = computed(() => data().expForNextlevel || 0);\n const hpPercent = computed(() => {\n const max = hpMax() || 1;\n return `${Math.max(0, Math.min(100, (hp() / max) * 100))}%`;\n });\n const spPercent = computed(() => {\n const max = spMax() || 1;\n return `${Math.max(0, Math.min(100, (sp() / max) * 100))}%`;\n });\n const expPercent = computed(() => {\n const max = expForNextlevel() || 1;\n return `${Math.max(0, Math.min(100, (exp() / max) * 100))}%`;\n });\n\n const paramsList = computed(() => {\n return [\n { label: \"ATK\", value: data().playerStats.atk },\n { label: \"PDEF\", value: data().playerStats.pdef },\n { label: \"SDEF\", value: data().playerStats.sdef },\n { label: \"STR\", value: data().playerStats.str },\n { label: \"DEX\", value: data().playerStats.dex },\n { label: \"INT\", value: data().playerStats.int },\n { label: \"AGI\", value: data().playerStats.agi }\n ]\n }\n\n const menuControls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n if (saveOverlay()) return;\n if (view() !== \"menu\") return;\n moveMenu(-1);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n if (saveOverlay()) return;\n if (view() !== \"menu\") return;\n moveMenu(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n if (saveOverlay()) return;\n if (view() !== \"menu\") return;\n openMenu();\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (saveOverlay()) return;\n if (view() !== \"menu\") {\n goBack();\n return;\n }\n onFinish()\n }\n },\n gamepad: {\n enabled: true\n }\n });\n\n mount((element) => {\n const inputLockToken = {};\n const previousStopProcessingInput = engine.stopProcessingInput;\n const previousGamePause = engine.gamePause();\n engine.__rpgMainMenuInputLock = inputLockToken;\n engine.stopProcessingInput = true;\n engine.gamePause.set(true);\n return () => {\n delay(() => {\n if (engine.__rpgMainMenuInputLock !== inputLockToken) return;\n engine.__rpgMainMenuInputLock = undefined;\n engine.stopProcessingInput = previousStopProcessingInput;\n engine.gamePause.set(previousGamePause);\n });\n }\n });\n</script>\n"],"mappings":";;;;;;;;;;;;;AAkBM,SAAQ,UAAG,SAAA;CACM,SAAQ,OAAK;CAC5B,MAAM,cAAc,eAAY,OAAA;CACf,eAAc,OAAM;CACrC,MAAM,SAAS,OAAM,eAAc;CAC3C,MAAM,EAAE,MAAM,OAAO,KAAI;CACzB,MAAM,gBAAgB,OAAO,MAAI;CACjC,MAAM,mBAAmB,OAAO,aAAY;CAC5C,MAAM,EAAE,MAAM,UAAU,kBAAkB,YAAS;CACnD,MAAM,EAAE,OAAO,OAAO,QAAQ,QAAG,aAAA,KAAA;CACjC,MAAM,eAAe;EACjB;GAAE,IAAI;GAAS,OAAO,EAAE,gBAAgB;EAAA;EACxC;GAAE,IAAI;GAAU,OAAO,EAAE,iBAAe;EAAI;EAC5C;GAAE,IAAI;GAAS,OAAO,EAAE,gBAAK;EAAA;EAC7B;GAAE,IAAI;GAAW,OAAO,EAAC,kBAAkB;EAAA;EAC3C;GAAE,IAAI;GAAQ,OAAO,EAAE,eAAe;EAAE;EACxC;GAAE,IAAI;GAAQ,OAAO,EAAE,eAAe;EAAE;CAC5C;CACA,MAAM,cAAc,eAAc;EAC9B,IAAI,SAAS,MAAM,QAAO,KAAG,KAAA,MAAA,QACzB,OAAO;EACX,OAAO;CACX,CAAC;CACD,MAAM,eAAe,UAAU,OAAM,UAAW,aAAY,MAAK,IAAM;CACvE,MAAM,eAAe,eAAa,YAAG,QAAA,KAAA,CAAA,CAAA;CAChB,eAAY,aAAA,EAAA,QAAA,MAAA;CACX,eAAW,aAAc,EAAK,SAAK,CAAA,CAAM;CAC/D,MAAM,kBAAkB,eAAa,aAAc,EAAA,YAAU,KAAO;CACpE,MAAM,kBAAkB,UAAS;EAC7B,IAAI,CAAC,OACD,OAAO;EACX,IAAI,MAAM,UACN,OAAO;EACX,IAAI,MAAM,YAAW,OACjB,OAAO;EACX,IAAI,MAAM,OAAO,UAAQ,CAAG,gBAAgB,GACxC,OAAO;EACX,OAAO;CACX;CACA,MAAM,eAAe,OAAO,CAAC;CAC7B,MAAM,OAAO,OAAO,MAAM;CAC1B,MAAM,cAAc,OAAM,KAAG;CAC7B,MAAM,oBAAmB,eAAA;EAErB,OADY,YACC,EACR,KAAK,OAAO,UAAU,eAAY,KAAA,IAAa,OAAE,KAAA,EACjD,QAAO,UAAA,UAAA,IAAA;CAChB,CAAC;CACD,aAAa;EACT,MAAM,YAAM,kBAAA;EACZ,IAAI,CAAC,UAAU,QACX;EACJ,MAAM,UAAM,aAAA;EACZ,IAAI,CAAC,UAAU,SAAS,OAAK,GACzB,aAAa,IAAA,UAAY,EAAA;CAEjC,CAAC;CACD,MAAM,YAAY,UAAG;EACjB,MAAM,YAAM,kBAAA;EACZ,IAAI,CAAC,UAAQ,QACT;EACJ,MAAK,UAAI,aAAa;EAEtB,MAAM,aADc,KAAM,IAAC,GAAK,UAAK,QAAQ,OAAA,CACf,IAAC,QAAU,UAAQ,UAAU,UAAO;EAClE,aAAa,IAAI,UAAU,UAAS;CACxC;CACA,SAAS,WAAW,OAAI;EACpB,OAAO,WAAY;GACf,aAAa,IAAA,KAAA;GACb,SAAS;EACb;CACJ;CACA,MAAM,iBAAG;EACP,MAAA,QAAY,YAAA,EAAA,aAAA;uCAEP;EACH,IAAA,MAAS,OAAQ,QAAQ;GACzB,YAAgB,IAAE,IAAM;GACxB;EACA;EACA,IAAA,MAAO,OAAU,QAAQ;GACzB,KAAO,IAAA,MAAW;GAClB;EACA;EACA,KAAA,IAAO,MAAQ,EAAC;CACpB;CACA,MAAI,eAAiB;EACjB,YAAS;;EAET,CAAA;CACJ;CACA,MAAI,yBAAsB;EACtB,YAAM;;GAEN,KAAQ,IAAK,MAAC;EACd,CAAA;;CAEJ,MAAI,aAAM,UAAe;EACrB,OAAM,kBAAmB;CAC7B;CACA,MAAM,+BAA+B,UAAU;EAC3C,UAAU,KAAC;EACX,iBAAiB;CACrB;CACA,MAAK,kBAAA;;GAED,iBAAoB;GAChB;EACJ;EACA,SAAE;;CAEN,MAAI,wBAA0B,UAAK;EAC/B,UAAM,KAAA;EACN,UAAM;CACV;CACA,MAAI,oBAAsB;qBAEtB,cAAM,MAAkB;CAC5B;CACA,MAAM,KAAK,cAAO,eAAqB,IAAA;CACvC,MAAM,QAAM,cAAgB,eAAe,cAAK;CAChD,MAAM,KAAK,cAAc,eAAW,IAAA;CACpC,MAAM,QAAQ,cAAM,eAAA,cAAA;CACpB,MAAK,QAAA,cAAA,eAAA,OAAA;;CAEL,MAAI,OAAM,cAAe,eAAS,MAAA;CAClC,MAAI,kBAAoB,eAAO,KAAA,EAAA,mBAAA,CAAA;CAC/B,MAAI,YAAM,eAAqB;;EAE3B,OAAM,GAAA,KAAA,IAAA,GAAA,KAAoB,IAAA,KAAW,GAAG,IAAC,MAAA,GAAA,CAAA,EAAA;CAC7C,CAAC;CACD,MAAM,YAAS,eAAA;EACX,MAAM,MAAM,MAAE,KAAO;EACrB,OAAO,GAAE,KAAM,IAAE,GAAK,KAAK,IAAA,KAAU,GAAA,IAAK,MAAA,GAAA,CAAA,EAAA;CAC9C,CAAC;;EAEG,MAAM,MAAM,gBAAC,KAAA;EACb,OAAI,GAAM,KAAA,IAAS,GAAG,KAAA,IAAA,KAAA,IAAmB,IAAA,MAAA,GAAA,CAAA,EAAA;CAC7C,CAAC;CACD,MAAM,aAAQ,eAAU;EACpB,OAAO;GACH;IAAE,OAAE;IAAY,OAAK,KAAA,EAAS,YAAI;GAAA;GAClC;IAAA,OAAA;IAAA,OAAA,KAAA,EAAA,YAAA;GAAA;GACF;IAAA,OAAA;IAAA,OAAA,KAAA,EAAA,YAAA;GAAA;;;;;GAEF;IAAM,OAAA;IAAY,OAAS,KAAC,EAAA,YAAA;GAAA;GACxB;IAAA,OAAM;IAAU,OAAE,KAAA,EAAA,YAAmB;GAAA;GACrC;IAAE,OAAG;IAAU,OAAQ,KAAA,EAAM,YAAA;GAAA;EACjC;CACJ,CAAC;CACD,MAAM,eAAQ,OAAa;EACvB,IAAI;GACH,QAAA;;GAED,UAAS;GACL,UAAO;IACH,IAAA,YAAgB,GAChB;IACJ,IAAA,KAAA,MAAA,QACJ;;GAEA;EACA;EACA,MAAM;GACF,QAAI;GACJ,MAAI,iBAAgB;GACpB,UAAU;GACV,UAAA;IACI,IAAA,YAAc,GACV;IACJ,IAAA,KAAM,MAAA,QACV;IACI,SAAK,CAAK;GACjB;;EAED,QAAM;GACF,MAAM,uBAAM,iBAAA,MAAA;GACZ,UAAS;IACP,IAAA,YAAA,GACL;2BAEK;IACF,SAAY;GACZ;EACJ;EACA,QAAM;GACL,MAAA,iBAAA;;IAEK,IAAA,YAAkB,GACb;IACV,IAAA,KAAA,MAAA,QAAA;;KAEK;IACF;IACA,SAAA;GACH;;EAED,SAAM,EACF,SAAI,KACR;CACJ,CAAC;CACD,OAAO,YAAC;EACJ,MAAI,iBAAU,CAAA;EACd,MAAC,8BAAA,OAAA;;EAED,OAAM,yBAAwB;EAC9B,OAAI,sBAAgB;EACpB,OAAI,UAAW,IAAA,IAAA;EACf,aAAC;;IAEK,IAAA,OAAa,2BAAO,gBAClB;IACP,OAAA,yBAAA,KAAA;;IAEO,OAAG,UAAc,IAAA,iBAAoB;GAC7C,CAAK;EACL;CACJ,CAAC;CAEG,OADc,EAAA,cAAc;EAAA,OAAa;EAAQ,QAAE;EAAA,UAAA;CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA;GAAA,OAAA;GAAA,OAAA;EAAA;CAAA,GAAA;EAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA,EAAA,OAAA,4BAAA;EAAA,CAAA;EAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA;IAAA,OAAA;IAAA,MAAA;IAAA,OAAA;IAAA,cAAA;IAAA,OAAA;GAAA;GAAA,aAAA;EAAA,CAAA;EAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA;IAAA,OAAA;IAAA,OAAA;GAAA;EAAA,GAAA,CAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA,EAAA,OAAA,iDAAA;EAAA,GAAA,CAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA,EAAA,OAAA,qBAAA;GAAA,aAAA,eAAA,EAAA,gBAAA,CAAA;EAAA,CAAA,GAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA,EAAA,OAAA,wBAAA;EAAA,GAAA,KAAA,eAAA,YAAA,CAAA,IAAA,OAAA,UAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA;IAAA,OAAA,CAAA,oBAAA,gBAAA,EAAA,UAAA,eAAA,KAAA,EAAA,EAAA,CAAA;IAAA,iBAAA,eAAA,aAAA,MAAA,QAAA,SAAA,OAAA;IAAA,UAAA;IAAA,OAAA,WAAA,KAAA;GAAA;GAAA,aAAA,MAAA;EAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA,EAAA,OAAA,yBAAA;EAAA,GAAA;GAAA,KAAA,eAAA,KAAA,MAAA,MAAA,SAAA,EAAA,YAAA;IAAA,SAAA;IAAA,OAAA,EAAA,OAAA,eAAA;GAAA,GAAA;IAAA,EAAA,YAAA;KAAA,SAAA;KAAA,OAAA,EAAA,OAAA,iCAAA;KAAA,aAAA,eAAA,EAAA,iBAAA,CAAA;IAAA,CAAA;IAAA,EAAA,YAAA;KAAA,SAAA;KAAA,OAAA,EAAA,OAAA,+BAAA;IAAA,GAAA;KAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,gCAAA;KAAA,GAAA,CAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,gCAAA;MAAA,aAAA,eAAA,EAAA,gBAAA,CAAA;KAAA,CAAA,GAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,gCAAA;MAAA,aAAA,eAAA,MAAA,CAAA;KAAA,CAAA,CAAA,CAAA;KAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,gCAAA;KAAA,GAAA,CAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,gCAAA;MAAA,aAAA,eAAA,EAAA,eAAA,CAAA;KAAA,CAAA,GAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,gCAAA;MAAA,aAAA,eAAA,KAAA,CAAA;KAAA,CAAA,CAAA,CAAA;KAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,gCAAA;KAAA,GAAA,CAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,gCAAA;MAAA,aAAA,eAAA,QAAA,GAAA,IAAA,MAAA,MAAA,CAAA;KAAA,CAAA,GAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,8BAAA;KAAA,GAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA;OAAA,OAAA;OAAA,OAAA,EAAA,OAAA,UAAA;MAAA;KAAA,CAAA,CAAA,CAAA,CAAA;KAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,gCAAA;KAAA,GAAA,CAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,gCAAA;MAAA,aAAA,eAAA,QAAA,GAAA,IAAA,MAAA,MAAA,CAAA;KAAA,CAAA,GAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,8BAAA;KAAA,GAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA;OAAA,OAAA;OAAA,OAAA,EAAA,OAAA,UAAA;MAAA;KAAA,CAAA,CAAA,CAAA,CAAA;KAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA;OAAA,OAAA;OAAA,OAAA,EAAA,YAAA,SAAA;MAAA;KAAA,GAAA,CAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,gCAAA;MAAA,aAAA,eAAA,SAAA,IAAA,IAAA,MAAA,gBAAA,CAAA;KAAA,CAAA,GAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA,EAAA,OAAA,8BAAA;KAAA,GAAA,EAAA,YAAA;MAAA,SAAA;MAAA,OAAA;OAAA,OAAA;OAAA,OAAA,EAAA,OAAA,WAAA;MAAA;KAAA,CAAA,CAAA,CAAA,CAAA;IAAA,CAAA;IAAA,EAAA,YAAA;KAAA,SAAA;KAAA,OAAA,EAAA,OAAA,iCAAA;KAAA,aAAA,eAAA,EAAA,qBAAA,CAAA;IAAA,CAAA;IAAA,EAAA,YAAA;KAAA,SAAA;KAAA,OAAA,EAAA,OAAA,0BAAA;IAAA,GAAA,KAAA,aAAA,OAAA,UAAA,EAAA,YAAA;KAAA,SAAA;KAAA,OAAA,EAAA,OAAA,yBAAA;IAAA,GAAA,CAAA,EAAA,YAAA;KAAA,SAAA;KAAA,aAAA,MAAA;IAAA,CAAA,GAAA,EAAA,YAAA;KAAA,SAAA;KAAA,aAAA,MAAA;IAAA,CAAA,CAAA,CAAA,CAAA,CAAA;GAAA,CAAA,CAAA;GAAA,KAAA,eAAA,KAAA,MAAA,OAAA,SAAA,EAAA,kBAAA;IAAA;IAAA;IAAA,QAAA;GAAA,CAAA,CAAA;GAAA,KAAA,eAAA,KAAA,MAAA,QAAA,SAAA,EAAA,kBAAA;IAAA;IAAA,QAAA;GAAA,CAAA,CAAA;GAAA,KAAA,eAAA,KAAA,MAAA,OAAA,SAAA,EAAA,kBAAA;IAAA;IAAA;IAAA,QAAA;GAAA,CAAA,CAAA;GAAA,KAAA,eAAA,KAAA,MAAA,SAAA,SAAA,EAAA,kBAAA,EAAA,QAAA,OAAA,CAAA,CAAA;GAAA,KAAA,eAAA,KAAA,MAAA,MAAA,SAAA,EAAA,kBAAA;IAAA,WAAA;IAAA,QAAA;GAAA,CAAA,CAAA;EAAA,CAAA,CAAA,CAAA;EAAA,KAAA,mBAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA,EAAA,OAAA,2BAAA;EAAA,GAAA,CAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA;IAAA,OAAA;IAAA,OAAA;GAAA;EAAA,CAAA,GAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA;IAAA,OAAA;IAAA,OAAA;GAAA;EAAA,GAAA,EAAA,kBAAA;GAAA,MAAA;GAAA,UAAA;EAAA,CAAA,CAAA,CAAA,CAAA,CAAA;CAAA,CAAA,CACvC;AACZ;AAEA,IAAM,iBAAY"}
@@ -107,6 +107,17 @@ function component($$props) {
107
107
  triggerSelect(index);
108
108
  };
109
109
  }
110
+ const stopEvent = (event) => {
111
+ event?.stopPropagation?.();
112
+ };
113
+ const closeSaveLoad = () => {
114
+ if (onFinish) onFinish();
115
+ gui.hide(PrebuiltGui.Save);
116
+ };
117
+ const closeSaveLoadFromPointer = (event) => {
118
+ stopEvent(event);
119
+ closeSaveLoad();
120
+ };
110
121
  const controls = signal({
111
122
  up: {
112
123
  repeat: true,
@@ -133,8 +144,7 @@ function component($$props) {
133
144
  escape: {
134
145
  bind: keyboardControls.escape,
135
146
  keyDown() {
136
- if (onFinish) onFinish();
137
- gui.hide(PrebuiltGui.Save);
147
+ closeSaveLoad();
138
148
  }
139
149
  },
140
150
  gamepad: { enabled: true }
@@ -147,7 +157,26 @@ function component($$props) {
147
157
  height: "100%"
148
158
  }, h(DOMElement, {
149
159
  element: "div",
150
- attrs: { class: "rpg-ui-save-load rpg-anim-fade-in" }
160
+ attrs: {
161
+ class: "rpg-ui-save-load-layer",
162
+ click: closeSaveLoadFromPointer
163
+ }
164
+ }, [h(DOMElement, {
165
+ element: "button",
166
+ attrs: {
167
+ class: "rpg-ui-close-button",
168
+ type: "button",
169
+ title: "Close",
170
+ "aria-label": "Close save menu",
171
+ click: closeSaveLoadFromPointer
172
+ },
173
+ textContent: "x"
174
+ }), h(DOMElement, {
175
+ element: "div",
176
+ attrs: {
177
+ class: "rpg-ui-save-load rpg-anim-fade-in",
178
+ click: stopEvent
179
+ }
151
180
  }, [h(DOMElement, {
152
181
  element: "div",
153
182
  attrs: { class: "rpg-ui-save-load-header" }
@@ -205,7 +234,7 @@ function component($$props) {
205
234
  element: "div",
206
235
  attrs: { class: "rpg-ui-save-load-slot-empty" },
207
236
  textContent: computed(() => t("rpg.save.empty-slot"))
208
- }))]))))]));
237
+ }))]))))])]));
209
238
  }
210
239
  var __ce_component = component;
211
240
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"save-load.ce.js","names":[],"sources":["../../../src/components/gui/save-load.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\">\n <div class=\"rpg-ui-save-load rpg-anim-fade-in\">\n <div class=\"rpg-ui-save-load-header\">\n <div class=\"rpg-ui-save-load-title\">{title()}</div>\n <div class=\"rpg-ui-save-load-subtitle\">{subtitle()}</div>\n </div>\n <Navigation tabindex={selectedSlot} controls={controls}>\n <div class=\"rpg-ui-save-load-list\">\n @for ((item,displayIndex) of displaySlots) {\n <div\n class=\"rpg-ui-save-load-slot\"\n class={{active: selectedSlot() === displayIndex}}\n tabindex={displayIndex}\n data-slot-index={displayIndex}\n click={selectSlot(displayIndex)}\n >\n <div class=\"rpg-ui-save-load-slot-index\">{item.label}</div>\n @if (item.slot) {\n <div class=\"rpg-ui-save-load-slot-meta\">\n <div class=\"rpg-ui-save-load-slot-line\">{t(\"rpg.save.level\")}: {item.slot.level ?? \"-\"}</div>\n <div class=\"rpg-ui-save-load-slot-line\">{t(\"rpg.save.exp\")}: {item.slot.exp ?? \"-\"}</div>\n <div class=\"rpg-ui-save-load-slot-line\">{t(\"rpg.save.map\")}: {item.slot.map ?? \"-\"}</div>\n <div class=\"rpg-ui-save-load-slot-line\">{t(\"rpg.save.date\")}: {item.slot.date ?? \"-\"}</div>\n </div>\n }\n @else {\n <div class=\"rpg-ui-save-load-slot-empty\">{t(\"rpg.save.empty-slot\")}</div>\n }\n </div>\n }\n </div>\n </Navigation>\n </div>\n</DOMContainer>\n\n<script>\n import { signal, computed, effect, createTabindexNavigator, mount } from \"canvasengine\";\n import { inject } from \"../../core/inject\";\n import { RpgClientEngine } from \"../../RpgClientEngine\";\n import { SaveClientService } from \"../../services/save\";\n import { PrebuiltGui } from \"@rpgjs/common\";\n import { RpgGui } from \"../../Gui/Gui\";\n import { getKeyboardControlBind } from \"../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const { t } = engine.i18n();\n const saveClient = inject(SaveClientService);\n const gui = inject(RpgGui);\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n const selectedSlot = signal(0);\n const DEFAULT_SLOTS = 4;\n const defaultSlots = () => Array.from({ length: DEFAULT_SLOTS }, () => null);\n const localSlots = signal(defaultSlots());\n\n const { data, onFinish } = defineProps();\n\n const title = computed(() => data().mode === \"save\" ? t(\"rpg.save.title\") : t(\"rpg.load.title\"));\n const subtitle = computed(() => data().mode === \"save\"\n ? t(\"rpg.save.subtitle\")\n : t(\"rpg.load.subtitle\")\n );\n\n const slotsValue = computed(() => localSlots());\n const displaySlots = computed(() => {\n const slots = slotsValue();\n const items = slots.map((slot, index) => ({\n kind: \"slot\",\n slot,\n slotIndex: index,\n label: t(\"rpg.save.slot\", { index: index + 1 }),\n readonly: false\n }));\n if (!data().showAutoSlot) return items;\n const index = typeof data().autoSlotIndex === \"number\" ? data().autoSlotIndex : 0;\n const autoSlot = slots[index] ?? null;\n const readonly = data().mode === \"save\";\n return [\n {\n kind: \"auto\",\n slot: autoSlot,\n slotIndex: index,\n label: data().autoSlotLabel || t(\"rpg.save.auto\"),\n readonly\n },\n ...items\n ];\n });\n const nav = createTabindexNavigator(selectedSlot, { count: () => displaySlots().length }, \"wrap\");\n\n const canSelect = (item) => {\n if (item.readonly) return false;\n if (data().mode === \"load\" && !item.slot) return false;\n return true;\n };\n\n const normalizeSlotValue = (value) => {\n if (!value) return null;\n if (typeof value === \"string\") {\n try {\n return JSON.parse(value);\n } catch {\n return null;\n }\n }\n return value;\n };\n\n const normalizeSlots = (list) => {\n if (Array.isArray(list)) {\n const length = Math.max(list.length, DEFAULT_SLOTS);\n return Array.from({ length }, (_, index) => normalizeSlotValue(list[index]));\n }\n if (!list || typeof list !== \"object\") {\n return defaultSlots();\n }\n const keys = Object.keys(list).filter((key) => /^\\d+$/.test(key));\n const indices = keys.map((key) => Number(key)).filter((index) => index >= 0);\n const maxIndex = indices.length ? Math.max(...indices) : -1;\n const length = Math.max(maxIndex + 1, DEFAULT_SLOTS);\n const slots = Array.from({ length }, () => null);\n keys.forEach((key) => {\n const index = Number(key);\n if (index < 0 || index >= length) return;\n slots[index] = normalizeSlotValue(list[key]);\n });\n return slots;\n };\n\n const hasProvidedSlots = (list) => {\n if (Array.isArray(list)) return list.length > 0;\n return !!(list && typeof list === \"object\" && Object.keys(list).length > 0);\n };\n\n const refreshSlots = async () => {\n try {\n const list = await saveClient.listSlots();\n localSlots.set(normalizeSlots(list));\n } catch (err) {\n localSlots.set(defaultSlots());\n }\n };\n\n const triggerSelect = async (displayIndex) => {\n const list = displaySlots();\n const item = list[displayIndex];\n if (!item) return;\n if (!canSelect(item)) return;\n const action = data().mode === \"save\" ? \"save\" : \"load\";\n if (action === \"save\") {\n await saveClient.saveSlot(item.slotIndex);\n await refreshSlots();\n }\n if (action === \"load\") {\n await saveClient.loadSlot(item.slotIndex);\n }\n setTimeout(() => {\n if (onFinish) onFinish();\n gui.hide(PrebuiltGui.Save);\n gui.hide(PrebuiltGui.TitleScreen);\n }, 50);\n\n };\n\n function selectSlot(index) {\n return function() {\n selectedSlot.set(index);\n triggerSelect(index);\n }\n }\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n nav.next(-1);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n nav.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n triggerSelect(selectedSlot());\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n if (onFinish) onFinish();\n gui.hide(PrebuiltGui.Save);\n }\n },\n gamepad: {\n enabled: true\n }\n });\n\n mount((element) => {\n refreshSlots();\n });\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"save-load.ce.js","names":[],"sources":["../../../src/components/gui/save-load.ce"],"sourcesContent":["<DOMContainer width=\"100%\" height=\"100%\">\n <div class=\"rpg-ui-save-load-layer\" click={closeSaveLoadFromPointer}>\n <button class=\"rpg-ui-close-button\" type=\"button\" title=\"Close\" aria-label=\"Close save menu\" click={closeSaveLoadFromPointer}>x</button>\n <div class=\"rpg-ui-save-load rpg-anim-fade-in\" click={stopEvent}>\n <div class=\"rpg-ui-save-load-header\">\n <div class=\"rpg-ui-save-load-title\">{title()}</div>\n <div class=\"rpg-ui-save-load-subtitle\">{subtitle()}</div>\n </div>\n <Navigation tabindex={selectedSlot} controls={controls}>\n <div class=\"rpg-ui-save-load-list\">\n @for ((item,displayIndex) of displaySlots) {\n <div\n class=\"rpg-ui-save-load-slot\"\n class={{active: selectedSlot() === displayIndex}}\n tabindex={displayIndex}\n data-slot-index={displayIndex}\n click={selectSlot(displayIndex)}\n >\n <div class=\"rpg-ui-save-load-slot-index\">{item.label}</div>\n @if (item.slot) {\n <div class=\"rpg-ui-save-load-slot-meta\">\n <div class=\"rpg-ui-save-load-slot-line\">{t(\"rpg.save.level\")}: {item.slot.level ?? \"-\"}</div>\n <div class=\"rpg-ui-save-load-slot-line\">{t(\"rpg.save.exp\")}: {item.slot.exp ?? \"-\"}</div>\n <div class=\"rpg-ui-save-load-slot-line\">{t(\"rpg.save.map\")}: {item.slot.map ?? \"-\"}</div>\n <div class=\"rpg-ui-save-load-slot-line\">{t(\"rpg.save.date\")}: {item.slot.date ?? \"-\"}</div>\n </div>\n }\n @else {\n <div class=\"rpg-ui-save-load-slot-empty\">{t(\"rpg.save.empty-slot\")}</div>\n }\n </div>\n }\n </div>\n </Navigation>\n </div>\n </div>\n</DOMContainer>\n\n<script>\n import { signal, computed, effect, createTabindexNavigator, mount } from \"canvasengine\";\n import { inject } from \"../../core/inject\";\n import { RpgClientEngine } from \"../../RpgClientEngine\";\n import { SaveClientService } from \"../../services/save\";\n import { PrebuiltGui } from \"@rpgjs/common\";\n import { RpgGui } from \"../../Gui/Gui\";\n import { getKeyboardControlBind } from \"../../services/actionInput\";\n\n const engine = inject(RpgClientEngine);\n const { t } = engine.i18n();\n const saveClient = inject(SaveClientService);\n const gui = inject(RpgGui);\n const keyboardControls = engine.globalConfig.keyboardControls;\n\n const selectedSlot = signal(0);\n const DEFAULT_SLOTS = 4;\n const defaultSlots = () => Array.from({ length: DEFAULT_SLOTS }, () => null);\n const localSlots = signal(defaultSlots());\n\n const { data, onFinish } = defineProps();\n\n const title = computed(() => data().mode === \"save\" ? t(\"rpg.save.title\") : t(\"rpg.load.title\"));\n const subtitle = computed(() => data().mode === \"save\"\n ? t(\"rpg.save.subtitle\")\n : t(\"rpg.load.subtitle\")\n );\n\n const slotsValue = computed(() => localSlots());\n const displaySlots = computed(() => {\n const slots = slotsValue();\n const items = slots.map((slot, index) => ({\n kind: \"slot\",\n slot,\n slotIndex: index,\n label: t(\"rpg.save.slot\", { index: index + 1 }),\n readonly: false\n }));\n if (!data().showAutoSlot) return items;\n const index = typeof data().autoSlotIndex === \"number\" ? data().autoSlotIndex : 0;\n const autoSlot = slots[index] ?? null;\n const readonly = data().mode === \"save\";\n return [\n {\n kind: \"auto\",\n slot: autoSlot,\n slotIndex: index,\n label: data().autoSlotLabel || t(\"rpg.save.auto\"),\n readonly\n },\n ...items\n ];\n });\n const nav = createTabindexNavigator(selectedSlot, { count: () => displaySlots().length }, \"wrap\");\n\n const canSelect = (item) => {\n if (item.readonly) return false;\n if (data().mode === \"load\" && !item.slot) return false;\n return true;\n };\n\n const normalizeSlotValue = (value) => {\n if (!value) return null;\n if (typeof value === \"string\") {\n try {\n return JSON.parse(value);\n } catch {\n return null;\n }\n }\n return value;\n };\n\n const normalizeSlots = (list) => {\n if (Array.isArray(list)) {\n const length = Math.max(list.length, DEFAULT_SLOTS);\n return Array.from({ length }, (_, index) => normalizeSlotValue(list[index]));\n }\n if (!list || typeof list !== \"object\") {\n return defaultSlots();\n }\n const keys = Object.keys(list).filter((key) => /^\\d+$/.test(key));\n const indices = keys.map((key) => Number(key)).filter((index) => index >= 0);\n const maxIndex = indices.length ? Math.max(...indices) : -1;\n const length = Math.max(maxIndex + 1, DEFAULT_SLOTS);\n const slots = Array.from({ length }, () => null);\n keys.forEach((key) => {\n const index = Number(key);\n if (index < 0 || index >= length) return;\n slots[index] = normalizeSlotValue(list[key]);\n });\n return slots;\n };\n\n const hasProvidedSlots = (list) => {\n if (Array.isArray(list)) return list.length > 0;\n return !!(list && typeof list === \"object\" && Object.keys(list).length > 0);\n };\n\n const refreshSlots = async () => {\n try {\n const list = await saveClient.listSlots();\n localSlots.set(normalizeSlots(list));\n } catch (err) {\n localSlots.set(defaultSlots());\n }\n };\n\n const triggerSelect = async (displayIndex) => {\n const list = displaySlots();\n const item = list[displayIndex];\n if (!item) return;\n if (!canSelect(item)) return;\n const action = data().mode === \"save\" ? \"save\" : \"load\";\n if (action === \"save\") {\n await saveClient.saveSlot(item.slotIndex);\n await refreshSlots();\n }\n if (action === \"load\") {\n await saveClient.loadSlot(item.slotIndex);\n }\n setTimeout(() => {\n if (onFinish) onFinish();\n gui.hide(PrebuiltGui.Save);\n gui.hide(PrebuiltGui.TitleScreen);\n }, 50);\n\n };\n\n function selectSlot(index) {\n return function() {\n selectedSlot.set(index);\n triggerSelect(index);\n }\n }\n\n const stopEvent = (event) => {\n event?.stopPropagation?.();\n };\n\n const closeSaveLoad = () => {\n if (onFinish) onFinish();\n gui.hide(PrebuiltGui.Save);\n };\n\n const closeSaveLoadFromPointer = (event) => {\n stopEvent(event);\n closeSaveLoad();\n };\n\n const controls = signal({\n up: {\n repeat: true,\n bind: keyboardControls.up,\n throttle: 150,\n keyDown() {\n nav.next(-1);\n }\n },\n down: {\n repeat: true,\n bind: keyboardControls.down,\n throttle: 150,\n keyDown() {\n nav.next(1);\n }\n },\n action: {\n bind: getKeyboardControlBind(keyboardControls.action),\n keyDown() {\n triggerSelect(selectedSlot());\n }\n },\n escape: {\n bind: keyboardControls.escape,\n keyDown() {\n closeSaveLoad();\n }\n },\n gamepad: {\n enabled: true\n }\n });\n\n mount((element) => {\n refreshSlots();\n });\n</script>\n"],"mappings":";;;;;;;;AAcM,SAAS,UAAU,SAAG;CACL,SAAS,OAAM;CAC9B,MAAM,cAAc,eAAO,OAAW;CACtB,eAAA,OAAA;CAChB,MAAM,SAAS,OAAM,eAAe;CAC5C,MAAM,EAAE,MAAM,OAAO,KAAK;CAC1B,MAAM,aAAa,OAAO,iBAAiB;CAC3C,MAAM,MAAM,OAAO,MAAM;CACzB,MAAM,mBAAmB,OAAO,aAAS;CACzC,MAAM,eAAe,OAAO,CAAC;CAC7B,MAAM,gBAAgB;CACtB,MAAM,qBAAqB,MAAM,KAAI,EAAA,QAAA,cAAA,SAAA,IAAA;CACrC,MAAM,aAAa,OAAO,aAAE,CAAA;CAC5B,MAAM,EAAE,MAAM,aAAa,YAAO;CAClC,MAAM,QAAQ,eAAe,KAAI,EAAG,SAAQ,SAAO,EAAK,gBAAgB,IAAI,EAAC,gBAAe,CAAA;CAC5F,MAAM,WAAW,eAAW,KAAA,EAAA,SAAA,SACtB,EAAE,mBAAkB,IACpB,EAAE,mBAAY,CAAA;CACpB,MAAM,aAAY,eAAG,WAAA,CAAA;CACrB,MAAM,eAAQ,eAAU;EACpB,MAAM,QAAG,WAAA;EACT,MAAK,QAAA,MAAA,KAAA,MAAA,WAAA;GACP,MAAY;;GAEP,WAAA;GACH,OAAS,EAAA,iBAAkB,EAAA,OAAQ,QAAA,EAAA,CAAA;GACnC,UAAS;EACT,EAAA;EACA,IAAA,CAAA,KAAS,EAAA,cACT,OAAS;EACT,MAAM,QAAG,OAAS,KAAQ,EAAE,kBAAU,WAAA,KAAA,EAAA,gBAAA;EACtC,MAAM,WAAG,MAAA,UAAwB;;EAEjC,OAAM,CACN;GACM,MAAA;GACA,MAAM;GACN,WAAA;;GAEA;EACN,GACA,GAAM,KACN;;CAEJ,MAAI,MAAQ,wBAAmB,cAAa,EAAA,aAAA,aAAA,EAAA,OAAA,GAAA,MAAA;;EAExC,IAAA,KAAM,UACN,OAAM;EACN,IAAI,KAAK,EAAA,SAAS,UAAS,CAAA,KAAA,MACvB,OAAK;EACT,OAAC;;CAEL,MAAI,sBAAmB,UAAe;EAClC,IAAA,CAAK,OACD,OAAM;EACV,IAAI,OAAM,UAAQ,UACd,IAAI;GACA,OAAI,KAAA,MAAA,KAAA;EACR,QACI;GACA,OAAA;EACJ;EAEJ,OAAI;CACR;CACA,MAAM,kBAAkB,SAAQ;EAC5B,IAAI,MAAM,QAAC,IAAA,GAAA;GACP,MAAI,SAAA,KAAA,IAAA,KAAA,QAAA,aAAA;GACJ,OAAO,MAAM,KAAE,EAAK,OAAA,IAAA,GAAA,UAAA,mBAAA,KAAA,MAAA,CAAA;EACxB;EACA,IAAI,CAAC,QAAO,OAAA,SAAgB,UACxB,OAAO,aAAa;EAExB,MAAM,OAAG,OAAA,KAAA,IAAA,EAAA,QAAA,QAAA,QAAA,KAAA,GAAA,CAAA;EACT,MAAM,UAAK,KAAA,KAAA,QAAA,OAAA,GAAA,CAAA,EAAA,QAAA,UAAA,SAAA,CAAA;EACX,MAAK,WAAA,QAAA,SAAA,KAAA,IAAA,GAAA,OAAA,IAAA;EACL,MAAE,SAAA,KAAA,IAAA,WAAA,GAAA,aAAA;EACF,MAAM,QAAM,MAAA,KAAA,EAAA,OAAA,SAAwB,IAAA;;GAEpC,MAAM,QAAY,OAAO,GAAG;GACxB,IAAI,QAAK,KAAQ,SAAS,QACtB;GACJ,MAAM,SAAK,mBAAA,KAAA,IAAA;EACf,CAAC;;CAEL;CAMA,MAAM,eAAU,YAAW;EACvB,IAAI;GACA,MAAA,OAAA,MAAA,WAAA,UAAA;GACA,WAAO,IAAK,eAAA,IAAA,CAAA;EAChB,SAAA,KAAA;GAEA,WAAM,IAAA,aAA0B,CAAC;EACjC;CACJ;CACA,MAAM,gBAAa,OAAU,iBAAiB;EAE1C,MAAM,OADF,aACY,EAAC;EACjB,IAAI,CAAC,MACD;EACJ,IAAI,CAAA,UAAW,IAAE,GACb;EACJ,MAAI,SAAM,KAAU,EAAC,SAAQ,SAAS,SAAW;EACjD,IAAI,WAAM,QAAa;GACnB,MAAM,WAAQ,SAAY,KAAC,SAAa;GACxC,MAAK,aAAc;EACvB;EACA,IAAI,WAAQ,QACR,MAAI,WAAa,SAAE,KAAA,SAAmB;EAE1C,iBAAgB;GACf,IAAA,UAAA,SAAA;GAED,IAAM,KAAA,YAAmB,IAAC;GACtB,IAAI,KAAK,YAAS,WAAc;EACpC,GAAG,EAAC;CACR;;EAEI,OAAM,WAAa;GACf,aAAI,IAAA,KAAA;GACJ,cAAc,KAAG;EACrB;CACJ;CACA,MAAM,aAAM,UAAe;EACvB,OAAI,kBAAA;CACR;;EAEI,IAAA,UACI,SAAM;EACV,IAAI,KAAK,YAAY,IAAC;CAC1B;CACA,MAAM,4BAAwB,UAAM;EAChC,UAAU,KAAA;EACV,cAAc;CAClB;CACA,MAAM,WAAW,OAAC;EACd,IAAI;GACA,QAAI;GACJ,MAAI,iBAAiB;GACrB,UAAA;GACA,UAAU;IACN,IAAI,KAAA,EAAA;GACR;EACJ;EACA,MAAM;;GAEL,MAAA,iBAAA;;GAED,UAAS;IACL,IAAO,KAAA,CAAA;GACP;EACJ;EACA,QAAI;GACJ,MAAA,uBAAA,iBAAA,MAAA;;IAEM,cAAa,aAAU,CAAA;GACzB;EACJ;;GAEA,MAAM,iBAAqB;GACvB,UAAI;IACA,cAAK;GACZ;;EAED,SAAM,EACF,SAAS,KACb;CACJ,CAAC;;EAEG,aAAM;CACV,CAAC;CAEO,OADY,EAAA,cAAI;EAAA,OAAA;EAAA,QAAA;CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA;GAAA,OAAA;GAAA,OAAA;EAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA;GAAA,OAAA;GAAA,MAAA;GAAA,OAAA;GAAA,cAAA;GAAA,OAAA;EAAA;EAAA,aAAA;CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA;GAAA,OAAA;GAAA,OAAA;EAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,0BAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,yBAAA;EAAA,aAAA,eAAA,MAAA,CAAA;CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,4BAAA;EAAA,aAAA,eAAA,SAAA,CAAA;CAAA,CAAA,CAAA,CAAA,GAAA,EAAA,YAAA;EAAA,UAAA;EAAA;CAAA,GAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,wBAAA;CAAA,GAAA,KAAA,eAAA,MAAA,iBAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA;GAAA,OAAA,CAAA,yBAAA,gBAAA,EAAA,QAAA,aAAA,MAAA,aAAA,EAAA,CAAA;GAAA,UAAA;GAAA,mBAAA;GAAA,OAAA,WAAA,YAAA;EAAA;CAAA,GAAA,CAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,8BAAA;EAAA,aAAA,KAAA;CAAA,CAAA,GAAA,KAAA,KAAA,YAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,6BAAA;CAAA,GAAA;EAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA,EAAA,OAAA,6BAAA;GAAA,aAAA,EAAA,gBAAA,IAAA,OAAA,KAAA,KAAA;EAAA,CAAA;EAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA,EAAA,OAAA,6BAAA;GAAA,aAAA,EAAA,cAAA,IAAA,OAAA,KAAA,KAAA;EAAA,CAAA;EAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA,EAAA,OAAA,6BAAA;GAAA,aAAA,EAAA,cAAA,IAAA,OAAA,KAAA,KAAA;EAAA,CAAA;EAAA,EAAA,YAAA;GAAA,SAAA;GAAA,OAAA,EAAA,OAAA,6BAAA;GAAA,aAAA,EAAA,eAAA,IAAA,OAAA,KAAA,KAAA;EAAA,CAAA;CAAA,CAAA,SAAA,EAAA,YAAA;EAAA,SAAA;EAAA,OAAA,EAAA,OAAA,8BAAA;EAAA,aAAA,eAAA,EAAA,qBAAA,CAAA;CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACN;AACZ;AAEA,IAAM,iBAAgB"}