@open-slot-ui/pixi 0.5.0 → 0.6.0
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 +19 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -663,6 +663,23 @@ interface BootedHud {
|
|
|
663
663
|
confirmLabel?: string;
|
|
664
664
|
cancelLabel?: string;
|
|
665
665
|
}): void;
|
|
666
|
+
/** Confirm-GATE a buy / bet-mode activation: when its `cost` (× base bet) exceeds
|
|
667
|
+
* the configured `confirmBuyAboveCost` threshold, show a confirm popup naming the
|
|
668
|
+
* feature + `price` and run `onConfirm` only on confirm; otherwise run `onConfirm`
|
|
669
|
+
* straight away. This is how a game honors Stake's "no one-click activation above
|
|
670
|
+
* 2×" rule — the library owns the threshold + popup, the game just calls this. */
|
|
671
|
+
requestBuyFeature(opts: {
|
|
672
|
+
cost: number;
|
|
673
|
+
name?: string;
|
|
674
|
+
price?: string;
|
|
675
|
+
onConfirm: () => void;
|
|
676
|
+
title?: string;
|
|
677
|
+
message?: string;
|
|
678
|
+
confirmLabel?: string;
|
|
679
|
+
cancelLabel?: string;
|
|
680
|
+
}): void;
|
|
681
|
+
/** Read-back: would a play of this `cost` (× base bet) require confirmation? */
|
|
682
|
+
shouldConfirmBuy(cost: number): boolean;
|
|
666
683
|
/** Slide the whole interactive HUD in / out — bottom controls go down, top ones up
|
|
667
684
|
* (behind the status-bar plaque). Non-interactive while moving. */
|
|
668
685
|
showControls(): void;
|
package/dist/index.d.ts
CHANGED
|
@@ -663,6 +663,23 @@ interface BootedHud {
|
|
|
663
663
|
confirmLabel?: string;
|
|
664
664
|
cancelLabel?: string;
|
|
665
665
|
}): void;
|
|
666
|
+
/** Confirm-GATE a buy / bet-mode activation: when its `cost` (× base bet) exceeds
|
|
667
|
+
* the configured `confirmBuyAboveCost` threshold, show a confirm popup naming the
|
|
668
|
+
* feature + `price` and run `onConfirm` only on confirm; otherwise run `onConfirm`
|
|
669
|
+
* straight away. This is how a game honors Stake's "no one-click activation above
|
|
670
|
+
* 2×" rule — the library owns the threshold + popup, the game just calls this. */
|
|
671
|
+
requestBuyFeature(opts: {
|
|
672
|
+
cost: number;
|
|
673
|
+
name?: string;
|
|
674
|
+
price?: string;
|
|
675
|
+
onConfirm: () => void;
|
|
676
|
+
title?: string;
|
|
677
|
+
message?: string;
|
|
678
|
+
confirmLabel?: string;
|
|
679
|
+
cancelLabel?: string;
|
|
680
|
+
}): void;
|
|
681
|
+
/** Read-back: would a play of this `cost` (× base bet) require confirmation? */
|
|
682
|
+
shouldConfirmBuy(cost: number): boolean;
|
|
666
683
|
/** Slide the whole interactive HUD in / out — bottom controls go down, top ones up
|
|
667
684
|
* (behind the status-bar plaque). Non-interactive while moving. */
|
|
668
685
|
showControls(): void;
|
package/dist/index.js
CHANGED
|
@@ -354,6 +354,25 @@ function mountHud(app, spec = {}, opts = {}) {
|
|
|
354
354
|
]
|
|
355
355
|
);
|
|
356
356
|
},
|
|
357
|
+
shouldConfirmBuy: (cost) => ui.shouldConfirmBuy(cost),
|
|
358
|
+
requestBuyFeature: (o) => {
|
|
359
|
+
if (ui.isDisabled("buyFeature")) return;
|
|
360
|
+
if (!ui.shouldConfirmBuy(o.cost)) {
|
|
361
|
+
o.onConfirm();
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const message = o.message ?? (o.name ? ui.t("openui.buyFeature.confirm", { name: ui.t(o.name), price: o.price ?? "" }) : "openui.buyFeature.message");
|
|
365
|
+
ui.showNotice(
|
|
366
|
+
[
|
|
367
|
+
{ kind: "heading", id: "buy-title", text: o.title ?? "openui.buyFeature.title" },
|
|
368
|
+
{ kind: "text", id: "buy-body", text: message }
|
|
369
|
+
],
|
|
370
|
+
[
|
|
371
|
+
{ label: o.cancelLabel ?? "openui.cancel", variant: "secondary" },
|
|
372
|
+
{ label: o.confirmLabel ?? "openui.confirm", variant: "primary", onSelect: o.onConfirm }
|
|
373
|
+
]
|
|
374
|
+
);
|
|
375
|
+
},
|
|
357
376
|
showControls: () => pixi.setControlsVisible(true),
|
|
358
377
|
hideControls: () => pixi.setControlsVisible(false),
|
|
359
378
|
setControlsVisible: (v) => pixi.setControlsVisible(v),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/views/PopoverView.ts","../src/views/PanelView.ts","../src/views/PanelBodyView.ts","../src/mountHud.ts"],"names":["Graphics","Container","opts","on"],"mappings":"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","file":"index.js","sourcesContent":["import { type Ticker, type Texture } from 'pixi.js';\nimport { type PanelControl, type SliderControl, type ButtonControl, type OpenUI } from '@open-slot-ui/core';\nimport { ControlView } from './ControlView';\nimport { SliderView } from './SliderView';\nimport { ButtonView } from './ButtonView';\n\nexport interface PopoverParts {\n music: SliderControl;\n sfx: SliderControl;\n rules: ButtonControl;\n}\n\nexport interface PopoverArt {\n rulesTexture?: Texture;\n musicTrack?: Texture;\n soundTrack?: Texture;\n}\n\ninterface FanItem {\n view: ControlView;\n tx: number;\n ty: number;\n prog: number;\n}\n\nconst GAP = 80; // vertical spacing between fanned items (ref px)\nconst RISE = 26; // how far each item rises into place\nconst STAGGER = 38; // ms between pops — snappy \"pop-pop-pop\"\n// slider track is 290x60 @ ~0.9 → its visual centre, used as the scale pivot\nconst SLIDER_PIVOT_X = 130;\nconst SLIDER_PIVOT_Y = 27;\n\n/**\n * The settings flyout as a VERTICAL FAN: on open, the options swoosh up and pop\n * in one-by-one (bottom→top); on close they retract together. Items are\n * right-aligned and rise above the (right-side) menu button. No static panel.\n */\nexport class PopoverView extends ControlView {\n private readonly music: SliderView;\n private readonly sfx: SliderView;\n private readonly rules: ButtonView;\n private readonly items: FanItem[];\n private phase = 0;\n private running = false;\n private readonly tick: (t: Ticker) => void;\n\n constructor(private readonly panel: PanelControl, parts: PopoverParts, ui: OpenUI, private readonly ticker: Ticker, art: PopoverArt = {}) {\n super(panel, ui);\n\n this.rules = new ButtonView(parts.rules, ui, ticker, { shape: 'pill', height: 50, iconTexture: art.rulesTexture, iconTarget: 50 });\n this.music = new SliderView(parts.music, ui, art.musicTrack);\n this.sfx = new SliderView(parts.sfx, ui, art.soundTrack);\n // pivot sliders at their centre so they scale from the middle, not the left edge\n this.music.pivot.set(SLIDER_PIVOT_X, SLIDER_PIVOT_Y);\n this.sfx.pivot.set(SLIDER_PIVOT_X, SLIDER_PIVOT_Y);\n\n // Right-aligned column rising above the button; pop order = bottom → top.\n // tx/ty are the item CENTRES (rules ButtonView is already centre-origin).\n this.items = [\n { view: this.sfx, tx: -130, ty: -GAP, prog: 0 },\n { view: this.music, tx: -130, ty: -GAP * 2, prog: 0 },\n { view: this.rules, tx: -132, ty: -GAP * 3, prog: 0 },\n ];\n for (const it of this.items) {\n it.view.position.set(it.tx, it.ty);\n it.view.scale.set(0);\n it.view.alpha = 0;\n it.view.visible = false;\n this.addChild(it.view);\n }\n\n this.tick = (t) => this.update(t.deltaMS);\n this.applyState();\n this.disposers.push(this.panel.state.subscribe(() => this.applyState()));\n }\n\n private applyState(): void {\n this.phase = 0;\n const open = this.panel.isOpen;\n this.eventMode = open ? 'auto' : 'none';\n if (open) for (const it of this.items) it.view.visible = true;\n if (!this.running) {\n this.running = true;\n this.ticker.add(this.tick);\n }\n }\n\n private update(dt: number): void {\n this.phase += Math.min(dt, 40); // cap stalls so the stagger never gets skipped\n const open = this.panel.isOpen;\n const finalTarget = open ? 1 : 0;\n let settled = true;\n for (let i = 0; i < this.items.length; i++) {\n const it = this.items[i]!;\n const target = open && this.phase > i * STAGGER ? 1 : 0; // staggered easing target\n it.prog += (target - it.prog) * Math.min(1, dt / (open ? 50 : 80));\n const s = it.prog;\n it.view.scale.set(s);\n it.view.alpha = Math.min(1, s * 1.5);\n it.view.position.set(it.tx, it.ty + (1 - s) * RISE);\n it.view.visible = s > 0.01;\n // settle against the FINAL target so the loop keeps running until every item arrives\n if (Math.abs(it.prog - finalTarget) > 0.01) settled = false;\n }\n if (settled) {\n this.running = false;\n this.ticker.remove(this.tick);\n }\n }\n\n override dispose(): void {\n if (this.running) {\n this.ticker.remove(this.tick);\n this.running = false;\n }\n this.music.dispose();\n this.sfx.dispose();\n this.rules.dispose();\n super.dispose();\n }\n}\n","import { Container, Graphics, Text, Rectangle, type Texture, type FederatedPointerEvent, type Ticker } from 'pixi.js';\nimport { type PanelControl, type ButtonControl, type OpenUI, type ScreenState, type Theme } from '@open-slot-ui/core';\nimport { ControlView } from './ControlView';\nimport { ButtonView } from './ButtonView';\n\nexport type InfoContentBuilder = (theme: Theme, width: number) => Container;\n\nexport interface PanelViewOptions {\n closeTexture?: Texture;\n content?: InfoContentBuilder;\n}\n\n// The modal is an intentionally LIGHT surface (per the design), distinct from the dark HUD theme.\nconst INK = 0x15171c;\nconst CARD = 0xffffff;\nconst HEADER_BG = 0x20242b;\nconst PAD = 16;\nconst HEADER_H = 56;\nconst MAX_W = 600;\n\n/**\n * Full-screen modal: dim backdrop + dark header (title + ✕ close) + a white,\n * scrollable content card. Content is built dynamically (so it scrolls and is\n * data-driven). Faithful to the provided Mobile Rules design.\n */\nexport class PanelView extends ControlView {\n private readonly backdrop = new Graphics();\n private readonly card = new Graphics();\n private readonly headerBg = new Graphics();\n private readonly title: Text;\n private readonly viewport = new Container();\n private readonly maskG = new Graphics();\n private readonly catcher = new Graphics();\n private readonly close: ButtonView;\n private content: Container | undefined;\n private builtWidth = -1;\n private scrollY = 0;\n private contentH = 0;\n private viewportH = 0;\n private dragging = false;\n private lastY = 0;\n private wheelHandler: ((e: WheelEvent) => void) | undefined;\n\n constructor(\n private readonly panel: PanelControl,\n closeBtn: ButtonControl,\n ui: OpenUI,\n ticker: Ticker,\n private readonly opts: PanelViewOptions = {},\n ) {\n super(panel, ui);\n this.zIndex = 100;\n\n this.backdrop.eventMode = 'static';\n this.backdrop.on('pointertap', () => this.panel.closePanel());\n\n this.title = new Text({\n text: panel.title ?? '',\n style: { fontFamily: ui.theme.type.family, fontSize: 22, fill: 0xffffff, fontWeight: '800', letterSpacing: 1 },\n });\n this.title.anchor.set(0.5);\n\n this.viewport.mask = this.maskG;\n this.catcher.eventMode = 'static';\n this.catcher.on('pointerdown', this.onDown);\n this.catcher.on('globalpointermove', this.onMove);\n this.catcher.on('pointerup', this.onUp);\n this.catcher.on('pointerupoutside', this.onUp);\n\n this.close = new ButtonView(closeBtn, ui, ticker, { iconTexture: opts.closeTexture, iconTarget: 44, glyph: 'close', radius: 24 });\n\n this.addChild(this.backdrop, this.card, this.viewport, this.maskG, this.catcher, this.headerBg, this.title, this.close);\n\n this.applyOpen(this.panel.isOpen);\n this.disposers.push(this.panel.state.subscribe(() => this.applyOpen(this.panel.isOpen)));\n }\n\n override applyLayout(screen: ScreenState): void {\n const W = screen.width;\n const H = screen.height;\n this.position.set(0, 0);\n this.scale.set(1);\n\n this.backdrop.clear().rect(0, 0, W, H).fill({ color: 0x000000, alpha: 0.6 });\n this.backdrop.hitArea = new Rectangle(0, 0, W, H);\n\n const cardW = Math.min(W - PAD * 2, MAX_W);\n const cx = (W - cardW) / 2;\n const hy = PAD;\n this.headerBg.clear().roundRect(cx, hy, cardW, HEADER_H, HEADER_H / 2).fill({ color: HEADER_BG });\n this.title.position.set(W / 2, hy + HEADER_H / 2);\n this.close.position.set(cx + cardW - HEADER_H / 2, hy + HEADER_H / 2);\n\n const cardY = hy + HEADER_H + 12;\n const cardH = H - cardY - PAD;\n this.card.clear().roundRect(cx, cardY, cardW, cardH, 22).fill({ color: CARD });\n\n const inset = 20;\n const vpX = cx + inset;\n const vpY = cardY + inset;\n const vpW = cardW - inset * 2;\n const vpH = cardH - inset * 2;\n this.viewport.position.set(vpX, vpY);\n this.viewportH = vpH;\n this.maskG.clear().rect(vpX, vpY, vpW, vpH).fill({ color: 0xffffff });\n this.catcher.clear().rect(vpX, vpY, vpW, vpH).fill({ color: 0xffffff, alpha: 0.0001 });\n\n // (re)build content to the current viewport width\n if (Math.abs(vpW - this.builtWidth) > 1) {\n this.content?.destroy({ children: true });\n this.content = this.opts.content?.(this.ui.theme, vpW) ?? this.fallback(vpW);\n this.viewport.addChild(this.content);\n this.builtWidth = vpW;\n }\n if (this.content) this.content.x = 0;\n this.contentH = this.content?.height ?? 0;\n this.clampScroll();\n }\n\n private fallback(width: number): Container {\n const c = new Container();\n const t = new Text({ text: 'No content provided.', style: { fontFamily: this.ui.theme.type.family, fontSize: 18, fill: INK, wordWrap: true, wordWrapWidth: width } });\n c.addChild(t);\n return c;\n }\n\n private readonly onDown = (e: FederatedPointerEvent): void => {\n this.dragging = true;\n this.lastY = e.global.y;\n };\n private readonly onMove = (e: FederatedPointerEvent): void => {\n if (!this.dragging) return;\n this.scrollY += e.global.y - this.lastY;\n this.lastY = e.global.y;\n this.clampScroll();\n };\n private readonly onUp = (): void => {\n this.dragging = false;\n };\n\n private clampScroll(): void {\n const min = Math.min(0, this.viewportH - this.contentH);\n this.scrollY = Math.max(min, Math.min(0, this.scrollY));\n if (this.content) this.content.y = this.scrollY;\n }\n\n private applyOpen(open: boolean): void {\n this.visible = open;\n this.eventMode = open ? 'static' : 'none';\n this.alpha = open ? 1 : 0;\n if (open) {\n this.scrollY = 0;\n this.clampScroll();\n if (!this.wheelHandler) {\n this.wheelHandler = (e: WheelEvent) => {\n this.scrollY -= e.deltaY;\n this.clampScroll();\n };\n window.addEventListener('wheel', this.wheelHandler, { passive: true });\n }\n } else if (this.wheelHandler) {\n window.removeEventListener('wheel', this.wheelHandler);\n this.wheelHandler = undefined;\n }\n }\n\n override dispose(): void {\n if (this.wheelHandler) window.removeEventListener('wheel', this.wheelHandler);\n this.close.dispose();\n super.dispose();\n }\n}\n","import { Container, Graphics, type Ticker } from 'pixi.js';\nimport { type OpenUI, type PanelControl, type Control, type BlockSpec } from '@open-slot-ui/core';\nimport { ControlView } from './ControlView';\nimport { buildBlockColumn, type ControlViewFactory } from './blockColumn';\n\nexport interface PanelBodyOptions {\n width?: number;\n controlSkins?: Partial<Record<string, ControlViewFactory>>;\n}\n\n/**\n * A small, CENTERED panel body (the settings popover / declarative panels): walks\n * a `BlockSpec[]` via the shared {@link buildBlockColumn} renderer, draws a branded\n * card behind it, and follows the PanelControl's open/closed state. A `modal`\n * variant also gets a dismissable backdrop. Text re-renders on `ui.locale` change.\n * (The big scrollable menu uses {@link MenuView}, which shares the same renderer.)\n */\nexport class PanelBodyView extends ControlView {\n private readonly backdrop = new Graphics();\n private readonly card = new Graphics();\n private readonly content = new Container();\n private childViews: ControlView[] = [];\n private readonly bodyW: number;\n\n constructor(\n private readonly panelControl: PanelControl,\n private readonly controls: Control[],\n private readonly blocks: BlockSpec[],\n ui: OpenUI,\n private readonly ticker: Ticker,\n private readonly opts: PanelBodyOptions = {},\n ) {\n super(panelControl, ui);\n this.bodyW = opts.width ?? 360;\n\n this.addChild(this.backdrop, this.card, this.content);\n this.rebuild();\n this.applyVisibility();\n\n this.disposers.push(\n this.panelControl.state.subscribe(() => this.applyVisibility()),\n this.ui.locale.subscribe(() => {\n if (!this.destroyed) this.rebuild();\n }),\n );\n\n if (this.panelControl.variant === 'modal') {\n this.backdrop.eventMode = 'static';\n this.backdrop.on('pointertap', () => this.panelControl.closePanel());\n }\n }\n\n private rebuild(): void {\n for (const v of this.childViews) v.dispose();\n this.childViews.length = 0;\n // Destroy direct children (wraps/static nodes) WITHOUT children:true so the\n // already-disposed control views aren't re-destroyed (matches the prior code).\n for (const child of this.content.removeChildren()) child.destroy();\n\n const col = buildBlockColumn(this.blocks, this.controls, this.ui, this.ticker, this.bodyW, { controlSkins: this.opts.controlSkins });\n this.childViews = col.views;\n this.content.addChild(...col.content.removeChildren());\n this.content.position.set(0, -col.height / 2);\n this.drawChrome(this.bodyW, col.height);\n }\n\n private drawChrome(width: number, height: number): void {\n const t = this.ui.theme;\n this.card.clear()\n .roundRect(-width / 2, -height / 2, width, height, t.radius.card)\n .fill({ color: t.color.surface })\n .stroke({ width: 3, color: t.color.accent });\n\n this.backdrop.clear();\n if (this.panelControl.variant === 'modal') {\n this.backdrop.rect(-3000, -3000, 6000, 6000).fill({ color: 0x000000, alpha: 0.6 });\n }\n }\n\n private applyVisibility(): void {\n const open = this.panelControl.isOpen;\n this.visible = open;\n this.eventMode = open ? 'auto' : 'none';\n }\n\n override dispose(): void {\n for (const v of this.childViews) v.dispose();\n this.childViews.length = 0;\n super.dispose();\n }\n}\n","import { type Application } from 'pixi.js';\nimport {\n createUI,\n buildPanel,\n composeMenu,\n type OpenUI,\n type UISpec,\n type HostHooks,\n type CurrencySpec,\n type EventLog,\n type ControlSnapshot,\n type Signal,\n type OpenUIEvents,\n type Dispose,\n type JurisdictionConfig,\n type BlockSpec,\n type NoticeAction,\n type NoticeOptions,\n type RgsErrorOptions,\n} from '@open-slot-ui/core';\nimport { OpenUIPixi, type OpenUIPixiOptions } from './OpenUIPixi';\nimport { PanelBodyView } from './views/PanelBodyView';\n\nexport interface HudOptions extends OpenUIPixiOptions {\n hooks?: HostHooks;\n}\n\n/**\n * The complete-HUD handle returned by `mountHud`. Wraps the headless OpenUI + the\n * Pixi controller with the day-to-day game verbs, so the host rarely touches the\n * lower layers. `dispose()` is the single, leak-free teardown (Charter P12).\n */\nexport interface BootedHud {\n readonly ui: OpenUI;\n readonly pixi: OpenUIPixi;\n on<K extends keyof OpenUIEvents>(type: K, fn: (p: OpenUIEvents[K]) => void): Dispose;\n setBalance(major: number): void;\n setBet(major: number): void;\n /** Set the bonus total-win amount (major units). Shown in the buy-feature slot while\n * the spin button is in free-spins mode (`setFreeSpins(n > 0)`). */\n setTotalWin(major: number): void;\n setCurrency(spec: CurrencySpec): void;\n /** Apply a Stake Engine jurisdiction config (the compliance switchboard) at runtime. */\n applyJurisdiction(jur: JurisdictionConfig): void;\n /** Report a settled round (major units): updates net position + enforces autoplay limits. */\n reportRound(win: number, bet: number): void;\n /** Set the RTP percentage shown by the RTP readout (when `displayRTP`). */\n setRtp(percent: number): void;\n /** Master mute / unmute (music + sfx). */\n setMuted(muted: boolean): void;\n /** Show a menu-style notice modal: declarative blocks + optional action buttons. */\n showNotice(blocks: BlockSpec[], actions?: NoticeAction[]): void;\n /** Show a menu-style error modal — `message`/`opts.title` are literal text OR i18n\n * keys, and `opts.actions` adds custom buttons (e.g. a \"Reload\"). */\n showError(message: string, opts?: NoticeOptions): void;\n /** Show the default (localizable, per-call overridable) message for an RGS status\n * code (e.g. `'ERR_IPB'`, `'ERR_IS'`, `'ERR_MAINTENANCE'`). */\n showRgsError(code: string, opts?: RgsErrorOptions): void;\n /** Show a FATAL error: a blocking modal that LOCKS the HUD and is dismissable only\n * in code (`hideNotice`) — for unrecoverable RGS states. */\n showFatal(message: string, opts?: NoticeOptions): void;\n /** Dismiss the notice / error modal. */\n hideNotice(): void;\n /** Social / sweepstakes mode: one switch swaps gambling wording (+ a coin → GC/SC). */\n setSocial(on: boolean, coin?: string): void;\n /** Switch the spin button to / from its free-spins face: `n > 0` shows \"N FS\". */\n setFreeSpins(n: number): void;\n /** Enter/leave replay mode (Stake `replay=true`) — locks the HUD + shows a REPLAY badge. */\n setReplay(on: boolean): void;\n /** Show a buy-feature confirm modal (Cancel / Confirm). Texts are literal-or-key. */\n confirmBuy(opts: { title?: string; message?: string; onConfirm: () => void; confirmLabel?: string; cancelLabel?: string }): void;\n /** Slide the whole interactive HUD in / out — bottom controls go down, top ones up\n * (behind the status-bar plaque). Non-interactive while moving. */\n showControls(): void;\n hideControls(): void;\n setControlsVisible(visible: boolean): void;\n snapshot(): ControlSnapshot[];\n readonly events: EventLog | undefined;\n readonly inputLocked: Signal<boolean>;\n lockInput(): void;\n unlockInput(): void;\n unmount(): void;\n dispose(): void;\n}\n\n/**\n * The one-call, out-of-the-box entry: `mountHud(app)` boots the full reference\n * HUD; `mountHud(app, spec, opts)` configures it from one JSON UISpec + renderer\n * art/skins. Pure assembly over `createUI` + `OpenUIPixi` (Charter B9).\n */\nexport function mountHud(app: Application, spec: UISpec = {}, opts: HudOptions = {}): BootedHud {\n const { hooks, ...pixiOpts } = opts;\n const ui = createUI(spec, hooks);\n // Compose the unified menu (Settings → Paytable → Rules). A Language switch is\n // added automatically when 2+ locales are configured; `spec.rules` is folded in\n // for back-compat. The built-in Music/Sound reuse the real volume controls.\n const locales = spec.locale ? Array.from(new Set([spec.locale.locale, ...Object.keys(spec.locale.messages)])) : [];\n // `menu: false` (e.g. when the host supplies its own HTML menu) skips the Pixi menu.\n const menu = pixiOpts.menu === false ? false : composeMenu(spec.menu, { locales, localeSelectId: spec.localeSelectId, rulesFallback: spec.rules });\n // Game name + version footer (support / certification) — appended to the menu.\n if (menu && spec.game && (spec.game.name || spec.game.version)) {\n menu.push({ kind: 'legal', id: 'openui-game-info', text: [spec.game.name, spec.game.version ? `v${spec.game.version}` : ''].filter(Boolean).join(' · ') });\n }\n const pixi = new OpenUIPixi(ui, { ...pixiOpts, menu });\n pixi.mount(app);\n\n // The reality-check reminder (RTS 13) is now wired in `createUI` (core), so it runs\n // on a wall-clock timer regardless of renderer — nothing to schedule here.\n\n // Extra declarative panels (beyond the settings menu) render as their own layers.\n const extra: PanelBodyView[] = [];\n if (spec.panels?.length) {\n for (const ps of spec.panels) {\n const built = buildPanel(ps, ui.bus);\n ui.register(built.panel);\n for (const c of built.controls) ui.register(c);\n const view = new PanelBodyView(built.panel, built.controls, built.blocks, ui, app.ticker, {\n controlSkins: pixiOpts.controlSkins,\n });\n pixi.root.addChild(view);\n view.applyLayout(ui.screen.get());\n extra.push(view);\n }\n }\n const offRelayout = ui.screen.subscribe(() => {\n const s = ui.screen.get();\n for (const v of extra) v.applyLayout(s);\n });\n\n const teardown = (): void => {\n offRelayout();\n for (const v of extra) v.dispose();\n extra.length = 0;\n pixi.unmount();\n ui.dispose(); // tear down the headless subscriptions too (Charter P12)\n };\n\n function on<K extends keyof OpenUIEvents>(type: K, fn: (p: OpenUIEvents[K]) => void): Dispose {\n return ui.on(type, fn);\n }\n\n return {\n ui,\n pixi,\n on,\n setBalance: (n) => ui.balance.set(n),\n setBet: (n) => ui.bet.set(n),\n setTotalWin: (n) => ui.totalWin.set(n),\n setCurrency: (c) => {\n ui.balance.setCurrency(c);\n ui.bet.setCurrency(c);\n ui.totalWin.setCurrency(c);\n ui.netPosition.setCurrency(c);\n },\n applyJurisdiction: (j) => ui.applyJurisdiction(j),\n reportRound: (win, bet) => ui.reportRound(win, bet),\n setRtp: (p) => ui.rtp.set(p),\n setMuted: (m) => ui.setMuted(m),\n showNotice: (blocks, actions) => ui.showNotice(blocks, actions),\n showError: (message, opts) => ui.showError(message, opts),\n showRgsError: (code, opts) => ui.showRgsError(code, opts),\n showFatal: (message, opts) => ui.showFatal(message, opts),\n hideNotice: () => ui.hideNotice(),\n setSocial: (on, coin) => ui.setSocial(on, coin),\n setFreeSpins: (n) => ui.spin.setFreeSpins(n),\n setReplay: (on) => ui.setReplay(on),\n confirmBuy: (o) => {\n // Real guard: a jurisdiction that disabled buy-feature makes this a no-op.\n if (ui.isDisabled('buyFeature')) return;\n ui.showNotice(\n [\n { kind: 'heading', id: 'buy-title', text: o.title ?? 'openui.buyFeature.title' },\n { kind: 'text', id: 'buy-body', text: o.message ?? 'openui.buyFeature.message' },\n ],\n [\n { label: o.cancelLabel ?? 'openui.cancel', variant: 'secondary' },\n { label: o.confirmLabel ?? 'openui.confirm', variant: 'primary', onSelect: o.onConfirm },\n ],\n );\n },\n showControls: () => pixi.setControlsVisible(true),\n hideControls: () => pixi.setControlsVisible(false),\n setControlsVisible: (v) => pixi.setControlsVisible(v),\n snapshot: () => ui.snapshot(),\n events: pixi.eventLog,\n inputLocked: ui.locked,\n lockInput: () => ui.lock(),\n unlockInput: () => ui.unlock(),\n unmount: teardown,\n dispose: teardown,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/views/PopoverView.ts","../src/views/PanelView.ts","../src/views/PanelBodyView.ts","../src/mountHud.ts"],"names":["Graphics","Container","opts","on"],"mappings":"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","file":"index.js","sourcesContent":["import { type Ticker, type Texture } from 'pixi.js';\nimport { type PanelControl, type SliderControl, type ButtonControl, type OpenUI } from '@open-slot-ui/core';\nimport { ControlView } from './ControlView';\nimport { SliderView } from './SliderView';\nimport { ButtonView } from './ButtonView';\n\nexport interface PopoverParts {\n music: SliderControl;\n sfx: SliderControl;\n rules: ButtonControl;\n}\n\nexport interface PopoverArt {\n rulesTexture?: Texture;\n musicTrack?: Texture;\n soundTrack?: Texture;\n}\n\ninterface FanItem {\n view: ControlView;\n tx: number;\n ty: number;\n prog: number;\n}\n\nconst GAP = 80; // vertical spacing between fanned items (ref px)\nconst RISE = 26; // how far each item rises into place\nconst STAGGER = 38; // ms between pops — snappy \"pop-pop-pop\"\n// slider track is 290x60 @ ~0.9 → its visual centre, used as the scale pivot\nconst SLIDER_PIVOT_X = 130;\nconst SLIDER_PIVOT_Y = 27;\n\n/**\n * The settings flyout as a VERTICAL FAN: on open, the options swoosh up and pop\n * in one-by-one (bottom→top); on close they retract together. Items are\n * right-aligned and rise above the (right-side) menu button. No static panel.\n */\nexport class PopoverView extends ControlView {\n private readonly music: SliderView;\n private readonly sfx: SliderView;\n private readonly rules: ButtonView;\n private readonly items: FanItem[];\n private phase = 0;\n private running = false;\n private readonly tick: (t: Ticker) => void;\n\n constructor(private readonly panel: PanelControl, parts: PopoverParts, ui: OpenUI, private readonly ticker: Ticker, art: PopoverArt = {}) {\n super(panel, ui);\n\n this.rules = new ButtonView(parts.rules, ui, ticker, { shape: 'pill', height: 50, iconTexture: art.rulesTexture, iconTarget: 50 });\n this.music = new SliderView(parts.music, ui, art.musicTrack);\n this.sfx = new SliderView(parts.sfx, ui, art.soundTrack);\n // pivot sliders at their centre so they scale from the middle, not the left edge\n this.music.pivot.set(SLIDER_PIVOT_X, SLIDER_PIVOT_Y);\n this.sfx.pivot.set(SLIDER_PIVOT_X, SLIDER_PIVOT_Y);\n\n // Right-aligned column rising above the button; pop order = bottom → top.\n // tx/ty are the item CENTRES (rules ButtonView is already centre-origin).\n this.items = [\n { view: this.sfx, tx: -130, ty: -GAP, prog: 0 },\n { view: this.music, tx: -130, ty: -GAP * 2, prog: 0 },\n { view: this.rules, tx: -132, ty: -GAP * 3, prog: 0 },\n ];\n for (const it of this.items) {\n it.view.position.set(it.tx, it.ty);\n it.view.scale.set(0);\n it.view.alpha = 0;\n it.view.visible = false;\n this.addChild(it.view);\n }\n\n this.tick = (t) => this.update(t.deltaMS);\n this.applyState();\n this.disposers.push(this.panel.state.subscribe(() => this.applyState()));\n }\n\n private applyState(): void {\n this.phase = 0;\n const open = this.panel.isOpen;\n this.eventMode = open ? 'auto' : 'none';\n if (open) for (const it of this.items) it.view.visible = true;\n if (!this.running) {\n this.running = true;\n this.ticker.add(this.tick);\n }\n }\n\n private update(dt: number): void {\n this.phase += Math.min(dt, 40); // cap stalls so the stagger never gets skipped\n const open = this.panel.isOpen;\n const finalTarget = open ? 1 : 0;\n let settled = true;\n for (let i = 0; i < this.items.length; i++) {\n const it = this.items[i]!;\n const target = open && this.phase > i * STAGGER ? 1 : 0; // staggered easing target\n it.prog += (target - it.prog) * Math.min(1, dt / (open ? 50 : 80));\n const s = it.prog;\n it.view.scale.set(s);\n it.view.alpha = Math.min(1, s * 1.5);\n it.view.position.set(it.tx, it.ty + (1 - s) * RISE);\n it.view.visible = s > 0.01;\n // settle against the FINAL target so the loop keeps running until every item arrives\n if (Math.abs(it.prog - finalTarget) > 0.01) settled = false;\n }\n if (settled) {\n this.running = false;\n this.ticker.remove(this.tick);\n }\n }\n\n override dispose(): void {\n if (this.running) {\n this.ticker.remove(this.tick);\n this.running = false;\n }\n this.music.dispose();\n this.sfx.dispose();\n this.rules.dispose();\n super.dispose();\n }\n}\n","import { Container, Graphics, Text, Rectangle, type Texture, type FederatedPointerEvent, type Ticker } from 'pixi.js';\nimport { type PanelControl, type ButtonControl, type OpenUI, type ScreenState, type Theme } from '@open-slot-ui/core';\nimport { ControlView } from './ControlView';\nimport { ButtonView } from './ButtonView';\n\nexport type InfoContentBuilder = (theme: Theme, width: number) => Container;\n\nexport interface PanelViewOptions {\n closeTexture?: Texture;\n content?: InfoContentBuilder;\n}\n\n// The modal is an intentionally LIGHT surface (per the design), distinct from the dark HUD theme.\nconst INK = 0x15171c;\nconst CARD = 0xffffff;\nconst HEADER_BG = 0x20242b;\nconst PAD = 16;\nconst HEADER_H = 56;\nconst MAX_W = 600;\n\n/**\n * Full-screen modal: dim backdrop + dark header (title + ✕ close) + a white,\n * scrollable content card. Content is built dynamically (so it scrolls and is\n * data-driven). Faithful to the provided Mobile Rules design.\n */\nexport class PanelView extends ControlView {\n private readonly backdrop = new Graphics();\n private readonly card = new Graphics();\n private readonly headerBg = new Graphics();\n private readonly title: Text;\n private readonly viewport = new Container();\n private readonly maskG = new Graphics();\n private readonly catcher = new Graphics();\n private readonly close: ButtonView;\n private content: Container | undefined;\n private builtWidth = -1;\n private scrollY = 0;\n private contentH = 0;\n private viewportH = 0;\n private dragging = false;\n private lastY = 0;\n private wheelHandler: ((e: WheelEvent) => void) | undefined;\n\n constructor(\n private readonly panel: PanelControl,\n closeBtn: ButtonControl,\n ui: OpenUI,\n ticker: Ticker,\n private readonly opts: PanelViewOptions = {},\n ) {\n super(panel, ui);\n this.zIndex = 100;\n\n this.backdrop.eventMode = 'static';\n this.backdrop.on('pointertap', () => this.panel.closePanel());\n\n this.title = new Text({\n text: panel.title ?? '',\n style: { fontFamily: ui.theme.type.family, fontSize: 22, fill: 0xffffff, fontWeight: '800', letterSpacing: 1 },\n });\n this.title.anchor.set(0.5);\n\n this.viewport.mask = this.maskG;\n this.catcher.eventMode = 'static';\n this.catcher.on('pointerdown', this.onDown);\n this.catcher.on('globalpointermove', this.onMove);\n this.catcher.on('pointerup', this.onUp);\n this.catcher.on('pointerupoutside', this.onUp);\n\n this.close = new ButtonView(closeBtn, ui, ticker, { iconTexture: opts.closeTexture, iconTarget: 44, glyph: 'close', radius: 24 });\n\n this.addChild(this.backdrop, this.card, this.viewport, this.maskG, this.catcher, this.headerBg, this.title, this.close);\n\n this.applyOpen(this.panel.isOpen);\n this.disposers.push(this.panel.state.subscribe(() => this.applyOpen(this.panel.isOpen)));\n }\n\n override applyLayout(screen: ScreenState): void {\n const W = screen.width;\n const H = screen.height;\n this.position.set(0, 0);\n this.scale.set(1);\n\n this.backdrop.clear().rect(0, 0, W, H).fill({ color: 0x000000, alpha: 0.6 });\n this.backdrop.hitArea = new Rectangle(0, 0, W, H);\n\n const cardW = Math.min(W - PAD * 2, MAX_W);\n const cx = (W - cardW) / 2;\n const hy = PAD;\n this.headerBg.clear().roundRect(cx, hy, cardW, HEADER_H, HEADER_H / 2).fill({ color: HEADER_BG });\n this.title.position.set(W / 2, hy + HEADER_H / 2);\n this.close.position.set(cx + cardW - HEADER_H / 2, hy + HEADER_H / 2);\n\n const cardY = hy + HEADER_H + 12;\n const cardH = H - cardY - PAD;\n this.card.clear().roundRect(cx, cardY, cardW, cardH, 22).fill({ color: CARD });\n\n const inset = 20;\n const vpX = cx + inset;\n const vpY = cardY + inset;\n const vpW = cardW - inset * 2;\n const vpH = cardH - inset * 2;\n this.viewport.position.set(vpX, vpY);\n this.viewportH = vpH;\n this.maskG.clear().rect(vpX, vpY, vpW, vpH).fill({ color: 0xffffff });\n this.catcher.clear().rect(vpX, vpY, vpW, vpH).fill({ color: 0xffffff, alpha: 0.0001 });\n\n // (re)build content to the current viewport width\n if (Math.abs(vpW - this.builtWidth) > 1) {\n this.content?.destroy({ children: true });\n this.content = this.opts.content?.(this.ui.theme, vpW) ?? this.fallback(vpW);\n this.viewport.addChild(this.content);\n this.builtWidth = vpW;\n }\n if (this.content) this.content.x = 0;\n this.contentH = this.content?.height ?? 0;\n this.clampScroll();\n }\n\n private fallback(width: number): Container {\n const c = new Container();\n const t = new Text({ text: 'No content provided.', style: { fontFamily: this.ui.theme.type.family, fontSize: 18, fill: INK, wordWrap: true, wordWrapWidth: width } });\n c.addChild(t);\n return c;\n }\n\n private readonly onDown = (e: FederatedPointerEvent): void => {\n this.dragging = true;\n this.lastY = e.global.y;\n };\n private readonly onMove = (e: FederatedPointerEvent): void => {\n if (!this.dragging) return;\n this.scrollY += e.global.y - this.lastY;\n this.lastY = e.global.y;\n this.clampScroll();\n };\n private readonly onUp = (): void => {\n this.dragging = false;\n };\n\n private clampScroll(): void {\n const min = Math.min(0, this.viewportH - this.contentH);\n this.scrollY = Math.max(min, Math.min(0, this.scrollY));\n if (this.content) this.content.y = this.scrollY;\n }\n\n private applyOpen(open: boolean): void {\n this.visible = open;\n this.eventMode = open ? 'static' : 'none';\n this.alpha = open ? 1 : 0;\n if (open) {\n this.scrollY = 0;\n this.clampScroll();\n if (!this.wheelHandler) {\n this.wheelHandler = (e: WheelEvent) => {\n this.scrollY -= e.deltaY;\n this.clampScroll();\n };\n window.addEventListener('wheel', this.wheelHandler, { passive: true });\n }\n } else if (this.wheelHandler) {\n window.removeEventListener('wheel', this.wheelHandler);\n this.wheelHandler = undefined;\n }\n }\n\n override dispose(): void {\n if (this.wheelHandler) window.removeEventListener('wheel', this.wheelHandler);\n this.close.dispose();\n super.dispose();\n }\n}\n","import { Container, Graphics, type Ticker } from 'pixi.js';\nimport { type OpenUI, type PanelControl, type Control, type BlockSpec } from '@open-slot-ui/core';\nimport { ControlView } from './ControlView';\nimport { buildBlockColumn, type ControlViewFactory } from './blockColumn';\n\nexport interface PanelBodyOptions {\n width?: number;\n controlSkins?: Partial<Record<string, ControlViewFactory>>;\n}\n\n/**\n * A small, CENTERED panel body (the settings popover / declarative panels): walks\n * a `BlockSpec[]` via the shared {@link buildBlockColumn} renderer, draws a branded\n * card behind it, and follows the PanelControl's open/closed state. A `modal`\n * variant also gets a dismissable backdrop. Text re-renders on `ui.locale` change.\n * (The big scrollable menu uses {@link MenuView}, which shares the same renderer.)\n */\nexport class PanelBodyView extends ControlView {\n private readonly backdrop = new Graphics();\n private readonly card = new Graphics();\n private readonly content = new Container();\n private childViews: ControlView[] = [];\n private readonly bodyW: number;\n\n constructor(\n private readonly panelControl: PanelControl,\n private readonly controls: Control[],\n private readonly blocks: BlockSpec[],\n ui: OpenUI,\n private readonly ticker: Ticker,\n private readonly opts: PanelBodyOptions = {},\n ) {\n super(panelControl, ui);\n this.bodyW = opts.width ?? 360;\n\n this.addChild(this.backdrop, this.card, this.content);\n this.rebuild();\n this.applyVisibility();\n\n this.disposers.push(\n this.panelControl.state.subscribe(() => this.applyVisibility()),\n this.ui.locale.subscribe(() => {\n if (!this.destroyed) this.rebuild();\n }),\n );\n\n if (this.panelControl.variant === 'modal') {\n this.backdrop.eventMode = 'static';\n this.backdrop.on('pointertap', () => this.panelControl.closePanel());\n }\n }\n\n private rebuild(): void {\n for (const v of this.childViews) v.dispose();\n this.childViews.length = 0;\n // Destroy direct children (wraps/static nodes) WITHOUT children:true so the\n // already-disposed control views aren't re-destroyed (matches the prior code).\n for (const child of this.content.removeChildren()) child.destroy();\n\n const col = buildBlockColumn(this.blocks, this.controls, this.ui, this.ticker, this.bodyW, { controlSkins: this.opts.controlSkins });\n this.childViews = col.views;\n this.content.addChild(...col.content.removeChildren());\n this.content.position.set(0, -col.height / 2);\n this.drawChrome(this.bodyW, col.height);\n }\n\n private drawChrome(width: number, height: number): void {\n const t = this.ui.theme;\n this.card.clear()\n .roundRect(-width / 2, -height / 2, width, height, t.radius.card)\n .fill({ color: t.color.surface })\n .stroke({ width: 3, color: t.color.accent });\n\n this.backdrop.clear();\n if (this.panelControl.variant === 'modal') {\n this.backdrop.rect(-3000, -3000, 6000, 6000).fill({ color: 0x000000, alpha: 0.6 });\n }\n }\n\n private applyVisibility(): void {\n const open = this.panelControl.isOpen;\n this.visible = open;\n this.eventMode = open ? 'auto' : 'none';\n }\n\n override dispose(): void {\n for (const v of this.childViews) v.dispose();\n this.childViews.length = 0;\n super.dispose();\n }\n}\n","import { type Application } from 'pixi.js';\nimport {\n createUI,\n buildPanel,\n composeMenu,\n type OpenUI,\n type UISpec,\n type HostHooks,\n type CurrencySpec,\n type EventLog,\n type ControlSnapshot,\n type Signal,\n type OpenUIEvents,\n type Dispose,\n type JurisdictionConfig,\n type BlockSpec,\n type NoticeAction,\n type NoticeOptions,\n type RgsErrorOptions,\n} from '@open-slot-ui/core';\nimport { OpenUIPixi, type OpenUIPixiOptions } from './OpenUIPixi';\nimport { PanelBodyView } from './views/PanelBodyView';\n\nexport interface HudOptions extends OpenUIPixiOptions {\n hooks?: HostHooks;\n}\n\n/**\n * The complete-HUD handle returned by `mountHud`. Wraps the headless OpenUI + the\n * Pixi controller with the day-to-day game verbs, so the host rarely touches the\n * lower layers. `dispose()` is the single, leak-free teardown (Charter P12).\n */\nexport interface BootedHud {\n readonly ui: OpenUI;\n readonly pixi: OpenUIPixi;\n on<K extends keyof OpenUIEvents>(type: K, fn: (p: OpenUIEvents[K]) => void): Dispose;\n setBalance(major: number): void;\n setBet(major: number): void;\n /** Set the bonus total-win amount (major units). Shown in the buy-feature slot while\n * the spin button is in free-spins mode (`setFreeSpins(n > 0)`). */\n setTotalWin(major: number): void;\n setCurrency(spec: CurrencySpec): void;\n /** Apply a Stake Engine jurisdiction config (the compliance switchboard) at runtime. */\n applyJurisdiction(jur: JurisdictionConfig): void;\n /** Report a settled round (major units): updates net position + enforces autoplay limits. */\n reportRound(win: number, bet: number): void;\n /** Set the RTP percentage shown by the RTP readout (when `displayRTP`). */\n setRtp(percent: number): void;\n /** Master mute / unmute (music + sfx). */\n setMuted(muted: boolean): void;\n /** Show a menu-style notice modal: declarative blocks + optional action buttons. */\n showNotice(blocks: BlockSpec[], actions?: NoticeAction[]): void;\n /** Show a menu-style error modal — `message`/`opts.title` are literal text OR i18n\n * keys, and `opts.actions` adds custom buttons (e.g. a \"Reload\"). */\n showError(message: string, opts?: NoticeOptions): void;\n /** Show the default (localizable, per-call overridable) message for an RGS status\n * code (e.g. `'ERR_IPB'`, `'ERR_IS'`, `'ERR_MAINTENANCE'`). */\n showRgsError(code: string, opts?: RgsErrorOptions): void;\n /** Show a FATAL error: a blocking modal that LOCKS the HUD and is dismissable only\n * in code (`hideNotice`) — for unrecoverable RGS states. */\n showFatal(message: string, opts?: NoticeOptions): void;\n /** Dismiss the notice / error modal. */\n hideNotice(): void;\n /** Social / sweepstakes mode: one switch swaps gambling wording (+ a coin → GC/SC). */\n setSocial(on: boolean, coin?: string): void;\n /** Switch the spin button to / from its free-spins face: `n > 0` shows \"N FS\". */\n setFreeSpins(n: number): void;\n /** Enter/leave replay mode (Stake `replay=true`) — locks the HUD + shows a REPLAY badge. */\n setReplay(on: boolean): void;\n /** Show a buy-feature confirm modal (Cancel / Confirm). Texts are literal-or-key. */\n confirmBuy(opts: { title?: string; message?: string; onConfirm: () => void; confirmLabel?: string; cancelLabel?: string }): void;\n /** Confirm-GATE a buy / bet-mode activation: when its `cost` (× base bet) exceeds\n * the configured `confirmBuyAboveCost` threshold, show a confirm popup naming the\n * feature + `price` and run `onConfirm` only on confirm; otherwise run `onConfirm`\n * straight away. This is how a game honors Stake's \"no one-click activation above\n * 2×\" rule — the library owns the threshold + popup, the game just calls this. */\n requestBuyFeature(opts: {\n cost: number;\n name?: string;\n price?: string;\n onConfirm: () => void;\n title?: string;\n message?: string;\n confirmLabel?: string;\n cancelLabel?: string;\n }): void;\n /** Read-back: would a play of this `cost` (× base bet) require confirmation? */\n shouldConfirmBuy(cost: number): boolean;\n /** Slide the whole interactive HUD in / out — bottom controls go down, top ones up\n * (behind the status-bar plaque). Non-interactive while moving. */\n showControls(): void;\n hideControls(): void;\n setControlsVisible(visible: boolean): void;\n snapshot(): ControlSnapshot[];\n readonly events: EventLog | undefined;\n readonly inputLocked: Signal<boolean>;\n lockInput(): void;\n unlockInput(): void;\n unmount(): void;\n dispose(): void;\n}\n\n/**\n * The one-call, out-of-the-box entry: `mountHud(app)` boots the full reference\n * HUD; `mountHud(app, spec, opts)` configures it from one JSON UISpec + renderer\n * art/skins. Pure assembly over `createUI` + `OpenUIPixi` (Charter B9).\n */\nexport function mountHud(app: Application, spec: UISpec = {}, opts: HudOptions = {}): BootedHud {\n const { hooks, ...pixiOpts } = opts;\n const ui = createUI(spec, hooks);\n // Compose the unified menu (Settings → Paytable → Rules). A Language switch is\n // added automatically when 2+ locales are configured; `spec.rules` is folded in\n // for back-compat. The built-in Music/Sound reuse the real volume controls.\n const locales = spec.locale ? Array.from(new Set([spec.locale.locale, ...Object.keys(spec.locale.messages)])) : [];\n // `menu: false` (e.g. when the host supplies its own HTML menu) skips the Pixi menu.\n const menu = pixiOpts.menu === false ? false : composeMenu(spec.menu, { locales, localeSelectId: spec.localeSelectId, rulesFallback: spec.rules });\n // Game name + version footer (support / certification) — appended to the menu.\n if (menu && spec.game && (spec.game.name || spec.game.version)) {\n menu.push({ kind: 'legal', id: 'openui-game-info', text: [spec.game.name, spec.game.version ? `v${spec.game.version}` : ''].filter(Boolean).join(' · ') });\n }\n const pixi = new OpenUIPixi(ui, { ...pixiOpts, menu });\n pixi.mount(app);\n\n // The reality-check reminder (RTS 13) is now wired in `createUI` (core), so it runs\n // on a wall-clock timer regardless of renderer — nothing to schedule here.\n\n // Extra declarative panels (beyond the settings menu) render as their own layers.\n const extra: PanelBodyView[] = [];\n if (spec.panels?.length) {\n for (const ps of spec.panels) {\n const built = buildPanel(ps, ui.bus);\n ui.register(built.panel);\n for (const c of built.controls) ui.register(c);\n const view = new PanelBodyView(built.panel, built.controls, built.blocks, ui, app.ticker, {\n controlSkins: pixiOpts.controlSkins,\n });\n pixi.root.addChild(view);\n view.applyLayout(ui.screen.get());\n extra.push(view);\n }\n }\n const offRelayout = ui.screen.subscribe(() => {\n const s = ui.screen.get();\n for (const v of extra) v.applyLayout(s);\n });\n\n const teardown = (): void => {\n offRelayout();\n for (const v of extra) v.dispose();\n extra.length = 0;\n pixi.unmount();\n ui.dispose(); // tear down the headless subscriptions too (Charter P12)\n };\n\n function on<K extends keyof OpenUIEvents>(type: K, fn: (p: OpenUIEvents[K]) => void): Dispose {\n return ui.on(type, fn);\n }\n\n return {\n ui,\n pixi,\n on,\n setBalance: (n) => ui.balance.set(n),\n setBet: (n) => ui.bet.set(n),\n setTotalWin: (n) => ui.totalWin.set(n),\n setCurrency: (c) => {\n ui.balance.setCurrency(c);\n ui.bet.setCurrency(c);\n ui.totalWin.setCurrency(c);\n ui.netPosition.setCurrency(c);\n },\n applyJurisdiction: (j) => ui.applyJurisdiction(j),\n reportRound: (win, bet) => ui.reportRound(win, bet),\n setRtp: (p) => ui.rtp.set(p),\n setMuted: (m) => ui.setMuted(m),\n showNotice: (blocks, actions) => ui.showNotice(blocks, actions),\n showError: (message, opts) => ui.showError(message, opts),\n showRgsError: (code, opts) => ui.showRgsError(code, opts),\n showFatal: (message, opts) => ui.showFatal(message, opts),\n hideNotice: () => ui.hideNotice(),\n setSocial: (on, coin) => ui.setSocial(on, coin),\n setFreeSpins: (n) => ui.spin.setFreeSpins(n),\n setReplay: (on) => ui.setReplay(on),\n confirmBuy: (o) => {\n // Real guard: a jurisdiction that disabled buy-feature makes this a no-op.\n if (ui.isDisabled('buyFeature')) return;\n ui.showNotice(\n [\n { kind: 'heading', id: 'buy-title', text: o.title ?? 'openui.buyFeature.title' },\n { kind: 'text', id: 'buy-body', text: o.message ?? 'openui.buyFeature.message' },\n ],\n [\n { label: o.cancelLabel ?? 'openui.cancel', variant: 'secondary' },\n { label: o.confirmLabel ?? 'openui.confirm', variant: 'primary', onSelect: o.onConfirm },\n ],\n );\n },\n shouldConfirmBuy: (cost) => ui.shouldConfirmBuy(cost),\n requestBuyFeature: (o) => {\n if (ui.isDisabled('buyFeature')) return; // jurisdiction fully disabled the feature\n if (!ui.shouldConfirmBuy(o.cost)) {\n o.onConfirm(); // cost at/under the threshold → one click is allowed\n return;\n }\n // Pre-resolve the message (block text can't interpolate); social/locale at open time.\n const message =\n o.message ??\n (o.name\n ? ui.t('openui.buyFeature.confirm', { name: ui.t(o.name), price: o.price ?? '' })\n : 'openui.buyFeature.message');\n ui.showNotice(\n [\n { kind: 'heading', id: 'buy-title', text: o.title ?? 'openui.buyFeature.title' },\n { kind: 'text', id: 'buy-body', text: message },\n ],\n [\n { label: o.cancelLabel ?? 'openui.cancel', variant: 'secondary' },\n { label: o.confirmLabel ?? 'openui.confirm', variant: 'primary', onSelect: o.onConfirm },\n ],\n );\n },\n showControls: () => pixi.setControlsVisible(true),\n hideControls: () => pixi.setControlsVisible(false),\n setControlsVisible: (v) => pixi.setControlsVisible(v),\n snapshot: () => ui.snapshot(),\n events: pixi.eventLog,\n inputLocked: ui.locked,\n lockInput: () => ui.lock(),\n unlockInput: () => ui.unlock(),\n unmount: teardown,\n dispose: teardown,\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-slot-ui/pixi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "PixiJS v8 view + controller binding for open-ui — mount a themeable, responsive, fully-tested slot-game HUD onto your Pixi scene in one call.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pixijs",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"access": "public"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@open-slot-ui/core": "0.
|
|
62
|
+
"@open-slot-ui/core": "0.6.0"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"pixi.js": "^8"
|