feat: bilingual support (FA/EN), IRANSans typography, RTL layout, and interactive product detail pages

This commit is contained in:
s.esmaeili
2026-10-04 07:11:52 +03:30
commit a001fa5d5f
302 changed files with 35491 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
import { generateKeyBetween, generateNKeysBetween } from "fractional-indexing";
export interface Ordered {
readonly id: string;
readonly order: string;
}
export function compareOrdered(a: Ordered, b: Ordered): number {
if (a.order !== b.order) {
return a.order < b.order ? -1 : 1;
}
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
}
/** Where `item` sorts into `sorted`: its own index when present, else its insertion index. */
export function rankOf(sorted: readonly Ordered[], item: Ordered): number {
let low = 0;
let high = sorted.length;
while (low < high) {
const middle = (low + high) >>> 1;
if (compareOrdered(sorted[middle]!, item) < 0) {
low = middle + 1;
} else {
high = middle;
}
}
return low;
}
/** A key after every item in `sorted`. */
export function appendKey(sorted: readonly Ordered[]): string {
return (
between(sorted[sorted.length - 1]?.order ?? null, null) ??
generateKeyBetween(null, null)
);
}
/** Keys that put `sorted[from]` at `index` among the other items; `repairs` re-key those only when no key fits between its new neighbours. */
export function placeAt(
sorted: readonly Ordered[],
from: number,
index: number,
): { key: string; repairs: Array<{ id: string; order: string }> } {
const other = (at: number) => sorted[at < from ? at : at + 1];
const key = between(
other(index - 1)?.order ?? null,
other(index)?.order ?? null,
);
if (key !== undefined) {
return { key, repairs: [] };
}
const keys = generateNKeysBetween(null, null, sorted.length);
return {
key: keys[index]!,
repairs: sorted
.filter((_, at) => at !== from)
.map((item, at) => ({
id: item.id,
order: keys[at < index ? at : at + 1]!,
})),
};
}
/** The index of `item` in `sorted`, or -1. */
export function indexOf(sorted: readonly Ordered[], item: Ordered): number {
const rank = rankOf(sorted, item);
return sorted[rank] === item ? rank : -1;
}
function between(a: string | null, b: string | null): string | undefined {
try {
return generateKeyBetween(a, b);
} catch {
return undefined;
}
}