This commit is contained in:
Aotumuri
2025-05-04 20:34:27 +09:00
parent cdb7e37972
commit b1d68fbae3
+120 -59
View File
@@ -18,6 +18,11 @@ export class territoryPatternsModal extends LitElement {
@state() private buttonWidth: number = 100;
@state() private lockedPatterns: string[] = [];
@state() private lockedReasons: Record<string, string> = {};
@state() private hoveredPattern: string | null = null;
@state() private hoverPosition = { x: 0, y: 0 };
private resizeObserver: ResizeObserver;
constructor() {
@@ -38,6 +43,10 @@ export class territoryPatternsModal extends LitElement {
containers.forEach((container) => this.resizeObserver.observe(container));
this.updatePreview();
});
this.setLockedPatterns(["evan"], {
evan: "This pattern is locked because it is restricted.",
});
}
disconnectedCallback() {
@@ -51,72 +60,95 @@ export class territoryPatternsModal extends LitElement {
render() {
return html`
${this.hoveredPattern && this.lockedReasons[this.hoveredPattern]
? html`
<div
class="fixed z-[9999] px-3 py-2 rounded bg-black text-white text-sm pointer-events-none shadow-md"
style="top: ${this.hoverPosition.y + 12}px; left: ${this
.hoverPosition.x + 12}px;"
>
${this.lockedReasons[this.hoveredPattern]}
</div>
`
: null}
<o-modal id="territoryPatternsModal" title="Select Territory Pattern">
<div
class="flex flex-wrap gap-4 p-2"
style="justify-content: center; align-items: flex-start;"
>
${Object.entries(territory_patterns.patterns).map(
([key, pattern]) => html`
<button
class="border p-2 rounded-lg shadow text-black dark:text-white text-left
${this.selectedPattern === key
? "bg-blue-500 text-white"
: "bg-gray-100 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700"}"
style="flex: 0 1 calc(25% - 1rem); max-width: calc(25% - 1rem);"
@click=${() => this.selectPattern(key)}
>
<div class="text-sm font-bold mb-1">${key}</div>
<div
class="preview-container"
style="
width: 100%;
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
border-radius: 8px;
overflow: hidden;
"
>
${(() => {
const cellCountX = pattern.tileWidth;
const cellCountY = pattern.tileHeight;
const cellSize = Math.floor(
this.buttonWidth / Math.max(cellCountX, cellCountY),
);
([key, pattern]) => {
const isLocked = this.isPatternLocked(key);
const reason = this.lockedReasons[key] || "Locked";
return html`
<div
style="
display: grid;
grid-template-columns: repeat(${cellCountX}, ${cellSize}px);
grid-template-rows: repeat(${cellCountY}, ${cellSize}px);
background-color: #ccc;
padding: 2px;
border-radius: 4px;
"
>
${pattern.pattern.flat().map(
(cell) => html`
<div
style="
background-color: ${cell === 1 ? "#000" : "transparent"};
border: 1px solid rgba(0, 0, 0, 0.1);
width: ${cellSize}px;
height: ${cellSize}px;
border-radius: 1px;
"
></div>
`,
)}
</div>
`;
})()}
</div>
</button>
`,
return html`
<button
class="border p-2 rounded-lg shadow text-black dark:text-white text-left
${this.selectedPattern === key
? "bg-blue-500 text-white"
: "bg-gray-100 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700"}
${isLocked ? "opacity-50 cursor-not-allowed" : ""}"
style="flex: 0 1 calc(25% - 1rem); max-width: calc(25% - 1rem);"
@click=${() => !isLocked && this.selectPattern(key)}
@mouseenter=${(e: MouseEvent) =>
this.handleMouseEnter(key, e)}
@mousemove=${(e: MouseEvent) => this.handleMouseMove(e)}
@mouseleave=${() => this.handleMouseLeave()}
>
<div class="text-sm font-bold mb-1">${key}</div>
<div
class="preview-container"
style="
width: 100%;
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
border-radius: 8px;
overflow: hidden;
"
>
${(() => {
const cellCountX = pattern.tileWidth;
const cellCountY = pattern.tileHeight;
const cellSize = Math.floor(
this.buttonWidth / Math.max(cellCountX, cellCountY),
);
return html`
<div
style="
display: grid;
grid-template-columns: repeat(${cellCountX}, ${cellSize}px);
grid-template-rows: repeat(${cellCountY}, ${cellSize}px);
background-color: #ccc;
padding: 2px;
border-radius: 4px;
"
>
${pattern.pattern.flat().map(
(cell) => html`
<div
style="
background-color: ${cell === 1
? "#000"
: "transparent"};
border: 1px solid rgba(0, 0, 0, 0.1);
width: ${cellSize}px;
height: ${cellSize}px;
border-radius: 1px;
"
></div>
`,
)}
</div>
`;
})()}
</div>
</button>
`;
},
)}
</div>
</o-modal>
@@ -198,4 +230,33 @@ export class territoryPatternsModal extends LitElement {
render(previewHTML, this.previewButton);
}
private setLockedPatterns(
lockedPatterns: string[],
reasons: Record<string, string>,
) {
this.lockedPatterns = lockedPatterns;
this.lockedReasons = reasons;
}
private isPatternLocked(patternKey: string): boolean {
return this.lockedPatterns.includes(patternKey);
}
private handleMouseEnter(patternKey: string, event: MouseEvent) {
if (this.isPatternLocked(patternKey)) {
this.hoveredPattern = patternKey;
this.hoverPosition = { x: event.clientX, y: event.clientY };
}
}
private handleMouseMove(event: MouseEvent) {
if (this.hoveredPattern) {
this.hoverPosition = { x: event.clientX, y: event.clientY };
}
}
private handleMouseLeave() {
this.hoveredPattern = null;
}
}