mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 11:30:43 +00:00
@@ -132,10 +132,6 @@
|
||||
"info_enemy_panel": "Enemy info panel",
|
||||
"exit_confirmation": "Are you sure you want to exit the game?"
|
||||
},
|
||||
"slider": {
|
||||
"label": "Bots:",
|
||||
"disabled": "Disabled"
|
||||
},
|
||||
"single_modal": {
|
||||
"title": "Single Player",
|
||||
"allow_alliances": "Allow alliances",
|
||||
|
||||
@@ -132,10 +132,6 @@
|
||||
"enables_title": "설정 활성화",
|
||||
"start": "게임 시작하기"
|
||||
},
|
||||
"slider": {
|
||||
"label": "봇:",
|
||||
"disabled": "사용 안 함"
|
||||
},
|
||||
"map": {
|
||||
"map": "지도",
|
||||
"world": "세계",
|
||||
|
||||
@@ -311,17 +311,26 @@ export class HostLobbyModal extends LitElement {
|
||||
${translateText("host_modal.options_title")}
|
||||
</div>
|
||||
<div class="option-cards">
|
||||
<label for="bots-count" class="option-card">
|
||||
<!-- Slider -->
|
||||
<fluent-slider
|
||||
.value=${this.bots}
|
||||
.min=${0}
|
||||
.max=${400}
|
||||
.step=${1}
|
||||
ariaLabel=${translateText("single_modal.bots")}
|
||||
@input=${this.handleBotsChange}
|
||||
></fluent-slider>
|
||||
</label>
|
||||
<label for="bots-count" class="option-card">
|
||||
<input
|
||||
type="range"
|
||||
id="bots-count"
|
||||
min="0"
|
||||
max="400"
|
||||
step="1"
|
||||
@input=${this.handleBotsChange}
|
||||
@change=${this.handleBotsChange}
|
||||
.value="${String(this.bots)}"
|
||||
/>
|
||||
<div class="option-card-title">
|
||||
<span>${translateText("host_modal.bots")}</span>${
|
||||
this.bots === 0
|
||||
? translateText("host_modal.bots_disabled")
|
||||
: this.bots
|
||||
}
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label
|
||||
for="disable-npcs"
|
||||
class="option-card ${this.disableNPCs ? "selected" : ""}"
|
||||
|
||||
@@ -20,7 +20,6 @@ import { generateID } from "../core/Util";
|
||||
import "./components/baseComponents/Button";
|
||||
import "./components/baseComponents/Modal";
|
||||
import "./components/Difficulties";
|
||||
import "./components/FluentSlider";
|
||||
import "./components/Maps";
|
||||
import { fetchCosmetics } from "./Cosmetics";
|
||||
import { FlagInput } from "./FlagInput";
|
||||
@@ -45,6 +44,7 @@ export class SinglePlayerModal extends LitElement {
|
||||
@state() private useRandomMap: boolean = false;
|
||||
@state() private gameMode: GameMode = GameMode.FFA;
|
||||
@state() private teamCount: TeamCountConfig = 2;
|
||||
|
||||
@state() private disabledUnits: UnitType[] = [];
|
||||
|
||||
private userSettings: UserSettings = new UserSettings();
|
||||
@@ -220,16 +220,24 @@ export class SinglePlayerModal extends LitElement {
|
||||
</div>
|
||||
<div class="option-cards">
|
||||
<label for="bots-count" class="option-card">
|
||||
<!-- Slider -->
|
||||
<fluent-slider
|
||||
.value=${this.bots}
|
||||
.min=${0}
|
||||
.max=${400}
|
||||
.step=${1}
|
||||
ariaLabel=${translateText("single_modal.bots")}
|
||||
<input
|
||||
type="range"
|
||||
id="bots-count"
|
||||
min="0"
|
||||
max="400"
|
||||
step="1"
|
||||
@input=${this.handleBotsChange}
|
||||
></fluent-slider>
|
||||
@change=${this.handleBotsChange}
|
||||
.value="${String(this.bots)}"
|
||||
/>
|
||||
<div class="option-card-title">
|
||||
<span>${translateText("single_modal.bots")}</span>${this
|
||||
.bots === 0
|
||||
? translateText("single_modal.bots_disabled")
|
||||
: this.bots}
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label
|
||||
for="singleplayer-modal-disable-npcs"
|
||||
class="option-card ${this.disableNPCs ? "selected" : ""}"
|
||||
@@ -364,11 +372,10 @@ export class SinglePlayerModal extends LitElement {
|
||||
}
|
||||
|
||||
private handleBotsChange(e: Event) {
|
||||
const inputEl = e.target as HTMLInputElement;
|
||||
let value = inputEl.valueAsNumber;
|
||||
if (Number.isNaN(value)) return;
|
||||
if (value < 0) value = 0;
|
||||
if (value > 400) value = 400;
|
||||
const value = parseInt((e.target as HTMLInputElement).value);
|
||||
if (isNaN(value) || value < 0 || value > 400) {
|
||||
return;
|
||||
}
|
||||
this.bots = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
import { LitElement, css, html } from "lit";
|
||||
import { property, query, state } from "lit/decorators.js";
|
||||
import { translateText } from "../Utils";
|
||||
|
||||
export class FluentSlider extends LitElement {
|
||||
static styles = css`
|
||||
:host {
|
||||
display: block;
|
||||
width: 100%;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.slider-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.option-card-title {
|
||||
font-size: 14px; /* match other cards */
|
||||
color: #aaa; /* light gray text */
|
||||
text-align: center;
|
||||
margin: 0 0 4px 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
width: 60px;
|
||||
background-color: #2d3748;
|
||||
color: #aaa; /* match label color */
|
||||
border: 1px solid #4a5568;
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
font-weight: normal;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
span.editable {
|
||||
cursor: pointer;
|
||||
min-width: 60px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
color: #aaa; /* match label color */
|
||||
font-weight: normal;
|
||||
user-select: none;
|
||||
}
|
||||
`;
|
||||
|
||||
@property({ type: Number }) value = 0;
|
||||
@property({ type: Number }) min = 0;
|
||||
@property({ type: Number }) max = 400;
|
||||
@property({ type: Number }) step = 1;
|
||||
|
||||
@state() private isEditing = false;
|
||||
|
||||
@query("input[type='number']") private numberInput!: HTMLInputElement;
|
||||
|
||||
private handleSliderChange(e: Event) {
|
||||
const target = e.target as HTMLInputElement;
|
||||
this.value = Number(target.value);
|
||||
}
|
||||
|
||||
private handleNumberChange(e: Event) {
|
||||
const target = e.target as HTMLInputElement;
|
||||
let val = Number(target.value);
|
||||
if (val < this.min) val = this.min;
|
||||
if (val > this.max) val = this.max;
|
||||
this.value = val;
|
||||
}
|
||||
|
||||
private handleNumberKeyDown(e: KeyboardEvent) {
|
||||
if (e.key === "Enter") this.isEditing = false;
|
||||
}
|
||||
|
||||
private enableEditing() {
|
||||
this.isEditing = true;
|
||||
this.updateComplete.then(() => this.numberInput?.focus());
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="slider-container">
|
||||
<input
|
||||
type="range"
|
||||
.min=${this.min}
|
||||
.max=${this.max}
|
||||
.step=${this.step}
|
||||
.value=${String(this.value)}
|
||||
@input=${this.handleSliderChange}
|
||||
/>
|
||||
|
||||
<div class="option-card-title">
|
||||
<span>${translateText("slider.label")}</span>
|
||||
|
||||
${this.isEditing
|
||||
? html`<input
|
||||
type="number"
|
||||
.min=${this.min}
|
||||
.max=${this.max}
|
||||
.value=${this.value}
|
||||
@input=${this.handleNumberChange}
|
||||
@blur=${() => (this.isEditing = false)}
|
||||
@keydown=${this.handleNumberKeyDown}
|
||||
/>`
|
||||
: html`<span
|
||||
class="editable"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
@click=${this.enableEditing}
|
||||
@keydown=${(e: KeyboardEvent) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
this.enableEditing();
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
>
|
||||
${this.value === 0
|
||||
? translateText("slider.disabled")
|
||||
: this.value}
|
||||
</span>`}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("fluent-slider", FluentSlider);
|
||||
Reference in New Issue
Block a user