Convert the bundled backend/internal/plugins/calcomblock package into a standalone reactor-mode wasm plugin, dropping every git.dev.alexdunmow.com/block/cms import (forbidden in standalone plugins): - package calcomblock -> package main; add wasip1 main.go with wasmguest.Serve(Registration). go.mod module git.dev.alexdunmow.com/block/calcomblock, block/core v0.18.2, no replace directives. - Settings persistence: replace the pool-backed poolQuerier (direct SQL against the public-schema `settings` table, which a sandboxed plugin role cannot read) with capabilityQuerier over the SDK settings.Settings / settings.Updater capabilities. GetSiteTimezone now resolves via GetSiteSettings host-side. - Vendor the small CMS-internal helpers the plugin used into internal/helpers (GetRealIP, StartCleanupLoop, MaskSecret, GetStringOr, the PluginSettingsQuerier settings helpers, PluginCrypto for tests) and internal/db (minimal Setting / UpsertSettingParams), each with a provenance header. - Inline the captcha widget: vendor blocks.CaptchaWidget as a local CaptchaWidget templ (captcha_widget.templ) and regenerate templ; drop the block/cms/blocks import from booking.templ. - blockConfig (server-authoritative captcha requirement via a page_block_snapshots scan) has no wasm-ABI capability, so it is left nil: honeypot + per-IP rate limit still apply. Documented as a follow-up. - web: @block-ninja/ui workspace:* -> ^0.1.0 registry version; eslint.config.js repointed at ../../../cms/web/eslint.config.js; rebuild web/dist. - Rewrite CLAUDE.md for the standalone wasm reality; add .gitignore. Full test suite preserved and passing; builds to calcomblock-2.0.0.bnp; check-safety passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
551 lines
23 KiB
JavaScript
551 lines
23 KiB
JavaScript
import { importShared } from "./__federation_fn_import-hlt2XzeI.js";
|
|
import { j as jsxRuntimeExports } from "./jsx-runtime-CvJTHeKY.js";
|
|
|
|
const { useCallback, useEffect, useState } = await importShared("react");
|
|
|
|
const {
|
|
Alert,
|
|
AlertDescription,
|
|
Button,
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardHeader,
|
|
CardTitle,
|
|
Tabs,
|
|
TabsContent,
|
|
TabsList,
|
|
TabsTrigger,
|
|
Input,
|
|
Label,
|
|
Textarea,
|
|
Switch,
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
Settings,
|
|
Edit3,
|
|
CheckCircle2,
|
|
XCircle,
|
|
Loader2,
|
|
Key,
|
|
AlertCircle,
|
|
ExternalLink,
|
|
RefreshCw,
|
|
t,
|
|
} = await importShared("@block-ninja/ui");
|
|
|
|
function renderConnectedAccount(apiKeyConfigured, calcomUsername) {
|
|
if (apiKeyConfigured === false) {
|
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("p", {
|
|
className: "text-xs text-muted-foreground",
|
|
children: t("calcom.editor.connectedAs.noKey", "Configure the API key in plugin settings to connect an account."),
|
|
});
|
|
}
|
|
if (calcomUsername) {
|
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-mono", children: calcomUsername });
|
|
}
|
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: t("calcom.editor.connectedAs.resolving", "Resolving account from API key…") });
|
|
}
|
|
function CalcomBlockEditor({ content, onChange }) {
|
|
const [activeTab, setActiveTab] = useState("config");
|
|
const [apiKeyConfigured, setApiKeyConfigured] = useState(null);
|
|
const [calcomUsername, setCalcomUsername] = useState("");
|
|
const [eventTypes, setEventTypes] = useState([]);
|
|
const [loadingEventTypes, setLoadingEventTypes] = useState(false);
|
|
const [fetchFailed, setFetchFailed] = useState(false);
|
|
const [retryCounter, setRetryCounter] = useState(0);
|
|
const handleFieldChange = useCallback(
|
|
(field, value) => {
|
|
onChange({ ...content, [field]: value });
|
|
},
|
|
[content, onChange],
|
|
);
|
|
const getString = (field, defaultValue = "") => {
|
|
return content[field] || defaultValue;
|
|
};
|
|
const getNumber = (field, defaultValue = 0) => {
|
|
const val = content[field];
|
|
if (typeof val === "number") return val;
|
|
if (typeof val === "string") return parseInt(val, 10) || defaultValue;
|
|
return defaultValue;
|
|
};
|
|
const getBool = (field, defaultValue = false) => {
|
|
const val = content[field];
|
|
if (typeof val === "boolean") return val;
|
|
return defaultValue;
|
|
};
|
|
const eventTypeSlug = getString("eventTypeSlug");
|
|
useEffect(() => {
|
|
fetch(`/api/plugins/calcomblock/settings`)
|
|
.then((r) => r.json())
|
|
.then((d) => {
|
|
setApiKeyConfigured(!!d.api_key_configured);
|
|
setCalcomUsername(d.username ?? "");
|
|
})
|
|
.catch(() => setApiKeyConfigured(false));
|
|
}, []);
|
|
useEffect(() => {
|
|
if (calcomUsername && content.username !== calcomUsername) {
|
|
onChange({ ...content, username: calcomUsername });
|
|
}
|
|
}, [calcomUsername, content, onChange]);
|
|
useEffect(() => {
|
|
if (!apiKeyConfigured) {
|
|
setEventTypes([]);
|
|
setFetchFailed(false);
|
|
return;
|
|
}
|
|
const timer = setTimeout(() => {
|
|
setLoadingEventTypes(true);
|
|
setFetchFailed(false);
|
|
fetch(`/api/plugins/calcomblock/event-types?username=${encodeURIComponent(calcomUsername)}`)
|
|
.then((r) => r.json())
|
|
.then((d) => {
|
|
if (d.success) {
|
|
setEventTypes(d.event_types ?? []);
|
|
} else {
|
|
setEventTypes([]);
|
|
setFetchFailed(true);
|
|
}
|
|
})
|
|
.catch(() => {
|
|
setEventTypes([]);
|
|
setFetchFailed(true);
|
|
})
|
|
.finally(() => setLoadingEventTypes(false));
|
|
}, 300);
|
|
return () => clearTimeout(timer);
|
|
}, [apiKeyConfigured, calcomUsername, retryCounter]);
|
|
const handleRetry = useCallback(() => {
|
|
setRetryCounter((n) => n + 1);
|
|
}, []);
|
|
const selectPlaceholder = (() => {
|
|
if (apiKeyConfigured === false) {
|
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", {
|
|
className: "inline-flex items-center gap-1.5 text-muted-foreground",
|
|
children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Key, { className: "h-3 w-3" }), t("calcom.editor.eventType.placeholder.noApiKey", "Configure API key first")],
|
|
});
|
|
}
|
|
if (loadingEventTypes) {
|
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", {
|
|
className: "inline-flex items-center gap-1.5 text-muted-foreground",
|
|
children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Loader2, { className: "h-3 w-3 animate-spin" }), t("calcom.editor.eventType.placeholder.loading", "Loading…")],
|
|
});
|
|
}
|
|
if (!calcomUsername) {
|
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", {
|
|
className: "inline-flex items-center gap-1.5 text-muted-foreground",
|
|
children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Loader2, { className: "h-3 w-3 animate-spin" }), t("calcom.editor.eventType.placeholder.resolvingUser", "Resolving account…")],
|
|
});
|
|
}
|
|
if (eventTypes.length === 0) {
|
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", {
|
|
className: "inline-flex items-center gap-1.5 text-muted-foreground",
|
|
children: [/* @__PURE__ */ jsxRuntimeExports.jsx(XCircle, { className: "h-3 w-3" }), t("calcom.editor.eventType.placeholder.noEventTypes", "No event types found")],
|
|
});
|
|
}
|
|
return t("calcom.editor.eventType.placeholder.select", "Select event type");
|
|
})();
|
|
const apiKeyReady = apiKeyConfigured === true;
|
|
const usernameReady = calcomUsername.length > 0;
|
|
const eventTypeReady = eventTypeSlug.length > 0;
|
|
const canOpenInCalcom = usernameReady && eventTypeReady;
|
|
const renderStatusRow = (ok, label, action) =>
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
className: "flex items-center gap-2 text-sm",
|
|
children: [
|
|
ok ?
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CheckCircle2, { "className": "h-4 w-4 text-primary", "aria-hidden": "true" })
|
|
: /* @__PURE__ */ jsxRuntimeExports.jsx(XCircle, { "className": "h-4 w-4 text-destructive", "aria-hidden": "true" }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: ok ? "text-foreground" : "text-muted-foreground", children: label }),
|
|
action ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-auto", children: action }) : null,
|
|
],
|
|
});
|
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", {
|
|
className: "space-y-4",
|
|
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tabs, {
|
|
value: activeTab,
|
|
onValueChange: setActiveTab,
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(TabsList, {
|
|
className: "grid w-full grid-cols-2",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, {
|
|
value: "config",
|
|
className: "gap-2",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Settings, { className: "h-4 w-4" }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t("calcom.editor.tab.configuration", "Configuration") }),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, {
|
|
value: "content",
|
|
className: "gap-2",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Edit3, { className: "h-4 w-4" }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t("calcom.editor.tab.content", "Content") }),
|
|
],
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(TabsContent, {
|
|
value: "config",
|
|
className: "space-y-4 mt-4",
|
|
children: [
|
|
apiKeyConfigured === false &&
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Alert, {
|
|
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDescription, {
|
|
children: [
|
|
t("calcom.editor.alert.apiKeyMissing.prefix", "Configure your Cal.com API key in"),
|
|
" ",
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("a", {
|
|
href: "/admin/plugins?plugin=calcomblock",
|
|
className: "text-primary hover:underline",
|
|
children: t("calcom.editor.alert.apiKeyMissing.linkLabel", "plugin settings"),
|
|
}),
|
|
" ",
|
|
t("calcom.editor.alert.apiKeyMissing.suffix", "to enable the event-type dropdown."),
|
|
],
|
|
}),
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Card, {
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, {
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-base", children: t("calcom.editor.section.config.title", "Cal.com Settings") }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, {
|
|
children: t("calcom.editor.section.config.description", "Connect to your Cal.com account and select an event type"),
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, {
|
|
className: "space-y-4",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
className: "space-y-2",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Label, { children: t("calcom.editor.connectedAs.label", "Connected Account") }),
|
|
renderConnectedAccount(apiKeyConfigured, calcomUsername),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
className: "space-y-2",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Label, {
|
|
htmlFor: "eventTypeSlug",
|
|
children: [
|
|
t("calcom.editor.eventType.label", "Event Type"),
|
|
" ",
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-destructive", children: "*" }),
|
|
],
|
|
}),
|
|
fetchFailed ?
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, {
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
className: "flex items-center gap-2",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Input, {
|
|
id: "eventTypeSlug",
|
|
value: eventTypeSlug,
|
|
onChange: (e) => handleFieldChange("eventTypeSlug", e.target.value),
|
|
placeholder: t("calcom.editor.eventType.fallbackPlaceholder", "30min"),
|
|
className: "flex-1",
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Button, {
|
|
"type": "button",
|
|
"size": "sm",
|
|
"variant": "outline",
|
|
"action": "retry",
|
|
"entity": "event-types",
|
|
"onClick": handleRetry,
|
|
"disabled": loadingEventTypes,
|
|
"aria-label": t("calcom.editor.eventType.retryAria", "Retry loading event types"),
|
|
"children": [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, {
|
|
"className": `h-4 w-4 ${loadingEventTypes ? "animate-spin" : ""}`,
|
|
"aria-hidden": "true",
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", {
|
|
className: "ml-1",
|
|
children: t("calcom.editor.eventType.retryLabel", "Retry"),
|
|
}),
|
|
],
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Alert, {
|
|
variant: "destructive",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertCircle, { "className": "h-4 w-4", "aria-hidden": "true" }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, {
|
|
children: t("calcom.editor.eventType.fetchFailed", "Couldn't load event types from Cal.com. Enter the slug manually or retry."),
|
|
}),
|
|
],
|
|
}),
|
|
],
|
|
})
|
|
: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, {
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Select, {
|
|
value: eventTypeSlug,
|
|
onValueChange: (v) => handleFieldChange("eventTypeSlug", v),
|
|
disabled: loadingEventTypes || !apiKeyConfigured || eventTypes.length === 0,
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, {
|
|
"aria-label": t("calcom.editor.eventType.label", "Event Type"),
|
|
"children": /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: selectPlaceholder }),
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectContent, {
|
|
children: eventTypes.map((et) =>
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
SelectItem,
|
|
{
|
|
value: et.slug,
|
|
children: [
|
|
et.title,
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", {
|
|
className: "text-muted-foreground",
|
|
children: [" ", "(", et.slug, " · ", et.lengthInMinutes, "m)"],
|
|
}),
|
|
],
|
|
},
|
|
et.id,
|
|
),
|
|
),
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", {
|
|
className: "text-xs text-muted-foreground",
|
|
children: t("calcom.editor.eventType.help", "Fetched from your Cal.com account"),
|
|
}),
|
|
],
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
className: "space-y-2",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "weeksToShow", children: t("calcom.editor.weeksToShow.label", "Weeks to Display") }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Select, {
|
|
value: String(getNumber("weeksToShow", 2)),
|
|
onValueChange: (v) => handleFieldChange("weeksToShow", parseInt(v, 10)),
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, {
|
|
"aria-label": t("calcom.editor.weeksToShow.label", "Weeks to Display"),
|
|
"children": /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: t("calcom.editor.weeksToShow.placeholder", "Select weeks") }),
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SelectContent, {
|
|
children: [1, 2, 3, 4, 5, 6, 7, 8].map((n) =>
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
SelectItem,
|
|
{
|
|
value: String(n),
|
|
children: [
|
|
n,
|
|
" ",
|
|
n > 1 ? t("calcom.editor.weeksToShow.unitPlural", "weeks") : t("calcom.editor.weeksToShow.unitSingular", "week"),
|
|
],
|
|
},
|
|
n,
|
|
),
|
|
),
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", {
|
|
className: "text-xs text-muted-foreground",
|
|
children: t("calcom.editor.weeksToShow.help", "How many weeks of dates to show in the calendar"),
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
className: "flex items-center justify-between rounded-lg border p-3",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
className: "space-y-0.5",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Label, { children: t("calcom.editor.showTimezone.label", "Show Timezone Selector") }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", {
|
|
className: "text-xs text-muted-foreground",
|
|
children: t("calcom.editor.showTimezone.help", "Show a label above the date grid indicating which timezone times are displayed in."),
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Switch, {
|
|
"checked": getBool("showTimezone", true),
|
|
"onCheckedChange": (v) => handleFieldChange("showTimezone", v),
|
|
"aria-label": t("calcom.editor.showTimezone.label", "Show Timezone Selector"),
|
|
}),
|
|
],
|
|
}),
|
|
],
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Card, {
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, {
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-base", children: t("calcom.editor.status.title", "Configuration status") }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, {
|
|
children: t("calcom.editor.status.description", "Quick check of the values needed before this block renders bookings."),
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, {
|
|
className: "space-y-2",
|
|
children: [
|
|
renderStatusRow(
|
|
apiKeyReady,
|
|
t("calcom.editor.status.apiKey", "API key configured"),
|
|
!apiKeyReady ?
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("a", {
|
|
href: "/admin/plugins?plugin=calcomblock",
|
|
className: "text-xs text-primary hover:underline",
|
|
children: t("calcom.editor.status.apiKey.configureLink", "Configure"),
|
|
})
|
|
: null,
|
|
),
|
|
renderStatusRow(usernameReady, t("calcom.editor.status.username", "Account resolved")),
|
|
renderStatusRow(eventTypeReady, t("calcom.editor.status.eventType", "Event type selected")),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
className: "flex items-center gap-2 text-sm",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex h-4 w-4 items-center justify-center text-muted-foreground", children: "·" }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", {
|
|
className: "text-muted-foreground",
|
|
children: t("calcom.editor.status.eventTypesAvailable", "{count} event types available").replace("{count}", String(eventTypes.length)),
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", {
|
|
className: "pt-2",
|
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Button, {
|
|
"type": "button",
|
|
"size": "sm",
|
|
"variant": "outline",
|
|
"action": "open",
|
|
"entity": "calcom-page",
|
|
"asChild": canOpenInCalcom,
|
|
"disabled": !canOpenInCalcom,
|
|
"aria-label": t("calcom.editor.status.openExternalAria", "Open Cal.com booking page in a new tab"),
|
|
"children":
|
|
canOpenInCalcom ?
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("a", {
|
|
href: `https://cal.com/${calcomUsername}/${eventTypeSlug}`,
|
|
target: "_blank",
|
|
rel: "noopener noreferrer",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { "className": "h-4 w-4", "aria-hidden": "true" }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", {
|
|
className: "ml-1",
|
|
children: t("calcom.editor.status.openExternal", "Open in Cal.com"),
|
|
}),
|
|
],
|
|
})
|
|
: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, {
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { "className": "h-4 w-4", "aria-hidden": "true" }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", {
|
|
className: "ml-1",
|
|
children: t("calcom.editor.status.openExternal", "Open in Cal.com"),
|
|
}),
|
|
],
|
|
}),
|
|
}),
|
|
}),
|
|
],
|
|
}),
|
|
],
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, {
|
|
value: "content",
|
|
className: "space-y-4 mt-4",
|
|
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, {
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, {
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-base", children: t("calcom.editor.section.content.title", "Widget Content") }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, {
|
|
children: t("calcom.editor.section.content.description", "Customize the text shown in the booking widget"),
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, {
|
|
className: "space-y-4",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
className: "space-y-2",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "title", children: t("calcom.editor.title.label", "Title") }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Input, {
|
|
id: "title",
|
|
value: getString("title"),
|
|
onChange: (e) => handleFieldChange("title", e.target.value),
|
|
placeholder: t("calcom.editor.title.placeholder", "Book a Meeting"),
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", {
|
|
className: "text-xs text-muted-foreground",
|
|
children: t("calcom.editor.title.help", "Main heading shown above the calendar"),
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
className: "space-y-2",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "description", children: t("calcom.editor.description.label", "Description") }),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Textarea, {
|
|
id: "description",
|
|
value: getString("description"),
|
|
onChange: (e) => handleFieldChange("description", e.target.value),
|
|
placeholder: t("calcom.editor.description.placeholder", "Choose a convenient time for your consultation..."),
|
|
rows: 3,
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", {
|
|
className: "text-xs text-muted-foreground",
|
|
children: t("calcom.editor.description.help", "Optional text shown below the title"),
|
|
}),
|
|
],
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
className: "space-y-2",
|
|
children: [
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Label, {
|
|
htmlFor: "unavailableMessage",
|
|
children: t("calcom.editor.unavailableMessage.label", "Booking unavailable message"),
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Textarea, {
|
|
id: "unavailableMessage",
|
|
value: getString("unavailableMessage"),
|
|
onChange: (e) => handleFieldChange("unavailableMessage", e.target.value),
|
|
placeholder: t(
|
|
"calcom.editor.unavailableMessage.placeholder",
|
|
"Sorry — we couldn't complete your booking online. Please use our contact form and we'll get you booked in.",
|
|
),
|
|
rows: 3,
|
|
}),
|
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", {
|
|
className: "text-xs text-muted-foreground",
|
|
children: t("calcom.editor.unavailableMessage.help", "Shown if an online booking can't be completed. Leave blank to use the default."),
|
|
}),
|
|
],
|
|
}),
|
|
],
|
|
}),
|
|
],
|
|
}),
|
|
}),
|
|
],
|
|
}),
|
|
});
|
|
}
|
|
|
|
export { CalcomBlockEditor as default };
|