@page-speed/maps 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -0
- package/dist/components/geo-map.cjs +1237 -0
- package/dist/components/geo-map.cjs.map +1 -0
- package/dist/components/geo-map.d.cts +138 -0
- package/dist/components/geo-map.d.ts +138 -0
- package/dist/components/geo-map.js +1216 -0
- package/dist/components/geo-map.js.map +1 -0
- package/dist/components/index.cjs +1359 -0
- package/dist/components/index.cjs.map +1 -0
- package/dist/components/index.d.cts +5 -0
- package/dist/components/index.d.ts +5 -0
- package/dist/components/index.js +1335 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/map-marker.cjs +137 -0
- package/dist/components/map-marker.cjs.map +1 -0
- package/dist/components/map-marker.d.cts +76 -0
- package/dist/components/map-marker.d.ts +76 -0
- package/dist/components/map-marker.js +130 -0
- package/dist/components/map-marker.js.map +1 -0
- package/dist/index.cjs +929 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +910 -21
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.cts +5 -5
- package/dist/types/index.d.ts +5 -5
- package/dist/utils/cn.cjs +13 -0
- package/dist/utils/cn.cjs.map +1 -0
- package/dist/utils/cn.d.cts +16 -0
- package/dist/utils/cn.d.ts +16 -0
- package/dist/utils/cn.js +11 -0
- package/dist/utils/cn.js.map +1 -0
- package/dist/utils/index.cjs +63 -0
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +4 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +42 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/simple-pressable.cjs +63 -0
- package/dist/utils/simple-pressable.cjs.map +1 -0
- package/dist/utils/simple-pressable.d.cts +20 -0
- package/dist/utils/simple-pressable.d.ts +20 -0
- package/dist/utils/simple-pressable.js +41 -0
- package/dist/utils/simple-pressable.js.map +1 -0
- package/package.json +29 -2
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/utils/cn.ts
|
|
6
|
+
function cn(...inputs) {
|
|
7
|
+
return twMerge(clsx(inputs));
|
|
8
|
+
}
|
|
9
|
+
var SIZE_CONFIG = {
|
|
10
|
+
sm: {
|
|
11
|
+
outer: "size-10",
|
|
12
|
+
middle: "size-7",
|
|
13
|
+
inner: "size-5",
|
|
14
|
+
dot: "size-2"
|
|
15
|
+
},
|
|
16
|
+
md: {
|
|
17
|
+
outer: "size-14",
|
|
18
|
+
middle: "size-10",
|
|
19
|
+
inner: "size-7",
|
|
20
|
+
dot: "size-2.5"
|
|
21
|
+
},
|
|
22
|
+
lg: {
|
|
23
|
+
outer: "size-20",
|
|
24
|
+
middle: "size-14",
|
|
25
|
+
inner: "size-10",
|
|
26
|
+
dot: "size-3.5"
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
function MapMarker({
|
|
30
|
+
size = "md",
|
|
31
|
+
isSelected = false,
|
|
32
|
+
dotColor,
|
|
33
|
+
innerRingColor,
|
|
34
|
+
middleRingColor,
|
|
35
|
+
outerRingColor,
|
|
36
|
+
className,
|
|
37
|
+
onClick,
|
|
38
|
+
interactive = true,
|
|
39
|
+
"aria-label": ariaLabel = "Map location marker"
|
|
40
|
+
}) {
|
|
41
|
+
const sizeConfig = SIZE_CONFIG[size];
|
|
42
|
+
const content = /* @__PURE__ */ jsxs(
|
|
43
|
+
"div",
|
|
44
|
+
{
|
|
45
|
+
className: cn(
|
|
46
|
+
"relative flex items-center justify-center rounded-full transition-transform duration-200",
|
|
47
|
+
sizeConfig.outer,
|
|
48
|
+
isSelected && "scale-110",
|
|
49
|
+
className
|
|
50
|
+
),
|
|
51
|
+
style: { backgroundColor: outerRingColor },
|
|
52
|
+
children: [
|
|
53
|
+
/* @__PURE__ */ jsx(
|
|
54
|
+
"div",
|
|
55
|
+
{
|
|
56
|
+
className: cn(
|
|
57
|
+
"absolute rounded-full transition-all duration-200",
|
|
58
|
+
sizeConfig.middle
|
|
59
|
+
),
|
|
60
|
+
style: { backgroundColor: middleRingColor }
|
|
61
|
+
}
|
|
62
|
+
),
|
|
63
|
+
/* @__PURE__ */ jsx(
|
|
64
|
+
"div",
|
|
65
|
+
{
|
|
66
|
+
className: cn(
|
|
67
|
+
"absolute rounded-full transition-all duration-200",
|
|
68
|
+
sizeConfig.inner
|
|
69
|
+
),
|
|
70
|
+
style: { backgroundColor: innerRingColor }
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
/* @__PURE__ */ jsx(
|
|
74
|
+
"div",
|
|
75
|
+
{
|
|
76
|
+
className: cn(
|
|
77
|
+
"absolute rounded-full transition-all duration-200",
|
|
78
|
+
sizeConfig.dot
|
|
79
|
+
),
|
|
80
|
+
style: { backgroundColor: dotColor }
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
if (!interactive) {
|
|
87
|
+
return content;
|
|
88
|
+
}
|
|
89
|
+
return /* @__PURE__ */ jsx(
|
|
90
|
+
"button",
|
|
91
|
+
{
|
|
92
|
+
type: "button",
|
|
93
|
+
className: "group cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-full",
|
|
94
|
+
onClick,
|
|
95
|
+
"aria-label": ariaLabel,
|
|
96
|
+
children: /* @__PURE__ */ jsx(
|
|
97
|
+
"div",
|
|
98
|
+
{
|
|
99
|
+
className: cn(
|
|
100
|
+
"transition-transform duration-200 group-hover:scale-110",
|
|
101
|
+
isSelected && "scale-110"
|
|
102
|
+
),
|
|
103
|
+
children: content
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
function NeutralMapMarker(props) {
|
|
110
|
+
return /* @__PURE__ */ jsx(
|
|
111
|
+
MapMarker,
|
|
112
|
+
{
|
|
113
|
+
...props,
|
|
114
|
+
dotColor: "hsl(var(--neutral-900, 0 0% 9%))",
|
|
115
|
+
innerRingColor: "hsl(var(--neutral-400, 0 0% 64%))",
|
|
116
|
+
middleRingColor: "hsl(var(--neutral-300, 0 0% 78%))",
|
|
117
|
+
outerRingColor: "hsl(var(--neutral-200, 0 0% 88%))"
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
function createMapMarkerElement(config) {
|
|
122
|
+
return function MarkerElement({ isSelected }) {
|
|
123
|
+
return /* @__PURE__ */ jsx(MapMarker, { ...config, isSelected, interactive: false });
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
var map_marker_default = MapMarker;
|
|
127
|
+
|
|
128
|
+
export { MapMarker, NeutralMapMarker, createMapMarkerElement, map_marker_default as default };
|
|
129
|
+
//# sourceMappingURL=map-marker.js.map
|
|
130
|
+
//# sourceMappingURL=map-marker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/cn.ts","../../src/components/map-marker.tsx"],"names":[],"mappings":"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","file":"map-marker.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Utility function to merge Tailwind CSS classes with proper conflict resolution.\n * Uses clsx for conditional class names and tailwind-merge for deduplication.\n *\n * @param inputs - Class names to merge\n * @returns Merged class string\n *\n * @example\n * cn(\"px-2 py-1\", \"px-4\") // => \"py-1 px-4\"\n * cn(\"text-red-500\", condition && \"text-blue-500\") // => \"text-blue-500\" (if condition is true)\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type MapMarkerSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface MapMarkerProps {\n /** Size variant of the marker */\n size?: MapMarkerSize;\n /** Whether the marker is currently selected/active */\n isSelected?: boolean;\n /** Custom color for the center dot (defaults to neutral-900) */\n dotColor?: string;\n /** Custom color for the inner ring (defaults to neutral-400) */\n innerRingColor?: string;\n /** Custom color for the middle ring (defaults to neutral-300) */\n middleRingColor?: string;\n /** Custom color for the outer ring (defaults to neutral-200) */\n outerRingColor?: string;\n /** Additional class name for the wrapper */\n className?: string;\n /** Click handler for the marker */\n onClick?: (event: React.MouseEvent) => void;\n /** Whether the marker is interactive/clickable */\n interactive?: boolean;\n /** Accessible label for the marker */\n \"aria-label\"?: string;\n}\n\nconst SIZE_CONFIG: Record<\n MapMarkerSize,\n {\n outer: string;\n middle: string;\n inner: string;\n dot: string;\n }\n> = {\n sm: {\n outer: \"size-10\",\n middle: \"size-7\",\n inner: \"size-5\",\n dot: \"size-2\",\n },\n md: {\n outer: \"size-14\",\n middle: \"size-10\",\n inner: \"size-7\",\n dot: \"size-2.5\",\n },\n lg: {\n outer: \"size-20\",\n middle: \"size-14\",\n inner: \"size-10\",\n dot: \"size-3.5\",\n },\n};\n\n/**\n * A reusable map marker component with concentric circle design.\n * Can be used directly with MapLibre markers via the `element` prop.\n *\n * @example\n * // Basic usage\n * <MapMarker />\n *\n * @example\n * // With MapLibre GeoMap\n * const markers = [{\n * id: 'location-1',\n * latitude: 40.7128,\n * longitude: -74.0060,\n * markerElement: ({ isSelected }) => (\n * <MapMarker isSelected={isSelected} size=\"md\" />\n * ),\n * }];\n *\n * @example\n * // Custom colors\n * <MapMarker\n * dotColor=\"#1E40AF\"\n * innerRingColor=\"#3B82F6\"\n * middleRingColor=\"#93C5FD\"\n * outerRingColor=\"#DBEAFE\"\n * />\n */\nexport function MapMarker({\n size = \"md\",\n isSelected = false,\n dotColor,\n innerRingColor,\n middleRingColor,\n outerRingColor,\n className,\n onClick,\n interactive = true,\n \"aria-label\": ariaLabel = \"Map location marker\",\n}: MapMarkerProps) {\n const sizeConfig = SIZE_CONFIG[size];\n\n const content = (\n <div\n className={cn(\n \"relative flex items-center justify-center rounded-full transition-transform duration-200\",\n sizeConfig.outer,\n isSelected && \"scale-110\",\n className\n )}\n style={{ backgroundColor: outerRingColor }}\n >\n {/* Middle ring */}\n <div\n className={cn(\n \"absolute rounded-full transition-all duration-200\",\n sizeConfig.middle\n )}\n style={{ backgroundColor: middleRingColor }}\n />\n\n {/* Inner ring */}\n <div\n className={cn(\n \"absolute rounded-full transition-all duration-200\",\n sizeConfig.inner\n )}\n style={{ backgroundColor: innerRingColor }}\n />\n\n {/* Center dot */}\n <div\n className={cn(\n \"absolute rounded-full transition-all duration-200\",\n sizeConfig.dot\n )}\n style={{ backgroundColor: dotColor }}\n />\n </div>\n );\n\n if (!interactive) {\n return content;\n }\n\n return (\n <button\n type=\"button\"\n className=\"group cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-full\"\n onClick={onClick}\n aria-label={ariaLabel}\n >\n <div\n className={cn(\n \"transition-transform duration-200 group-hover:scale-110\",\n isSelected && \"scale-110\"\n )}\n >\n {content}\n </div>\n </button>\n );\n}\n\n/**\n * Pre-configured marker with neutral gray colors matching the reference design.\n */\nexport function NeutralMapMarker(\n props: Omit<\n MapMarkerProps,\n \"dotColor\" | \"innerRingColor\" | \"middleRingColor\" | \"outerRingColor\"\n >\n) {\n return (\n <MapMarker\n {...props}\n dotColor=\"hsl(var(--neutral-900, 0 0% 9%))\"\n innerRingColor=\"hsl(var(--neutral-400, 0 0% 64%))\"\n middleRingColor=\"hsl(var(--neutral-300, 0 0% 78%))\"\n outerRingColor=\"hsl(var(--neutral-200, 0 0% 88%))\"\n />\n );\n}\n\n/**\n * Factory function to create a marker element for use with MapLibre/GeoMap.\n * Returns a function compatible with the `markerElement` prop.\n *\n * @example\n * const markers = [{\n * id: 'location-1',\n * latitude: 40.7128,\n * longitude: -74.0060,\n * markerElement: createMapMarkerElement({ size: 'lg' }),\n * }];\n */\nexport function createMapMarkerElement(\n config?: Omit<MapMarkerProps, \"isSelected\" | \"onClick\">\n) {\n return function MarkerElement({ isSelected }: { isSelected: boolean }) {\n return <MapMarker {...config} isSelected={isSelected} interactive={false} />;\n };\n}\n\nexport default MapMarker;\n"]}
|