1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
import { buildStickerId, parseStickerId } from "../sticker-id";
import type {
StickerItem,
StickerProvider,
StickerSearchResult,
} from "../types";
const SHAPES_PROVIDER_ID = "shapes";
const SHAPES = [
{ key: "circle", name: "Circle" },
{ key: "square", name: "Square" },
{ key: "triangle", name: "Triangle" },
{ key: "star", name: "Star" },
{ key: "hexagon", name: "Hexagon" },
{ key: "diamond", name: "Diamond" },
] as const;
function buildShapeUrl({ shapeKey }: { shapeKey: string }): string {
return `/shapes/${shapeKey}.svg`;
}
function toStickerItem({
shape,
}: {
shape: (typeof SHAPES)[number];
}): StickerItem {
return {
id: buildStickerId({
providerId: SHAPES_PROVIDER_ID,
providerValue: shape.key,
}),
provider: SHAPES_PROVIDER_ID,
name: shape.name,
previewUrl: buildShapeUrl({ shapeKey: shape.key }),
metadata: { shape: shape.key },
};
}
function filterShapesByQuery({
query,
}: {
query: string;
}): Array<(typeof SHAPES)[number]> {
const normalizedQuery = query.trim().toLowerCase();
if (!normalizedQuery) {
return [...SHAPES];
}
return SHAPES.filter((shape) =>
shape.name.toLowerCase().includes(normalizedQuery),
);
}
function paginateShapes({
shapes,
options,
}: {
shapes: Array<(typeof SHAPES)[number]>;
options?: { page?: number; limit?: number };
}): { items: Array<(typeof SHAPES)[number]>; hasMore: boolean; total: number } {
const page = Math.max(1, options?.page ?? 1);
const limit = Math.max(1, options?.limit ?? SHAPES.length);
const startIndex = (page - 1) * limit;
const endIndex = startIndex + limit;
const pagedItems = shapes.slice(startIndex, endIndex);
return {
items: pagedItems,
hasMore: endIndex < shapes.length,
total: shapes.length,
};
}
export const shapesProvider: StickerProvider = {
id: SHAPES_PROVIDER_ID,
async search({
query,
options,
}: {
query: string;
options?: { limit?: number };
}): Promise<StickerSearchResult> {
const filteredShapes = filterShapesByQuery({ query });
const paged = paginateShapes({
shapes: filteredShapes,
options: { page: 1, limit: options?.limit ?? SHAPES.length },
});
return {
items: paged.items.map((shape) => toStickerItem({ shape })),
total: paged.total,
hasMore: paged.hasMore,
};
},
async browse({
options,
}: {
options?: { page?: number; limit?: number };
}): Promise<StickerSearchResult> {
const paged = paginateShapes({
shapes: [...SHAPES],
options,
});
return {
items: paged.items.map((shape) => toStickerItem({ shape })),
total: paged.total,
hasMore: paged.hasMore,
};
},
resolveUrl({
stickerId,
}: {
stickerId: string;
options?: { width?: number; height?: number };
}): string {
const { providerValue } = parseStickerId({ stickerId });
return buildShapeUrl({ shapeKey: providerValue });
},
};
|