refactor: pick out magic numbers to constants
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Button from "$components/ui/Button.svelte";
|
import Button from "$components/ui/Button.svelte";
|
||||||
|
import { PANEL_SETTINGS, TYPOGRAPHY, UI_SETTINGS } from "$lib/constants";
|
||||||
import type { Panel, TextItem } from "$lib/types/panel";
|
import type { Panel, TextItem } from "$lib/types/panel";
|
||||||
import { setCurrentStep } from "$stores/uiStore";
|
import { setCurrentStep } from "$stores/uiStore";
|
||||||
import type { Stage as KonvaStage } from "konva/lib/Stage";
|
import type { Stage as KonvaStage } from "konva/lib/Stage";
|
||||||
@@ -23,7 +24,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
function handleUploadNewImage() {
|
function handleUploadNewImage() {
|
||||||
setCurrentStep("upload");
|
setCurrentStep(UI_SETTINGS.STEPS.UPLOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
@@ -63,7 +64,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getTextPosition(textItem: TextItem) {
|
function getTextPosition(textItem: TextItem) {
|
||||||
const panelWidth = 320;
|
const panelWidth = PANEL_SETTINGS.PANEL_WIDTH;
|
||||||
const paddingX = textItem.paddingX || 20;
|
const paddingX = textItem.paddingX || 20;
|
||||||
const verticalOffset = textItem.verticalOffset || 0;
|
const verticalOffset = textItem.verticalOffset || 0;
|
||||||
const centerY = panel.height / 2 + verticalOffset;
|
const centerY = panel.height / 2 + verticalOffset;
|
||||||
@@ -95,10 +96,10 @@
|
|||||||
<div class="preview-sections">
|
<div class="preview-sections">
|
||||||
<div class="preview-section">
|
<div class="preview-section">
|
||||||
<div class="canvas-container">
|
<div class="canvas-container">
|
||||||
<Stage width={320} height={panel.height} bind:this={stageComponent}>
|
<Stage width={PANEL_SETTINGS.PANEL_WIDTH} height={panel.height} bind:this={stageComponent}>
|
||||||
<Layer>
|
<Layer>
|
||||||
{#if backgroundImage}
|
{#if backgroundImage}
|
||||||
<Image image={backgroundImage} width={320} height={panel.height} />
|
<Image image={backgroundImage} width={PANEL_SETTINGS.PANEL_WIDTH} height={panel.height} />
|
||||||
{/if}
|
{/if}
|
||||||
</Layer>
|
</Layer>
|
||||||
|
|
||||||
@@ -108,12 +109,12 @@
|
|||||||
|
|
||||||
<Text
|
<Text
|
||||||
text={panel.text.text}
|
text={panel.text.text}
|
||||||
fontSize={panel.text.fontSize || 24}
|
fontSize={panel.text.fontSize || TYPOGRAPHY.FONT_SIZE_DEFAULT}
|
||||||
fill={panel.text.color || "#ffffff"}
|
fill={panel.text.color || TYPOGRAPHY.TEXT_COLOR_DEFAULT}
|
||||||
fontFamily={panel.text.fontFamily || "Arial"}
|
fontFamily={panel.text.fontFamily || "Arial"}
|
||||||
x={textPosition.x}
|
x={textPosition.x}
|
||||||
y={textPosition.y}
|
y={textPosition.y}
|
||||||
align={panel.text.textAlign || "center"}
|
align={panel.text.textAlign || TYPOGRAPHY.TEXT_ALIGN_CENTER}
|
||||||
width={300}
|
width={300}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Button from "$components/ui/Button.svelte";
|
import Button from "$components/ui/Button.svelte";
|
||||||
|
import { TYPOGRAPHY } from "$lib/constants";
|
||||||
import type { TextAlign, TextItem } from "$lib/types/panel";
|
import type { TextAlign, TextItem } from "$lib/types/panel";
|
||||||
import { textSettingsStore, updateAllTextSettings } from "$stores/panelStore";
|
import { textSettingsStore, updateAllTextSettings } from "$stores/panelStore";
|
||||||
|
|
||||||
@@ -17,16 +18,7 @@
|
|||||||
|
|
||||||
let commonTextSettings = $derived($textSettingsStore);
|
let commonTextSettings = $derived($textSettingsStore);
|
||||||
|
|
||||||
const availableFonts = [
|
const availableFonts = TYPOGRAPHY.FONT_FAMILIES;
|
||||||
"Arial",
|
|
||||||
"Verdana",
|
|
||||||
"Georgia",
|
|
||||||
"Times New Roman",
|
|
||||||
"Courier New",
|
|
||||||
"Impact",
|
|
||||||
"Comic Sans MS",
|
|
||||||
"Trebuchet MS",
|
|
||||||
];
|
|
||||||
|
|
||||||
function handleAddText() {
|
function handleAddText() {
|
||||||
if (!newText.trim()) {
|
if (!newText.trim()) {
|
||||||
@@ -34,8 +26,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newText.length > 100) {
|
if (newText.length > TYPOGRAPHY.MAX_TEXT_LENGTH) {
|
||||||
errorMessage = "Текст не должен превышать 100 символов";
|
errorMessage = `Текст не должен превышать ${TYPOGRAPHY.MAX_TEXT_LENGTH} символов`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +67,7 @@
|
|||||||
bind:value={newText}
|
bind:value={newText}
|
||||||
placeholder="Введите текст для панели (например: links, about me, projects...)"
|
placeholder="Введите текст для панели (например: links, about me, projects...)"
|
||||||
class="text-input"
|
class="text-input"
|
||||||
maxlength="100"
|
maxlength={TYPOGRAPHY.MAX_TEXT_LENGTH}
|
||||||
onkeypress={handleKeyPress}
|
onkeypress={handleKeyPress}
|
||||||
/>
|
/>
|
||||||
<Button variant="primary" onclick={handleAddText}>Добавить</Button>
|
<Button variant="primary" onclick={handleAddText}>Добавить</Button>
|
||||||
@@ -98,7 +90,7 @@
|
|||||||
value={textItem.text}
|
value={textItem.text}
|
||||||
oninput={(e) => handleUpdateText(textItem.id, e.currentTarget.value)}
|
oninput={(e) => handleUpdateText(textItem.id, e.currentTarget.value)}
|
||||||
class="text-edit-input"
|
class="text-edit-input"
|
||||||
maxlength="100"
|
maxlength={TYPOGRAPHY.MAX_TEXT_LENGTH}
|
||||||
/>
|
/>
|
||||||
<Button variant="danger" size="sm" onclick={() => handleDeleteText(textItem.id)} aria-label="Удалить текст">
|
<Button variant="danger" size="sm" onclick={() => handleDeleteText(textItem.id)} aria-label="Удалить текст">
|
||||||
×
|
×
|
||||||
@@ -119,8 +111,8 @@
|
|||||||
Размер шрифта:
|
Размер шрифта:
|
||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
min="10"
|
min={TYPOGRAPHY.FONT_SIZE_MIN}
|
||||||
max="72"
|
max={TYPOGRAPHY.FONT_SIZE_MAX}
|
||||||
step="1"
|
step="1"
|
||||||
value={commonTextSettings.fontSize}
|
value={commonTextSettings.fontSize}
|
||||||
oninput={(e: Event) => {
|
oninput={(e: Event) => {
|
||||||
@@ -201,7 +193,7 @@
|
|||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
min="0"
|
min="0"
|
||||||
max="50"
|
max={TYPOGRAPHY.PADDING_X_MAX}
|
||||||
step="1"
|
step="1"
|
||||||
value={commonTextSettings.paddingX}
|
value={commonTextSettings.paddingX}
|
||||||
oninput={(e) => {
|
oninput={(e) => {
|
||||||
@@ -217,8 +209,8 @@
|
|||||||
Смещение от центра:
|
Смещение от центра:
|
||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
min="-50"
|
min={TYPOGRAPHY.VERTICAL_OFFSET_MIN}
|
||||||
max="50"
|
max={TYPOGRAPHY.VERTICAL_OFFSET_MAX}
|
||||||
step="1"
|
step="1"
|
||||||
value={commonTextSettings.verticalOffset}
|
value={commonTextSettings.verticalOffset}
|
||||||
oninput={(e) => {
|
oninput={(e) => {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { PANEL_SETTINGS, TYPOGRAPHY } from "$lib/constants";
|
||||||
import type { TextItem } from "$lib/types/panel";
|
import type { TextItem } from "$lib/types/panel";
|
||||||
import { panelStore } from "$stores/panelStore";
|
import { panelStore } from "$stores/panelStore";
|
||||||
import { Image, Layer, Stage, Text } from "svelte-konva";
|
import { Image, Layer, Stage, Text } from "svelte-konva";
|
||||||
@@ -28,17 +29,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getTextPosition() {
|
function getTextPosition() {
|
||||||
const panelWidth = 320;
|
const panelWidth = PANEL_SETTINGS.PANEL_WIDTH;
|
||||||
const paddingX = textItem.paddingX || 0;
|
const paddingX = textItem.paddingX || 0;
|
||||||
const verticalOffset = textItem.verticalOffset || 0;
|
const verticalOffset = textItem.verticalOffset || 0;
|
||||||
const centerY = height / 2 + verticalOffset;
|
const centerY = height / 2 + verticalOffset;
|
||||||
|
|
||||||
switch (textItem.textAlign) {
|
switch (textItem.textAlign) {
|
||||||
case "left":
|
case TYPOGRAPHY.TEXT_ALIGN_LEFT:
|
||||||
return { x: paddingX, y: centerY };
|
return { x: paddingX, y: centerY };
|
||||||
case "right":
|
case TYPOGRAPHY.TEXT_ALIGN_RIGHT:
|
||||||
return { x: panelWidth - paddingX, y: centerY };
|
return { x: panelWidth - paddingX, y: centerY };
|
||||||
case "center":
|
case TYPOGRAPHY.TEXT_ALIGN_CENTER:
|
||||||
default:
|
default:
|
||||||
return { x: panelWidth / 2, y: centerY };
|
return { x: panelWidth / 2, y: centerY };
|
||||||
}
|
}
|
||||||
@@ -50,9 +51,9 @@
|
|||||||
<div class="text-preview">
|
<div class="text-preview">
|
||||||
{#if bgImage}
|
{#if bgImage}
|
||||||
<div class="canvas-container">
|
<div class="canvas-container">
|
||||||
<Stage width={320} {height}>
|
<Stage width={PANEL_SETTINGS.PANEL_WIDTH} {height}>
|
||||||
<Layer>
|
<Layer>
|
||||||
<Image image={bgImage} width={320} {height} />
|
<Image image={bgImage} width={PANEL_SETTINGS.PANEL_WIDTH} {height} />
|
||||||
<Text
|
<Text
|
||||||
text={textItem.text}
|
text={textItem.text}
|
||||||
fontSize={textItem.fontSize}
|
fontSize={textItem.fontSize}
|
||||||
@@ -62,7 +63,11 @@
|
|||||||
y={textPosition.y}
|
y={textPosition.y}
|
||||||
align={textItem.textAlign}
|
align={textItem.textAlign}
|
||||||
width={320 - textItem.paddingX * 2}
|
width={320 - textItem.paddingX * 2}
|
||||||
offsetX={textItem.textAlign === "center" ? 0 : textItem.textAlign === "right" ? 0 : 0}
|
offsetX={textItem.textAlign === TYPOGRAPHY.TEXT_ALIGN_CENTER
|
||||||
|
? 0
|
||||||
|
: textItem.textAlign === TYPOGRAPHY.TEXT_ALIGN_RIGHT
|
||||||
|
? 0
|
||||||
|
: 0}
|
||||||
/>
|
/>
|
||||||
</Layer>
|
</Layer>
|
||||||
</Stage>
|
</Stage>
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
// Application Constants
|
||||||
|
// This file contains magic numbers and strings used in JavaScript/TypeScript logic
|
||||||
|
|
||||||
|
// ===== PANEL SETTINGS =====
|
||||||
|
export const PANEL_SETTINGS = {
|
||||||
|
// Storage
|
||||||
|
STORAGE_KEY: "twitch-panels",
|
||||||
|
MAX_PANELS_COUNT: 50,
|
||||||
|
|
||||||
|
// Dimensions
|
||||||
|
PANEL_WIDTH: 320,
|
||||||
|
PANEL_HEIGHT_DEFAULT: 100,
|
||||||
|
PANEL_HEIGHT_MAX: 1000,
|
||||||
|
|
||||||
|
// Default values
|
||||||
|
DEFAULT_BACKGROUND_IMAGE: "/backgrounds/b1.jpg",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// ===== TYPOGRAPHY =====
|
||||||
|
export const TYPOGRAPHY = {
|
||||||
|
// Font families
|
||||||
|
FONT_FAMILY_DEFAULT: "Arial",
|
||||||
|
FONT_FAMILIES: [
|
||||||
|
"Arial",
|
||||||
|
"Verdana",
|
||||||
|
"Georgia",
|
||||||
|
"Times New Roman",
|
||||||
|
"Courier New",
|
||||||
|
"Impact",
|
||||||
|
"Comic Sans MS",
|
||||||
|
"Trebuchet MS",
|
||||||
|
],
|
||||||
|
|
||||||
|
// Font sizes for range inputs
|
||||||
|
FONT_SIZE_MIN: 10,
|
||||||
|
FONT_SIZE_MAX: 72,
|
||||||
|
FONT_SIZE_DEFAULT: 18,
|
||||||
|
|
||||||
|
// Text alignment
|
||||||
|
TEXT_ALIGN_LEFT: "left",
|
||||||
|
TEXT_ALIGN_CENTER: "center",
|
||||||
|
TEXT_ALIGN_RIGHT: "right",
|
||||||
|
|
||||||
|
// Text limits
|
||||||
|
MAX_TEXT_LENGTH: 100,
|
||||||
|
|
||||||
|
// Padding for range inputs
|
||||||
|
PADDING_X_DEFAULT: 10,
|
||||||
|
PADDING_X_LARGE: 20,
|
||||||
|
PADDING_X_MAX: 50,
|
||||||
|
|
||||||
|
// Vertical offset for range inputs
|
||||||
|
VERTICAL_OFFSET_MAX: 50,
|
||||||
|
VERTICAL_OFFSET_MIN: -50,
|
||||||
|
|
||||||
|
// Colors
|
||||||
|
TEXT_COLOR_DEFAULT: "#ffffff",
|
||||||
|
TEXT_COLOR_ERROR: "#c62828",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// ===== IMAGE SETTINGS =====
|
||||||
|
export const IMAGE_SETTINGS = {
|
||||||
|
// File sizes
|
||||||
|
MAX_FILE_SIZE: 10 * 1024 * 1024, // 10MB
|
||||||
|
|
||||||
|
// Supported formats
|
||||||
|
SUPPORTED_FORMATS: ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/gif"] as const,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// ===== UI SETTINGS =====
|
||||||
|
export const UI_SETTINGS = {
|
||||||
|
// Steps
|
||||||
|
STEPS: {
|
||||||
|
UPLOAD: "upload",
|
||||||
|
CROP: "crop",
|
||||||
|
TEXT: "text",
|
||||||
|
} as const,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// ===== ERROR HANDLING =====
|
||||||
|
export const ERROR_HANDLING = {
|
||||||
|
// Retry settings
|
||||||
|
MAX_RETRIES: 3,
|
||||||
|
RETRY_DELAY_MS: 1000,
|
||||||
|
} as const;
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { AppError, type ErrorType } from "../types/errors";
|
import { ERROR_HANDLING } from "../constants";
|
||||||
|
import { AppError } from "../types/errors";
|
||||||
|
|
||||||
export function handleError(error: unknown, defaultMessage: string = "Произошла ошибка"): string {
|
export function handleError(error: unknown, defaultMessage: string = "Произошла ошибка"): string {
|
||||||
if (error instanceof AppError) {
|
if (error instanceof AppError) {
|
||||||
@@ -38,8 +39,8 @@ export function logError(error: unknown, context?: string): void {
|
|||||||
|
|
||||||
export function retryOperation<T>(
|
export function retryOperation<T>(
|
||||||
operation: () => Promise<T>,
|
operation: () => Promise<T>,
|
||||||
maxRetries: number = 3,
|
maxRetries: number = ERROR_HANDLING.MAX_RETRIES,
|
||||||
delayMs: number = 1000,
|
delayMs: number = ERROR_HANDLING.RETRY_DELAY_MS,
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let attempt = 0;
|
let attempt = 0;
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
|
import { IMAGE_SETTINGS } from "../constants";
|
||||||
import { ImageError } from "../types/errors";
|
import { ImageError } from "../types/errors";
|
||||||
|
|
||||||
export const MAX_FILE_SIZE = 10 * 1024 * 1024;
|
export const MAX_FILE_SIZE = IMAGE_SETTINGS.MAX_FILE_SIZE;
|
||||||
export const SUPPORTED_FORMATS = ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/gif"];
|
export const SUPPORTED_FORMATS = IMAGE_SETTINGS.SUPPORTED_FORMATS;
|
||||||
|
|
||||||
export type ValidationResult =
|
export type ValidationResult =
|
||||||
| {
|
| {
|
||||||
@@ -23,7 +24,7 @@ export function validateFileSize(file: File): ValidationResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function validateFileType(file: File): ValidationResult {
|
export function validateFileType(file: File): ValidationResult {
|
||||||
if (!SUPPORTED_FORMATS.includes(file.type)) {
|
if (!SUPPORTED_FORMATS.includes(file.type as any)) {
|
||||||
return {
|
return {
|
||||||
isValid: false,
|
isValid: false,
|
||||||
error: `Неподдерживаемый формат. Допустимые форматы: ${SUPPORTED_FORMATS.join(", ")}`,
|
error: `Неподдерживаемый формат. Допустимые форматы: ${SUPPORTED_FORMATS.join(", ")}`,
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
|
import { PANEL_SETTINGS } from "../constants";
|
||||||
import type { Panel } from "../types/panel";
|
import type { Panel } from "../types/panel";
|
||||||
import { handleError, logError } from "./errorHandler";
|
import { handleError, logError } from "./errorHandler";
|
||||||
|
|
||||||
const STORAGE_KEY = "twitch-panels";
|
const STORAGE_KEY = PANEL_SETTINGS.STORAGE_KEY;
|
||||||
const MAX_PANELS = 50;
|
const MAX_PANELS = PANEL_SETTINGS.MAX_PANELS_COUNT;
|
||||||
|
|
||||||
export interface StorageResult {
|
export interface StorageResult {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
@@ -109,7 +110,7 @@ export class PanelStorage {
|
|||||||
Array.isArray(panel.texts) &&
|
Array.isArray(panel.texts) &&
|
||||||
typeof panel.height === "number" &&
|
typeof panel.height === "number" &&
|
||||||
panel.height > 0 &&
|
panel.height > 0 &&
|
||||||
panel.height <= 1000 &&
|
panel.height <= PANEL_SETTINGS.PANEL_HEIGHT_MAX &&
|
||||||
panel.createdAt instanceof Date &&
|
panel.createdAt instanceof Date &&
|
||||||
panel.updatedAt instanceof Date
|
panel.updatedAt instanceof Date
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { PANEL_SETTINGS } from "../lib/constants";
|
||||||
import type { Panel, TextItem } from "../lib/types/panel";
|
import type { Panel, TextItem } from "../lib/types/panel";
|
||||||
import { createPanelFromText, updatePanelText } from "../stores/panelStore";
|
import { createPanelFromText, updatePanelText } from "../stores/panelStore";
|
||||||
|
|
||||||
@@ -54,7 +55,7 @@ export class PanelService {
|
|||||||
if (existingPanel) {
|
if (existingPanel) {
|
||||||
return updatePanelText(existingPanel, textItem.text);
|
return updatePanelText(existingPanel, textItem.text);
|
||||||
}
|
}
|
||||||
return createPanelFromText(backgroundImage, textItem.text, 100, textSettings);
|
return createPanelFromText(backgroundImage, textItem.text, PANEL_SETTINGS.PANEL_HEIGHT_DEFAULT, textSettings);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-17
@@ -1,15 +1,16 @@
|
|||||||
import { writable, type Writable } from "svelte/store";
|
import { writable, type Writable } from "svelte/store";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
import { PANEL_SETTINGS, TYPOGRAPHY } from "../lib/constants";
|
||||||
import { type Panel, type TextItem } from "../lib/types/panel";
|
import { type Panel, type TextItem } from "../lib/types/panel";
|
||||||
|
|
||||||
export const panelStore: Writable<Panel | undefined> = writable(undefined);
|
export const panelStore: Writable<Panel | undefined> = writable(undefined);
|
||||||
|
|
||||||
export const textSettingsStore = writable<Partial<TextItem>>({
|
export const textSettingsStore = writable<Partial<TextItem>>({
|
||||||
fontSize: 18,
|
fontSize: TYPOGRAPHY.FONT_SIZE_DEFAULT,
|
||||||
fontFamily: "Arial",
|
fontFamily: TYPOGRAPHY.FONT_FAMILY_DEFAULT,
|
||||||
color: "#ffffff",
|
color: TYPOGRAPHY.TEXT_COLOR_DEFAULT,
|
||||||
textAlign: "left",
|
textAlign: TYPOGRAPHY.TEXT_ALIGN_LEFT,
|
||||||
paddingX: 10,
|
paddingX: TYPOGRAPHY.PADDING_X_DEFAULT,
|
||||||
verticalOffset: 0,
|
verticalOffset: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -17,15 +18,15 @@ export const updateAllTextSettings = (settings: Partial<TextItem>) => {
|
|||||||
textSettingsStore.update((current) => ({ ...current, ...settings }));
|
textSettingsStore.update((current) => ({ ...current, ...settings }));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createEmptyPanel = (height: number = 100): Panel => {
|
export const createEmptyPanel = (height: number = PANEL_SETTINGS.PANEL_HEIGHT_DEFAULT): Panel => {
|
||||||
const defaultText: TextItem = {
|
const defaultText: TextItem = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
text: "",
|
text: "",
|
||||||
fontSize: 18,
|
fontSize: TYPOGRAPHY.FONT_SIZE_DEFAULT,
|
||||||
fontFamily: "Arial",
|
fontFamily: TYPOGRAPHY.FONT_FAMILY_DEFAULT,
|
||||||
color: "#ffffff",
|
color: TYPOGRAPHY.TEXT_COLOR_DEFAULT,
|
||||||
textAlign: "center",
|
textAlign: TYPOGRAPHY.TEXT_ALIGN_CENTER,
|
||||||
paddingX: 10,
|
paddingX: TYPOGRAPHY.PADDING_X_DEFAULT,
|
||||||
verticalOffset: 0,
|
verticalOffset: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -62,17 +63,17 @@ export const updateTextProperties = (panel: Panel, updates: Partial<TextItem>):
|
|||||||
export const createPanelFromText = (
|
export const createPanelFromText = (
|
||||||
backgroundImage: string,
|
backgroundImage: string,
|
||||||
text: string,
|
text: string,
|
||||||
height: number = 100,
|
height: number = PANEL_SETTINGS.PANEL_HEIGHT_DEFAULT,
|
||||||
textSettings?: Partial<TextItem>,
|
textSettings?: Partial<TextItem>,
|
||||||
): Panel => {
|
): Panel => {
|
||||||
const newText: TextItem = {
|
const newText: TextItem = {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
text,
|
text,
|
||||||
fontSize: textSettings?.fontSize ?? 18,
|
fontSize: textSettings?.fontSize ?? TYPOGRAPHY.FONT_SIZE_DEFAULT,
|
||||||
fontFamily: textSettings?.fontFamily ?? "Arial",
|
fontFamily: textSettings?.fontFamily ?? TYPOGRAPHY.FONT_FAMILY_DEFAULT,
|
||||||
color: textSettings?.color ?? "#ffffff",
|
color: textSettings?.color ?? TYPOGRAPHY.TEXT_COLOR_DEFAULT,
|
||||||
textAlign: textSettings?.textAlign ?? "center",
|
textAlign: textSettings?.textAlign ?? TYPOGRAPHY.TEXT_ALIGN_CENTER,
|
||||||
paddingX: textSettings?.paddingX ?? 10,
|
paddingX: textSettings?.paddingX ?? TYPOGRAPHY.PADDING_X_DEFAULT,
|
||||||
verticalOffset: textSettings?.verticalOffset ?? 0,
|
verticalOffset: textSettings?.verticalOffset ?? 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user