refactor: store based md-pins
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
import { createStore } from "solid-js/store";
|
||||
|
||||
export interface Pin {
|
||||
x: number;
|
||||
y: number;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface PinsState {
|
||||
pins: Pin[];
|
||||
rawSrc: string;
|
||||
isFixed: boolean;
|
||||
}
|
||||
|
||||
// 生成标签 A-Z, AA-ZZ, AAA-ZZZ ...
|
||||
export function generateLabel(index: number): string {
|
||||
const labels: string[] = [];
|
||||
let num = index;
|
||||
|
||||
do {
|
||||
const remainder = num % 26;
|
||||
labels.unshift(String.fromCharCode(65 + remainder));
|
||||
num = Math.floor(num / 26) - 1;
|
||||
} while (num >= 0);
|
||||
|
||||
return labels.join('');
|
||||
}
|
||||
|
||||
// 解析 pins 字符串 "A:30,40 B:10,30" -> Pin[]
|
||||
export function parsePins(pinsStr: string): Pin[] {
|
||||
if (!pinsStr) return [];
|
||||
|
||||
const pins: Pin[] = [];
|
||||
const regex = /([A-Z]+):(\d+),(\d+)/g;
|
||||
let match;
|
||||
|
||||
while ((match = regex.exec(pinsStr)) !== null) {
|
||||
pins.push({
|
||||
label: match[1],
|
||||
x: parseInt(match[2]),
|
||||
y: parseInt(match[3])
|
||||
});
|
||||
}
|
||||
|
||||
return pins;
|
||||
}
|
||||
|
||||
// 格式化 pins 为字符串 "A:30,40 B:10,30"
|
||||
export function formatPins(pins: Pin[]): string {
|
||||
return pins.map(pin => `${pin.label}:${pin.x},${pin.y}`).join(' ');
|
||||
}
|
||||
|
||||
// 找到最早未使用的标签
|
||||
export function findNextUnusedLabel(pins: Pin[]): string {
|
||||
const usedLabels = new Set(pins.map(p => p.label));
|
||||
|
||||
let index = 0;
|
||||
while (true) {
|
||||
const label = generateLabel(index);
|
||||
if (!usedLabels.has(label)) {
|
||||
return label;
|
||||
}
|
||||
index++;
|
||||
if (index > 10000) break; // 安全限制
|
||||
}
|
||||
|
||||
return generateLabel(pins.length);
|
||||
}
|
||||
|
||||
// 创建 store 实例
|
||||
export function createPinsStore(initialPinsStr: string = "", initialFixed: boolean = false) {
|
||||
const [state, setState] = createStore<PinsState>({
|
||||
pins: parsePins(initialPinsStr),
|
||||
rawSrc: "",
|
||||
isFixed: initialFixed
|
||||
});
|
||||
|
||||
const setRawSrc = (src: string) => {
|
||||
setState("rawSrc", src);
|
||||
};
|
||||
|
||||
const addPin = (x: number, y: number) => {
|
||||
const label = findNextUnusedLabel(state.pins);
|
||||
setState("pins", [...state.pins, { x, y, label }]);
|
||||
};
|
||||
|
||||
const removePin = (index: number) => {
|
||||
setState("pins", state.pins.filter((_, i) => i !== index));
|
||||
};
|
||||
|
||||
const formatCurrentPins = () => formatPins(state.pins);
|
||||
|
||||
const getCopyText = () => {
|
||||
const pinsStr = formatCurrentPins();
|
||||
return `:md-pins[${state.rawSrc}]{pins="${pinsStr}" fixed}`;
|
||||
};
|
||||
|
||||
return {
|
||||
state,
|
||||
setState,
|
||||
setRawSrc,
|
||||
addPin,
|
||||
removePin,
|
||||
formatCurrentPins,
|
||||
getCopyText
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user