@open-slot-ui/pixi 0.8.2 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -762,6 +762,31 @@ interface BuyFeatureOptions {
762
762
  /** Mount the buy-feature modal. Returns a leak-free teardown. */
763
763
  declare function mountBuyFeatureModal(_app: Application, hud: BootedHud, features: FeatureSpec[], opts?: BuyFeatureOptions): () => void;
764
764
 
765
+ /** Minimal HUD surface the confirm needs — the translator + theme font. */
766
+ interface ConfirmUI {
767
+ t(key: string, params?: Record<string, string | number>): string;
768
+ theme: {
769
+ type: {
770
+ family: string;
771
+ };
772
+ };
773
+ }
774
+ interface ConfirmOptions {
775
+ /** Heading (already resolved text, or an i18n key). Default `Buy Feature`. */
776
+ title?: string;
777
+ /** Body message (already resolved). */
778
+ message: string;
779
+ /** Confirm button label (resolved text or i18n key). Default `openui.confirm`. */
780
+ confirmLabel?: string;
781
+ /** Cancel button label. Default `openui.cancel`. */
782
+ cancelLabel?: string;
783
+ }
784
+ /**
785
+ * Show the universal confirm dialog. Resolves `true` on Confirm, `false` on Cancel / backdrop
786
+ * / Escape. Self-mounting + self-cleaning; layers above everything (z-index above the buy modal).
787
+ */
788
+ declare function showConfirm(ui: ConfirmUI, opts: ConfirmOptions): Promise<boolean>;
789
+
765
790
  interface BootErrorOptions {
766
791
  title?: string;
767
792
  message?: string;
@@ -844,4 +869,4 @@ declare class Tweener {
844
869
  /** Treat touch devices as non-desktop so we don't fire phantom hover states. */
845
870
  declare function isDesktop(): boolean;
846
871
 
847
- export { AutoplayDrawerView, AutoplayView, type AutoplayViewOptions, type BootErrorOptions, type BootedHud, type ButtonGlyph, ButtonView, type ButtonViewOptions, type BuyFeatureOptions, ControlView, ControlViewFactory, DialogView, type DialogViewOptions, type FeatureSpec, type HudOptions, type InfoContentBuilder, MenuView, type MenuViewOptions, OpenUIPixi, OpenUIPixiOptions, type PanelBodyOptions, PanelBodyView, PanelView, type PanelViewOptions, type PopoverArt, type PopoverParts, PopoverView, ReadoutView, type ReadoutViewOptions, type ReplayInfo, SelectView, type SelectViewOptions, SliderView, SpinSkin, SpinSkinFactory, SpinView, type SpinViewOptions, StepperView, type SvgSpinTextures, TextCellRenderer, type TextCellRendererOptions, ToggleView, type ToggleViewOptions, TurboView, type TurboViewOptions, Tweener, ValueDisplayView, defaultSpinSkin, drawSpin, hideBootError, isDesktop, mountBuyFeatureModal, mountHud, mountInfoMenu, showBootError, svgSpinSkin };
872
+ export { AutoplayDrawerView, AutoplayView, type AutoplayViewOptions, type BootErrorOptions, type BootedHud, type ButtonGlyph, ButtonView, type ButtonViewOptions, type BuyFeatureOptions, type ConfirmOptions, ControlView, ControlViewFactory, DialogView, type DialogViewOptions, type FeatureSpec, type HudOptions, type InfoContentBuilder, MenuView, type MenuViewOptions, OpenUIPixi, OpenUIPixiOptions, type PanelBodyOptions, PanelBodyView, PanelView, type PanelViewOptions, type PopoverArt, type PopoverParts, PopoverView, ReadoutView, type ReadoutViewOptions, type ReplayInfo, SelectView, type SelectViewOptions, SliderView, SpinSkin, SpinSkinFactory, SpinView, type SpinViewOptions, StepperView, type SvgSpinTextures, TextCellRenderer, type TextCellRendererOptions, ToggleView, type ToggleViewOptions, TurboView, type TurboViewOptions, Tweener, ValueDisplayView, defaultSpinSkin, drawSpin, hideBootError, isDesktop, mountBuyFeatureModal, mountHud, mountInfoMenu, showBootError, showConfirm, svgSpinSkin };
package/dist/index.d.ts CHANGED
@@ -762,6 +762,31 @@ interface BuyFeatureOptions {
762
762
  /** Mount the buy-feature modal. Returns a leak-free teardown. */
763
763
  declare function mountBuyFeatureModal(_app: Application, hud: BootedHud, features: FeatureSpec[], opts?: BuyFeatureOptions): () => void;
764
764
 
765
+ /** Minimal HUD surface the confirm needs — the translator + theme font. */
766
+ interface ConfirmUI {
767
+ t(key: string, params?: Record<string, string | number>): string;
768
+ theme: {
769
+ type: {
770
+ family: string;
771
+ };
772
+ };
773
+ }
774
+ interface ConfirmOptions {
775
+ /** Heading (already resolved text, or an i18n key). Default `Buy Feature`. */
776
+ title?: string;
777
+ /** Body message (already resolved). */
778
+ message: string;
779
+ /** Confirm button label (resolved text or i18n key). Default `openui.confirm`. */
780
+ confirmLabel?: string;
781
+ /** Cancel button label. Default `openui.cancel`. */
782
+ cancelLabel?: string;
783
+ }
784
+ /**
785
+ * Show the universal confirm dialog. Resolves `true` on Confirm, `false` on Cancel / backdrop
786
+ * / Escape. Self-mounting + self-cleaning; layers above everything (z-index above the buy modal).
787
+ */
788
+ declare function showConfirm(ui: ConfirmUI, opts: ConfirmOptions): Promise<boolean>;
789
+
765
790
  interface BootErrorOptions {
766
791
  title?: string;
767
792
  message?: string;
@@ -844,4 +869,4 @@ declare class Tweener {
844
869
  /** Treat touch devices as non-desktop so we don't fire phantom hover states. */
845
870
  declare function isDesktop(): boolean;
846
871
 
847
- export { AutoplayDrawerView, AutoplayView, type AutoplayViewOptions, type BootErrorOptions, type BootedHud, type ButtonGlyph, ButtonView, type ButtonViewOptions, type BuyFeatureOptions, ControlView, ControlViewFactory, DialogView, type DialogViewOptions, type FeatureSpec, type HudOptions, type InfoContentBuilder, MenuView, type MenuViewOptions, OpenUIPixi, OpenUIPixiOptions, type PanelBodyOptions, PanelBodyView, PanelView, type PanelViewOptions, type PopoverArt, type PopoverParts, PopoverView, ReadoutView, type ReadoutViewOptions, type ReplayInfo, SelectView, type SelectViewOptions, SliderView, SpinSkin, SpinSkinFactory, SpinView, type SpinViewOptions, StepperView, type SvgSpinTextures, TextCellRenderer, type TextCellRendererOptions, ToggleView, type ToggleViewOptions, TurboView, type TurboViewOptions, Tweener, ValueDisplayView, defaultSpinSkin, drawSpin, hideBootError, isDesktop, mountBuyFeatureModal, mountHud, mountInfoMenu, showBootError, svgSpinSkin };
872
+ export { AutoplayDrawerView, AutoplayView, type AutoplayViewOptions, type BootErrorOptions, type BootedHud, type ButtonGlyph, ButtonView, type ButtonViewOptions, type BuyFeatureOptions, type ConfirmOptions, ControlView, ControlViewFactory, DialogView, type DialogViewOptions, type FeatureSpec, type HudOptions, type InfoContentBuilder, MenuView, type MenuViewOptions, OpenUIPixi, OpenUIPixiOptions, type PanelBodyOptions, PanelBodyView, PanelView, type PanelViewOptions, type PopoverArt, type PopoverParts, PopoverView, ReadoutView, type ReadoutViewOptions, type ReplayInfo, SelectView, type SelectViewOptions, SliderView, SpinSkin, SpinSkinFactory, SpinView, type SpinViewOptions, StepperView, type SvgSpinTextures, TextCellRenderer, type TextCellRendererOptions, ToggleView, type ToggleViewOptions, TurboView, type TurboViewOptions, Tweener, ValueDisplayView, defaultSpinSkin, drawSpin, hideBootError, isDesktop, mountBuyFeatureModal, mountHud, mountInfoMenu, showBootError, showConfirm, svgSpinSkin };
package/dist/index.js CHANGED
@@ -562,6 +562,63 @@ var OHM_CSS = `
562
562
  .ohm-group { margin: 8px 0; }
563
563
  `;
564
564
 
565
+ // src/confirmModal.ts
566
+ var esc2 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
567
+ function showConfirm(ui, opts) {
568
+ return new Promise((resolve) => {
569
+ const host2 = document.createElement("div");
570
+ host2.className = "osc-confirm";
571
+ host2.style.setProperty("--font", ui.theme.type.family);
572
+ const title = ui.t(opts.title ?? "Buy Feature");
573
+ const yes = ui.t(opts.confirmLabel ?? "openui.confirm");
574
+ const no = ui.t(opts.cancelLabel ?? "openui.cancel");
575
+ host2.innerHTML = `
576
+ <div class="osc-confirm-backdrop" data-no></div>
577
+ <div class="osc-confirm-card" role="dialog" aria-modal="true">
578
+ ${title ? `<h3 class="osc-confirm-title">${esc2(title)}</h3>` : ""}
579
+ <p class="osc-confirm-msg">${esc2(opts.message)}</p>
580
+ <div class="osc-confirm-row">
581
+ <button class="osc-confirm-btn osc-confirm-no" data-no>${esc2(no)}</button>
582
+ <button class="osc-confirm-btn osc-confirm-yes" data-yes>${esc2(yes)}</button>
583
+ </div>
584
+ </div>`;
585
+ const style = document.createElement("style");
586
+ style.textContent = CONFIRM_CSS;
587
+ host2.appendChild(style);
588
+ document.body.appendChild(host2);
589
+ let settled = false;
590
+ const close = (val) => {
591
+ if (settled) return;
592
+ settled = true;
593
+ window.removeEventListener("keydown", onKey);
594
+ host2.remove();
595
+ resolve(val);
596
+ };
597
+ const onKey = (e) => {
598
+ if (e.key === "Escape") close(false);
599
+ else if (e.key === "Enter") close(true);
600
+ };
601
+ host2.querySelectorAll("[data-no]").forEach((b) => b.addEventListener("click", () => close(false)));
602
+ host2.querySelector("[data-yes]")?.addEventListener("click", () => close(true));
603
+ window.addEventListener("keydown", onKey);
604
+ });
605
+ }
606
+ var CONFIRM_CSS = `
607
+ .osc-confirm { position: fixed; inset: 0; z-index: 12000; display: grid; place-items: center; font-family: var(--font); }
608
+ .osc-confirm *, .osc-confirm *::before, .osc-confirm *::after { box-sizing: border-box; }
609
+ .osc-confirm-backdrop { position: absolute; inset: 0; background: rgba(8,6,4,.6); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
610
+ .osc-confirm-card { position: relative; width: min(90vw, 420px); background: #ffffff; color: #181b20; border: 3px solid #000; border-radius: 14px; padding: 24px; box-shadow: 0 24px 60px rgba(0,0,0,.55); text-align: center; }
611
+ .osc-confirm-title { margin: 0 0 12px; font-size: 22px; font-weight: 800; letter-spacing: .3px; }
612
+ .osc-confirm-msg { margin: 0 0 22px; font-size: 19px; font-weight: 700; line-height: 1.4; }
613
+ .osc-confirm-row { display: flex; gap: 14px; }
614
+ .osc-confirm-btn { flex: 1; padding: 14px 10px; border-radius: 12px; border: 3px solid #000; font-size: 15px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase; cursor: pointer; transition: transform .1s, background .12s; }
615
+ .osc-confirm-btn:active { transform: scale(.96); }
616
+ .osc-confirm-no { background: #ffffff; color: #181b20; }
617
+ .osc-confirm-no:hover { background: #eef1f6; }
618
+ .osc-confirm-yes { background: #d99000; color: #1a1200; }
619
+ .osc-confirm-yes:hover { filter: brightness(1.05); }
620
+ `;
621
+
565
622
  // src/mountHud.ts
566
623
  function showReplayModal(ui, info, buttonKey, onSelect) {
567
624
  const cur = info.currency ?? ui.balance.currency.get();
@@ -680,17 +737,15 @@ function mountHud(app, spec = {}, opts = {}) {
680
737
  o.onConfirm();
681
738
  return;
682
739
  }
683
- const message = o.message ?? (o.name ? ui.t("openui.buyFeature.confirm", { name: ui.t(o.name), price: o.price ?? "" }) : "openui.buyFeature.message");
684
- ui.showNotice(
685
- [
686
- { kind: "heading", id: "buy-title", text: o.title ?? "openui.buyFeature.title" },
687
- { kind: "text", id: "buy-body", text: message }
688
- ],
689
- [
690
- { label: o.cancelLabel ?? "openui.cancel", variant: "secondary" },
691
- { label: o.confirmLabel ?? "openui.confirm", variant: "primary", onSelect: o.onConfirm }
692
- ]
693
- );
740
+ const message = o.message ?? (o.name ? ui.t("openui.buyFeature.confirm", { name: ui.t(o.name), price: o.price ?? "" }) : ui.t("openui.buyFeature.message"));
741
+ void showConfirm(ui, {
742
+ title: o.title ?? "openui.buyFeature.title",
743
+ message,
744
+ confirmLabel: o.confirmLabel,
745
+ cancelLabel: o.cancelLabel
746
+ }).then((ok) => {
747
+ if (ok) o.onConfirm();
748
+ });
694
749
  },
695
750
  showControls: () => pixi.setControlsVisible(true),
696
751
  hideControls: () => pixi.setControlsVisible(false),
@@ -707,7 +762,7 @@ function mountHud(app, spec = {}, opts = {}) {
707
762
  function money(amount, cur) {
708
763
  return formatAmount(amount, cur);
709
764
  }
710
- var esc2 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
765
+ var esc3 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
711
766
  function mountBuyFeatureModal(_app, hud, features, opts = {}) {
712
767
  const ui = hud.ui;
713
768
  const tr = (k) => ui.t(k);
@@ -733,23 +788,14 @@ function mountBuyFeatureModal(_app, hud, features, opts = {}) {
733
788
  <button class="bfm-x" data-close aria-label="Close">\u2715</button>
734
789
  <div class="bfm-panel" role="dialog" aria-modal="true">
735
790
  <div class="bfm-fit" id="bfm-fit">
736
- <h2 class="bfm-title" data-t="Buy Feature">${esc2(tr("Buy Feature"))}</h2>
791
+ <h2 class="bfm-title" data-t="Buy Feature">${esc3(tr("Buy Feature"))}</h2>
737
792
  <div class="bfm-bet">
738
793
  <button class="bfm-step" id="bfm-minus" aria-label="Decrease">\u2212</button>
739
- <div class="bfm-betbox"><span class="bfm-betlabel" data-t="Bet">${esc2(tr("Bet"))}</span><b id="bfm-betval">\u2014</b></div>
794
+ <div class="bfm-betbox"><span class="bfm-betlabel" data-t="Bet">${esc3(tr("Bet"))}</span><b id="bfm-betval">\u2014</b></div>
740
795
  <button class="bfm-step" id="bfm-plus" aria-label="Increase">+</button>
741
796
  </div>
742
797
  <div class="bfm-cards" id="bfm-cards"></div>
743
798
  </div>
744
- </div>
745
- <div class="bfm-confirm" id="bfm-confirm">
746
- <div class="bfm-confirm-card">
747
- <p class="bfm-confirm-msg" id="bfm-confirm-msg"></p>
748
- <div class="bfm-confirm-row">
749
- <button class="bfm-confirm-btn bfm-confirm-no" id="bfm-confirm-no" data-t="openui.cancel">${esc2(tr("openui.cancel"))}</button>
750
- <button class="bfm-confirm-btn bfm-confirm-yes" id="bfm-confirm-yes" data-t="openui.confirm">${esc2(tr("openui.confirm"))}</button>
751
- </div>
752
- </div>
753
799
  </div>`;
754
800
  const style = document.createElement("style");
755
801
  style.textContent = BFM_CSS;
@@ -760,29 +806,11 @@ function mountBuyFeatureModal(_app, hud, features, opts = {}) {
760
806
  const fitEl = $("#bfm-fit");
761
807
  const cardsEl = $("#bfm-cards");
762
808
  const betValEl = $("#bfm-betval");
763
- const confirmEl = $("#bfm-confirm");
764
- const confirmMsg = $("#bfm-confirm-msg");
765
- const confirmYes = $("#bfm-confirm-yes");
766
- const confirmNo = $("#bfm-confirm-no");
767
- let pendingConfirm = null;
768
- const hideConfirm = () => {
769
- confirmEl.classList.remove("show");
770
- pendingConfirm = null;
771
- };
772
- confirmNo.addEventListener("click", hideConfirm);
773
- confirmYes.addEventListener("click", () => {
774
- const fn = pendingConfirm;
775
- hideConfirm();
776
- fn?.();
777
- });
778
- const askConfirm = (totalCost, name, price, onYes) => {
779
- if (!hud.shouldConfirmBuy(totalCost)) {
780
- onYes();
781
- return;
782
- }
783
- confirmMsg.textContent = ui.t("openui.buyFeature.confirm", { name: ui.t(name), price });
784
- pendingConfirm = onYes;
785
- confirmEl.classList.add("show");
809
+ const askConfirm = (name, price, onYes) => {
810
+ const message = ui.t("openui.buyFeature.confirm", { name: ui.t(name), price });
811
+ void showConfirm(ui, { title: "Buy Feature", message }).then((ok) => {
812
+ if (ok) onYes();
813
+ });
786
814
  };
787
815
  const layout = () => {
788
816
  const vw = window.innerWidth;
@@ -814,11 +842,11 @@ function mountBuyFeatureModal(_app, hud, features, opts = {}) {
814
842
  <div class="bfm-cardimg"${img}></div>
815
843
  <div class="bfm-strip"></div>
816
844
  <div class="bfm-cardbody">
817
- <span class="bfm-name">${esc2(tr(f.name))}</span>
818
- <b class="bfm-price">${esc2(price)}</b>
845
+ <span class="bfm-name">${esc3(tr(f.name))}</span>
846
+ <b class="bfm-price">${esc3(price)}</b>
819
847
  </div>
820
848
  </div>
821
- <button class="${cls}" data-id="${f.id}" data-variant="${f.variant}"${buyBlocked ? " disabled" : ""}>${esc2(label)}</button>
849
+ <button class="${cls}" data-id="${f.id}" data-variant="${f.variant}"${buyBlocked ? " disabled" : ""}>${esc3(label)}</button>
822
850
  </div>`;
823
851
  }).join("");
824
852
  betValEl.textContent = money(bet, cur);
@@ -846,11 +874,11 @@ function mountBuyFeatureModal(_app, hud, features, opts = {}) {
846
874
  return;
847
875
  }
848
876
  const total = 1 + (f?.cost ?? 0);
849
- askConfirm(total, f?.name ?? id, money(total * bet, cur), commit);
877
+ askConfirm(f?.name ?? id, money(total * bet, cur), commit);
850
878
  } else {
851
879
  if (blocksBuy && boosts.size > 0) return;
852
880
  const cost = (f?.cost ?? 0) * bet;
853
- askConfirm(f?.cost ?? 0, f?.name ?? id, money(cost, cur), () => {
881
+ askConfirm(f?.name ?? id, money(cost, cur), () => {
854
882
  ui.bus.emit("cardActivated", { id });
855
883
  close();
856
884
  opts.onBuy?.(id, cost);
@@ -919,22 +947,11 @@ var BFM_CSS = `
919
947
  .bfm-action.is-active { background: var(--accent); color: var(--accent-text); border-color: #000; }
920
948
  .bfm-action.is-blocked, .bfm-action:disabled { opacity: .38; cursor: not-allowed; box-shadow: none; }
921
949
  .bfm-action.is-blocked:hover, .bfm-action:disabled:hover { background: var(--surface); }
922
- .bfm-confirm { position: absolute; inset: 0; z-index: 5; display: grid; place-items: center; opacity: 0; pointer-events: none; transition: opacity .16s ease; }
923
- .bfm-confirm.show { opacity: 1; pointer-events: auto; }
924
- .bfm-confirm::before { content: ""; position: absolute; inset: 0; background: rgba(8,6,4,.6); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
925
- .bfm-confirm-card { position: relative; width: min(90%, 420px); background: var(--surface); color: var(--text); border: 3px solid #000; border-radius: 14px; padding: 26px 24px 22px; box-shadow: 0 24px 60px rgba(0,0,0,.55); text-align: center; }
926
- .bfm-confirm-msg { margin: 0 0 22px; font-size: 19px; font-weight: 700; line-height: 1.4; color: var(--text); }
927
- .bfm-confirm-row { display: flex; gap: 14px; }
928
- .bfm-confirm-btn { flex: 1; padding: 14px 10px; border-radius: 12px; border: 3px solid #000; font-size: 15px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase; cursor: pointer; transition: transform .1s, background .12s; }
929
- .bfm-confirm-btn:active { transform: scale(.96); }
930
- .bfm-confirm-no { background: var(--surface); color: var(--text); }
931
- .bfm-confirm-no:hover { background: var(--surface-alt); }
932
- .bfm-confirm-yes { background: var(--accent); color: var(--accent-text); }
933
950
  `;
934
951
 
935
952
  // src/bootError.ts
936
953
  var host = null;
937
- var esc3 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
954
+ var esc4 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
938
955
  function showBootError(opts = {}) {
939
956
  const title = opts.title ?? "Connection lost";
940
957
  const message = opts.message ?? "The game could not reach the game server. Please reload to reconnect and continue.";
@@ -948,10 +965,10 @@ function showBootError(opts = {}) {
948
965
  <div class="openui-be-icon" aria-hidden="true">
949
966
  <svg viewBox="0 0 48 48" width="48" height="48"><path d="M24 4 3 42h42L24 4Z" fill="none" stroke="#ffc935" stroke-width="3" stroke-linejoin="round"/><rect x="22" y="18" width="4" height="12" rx="2" fill="#ffc935"/><circle cx="24" cy="35" r="2.4" fill="#ffc935"/></svg>
950
967
  </div>
951
- <h1 class="openui-be-title">${esc3(title)}</h1>
952
- <p class="openui-be-msg">${esc3(message)}</p>
953
- ${opts.detail ? `<p class="openui-be-detail">${esc3(opts.detail)}</p>` : ""}
954
- ${showReload ? `<button class="openui-be-reload" type="button">${esc3(opts.reloadLabel ?? "Reload")}</button>` : ""}
968
+ <h1 class="openui-be-title">${esc4(title)}</h1>
969
+ <p class="openui-be-msg">${esc4(message)}</p>
970
+ ${opts.detail ? `<p class="openui-be-detail">${esc4(opts.detail)}</p>` : ""}
971
+ ${showReload ? `<button class="openui-be-reload" type="button">${esc4(opts.reloadLabel ?? "Reload")}</button>` : ""}
955
972
  </div>
956
973
  <style>
957
974
  .openui-boot-error { position: fixed; inset: 0; z-index: 2147483000; display: grid; place-items: center;
@@ -979,6 +996,6 @@ function hideBootError() {
979
996
  host = null;
980
997
  }
981
998
 
982
- export { PanelBodyView, PanelView, PopoverView, hideBootError, mountBuyFeatureModal, mountHud, mountInfoMenu, showBootError };
999
+ export { PanelBodyView, PanelView, PopoverView, hideBootError, mountBuyFeatureModal, mountHud, mountInfoMenu, showBootError, showConfirm };
983
1000
  //# sourceMappingURL=index.js.map
984
1001
  //# sourceMappingURL=index.js.map