@open-slot-ui/core 0.9.0 → 0.11.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 +251 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -1
- package/dist/index.d.ts +40 -1
- package/dist/index.js +246 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1652,6 +1652,10 @@ interface ResponsiveOverride {
|
|
|
1652
1652
|
type BlockSpec = {
|
|
1653
1653
|
/** Rules-audit topics this block covers (see `auditRules`). */
|
|
1654
1654
|
covers?: string[];
|
|
1655
|
+
/** The declared mode id this block EXPLAINS (e.g. `'bonus'`). Every declared mode
|
|
1656
|
+
* must have its own rules section — a heading naming it, or blocks tagged with
|
|
1657
|
+
* `explains` — with real prose; the audit enforces it (see `auditRules`). */
|
|
1658
|
+
explains?: string;
|
|
1655
1659
|
} & ({
|
|
1656
1660
|
kind: 'slider';
|
|
1657
1661
|
id: string;
|
|
@@ -2087,6 +2091,41 @@ declare function auditRulesDoc(doc: RulesDoc, opts?: {
|
|
|
2087
2091
|
facts?: GameFacts;
|
|
2088
2092
|
}): RulesAuditIssue[];
|
|
2089
2093
|
|
|
2094
|
+
/**
|
|
2095
|
+
* The ONE in-game rules/menu HTML renderer — the white-card-with-gold-accents
|
|
2096
|
+
* design the info menu shows in every game — as PURE string builders (zero deps,
|
|
2097
|
+
* no DOM required), so the SAME renderer that draws the menu in-game also powers
|
|
2098
|
+
* external tooling (the stakeplate rules editor's WYSIWYG preview, docs, CI
|
|
2099
|
+
* snapshots). `@open-slot-ui/pixi`'s `mountInfoMenu` consumes these — there is
|
|
2100
|
+
* exactly one source of truth for how a rules block looks.
|
|
2101
|
+
*/
|
|
2102
|
+
|
|
2103
|
+
/** Escape text for safe HTML interpolation. */
|
|
2104
|
+
declare const escapeHtml: (s: string) => string;
|
|
2105
|
+
/** Escape, then turn `**bold**` runs into `<b>` — the shared inline syntax. */
|
|
2106
|
+
declare const richHtml: (s: string) => string;
|
|
2107
|
+
/**
|
|
2108
|
+
* Render a declarative rules `BlockSpec[]` to the in-game HTML — the full modular
|
|
2109
|
+
* palette. `tr` is the translate function (pass a translate-and-interpolate so
|
|
2110
|
+
* `{{rtp.base}}`-style tokens resolve — see `factsVars`); `facts` feeds the auto
|
|
2111
|
+
* `mode-stats` block.
|
|
2112
|
+
*/
|
|
2113
|
+
declare function renderBlocksHtml(blocks: BlockSpec[], tr: (s: string) => string, facts?: GameFacts): string;
|
|
2114
|
+
/**
|
|
2115
|
+
* The "⚠ Rules incomplete" warning card the info menu shows at the top of Rules
|
|
2116
|
+
* when the audit finds forgotten declarations. `tr` localizes the chrome strings
|
|
2117
|
+
* (`openui.rulesAudit.*`) + the finding messages. Empty issues → ''.
|
|
2118
|
+
*/
|
|
2119
|
+
declare function renderRulesAuditHtml(issues: RulesAuditIssue[], tr: (s: string) => string): string;
|
|
2120
|
+
/**
|
|
2121
|
+
* The in-game info-menu stylesheet (the white card + gold accents design). One
|
|
2122
|
+
* copy, used by `mountInfoMenu` AND any external preview. Expects the CSS custom
|
|
2123
|
+
* properties `--accent --accent-text --surface --surface-alt --text --text-dim
|
|
2124
|
+
* --card-radius --font` on the `.ohm-root` (see {@link INFO_MENU_VARS}).
|
|
2125
|
+
*/
|
|
2126
|
+
declare const INFO_MENU_VARS: Readonly<Record<string, string>>;
|
|
2127
|
+
declare const INFO_MENU_CSS = "\n.ohm-root { position: fixed; inset: 0; z-index: 10000; display: grid; place-items: center; font-family: var(--font); opacity: 0; pointer-events: none; transition: opacity .18s ease; }\n.ohm-root.open { opacity: 1; pointer-events: auto; }\n.ohm-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; }\n.ohm-root.open .ohm-backdrop { background: rgba(8,6,4,.34); backdrop-filter: blur(6px) saturate(1.1); -webkit-backdrop-filter: blur(6px) saturate(1.1); }\n.ohm-card { position: relative; width: min(92%, 1100px); max-height: 86vh; display: flex; flex-direction: column; background: var(--surface); color: var(--text); border: 1.5px solid #000; border-radius: var(--card-radius); box-shadow: 0 30px 80px rgba(0,0,0,.5); overflow: hidden; transform: translateY(8px) scale(.99); transition: transform .18s ease; }\n.ohm-root.open .ohm-card { transform: none; }\n.ohm-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; }\n.ohm-x:hover { transform: scale(1.08); background: rgba(18,14,10,.95); }\n.ohm-body { padding: 24px 26px 26px; overflow-y: scroll; }\n.ohm-body::-webkit-scrollbar { width: 18px; }\n.ohm-body::-webkit-scrollbar-track { background: transparent; margin: 12px 0; }\n.ohm-body::-webkit-scrollbar-thumb { background-color: #111; border: 6px solid transparent; background-clip: padding-box; border-radius: 999px; min-height: 44px; }\n.ohm-body::-webkit-scrollbar-thumb:hover { background-color: #000; }\n.ohm-logo { display: block; margin: 6px auto 18px; max-width: 64%; height: auto; }\n.ohm-logo-text { margin: 6px 0 18px; text-align: center; font-size: 30px; font-weight: 900; letter-spacing: 1px; color: var(--text); }\n.ohm-sec { display: flex; align-items: center; gap: 14px; margin: 26px 0 14px; color: var(--text); font-weight: 800; letter-spacing: 1px; }\n.ohm-sec::before, .ohm-sec::after { content: \"\"; flex: 1; height: 2px; background: color-mix(in srgb, var(--text) 80%, transparent); border-radius: 2px; }\n.ohm-root *, .ohm-root *::before, .ohm-root *::after { box-sizing: border-box; }\n.ohm-row { display: flex; align-items: center; gap: 16px; margin: 14px 0; font-weight: 700; }\n.ohm-setting { margin: 14px 0; }\n.ohm-setting .ohm-row { margin: 0; }\n.ohm-hint { margin: 3px 0 0; font-size: 12.5px; font-weight: 500; color: var(--text-dim); }\n.ohm-row > span:first-child { flex: none; min-width: 110px; }\n.ohm-row input[type=range] { flex: 1; min-width: 0; max-width: min(440px, 60dvw); accent-color: var(--accent); height: 6px; }\n.ohm-row select { flex: 1; min-width: 0; max-width: min(440px, 60dvw); padding: 11px 14px; border-radius: 4px; border: 2px solid var(--accent); background: var(--surface-alt); color: var(--text); font-weight: 700; font-size: 15px; cursor: pointer; }\n.ohm-row select option { background: var(--surface); color: var(--text); font-weight: 600; }\n.ohm-row select option:checked { background: var(--accent); color: var(--accent-text); }\n.ohm-ctl { flex: 1; min-width: 0; max-width: min(440px, 60dvw); display: flex; align-items: center; justify-content: flex-end; }\n.ohm-check input[type=checkbox] { appearance: none; -webkit-appearance: none; width: 50px; height: 28px; border-radius: 999px; background: color-mix(in srgb, var(--text-dim) 38%, transparent); position: relative; cursor: pointer; transition: background .15s; flex: none; }\n.ohm-check input[type=checkbox]:checked { background: var(--accent); }\n.ohm-check input[type=checkbox]::before { content: \"\"; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 999px; background: #fff; transition: left .15s; box-shadow: 0 1px 3px rgba(0,0,0,.3); }\n.ohm-check input[type=checkbox]:checked::before { left: 25px; }\n.ohm-segmented { display: inline-flex; gap: 4px; padding: 4px; background: var(--surface-alt); border-radius: 999px; border: 1px solid color-mix(in srgb, var(--text-dim) 30%, transparent); }\n.ohm-seg { border: 0; background: transparent; color: var(--text-dim); font-weight: 700; font-size: 14px; padding: 8px 18px; border-radius: 999px; cursor: pointer; transition: background .12s, color .12s; }\n.ohm-seg.active { background: var(--accent); color: var(--accent-text); }\n.ohm-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }\n.ohm-sym { display: flex; align-items: center; gap: 16px; padding: 6px 4px; }\n.ohm-emoji { font-size: 48px; line-height: 1; filter: drop-shadow(0 2px 4px rgba(0,0,0,.3)); }\n.ohm-symimg { width: 56px; height: 56px; object-fit: contain; flex: none; }\n.ohm-pay { font-size: 13px; line-height: 1.6; }\n.ohm-pay div { display: flex; gap: 6px; }\n.ohm-pay b { min-width: 42px; }\n.ohm-pay span { color: var(--accent); font-weight: 700; }\n.ohm-body p { color: var(--text-dim); line-height: 1.6; }\n.ohm-body p b { color: var(--text); }\n.ohm-feature { display: block; width: 100%; height: auto; margin: 10px 0; }\n.ohm-stats { margin: 12px 0; display: grid; grid-template-columns: 1fr 1fr; gap: 0 28px; }\n.ohm-stats > div { display: flex; justify-content: space-between; padding: 9px 0; border-bottom: 1px solid color-mix(in srgb, var(--text-dim) 20%, transparent); }\n.ohm-stats dt { color: var(--text-dim); margin: 0; } .ohm-stats dd { margin: 0; font-weight: 700; }\n.ohm-audit { margin: 12px 0 18px; padding: 14px 16px; border-radius: 12px; border: 2px solid #d03131; background: color-mix(in srgb, #d03131 8%, transparent); }\n.ohm-audit-title { font-weight: 900; letter-spacing: .5px; color: #b31d1d; }\n.ohm-audit-sub { margin-top: 8px; font-size: 13px; font-weight: 800; color: #b31d1d; }\n.ohm-audit-sub--rec { color: #b07d09; }\n.ohm-audit ul { margin: 6px 0 0; padding-left: 20px; color: var(--text); font-size: 13.5px; line-height: 1.55; }\n.ohm-audit li { margin: 3px 0; }\n.ohm-audit-rec ul { color: var(--text-dim); }\n.ohm-callout { margin: 16px 0 4px; padding: 14px 16px; border-radius: 12px; border-left: 4px solid var(--accent); background: color-mix(in srgb, var(--accent) 9%, transparent); }\n.ohm-callout b { color: var(--accent); } .ohm-callout p { margin: 4px 0 0; color: var(--text); }\n.ohm-callout--warning { border-left-color: #e0a106; background: color-mix(in srgb, #e0a106 10%, transparent); }\n.ohm-callout--warning b { color: #b07d09; }\n.ohm-subh { margin: 22px 0 8px; font-size: 15px; font-weight: 800; letter-spacing: .5px; color: var(--text); }\n.ohm-legal { font-size: 12px; line-height: 1.6; color: var(--text-dim); opacity: .85; }\n.ohm-hr { border: 0; border-top: 1px solid color-mix(in srgb, var(--text-dim) 30%, transparent); margin: 18px 0; }\n.ohm-media { display: flex; align-items: center; gap: 18px; margin: 14px 0; }\n.ohm-media--right { flex-direction: row-reverse; }\n.ohm-media > img { width: 40%; max-width: 320px; height: auto; flex: none; }\n.ohm-media-body { flex: 1; }\n.ohm-media-body h4 { margin: 0 0 6px; font-size: 16px; color: var(--text); }\n.ohm-media-body p { margin: 0; }\n.ohm-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin: 12px 0; }\n.ohm-fcard { padding: 8px 6px; text-align: center; }\n.ohm-fcard img { display: block; width: 48px; height: 48px; margin: 0 auto 8px; }\n.ohm-fcard h5 { margin: 0 0 4px; font-size: 14px; color: var(--text); }\n.ohm-fcard p { margin: 0; font-size: 12px; line-height: 1.5; }\n.ohm-table { width: 100%; border-collapse: collapse; margin: 12px 0; font-size: 14px; }\n.ohm-table th { text-align: left; padding: 8px 10px; font-weight: 800; color: var(--text); border-bottom: 2px solid color-mix(in srgb, var(--text-dim) 35%, transparent); }\n.ohm-table td { padding: 8px 10px; border-bottom: 1px solid color-mix(in srgb, var(--text-dim) 18%, transparent); }\n.ohm-table td:first-child { color: var(--text); font-weight: 700; }\n.ohm-table td:not(:first-child) { color: var(--accent); font-weight: 700; }\n.ohm-steps { margin: 12px 0; padding-left: 22px; color: var(--text-dim); line-height: 1.7; }\n.ohm-steps li { margin: 5px 0; }\n.ohm-steps b { color: var(--text); }\n.ohm-group { margin: 8px 0; }\n";
|
|
2128
|
+
|
|
2090
2129
|
/**
|
|
2091
2130
|
* The reference HUD expressed as data — the knobs `new OpenUI()` ships with.
|
|
2092
2131
|
* `createUI(defaultHudSpec)` is byte-equivalent to zero-arg `createUI()` (a test
|
|
@@ -2243,4 +2282,4 @@ declare function resolveBetLadder(availableBets: number[] | undefined, defaultBe
|
|
|
2243
2282
|
/** Clamp a stake (major units) to the RGS min/max and snap to `stepBet`. Pure. */
|
|
2244
2283
|
declare function clampBet(amount: number, cfg: RgsBetConfig, divisor?: number): number;
|
|
2245
2284
|
|
|
2246
|
-
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 ForbiddenMatch, type FreeSpinsFact, type GameFacts, type GameModeFact, 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 RulesAuditIssue, type RulesDoc, type ScreenState, SelectControl, type SelectControlOptions, type SelectOption, Sequence, Signal, SliderControl, type SliderOptions, type SocialPhraseIssue, type SoundControls, type SpecIssue, SpinControl, type SpinPress, type SpinSpec, Squish, type StageRect, 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, applyRulesDoc, auditRules, auditRulesDoc, breakpointFor, buildBetLadder, buildBlocks, buildPanel, buttonBlocks, checkSocialPhrases, clampBet, clampDecimals, clampDigits, clampMinDigits, collectSocialCopy, composeMenu, computeScreen, createUI, defaultHudSpec, defaultLayout, defaultLayoutConfig, defaultTheme, defineUI, dictionary, displayDigits, effect, errorBlocks, extendTheme, factsVars, findForbiddenPhrases, formatAmount, formatAmountPrecise, formatRtp, formatTimes, installResponsive, integerDigits, isRulesDoc, isSafeColor, isSocialCurrency, landscapeDefaultLayouts, mergeFacts, modeStatsItems, neededDecimals, openuiDefaults, openuiSocialDefaults, portraitDefaultLayouts, resolveBetLadder, resolveCurrency, resolvePlacement, resolveTheme, resolveTurboModes, safeAmount, sanitizeThemeOverrides, themePresets, validateSpec, valueFitMaxWidth };
|
|
2285
|
+
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 ForbiddenMatch, type FreeSpinsFact, type GameFacts, type GameModeFact, type HostHooks, INFO_MENU_CSS, INFO_MENU_VARS, 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 RulesAuditIssue, type RulesDoc, type ScreenState, SelectControl, type SelectControlOptions, type SelectOption, Sequence, Signal, SliderControl, type SliderOptions, type SocialPhraseIssue, type SoundControls, type SpecIssue, SpinControl, type SpinPress, type SpinSpec, Squish, type StageRect, 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, applyRulesDoc, auditRules, auditRulesDoc, breakpointFor, buildBetLadder, buildBlocks, buildPanel, buttonBlocks, checkSocialPhrases, clampBet, clampDecimals, clampDigits, clampMinDigits, collectSocialCopy, composeMenu, computeScreen, createUI, defaultHudSpec, defaultLayout, defaultLayoutConfig, defaultTheme, defineUI, dictionary, displayDigits, effect, errorBlocks, escapeHtml, extendTheme, factsVars, findForbiddenPhrases, formatAmount, formatAmountPrecise, formatRtp, formatTimes, installResponsive, integerDigits, isRulesDoc, isSafeColor, isSocialCurrency, landscapeDefaultLayouts, mergeFacts, modeStatsItems, neededDecimals, openuiDefaults, openuiSocialDefaults, portraitDefaultLayouts, renderBlocksHtml, renderRulesAuditHtml, resolveBetLadder, resolveCurrency, resolvePlacement, resolveTheme, resolveTurboModes, richHtml, safeAmount, sanitizeThemeOverrides, themePresets, validateSpec, valueFitMaxWidth };
|
package/dist/index.d.ts
CHANGED
|
@@ -1652,6 +1652,10 @@ interface ResponsiveOverride {
|
|
|
1652
1652
|
type BlockSpec = {
|
|
1653
1653
|
/** Rules-audit topics this block covers (see `auditRules`). */
|
|
1654
1654
|
covers?: string[];
|
|
1655
|
+
/** The declared mode id this block EXPLAINS (e.g. `'bonus'`). Every declared mode
|
|
1656
|
+
* must have its own rules section — a heading naming it, or blocks tagged with
|
|
1657
|
+
* `explains` — with real prose; the audit enforces it (see `auditRules`). */
|
|
1658
|
+
explains?: string;
|
|
1655
1659
|
} & ({
|
|
1656
1660
|
kind: 'slider';
|
|
1657
1661
|
id: string;
|
|
@@ -2087,6 +2091,41 @@ declare function auditRulesDoc(doc: RulesDoc, opts?: {
|
|
|
2087
2091
|
facts?: GameFacts;
|
|
2088
2092
|
}): RulesAuditIssue[];
|
|
2089
2093
|
|
|
2094
|
+
/**
|
|
2095
|
+
* The ONE in-game rules/menu HTML renderer — the white-card-with-gold-accents
|
|
2096
|
+
* design the info menu shows in every game — as PURE string builders (zero deps,
|
|
2097
|
+
* no DOM required), so the SAME renderer that draws the menu in-game also powers
|
|
2098
|
+
* external tooling (the stakeplate rules editor's WYSIWYG preview, docs, CI
|
|
2099
|
+
* snapshots). `@open-slot-ui/pixi`'s `mountInfoMenu` consumes these — there is
|
|
2100
|
+
* exactly one source of truth for how a rules block looks.
|
|
2101
|
+
*/
|
|
2102
|
+
|
|
2103
|
+
/** Escape text for safe HTML interpolation. */
|
|
2104
|
+
declare const escapeHtml: (s: string) => string;
|
|
2105
|
+
/** Escape, then turn `**bold**` runs into `<b>` — the shared inline syntax. */
|
|
2106
|
+
declare const richHtml: (s: string) => string;
|
|
2107
|
+
/**
|
|
2108
|
+
* Render a declarative rules `BlockSpec[]` to the in-game HTML — the full modular
|
|
2109
|
+
* palette. `tr` is the translate function (pass a translate-and-interpolate so
|
|
2110
|
+
* `{{rtp.base}}`-style tokens resolve — see `factsVars`); `facts` feeds the auto
|
|
2111
|
+
* `mode-stats` block.
|
|
2112
|
+
*/
|
|
2113
|
+
declare function renderBlocksHtml(blocks: BlockSpec[], tr: (s: string) => string, facts?: GameFacts): string;
|
|
2114
|
+
/**
|
|
2115
|
+
* The "⚠ Rules incomplete" warning card the info menu shows at the top of Rules
|
|
2116
|
+
* when the audit finds forgotten declarations. `tr` localizes the chrome strings
|
|
2117
|
+
* (`openui.rulesAudit.*`) + the finding messages. Empty issues → ''.
|
|
2118
|
+
*/
|
|
2119
|
+
declare function renderRulesAuditHtml(issues: RulesAuditIssue[], tr: (s: string) => string): string;
|
|
2120
|
+
/**
|
|
2121
|
+
* The in-game info-menu stylesheet (the white card + gold accents design). One
|
|
2122
|
+
* copy, used by `mountInfoMenu` AND any external preview. Expects the CSS custom
|
|
2123
|
+
* properties `--accent --accent-text --surface --surface-alt --text --text-dim
|
|
2124
|
+
* --card-radius --font` on the `.ohm-root` (see {@link INFO_MENU_VARS}).
|
|
2125
|
+
*/
|
|
2126
|
+
declare const INFO_MENU_VARS: Readonly<Record<string, string>>;
|
|
2127
|
+
declare const INFO_MENU_CSS = "\n.ohm-root { position: fixed; inset: 0; z-index: 10000; display: grid; place-items: center; font-family: var(--font); opacity: 0; pointer-events: none; transition: opacity .18s ease; }\n.ohm-root.open { opacity: 1; pointer-events: auto; }\n.ohm-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; }\n.ohm-root.open .ohm-backdrop { background: rgba(8,6,4,.34); backdrop-filter: blur(6px) saturate(1.1); -webkit-backdrop-filter: blur(6px) saturate(1.1); }\n.ohm-card { position: relative; width: min(92%, 1100px); max-height: 86vh; display: flex; flex-direction: column; background: var(--surface); color: var(--text); border: 1.5px solid #000; border-radius: var(--card-radius); box-shadow: 0 30px 80px rgba(0,0,0,.5); overflow: hidden; transform: translateY(8px) scale(.99); transition: transform .18s ease; }\n.ohm-root.open .ohm-card { transform: none; }\n.ohm-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; }\n.ohm-x:hover { transform: scale(1.08); background: rgba(18,14,10,.95); }\n.ohm-body { padding: 24px 26px 26px; overflow-y: scroll; }\n.ohm-body::-webkit-scrollbar { width: 18px; }\n.ohm-body::-webkit-scrollbar-track { background: transparent; margin: 12px 0; }\n.ohm-body::-webkit-scrollbar-thumb { background-color: #111; border: 6px solid transparent; background-clip: padding-box; border-radius: 999px; min-height: 44px; }\n.ohm-body::-webkit-scrollbar-thumb:hover { background-color: #000; }\n.ohm-logo { display: block; margin: 6px auto 18px; max-width: 64%; height: auto; }\n.ohm-logo-text { margin: 6px 0 18px; text-align: center; font-size: 30px; font-weight: 900; letter-spacing: 1px; color: var(--text); }\n.ohm-sec { display: flex; align-items: center; gap: 14px; margin: 26px 0 14px; color: var(--text); font-weight: 800; letter-spacing: 1px; }\n.ohm-sec::before, .ohm-sec::after { content: \"\"; flex: 1; height: 2px; background: color-mix(in srgb, var(--text) 80%, transparent); border-radius: 2px; }\n.ohm-root *, .ohm-root *::before, .ohm-root *::after { box-sizing: border-box; }\n.ohm-row { display: flex; align-items: center; gap: 16px; margin: 14px 0; font-weight: 700; }\n.ohm-setting { margin: 14px 0; }\n.ohm-setting .ohm-row { margin: 0; }\n.ohm-hint { margin: 3px 0 0; font-size: 12.5px; font-weight: 500; color: var(--text-dim); }\n.ohm-row > span:first-child { flex: none; min-width: 110px; }\n.ohm-row input[type=range] { flex: 1; min-width: 0; max-width: min(440px, 60dvw); accent-color: var(--accent); height: 6px; }\n.ohm-row select { flex: 1; min-width: 0; max-width: min(440px, 60dvw); padding: 11px 14px; border-radius: 4px; border: 2px solid var(--accent); background: var(--surface-alt); color: var(--text); font-weight: 700; font-size: 15px; cursor: pointer; }\n.ohm-row select option { background: var(--surface); color: var(--text); font-weight: 600; }\n.ohm-row select option:checked { background: var(--accent); color: var(--accent-text); }\n.ohm-ctl { flex: 1; min-width: 0; max-width: min(440px, 60dvw); display: flex; align-items: center; justify-content: flex-end; }\n.ohm-check input[type=checkbox] { appearance: none; -webkit-appearance: none; width: 50px; height: 28px; border-radius: 999px; background: color-mix(in srgb, var(--text-dim) 38%, transparent); position: relative; cursor: pointer; transition: background .15s; flex: none; }\n.ohm-check input[type=checkbox]:checked { background: var(--accent); }\n.ohm-check input[type=checkbox]::before { content: \"\"; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 999px; background: #fff; transition: left .15s; box-shadow: 0 1px 3px rgba(0,0,0,.3); }\n.ohm-check input[type=checkbox]:checked::before { left: 25px; }\n.ohm-segmented { display: inline-flex; gap: 4px; padding: 4px; background: var(--surface-alt); border-radius: 999px; border: 1px solid color-mix(in srgb, var(--text-dim) 30%, transparent); }\n.ohm-seg { border: 0; background: transparent; color: var(--text-dim); font-weight: 700; font-size: 14px; padding: 8px 18px; border-radius: 999px; cursor: pointer; transition: background .12s, color .12s; }\n.ohm-seg.active { background: var(--accent); color: var(--accent-text); }\n.ohm-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }\n.ohm-sym { display: flex; align-items: center; gap: 16px; padding: 6px 4px; }\n.ohm-emoji { font-size: 48px; line-height: 1; filter: drop-shadow(0 2px 4px rgba(0,0,0,.3)); }\n.ohm-symimg { width: 56px; height: 56px; object-fit: contain; flex: none; }\n.ohm-pay { font-size: 13px; line-height: 1.6; }\n.ohm-pay div { display: flex; gap: 6px; }\n.ohm-pay b { min-width: 42px; }\n.ohm-pay span { color: var(--accent); font-weight: 700; }\n.ohm-body p { color: var(--text-dim); line-height: 1.6; }\n.ohm-body p b { color: var(--text); }\n.ohm-feature { display: block; width: 100%; height: auto; margin: 10px 0; }\n.ohm-stats { margin: 12px 0; display: grid; grid-template-columns: 1fr 1fr; gap: 0 28px; }\n.ohm-stats > div { display: flex; justify-content: space-between; padding: 9px 0; border-bottom: 1px solid color-mix(in srgb, var(--text-dim) 20%, transparent); }\n.ohm-stats dt { color: var(--text-dim); margin: 0; } .ohm-stats dd { margin: 0; font-weight: 700; }\n.ohm-audit { margin: 12px 0 18px; padding: 14px 16px; border-radius: 12px; border: 2px solid #d03131; background: color-mix(in srgb, #d03131 8%, transparent); }\n.ohm-audit-title { font-weight: 900; letter-spacing: .5px; color: #b31d1d; }\n.ohm-audit-sub { margin-top: 8px; font-size: 13px; font-weight: 800; color: #b31d1d; }\n.ohm-audit-sub--rec { color: #b07d09; }\n.ohm-audit ul { margin: 6px 0 0; padding-left: 20px; color: var(--text); font-size: 13.5px; line-height: 1.55; }\n.ohm-audit li { margin: 3px 0; }\n.ohm-audit-rec ul { color: var(--text-dim); }\n.ohm-callout { margin: 16px 0 4px; padding: 14px 16px; border-radius: 12px; border-left: 4px solid var(--accent); background: color-mix(in srgb, var(--accent) 9%, transparent); }\n.ohm-callout b { color: var(--accent); } .ohm-callout p { margin: 4px 0 0; color: var(--text); }\n.ohm-callout--warning { border-left-color: #e0a106; background: color-mix(in srgb, #e0a106 10%, transparent); }\n.ohm-callout--warning b { color: #b07d09; }\n.ohm-subh { margin: 22px 0 8px; font-size: 15px; font-weight: 800; letter-spacing: .5px; color: var(--text); }\n.ohm-legal { font-size: 12px; line-height: 1.6; color: var(--text-dim); opacity: .85; }\n.ohm-hr { border: 0; border-top: 1px solid color-mix(in srgb, var(--text-dim) 30%, transparent); margin: 18px 0; }\n.ohm-media { display: flex; align-items: center; gap: 18px; margin: 14px 0; }\n.ohm-media--right { flex-direction: row-reverse; }\n.ohm-media > img { width: 40%; max-width: 320px; height: auto; flex: none; }\n.ohm-media-body { flex: 1; }\n.ohm-media-body h4 { margin: 0 0 6px; font-size: 16px; color: var(--text); }\n.ohm-media-body p { margin: 0; }\n.ohm-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin: 12px 0; }\n.ohm-fcard { padding: 8px 6px; text-align: center; }\n.ohm-fcard img { display: block; width: 48px; height: 48px; margin: 0 auto 8px; }\n.ohm-fcard h5 { margin: 0 0 4px; font-size: 14px; color: var(--text); }\n.ohm-fcard p { margin: 0; font-size: 12px; line-height: 1.5; }\n.ohm-table { width: 100%; border-collapse: collapse; margin: 12px 0; font-size: 14px; }\n.ohm-table th { text-align: left; padding: 8px 10px; font-weight: 800; color: var(--text); border-bottom: 2px solid color-mix(in srgb, var(--text-dim) 35%, transparent); }\n.ohm-table td { padding: 8px 10px; border-bottom: 1px solid color-mix(in srgb, var(--text-dim) 18%, transparent); }\n.ohm-table td:first-child { color: var(--text); font-weight: 700; }\n.ohm-table td:not(:first-child) { color: var(--accent); font-weight: 700; }\n.ohm-steps { margin: 12px 0; padding-left: 22px; color: var(--text-dim); line-height: 1.7; }\n.ohm-steps li { margin: 5px 0; }\n.ohm-steps b { color: var(--text); }\n.ohm-group { margin: 8px 0; }\n";
|
|
2128
|
+
|
|
2090
2129
|
/**
|
|
2091
2130
|
* The reference HUD expressed as data — the knobs `new OpenUI()` ships with.
|
|
2092
2131
|
* `createUI(defaultHudSpec)` is byte-equivalent to zero-arg `createUI()` (a test
|
|
@@ -2243,4 +2282,4 @@ declare function resolveBetLadder(availableBets: number[] | undefined, defaultBe
|
|
|
2243
2282
|
/** Clamp a stake (major units) to the RGS min/max and snap to `stepBet`. Pure. */
|
|
2244
2283
|
declare function clampBet(amount: number, cfg: RgsBetConfig, divisor?: number): number;
|
|
2245
2284
|
|
|
2246
|
-
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 ForbiddenMatch, type FreeSpinsFact, type GameFacts, type GameModeFact, 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 RulesAuditIssue, type RulesDoc, type ScreenState, SelectControl, type SelectControlOptions, type SelectOption, Sequence, Signal, SliderControl, type SliderOptions, type SocialPhraseIssue, type SoundControls, type SpecIssue, SpinControl, type SpinPress, type SpinSpec, Squish, type StageRect, 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, applyRulesDoc, auditRules, auditRulesDoc, breakpointFor, buildBetLadder, buildBlocks, buildPanel, buttonBlocks, checkSocialPhrases, clampBet, clampDecimals, clampDigits, clampMinDigits, collectSocialCopy, composeMenu, computeScreen, createUI, defaultHudSpec, defaultLayout, defaultLayoutConfig, defaultTheme, defineUI, dictionary, displayDigits, effect, errorBlocks, extendTheme, factsVars, findForbiddenPhrases, formatAmount, formatAmountPrecise, formatRtp, formatTimes, installResponsive, integerDigits, isRulesDoc, isSafeColor, isSocialCurrency, landscapeDefaultLayouts, mergeFacts, modeStatsItems, neededDecimals, openuiDefaults, openuiSocialDefaults, portraitDefaultLayouts, resolveBetLadder, resolveCurrency, resolvePlacement, resolveTheme, resolveTurboModes, safeAmount, sanitizeThemeOverrides, themePresets, validateSpec, valueFitMaxWidth };
|
|
2285
|
+
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 ForbiddenMatch, type FreeSpinsFact, type GameFacts, type GameModeFact, type HostHooks, INFO_MENU_CSS, INFO_MENU_VARS, 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 RulesAuditIssue, type RulesDoc, type ScreenState, SelectControl, type SelectControlOptions, type SelectOption, Sequence, Signal, SliderControl, type SliderOptions, type SocialPhraseIssue, type SoundControls, type SpecIssue, SpinControl, type SpinPress, type SpinSpec, Squish, type StageRect, 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, applyRulesDoc, auditRules, auditRulesDoc, breakpointFor, buildBetLadder, buildBlocks, buildPanel, buttonBlocks, checkSocialPhrases, clampBet, clampDecimals, clampDigits, clampMinDigits, collectSocialCopy, composeMenu, computeScreen, createUI, defaultHudSpec, defaultLayout, defaultLayoutConfig, defaultTheme, defineUI, dictionary, displayDigits, effect, errorBlocks, escapeHtml, extendTheme, factsVars, findForbiddenPhrases, formatAmount, formatAmountPrecise, formatRtp, formatTimes, installResponsive, integerDigits, isRulesDoc, isSafeColor, isSocialCurrency, landscapeDefaultLayouts, mergeFacts, modeStatsItems, neededDecimals, openuiDefaults, openuiSocialDefaults, portraitDefaultLayouts, renderBlocksHtml, renderRulesAuditHtml, resolveBetLadder, resolveCurrency, resolvePlacement, resolveTheme, resolveTurboModes, richHtml, safeAmount, sanitizeThemeOverrides, themePresets, validateSpec, valueFitMaxWidth };
|
package/dist/index.js
CHANGED
|
@@ -1410,6 +1410,9 @@ function validateSpec(spec) {
|
|
|
1410
1410
|
return;
|
|
1411
1411
|
}
|
|
1412
1412
|
seeId(b.id, `${p}.id`);
|
|
1413
|
+
if (b.explains && b.explains !== "freeSpins" && spec.facts?.modes?.length && !spec.facts.modes.some((m) => m.id === b.explains)) {
|
|
1414
|
+
add("warn", `${p}.explains`, "explains-unknown-mode", `explains "${b.explains}" matches no declared mode id (facts.modes)`);
|
|
1415
|
+
}
|
|
1413
1416
|
if (b.kind === "select" && (!b.options || b.options.length === 0)) {
|
|
1414
1417
|
add("error", `${p}.options`, "select-empty", "a select block needs at least one option");
|
|
1415
1418
|
}
|
|
@@ -1762,14 +1765,29 @@ function factsVars(facts, extra) {
|
|
|
1762
1765
|
return extra ? { ...vars, ...extra } : vars;
|
|
1763
1766
|
}
|
|
1764
1767
|
function scanBlocks(blocks, resolve = (s) => s) {
|
|
1765
|
-
const scan = { text: "", headings: "", covers: /* @__PURE__ */ new Set(), hasModeStats: false, hasLegal: false };
|
|
1768
|
+
const scan = { text: "", headings: "", covers: /* @__PURE__ */ new Set(), hasModeStats: false, hasLegal: false, sections: [] };
|
|
1769
|
+
let section = { heading: "", text: "", explains: /* @__PURE__ */ new Set(), covers: /* @__PURE__ */ new Set() };
|
|
1770
|
+
scan.sections.push(section);
|
|
1766
1771
|
const addText = (t) => {
|
|
1767
|
-
if (typeof t === "string" && t)
|
|
1768
|
-
|
|
1772
|
+
if (typeof t === "string" && t) {
|
|
1773
|
+
const r = resolve(t);
|
|
1774
|
+
scan.text += `
|
|
1775
|
+
${r}`;
|
|
1776
|
+
section.text += `
|
|
1777
|
+
${r}`;
|
|
1778
|
+
}
|
|
1769
1779
|
};
|
|
1770
1780
|
const walk = (list) => {
|
|
1771
1781
|
for (const b of list ?? []) {
|
|
1772
|
-
|
|
1782
|
+
if (b.kind === "heading" || b.kind === "subheading") {
|
|
1783
|
+
section = { heading: resolve(b.text), text: "", explains: /* @__PURE__ */ new Set(), covers: /* @__PURE__ */ new Set() };
|
|
1784
|
+
scan.sections.push(section);
|
|
1785
|
+
}
|
|
1786
|
+
for (const c of b.covers ?? []) {
|
|
1787
|
+
scan.covers.add(c);
|
|
1788
|
+
section.covers.add(c);
|
|
1789
|
+
}
|
|
1790
|
+
if (b.explains) section.explains.add(b.explains);
|
|
1773
1791
|
const anyB = b;
|
|
1774
1792
|
switch (b.kind) {
|
|
1775
1793
|
case "mode-stats":
|
|
@@ -1784,11 +1802,14 @@ ${resolve(t)}`;
|
|
|
1784
1802
|
addText(b.text);
|
|
1785
1803
|
break;
|
|
1786
1804
|
case "heading":
|
|
1787
|
-
case "subheading":
|
|
1805
|
+
case "subheading": {
|
|
1806
|
+
const r = resolve(b.text);
|
|
1788
1807
|
scan.headings += `
|
|
1789
|
-
${
|
|
1790
|
-
|
|
1808
|
+
${r}`;
|
|
1809
|
+
scan.text += `
|
|
1810
|
+
${r}`;
|
|
1791
1811
|
break;
|
|
1812
|
+
}
|
|
1792
1813
|
case "text":
|
|
1793
1814
|
addText(b.text);
|
|
1794
1815
|
break;
|
|
@@ -1857,6 +1878,17 @@ function mentionsTimes(text, x) {
|
|
|
1857
1878
|
return new RegExp(`\\b${grouped}${frac}\\s*[x\xD7]`, "i").test(text);
|
|
1858
1879
|
}
|
|
1859
1880
|
var mentionsName = (text, name) => text.toLowerCase().includes(name.toLowerCase());
|
|
1881
|
+
function mentionsCost(text, cost) {
|
|
1882
|
+
if (mentionsTimes(text, cost) || mentionsTimes(text, cost + 1)) return true;
|
|
1883
|
+
if (cost > 0 && cost < 1) return new RegExp(`\\b${Math.round(cost * 100)}\\s*%`).test(text);
|
|
1884
|
+
return false;
|
|
1885
|
+
}
|
|
1886
|
+
function findModeSection(sections, m) {
|
|
1887
|
+
return sections.find(
|
|
1888
|
+
(s) => s.explains.has(m.id) || s.covers.has(`feature:${m.id}`) || s.heading !== "" && m.name !== "" && mentionsName(s.heading, m.name) || (m.kind === "base" || !m.kind) && /how to play|about the game/i.test(s.heading)
|
|
1889
|
+
);
|
|
1890
|
+
}
|
|
1891
|
+
var MIN_SECTION_PROSE = 40;
|
|
1860
1892
|
function auditRules(facts, rules, opts = {}) {
|
|
1861
1893
|
const out = [];
|
|
1862
1894
|
try {
|
|
@@ -1877,8 +1909,17 @@ function auditRules(facts, rules, opts = {}) {
|
|
|
1877
1909
|
} else if (!(scan.hasModeStats || covered(`maxwin:${m.id}`) || nameIn && mentionsTimes(scan.text, m.maxWinX))) {
|
|
1878
1910
|
add("required", "rules-missing-maxwin", `maxwin:${m.id}`, `The max win of \u201C${m.name}\u201D (${formatTimes(m.maxWinX)}) is not stated in the rules.`);
|
|
1879
1911
|
}
|
|
1880
|
-
if (
|
|
1881
|
-
|
|
1912
|
+
if (!m.id) continue;
|
|
1913
|
+
const sec = findModeSection(scan.sections, m);
|
|
1914
|
+
if (!sec) {
|
|
1915
|
+
add("required", "rules-missing-mode-section", `section:${m.id}`, `\u201C${m.name}\u201D has no rules section of its own \u2014 add a heading naming it (or tag its blocks with explains: "${m.id}") and explain how the mode plays.`);
|
|
1916
|
+
} else {
|
|
1917
|
+
if (sec.text.trim().length < MIN_SECTION_PROSE) {
|
|
1918
|
+
add("required", "rules-mode-section-empty", `section:${m.id}`, `The \u201C${m.name}\u201D section has a heading but no real explanation \u2014 describe how the mode actually plays.`);
|
|
1919
|
+
}
|
|
1920
|
+
if (m.kind && m.kind !== "base" && m.cost != null && !(sec.covers.has(`cost:${m.id}`) || mentionsCost(sec.text, m.cost))) {
|
|
1921
|
+
add("required", "rules-mode-missing-cost", `cost:${m.id}`, `State what \u201C${m.name}\u201D costs (${formatTimes(m.cost)} the bet \u2014 e.g. via {{cost.${m.id}}}) inside its own section.`);
|
|
1922
|
+
}
|
|
1882
1923
|
}
|
|
1883
1924
|
}
|
|
1884
1925
|
const fs = facts?.freeSpins;
|
|
@@ -2819,6 +2860,201 @@ function auditRulesDoc(doc, opts = {}) {
|
|
|
2819
2860
|
return auditRules(facts, doc.blocks, { resolve });
|
|
2820
2861
|
}
|
|
2821
2862
|
|
|
2863
|
+
// src/spec/rulesHtml.ts
|
|
2864
|
+
var escapeHtml = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
2865
|
+
var richHtml = (s) => escapeHtml(s).replace(/\*\*(.+?)\*\*/g, "<b>$1</b>");
|
|
2866
|
+
var esc = escapeHtml;
|
|
2867
|
+
var rich = richHtml;
|
|
2868
|
+
function statGridHtml(items, tr) {
|
|
2869
|
+
const rows = items.map((it) => `<div><dt>${esc(tr(it.label))}</dt><dd>${esc(tr(it.value))}</dd></div>`).join("");
|
|
2870
|
+
return `<dl class="ohm-stats">${rows}</dl>`;
|
|
2871
|
+
}
|
|
2872
|
+
function renderPaytable(rows, tr) {
|
|
2873
|
+
return rows.map((r) => {
|
|
2874
|
+
const icon = r.icon ? `<img class="ohm-symimg" src="${r.icon}" alt="" loading="lazy">` : `<span class="ohm-emoji">${esc(tr(r.symbol ?? ""))}</span>`;
|
|
2875
|
+
const lines = r.payouts.split("\n").map((line) => {
|
|
2876
|
+
const i = line.indexOf(":");
|
|
2877
|
+
return i >= 0 ? `<div><b>${esc(line.slice(0, i))}</b><span>${esc(line.slice(i + 1))}</span></div>` : `<div><span>${esc(line)}</span></div>`;
|
|
2878
|
+
}).join("");
|
|
2879
|
+
return `<div class="ohm-sym">${icon}<div class="ohm-pay">${lines}</div></div>`;
|
|
2880
|
+
}).join("");
|
|
2881
|
+
}
|
|
2882
|
+
function renderBlocksHtml(blocks, tr, facts) {
|
|
2883
|
+
const out = [];
|
|
2884
|
+
for (const b of blocks) {
|
|
2885
|
+
switch (b.kind) {
|
|
2886
|
+
case "text":
|
|
2887
|
+
out.push(`<p>${rich(tr(b.text))}</p>`);
|
|
2888
|
+
break;
|
|
2889
|
+
case "heading":
|
|
2890
|
+
out.push(`<div class="ohm-sec"><span>${esc(tr(b.text))}</span></div>`);
|
|
2891
|
+
break;
|
|
2892
|
+
case "subheading":
|
|
2893
|
+
out.push(`<h4 class="ohm-subh">${esc(tr(b.text))}</h4>`);
|
|
2894
|
+
break;
|
|
2895
|
+
case "legal":
|
|
2896
|
+
out.push(`<p class="ohm-legal">${rich(tr(b.text))}</p>`);
|
|
2897
|
+
break;
|
|
2898
|
+
case "divider":
|
|
2899
|
+
out.push('<hr class="ohm-hr">');
|
|
2900
|
+
break;
|
|
2901
|
+
case "image":
|
|
2902
|
+
out.push(`<img class="ohm-feature" alt="${esc(tr(b.alt ?? ""))}" src="${b.src}" loading="lazy">`);
|
|
2903
|
+
break;
|
|
2904
|
+
case "media": {
|
|
2905
|
+
const img = `<img alt="${esc(tr(b.alt ?? ""))}" src="${b.src}" loading="lazy">`;
|
|
2906
|
+
const body = `<div class="ohm-media-body">${b.title ? `<h4>${esc(tr(b.title))}</h4>` : ""}<p>${rich(tr(b.text))}</p></div>`;
|
|
2907
|
+
out.push(`<div class="ohm-media ohm-media--${b.side ?? "left"}">${img}${body}</div>`);
|
|
2908
|
+
break;
|
|
2909
|
+
}
|
|
2910
|
+
case "cards": {
|
|
2911
|
+
const cards = b.items.map((it) => `<div class="ohm-fcard">${it.icon ? `<img src="${it.icon}" alt="" loading="lazy">` : ""}<h5>${esc(tr(it.title))}</h5>${it.text ? `<p>${rich(tr(it.text))}</p>` : ""}</div>`).join("");
|
|
2912
|
+
out.push(`<div class="ohm-cards">${cards}</div>`);
|
|
2913
|
+
break;
|
|
2914
|
+
}
|
|
2915
|
+
case "paytable":
|
|
2916
|
+
out.push(`<div class="ohm-grid">${renderPaytable(b.rows, tr)}</div>`);
|
|
2917
|
+
break;
|
|
2918
|
+
case "table": {
|
|
2919
|
+
const head = b.columns?.length ? `<thead><tr>${b.columns.map((c) => `<th>${esc(tr(c))}</th>`).join("")}</tr></thead>` : "";
|
|
2920
|
+
const body = b.rows.map((r) => `<tr>${r.map((c) => `<td>${esc(tr(c))}</td>`).join("")}</tr>`).join("");
|
|
2921
|
+
out.push(`<table class="ohm-table">${head}<tbody>${body}</tbody></table>`);
|
|
2922
|
+
break;
|
|
2923
|
+
}
|
|
2924
|
+
case "stat-grid":
|
|
2925
|
+
out.push(statGridHtml(b.items, tr));
|
|
2926
|
+
break;
|
|
2927
|
+
// The AUTO per-mode RTP / Max-win grid — rendered straight from the declared
|
|
2928
|
+
// game facts (+ any host extras), so the table can never drift from the config.
|
|
2929
|
+
// `modeStatsItems` localizes the label PARTS itself ("Max win" · the mode name),
|
|
2930
|
+
// so the grid renderer gets identity-tr — no double translation.
|
|
2931
|
+
case "mode-stats": {
|
|
2932
|
+
const extras = (b.extras ?? []).map((e) => ({ label: tr(e.label), value: tr(e.value) }));
|
|
2933
|
+
out.push(statGridHtml([...modeStatsItems(facts, tr), ...extras], (s) => s));
|
|
2934
|
+
break;
|
|
2935
|
+
}
|
|
2936
|
+
case "steps": {
|
|
2937
|
+
const items = b.items.map((s) => `<li>${rich(tr(s))}</li>`).join("");
|
|
2938
|
+
out.push(b.ordered ? `<ol class="ohm-steps">${items}</ol>` : `<ul class="ohm-steps">${items}</ul>`);
|
|
2939
|
+
break;
|
|
2940
|
+
}
|
|
2941
|
+
case "callout":
|
|
2942
|
+
out.push(`<div class="ohm-callout ohm-callout--${b.tone ?? "info"}">${b.title ? `<b>${esc(tr(b.title))}</b>` : ""}<p>${rich(tr(b.text))}</p></div>`);
|
|
2943
|
+
break;
|
|
2944
|
+
case "group":
|
|
2945
|
+
out.push(`<div class="ohm-group">${b.title ? `<h4 class="ohm-subh">${esc(tr(b.title))}</h4>` : ""}${renderBlocksHtml(b.children, tr, facts)}</div>`);
|
|
2946
|
+
break;
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2949
|
+
return out.join("\n");
|
|
2950
|
+
}
|
|
2951
|
+
function renderRulesAuditHtml(issues, tr) {
|
|
2952
|
+
if (!issues.length) return "";
|
|
2953
|
+
const req = issues.filter((i) => i.level === "required");
|
|
2954
|
+
const rec = issues.filter((i) => i.level === "recommended");
|
|
2955
|
+
const list = (items) => `<ul>${items.map((i) => `<li>${esc(tr(i.message))}</li>`).join("")}</ul>`;
|
|
2956
|
+
return `<div class="ohm-audit" role="alert">
|
|
2957
|
+
<div class="ohm-audit-title">\u26A0 ${esc(tr("openui.rulesAudit.title"))}</div>
|
|
2958
|
+
${req.length ? `<div class="ohm-audit-sub">${esc(tr("openui.rulesAudit.required"))}</div>${list(req)}` : ""}
|
|
2959
|
+
${rec.length ? `<div class="ohm-audit-sub ohm-audit-sub--rec">${esc(tr("openui.rulesAudit.recommended"))}</div><div class="ohm-audit-rec">${list(rec)}</div>` : ""}
|
|
2960
|
+
</div>`;
|
|
2961
|
+
}
|
|
2962
|
+
var INFO_MENU_VARS = Object.freeze({
|
|
2963
|
+
"--accent": "#d99000",
|
|
2964
|
+
"--accent-text": "#1a1200",
|
|
2965
|
+
"--surface": "#ffffff",
|
|
2966
|
+
"--surface-alt": "#eef1f6",
|
|
2967
|
+
"--text": "#181b20",
|
|
2968
|
+
"--text-dim": "#5b6472",
|
|
2969
|
+
"--card-radius": "8px",
|
|
2970
|
+
"--font": "system-ui, sans-serif"
|
|
2971
|
+
});
|
|
2972
|
+
var INFO_MENU_CSS = `
|
|
2973
|
+
.ohm-root { position: fixed; inset: 0; z-index: 10000; display: grid; place-items: center; font-family: var(--font); opacity: 0; pointer-events: none; transition: opacity .18s ease; }
|
|
2974
|
+
.ohm-root.open { opacity: 1; pointer-events: auto; }
|
|
2975
|
+
.ohm-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; }
|
|
2976
|
+
.ohm-root.open .ohm-backdrop { background: rgba(8,6,4,.34); backdrop-filter: blur(6px) saturate(1.1); -webkit-backdrop-filter: blur(6px) saturate(1.1); }
|
|
2977
|
+
.ohm-card { position: relative; width: min(92%, 1100px); max-height: 86vh; display: flex; flex-direction: column; background: var(--surface); color: var(--text); border: 1.5px solid #000; border-radius: var(--card-radius); box-shadow: 0 30px 80px rgba(0,0,0,.5); overflow: hidden; transform: translateY(8px) scale(.99); transition: transform .18s ease; }
|
|
2978
|
+
.ohm-root.open .ohm-card { transform: none; }
|
|
2979
|
+
.ohm-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; }
|
|
2980
|
+
.ohm-x:hover { transform: scale(1.08); background: rgba(18,14,10,.95); }
|
|
2981
|
+
.ohm-body { padding: 24px 26px 26px; overflow-y: scroll; }
|
|
2982
|
+
.ohm-body::-webkit-scrollbar { width: 18px; }
|
|
2983
|
+
.ohm-body::-webkit-scrollbar-track { background: transparent; margin: 12px 0; }
|
|
2984
|
+
.ohm-body::-webkit-scrollbar-thumb { background-color: #111; border: 6px solid transparent; background-clip: padding-box; border-radius: 999px; min-height: 44px; }
|
|
2985
|
+
.ohm-body::-webkit-scrollbar-thumb:hover { background-color: #000; }
|
|
2986
|
+
.ohm-logo { display: block; margin: 6px auto 18px; max-width: 64%; height: auto; }
|
|
2987
|
+
.ohm-logo-text { margin: 6px 0 18px; text-align: center; font-size: 30px; font-weight: 900; letter-spacing: 1px; color: var(--text); }
|
|
2988
|
+
.ohm-sec { display: flex; align-items: center; gap: 14px; margin: 26px 0 14px; color: var(--text); font-weight: 800; letter-spacing: 1px; }
|
|
2989
|
+
.ohm-sec::before, .ohm-sec::after { content: ""; flex: 1; height: 2px; background: color-mix(in srgb, var(--text) 80%, transparent); border-radius: 2px; }
|
|
2990
|
+
.ohm-root *, .ohm-root *::before, .ohm-root *::after { box-sizing: border-box; }
|
|
2991
|
+
.ohm-row { display: flex; align-items: center; gap: 16px; margin: 14px 0; font-weight: 700; }
|
|
2992
|
+
.ohm-setting { margin: 14px 0; }
|
|
2993
|
+
.ohm-setting .ohm-row { margin: 0; }
|
|
2994
|
+
.ohm-hint { margin: 3px 0 0; font-size: 12.5px; font-weight: 500; color: var(--text-dim); }
|
|
2995
|
+
.ohm-row > span:first-child { flex: none; min-width: 110px; }
|
|
2996
|
+
.ohm-row input[type=range] { flex: 1; min-width: 0; max-width: min(440px, 60dvw); accent-color: var(--accent); height: 6px; }
|
|
2997
|
+
.ohm-row select { flex: 1; min-width: 0; max-width: min(440px, 60dvw); padding: 11px 14px; border-radius: 4px; border: 2px solid var(--accent); background: var(--surface-alt); color: var(--text); font-weight: 700; font-size: 15px; cursor: pointer; }
|
|
2998
|
+
.ohm-row select option { background: var(--surface); color: var(--text); font-weight: 600; }
|
|
2999
|
+
.ohm-row select option:checked { background: var(--accent); color: var(--accent-text); }
|
|
3000
|
+
.ohm-ctl { flex: 1; min-width: 0; max-width: min(440px, 60dvw); display: flex; align-items: center; justify-content: flex-end; }
|
|
3001
|
+
.ohm-check input[type=checkbox] { appearance: none; -webkit-appearance: none; width: 50px; height: 28px; border-radius: 999px; background: color-mix(in srgb, var(--text-dim) 38%, transparent); position: relative; cursor: pointer; transition: background .15s; flex: none; }
|
|
3002
|
+
.ohm-check input[type=checkbox]:checked { background: var(--accent); }
|
|
3003
|
+
.ohm-check input[type=checkbox]::before { content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 999px; background: #fff; transition: left .15s; box-shadow: 0 1px 3px rgba(0,0,0,.3); }
|
|
3004
|
+
.ohm-check input[type=checkbox]:checked::before { left: 25px; }
|
|
3005
|
+
.ohm-segmented { display: inline-flex; gap: 4px; padding: 4px; background: var(--surface-alt); border-radius: 999px; border: 1px solid color-mix(in srgb, var(--text-dim) 30%, transparent); }
|
|
3006
|
+
.ohm-seg { border: 0; background: transparent; color: var(--text-dim); font-weight: 700; font-size: 14px; padding: 8px 18px; border-radius: 999px; cursor: pointer; transition: background .12s, color .12s; }
|
|
3007
|
+
.ohm-seg.active { background: var(--accent); color: var(--accent-text); }
|
|
3008
|
+
.ohm-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }
|
|
3009
|
+
.ohm-sym { display: flex; align-items: center; gap: 16px; padding: 6px 4px; }
|
|
3010
|
+
.ohm-emoji { font-size: 48px; line-height: 1; filter: drop-shadow(0 2px 4px rgba(0,0,0,.3)); }
|
|
3011
|
+
.ohm-symimg { width: 56px; height: 56px; object-fit: contain; flex: none; }
|
|
3012
|
+
.ohm-pay { font-size: 13px; line-height: 1.6; }
|
|
3013
|
+
.ohm-pay div { display: flex; gap: 6px; }
|
|
3014
|
+
.ohm-pay b { min-width: 42px; }
|
|
3015
|
+
.ohm-pay span { color: var(--accent); font-weight: 700; }
|
|
3016
|
+
.ohm-body p { color: var(--text-dim); line-height: 1.6; }
|
|
3017
|
+
.ohm-body p b { color: var(--text); }
|
|
3018
|
+
.ohm-feature { display: block; width: 100%; height: auto; margin: 10px 0; }
|
|
3019
|
+
.ohm-stats { margin: 12px 0; display: grid; grid-template-columns: 1fr 1fr; gap: 0 28px; }
|
|
3020
|
+
.ohm-stats > div { display: flex; justify-content: space-between; padding: 9px 0; border-bottom: 1px solid color-mix(in srgb, var(--text-dim) 20%, transparent); }
|
|
3021
|
+
.ohm-stats dt { color: var(--text-dim); margin: 0; } .ohm-stats dd { margin: 0; font-weight: 700; }
|
|
3022
|
+
.ohm-audit { margin: 12px 0 18px; padding: 14px 16px; border-radius: 12px; border: 2px solid #d03131; background: color-mix(in srgb, #d03131 8%, transparent); }
|
|
3023
|
+
.ohm-audit-title { font-weight: 900; letter-spacing: .5px; color: #b31d1d; }
|
|
3024
|
+
.ohm-audit-sub { margin-top: 8px; font-size: 13px; font-weight: 800; color: #b31d1d; }
|
|
3025
|
+
.ohm-audit-sub--rec { color: #b07d09; }
|
|
3026
|
+
.ohm-audit ul { margin: 6px 0 0; padding-left: 20px; color: var(--text); font-size: 13.5px; line-height: 1.55; }
|
|
3027
|
+
.ohm-audit li { margin: 3px 0; }
|
|
3028
|
+
.ohm-audit-rec ul { color: var(--text-dim); }
|
|
3029
|
+
.ohm-callout { margin: 16px 0 4px; padding: 14px 16px; border-radius: 12px; border-left: 4px solid var(--accent); background: color-mix(in srgb, var(--accent) 9%, transparent); }
|
|
3030
|
+
.ohm-callout b { color: var(--accent); } .ohm-callout p { margin: 4px 0 0; color: var(--text); }
|
|
3031
|
+
.ohm-callout--warning { border-left-color: #e0a106; background: color-mix(in srgb, #e0a106 10%, transparent); }
|
|
3032
|
+
.ohm-callout--warning b { color: #b07d09; }
|
|
3033
|
+
.ohm-subh { margin: 22px 0 8px; font-size: 15px; font-weight: 800; letter-spacing: .5px; color: var(--text); }
|
|
3034
|
+
.ohm-legal { font-size: 12px; line-height: 1.6; color: var(--text-dim); opacity: .85; }
|
|
3035
|
+
.ohm-hr { border: 0; border-top: 1px solid color-mix(in srgb, var(--text-dim) 30%, transparent); margin: 18px 0; }
|
|
3036
|
+
.ohm-media { display: flex; align-items: center; gap: 18px; margin: 14px 0; }
|
|
3037
|
+
.ohm-media--right { flex-direction: row-reverse; }
|
|
3038
|
+
.ohm-media > img { width: 40%; max-width: 320px; height: auto; flex: none; }
|
|
3039
|
+
.ohm-media-body { flex: 1; }
|
|
3040
|
+
.ohm-media-body h4 { margin: 0 0 6px; font-size: 16px; color: var(--text); }
|
|
3041
|
+
.ohm-media-body p { margin: 0; }
|
|
3042
|
+
.ohm-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin: 12px 0; }
|
|
3043
|
+
.ohm-fcard { padding: 8px 6px; text-align: center; }
|
|
3044
|
+
.ohm-fcard img { display: block; width: 48px; height: 48px; margin: 0 auto 8px; }
|
|
3045
|
+
.ohm-fcard h5 { margin: 0 0 4px; font-size: 14px; color: var(--text); }
|
|
3046
|
+
.ohm-fcard p { margin: 0; font-size: 12px; line-height: 1.5; }
|
|
3047
|
+
.ohm-table { width: 100%; border-collapse: collapse; margin: 12px 0; font-size: 14px; }
|
|
3048
|
+
.ohm-table th { text-align: left; padding: 8px 10px; font-weight: 800; color: var(--text); border-bottom: 2px solid color-mix(in srgb, var(--text-dim) 35%, transparent); }
|
|
3049
|
+
.ohm-table td { padding: 8px 10px; border-bottom: 1px solid color-mix(in srgb, var(--text-dim) 18%, transparent); }
|
|
3050
|
+
.ohm-table td:first-child { color: var(--text); font-weight: 700; }
|
|
3051
|
+
.ohm-table td:not(:first-child) { color: var(--accent); font-weight: 700; }
|
|
3052
|
+
.ohm-steps { margin: 12px 0; padding-left: 22px; color: var(--text-dim); line-height: 1.7; }
|
|
3053
|
+
.ohm-steps li { margin: 5px 0; }
|
|
3054
|
+
.ohm-steps b { color: var(--text); }
|
|
3055
|
+
.ohm-group { margin: 8px 0; }
|
|
3056
|
+
`;
|
|
3057
|
+
|
|
2822
3058
|
// src/spec/defaultHudSpec.ts
|
|
2823
3059
|
var defaultHudSpec = Object.freeze({
|
|
2824
3060
|
meta: { id: "open-ui-reference-hud", version: 1 },
|
|
@@ -2923,6 +3159,6 @@ function clampBet(amount, cfg, divisor = API_AMOUNT_DIVISOR) {
|
|
|
2923
3159
|
return Math.min(max, Math.max(min, v));
|
|
2924
3160
|
}
|
|
2925
3161
|
|
|
2926
|
-
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, applyRulesDoc, auditRules, auditRulesDoc, breakpointFor, buildBetLadder, buildBlocks, buildPanel, buttonBlocks, checkSocialPhrases, clampBet, clampDecimals, clampDigits, clampMinDigits, collectSocialCopy, composeMenu, computeScreen, createUI, defaultHudSpec, defaultLayout, defaultLayoutConfig, defaultTheme, defineUI, dictionary, displayDigits, effect, errorBlocks, extendTheme, factsVars, findForbiddenPhrases, formatAmount, formatAmountPrecise, formatRtp, formatTimes, installResponsive, integerDigits, isRulesDoc, isSafeColor, isSocialCurrency, landscapeDefaultLayouts, mergeFacts, modeStatsItems, neededDecimals, openuiDefaults, openuiSocialDefaults, portraitDefaultLayouts, resolveBetLadder, resolveCurrency, resolvePlacement, resolveTheme, resolveTurboModes, safeAmount, sanitizeThemeOverrides, themePresets, validateSpec, valueFitMaxWidth };
|
|
3162
|
+
export { API_AMOUNT_DIVISOR, AutoplayControl, BLOCK_KINDS, ButtonControl, CURRENCY_TABLE, CardControl, Control, ControlRegistry, DEFAULT_MENU_TITLES, DEFAULT_NOTICE_ACTION, DictionaryTranslator, EventBus, EventLog, Fade, INFO_MENU_CSS, INFO_MENU_VARS, LOCALE_LABELS, OpenUI, PanelControl, Parallel, Pulse, RGS_ERROR_KEYS, ReadoutControl, SelectControl, Sequence, Signal, SliderControl, SpinControl, Squish, StepperControl, ToggleControl, TurboControl, Turn, ValueDisplay, applyJurisdiction, applyRulesDoc, auditRules, auditRulesDoc, breakpointFor, buildBetLadder, buildBlocks, buildPanel, buttonBlocks, checkSocialPhrases, clampBet, clampDecimals, clampDigits, clampMinDigits, collectSocialCopy, composeMenu, computeScreen, createUI, defaultHudSpec, defaultLayout, defaultLayoutConfig, defaultTheme, defineUI, dictionary, displayDigits, effect, errorBlocks, escapeHtml, extendTheme, factsVars, findForbiddenPhrases, formatAmount, formatAmountPrecise, formatRtp, formatTimes, installResponsive, integerDigits, isRulesDoc, isSafeColor, isSocialCurrency, landscapeDefaultLayouts, mergeFacts, modeStatsItems, neededDecimals, openuiDefaults, openuiSocialDefaults, portraitDefaultLayouts, renderBlocksHtml, renderRulesAuditHtml, resolveBetLadder, resolveCurrency, resolvePlacement, resolveTheme, resolveTurboModes, richHtml, safeAmount, sanitizeThemeOverrides, themePresets, validateSpec, valueFitMaxWidth };
|
|
2927
3163
|
//# sourceMappingURL=index.js.map
|
|
2928
3164
|
//# sourceMappingURL=index.js.map
|