@open-slot-ui/core 0.10.0 → 0.11.1
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 +201 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -1
- package/dist/index.d.ts +36 -1
- package/dist/index.js +196 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -2091,6 +2091,41 @@ declare function auditRulesDoc(doc: RulesDoc, opts?: {
|
|
|
2091
2091
|
facts?: GameFacts;
|
|
2092
2092
|
}): RulesAuditIssue[];
|
|
2093
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
|
+
|
|
2094
2129
|
/**
|
|
2095
2130
|
* The reference HUD expressed as data — the knobs `new OpenUI()` ships with.
|
|
2096
2131
|
* `createUI(defaultHudSpec)` is byte-equivalent to zero-arg `createUI()` (a test
|
|
@@ -2247,4 +2282,4 @@ declare function resolveBetLadder(availableBets: number[] | undefined, defaultBe
|
|
|
2247
2282
|
/** Clamp a stake (major units) to the RGS min/max and snap to `stepBet`. Pure. */
|
|
2248
2283
|
declare function clampBet(amount: number, cfg: RgsBetConfig, divisor?: number): number;
|
|
2249
2284
|
|
|
2250
|
-
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
|
@@ -2091,6 +2091,41 @@ declare function auditRulesDoc(doc: RulesDoc, opts?: {
|
|
|
2091
2091
|
facts?: GameFacts;
|
|
2092
2092
|
}): RulesAuditIssue[];
|
|
2093
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
|
+
|
|
2094
2129
|
/**
|
|
2095
2130
|
* The reference HUD expressed as data — the knobs `new OpenUI()` ships with.
|
|
2096
2131
|
* `createUI(defaultHudSpec)` is byte-equivalent to zero-arg `createUI()` (a test
|
|
@@ -2247,4 +2282,4 @@ declare function resolveBetLadder(availableBets: number[] | undefined, defaultBe
|
|
|
2247
2282
|
/** Clamp a stake (major units) to the RGS min/max and snap to `stepBet`. Pure. */
|
|
2248
2283
|
declare function clampBet(amount: number, cfg: RgsBetConfig, divisor?: number): number;
|
|
2249
2284
|
|
|
2250
|
-
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
|
@@ -2860,6 +2860,201 @@ function auditRulesDoc(doc, opts = {}) {
|
|
|
2860
2860
|
return auditRules(facts, doc.blocks, { resolve });
|
|
2861
2861
|
}
|
|
2862
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
|
+
|
|
2863
3058
|
// src/spec/defaultHudSpec.ts
|
|
2864
3059
|
var defaultHudSpec = Object.freeze({
|
|
2865
3060
|
meta: { id: "open-ui-reference-hud", version: 1 },
|
|
@@ -2964,6 +3159,6 @@ function clampBet(amount, cfg, divisor = API_AMOUNT_DIVISOR) {
|
|
|
2964
3159
|
return Math.min(max, Math.max(min, v));
|
|
2965
3160
|
}
|
|
2966
3161
|
|
|
2967
|
-
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 };
|
|
2968
3163
|
//# sourceMappingURL=index.js.map
|
|
2969
3164
|
//# sourceMappingURL=index.js.map
|