@zekidev/ui 2.1.0 → 2.2.0

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.
@@ -45,6 +45,14 @@ export interface SectionBase {
45
45
  paddingTop?: "none" | "sm" | "md" | "lg" | "xl";
46
46
  paddingBottom?: "none" | "sm" | "md" | "lg" | "xl";
47
47
  background?: "default" | "muted" | "primary" | "secondary" | "success" | "info" | "warning" | "error";
48
+ /** Decorative background image (shown behind section content) */
49
+ backgroundImage?: MediaAsset;
50
+ /** Direct URL to a .mp4 file. Not played on mobile. */
51
+ backgroundVideoUrl?: string;
52
+ /** 0–100 opacity of a dark overlay on top of background media */
53
+ backgroundOverlay?: number;
54
+ /** Fade-in entrance animation triggered on scroll */
55
+ animate?: boolean;
48
56
  }
49
57
  export type HeroVariant = "centered" | "split" | "left" | "video" | "minimal" | "background" | "card";
50
58
  export interface HeroSection extends SectionBase {
@@ -407,15 +415,18 @@ export interface BackgroundMusic {
407
415
  */
408
416
  autoplayOnInteraction?: boolean;
409
417
  }
418
+ export type NotFoundVariant = "centered" | "split" | "minimal";
410
419
  export interface SiteSettings {
411
420
  _id: string;
412
421
  _type: "siteSettings";
413
422
  siteName: string;
414
423
  logo?: MediaAsset;
424
+ favicon?: MediaAsset;
415
425
  theme: SiteTheme;
416
426
  headerVariant?: HeaderVariant;
417
427
  footerVariant?: FooterVariant;
418
428
  layoutVariant?: LayoutVariant;
429
+ notFoundVariant?: NotFoundVariant;
419
430
  navigation?: {
420
431
  links: {
421
432
  label: string;
package/package.json CHANGED
@@ -1,43 +1,26 @@
1
1
  {
2
2
  "name": "@zekidev/ui",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
7
- "types": "./src/index.ts",
8
- "import": "./src/index.ts",
9
- "default": "./src/index.ts"
7
+ "types": "./dist/index.d.ts",
8
+ "import": "./dist/index.js",
9
+ "require": "./dist/index.cjs",
10
+ "default": "./dist/index.js"
10
11
  },
11
12
  "./styles": "./src/styles/globals.css",
12
13
  "./tailwind-config": "./tailwind.config.ts"
13
14
  },
14
- "main": "./src/index.ts",
15
- "types": "./src/index.ts",
15
+ "main": "./dist/index.cjs",
16
+ "types": "./dist/index.d.ts",
16
17
  "files": [
17
18
  "dist",
18
19
  "src/styles",
19
20
  "tailwind.config.ts"
20
21
  ],
21
22
  "publishConfig": {
22
- "access": "public",
23
- "exports": {
24
- ".": {
25
- "types": "./dist/index.d.ts",
26
- "import": "./dist/index.js",
27
- "default": "./dist/index.js"
28
- },
29
- "./styles": "./src/styles/globals.css",
30
- "./tailwind-config": "./tailwind.config.ts"
31
- },
32
- "main": "./dist/index.js",
33
- "module": "./dist/index.js",
34
- "types": "./dist/index.d.ts"
35
- },
36
- "scripts": {
37
- "build": "tsup && tsc -p tsconfig.build.json",
38
- "dev": "tsup --watch",
39
- "type-check": "tsc --noEmit",
40
- "lint": "eslint src --ext ts,tsx"
23
+ "access": "public"
41
24
  },
42
25
  "dependencies": {
43
26
  "@portabletext/react": "^3.0.0",
@@ -73,5 +56,12 @@
73
56
  "tailwindcss": "^3.4.0",
74
57
  "tsup": "^8.0.0",
75
58
  "typescript": "^5.4.0"
76
- }
77
- }
59
+ },
60
+ "scripts": {
61
+ "build": "tsup && tsc -p tsconfig.build.json",
62
+ "dev": "tsup --watch",
63
+ "type-check": "tsc --noEmit",
64
+ "lint": "eslint src --ext ts,tsx"
65
+ },
66
+ "module": "./dist/index.js"
67
+ }
@@ -73,7 +73,7 @@
73
73
  --input: 214.3 31.8% 91.4%;
74
74
  --ring: 221.2 83.2% 53.3%;
75
75
  }
76
- .dark [data-palette="default"],
76
+ .dark[data-palette="default"],
77
77
  .dark:not([data-palette]) {
78
78
  --background: 222.2 84% 4.9%;
79
79
  --foreground: 210 40% 98%;
@@ -118,7 +118,7 @@
118
118
  --input: 240 5.9% 90%;
119
119
  --ring: 346.8 77.2% 49.8%;
120
120
  }
121
- .dark [data-palette="rose"] {
121
+ .dark[data-palette="rose"] {
122
122
  --background: 20 14.3% 4.1%;
123
123
  --foreground: 0 0% 95%;
124
124
  --card: 24 9.8% 10%;
@@ -162,7 +162,7 @@
162
162
  --input: 20 5.9% 90%;
163
163
  --ring: 24.6 95% 53.1%;
164
164
  }
165
- .dark [data-palette="orange"] {
165
+ .dark[data-palette="orange"] {
166
166
  --background: 20 14.3% 4.1%;
167
167
  --foreground: 60 9.1% 97.8%;
168
168
  --card: 20 14.3% 4.1%;
@@ -206,7 +206,7 @@
206
206
  --input: 240 5.9% 90%;
207
207
  --ring: 142.1 76.2% 36.3%;
208
208
  }
209
- .dark [data-palette="green"] {
209
+ .dark[data-palette="green"] {
210
210
  --background: 20 14.3% 4.1%;
211
211
  --foreground: 0 0% 95%;
212
212
  --card: 24 9.8% 10%;
@@ -250,7 +250,7 @@
250
250
  --input: 220 13% 91%;
251
251
  --ring: 262.1 83.3% 57.8%;
252
252
  }
253
- .dark [data-palette="violet"] {
253
+ .dark[data-palette="violet"] {
254
254
  --background: 224 71.4% 4.1%;
255
255
  --foreground: 210 20% 98%;
256
256
  --card: 224 71.4% 4.1%;
@@ -294,7 +294,7 @@
294
294
  --input: 214.3 31.8% 91.4%;
295
295
  --ring: 173 80% 36%;
296
296
  }
297
- .dark [data-palette="teal"] {
297
+ .dark[data-palette="teal"] {
298
298
  --background: 222.2 84% 4.9%;
299
299
  --foreground: 210 40% 98%;
300
300
  --card: 222.2 84% 4.9%;
@@ -338,7 +338,7 @@
338
338
  --input: 20 5.9% 90%;
339
339
  --ring: 47.9 95.8% 53.1%;
340
340
  }
341
- .dark [data-palette="yellow"] {
341
+ .dark[data-palette="yellow"] {
342
342
  --background: 20 14.3% 4.1%;
343
343
  --foreground: 60 9.1% 97.8%;
344
344
  --card: 20 14.3% 4.1%;
@@ -382,7 +382,7 @@
382
382
  --input: 240 5.9% 90%;
383
383
  --ring: 0 72.2% 50.6%;
384
384
  }
385
- .dark [data-palette="red"] {
385
+ .dark[data-palette="red"] {
386
386
  --background: 20 14.3% 4.1%;
387
387
  --foreground: 0 0% 95%;
388
388
  --card: 24 9.8% 10%;
@@ -1,171 +0,0 @@
1
- "use client";
2
-
3
- // src/sections/map/leaflet-map-inner.tsx
4
- import "leaflet/dist/leaflet.css";
5
- import { useEffect, useRef, useState } from "react";
6
- import L from "leaflet";
7
- import { jsx, jsxs } from "react/jsx-runtime";
8
- var OSM_ATTR = '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
9
- var CARTO_ATTR = `${OSM_ATTR} &copy; <a href="https://carto.com/attributions">CARTO</a>`;
10
- var ESRI_ATTR = "Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community";
11
- var TILES = {
12
- // OpenStreetMap
13
- standard: {
14
- url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
15
- attribution: OSM_ATTR
16
- },
17
- // CartoDB Positron — clean, minimal, ideal for data overlays
18
- light: {
19
- url: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",
20
- attribution: CARTO_ATTR
21
- },
22
- // CartoDB Dark Matter
23
- dark: {
24
- url: "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",
25
- attribution: CARTO_ATTR
26
- },
27
- // CartoDB Voyager — colorful, modern
28
- voyager: {
29
- url: "https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png",
30
- attribution: CARTO_ATTR
31
- },
32
- // OpenTopoMap — topographic with elevation contours
33
- topo: {
34
- url: "https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",
35
- attribution: `${OSM_ATTR}, <a href="https://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a>`,
36
- maxZoom: 17
37
- },
38
- // ESRI World Imagery — satellite/aerial photography
39
- satellite: {
40
- url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
41
- attribution: ESRI_ATTR,
42
- maxZoom: 18
43
- },
44
- // ESRI World Street Map — detailed street basemap
45
- streets: {
46
- url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}",
47
- attribution: ESRI_ATTR,
48
- maxZoom: 18
49
- }
50
- };
51
- var markerIcon = new L.Icon({
52
- iconUrl: "https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png",
53
- iconRetinaUrl: "https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png",
54
- shadowUrl: "https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png",
55
- iconSize: [25, 41],
56
- iconAnchor: [12, 41],
57
- popupAnchor: [1, -34],
58
- shadowSize: [41, 41]
59
- });
60
- async function geocodeAddress(address) {
61
- try {
62
- const res = await fetch(
63
- `https://nominatim.openstreetmap.org/search?format=json&limit=1&q=${encodeURIComponent(address)}`,
64
- { headers: { "Accept-Language": "en", "User-Agent": "LandingBuilder/1.0" } }
65
- );
66
- if (!res.ok) return null;
67
- const data = await res.json();
68
- if (!data.length) return null;
69
- return [parseFloat(data[0].lat), parseFloat(data[0].lon)];
70
- } catch {
71
- return null;
72
- }
73
- }
74
- async function geocodeAll(locations) {
75
- const result = [];
76
- for (const loc of locations) {
77
- if (loc.lat != null && loc.lng != null) {
78
- result.push({ ...loc, coords: [loc.lat, loc.lng] });
79
- continue;
80
- }
81
- if (loc.address) {
82
- const coords = await geocodeAddress(loc.address);
83
- if (coords) result.push({ ...loc, coords });
84
- await new Promise((r) => setTimeout(r, 1e3));
85
- }
86
- }
87
- return result;
88
- }
89
- function buildPopup(loc) {
90
- const parts = [];
91
- parts.push(`<strong style="display:block;font-size:13px">${loc.name}</strong>`);
92
- if (loc.address)
93
- parts.push(`<span style="display:block;font-size:11px;color:#6b7280;margin-top:2px">${loc.address}</span>`);
94
- if (loc.phone)
95
- parts.push(`<span style="display:block;font-size:11px;margin-top:2px">${loc.phone}</span>`);
96
- if (loc.hours)
97
- parts.push(`<span style="display:block;font-size:11px;color:#6b7280;margin-top:2px">${loc.hours}</span>`);
98
- if (loc.address)
99
- parts.push(
100
- `<a href="https://maps.google.com/?q=${encodeURIComponent(loc.address)}" target="_blank" rel="noopener noreferrer" style="display:block;font-size:11px;color:#2563eb;margin-top:4px">Ver en Google Maps \u2192</a>`
101
- );
102
- return parts.join("");
103
- }
104
- function LeafletMapInner({ locations, mapStyle = "standard", className }) {
105
- const containerRef = useRef(null);
106
- const mapRef = useRef(null);
107
- const tileRef = useRef(null);
108
- const [loading, setLoading] = useState(!!locations?.length);
109
- useEffect(() => {
110
- if (!containerRef.current || mapRef.current) return;
111
- const tile = TILES[mapStyle] ?? TILES.standard;
112
- const map = L.map(containerRef.current, { scrollWheelZoom: false });
113
- const tileLayer = L.tileLayer(tile.url, { attribution: tile.attribution, maxZoom: tile.maxZoom ?? 19 }).addTo(map);
114
- map.setView([20, 0], 2);
115
- mapRef.current = map;
116
- tileRef.current = tileLayer;
117
- return () => {
118
- map.remove();
119
- mapRef.current = null;
120
- tileRef.current = null;
121
- };
122
- }, []);
123
- useEffect(() => {
124
- if (!mapRef.current) return;
125
- const tile = TILES[mapStyle] ?? TILES.standard;
126
- tileRef.current?.remove();
127
- tileRef.current = L.tileLayer(tile.url, { attribution: tile.attribution, maxZoom: tile.maxZoom ?? 19 }).addTo(mapRef.current);
128
- }, [mapStyle]);
129
- useEffect(() => {
130
- if (!locations?.length) {
131
- setLoading(false);
132
- return;
133
- }
134
- let cancelled = false;
135
- setLoading(true);
136
- geocodeAll(locations).then((geocoded) => {
137
- if (cancelled || !mapRef.current) return;
138
- mapRef.current.eachLayer((layer) => {
139
- if (layer instanceof L.Marker) layer.remove();
140
- });
141
- geocoded.forEach((loc) => {
142
- L.marker(loc.coords, { icon: markerIcon }).addTo(mapRef.current).bindPopup(buildPopup(loc));
143
- });
144
- if (geocoded.length === 1) {
145
- mapRef.current.setView(geocoded[0].coords, 14);
146
- } else if (geocoded.length > 1) {
147
- mapRef.current.fitBounds(
148
- geocoded.map((l) => l.coords),
149
- { padding: [48, 48] }
150
- );
151
- }
152
- setLoading(false);
153
- });
154
- return () => {
155
- cancelled = true;
156
- };
157
- }, [locations]);
158
- return /* @__PURE__ */ jsxs("div", { className: `relative ${className ?? ""}`, children: [
159
- loading && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-[1000] flex items-center justify-center bg-muted/80 rounded-xl", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 text-muted-foreground text-sm", children: [
160
- /* @__PURE__ */ jsxs("svg", { className: "animate-spin h-6 w-6", viewBox: "0 0 24 24", fill: "none", children: [
161
- /* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
162
- /* @__PURE__ */ jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" })
163
- ] }),
164
- "Geocoding addresses\u2026"
165
- ] }) }),
166
- /* @__PURE__ */ jsx("div", { ref: containerRef, style: { height: "100%", width: "100%" } })
167
- ] });
168
- }
169
- export {
170
- LeafletMapInner
171
- };