@open-slot-ui/core 0.1.0 → 0.2.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.d.cts CHANGED
@@ -1084,9 +1084,19 @@ interface Translator {
1084
1084
  /** Switch the active locale (a no-op for the same locale); fires onChange. */
1085
1085
  setLocale(next: string): void;
1086
1086
  onChange(cb: (locale: string) => void): Dispose;
1087
+ /** Switch social/sweepstakes wording on/off. In social mode `t` resolves from a
1088
+ * SEPARATE social dictionary first, so social copy can never be mixed into the
1089
+ * normal keys by accident (by design). No-op if unsupported. */
1090
+ setSocial?(on: boolean): void;
1087
1091
  }
1088
1092
  /** open-ui owns this namespace; the host's translator may override any key. */
1089
1093
  declare const openuiDefaults: Record<string, string>;
1094
+ /**
1095
+ * Social / sweepstakes wording — a SEPARATE dictionary (same keys as the normal
1096
+ * ones). Kept apart on purpose so a host can never mix gambling and social copy in
1097
+ * one map: provide your social overrides under `locale.socialMessages`, not inline.
1098
+ */
1099
+ declare const openuiSocialDefaults: Record<string, string>;
1090
1100
  /**
1091
1101
  * Zero-dep dictionary translator. Falls back to open-ui defaults, then to the
1092
1102
  * key itself only if nothing is found — but built-in keys always resolve, so the
@@ -1094,16 +1104,22 @@ declare const openuiDefaults: Record<string, string>;
1094
1104
  */
1095
1105
  declare class DictionaryTranslator implements Translator {
1096
1106
  private readonly messages;
1107
+ /** SEPARATE social/sweepstakes dictionary — consulted first in social mode. */
1108
+ private readonly socialMessages;
1097
1109
  private _locale;
1110
+ private _social;
1098
1111
  private readonly subs;
1099
- constructor(messages: Record<string, Record<string, string>>, locale: string);
1112
+ constructor(messages: Record<string, Record<string, string>>, locale: string,
1113
+ /** SEPARATE social/sweepstakes dictionary — consulted first in social mode. */
1114
+ socialMessages?: Record<string, Record<string, string>>);
1100
1115
  get locale(): string;
1101
1116
  setLocale(next: string): void;
1117
+ setSocial(on: boolean): void;
1102
1118
  t(key: string, vars?: Record<string, string | number>): string;
1103
1119
  onChange(cb: (locale: string) => void): Dispose;
1104
1120
  }
1105
1121
  /** Convenience factory for a zero-dep dictionary translator. */
1106
- declare function dictionary(messages: Record<string, Record<string, string>>, locale: string): DictionaryTranslator;
1122
+ declare function dictionary(messages: Record<string, Record<string, string>>, locale: string, socialMessages?: Record<string, Record<string, string>>): DictionaryTranslator;
1107
1123
 
1108
1124
  interface OpenUIOptions {
1109
1125
  theme?: Theme;
@@ -1183,9 +1199,6 @@ declare class OpenUI {
1183
1199
  readonly settingsPanel: PanelControl;
1184
1200
  readonly musicSlider: SliderControl;
1185
1201
  readonly sfxSlider: SliderControl;
1186
- readonly rulesButton: ButtonControl;
1187
- readonly infoPanel: PanelControl;
1188
- readonly infoClose: ButtonControl;
1189
1202
  readonly turbo: TurboControl;
1190
1203
  readonly autoplay: AutoplayControl;
1191
1204
  readonly bonusButton: ButtonControl;
@@ -1264,20 +1277,21 @@ declare class OpenUI {
1264
1277
  * `localeChanged`; controls' views, subscribed to `locale`, re-render their text.
1265
1278
  */
1266
1279
  setLocale(next: string): void;
1267
- /** Translate a key (or pass plain text through) via the active translator. In
1268
- * social mode, a `<key>.social` variant wins when one resolves so gambling
1269
- * wording (Bet/Buy feature) swaps to sweepstakes terms automatically. */
1280
+ /** Translate a key (or pass plain text through) via the active translator. Social
1281
+ * wording is resolved by the translator from a SEPARATE social dictionary (see
1282
+ * `setSocial`), so gambling and social copy can never be mixed by accident. */
1270
1283
  t(key: string, vars?: Record<string, string | number>): string;
1271
1284
  /**
1272
- * Turn social / sweepstakes mode on or off (one switch). Swaps gambling wording
1273
- * (Bet/Buy feature social terms via `<key>.social` i18n) AND, when a `coin` is
1274
- * given (e.g. `'GC'`/`'SC'`/`'XGC'`), shows balance/bet/net in that coin. Wording
1275
- * re-renders live; the host can still override any `.social` key.
1285
+ * Turn social / sweepstakes mode on or off (one switch). Flips the translator to
1286
+ * its SEPARATE social dictionary (Bet→Play, Buy feature→Play bonus, etc.) and,
1287
+ * when a `coin` is given (e.g. `'GC'`/`'SC'`), shows balance/bet/net in that coin.
1288
+ * Wording re-renders live. Social copy lives in `locale.socialMessages` kept
1289
+ * apart from your normal `locale.messages` by design.
1276
1290
  */
1277
1291
  setSocial(on: boolean, coin?: string): void;
1278
1292
  /** Read-back: did the applied jurisdiction disable this feature? (real guard, not
1279
1293
  * just a hide — `confirmBuy`/autoplay entry points consult this). */
1280
- isDisabled(feature: 'autoplay' | 'buyFeature' | 'turbo' | 'superTurbo' | 'fullscreen' | 'slamstop' | 'spacebar'): boolean;
1294
+ isDisabled(feature: 'autoplay' | 'buyFeature' | 'turbo' | 'fullscreen' | 'slamstop' | 'spacebar'): boolean;
1281
1295
  /**
1282
1296
  * Start a reality-check reminder (RTS 13). Every `everyMinutes` (WALL-CLOCK, so a
1283
1297
  * backgrounded tab can't cheat it) it emits a `realityCheck` event, stops autoplay,
@@ -1309,7 +1323,6 @@ interface JurisdictionConfig {
1309
1323
  socialCasino?: boolean;
1310
1324
  disabledFullscreen?: boolean;
1311
1325
  disabledTurbo?: boolean;
1312
- disabledSuperTurbo?: boolean;
1313
1326
  disabledAutoplay?: boolean;
1314
1327
  disabledSlamstop?: boolean;
1315
1328
  disabledSpacebar?: boolean;
@@ -1568,6 +1581,9 @@ interface UISpec {
1568
1581
  locale?: {
1569
1582
  messages: Record<string, Record<string, string>>;
1570
1583
  locale: string;
1584
+ /** SEPARATE social/sweepstakes wording dictionary (same keys as `messages`),
1585
+ * used only in social mode — kept apart so the two can't be mixed up. */
1586
+ socialMessages?: Record<string, Record<string, string>>;
1571
1587
  };
1572
1588
  /** Block/control id whose `optionSelected` switches the locale. Default 'lang'. */
1573
1589
  localeSelectId?: string;
@@ -1582,9 +1598,6 @@ interface UISpec {
1582
1598
  jurisdiction?: JurisdictionConfig;
1583
1599
  /** Initial RTP percentage for the RTP readout (e.g. 96 → "96.0%"). */
1584
1600
  rtp?: number;
1585
- /** Put the compliance readouts (net · RTP · session) in a thin status bar pinned
1586
- * to the `'top'` or `'bottom'` edge instead of at screen corners. */
1587
- statusBar?: 'top' | 'bottom';
1588
1601
  /** Game name + version — shown in the menu footer (support / certification). */
1589
1602
  game?: {
1590
1603
  name?: string;
@@ -1792,24 +1805,4 @@ declare function buildBetLadder(cfg: RgsBetConfig, divisor?: number): {
1792
1805
  /** Clamp a stake (major units) to the RGS min/max and snap to `stepBet`. Pure. */
1793
1806
  declare function clampBet(amount: number, cfg: RgsBetConfig, divisor?: number): number;
1794
1807
 
1795
- /**
1796
- * Win-celebration classifier — the RTS 14F guardrail. open-ui doesn't render the win
1797
- * (the game does), but this helper lets a game decide HOW LOUD to celebrate without
1798
- * ever celebrating a return ≤ the stake (the most-fined responsible-gambling rule).
1799
- */
1800
- interface WinTier {
1801
- name: string;
1802
- /** Minimum win/stake multiplier for this tier. */
1803
- minMultiplier: number;
1804
- }
1805
- /** Default escalation tiers (multipliers of stake). */
1806
- declare const DEFAULT_WIN_TIERS: readonly WinTier[];
1807
- /**
1808
- * Classify a win for celebration. Returns `'none'` when the win is ≤ the stake (so a
1809
- * "win" that returns less than was staked is NEVER celebrated — UKGC RTS 14F), else
1810
- * `'win'` for a positive win below the first tier, or the highest tier whose
1811
- * multiplier threshold is met. Pure + total.
1812
- */
1813
- declare function winTier(win: number, stake: number, tiers?: readonly WinTier[]): string;
1814
-
1815
- export { API_AMOUNT_DIVISOR, type Anchor, AutoplayControl, type AutoplayLimits, type AutoplayMode, type AutoplayOptions, BLOCK_KINDS, type BlockFactory, type BlockSpec, type Breakpoint, type BuiltPanel, ButtonControl, type ButtonOptions, CURRENCY_TABLE, CardControl, type CardOptions, type ComposeMenuOptions, Control, type ControlOptions, type ControlOverride, ControlRegistry, type ControlSnapshot, type CurrencyInfo, type CurrencySpec, DEFAULT_MENU_TITLES, DEFAULT_NOTICE_ACTION, DEFAULT_WIN_TIERS, type DeepPartial, DictionaryTranslator, type Dispose, EventBus, EventLog, type EventLogOptions, type EventMap, Fade, type HostHooks, type JurisdictionConfig, type KnownControlId, LOCALE_LABELS, type LayoutConfig, type LayoutSpec, type LoggedEvent, type MenuSpec, type NoticeAction, type NoticeOptions, OpenUI, type OpenUIEvents, type OpenUIOptions, type Orientation, PanelControl, type PanelOptions, type PanelSpec, type PanelVariant, Parallel, type Placement, Pulse, RGS_ERROR_KEYS, ReadoutControl, type ReadoutKind, type ReadoutOptions, type RealityCheckOptions, type Rect, type ResponsiveKey, type ResponsiveOverride, type RgsBetConfig, type RgsErrorCode, type RgsErrorOptions, type ScreenState, SelectControl, type SelectControlOptions, type SelectOption, Sequence, Signal, SliderControl, type SliderOptions, type SpecIssue, SpinControl, type SpinPress, type SpinSpec, Squish, type StateDef, type StateMap, StepperControl, type StepperOptions, type Subscribable, type Theme, type ThemeChoice, type ThemeIssue, type ThemeOverrides, type ThemePreset, ToggleControl, type ToggleOptions, type Transition, type Translator, TurboControl, type TurboOptions, type TurboSpec, Turn, type UISpec, ValueDisplay, type ValueDisplayOptions, type ViewInspect, type WinTier, applyJurisdiction, breakpointFor, buildBetLadder, buildBlocks, buildPanel, buttonBlocks, clampBet, clampDecimals, clampDigits, clampMinDigits, composeMenu, computeScreen, createUI, defaultHudSpec, defaultLayoutConfig, defaultTheme, defineUI, dictionary, displayDigits, effect, errorBlocks, extendTheme, formatAmount, installResponsive, integerDigits, isSafeColor, isSocialCurrency, openuiDefaults, resolveCurrency, resolvePlacement, resolveTheme, resolveTurboModes, safeAmount, sanitizeThemeOverrides, themePresets, validateSpec, valueFitMaxWidth, winTier };
1808
+ export { API_AMOUNT_DIVISOR, type Anchor, AutoplayControl, type AutoplayLimits, type AutoplayMode, type AutoplayOptions, BLOCK_KINDS, type BlockFactory, type BlockSpec, type Breakpoint, type BuiltPanel, ButtonControl, type ButtonOptions, CURRENCY_TABLE, CardControl, type CardOptions, type ComposeMenuOptions, Control, type ControlOptions, type ControlOverride, ControlRegistry, type ControlSnapshot, type CurrencyInfo, type CurrencySpec, DEFAULT_MENU_TITLES, DEFAULT_NOTICE_ACTION, type DeepPartial, DictionaryTranslator, type Dispose, EventBus, EventLog, type EventLogOptions, type EventMap, Fade, type HostHooks, type JurisdictionConfig, type KnownControlId, LOCALE_LABELS, type LayoutConfig, type LayoutSpec, type LoggedEvent, type MenuSpec, type NoticeAction, type NoticeOptions, OpenUI, type OpenUIEvents, type OpenUIOptions, type Orientation, PanelControl, type PanelOptions, type PanelSpec, type PanelVariant, Parallel, type Placement, Pulse, RGS_ERROR_KEYS, ReadoutControl, type ReadoutKind, type ReadoutOptions, type RealityCheckOptions, type Rect, type ResponsiveKey, type ResponsiveOverride, type RgsBetConfig, type RgsErrorCode, type RgsErrorOptions, type ScreenState, SelectControl, type SelectControlOptions, type SelectOption, Sequence, Signal, SliderControl, type SliderOptions, type SpecIssue, SpinControl, type SpinPress, type SpinSpec, Squish, type StateDef, type StateMap, StepperControl, type StepperOptions, type Subscribable, type Theme, type ThemeChoice, type ThemeIssue, type ThemeOverrides, type ThemePreset, ToggleControl, type ToggleOptions, type Transition, type Translator, TurboControl, type TurboOptions, type TurboSpec, Turn, type UISpec, ValueDisplay, type ValueDisplayOptions, type ViewInspect, applyJurisdiction, breakpointFor, buildBetLadder, buildBlocks, buildPanel, buttonBlocks, clampBet, clampDecimals, clampDigits, clampMinDigits, composeMenu, computeScreen, createUI, defaultHudSpec, defaultLayoutConfig, defaultTheme, defineUI, dictionary, displayDigits, effect, errorBlocks, extendTheme, formatAmount, installResponsive, integerDigits, isSafeColor, isSocialCurrency, openuiDefaults, openuiSocialDefaults, resolveCurrency, resolvePlacement, resolveTheme, resolveTurboModes, safeAmount, sanitizeThemeOverrides, themePresets, validateSpec, valueFitMaxWidth };
package/dist/index.d.ts CHANGED
@@ -1084,9 +1084,19 @@ interface Translator {
1084
1084
  /** Switch the active locale (a no-op for the same locale); fires onChange. */
1085
1085
  setLocale(next: string): void;
1086
1086
  onChange(cb: (locale: string) => void): Dispose;
1087
+ /** Switch social/sweepstakes wording on/off. In social mode `t` resolves from a
1088
+ * SEPARATE social dictionary first, so social copy can never be mixed into the
1089
+ * normal keys by accident (by design). No-op if unsupported. */
1090
+ setSocial?(on: boolean): void;
1087
1091
  }
1088
1092
  /** open-ui owns this namespace; the host's translator may override any key. */
1089
1093
  declare const openuiDefaults: Record<string, string>;
1094
+ /**
1095
+ * Social / sweepstakes wording — a SEPARATE dictionary (same keys as the normal
1096
+ * ones). Kept apart on purpose so a host can never mix gambling and social copy in
1097
+ * one map: provide your social overrides under `locale.socialMessages`, not inline.
1098
+ */
1099
+ declare const openuiSocialDefaults: Record<string, string>;
1090
1100
  /**
1091
1101
  * Zero-dep dictionary translator. Falls back to open-ui defaults, then to the
1092
1102
  * key itself only if nothing is found — but built-in keys always resolve, so the
@@ -1094,16 +1104,22 @@ declare const openuiDefaults: Record<string, string>;
1094
1104
  */
1095
1105
  declare class DictionaryTranslator implements Translator {
1096
1106
  private readonly messages;
1107
+ /** SEPARATE social/sweepstakes dictionary — consulted first in social mode. */
1108
+ private readonly socialMessages;
1097
1109
  private _locale;
1110
+ private _social;
1098
1111
  private readonly subs;
1099
- constructor(messages: Record<string, Record<string, string>>, locale: string);
1112
+ constructor(messages: Record<string, Record<string, string>>, locale: string,
1113
+ /** SEPARATE social/sweepstakes dictionary — consulted first in social mode. */
1114
+ socialMessages?: Record<string, Record<string, string>>);
1100
1115
  get locale(): string;
1101
1116
  setLocale(next: string): void;
1117
+ setSocial(on: boolean): void;
1102
1118
  t(key: string, vars?: Record<string, string | number>): string;
1103
1119
  onChange(cb: (locale: string) => void): Dispose;
1104
1120
  }
1105
1121
  /** Convenience factory for a zero-dep dictionary translator. */
1106
- declare function dictionary(messages: Record<string, Record<string, string>>, locale: string): DictionaryTranslator;
1122
+ declare function dictionary(messages: Record<string, Record<string, string>>, locale: string, socialMessages?: Record<string, Record<string, string>>): DictionaryTranslator;
1107
1123
 
1108
1124
  interface OpenUIOptions {
1109
1125
  theme?: Theme;
@@ -1183,9 +1199,6 @@ declare class OpenUI {
1183
1199
  readonly settingsPanel: PanelControl;
1184
1200
  readonly musicSlider: SliderControl;
1185
1201
  readonly sfxSlider: SliderControl;
1186
- readonly rulesButton: ButtonControl;
1187
- readonly infoPanel: PanelControl;
1188
- readonly infoClose: ButtonControl;
1189
1202
  readonly turbo: TurboControl;
1190
1203
  readonly autoplay: AutoplayControl;
1191
1204
  readonly bonusButton: ButtonControl;
@@ -1264,20 +1277,21 @@ declare class OpenUI {
1264
1277
  * `localeChanged`; controls' views, subscribed to `locale`, re-render their text.
1265
1278
  */
1266
1279
  setLocale(next: string): void;
1267
- /** Translate a key (or pass plain text through) via the active translator. In
1268
- * social mode, a `<key>.social` variant wins when one resolves so gambling
1269
- * wording (Bet/Buy feature) swaps to sweepstakes terms automatically. */
1280
+ /** Translate a key (or pass plain text through) via the active translator. Social
1281
+ * wording is resolved by the translator from a SEPARATE social dictionary (see
1282
+ * `setSocial`), so gambling and social copy can never be mixed by accident. */
1270
1283
  t(key: string, vars?: Record<string, string | number>): string;
1271
1284
  /**
1272
- * Turn social / sweepstakes mode on or off (one switch). Swaps gambling wording
1273
- * (Bet/Buy feature social terms via `<key>.social` i18n) AND, when a `coin` is
1274
- * given (e.g. `'GC'`/`'SC'`/`'XGC'`), shows balance/bet/net in that coin. Wording
1275
- * re-renders live; the host can still override any `.social` key.
1285
+ * Turn social / sweepstakes mode on or off (one switch). Flips the translator to
1286
+ * its SEPARATE social dictionary (Bet→Play, Buy feature→Play bonus, etc.) and,
1287
+ * when a `coin` is given (e.g. `'GC'`/`'SC'`), shows balance/bet/net in that coin.
1288
+ * Wording re-renders live. Social copy lives in `locale.socialMessages` kept
1289
+ * apart from your normal `locale.messages` by design.
1276
1290
  */
1277
1291
  setSocial(on: boolean, coin?: string): void;
1278
1292
  /** Read-back: did the applied jurisdiction disable this feature? (real guard, not
1279
1293
  * just a hide — `confirmBuy`/autoplay entry points consult this). */
1280
- isDisabled(feature: 'autoplay' | 'buyFeature' | 'turbo' | 'superTurbo' | 'fullscreen' | 'slamstop' | 'spacebar'): boolean;
1294
+ isDisabled(feature: 'autoplay' | 'buyFeature' | 'turbo' | 'fullscreen' | 'slamstop' | 'spacebar'): boolean;
1281
1295
  /**
1282
1296
  * Start a reality-check reminder (RTS 13). Every `everyMinutes` (WALL-CLOCK, so a
1283
1297
  * backgrounded tab can't cheat it) it emits a `realityCheck` event, stops autoplay,
@@ -1309,7 +1323,6 @@ interface JurisdictionConfig {
1309
1323
  socialCasino?: boolean;
1310
1324
  disabledFullscreen?: boolean;
1311
1325
  disabledTurbo?: boolean;
1312
- disabledSuperTurbo?: boolean;
1313
1326
  disabledAutoplay?: boolean;
1314
1327
  disabledSlamstop?: boolean;
1315
1328
  disabledSpacebar?: boolean;
@@ -1568,6 +1581,9 @@ interface UISpec {
1568
1581
  locale?: {
1569
1582
  messages: Record<string, Record<string, string>>;
1570
1583
  locale: string;
1584
+ /** SEPARATE social/sweepstakes wording dictionary (same keys as `messages`),
1585
+ * used only in social mode — kept apart so the two can't be mixed up. */
1586
+ socialMessages?: Record<string, Record<string, string>>;
1571
1587
  };
1572
1588
  /** Block/control id whose `optionSelected` switches the locale. Default 'lang'. */
1573
1589
  localeSelectId?: string;
@@ -1582,9 +1598,6 @@ interface UISpec {
1582
1598
  jurisdiction?: JurisdictionConfig;
1583
1599
  /** Initial RTP percentage for the RTP readout (e.g. 96 → "96.0%"). */
1584
1600
  rtp?: number;
1585
- /** Put the compliance readouts (net · RTP · session) in a thin status bar pinned
1586
- * to the `'top'` or `'bottom'` edge instead of at screen corners. */
1587
- statusBar?: 'top' | 'bottom';
1588
1601
  /** Game name + version — shown in the menu footer (support / certification). */
1589
1602
  game?: {
1590
1603
  name?: string;
@@ -1792,24 +1805,4 @@ declare function buildBetLadder(cfg: RgsBetConfig, divisor?: number): {
1792
1805
  /** Clamp a stake (major units) to the RGS min/max and snap to `stepBet`. Pure. */
1793
1806
  declare function clampBet(amount: number, cfg: RgsBetConfig, divisor?: number): number;
1794
1807
 
1795
- /**
1796
- * Win-celebration classifier — the RTS 14F guardrail. open-ui doesn't render the win
1797
- * (the game does), but this helper lets a game decide HOW LOUD to celebrate without
1798
- * ever celebrating a return ≤ the stake (the most-fined responsible-gambling rule).
1799
- */
1800
- interface WinTier {
1801
- name: string;
1802
- /** Minimum win/stake multiplier for this tier. */
1803
- minMultiplier: number;
1804
- }
1805
- /** Default escalation tiers (multipliers of stake). */
1806
- declare const DEFAULT_WIN_TIERS: readonly WinTier[];
1807
- /**
1808
- * Classify a win for celebration. Returns `'none'` when the win is ≤ the stake (so a
1809
- * "win" that returns less than was staked is NEVER celebrated — UKGC RTS 14F), else
1810
- * `'win'` for a positive win below the first tier, or the highest tier whose
1811
- * multiplier threshold is met. Pure + total.
1812
- */
1813
- declare function winTier(win: number, stake: number, tiers?: readonly WinTier[]): string;
1814
-
1815
- export { API_AMOUNT_DIVISOR, type Anchor, AutoplayControl, type AutoplayLimits, type AutoplayMode, type AutoplayOptions, BLOCK_KINDS, type BlockFactory, type BlockSpec, type Breakpoint, type BuiltPanel, ButtonControl, type ButtonOptions, CURRENCY_TABLE, CardControl, type CardOptions, type ComposeMenuOptions, Control, type ControlOptions, type ControlOverride, ControlRegistry, type ControlSnapshot, type CurrencyInfo, type CurrencySpec, DEFAULT_MENU_TITLES, DEFAULT_NOTICE_ACTION, DEFAULT_WIN_TIERS, type DeepPartial, DictionaryTranslator, type Dispose, EventBus, EventLog, type EventLogOptions, type EventMap, Fade, type HostHooks, type JurisdictionConfig, type KnownControlId, LOCALE_LABELS, type LayoutConfig, type LayoutSpec, type LoggedEvent, type MenuSpec, type NoticeAction, type NoticeOptions, OpenUI, type OpenUIEvents, type OpenUIOptions, type Orientation, PanelControl, type PanelOptions, type PanelSpec, type PanelVariant, Parallel, type Placement, Pulse, RGS_ERROR_KEYS, ReadoutControl, type ReadoutKind, type ReadoutOptions, type RealityCheckOptions, type Rect, type ResponsiveKey, type ResponsiveOverride, type RgsBetConfig, type RgsErrorCode, type RgsErrorOptions, type ScreenState, SelectControl, type SelectControlOptions, type SelectOption, Sequence, Signal, SliderControl, type SliderOptions, type SpecIssue, SpinControl, type SpinPress, type SpinSpec, Squish, type StateDef, type StateMap, StepperControl, type StepperOptions, type Subscribable, type Theme, type ThemeChoice, type ThemeIssue, type ThemeOverrides, type ThemePreset, ToggleControl, type ToggleOptions, type Transition, type Translator, TurboControl, type TurboOptions, type TurboSpec, Turn, type UISpec, ValueDisplay, type ValueDisplayOptions, type ViewInspect, type WinTier, applyJurisdiction, breakpointFor, buildBetLadder, buildBlocks, buildPanel, buttonBlocks, clampBet, clampDecimals, clampDigits, clampMinDigits, composeMenu, computeScreen, createUI, defaultHudSpec, defaultLayoutConfig, defaultTheme, defineUI, dictionary, displayDigits, effect, errorBlocks, extendTheme, formatAmount, installResponsive, integerDigits, isSafeColor, isSocialCurrency, openuiDefaults, resolveCurrency, resolvePlacement, resolveTheme, resolveTurboModes, safeAmount, sanitizeThemeOverrides, themePresets, validateSpec, valueFitMaxWidth, winTier };
1808
+ export { API_AMOUNT_DIVISOR, type Anchor, AutoplayControl, type AutoplayLimits, type AutoplayMode, type AutoplayOptions, BLOCK_KINDS, type BlockFactory, type BlockSpec, type Breakpoint, type BuiltPanel, ButtonControl, type ButtonOptions, CURRENCY_TABLE, CardControl, type CardOptions, type ComposeMenuOptions, Control, type ControlOptions, type ControlOverride, ControlRegistry, type ControlSnapshot, type CurrencyInfo, type CurrencySpec, DEFAULT_MENU_TITLES, DEFAULT_NOTICE_ACTION, type DeepPartial, DictionaryTranslator, type Dispose, EventBus, EventLog, type EventLogOptions, type EventMap, Fade, type HostHooks, type JurisdictionConfig, type KnownControlId, LOCALE_LABELS, type LayoutConfig, type LayoutSpec, type LoggedEvent, type MenuSpec, type NoticeAction, type NoticeOptions, OpenUI, type OpenUIEvents, type OpenUIOptions, type Orientation, PanelControl, type PanelOptions, type PanelSpec, type PanelVariant, Parallel, type Placement, Pulse, RGS_ERROR_KEYS, ReadoutControl, type ReadoutKind, type ReadoutOptions, type RealityCheckOptions, type Rect, type ResponsiveKey, type ResponsiveOverride, type RgsBetConfig, type RgsErrorCode, type RgsErrorOptions, type ScreenState, SelectControl, type SelectControlOptions, type SelectOption, Sequence, Signal, SliderControl, type SliderOptions, type SpecIssue, SpinControl, type SpinPress, type SpinSpec, Squish, type StateDef, type StateMap, StepperControl, type StepperOptions, type Subscribable, type Theme, type ThemeChoice, type ThemeIssue, type ThemeOverrides, type ThemePreset, ToggleControl, type ToggleOptions, type Transition, type Translator, TurboControl, type TurboOptions, type TurboSpec, Turn, type UISpec, ValueDisplay, type ValueDisplayOptions, type ViewInspect, applyJurisdiction, breakpointFor, buildBetLadder, buildBlocks, buildPanel, buttonBlocks, clampBet, clampDecimals, clampDigits, clampMinDigits, composeMenu, computeScreen, createUI, defaultHudSpec, defaultLayoutConfig, defaultTheme, defineUI, dictionary, displayDigits, effect, errorBlocks, extendTheme, formatAmount, installResponsive, integerDigits, isSafeColor, isSocialCurrency, openuiDefaults, openuiSocialDefaults, resolveCurrency, resolvePlacement, resolveTheme, resolveTurboModes, safeAmount, sanitizeThemeOverrides, themePresets, validateSpec, valueFitMaxWidth };
package/dist/index.js CHANGED
@@ -1170,9 +1170,6 @@ function validateSpec(spec) {
1170
1170
  if (spec.rtp != null && !(typeof spec.rtp === "number" && Number.isFinite(spec.rtp))) {
1171
1171
  add("error", "rtp", "bad-rtp", `rtp must be a number, got ${String(spec.rtp)}`);
1172
1172
  }
1173
- if (spec.statusBar != null && spec.statusBar !== "top" && spec.statusBar !== "bottom") {
1174
- add("error", "statusBar", "bad-statusbar", `statusBar must be 'top' or 'bottom', got "${String(spec.statusBar)}"`);
1175
- }
1176
1173
  if (spec.realityCheck != null && !(typeof spec.realityCheck.everyMinutes === "number" && spec.realityCheck.everyMinutes > 0)) {
1177
1174
  add("error", "realityCheck.everyMinutes", "bad-interval", "realityCheck.everyMinutes must be a number > 0");
1178
1175
  }
@@ -1312,7 +1309,6 @@ function applyJurisdiction(ui, jur) {
1312
1309
  lockHidden("bonus");
1313
1310
  ui.bonusButton.disable();
1314
1311
  }
1315
- if (jur.disabledSuperTurbo && ui.turbo.modeCount > 2) ui.turbo.setModes(["off", "on"]);
1316
1312
  if (jur.disabledSlamstop) ui.spin.allowSlamStop.set(false);
1317
1313
  if (jur.disabledSpacebar) {
1318
1314
  ui.spin.holdToSpin = false;
@@ -1386,13 +1382,6 @@ var openuiDefaults = {
1386
1382
  "openui.buyFeature.title": "Buy feature",
1387
1383
  "openui.buyFeature.message": "Buy this feature now?",
1388
1384
  "openui.freeSpins": "FS",
1389
- // ── social / sweepstakes wording (used when `ui.social` is on; see OpenUI.t) ──
1390
- // open-ui resolves `<key>.social` first in social mode, falling back to the base
1391
- // key. These are the gambling-loaded terms a sweepstakes jurisdiction must avoid;
1392
- // override any of them (or add `openui.bet.social` etc.) in your messages dict.
1393
- "openui.buyFeature.title.social": "Play bonus",
1394
- "openui.buyFeature.message.social": "Play this bonus now?",
1395
- "openui.win.social": "Prize",
1396
1385
  // reality check (RTS 13) — {{minutes}} is interpolated by open-ui's scheduler
1397
1386
  "openui.realityCheck.title": "Reality check",
1398
1387
  "openui.realityCheck.message": "You've been playing for {{minutes}} minutes. Take a moment before continuing.",
@@ -1414,17 +1403,27 @@ var openuiDefaults = {
1414
1403
  "openui.err.connection.title": "Connection lost",
1415
1404
  "openui.err.connection.message": "A stable connection is required. Reload to finish any open round."
1416
1405
  };
1406
+ var openuiSocialDefaults = {
1407
+ "openui.bet": "Play",
1408
+ "openui.balance": "Credits",
1409
+ "openui.win": "Prize",
1410
+ "openui.buyFeature.title": "Play bonus",
1411
+ "openui.buyFeature.message": "Play this bonus now?"
1412
+ };
1417
1413
  function interpolate(template, vars) {
1418
1414
  if (!vars) return template;
1419
1415
  return template.replace(/\{\{(\w+)\}\}/g, (_m, k) => String(vars[k] ?? `{{${k}}}`));
1420
1416
  }
1421
1417
  var DictionaryTranslator = class {
1422
- constructor(messages, locale) {
1418
+ constructor(messages, locale, socialMessages = {}) {
1423
1419
  this.messages = messages;
1420
+ this.socialMessages = socialMessages;
1424
1421
  this._locale = locale;
1425
1422
  }
1426
1423
  messages;
1424
+ socialMessages;
1427
1425
  _locale;
1426
+ _social = false;
1428
1427
  subs = /* @__PURE__ */ new Set();
1429
1428
  get locale() {
1430
1429
  return this._locale;
@@ -1434,8 +1433,12 @@ var DictionaryTranslator = class {
1434
1433
  this._locale = next;
1435
1434
  for (const cb of [...this.subs]) cb(next);
1436
1435
  }
1436
+ setSocial(on) {
1437
+ this._social = on;
1438
+ }
1437
1439
  t(key, vars) {
1438
- const resolved = this.messages[this._locale]?.[key] ?? openuiDefaults[key] ?? key;
1440
+ const social = this._social ? this.socialMessages[this._locale]?.[key] ?? openuiSocialDefaults[key] : void 0;
1441
+ const resolved = social ?? this.messages[this._locale]?.[key] ?? openuiDefaults[key] ?? key;
1439
1442
  return interpolate(resolved, vars);
1440
1443
  }
1441
1444
  onChange(cb) {
@@ -1445,8 +1448,8 @@ var DictionaryTranslator = class {
1445
1448
  };
1446
1449
  }
1447
1450
  };
1448
- function dictionary(messages, locale) {
1449
- return new DictionaryTranslator(messages, locale);
1451
+ function dictionary(messages, locale, socialMessages) {
1452
+ return new DictionaryTranslator(messages, locale, socialMessages);
1450
1453
  }
1451
1454
 
1452
1455
  // src/format/currency.ts
@@ -1552,9 +1555,6 @@ var OpenUI = class {
1552
1555
  settingsPanel;
1553
1556
  musicSlider;
1554
1557
  sfxSlider;
1555
- rulesButton;
1556
- infoPanel;
1557
- infoClose;
1558
1558
  turbo;
1559
1559
  autoplay;
1560
1560
  bonusButton;
@@ -1609,9 +1609,6 @@ var OpenUI = class {
1609
1609
  );
1610
1610
  this.musicSlider = new SliderControl({ id: "music", label: "Music", layout: { anchor: "center" }, initial: 0.7 }, this.bus);
1611
1611
  this.sfxSlider = new SliderControl({ id: "sfx", label: "Sound", layout: { anchor: "center" }, initial: 0.5 }, this.bus);
1612
- this.rulesButton = new ButtonControl({ id: "rules", label: "Rules", layout: { anchor: "center" } }, this.bus);
1613
- this.infoPanel = new PanelControl({ id: "info-panel", variant: "modal", title: "Game Info", layout: { anchor: "center" } }, this.bus);
1614
- this.infoClose = new ButtonControl({ id: "info-close", layout: { anchor: "top-right" } }, this.bus);
1615
1612
  this.bonusButton = new ButtonControl({ id: "bonus", layout: { anchor: "bottom-center", offset: [-400, -440] } }, this.bus);
1616
1613
  this.autoplay = new AutoplayControl(
1617
1614
  { id: "autoplay", layout: { anchor: "bottom-center", offset: [-225, -440] }, options: [5, 10, 25, 50, 100, Infinity] },
@@ -1635,9 +1632,6 @@ var OpenUI = class {
1635
1632
  this.settingsPanel,
1636
1633
  this.musicSlider,
1637
1634
  this.sfxSlider,
1638
- this.rulesButton,
1639
- this.infoPanel,
1640
- this.infoClose,
1641
1635
  this.bonusButton,
1642
1636
  this.autoplay,
1643
1637
  this.turbo,
@@ -1658,12 +1652,7 @@ var OpenUI = class {
1658
1652
  this.hidden.add("session-timer");
1659
1653
  this.bus.on("buttonActivated", ({ id }) => {
1660
1654
  if (id === "settings") this.settingsPanel.toggle();
1661
- else if (id === "rules") {
1662
- this.settingsPanel.closePanel();
1663
- this.infoPanel.openPanel();
1664
- } else if (id === "info-close") {
1665
- this.infoPanel.closePanel();
1666
- } else if (id === "bet-plus") {
1655
+ else if (id === "bet-plus") {
1667
1656
  this.betStepper.inc();
1668
1657
  } else if (id === "bet-minus") {
1669
1658
  this.betStepper.dec();
@@ -1858,26 +1847,23 @@ var OpenUI = class {
1858
1847
  setLocale(next) {
1859
1848
  this.translator.setLocale(next);
1860
1849
  }
1861
- /** Translate a key (or pass plain text through) via the active translator. In
1862
- * social mode, a `<key>.social` variant wins when one resolves so gambling
1863
- * wording (Bet/Buy feature) swaps to sweepstakes terms automatically. */
1850
+ /** Translate a key (or pass plain text through) via the active translator. Social
1851
+ * wording is resolved by the translator from a SEPARATE social dictionary (see
1852
+ * `setSocial`), so gambling and social copy can never be mixed by accident. */
1864
1853
  t(key, vars) {
1865
- if (this.social.get()) {
1866
- const sk = `${key}.social`;
1867
- const s = this.translator.t(sk, vars);
1868
- if (s !== sk) return s;
1869
- }
1870
1854
  return this.translator.t(key, vars);
1871
1855
  }
1872
1856
  /**
1873
- * Turn social / sweepstakes mode on or off (one switch). Swaps gambling wording
1874
- * (Bet/Buy feature social terms via `<key>.social` i18n) AND, when a `coin` is
1875
- * given (e.g. `'GC'`/`'SC'`/`'XGC'`), shows balance/bet/net in that coin. Wording
1876
- * re-renders live; the host can still override any `.social` key.
1857
+ * Turn social / sweepstakes mode on or off (one switch). Flips the translator to
1858
+ * its SEPARATE social dictionary (Bet→Play, Buy feature→Play bonus, etc.) and,
1859
+ * when a `coin` is given (e.g. `'GC'`/`'SC'`), shows balance/bet/net in that coin.
1860
+ * Wording re-renders live. Social copy lives in `locale.socialMessages` kept
1861
+ * apart from your normal `locale.messages` by design.
1877
1862
  */
1878
1863
  setSocial(on, coin) {
1879
1864
  if (on !== this.social.get()) {
1880
1865
  this.social.set(on);
1866
+ this.translator.setSocial?.(on);
1881
1867
  this.locale.update(() => {
1882
1868
  });
1883
1869
  }
@@ -1892,7 +1878,7 @@ var OpenUI = class {
1892
1878
  * just a hide — `confirmBuy`/autoplay entry points consult this). */
1893
1879
  isDisabled(feature) {
1894
1880
  const j = this.jurisdiction;
1895
- return feature === "autoplay" && !!j.disabledAutoplay || feature === "buyFeature" && !!j.disabledBuyFeature || feature === "turbo" && !!j.disabledTurbo || feature === "superTurbo" && !!j.disabledSuperTurbo || feature === "fullscreen" && !!j.disabledFullscreen || feature === "slamstop" && !!j.disabledSlamstop || feature === "spacebar" && !!j.disabledSpacebar;
1881
+ return feature === "autoplay" && !!j.disabledAutoplay || feature === "buyFeature" && !!j.disabledBuyFeature || feature === "turbo" && !!j.disabledTurbo || feature === "fullscreen" && !!j.disabledFullscreen || feature === "slamstop" && !!j.disabledSlamstop || feature === "spacebar" && !!j.disabledSpacebar;
1896
1882
  }
1897
1883
  /**
1898
1884
  * Start a reality-check reminder (RTS 13). Every `everyMinutes` (WALL-CLOCK, so a
@@ -1936,7 +1922,7 @@ var OpenUI = class {
1936
1922
  this.showNotice(
1937
1923
  [
1938
1924
  { kind: "heading", id: "rc-title", text: this.t(opts.title ?? "openui.realityCheck.title", vars) },
1939
- { kind: "callout", id: "rc-body", tone: "info", text: this.t(opts.message ?? "openui.realityCheck.message", vars) }
1925
+ { kind: "text", id: "rc-body", text: this.t(opts.message ?? "openui.realityCheck.message", vars) }
1940
1926
  ],
1941
1927
  opts.actions ?? [{ label: "openui.continue", variant: "primary" }]
1942
1928
  );
@@ -2025,7 +2011,7 @@ var ANALYTICS_EVENTS = [
2025
2011
  function createUI(spec = {}, hooks = {}) {
2026
2012
  const { issues } = validateSpec(spec);
2027
2013
  for (const issue of issues) hooks.onDataIssue?.(issue);
2028
- const translator = spec.locale ? new DictionaryTranslator(spec.locale.messages, spec.locale.locale) : void 0;
2014
+ const translator = spec.locale ? new DictionaryTranslator(spec.locale.messages, spec.locale.locale, spec.locale.socialMessages) : void 0;
2029
2015
  const theme = resolveTheme(spec.theme, (i) => hooks.onDataIssue?.(i));
2030
2016
  const ui = new OpenUI({ theme, layout: spec.layout, translator, startMuted: spec.audio?.startMuted });
2031
2017
  if (spec.currency) {
@@ -2255,20 +2241,6 @@ function clampBet(amount, cfg, divisor = API_AMOUNT_DIVISOR) {
2255
2241
  return Math.min(max, Math.max(min, v));
2256
2242
  }
2257
2243
 
2258
- // src/win.ts
2259
- var DEFAULT_WIN_TIERS = Object.freeze([
2260
- { name: "big", minMultiplier: 10 },
2261
- { name: "mega", minMultiplier: 50 },
2262
- { name: "epic", minMultiplier: 100 }
2263
- ]);
2264
- function winTier(win, stake, tiers = DEFAULT_WIN_TIERS) {
2265
- if (!Number.isFinite(win) || !Number.isFinite(stake) || stake <= 0 || win <= stake) return "none";
2266
- const mult = win / stake;
2267
- let name = "win";
2268
- for (const t of tiers) if (mult >= t.minMultiplier) name = t.name;
2269
- return name;
2270
- }
2271
-
2272
- export { API_AMOUNT_DIVISOR, AutoplayControl, BLOCK_KINDS, ButtonControl, CURRENCY_TABLE, CardControl, Control, ControlRegistry, DEFAULT_MENU_TITLES, DEFAULT_NOTICE_ACTION, DEFAULT_WIN_TIERS, DictionaryTranslator, EventBus, EventLog, Fade, LOCALE_LABELS, OpenUI, PanelControl, Parallel, Pulse, RGS_ERROR_KEYS, ReadoutControl, SelectControl, Sequence, Signal, SliderControl, SpinControl, Squish, StepperControl, ToggleControl, TurboControl, Turn, ValueDisplay, applyJurisdiction, breakpointFor, buildBetLadder, buildBlocks, buildPanel, buttonBlocks, clampBet, clampDecimals, clampDigits, clampMinDigits, composeMenu, computeScreen, createUI, defaultHudSpec, defaultLayoutConfig, defaultTheme, defineUI, dictionary, displayDigits, effect, errorBlocks, extendTheme, formatAmount, installResponsive, integerDigits, isSafeColor, isSocialCurrency, openuiDefaults, resolveCurrency, resolvePlacement, resolveTheme, resolveTurboModes, safeAmount, sanitizeThemeOverrides, themePresets, validateSpec, valueFitMaxWidth, winTier };
2244
+ export { API_AMOUNT_DIVISOR, AutoplayControl, BLOCK_KINDS, ButtonControl, CURRENCY_TABLE, CardControl, Control, ControlRegistry, DEFAULT_MENU_TITLES, DEFAULT_NOTICE_ACTION, DictionaryTranslator, EventBus, EventLog, Fade, LOCALE_LABELS, OpenUI, PanelControl, Parallel, Pulse, RGS_ERROR_KEYS, ReadoutControl, SelectControl, Sequence, Signal, SliderControl, SpinControl, Squish, StepperControl, ToggleControl, TurboControl, Turn, ValueDisplay, applyJurisdiction, breakpointFor, buildBetLadder, buildBlocks, buildPanel, buttonBlocks, clampBet, clampDecimals, clampDigits, clampMinDigits, composeMenu, computeScreen, createUI, defaultHudSpec, defaultLayoutConfig, defaultTheme, defineUI, dictionary, displayDigits, effect, errorBlocks, extendTheme, formatAmount, installResponsive, integerDigits, isSafeColor, isSocialCurrency, openuiDefaults, openuiSocialDefaults, resolveCurrency, resolvePlacement, resolveTheme, resolveTurboModes, safeAmount, sanitizeThemeOverrides, themePresets, validateSpec, valueFitMaxWidth };
2273
2245
  //# sourceMappingURL=index.js.map
2274
2246
  //# sourceMappingURL=index.js.map