Wire Ladill domain picker and purchase modal into hosting flows.
Deploy Ladill Hosting / deploy (push) Successful in 51s

Use the Domains API for owned domains across panel, account, and order forms, with an embedded iframe purchase modal instead of redirecting to domains.ladill.com.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-06-19 18:01:23 +00:00
co-authored by Cursor
parent 44cfb1d9b9
commit 537e34cbd7
20 changed files with 532 additions and 306 deletions
+4
View File
@@ -1,8 +1,12 @@
import './bootstrap';
import { registerLadillConfirmStore, registerLadillModalHelpers } from './ladill-modals';
import { registerLadillSearchShortcut } from './ladill-search-shortcut';
import { registerLadillDomainPurchase } from './ladill-domain-purchase';
registerLadillModalHelpers();
registerLadillSearchShortcut();
registerLadillDomainPurchase();
import Alpine from 'alpinejs';
+99
View File
@@ -0,0 +1,99 @@
import { closeLadillModal, openLadillModal } from './ladill-modals';
const PURCHASE_MODAL = 'domain-purchase';
function allowedParentOrigin(origin) {
try {
const host = new URL(origin).hostname;
return host === 'ladill.com' || host.endsWith('.ladill.com');
} catch {
return false;
}
}
function loadPurchaseFrame() {
const frame = document.getElementById('ladill-domain-purchase-frame');
if (!frame || frame.dataset.loaded === '1') {
return;
}
const embedUrl = frame.dataset.embedUrl;
if (embedUrl) {
frame.src = embedUrl;
frame.dataset.loaded = '1';
}
}
export function registerLadillDomainPurchase() {
window.ladillDomainSourceForm = (initial = {}) => ({
domainSource: initial.domainSource ?? 'external',
selectedOwnedDomain: initial.selectedOwnedDomain ?? '',
externalDomain: initial.externalDomain ?? '',
ownedDomains: initial.ownedDomains ?? [],
ownedUrl: initial.ownedUrl ?? '',
onboardingMode: initial.onboardingMode ?? 'ns_auto',
openPurchaseModal() {
loadPurchaseFrame();
openLadillModal(PURCHASE_MODAL);
},
async refreshOwnedDomains() {
if (!this.ownedUrl) {
return;
}
try {
const res = await fetch(this.ownedUrl, {
headers: { Accept: 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
});
if (!res.ok) {
return;
}
const payload = await res.json();
this.ownedDomains = Array.isArray(payload.data) ? payload.data : [];
this.domainSource = 'ladill';
} catch {
// Non-fatal.
}
},
});
window.addEventListener('message', (event) => {
if (!allowedParentOrigin(event.origin)) {
return;
}
const data = event.data;
if (!data || data.type !== 'ladill:domains:purchase-complete') {
return;
}
closeLadillModal(PURCHASE_MODAL);
const domains = Array.isArray(data.domains) ? data.domains : (data.domain ? [data.domain] : []);
document.querySelectorAll('[x-data*="ladillDomainSourceForm"]').forEach((el) => {
const component = el._x_dataStack?.[0];
if (!component?.refreshOwnedDomains) {
return;
}
component.refreshOwnedDomains().then(() => {
const newest = domains.map((d) => String(d).toLowerCase()).find(Boolean);
if (newest) {
component.selectedOwnedDomain = newest;
component.domainSource = 'ladill';
}
});
});
});
window.addEventListener('open-modal', (event) => {
if (String(event.detail) === PURCHASE_MODAL) {
loadPurchaseFrame();
}
});
}
+97
View File
@@ -0,0 +1,97 @@
function isEditableTarget(element) {
if (!(element instanceof HTMLElement)) {
return false;
}
const tag = element.tagName;
if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') {
return true;
}
return element.isContentEditable;
}
function isVisibleInput(input) {
if (!(input instanceof HTMLElement)) {
return false;
}
const style = window.getComputedStyle(input);
return style.display !== 'none'
&& style.visibility !== 'hidden'
&& style.opacity !== '0';
}
function findSearchInput() {
const marked = [...document.querySelectorAll('[data-ladill-search-input]')];
const visibleMarked = marked.find(isVisibleInput);
if (visibleMarked) {
return visibleMarked;
}
if (marked.length > 0) {
return marked[0];
}
return document.querySelector('[x-data*="topbarSearch"] input');
}
function focusSearchInput() {
const input = findSearchInput();
if (!input) {
const fallbackUrl = document.body?.dataset?.ladillSearchUrl;
if (fallbackUrl) {
window.location.href = fallbackUrl;
}
return false;
}
if (!isVisibleInput(input)) {
const fallbackUrl = document.body?.dataset?.ladillSearchUrl;
if (fallbackUrl) {
window.location.href = fallbackUrl;
return true;
}
}
input.focus();
if (input instanceof HTMLInputElement && (input.type === 'text' || input.type === 'search')) {
input.select();
}
return true;
}
export function registerLadillSearchShortcut() {
if (window.__ladillSearchShortcutRegistered) {
return;
}
window.__ladillSearchShortcutRegistered = true;
document.addEventListener('keydown', (event) => {
if (event.key !== '/' && event.code !== 'Slash') {
return;
}
if (event.ctrlKey || event.metaKey || event.altKey) {
return;
}
if (isEditableTarget(document.activeElement)) {
return;
}
event.preventDefault();
focusSearchInput();
});
}