@open-slot-ui/pixi 0.8.1 → 0.8.2
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.cjs +236 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -1
- package/dist/index.d.ts +28 -1
- package/dist/index.js +236 -9
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -735,6 +735,33 @@ declare function mountHud(app: Application, spec?: UISpec, opts?: HudOptions): B
|
|
|
735
735
|
*/
|
|
736
736
|
declare function mountInfoMenu(app: Application, ui: OpenUI): () => void;
|
|
737
737
|
|
|
738
|
+
/** A buy-feature card. */
|
|
739
|
+
interface FeatureSpec {
|
|
740
|
+
id: string;
|
|
741
|
+
name: string;
|
|
742
|
+
variant: 'buy' | 'boost';
|
|
743
|
+
/** Price as a multiple of the current bet (× bet). */
|
|
744
|
+
cost: number;
|
|
745
|
+
/** Card image URL (or data URI). Optional — a neutral gradient is used when absent. */
|
|
746
|
+
image?: string;
|
|
747
|
+
}
|
|
748
|
+
/** Configurable behavior of the activatable bet-boost cards. */
|
|
749
|
+
interface BuyFeatureOptions {
|
|
750
|
+
/** `'single'` → only one boost active at a time · `'multi'` → combine them. Default `'multi'`. */
|
|
751
|
+
activation?: 'single' | 'multi';
|
|
752
|
+
/** When any boost is active, disable the Buy buttons. Default `false`. */
|
|
753
|
+
activationBlocksBuy?: boolean;
|
|
754
|
+
/** Host hook for a confirmed Buy (the modal has just closed): deduct + start the feature. */
|
|
755
|
+
onBuy?: (id: string, cost: number) => void;
|
|
756
|
+
/** Host hook whenever the active-boost set changes (the modal stays open). */
|
|
757
|
+
onActivate?: (activeIds: string[], id: string, active: boolean) => void;
|
|
758
|
+
/** BASE bet source for pricing. Default reads ui.bet — pass this when ui.bet
|
|
759
|
+
* displays a modified EFFECTIVE stake (boost active) instead of the base bet. */
|
|
760
|
+
getBet?: () => number;
|
|
761
|
+
}
|
|
762
|
+
/** Mount the buy-feature modal. Returns a leak-free teardown. */
|
|
763
|
+
declare function mountBuyFeatureModal(_app: Application, hud: BootedHud, features: FeatureSpec[], opts?: BuyFeatureOptions): () => void;
|
|
764
|
+
|
|
738
765
|
interface BootErrorOptions {
|
|
739
766
|
title?: string;
|
|
740
767
|
message?: string;
|
|
@@ -817,4 +844,4 @@ declare class Tweener {
|
|
|
817
844
|
/** Treat touch devices as non-desktop so we don't fire phantom hover states. */
|
|
818
845
|
declare function isDesktop(): boolean;
|
|
819
846
|
|
|
820
|
-
export { AutoplayDrawerView, AutoplayView, type AutoplayViewOptions, type BootErrorOptions, type BootedHud, type ButtonGlyph, ButtonView, type ButtonViewOptions, ControlView, ControlViewFactory, DialogView, type DialogViewOptions, 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, mountHud, mountInfoMenu, showBootError, svgSpinSkin };
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -735,6 +735,33 @@ declare function mountHud(app: Application, spec?: UISpec, opts?: HudOptions): B
|
|
|
735
735
|
*/
|
|
736
736
|
declare function mountInfoMenu(app: Application, ui: OpenUI): () => void;
|
|
737
737
|
|
|
738
|
+
/** A buy-feature card. */
|
|
739
|
+
interface FeatureSpec {
|
|
740
|
+
id: string;
|
|
741
|
+
name: string;
|
|
742
|
+
variant: 'buy' | 'boost';
|
|
743
|
+
/** Price as a multiple of the current bet (× bet). */
|
|
744
|
+
cost: number;
|
|
745
|
+
/** Card image URL (or data URI). Optional — a neutral gradient is used when absent. */
|
|
746
|
+
image?: string;
|
|
747
|
+
}
|
|
748
|
+
/** Configurable behavior of the activatable bet-boost cards. */
|
|
749
|
+
interface BuyFeatureOptions {
|
|
750
|
+
/** `'single'` → only one boost active at a time · `'multi'` → combine them. Default `'multi'`. */
|
|
751
|
+
activation?: 'single' | 'multi';
|
|
752
|
+
/** When any boost is active, disable the Buy buttons. Default `false`. */
|
|
753
|
+
activationBlocksBuy?: boolean;
|
|
754
|
+
/** Host hook for a confirmed Buy (the modal has just closed): deduct + start the feature. */
|
|
755
|
+
onBuy?: (id: string, cost: number) => void;
|
|
756
|
+
/** Host hook whenever the active-boost set changes (the modal stays open). */
|
|
757
|
+
onActivate?: (activeIds: string[], id: string, active: boolean) => void;
|
|
758
|
+
/** BASE bet source for pricing. Default reads ui.bet — pass this when ui.bet
|
|
759
|
+
* displays a modified EFFECTIVE stake (boost active) instead of the base bet. */
|
|
760
|
+
getBet?: () => number;
|
|
761
|
+
}
|
|
762
|
+
/** Mount the buy-feature modal. Returns a leak-free teardown. */
|
|
763
|
+
declare function mountBuyFeatureModal(_app: Application, hud: BootedHud, features: FeatureSpec[], opts?: BuyFeatureOptions): () => void;
|
|
764
|
+
|
|
738
765
|
interface BootErrorOptions {
|
|
739
766
|
title?: string;
|
|
740
767
|
message?: string;
|
|
@@ -817,4 +844,4 @@ declare class Tweener {
|
|
|
817
844
|
/** Treat touch devices as non-desktop so we don't fire phantom hover states. */
|
|
818
845
|
declare function isDesktop(): boolean;
|
|
819
846
|
|
|
820
|
-
export { AutoplayDrawerView, AutoplayView, type AutoplayViewOptions, type BootErrorOptions, type BootedHud, type ButtonGlyph, ButtonView, type ButtonViewOptions, ControlView, ControlViewFactory, DialogView, type DialogViewOptions, 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, mountHud, mountInfoMenu, showBootError, svgSpinSkin };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -565,7 +565,7 @@ var OHM_CSS = `
|
|
|
565
565
|
// src/mountHud.ts
|
|
566
566
|
function showReplayModal(ui, info, buttonKey, onSelect) {
|
|
567
567
|
const cur = info.currency ?? ui.balance.currency.get();
|
|
568
|
-
const
|
|
568
|
+
const money2 = (n) => formatAmount(n, cur);
|
|
569
569
|
ui.showNotice(
|
|
570
570
|
[
|
|
571
571
|
{ kind: "heading", id: "openui-replay-h", text: "openui.replay.title" },
|
|
@@ -573,10 +573,10 @@ function showReplayModal(ui, info, buttonKey, onSelect) {
|
|
|
573
573
|
kind: "stat-grid",
|
|
574
574
|
id: "openui-replay-g",
|
|
575
575
|
items: [
|
|
576
|
-
{ label: "openui.replay.baseBet", value:
|
|
576
|
+
{ label: "openui.replay.baseBet", value: money2(info.baseBet) },
|
|
577
577
|
{ label: "openui.replay.costMultiplier", value: `${info.costMultiplier}\xD7` },
|
|
578
578
|
{ label: "openui.replay.payoutMultiplier", value: `${info.payoutMultiplier}\xD7` },
|
|
579
|
-
{ label: "openui.replay.amount", value:
|
|
579
|
+
{ label: "openui.replay.amount", value: money2(info.amount) }
|
|
580
580
|
]
|
|
581
581
|
}
|
|
582
582
|
],
|
|
@@ -704,10 +704,237 @@ function mountHud(app, spec = {}, opts = {}) {
|
|
|
704
704
|
dispose: teardown
|
|
705
705
|
};
|
|
706
706
|
}
|
|
707
|
+
function money(amount, cur) {
|
|
708
|
+
return formatAmount(amount, cur);
|
|
709
|
+
}
|
|
710
|
+
var esc2 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
711
|
+
function mountBuyFeatureModal(_app, hud, features, opts = {}) {
|
|
712
|
+
const ui = hud.ui;
|
|
713
|
+
const tr = (k) => ui.t(k);
|
|
714
|
+
const list = features.slice(0, 4);
|
|
715
|
+
const boosts = /* @__PURE__ */ new Set();
|
|
716
|
+
const activation = opts.activation ?? "multi";
|
|
717
|
+
const blocksBuy = opts.activationBlocksBuy ?? false;
|
|
718
|
+
const disposers = [];
|
|
719
|
+
const host2 = document.createElement("div");
|
|
720
|
+
host2.className = "bfm-root";
|
|
721
|
+
const vars = {
|
|
722
|
+
"--accent": "#d99000",
|
|
723
|
+
"--accent-text": "#1a1200",
|
|
724
|
+
"--surface": "#ffffff",
|
|
725
|
+
"--surface-alt": "#eef1f6",
|
|
726
|
+
"--text": "#181b20",
|
|
727
|
+
"--text-dim": "#5b6472",
|
|
728
|
+
"--font": ui.theme.type.family
|
|
729
|
+
};
|
|
730
|
+
for (const [k, v] of Object.entries(vars)) host2.style.setProperty(k, v);
|
|
731
|
+
host2.innerHTML = `
|
|
732
|
+
<div class="bfm-backdrop" data-close></div>
|
|
733
|
+
<button class="bfm-x" data-close aria-label="Close">\u2715</button>
|
|
734
|
+
<div class="bfm-panel" role="dialog" aria-modal="true">
|
|
735
|
+
<div class="bfm-fit" id="bfm-fit">
|
|
736
|
+
<h2 class="bfm-title" data-t="Buy Feature">${esc2(tr("Buy Feature"))}</h2>
|
|
737
|
+
<div class="bfm-bet">
|
|
738
|
+
<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>
|
|
740
|
+
<button class="bfm-step" id="bfm-plus" aria-label="Increase">+</button>
|
|
741
|
+
</div>
|
|
742
|
+
<div class="bfm-cards" id="bfm-cards"></div>
|
|
743
|
+
</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
|
+
</div>`;
|
|
754
|
+
const style = document.createElement("style");
|
|
755
|
+
style.textContent = BFM_CSS;
|
|
756
|
+
host2.appendChild(style);
|
|
757
|
+
document.body.appendChild(host2);
|
|
758
|
+
const $ = (sel) => host2.querySelector(sel);
|
|
759
|
+
const panel = $(".bfm-panel");
|
|
760
|
+
const fitEl = $("#bfm-fit");
|
|
761
|
+
const cardsEl = $("#bfm-cards");
|
|
762
|
+
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");
|
|
786
|
+
};
|
|
787
|
+
const layout = () => {
|
|
788
|
+
const vw = window.innerWidth;
|
|
789
|
+
const vh = window.innerHeight;
|
|
790
|
+
const cols = vh <= 540 || vw >= 900 ? Math.min(4, list.length) : Math.min(2, list.length);
|
|
791
|
+
cardsEl.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
|
|
792
|
+
const fitW = Math.min(vw * 0.96, cols >= 4 ? 1180 : cols === 1 ? 380 : 760);
|
|
793
|
+
fitEl.style.width = `${fitW}px`;
|
|
794
|
+
fitEl.style.transform = "none";
|
|
795
|
+
const natH = fitEl.offsetHeight;
|
|
796
|
+
const s = Math.min(1, vh * 0.95 / natH);
|
|
797
|
+
fitEl.style.transform = `translateX(-50%) scale(${s})`;
|
|
798
|
+
panel.style.width = `${Math.ceil(fitW * s)}px`;
|
|
799
|
+
panel.style.height = `${Math.ceil(natH * s)}px`;
|
|
800
|
+
};
|
|
801
|
+
const renderCards = () => {
|
|
802
|
+
const bet = opts.getBet ? opts.getBet() : ui.bet.get();
|
|
803
|
+
const cur = ui.bet.currency.get();
|
|
804
|
+
cardsEl.innerHTML = list.map((f) => {
|
|
805
|
+
const active = boosts.has(f.id);
|
|
806
|
+
const buyBlocked = f.variant === "buy" && blocksBuy && boosts.size > 0;
|
|
807
|
+
const price = f.variant === "buy" ? money(f.cost * bet, cur) : `+${money(f.cost * bet, cur)}`;
|
|
808
|
+
const label = f.variant === "buy" ? tr("Buy") : active ? tr("Activated") : tr("Activate");
|
|
809
|
+
const cls = `bfm-action bfm-action--${f.variant}${active ? " is-active" : ""}${buyBlocked ? " is-blocked" : ""}`;
|
|
810
|
+
const img = f.image ? ` style="background-image:url('${f.image}')"` : "";
|
|
811
|
+
return `
|
|
812
|
+
<div class="bfm-cell">
|
|
813
|
+
<div class="bfm-card">
|
|
814
|
+
<div class="bfm-cardimg"${img}></div>
|
|
815
|
+
<div class="bfm-strip"></div>
|
|
816
|
+
<div class="bfm-cardbody">
|
|
817
|
+
<span class="bfm-name">${esc2(tr(f.name))}</span>
|
|
818
|
+
<b class="bfm-price">${esc2(price)}</b>
|
|
819
|
+
</div>
|
|
820
|
+
</div>
|
|
821
|
+
<button class="${cls}" data-id="${f.id}" data-variant="${f.variant}"${buyBlocked ? " disabled" : ""}>${esc2(label)}</button>
|
|
822
|
+
</div>`;
|
|
823
|
+
}).join("");
|
|
824
|
+
betValEl.textContent = money(bet, cur);
|
|
825
|
+
cardsEl.querySelectorAll(".bfm-action").forEach((b) => {
|
|
826
|
+
b.addEventListener("click", () => onAction(b.dataset.id, b.dataset.variant));
|
|
827
|
+
});
|
|
828
|
+
layout();
|
|
829
|
+
};
|
|
830
|
+
const onAction = (id, variant) => {
|
|
831
|
+
const f = list.find((x) => x.id === id);
|
|
832
|
+
const bet = opts.getBet ? opts.getBet() : ui.bet.get();
|
|
833
|
+
const cur = ui.bet.currency.get();
|
|
834
|
+
if (variant === "boost") {
|
|
835
|
+
const wasActive = boosts.has(id);
|
|
836
|
+
const commit = () => {
|
|
837
|
+
if (activation === "single") boosts.clear();
|
|
838
|
+
if (wasActive) boosts.delete(id);
|
|
839
|
+
else boosts.add(id);
|
|
840
|
+
ui.bus.emit("cardActivated", { id });
|
|
841
|
+
renderCards();
|
|
842
|
+
opts.onActivate?.([...boosts], id, boosts.has(id));
|
|
843
|
+
};
|
|
844
|
+
if (wasActive) {
|
|
845
|
+
commit();
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
const total = 1 + (f?.cost ?? 0);
|
|
849
|
+
askConfirm(total, f?.name ?? id, money(total * bet, cur), commit);
|
|
850
|
+
} else {
|
|
851
|
+
if (blocksBuy && boosts.size > 0) return;
|
|
852
|
+
const cost = (f?.cost ?? 0) * bet;
|
|
853
|
+
askConfirm(f?.cost ?? 0, f?.name ?? id, money(cost, cur), () => {
|
|
854
|
+
ui.bus.emit("cardActivated", { id });
|
|
855
|
+
close();
|
|
856
|
+
opts.onBuy?.(id, cost);
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
};
|
|
860
|
+
$("#bfm-minus").addEventListener("click", () => ui.betStepper.dec());
|
|
861
|
+
$("#bfm-plus").addEventListener("click", () => ui.betStepper.inc());
|
|
862
|
+
disposers.push(ui.bet.value.subscribe(() => renderCards()));
|
|
863
|
+
const open = () => {
|
|
864
|
+
renderCards();
|
|
865
|
+
host2.classList.add("open");
|
|
866
|
+
};
|
|
867
|
+
const close = () => host2.classList.remove("open");
|
|
868
|
+
host2.querySelectorAll("[data-close]").forEach((b) => b.addEventListener("click", close));
|
|
869
|
+
disposers.push(ui.on("buttonActivated", ({ id }) => {
|
|
870
|
+
if (id === "bonus") open();
|
|
871
|
+
}));
|
|
872
|
+
const onResize = () => {
|
|
873
|
+
if (host2.classList.contains("open")) layout();
|
|
874
|
+
};
|
|
875
|
+
window.addEventListener("resize", onResize);
|
|
876
|
+
disposers.push(
|
|
877
|
+
ui.locale.subscribe(() => {
|
|
878
|
+
host2.querySelectorAll("[data-t]").forEach((n) => n.textContent = tr(n.dataset.t));
|
|
879
|
+
renderCards();
|
|
880
|
+
})
|
|
881
|
+
);
|
|
882
|
+
renderCards();
|
|
883
|
+
return () => {
|
|
884
|
+
window.removeEventListener("resize", onResize);
|
|
885
|
+
for (const d of disposers.splice(0)) d();
|
|
886
|
+
host2.remove();
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
var BFM_CSS = `
|
|
890
|
+
.bfm-root { position: fixed; inset: 0; z-index: 11000; display: grid; place-items: center; font-family: var(--font); opacity: 0; pointer-events: none; transition: opacity .18s ease; }
|
|
891
|
+
.bfm-root.open { opacity: 1; pointer-events: auto; }
|
|
892
|
+
.bfm-backdrop { position: absolute; inset: 0; background: rgba(8,6,4,0); backdrop-filter: blur(0px) saturate(1); -webkit-backdrop-filter: blur(0px) saturate(1); transition: background .4s ease, backdrop-filter .4s ease, -webkit-backdrop-filter .4s ease; }
|
|
893
|
+
.bfm-root.open .bfm-backdrop { background: rgba(8,6,4,.5); backdrop-filter: blur(10px) saturate(1.1); -webkit-backdrop-filter: blur(10px) saturate(1.1); }
|
|
894
|
+
.bfm-x { position: absolute; top: 18px; right: 22px; width: 46px; height: 46px; border-radius: 999px; border: 0; background: rgba(18,14,10,.82); color: #fff; font-size: 18px; cursor: pointer; display: grid; place-items: center; box-shadow: 0 6px 18px rgba(0,0,0,.45); z-index: 2; transition: transform .12s, background .12s; }
|
|
895
|
+
.bfm-x:hover { transform: scale(1.08); background: rgba(18,14,10,.95); }
|
|
896
|
+
.bfm-root *, .bfm-root *::before, .bfm-root *::after { box-sizing: border-box; }
|
|
897
|
+
.bfm-panel { position: relative; transform: translateY(8px) scale(.985); transition: transform .18s ease; }
|
|
898
|
+
.bfm-root.open .bfm-panel { transform: none; }
|
|
899
|
+
.bfm-fit { position: absolute; top: 0; left: 50%; transform: translateX(-50%); transform-origin: top center; }
|
|
900
|
+
.bfm-title { margin: 0 0 14px; text-align: center; color: #fff; font-size: 30px; font-weight: 800; letter-spacing: 1px; text-shadow: 0 2px 12px rgba(0,0,0,.6); }
|
|
901
|
+
.bfm-bet { display: flex; align-items: center; justify-content: center; gap: 16px; margin: 0 0 24px; }
|
|
902
|
+
.bfm-betbox { min-width: 200px; padding: 10px 22px; border-radius: 12px; background: var(--surface); border: 3px solid #000; display: flex; flex-direction: column; align-items: center; line-height: 1.1; }
|
|
903
|
+
.bfm-betlabel { font-size: 12px; font-weight: 700; color: var(--text-dim); text-transform: uppercase; letter-spacing: 1px; }
|
|
904
|
+
.bfm-betbox b { font-size: 24px; color: var(--text); }
|
|
905
|
+
.bfm-step { flex: none; width: 54px; height: 54px; border-radius: 999px; border: 3px solid #000; background: var(--surface); color: var(--text); font-size: 28px; font-weight: 800; cursor: pointer; display: grid; place-items: center; line-height: 1; transition: transform .1s, background .12s; box-shadow: 0 4px 12px rgba(0,0,0,.3); }
|
|
906
|
+
.bfm-step:hover { background: var(--surface-alt); }
|
|
907
|
+
.bfm-step:active { transform: scale(.92); }
|
|
908
|
+
.bfm-cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; align-items: start; }
|
|
909
|
+
.bfm-cell { display: flex; flex-direction: column; min-width: 0; }
|
|
910
|
+
.bfm-card { background: var(--surface); border: 4px solid #000; border-radius: 14px; overflow: hidden; box-shadow: 0 14px 34px rgba(0,0,0,.45); }
|
|
911
|
+
.bfm-cardimg { width: 100%; aspect-ratio: 16 / 10; background-size: cover; background-position: center; background-color: var(--surface-alt); background-image: linear-gradient(135deg, #e7ebf2, #cfd6e2); }
|
|
912
|
+
.bfm-strip { height: 8px; background: linear-gradient(90deg, #f0a500, #ffd166, #f0a500); }
|
|
913
|
+
.bfm-cardbody { padding: 12px 14px 16px; text-align: center; }
|
|
914
|
+
.bfm-name { display: block; font-size: 15px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
915
|
+
.bfm-price { display: block; margin-top: 2px; font-size: 22px; font-weight: 800; color: var(--text); }
|
|
916
|
+
.bfm-action { display: block; width: 100%; margin-top: 12px; padding: 14px 10px; border-radius: 12px; border: 4px solid #000; background: var(--surface); color: var(--text); font-size: 15px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase; cursor: pointer; transition: transform .1s, background .12s, color .12s; box-shadow: 0 5px 14px rgba(0,0,0,.35); white-space: nowrap; }
|
|
917
|
+
.bfm-action:hover { background: var(--surface-alt); }
|
|
918
|
+
.bfm-action:active { transform: scale(.96); }
|
|
919
|
+
.bfm-action.is-active { background: var(--accent); color: var(--accent-text); border-color: #000; }
|
|
920
|
+
.bfm-action.is-blocked, .bfm-action:disabled { opacity: .38; cursor: not-allowed; box-shadow: none; }
|
|
921
|
+
.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
|
+
`;
|
|
707
934
|
|
|
708
935
|
// src/bootError.ts
|
|
709
936
|
var host = null;
|
|
710
|
-
var
|
|
937
|
+
var esc3 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
711
938
|
function showBootError(opts = {}) {
|
|
712
939
|
const title = opts.title ?? "Connection lost";
|
|
713
940
|
const message = opts.message ?? "The game could not reach the game server. Please reload to reconnect and continue.";
|
|
@@ -721,10 +948,10 @@ function showBootError(opts = {}) {
|
|
|
721
948
|
<div class="openui-be-icon" aria-hidden="true">
|
|
722
949
|
<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>
|
|
723
950
|
</div>
|
|
724
|
-
<h1 class="openui-be-title">${
|
|
725
|
-
<p class="openui-be-msg">${
|
|
726
|
-
${opts.detail ? `<p class="openui-be-detail">${
|
|
727
|
-
${showReload ? `<button class="openui-be-reload" type="button">${
|
|
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>` : ""}
|
|
728
955
|
</div>
|
|
729
956
|
<style>
|
|
730
957
|
.openui-boot-error { position: fixed; inset: 0; z-index: 2147483000; display: grid; place-items: center;
|
|
@@ -752,6 +979,6 @@ function hideBootError() {
|
|
|
752
979
|
host = null;
|
|
753
980
|
}
|
|
754
981
|
|
|
755
|
-
export { PanelBodyView, PanelView, PopoverView, hideBootError, mountHud, mountInfoMenu, showBootError };
|
|
982
|
+
export { PanelBodyView, PanelView, PopoverView, hideBootError, mountBuyFeatureModal, mountHud, mountInfoMenu, showBootError };
|
|
756
983
|
//# sourceMappingURL=index.js.map
|
|
757
984
|
//# sourceMappingURL=index.js.map
|