dune-react 0.0.16 → 0.0.19
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/dist/components/puck-base/core/fields.d.ts +23 -0
- package/dist/components/puck-base/core/fields.js +24 -15
- package/dist/components/puck-base/core/styles.d.ts +1 -5
- package/dist/components/puck-base/core/styles.js +1 -5
- package/dist/components/puck-base/core/with-editable.js +2 -2
- package/dist/components/puck-base/editor-context.d.ts +2 -0
- package/dist/components/puck-base/fields/index.d.ts +1 -0
- package/dist/components/puck-base/fields/location-field.d.ts +44 -0
- package/dist/components/puck-base/fields/location-field.js +207 -0
- package/dist/components/puck-block/hero-sections/fullscreen-hero-1/fullscreen-hero.d.ts +3 -3
- package/dist/components/puck-block/hero-sections/fullscreen-hero-1/fullscreen-hero.js +57 -11
- package/dist/components/puck-block/hero-sections/fullscreen-hero-1/index.js +4 -4
- package/dist/components/puck-block/hero-sections/image-hero-1/image-hero.d.ts +3 -3
- package/dist/components/puck-block/hero-sections/image-hero-1/image-hero.js +4 -3
- package/dist/components/puck-block/hero-sections/image-hero-1/index.js +3 -10
- package/dist/components/puck-block/hero-sections/props.d.ts +1 -3
- package/dist/components/puck-block/hero-sections/video-hero-1/index.js +3 -3
- package/dist/components/puck-block/hero-sections/video-hero-1/video-hero.d.ts +4 -4
- package/dist/components/puck-block/hero-sections/video-hero-1/video-hero.js +32 -29
- package/dist/components/puck-block/location-sections/location-1/index.js +17 -22
- package/dist/components/puck-block/location-sections/location-1/location.d.ts +5 -7
- package/dist/components/puck-block/location-sections/location-1/location.js +15 -12
- package/dist/components/puck-block/location-sections/location-2/index.js +28 -24
- package/dist/components/puck-block/location-sections/location-2/location.d.ts +6 -8
- package/dist/components/puck-block/location-sections/location-2/location.js +18 -15
- package/dist/components/puck-block/location-sections/location-3/index.js +43 -20
- package/dist/components/puck-block/location-sections/location-3/location.d.ts +5 -6
- package/dist/components/puck-block/location-sections/location-3/location.js +96 -86
- package/dist/components/puck-block/location-sections/props.d.ts +9 -10
- package/package.json +3 -2
|
@@ -801,4 +801,27 @@ export declare const form: {
|
|
|
801
801
|
};
|
|
802
802
|
};
|
|
803
803
|
export declare const formDefaults: CompoundFormProps;
|
|
804
|
+
/** 地图定位的核心数据:地址 + 坐标 */
|
|
805
|
+
export interface MapLocation {
|
|
806
|
+
/** 用户可读的完整地址(显示 & 搜索用) */
|
|
807
|
+
address: string;
|
|
808
|
+
/** 纬度 */
|
|
809
|
+
lat: number;
|
|
810
|
+
/** 经度 */
|
|
811
|
+
lng: number;
|
|
812
|
+
/** 地图缩放级别,默认 14 */
|
|
813
|
+
zoom?: number;
|
|
814
|
+
/** Google Place ID(可选,便于精确定位) */
|
|
815
|
+
placeId?: string;
|
|
816
|
+
}
|
|
817
|
+
/** 从 MapLocation 生成 Google Maps embed URL */
|
|
818
|
+
export declare function getMapEmbedUrl(loc: MapLocation): string;
|
|
819
|
+
/** 从 MapLocation 生成 Google Maps 导航 URL */
|
|
820
|
+
export declare function getDirectionsUrl(loc: MapLocation): string;
|
|
821
|
+
export declare const locationDefaults: MapLocation;
|
|
822
|
+
export declare const location: {
|
|
823
|
+
type: "custom";
|
|
824
|
+
label: string;
|
|
825
|
+
render: any;
|
|
826
|
+
};
|
|
804
827
|
export * from "./styles";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { fieldTypes } from "../field.js";
|
|
2
2
|
import { ActionField } from "../fields/action-field.js";
|
|
3
3
|
import { IconPickerField } from "../icon-picker-field.js";
|
|
4
|
-
import {
|
|
4
|
+
import { LocationField } from "../fields/location-field.js";
|
|
5
5
|
const formMethods = ["get", "post", "put", "patch", "delete"];
|
|
6
6
|
const icon = {
|
|
7
7
|
type: "custom",
|
|
@@ -241,42 +241,51 @@ const formDefaults = {
|
|
|
241
241
|
icon: "move-right"
|
|
242
242
|
}
|
|
243
243
|
};
|
|
244
|
+
function getMapEmbedUrl(loc) {
|
|
245
|
+
const { lat, lng, zoom = 14 } = loc;
|
|
246
|
+
return `https://maps.google.com/maps?q=${lat},${lng}&z=${zoom}&output=embed`;
|
|
247
|
+
}
|
|
248
|
+
function getDirectionsUrl(loc) {
|
|
249
|
+
return `https://www.google.com/maps/dir/?api=1&destination=${loc.lat},${loc.lng}`;
|
|
250
|
+
}
|
|
251
|
+
const locationDefaults = {
|
|
252
|
+
address: "San Francisco, CA, USA",
|
|
253
|
+
lat: 37.7749,
|
|
254
|
+
lng: -122.4194,
|
|
255
|
+
zoom: 13
|
|
256
|
+
};
|
|
257
|
+
const location = {
|
|
258
|
+
type: "custom",
|
|
259
|
+
label: "Location",
|
|
260
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
261
|
+
render: LocationField
|
|
262
|
+
};
|
|
244
263
|
export {
|
|
245
264
|
action,
|
|
246
265
|
actionDefaults,
|
|
247
|
-
backgroundColor,
|
|
248
|
-
backgroundImage,
|
|
249
266
|
badge,
|
|
250
|
-
bannerStylesDefaults,
|
|
251
|
-
bannerStylesField,
|
|
252
267
|
button,
|
|
253
268
|
buttons,
|
|
254
269
|
card,
|
|
255
270
|
cards,
|
|
256
271
|
contentFields,
|
|
257
272
|
contentFieldsWithFeatures,
|
|
258
|
-
createStylesDefaults,
|
|
259
|
-
createStylesField,
|
|
260
273
|
description,
|
|
261
274
|
features,
|
|
262
275
|
field,
|
|
263
276
|
fieldDefaults,
|
|
264
277
|
form,
|
|
265
278
|
formDefaults,
|
|
279
|
+
getDirectionsUrl,
|
|
280
|
+
getMapEmbedUrl,
|
|
266
281
|
getPlaceholderImageUrl,
|
|
267
282
|
heading,
|
|
268
|
-
heroStylesDefaults,
|
|
269
283
|
icon,
|
|
270
284
|
image,
|
|
271
285
|
image16x9Placeholder,
|
|
272
286
|
image1x1Placeholder,
|
|
273
287
|
image9x16Placeholder,
|
|
274
288
|
images,
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
paddingLevel,
|
|
278
|
-
sectionBaseStyleDefaults,
|
|
279
|
-
sectionBaseStyleFields,
|
|
280
|
-
sectionOverlay,
|
|
281
|
-
sectionStyle
|
|
289
|
+
location,
|
|
290
|
+
locationDefaults
|
|
282
291
|
};
|
|
@@ -1394,11 +1394,7 @@ export declare const contactStylesDefaults: {
|
|
|
1394
1394
|
readonly bottom: "medium";
|
|
1395
1395
|
};
|
|
1396
1396
|
};
|
|
1397
|
-
export
|
|
1398
|
-
mapHeight?: number;
|
|
1399
|
-
mapFilter?: string;
|
|
1400
|
-
mapTintColor?: string;
|
|
1401
|
-
}
|
|
1397
|
+
export type LocationSectionStyles = SectionBaseStyles;
|
|
1402
1398
|
export declare const locationStylesField: {
|
|
1403
1399
|
type: "object";
|
|
1404
1400
|
label: string;
|
|
@@ -216,11 +216,7 @@ createStylesField({
|
|
|
216
216
|
}
|
|
217
217
|
});
|
|
218
218
|
createStylesDefaults();
|
|
219
|
-
createStylesField(
|
|
220
|
-
mapHeight: { type: "number", label: "Map Height", min: 200, max: 800 },
|
|
221
|
-
mapFilter: { type: "text", label: "Map Filter (CSS)" },
|
|
222
|
-
mapTintColor: { type: "text", label: "Map Tint Color" }
|
|
223
|
-
});
|
|
219
|
+
createStylesField();
|
|
224
220
|
createStylesDefaults();
|
|
225
221
|
createStylesField();
|
|
226
222
|
createStylesDefaults();
|
|
@@ -70,7 +70,7 @@ function withEditable(Component, config) {
|
|
|
70
70
|
if (isBlock) {
|
|
71
71
|
return /* @__PURE__ */ jsxs("span", { ref: wrapperRef, className: "group relative block h-full w-full", children: [
|
|
72
72
|
/* @__PURE__ */ jsx(Component, { ...props }),
|
|
73
|
-
/* @__PURE__ */ jsx("span", { className: "absolute inset-0 z-
|
|
73
|
+
/* @__PURE__ */ jsx("span", { className: "absolute inset-0 z-60 flex items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
74
74
|
"span",
|
|
75
75
|
{
|
|
76
76
|
ref: portalRef,
|
|
@@ -84,7 +84,7 @@ function withEditable(Component, config) {
|
|
|
84
84
|
}
|
|
85
85
|
return /* @__PURE__ */ jsxs("span", { ref: wrapperRef, className: "group relative inline-flex", children: [
|
|
86
86
|
/* @__PURE__ */ jsx(Component, { ...props }),
|
|
87
|
-
/* @__PURE__ */ jsx("span", { className: "absolute inset-0 z-
|
|
87
|
+
/* @__PURE__ */ jsx("span", { className: "absolute inset-0 z-60 flex items-center justify-center opacity-0 transition-opacity group-hover:opacity-100", children: /* @__PURE__ */ jsx(
|
|
88
88
|
"span",
|
|
89
89
|
{
|
|
90
90
|
onClick: handleEdit,
|
|
@@ -17,6 +17,8 @@ type EditorContextValue = {
|
|
|
17
17
|
domain?: string;
|
|
18
18
|
/** 站内可选页面列表,用于 url 字段快捷选择 */
|
|
19
19
|
sitePages?: SitePage[];
|
|
20
|
+
/** Google Maps API Key,用于 LocationField 地址搜索 */
|
|
21
|
+
googleMapsApiKey?: string;
|
|
20
22
|
};
|
|
21
23
|
export declare const EditorContextProvider: import("react").Provider<EditorContextValue>;
|
|
22
24
|
export declare const useEditorContext: () => EditorContextValue;
|
|
@@ -4,4 +4,5 @@ export { ColorField } from "./color-field";
|
|
|
4
4
|
export { RadioToggleField } from "./radio-toggle-field";
|
|
5
5
|
export { ObjectField } from "./object-field";
|
|
6
6
|
export { VirtualizedSelectField, LARGE_SELECT_THRESHOLD, } from "./virtualized-select-field";
|
|
7
|
+
export { LocationField } from "./location-field";
|
|
7
8
|
export { ActionField, ACTION_TYPE_FIELD_MAP, ACTION_TYPE_OPTIONS, PageActionFields, ExternalActionFields, EmailActionFields, PhoneActionFields, SectionActionFields, DownloadActionFields, type ActionTypeFieldProps, } from "./action-field";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { MapLocation } from "../core/fields";
|
|
2
|
+
interface GLatLng {
|
|
3
|
+
lat(): number;
|
|
4
|
+
lng(): number;
|
|
5
|
+
}
|
|
6
|
+
interface GGeometry {
|
|
7
|
+
location?: GLatLng;
|
|
8
|
+
}
|
|
9
|
+
interface GPlaceResult {
|
|
10
|
+
formatted_address?: string;
|
|
11
|
+
geometry?: GGeometry;
|
|
12
|
+
place_id?: string;
|
|
13
|
+
address_components?: unknown[];
|
|
14
|
+
}
|
|
15
|
+
interface GAutocomplete {
|
|
16
|
+
getPlace(): GPlaceResult;
|
|
17
|
+
addListener(event: string, handler: () => void): void;
|
|
18
|
+
}
|
|
19
|
+
interface GAutocompleteConstructor {
|
|
20
|
+
new (input: HTMLInputElement, opts?: Record<string, unknown>): GAutocomplete;
|
|
21
|
+
}
|
|
22
|
+
interface GGoogleMaps {
|
|
23
|
+
places: {
|
|
24
|
+
Autocomplete: GAutocompleteConstructor;
|
|
25
|
+
};
|
|
26
|
+
event: {
|
|
27
|
+
clearInstanceListeners(instance: unknown): void;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
interface GGoogle {
|
|
31
|
+
maps: GGoogleMaps;
|
|
32
|
+
}
|
|
33
|
+
declare global {
|
|
34
|
+
interface Window {
|
|
35
|
+
google?: GGoogle;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export interface LocationFieldProps {
|
|
39
|
+
name: string;
|
|
40
|
+
value: MapLocation | undefined;
|
|
41
|
+
onChange: (value: MapLocation) => void;
|
|
42
|
+
}
|
|
43
|
+
export declare const LocationField: import("react").NamedExoticComponent<LocationFieldProps>;
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
|
+
import { memo, useState, useRef, useEffect, useCallback } from "react";
|
|
4
|
+
import { Input } from "../../shadcn/input.js";
|
|
5
|
+
import { Label } from "../../shadcn/label.js";
|
|
6
|
+
import { Loader2, Search, X, MapPin } from "lucide-react";
|
|
7
|
+
import { useEditorContext } from "../editor-context.js";
|
|
8
|
+
let googleLoadPromise = null;
|
|
9
|
+
function loadGooglePlaces(apiKey) {
|
|
10
|
+
var _a, _b;
|
|
11
|
+
if (googleLoadPromise) return googleLoadPromise;
|
|
12
|
+
if (typeof window !== "undefined" && ((_b = (_a = window.google) == null ? void 0 : _a.maps) == null ? void 0 : _b.places)) {
|
|
13
|
+
return Promise.resolve();
|
|
14
|
+
}
|
|
15
|
+
googleLoadPromise = new Promise((resolve, reject) => {
|
|
16
|
+
const script = document.createElement("script");
|
|
17
|
+
script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places`;
|
|
18
|
+
script.async = true;
|
|
19
|
+
script.onload = () => resolve();
|
|
20
|
+
script.onerror = () => {
|
|
21
|
+
googleLoadPromise = null;
|
|
22
|
+
reject(new Error("Failed to load Google Maps API"));
|
|
23
|
+
};
|
|
24
|
+
document.head.appendChild(script);
|
|
25
|
+
});
|
|
26
|
+
return googleLoadPromise;
|
|
27
|
+
}
|
|
28
|
+
const LocationField = memo(function LocationField2({
|
|
29
|
+
value,
|
|
30
|
+
onChange
|
|
31
|
+
}) {
|
|
32
|
+
const { googleMapsApiKey } = useEditorContext();
|
|
33
|
+
const apiKey = googleMapsApiKey || "";
|
|
34
|
+
const [inputValue, setInputValue] = useState((value == null ? void 0 : value.address) || "");
|
|
35
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
36
|
+
const [loadError, setLoadError] = useState(false);
|
|
37
|
+
const inputRef = useRef(null);
|
|
38
|
+
const autocompleteRef = useRef(null);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if ((value == null ? void 0 : value.address) && value.address !== inputValue) {
|
|
41
|
+
setInputValue(value.address);
|
|
42
|
+
}
|
|
43
|
+
}, [value == null ? void 0 : value.address]);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (!apiKey) {
|
|
46
|
+
setLoadError(true);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
loadGooglePlaces(apiKey).then(() => setIsLoaded(true)).catch(() => setLoadError(true));
|
|
50
|
+
}, [apiKey]);
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
if (!isLoaded || !inputRef.current || autocompleteRef.current) return;
|
|
53
|
+
const G = window.google;
|
|
54
|
+
const autocomplete = new G.maps.places.Autocomplete(inputRef.current, {
|
|
55
|
+
fields: [
|
|
56
|
+
"formatted_address",
|
|
57
|
+
"geometry",
|
|
58
|
+
"place_id",
|
|
59
|
+
"address_components"
|
|
60
|
+
]
|
|
61
|
+
});
|
|
62
|
+
autocomplete.addListener("place_changed", () => {
|
|
63
|
+
var _a;
|
|
64
|
+
const place = autocomplete.getPlace();
|
|
65
|
+
if (!((_a = place.geometry) == null ? void 0 : _a.location)) return;
|
|
66
|
+
const lat = place.geometry.location.lat();
|
|
67
|
+
const lng = place.geometry.location.lng();
|
|
68
|
+
const address = place.formatted_address || "";
|
|
69
|
+
const newLocation = {
|
|
70
|
+
address,
|
|
71
|
+
lat,
|
|
72
|
+
lng,
|
|
73
|
+
zoom: (value == null ? void 0 : value.zoom) ?? 14,
|
|
74
|
+
placeId: place.place_id || ""
|
|
75
|
+
};
|
|
76
|
+
setInputValue(address);
|
|
77
|
+
onChange(newLocation);
|
|
78
|
+
});
|
|
79
|
+
autocompleteRef.current = autocomplete;
|
|
80
|
+
return () => {
|
|
81
|
+
var _a;
|
|
82
|
+
(_a = window.google) == null ? void 0 : _a.maps.event.clearInstanceListeners(autocomplete);
|
|
83
|
+
autocompleteRef.current = null;
|
|
84
|
+
};
|
|
85
|
+
}, [isLoaded]);
|
|
86
|
+
const handleClear = useCallback(() => {
|
|
87
|
+
var _a;
|
|
88
|
+
setInputValue("");
|
|
89
|
+
onChange({
|
|
90
|
+
address: "",
|
|
91
|
+
lat: 0,
|
|
92
|
+
lng: 0,
|
|
93
|
+
zoom: 14,
|
|
94
|
+
placeId: ""
|
|
95
|
+
});
|
|
96
|
+
(_a = inputRef.current) == null ? void 0 : _a.focus();
|
|
97
|
+
}, [onChange]);
|
|
98
|
+
const handleZoomChange = useCallback(
|
|
99
|
+
(e) => {
|
|
100
|
+
if (!value) return;
|
|
101
|
+
onChange({ ...value, zoom: Number(e.target.value) });
|
|
102
|
+
},
|
|
103
|
+
[value, onChange]
|
|
104
|
+
);
|
|
105
|
+
const embedUrl = value && value.lat !== 0 ? `https://maps.google.com/maps?q=${value.lat},${value.lng}&z=${value.zoom ?? 14}&output=embed` : null;
|
|
106
|
+
return /* @__PURE__ */ jsxs("div", { className: "mb-4 space-y-3", children: [
|
|
107
|
+
/* @__PURE__ */ jsx(Label, { children: "Location" }),
|
|
108
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
109
|
+
/* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3", children: !isLoaded && !loadError ? /* @__PURE__ */ jsx(Loader2, { className: "text-muted-foreground size-4 animate-spin" }) : /* @__PURE__ */ jsx(Search, { className: "text-muted-foreground size-4" }) }),
|
|
110
|
+
/* @__PURE__ */ jsx(
|
|
111
|
+
Input,
|
|
112
|
+
{
|
|
113
|
+
ref: inputRef,
|
|
114
|
+
value: inputValue,
|
|
115
|
+
onChange: (e) => setInputValue(e.target.value),
|
|
116
|
+
placeholder: loadError ? "Enter address manually..." : "Search address or place...",
|
|
117
|
+
className: "pl-9 pr-8"
|
|
118
|
+
}
|
|
119
|
+
),
|
|
120
|
+
inputValue && /* @__PURE__ */ jsx(
|
|
121
|
+
"button",
|
|
122
|
+
{
|
|
123
|
+
type: "button",
|
|
124
|
+
onClick: handleClear,
|
|
125
|
+
className: "text-muted-foreground hover:text-foreground absolute inset-y-0 right-0 flex items-center pr-3",
|
|
126
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
] }),
|
|
130
|
+
loadError && /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
131
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
132
|
+
/* @__PURE__ */ jsx(Label, { className: "text-xs", children: "Latitude" }),
|
|
133
|
+
/* @__PURE__ */ jsx(
|
|
134
|
+
Input,
|
|
135
|
+
{
|
|
136
|
+
type: "number",
|
|
137
|
+
step: "any",
|
|
138
|
+
value: (value == null ? void 0 : value.lat) ?? "",
|
|
139
|
+
onChange: (e) => onChange({
|
|
140
|
+
...value || { address: "", lng: 0, zoom: 14 },
|
|
141
|
+
lat: Number(e.target.value)
|
|
142
|
+
}),
|
|
143
|
+
placeholder: "37.7749",
|
|
144
|
+
className: "h-8 text-xs"
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
] }),
|
|
148
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
149
|
+
/* @__PURE__ */ jsx(Label, { className: "text-xs", children: "Longitude" }),
|
|
150
|
+
/* @__PURE__ */ jsx(
|
|
151
|
+
Input,
|
|
152
|
+
{
|
|
153
|
+
type: "number",
|
|
154
|
+
step: "any",
|
|
155
|
+
value: (value == null ? void 0 : value.lng) ?? "",
|
|
156
|
+
onChange: (e) => onChange({
|
|
157
|
+
...value || { address: "", lat: 0, zoom: 14 },
|
|
158
|
+
lng: Number(e.target.value)
|
|
159
|
+
}),
|
|
160
|
+
placeholder: "-122.4194",
|
|
161
|
+
className: "h-8 text-xs"
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
] })
|
|
165
|
+
] }),
|
|
166
|
+
value && value.lat !== 0 && /* @__PURE__ */ jsxs("div", { className: "border-border bg-muted/50 space-y-2 rounded-lg border p-3", children: [
|
|
167
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
168
|
+
/* @__PURE__ */ jsx(MapPin, { className: "text-primary mt-0.5 size-3.5 shrink-0" }),
|
|
169
|
+
/* @__PURE__ */ jsx("span", { className: "text-foreground text-sm font-medium leading-tight", children: value.address })
|
|
170
|
+
] }),
|
|
171
|
+
/* @__PURE__ */ jsxs("div", { className: "text-muted-foreground pl-5.5 text-xs", children: [
|
|
172
|
+
value.lat.toFixed(4),
|
|
173
|
+
", ",
|
|
174
|
+
value.lng.toFixed(4)
|
|
175
|
+
] })
|
|
176
|
+
] }),
|
|
177
|
+
embedUrl && /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-lg border", children: /* @__PURE__ */ jsx(
|
|
178
|
+
"iframe",
|
|
179
|
+
{
|
|
180
|
+
src: embedUrl,
|
|
181
|
+
title: "Location preview",
|
|
182
|
+
className: "h-[160px] w-full border-0",
|
|
183
|
+
loading: "lazy",
|
|
184
|
+
referrerPolicy: "no-referrer-when-downgrade"
|
|
185
|
+
}
|
|
186
|
+
) }),
|
|
187
|
+
value && value.lat !== 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
188
|
+
/* @__PURE__ */ jsx(Label, { className: "shrink-0 text-xs", children: "Zoom" }),
|
|
189
|
+
/* @__PURE__ */ jsx(
|
|
190
|
+
"input",
|
|
191
|
+
{
|
|
192
|
+
type: "range",
|
|
193
|
+
min: 1,
|
|
194
|
+
max: 20,
|
|
195
|
+
step: 1,
|
|
196
|
+
value: value.zoom ?? 14,
|
|
197
|
+
onChange: handleZoomChange,
|
|
198
|
+
className: "h-1.5 flex-1 cursor-pointer appearance-none rounded-full bg-gray-200 accent-current"
|
|
199
|
+
}
|
|
200
|
+
),
|
|
201
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground w-6 text-right text-xs tabular-nums", children: value.zoom ?? 14 })
|
|
202
|
+
] })
|
|
203
|
+
] });
|
|
204
|
+
});
|
|
205
|
+
export {
|
|
206
|
+
LocationField
|
|
207
|
+
};
|
|
@@ -9,10 +9,10 @@ export interface FullscreenHeroProps {
|
|
|
9
9
|
variant: string;
|
|
10
10
|
};
|
|
11
11
|
buttons?: CompoundButtonProps[];
|
|
12
|
-
|
|
12
|
+
images?: {
|
|
13
13
|
src: string;
|
|
14
14
|
alt?: string;
|
|
15
|
-
}
|
|
15
|
+
}[];
|
|
16
16
|
styles?: {
|
|
17
17
|
padding?: CompoundContainerProps["padding"];
|
|
18
18
|
sectionStyle?: CompoundContainerProps["sectionStyle"];
|
|
@@ -20,4 +20,4 @@ export interface FullscreenHeroProps {
|
|
|
20
20
|
overlay?: "none" | "dark" | "gradient";
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
|
-
export declare const FullscreenHero: ({ heading, description, badge, buttons,
|
|
23
|
+
export declare const FullscreenHero: ({ heading, description, badge, buttons, images, styles, }: FullscreenHeroProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -12,15 +12,16 @@ const FullscreenHero = ({
|
|
|
12
12
|
description,
|
|
13
13
|
badge,
|
|
14
14
|
buttons,
|
|
15
|
-
|
|
15
|
+
images,
|
|
16
16
|
styles
|
|
17
17
|
}) => {
|
|
18
18
|
const sectionStyle = styles == null ? void 0 : styles.sectionStyle;
|
|
19
19
|
const overlay = (styles == null ? void 0 : styles.overlay) ?? "dark";
|
|
20
20
|
const backgroundColor = styles == null ? void 0 : styles.backgroundColor;
|
|
21
21
|
const padding = styles == null ? void 0 : styles.padding;
|
|
22
|
-
const
|
|
23
|
-
const
|
|
22
|
+
const bgImage = images == null ? void 0 : images[0];
|
|
23
|
+
const bgSrc = bgImage == null ? void 0 : bgImage.src;
|
|
24
|
+
const bgAlt = (bgImage == null ? void 0 : bgImage.alt) ?? "";
|
|
24
25
|
if (!bgSrc) {
|
|
25
26
|
return /* @__PURE__ */ jsx(
|
|
26
27
|
CompoundContainer,
|
|
@@ -29,7 +30,15 @@ const FullscreenHero = ({
|
|
|
29
30
|
sectionStyle,
|
|
30
31
|
backgroundColor,
|
|
31
32
|
className: "min-h-[100vh] flex flex-col justify-end",
|
|
32
|
-
children: /* @__PURE__ */ jsx(
|
|
33
|
+
children: /* @__PURE__ */ jsx(
|
|
34
|
+
Content,
|
|
35
|
+
{
|
|
36
|
+
badge,
|
|
37
|
+
heading,
|
|
38
|
+
description,
|
|
39
|
+
buttons
|
|
40
|
+
}
|
|
41
|
+
)
|
|
33
42
|
}
|
|
34
43
|
);
|
|
35
44
|
}
|
|
@@ -40,20 +49,57 @@ const FullscreenHero = ({
|
|
|
40
49
|
{
|
|
41
50
|
className: cn(
|
|
42
51
|
"relative w-full min-h-[100vh] flex flex-col justify-end overflow-hidden bg-background text-foreground",
|
|
43
|
-
{
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
{
|
|
53
|
+
"pt-20 lg:pt-40": top === "large",
|
|
54
|
+
"pb-20 lg:pb-40": bottom === "large"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"pt-15 lg:pt-30": top === "medium",
|
|
58
|
+
"pb-15 lg:pb-30": bottom === "medium"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"pt-10 lg:pt-20": top === "small",
|
|
62
|
+
"pb-10 lg:pb-20": bottom === "small"
|
|
63
|
+
}
|
|
46
64
|
),
|
|
47
65
|
style: { ...styleVars, ...backgroundColor ? { backgroundColor } : {} },
|
|
48
66
|
children: [
|
|
49
|
-
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 [&>span]:h-full [&>span]:w-full", children: /* @__PURE__ */ jsx(
|
|
50
|
-
|
|
51
|
-
|
|
67
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 [&>span]:h-full [&>span]:w-full", children: /* @__PURE__ */ jsx(
|
|
68
|
+
CompoundImage,
|
|
69
|
+
{
|
|
70
|
+
src: bgSrc,
|
|
71
|
+
alt: bgAlt,
|
|
72
|
+
className: "h-full w-full object-cover"
|
|
73
|
+
}
|
|
74
|
+
) }),
|
|
75
|
+
overlay !== "none" && /* @__PURE__ */ jsx(
|
|
76
|
+
"div",
|
|
77
|
+
{
|
|
78
|
+
className: cn(
|
|
79
|
+
"absolute inset-0",
|
|
80
|
+
overlayStyles[overlay] ?? overlayStyles.dark
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
),
|
|
84
|
+
/* @__PURE__ */ jsx("div", { className: "container mx-auto relative z-50", children: /* @__PURE__ */ jsx(
|
|
85
|
+
Content,
|
|
86
|
+
{
|
|
87
|
+
badge,
|
|
88
|
+
heading,
|
|
89
|
+
description,
|
|
90
|
+
buttons
|
|
91
|
+
}
|
|
92
|
+
) })
|
|
52
93
|
]
|
|
53
94
|
}
|
|
54
95
|
);
|
|
55
96
|
};
|
|
56
|
-
function Content({
|
|
97
|
+
function Content({
|
|
98
|
+
badge,
|
|
99
|
+
heading,
|
|
100
|
+
description,
|
|
101
|
+
buttons
|
|
102
|
+
}) {
|
|
57
103
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
58
104
|
badge && /* @__PURE__ */ jsx("span", { className: "bg-primary/10 text-primary mb-6 inline-block rounded-full px-3 py-1 text-xs font-medium", children: badge.label }),
|
|
59
105
|
/* @__PURE__ */ jsx("h1", { className: "font-serif text-5xl md:text-7xl lg:text-8xl font-medium leading-[0.95] mb-8 max-w-[800px] text-foreground", children: heading }),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { contentFields } from "../../../puck-base/core/fields.js";
|
|
1
|
+
import { images, contentFields } from "../../../puck-base/core/fields.js";
|
|
2
2
|
import { FullscreenHero } from "./fullscreen-hero.js";
|
|
3
|
-
import {
|
|
3
|
+
import { createStylesDefaults, createStylesField } from "../../../puck-base/core/styles.js";
|
|
4
4
|
const conf = {
|
|
5
5
|
fields: {
|
|
6
6
|
badge: contentFields.badge,
|
|
@@ -13,7 +13,7 @@ const conf = {
|
|
|
13
13
|
contentEditable: true
|
|
14
14
|
},
|
|
15
15
|
buttons: contentFields.buttons,
|
|
16
|
-
|
|
16
|
+
images: { ...images, max: 1 },
|
|
17
17
|
styles: createStylesField({
|
|
18
18
|
overlay: {
|
|
19
19
|
type: "select",
|
|
@@ -37,7 +37,7 @@ const conf = {
|
|
|
37
37
|
icon: "none"
|
|
38
38
|
}
|
|
39
39
|
],
|
|
40
|
-
|
|
40
|
+
images: [{ src: "https://images.pexels.com/photos/924824/pexels-photo-924824.jpeg?auto=compress&cs=tinysrgb&w=1920", alt: "Hero background" }],
|
|
41
41
|
styles: createStylesDefaults({
|
|
42
42
|
sectionStyle: "dark",
|
|
43
43
|
overlay: "dark"
|
|
@@ -6,10 +6,10 @@ export interface ImageHeroProps {
|
|
|
6
6
|
description?: string;
|
|
7
7
|
badge?: CompoundBadgeProps;
|
|
8
8
|
buttons?: CompoundButtonProps[];
|
|
9
|
-
|
|
9
|
+
images?: {
|
|
10
10
|
src: string;
|
|
11
11
|
alt?: string;
|
|
12
|
-
}
|
|
12
|
+
}[];
|
|
13
13
|
styles?: {
|
|
14
14
|
padding?: CompoundContainerProps["padding"];
|
|
15
15
|
sectionStyle?: CompoundContainerProps["sectionStyle"];
|
|
@@ -19,4 +19,4 @@ export interface ImageHeroProps {
|
|
|
19
19
|
minHeight?: "medium" | "large" | "full";
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
|
-
export declare const ImageHero: ({ heading, description, badge, buttons,
|
|
22
|
+
export declare const ImageHero: ({ heading, description, badge, buttons, images, styles, }: ImageHeroProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -18,14 +18,15 @@ const ImageHero = ({
|
|
|
18
18
|
description,
|
|
19
19
|
badge,
|
|
20
20
|
buttons,
|
|
21
|
-
|
|
21
|
+
images,
|
|
22
22
|
styles
|
|
23
23
|
}) => {
|
|
24
24
|
const overlay = (styles == null ? void 0 : styles.overlay) ?? "dark";
|
|
25
25
|
const align = (styles == null ? void 0 : styles.align) ?? "center";
|
|
26
26
|
const minHeight = (styles == null ? void 0 : styles.minHeight) ?? "large";
|
|
27
|
-
const
|
|
28
|
-
const
|
|
27
|
+
const bgImage = images == null ? void 0 : images[0];
|
|
28
|
+
const bgSrc = bgImage == null ? void 0 : bgImage.src;
|
|
29
|
+
const bgAlt = (bgImage == null ? void 0 : bgImage.alt) ?? "";
|
|
29
30
|
return /* @__PURE__ */ jsx(
|
|
30
31
|
CompoundContainer,
|
|
31
32
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buttons, badge } from "../../../puck-base/core/fields.js";
|
|
1
|
+
import { images, buttons, badge } from "../../../puck-base/core/fields.js";
|
|
2
2
|
import { heroStylesDefaults, createStylesField, sectionOverlay } from "../../../puck-base/core/styles.js";
|
|
3
3
|
import { ImageHero } from "./image-hero.js";
|
|
4
4
|
const imageHeroStylesField = createStylesField({
|
|
@@ -26,20 +26,13 @@ const conf = {
|
|
|
26
26
|
description: { type: "textarea", contentEditable: true },
|
|
27
27
|
badge,
|
|
28
28
|
buttons,
|
|
29
|
-
|
|
30
|
-
type: "text",
|
|
31
|
-
label: "Background Image URL",
|
|
32
|
-
ai: {
|
|
33
|
-
instructions: "URL for a full-width background image behind the section.",
|
|
34
|
-
stream: false
|
|
35
|
-
}
|
|
36
|
-
},
|
|
29
|
+
images: { ...images, max: 1 },
|
|
37
30
|
styles: imageHeroStylesField
|
|
38
31
|
},
|
|
39
32
|
defaultProps: {
|
|
40
33
|
heading: "Build something people want",
|
|
41
34
|
description: "A modern platform for teams who care about speed, quality, and customer experience.",
|
|
42
|
-
|
|
35
|
+
images: [{ src: "https://images.pexels.com/photos/3184291/pexels-photo-3184291.jpeg?auto=compress&cs=tinysrgb&w=1920", alt: "Hero background" }],
|
|
43
36
|
buttons: [
|
|
44
37
|
{
|
|
45
38
|
label: "Get Started",
|
|
@@ -37,9 +37,7 @@ type HeroSectionProps = {
|
|
|
37
37
|
spacing?: "tight" | "normal" | "relaxed";
|
|
38
38
|
align?: "left" | "center";
|
|
39
39
|
displaySize?: "default" | "display";
|
|
40
|
-
images?: HeroImage
|
|
41
|
-
backgroundImage?: HeroImage | string;
|
|
42
|
-
posterImage?: HeroImage;
|
|
40
|
+
images?: HeroImage[];
|
|
43
41
|
videoUrl?: string;
|
|
44
42
|
adjectives?: {
|
|
45
43
|
adjective: string;
|