@octaviaflow/core 3.1.0-beta.70 → 3.1.0-beta.71
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/marketing/components/BetaAccessForm/BetaAccessForm.d.ts +11 -1
- package/dist/marketing/components/BetaAccessForm/BetaAccessForm.d.ts.map +1 -1
- package/dist/marketing/components/MarketingNav/MarketingNav.d.ts.map +1 -1
- package/dist/marketing.cjs +1772 -1681
- package/dist/marketing.cjs.map +1 -1
- package/dist/marketing.js +113 -20
- package/dist/marketing.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/marketing.cjs
CHANGED
|
@@ -129,7 +129,7 @@ function BackedBy({
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
// src/marketing/components/BetaAccessForm/BetaAccessForm.tsx
|
|
132
|
-
var
|
|
132
|
+
var import_react21 = require("react");
|
|
133
133
|
|
|
134
134
|
// src/components/Button/Button.tsx
|
|
135
135
|
var import_framer_motion = require("framer-motion");
|
|
@@ -2309,1710 +2309,1755 @@ var Select = (0, import_react16.forwardRef)(function Select2({
|
|
|
2309
2309
|
});
|
|
2310
2310
|
Select.displayName = "Select";
|
|
2311
2311
|
|
|
2312
|
-
// src/
|
|
2313
|
-
var
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
var
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
id: "daily-load",
|
|
2337
|
-
label: "Payments payouts \u2192 Lakehouse, daily",
|
|
2338
|
-
prompt: "Load Payments payouts into Lakehouse daily"
|
|
2339
|
-
},
|
|
2340
|
-
{
|
|
2341
|
-
id: "realtime-stream",
|
|
2342
|
-
label: "Orders DB changes \u2192 Warehouse + Team Chat",
|
|
2343
|
-
prompt: "Stream Orders DB changes to Warehouse in real-time and notify Team Chat"
|
|
2344
|
-
}
|
|
2345
|
-
];
|
|
2346
|
-
var WORKFLOW_SHOWCASE_DEFAULT_METRICS = [
|
|
2347
|
-
{ id: "throughput", value: 2341, buildingValue: 842, unit: "rows/min", label: "THROUGHPUT" },
|
|
2348
|
-
{
|
|
2349
|
-
id: "latency",
|
|
2350
|
-
value: 0.8,
|
|
2351
|
-
buildingValue: 1.1,
|
|
2352
|
-
decimals: 1,
|
|
2353
|
-
unit: "s latency",
|
|
2354
|
-
label: "SYNC SPEED"
|
|
2355
|
-
},
|
|
2356
|
-
{ id: "cost", value: 43, suffix: "%", label: "SAVED VS BASELINE", tone: "success" }
|
|
2357
|
-
];
|
|
2358
|
-
var WORKFLOW_SHOWCASE_SCHEDULES = ["AUTO", "HOURLY", "DAILY", "REAL-TIME"];
|
|
2359
|
-
var WORKFLOW_SHOWCASE_TRIGGERS = ["SCHEDULE", "WEBHOOK", "APP EVENT", "MANUAL"];
|
|
2360
|
-
var WORKFLOW_SHOWCASE_DEFAULT_TILES = [
|
|
2361
|
-
"ELT",
|
|
2362
|
-
"CDC",
|
|
2363
|
-
"LLM",
|
|
2364
|
-
"RAG",
|
|
2365
|
-
"HEAL",
|
|
2366
|
-
"COST",
|
|
2367
|
-
"IDP",
|
|
2368
|
-
"VEC"
|
|
2369
|
-
];
|
|
2370
|
-
function escapeRegExp(value) {
|
|
2371
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2372
|
-
}
|
|
2373
|
-
function mentionsOf(catalog) {
|
|
2374
|
-
const out = [];
|
|
2375
|
-
for (const connector of catalog) {
|
|
2376
|
-
out.push({ connector, pattern: connector.name });
|
|
2377
|
-
for (const alias of connector.aliases ?? []) out.push({ connector, pattern: alias });
|
|
2312
|
+
// src/components/Textarea/Textarea.tsx
|
|
2313
|
+
var import_react20 = require("react");
|
|
2314
|
+
var import_react_aria4 = require("react-aria");
|
|
2315
|
+
var import_react_dom3 = require("react-dom");
|
|
2316
|
+
var import_icons4 = require("@octaviaflow/icons");
|
|
2317
|
+
|
|
2318
|
+
// src/hooks/useTextareaCommands.ts
|
|
2319
|
+
var import_react17 = require("react");
|
|
2320
|
+
function findOpenTrigger(value, caret, trigger) {
|
|
2321
|
+
let i = caret - 1;
|
|
2322
|
+
while (i >= 0) {
|
|
2323
|
+
const ch = value[i];
|
|
2324
|
+
if (ch === "\n" || ch === " " || ch === " ") return null;
|
|
2325
|
+
if (value.startsWith(trigger, i)) {
|
|
2326
|
+
const before = i === 0 ? "" : value[i - 1];
|
|
2327
|
+
if (i === 0 || before === " " || before === "\n" || before === " ") {
|
|
2328
|
+
return {
|
|
2329
|
+
triggerIndex: i,
|
|
2330
|
+
query: value.slice(i + trigger.length, caret)
|
|
2331
|
+
};
|
|
2332
|
+
}
|
|
2333
|
+
return null;
|
|
2334
|
+
}
|
|
2335
|
+
i--;
|
|
2378
2336
|
}
|
|
2379
|
-
return out.sort((a, b) => b.pattern.length - a.pattern.length);
|
|
2380
|
-
}
|
|
2381
|
-
function detectConnectors(prompt, catalog) {
|
|
2382
|
-
const lower = prompt.toLowerCase();
|
|
2383
|
-
return catalog.filter((c) => [c.name, ...c.aliases ?? []].some((p) => lower.includes(p.toLowerCase()))).map((c) => c.name);
|
|
2384
|
-
}
|
|
2385
|
-
function segmentPrompt(prompt, catalog) {
|
|
2386
|
-
if (!prompt) return [];
|
|
2387
|
-
const mentions = mentionsOf(catalog);
|
|
2388
|
-
if (!mentions.length) return [{ text: prompt }];
|
|
2389
|
-
const re = new RegExp(`(${mentions.map((m) => escapeRegExp(m.pattern)).join("|")})`, "gi");
|
|
2390
|
-
const byPattern = new Map(mentions.map((m) => [m.pattern.toLowerCase(), m.connector]));
|
|
2391
|
-
return prompt.split(re).filter((part) => part !== "").map((part) => {
|
|
2392
|
-
const connector = byPattern.get(part.toLowerCase());
|
|
2393
|
-
return connector ? { text: part, connector } : { text: part };
|
|
2394
|
-
});
|
|
2395
|
-
}
|
|
2396
|
-
function scheduleFromPrompt(prompt) {
|
|
2397
|
-
const t = prompt.toLowerCase();
|
|
2398
|
-
if (/stream|real.?time|cdc/.test(t)) return "REAL-TIME";
|
|
2399
|
-
if (/hour/.test(t)) return "HOURLY";
|
|
2400
|
-
if (/dail|every day|nightly/.test(t)) return "DAILY";
|
|
2401
2337
|
return null;
|
|
2402
2338
|
}
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
if (sink) names = [...names, sink.name];
|
|
2339
|
+
function getCaretRect(textarea, caret) {
|
|
2340
|
+
if (typeof document === "undefined") return null;
|
|
2341
|
+
const mirror = document.createElement("div");
|
|
2342
|
+
const styles = window.getComputedStyle(textarea);
|
|
2343
|
+
for (const prop of [
|
|
2344
|
+
"boxSizing",
|
|
2345
|
+
"width",
|
|
2346
|
+
"fontFamily",
|
|
2347
|
+
"fontSize",
|
|
2348
|
+
"fontWeight",
|
|
2349
|
+
"fontStyle",
|
|
2350
|
+
"letterSpacing",
|
|
2351
|
+
"lineHeight",
|
|
2352
|
+
"paddingTop",
|
|
2353
|
+
"paddingRight",
|
|
2354
|
+
"paddingBottom",
|
|
2355
|
+
"paddingLeft",
|
|
2356
|
+
"borderTopWidth",
|
|
2357
|
+
"borderRightWidth",
|
|
2358
|
+
"borderBottomWidth",
|
|
2359
|
+
"borderLeftWidth",
|
|
2360
|
+
"textTransform",
|
|
2361
|
+
"wordSpacing",
|
|
2362
|
+
"tabSize",
|
|
2363
|
+
"whiteSpace"
|
|
2364
|
+
]) {
|
|
2365
|
+
mirror.style[prop] = styles[prop];
|
|
2431
2366
|
}
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2367
|
+
mirror.style.position = "absolute";
|
|
2368
|
+
mirror.style.visibility = "hidden";
|
|
2369
|
+
mirror.style.overflow = "hidden";
|
|
2370
|
+
mirror.style.top = "0";
|
|
2371
|
+
mirror.style.left = "0";
|
|
2372
|
+
mirror.style.whiteSpace = "pre-wrap";
|
|
2373
|
+
mirror.style.wordWrap = "break-word";
|
|
2374
|
+
mirror.textContent = textarea.value.slice(0, caret);
|
|
2375
|
+
const marker = document.createElement("span");
|
|
2376
|
+
marker.textContent = "\u200B";
|
|
2377
|
+
mirror.appendChild(marker);
|
|
2378
|
+
document.body.appendChild(mirror);
|
|
2379
|
+
const taRect = textarea.getBoundingClientRect();
|
|
2380
|
+
const markerRect = marker.getBoundingClientRect();
|
|
2381
|
+
const mirrorRect = mirror.getBoundingClientRect();
|
|
2382
|
+
const x = taRect.left + (markerRect.left - mirrorRect.left) - textarea.scrollLeft;
|
|
2383
|
+
const y = taRect.top + (markerRect.top - mirrorRect.top) - textarea.scrollTop;
|
|
2384
|
+
const out = new DOMRect(x, y, 0, markerRect.height || 16);
|
|
2385
|
+
document.body.removeChild(mirror);
|
|
2386
|
+
return out;
|
|
2449
2387
|
}
|
|
2450
|
-
function
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2388
|
+
function useTextareaCommands({
|
|
2389
|
+
textareaRef,
|
|
2390
|
+
value,
|
|
2391
|
+
onChange,
|
|
2392
|
+
commands,
|
|
2393
|
+
trigger = "/",
|
|
2394
|
+
openOnEmptyTrigger = true,
|
|
2395
|
+
maxItems = 8
|
|
2396
|
+
}) {
|
|
2397
|
+
const [isOpen, setIsOpen] = (0, import_react17.useState)(false);
|
|
2398
|
+
const [query, setQuery] = (0, import_react17.useState)("");
|
|
2399
|
+
const [activeIndex, setActiveIndex] = (0, import_react17.useState)(0);
|
|
2400
|
+
const [triggerIndex, setTriggerIndex] = (0, import_react17.useState)(null);
|
|
2401
|
+
const [caretRect, setCaretRect] = (0, import_react17.useState)(null);
|
|
2402
|
+
const dismissedAtRef = (0, import_react17.useRef)(
|
|
2403
|
+
null
|
|
2404
|
+
);
|
|
2405
|
+
const items = (0, import_react17.useMemo)(() => {
|
|
2406
|
+
const q = query.trim().toLowerCase();
|
|
2407
|
+
if (!q) return commands.slice(0, maxItems);
|
|
2408
|
+
return commands.filter((c) => {
|
|
2409
|
+
const hay = [
|
|
2410
|
+
typeof c.label === "string" ? c.label : "",
|
|
2411
|
+
typeof c.description === "string" ? c.description : "",
|
|
2412
|
+
c.id,
|
|
2413
|
+
...c.keywords ?? []
|
|
2414
|
+
].join(" ").toLowerCase();
|
|
2415
|
+
return hay.includes(q);
|
|
2416
|
+
}).slice(0, maxItems);
|
|
2417
|
+
}, [commands, query, maxItems]);
|
|
2418
|
+
(0, import_react17.useEffect)(() => {
|
|
2419
|
+
const ta = textareaRef.current;
|
|
2420
|
+
if (!ta) return;
|
|
2421
|
+
const caret = ta.selectionStart ?? 0;
|
|
2422
|
+
const dismissedAt = dismissedAtRef.current;
|
|
2423
|
+
if (dismissedAt && dismissedAt.value === value && dismissedAt.caret === caret) {
|
|
2424
|
+
return;
|
|
2461
2425
|
}
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2426
|
+
const found = findOpenTrigger(value, caret, trigger);
|
|
2427
|
+
if (!found) {
|
|
2428
|
+
if (isOpen) setIsOpen(false);
|
|
2429
|
+
setTriggerIndex(null);
|
|
2430
|
+
return;
|
|
2467
2431
|
}
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
});
|
|
2476
|
-
if (settled) lines.push({ id: "errors", text: "\u2713 error handling attached", tone: "done" });
|
|
2477
|
-
return lines.slice(-8);
|
|
2478
|
-
}
|
|
2479
|
-
function slugify(value) {
|
|
2480
|
-
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "your-team";
|
|
2481
|
-
}
|
|
2482
|
-
function isValidEmail(value) {
|
|
2483
|
-
return /^\S+@\S+\.\S+$/.test(value.trim());
|
|
2484
|
-
}
|
|
2485
|
-
|
|
2486
|
-
// src/marketing/components/BetaAccessForm/BetaAccessForm.tsx
|
|
2487
|
-
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
2488
|
-
function BetaAccessForm({
|
|
2489
|
-
title = "Request early access",
|
|
2490
|
-
subtitle = "CURRENTLY IN PRIVATE BETA \u2014 WE REVIEW ACCESS REQUESTS WEEKLY",
|
|
2491
|
-
fields = "email",
|
|
2492
|
-
appearance = "card",
|
|
2493
|
-
teamSizes,
|
|
2494
|
-
plans,
|
|
2495
|
-
defaultPlan,
|
|
2496
|
-
submitLabel = "Request access \u2192",
|
|
2497
|
-
footnote = "NO CREDIT CARD \xB7 SSO & SELF-HOSTING AVAILABLE",
|
|
2498
|
-
onSubmit,
|
|
2499
|
-
successTitle = "Request received.",
|
|
2500
|
-
successBody = "We review access requests weekly \u2014 you'll hear from us by email.",
|
|
2501
|
-
disabled = false,
|
|
2502
|
-
className
|
|
2503
|
-
}) {
|
|
2504
|
-
const uid = (0, import_react17.useId)();
|
|
2505
|
-
const [values, setValues] = (0, import_react17.useState)({
|
|
2506
|
-
email: "",
|
|
2507
|
-
name: "",
|
|
2508
|
-
company: "",
|
|
2509
|
-
teamSize: "",
|
|
2510
|
-
plan: defaultPlan ?? ""
|
|
2511
|
-
});
|
|
2512
|
-
const [phase, setPhase] = (0, import_react17.useState)("idle");
|
|
2513
|
-
const [error, setError] = (0, import_react17.useState)(null);
|
|
2514
|
-
const handleSubmit = async (event) => {
|
|
2515
|
-
event.preventDefault();
|
|
2516
|
-
if (phase === "submitting") return;
|
|
2517
|
-
if (!isValidEmail(values.email)) {
|
|
2518
|
-
setError("Please enter a valid work email.");
|
|
2519
|
-
return;
|
|
2520
|
-
}
|
|
2521
|
-
if (fields === "full" && !values.name?.trim()) {
|
|
2522
|
-
setError("Please enter your name.");
|
|
2523
|
-
return;
|
|
2524
|
-
}
|
|
2525
|
-
if (fields === "full" && teamSizes?.length && !values.teamSize) {
|
|
2526
|
-
setError("Please select your team size.");
|
|
2527
|
-
return;
|
|
2528
|
-
}
|
|
2529
|
-
setError(null);
|
|
2530
|
-
setPhase("submitting");
|
|
2531
|
-
try {
|
|
2532
|
-
await onSubmit?.(values);
|
|
2533
|
-
setPhase("success");
|
|
2534
|
-
} catch {
|
|
2535
|
-
setError("Something went wrong \u2014 please try again.");
|
|
2536
|
-
setPhase("idle");
|
|
2432
|
+
if (dismissedAt) dismissedAtRef.current = null;
|
|
2433
|
+
if (found.query.length > 0 || openOnEmptyTrigger) {
|
|
2434
|
+
setQuery(found.query);
|
|
2435
|
+
setTriggerIndex(found.triggerIndex);
|
|
2436
|
+
setIsOpen(true);
|
|
2437
|
+
setActiveIndex(0);
|
|
2438
|
+
setCaretRect(getCaretRect(ta, caret));
|
|
2537
2439
|
}
|
|
2538
|
-
};
|
|
2539
|
-
const
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2440
|
+
}, [value, trigger, openOnEmptyTrigger, isOpen, textareaRef]);
|
|
2441
|
+
const commit = (0, import_react17.useCallback)(
|
|
2442
|
+
(cmd) => {
|
|
2443
|
+
const ta = textareaRef.current;
|
|
2444
|
+
if (!ta || triggerIndex == null) return;
|
|
2445
|
+
const insertText = typeof cmd.insert === "function" ? cmd.insert(query) : cmd.insert;
|
|
2446
|
+
const caret = ta.selectionStart ?? value.length;
|
|
2447
|
+
const before = value.slice(0, triggerIndex);
|
|
2448
|
+
const after = value.slice(caret);
|
|
2449
|
+
const next = `${before}${insertText}${after}`;
|
|
2450
|
+
dismissedAtRef.current = {
|
|
2451
|
+
value,
|
|
2452
|
+
caret
|
|
2453
|
+
};
|
|
2454
|
+
onChange(next);
|
|
2455
|
+
setIsOpen(false);
|
|
2456
|
+
setTriggerIndex(null);
|
|
2457
|
+
requestAnimationFrame(() => {
|
|
2458
|
+
const pos = before.length + insertText.length;
|
|
2459
|
+
ta.focus();
|
|
2460
|
+
ta.setSelectionRange(pos, pos);
|
|
2461
|
+
});
|
|
2462
|
+
},
|
|
2463
|
+
[textareaRef, triggerIndex, query, value, onChange]
|
|
2464
|
+
);
|
|
2465
|
+
const dismiss = (0, import_react17.useCallback)(() => {
|
|
2466
|
+
const ta = textareaRef.current;
|
|
2467
|
+
dismissedAtRef.current = {
|
|
2468
|
+
value,
|
|
2469
|
+
caret: ta?.selectionStart ?? value.length
|
|
2470
|
+
};
|
|
2471
|
+
setIsOpen(false);
|
|
2472
|
+
setTriggerIndex(null);
|
|
2473
|
+
}, [textareaRef, value]);
|
|
2474
|
+
const onKeyDown = (0, import_react17.useCallback)(
|
|
2475
|
+
(e) => {
|
|
2476
|
+
if (!isOpen) return false;
|
|
2477
|
+
if (e.key === "ArrowDown") {
|
|
2478
|
+
e.preventDefault();
|
|
2479
|
+
setActiveIndex((i) => Math.min(items.length - 1, i + 1));
|
|
2480
|
+
return true;
|
|
2558
2481
|
}
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
children: [
|
|
2581
|
-
fields === "full" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
2582
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "ods-mkt-access__label", htmlFor: `${uid}-name`, children: "Full name" }),
|
|
2583
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2584
|
-
Input,
|
|
2585
|
-
{
|
|
2586
|
-
id: `${uid}-name`,
|
|
2587
|
-
autoComplete: "name",
|
|
2588
|
-
placeholder: "Ada Lovelace",
|
|
2589
|
-
value: values.name ?? "",
|
|
2590
|
-
onChange: (e) => setValues((v) => ({ ...v, name: e.target.value })),
|
|
2591
|
-
disabled: busy
|
|
2592
|
-
}
|
|
2593
|
-
)
|
|
2594
|
-
] }),
|
|
2595
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
2596
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "ods-mkt-access__label", htmlFor: `${uid}-email`, children: "Work email" }),
|
|
2597
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2598
|
-
Input,
|
|
2599
|
-
{
|
|
2600
|
-
id: `${uid}-email`,
|
|
2601
|
-
type: "email",
|
|
2602
|
-
autoComplete: "email",
|
|
2603
|
-
placeholder: "ada@company.com",
|
|
2604
|
-
value: values.email,
|
|
2605
|
-
onChange: (e) => setValues((v) => ({ ...v, email: e.target.value })),
|
|
2606
|
-
disabled: busy
|
|
2607
|
-
}
|
|
2608
|
-
)
|
|
2609
|
-
] }),
|
|
2610
|
-
fields === "full" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
2611
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "ods-mkt-access__label", htmlFor: `${uid}-company`, children: "Company" }),
|
|
2612
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2613
|
-
Input,
|
|
2614
|
-
{
|
|
2615
|
-
id: `${uid}-company`,
|
|
2616
|
-
autoComplete: "organization",
|
|
2617
|
-
placeholder: "Acme Inc.",
|
|
2618
|
-
value: values.company ?? "",
|
|
2619
|
-
onChange: (e) => setValues((v) => ({ ...v, company: e.target.value })),
|
|
2620
|
-
disabled: busy
|
|
2621
|
-
}
|
|
2622
|
-
)
|
|
2623
|
-
] }),
|
|
2624
|
-
fields === "full" && teamSizes && teamSizes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
2625
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ods-mkt-access__label", id: `${uid}-teamsize-label`, children: "Team size" }),
|
|
2626
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2627
|
-
Select,
|
|
2628
|
-
{
|
|
2629
|
-
"aria-labelledby": `${uid}-teamsize-label`,
|
|
2630
|
-
placeholder: "Select team size\u2026",
|
|
2631
|
-
options: teamSizes.map((size) => ({ value: size, label: size })),
|
|
2632
|
-
value: values.teamSize ?? "",
|
|
2633
|
-
onChange: (teamSize) => setValues((v) => ({ ...v, teamSize })),
|
|
2634
|
-
disabled: busy
|
|
2635
|
-
}
|
|
2636
|
-
)
|
|
2637
|
-
] }),
|
|
2638
|
-
fields === "full" && plans && plans.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
2639
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ods-mkt-access__label", id: `${uid}-plan-label`, children: "Plan (optional)" }),
|
|
2640
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2641
|
-
Select,
|
|
2642
|
-
{
|
|
2643
|
-
"aria-labelledby": `${uid}-plan-label`,
|
|
2644
|
-
placeholder: "Not sure yet",
|
|
2645
|
-
options: plans.map((plan) => ({ value: plan, label: plan })),
|
|
2646
|
-
value: values.plan ?? "",
|
|
2647
|
-
onChange: (plan) => setValues((v) => ({ ...v, plan })),
|
|
2648
|
-
disabled: busy
|
|
2649
|
-
}
|
|
2650
|
-
)
|
|
2651
|
-
] }),
|
|
2652
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2653
|
-
Button,
|
|
2654
|
-
{
|
|
2655
|
-
type: "submit",
|
|
2656
|
-
variant: "primary",
|
|
2657
|
-
loading: phase === "submitting",
|
|
2658
|
-
disabled,
|
|
2659
|
-
children: submitLabel
|
|
2660
|
-
}
|
|
2661
|
-
)
|
|
2662
|
-
]
|
|
2663
|
-
}
|
|
2664
|
-
),
|
|
2665
|
-
error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "ods-mkt-access__error", role: "alert", children: error }),
|
|
2666
|
-
footnote && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "ods-mkt-access__footnote", children: footnote })
|
|
2667
|
-
]
|
|
2668
|
-
}
|
|
2482
|
+
if (e.key === "ArrowUp") {
|
|
2483
|
+
e.preventDefault();
|
|
2484
|
+
setActiveIndex((i) => Math.max(0, i - 1));
|
|
2485
|
+
return true;
|
|
2486
|
+
}
|
|
2487
|
+
if (e.key === "Enter" || e.key === "Tab") {
|
|
2488
|
+
const pick = items[activeIndex];
|
|
2489
|
+
if (pick) {
|
|
2490
|
+
e.preventDefault();
|
|
2491
|
+
commit(pick);
|
|
2492
|
+
return true;
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
if (e.key === "Escape") {
|
|
2496
|
+
e.preventDefault();
|
|
2497
|
+
dismiss();
|
|
2498
|
+
return true;
|
|
2499
|
+
}
|
|
2500
|
+
return false;
|
|
2501
|
+
},
|
|
2502
|
+
[isOpen, items, activeIndex, commit, dismiss]
|
|
2669
2503
|
);
|
|
2504
|
+
return {
|
|
2505
|
+
isOpen,
|
|
2506
|
+
query,
|
|
2507
|
+
activeIndex,
|
|
2508
|
+
items,
|
|
2509
|
+
onKeyDown,
|
|
2510
|
+
dismiss,
|
|
2511
|
+
commit,
|
|
2512
|
+
caretRect
|
|
2513
|
+
};
|
|
2670
2514
|
}
|
|
2671
2515
|
|
|
2672
|
-
// src/
|
|
2673
|
-
var import_react20 = require("react");
|
|
2674
|
-
|
|
2675
|
-
// src/components/Avatar/Avatar.tsx
|
|
2516
|
+
// src/hooks/useTextareaSelection.ts
|
|
2676
2517
|
var import_react18 = require("react");
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2518
|
+
function getSelectionRect(textarea, start, end) {
|
|
2519
|
+
if (typeof document === "undefined") return null;
|
|
2520
|
+
if (start === end) return null;
|
|
2521
|
+
const mirror = document.createElement("div");
|
|
2522
|
+
const styles = window.getComputedStyle(textarea);
|
|
2523
|
+
for (const prop of [
|
|
2524
|
+
"boxSizing",
|
|
2525
|
+
"width",
|
|
2526
|
+
"fontFamily",
|
|
2527
|
+
"fontSize",
|
|
2528
|
+
"fontWeight",
|
|
2529
|
+
"fontStyle",
|
|
2530
|
+
"letterSpacing",
|
|
2531
|
+
"lineHeight",
|
|
2532
|
+
"paddingTop",
|
|
2533
|
+
"paddingRight",
|
|
2534
|
+
"paddingBottom",
|
|
2535
|
+
"paddingLeft",
|
|
2536
|
+
"borderTopWidth",
|
|
2537
|
+
"borderRightWidth",
|
|
2538
|
+
"borderBottomWidth",
|
|
2539
|
+
"borderLeftWidth",
|
|
2540
|
+
"textTransform",
|
|
2541
|
+
"wordSpacing",
|
|
2542
|
+
"tabSize",
|
|
2543
|
+
"whiteSpace"
|
|
2544
|
+
]) {
|
|
2545
|
+
mirror.style[prop] = styles[prop];
|
|
2693
2546
|
}
|
|
2694
|
-
|
|
2547
|
+
mirror.style.position = "absolute";
|
|
2548
|
+
mirror.style.visibility = "hidden";
|
|
2549
|
+
mirror.style.overflow = "hidden";
|
|
2550
|
+
mirror.style.top = "0";
|
|
2551
|
+
mirror.style.left = "0";
|
|
2552
|
+
mirror.style.whiteSpace = "pre-wrap";
|
|
2553
|
+
mirror.style.wordWrap = "break-word";
|
|
2554
|
+
const pre = document.createTextNode(textarea.value.slice(0, start));
|
|
2555
|
+
const range = document.createElement("span");
|
|
2556
|
+
range.textContent = textarea.value.slice(start, end) || "\u200B";
|
|
2557
|
+
const post = document.createTextNode(textarea.value.slice(end));
|
|
2558
|
+
mirror.appendChild(pre);
|
|
2559
|
+
mirror.appendChild(range);
|
|
2560
|
+
mirror.appendChild(post);
|
|
2561
|
+
document.body.appendChild(mirror);
|
|
2562
|
+
const taRect = textarea.getBoundingClientRect();
|
|
2563
|
+
const rangeRect = range.getBoundingClientRect();
|
|
2564
|
+
const mirrorRect = mirror.getBoundingClientRect();
|
|
2565
|
+
const out = new DOMRect(
|
|
2566
|
+
taRect.left + (rangeRect.left - mirrorRect.left) - textarea.scrollLeft,
|
|
2567
|
+
taRect.top + (rangeRect.top - mirrorRect.top) - textarea.scrollTop,
|
|
2568
|
+
rangeRect.width,
|
|
2569
|
+
rangeRect.height
|
|
2570
|
+
);
|
|
2571
|
+
document.body.removeChild(mirror);
|
|
2572
|
+
return out;
|
|
2695
2573
|
}
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2574
|
+
function useTextareaSelection({
|
|
2575
|
+
textareaRef,
|
|
2576
|
+
value,
|
|
2577
|
+
onChange
|
|
2578
|
+
}) {
|
|
2579
|
+
const [start, setStart] = (0, import_react18.useState)(0);
|
|
2580
|
+
const [end, setEnd] = (0, import_react18.useState)(0);
|
|
2581
|
+
const [rect, setRect] = (0, import_react18.useState)(null);
|
|
2582
|
+
(0, import_react18.useEffect)(() => {
|
|
2583
|
+
if (typeof document === "undefined") return;
|
|
2584
|
+
const handler = () => {
|
|
2585
|
+
const ta = textareaRef.current;
|
|
2586
|
+
if (!ta || document.activeElement !== ta) {
|
|
2587
|
+
setStart(0);
|
|
2588
|
+
setEnd(0);
|
|
2589
|
+
setRect(null);
|
|
2590
|
+
return;
|
|
2591
|
+
}
|
|
2592
|
+
const s = ta.selectionStart ?? 0;
|
|
2593
|
+
const e = ta.selectionEnd ?? 0;
|
|
2594
|
+
setStart(s);
|
|
2595
|
+
setEnd(e);
|
|
2596
|
+
setRect(s !== e ? getSelectionRect(ta, s, e) : null);
|
|
2597
|
+
};
|
|
2598
|
+
document.addEventListener("selectionchange", handler);
|
|
2599
|
+
return () => document.removeEventListener("selectionchange", handler);
|
|
2600
|
+
}, [textareaRef]);
|
|
2601
|
+
const active = start !== end;
|
|
2602
|
+
const text = active ? value.slice(start, end) : "";
|
|
2603
|
+
const writeToClipboard = (0, import_react18.useCallback)(
|
|
2604
|
+
async (str) => {
|
|
2605
|
+
try {
|
|
2606
|
+
if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) {
|
|
2607
|
+
await navigator.clipboard.writeText(str);
|
|
2608
|
+
return true;
|
|
2609
|
+
}
|
|
2610
|
+
} catch {
|
|
2611
|
+
}
|
|
2612
|
+
try {
|
|
2613
|
+
const tmp = document.createElement("textarea");
|
|
2614
|
+
tmp.value = str;
|
|
2615
|
+
tmp.style.position = "fixed";
|
|
2616
|
+
tmp.style.left = "-9999px";
|
|
2617
|
+
document.body.appendChild(tmp);
|
|
2618
|
+
tmp.select();
|
|
2619
|
+
const ok = document.execCommand("copy");
|
|
2620
|
+
document.body.removeChild(tmp);
|
|
2621
|
+
return ok;
|
|
2622
|
+
} catch {
|
|
2623
|
+
return false;
|
|
2624
|
+
}
|
|
2625
|
+
},
|
|
2626
|
+
[]
|
|
2725
2627
|
);
|
|
2726
|
-
const
|
|
2727
|
-
|
|
2728
|
-
return
|
|
2729
|
-
}, [
|
|
2730
|
-
const
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
`ods-avatar--${size}`,
|
|
2744
|
-
`ods-avatar--${shape}`,
|
|
2745
|
-
isClickable && "ods-avatar--clickable",
|
|
2746
|
-
className
|
|
2628
|
+
const copy = (0, import_react18.useCallback)(async () => {
|
|
2629
|
+
if (!active) return false;
|
|
2630
|
+
return writeToClipboard(text);
|
|
2631
|
+
}, [active, text, writeToClipboard]);
|
|
2632
|
+
const replace = (0, import_react18.useCallback)(
|
|
2633
|
+
(str) => {
|
|
2634
|
+
const ta = textareaRef.current;
|
|
2635
|
+
if (!ta) return;
|
|
2636
|
+
const next = value.slice(0, start) + str + value.slice(end);
|
|
2637
|
+
onChange(next);
|
|
2638
|
+
requestAnimationFrame(() => {
|
|
2639
|
+
ta.focus();
|
|
2640
|
+
const caret = start + str.length;
|
|
2641
|
+
ta.setSelectionRange(caret, caret);
|
|
2642
|
+
});
|
|
2643
|
+
},
|
|
2644
|
+
[textareaRef, value, start, end, onChange]
|
|
2747
2645
|
);
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
}
|
|
2773
|
-
) : icon ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "ods-avatar__icon", "aria-hidden": "true", children: icon }) : normalizedInitials ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "ods-avatar__initials", "aria-hidden": "true", children: normalizedInitials }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "ods-avatar__initials", "aria-hidden": "true", children: fallback ?? "?" }) }),
|
|
2774
|
-
status && // Decorative — the textual status is folded into the wrapper's
|
|
2775
|
-
// aria-label above. `aria-hidden` keeps AT from double-announcing.
|
|
2776
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2777
|
-
"span",
|
|
2778
|
-
{
|
|
2779
|
-
className: cn("ods-avatar__status", `ods-avatar__status--${status}`),
|
|
2780
|
-
"aria-hidden": "true"
|
|
2781
|
-
}
|
|
2782
|
-
)
|
|
2783
|
-
]
|
|
2784
|
-
}
|
|
2646
|
+
const cut = (0, import_react18.useCallback)(async () => {
|
|
2647
|
+
if (!active) return false;
|
|
2648
|
+
const ok = await writeToClipboard(text);
|
|
2649
|
+
if (ok) replace("");
|
|
2650
|
+
return ok;
|
|
2651
|
+
}, [active, text, writeToClipboard, replace]);
|
|
2652
|
+
const wrap = (0, import_react18.useCallback)(
|
|
2653
|
+
(open, close) => {
|
|
2654
|
+
const ta = textareaRef.current;
|
|
2655
|
+
if (!ta) return;
|
|
2656
|
+
const closing = close ?? open;
|
|
2657
|
+
const before = value.slice(0, start);
|
|
2658
|
+
const sel = value.slice(start, end);
|
|
2659
|
+
const after = value.slice(end);
|
|
2660
|
+
const next = `${before}${open}${sel}${closing}${after}`;
|
|
2661
|
+
onChange(next);
|
|
2662
|
+
requestAnimationFrame(() => {
|
|
2663
|
+
ta.focus();
|
|
2664
|
+
const newStart = start;
|
|
2665
|
+
const newEnd = end + open.length + closing.length;
|
|
2666
|
+
ta.setSelectionRange(newStart, newEnd);
|
|
2667
|
+
});
|
|
2668
|
+
},
|
|
2669
|
+
[textareaRef, value, start, end, onChange]
|
|
2785
2670
|
);
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
const arr = Array.isArray(children) ? children : [children];
|
|
2799
|
-
const visible = max && arr.length > max ? arr.slice(0, max) : arr;
|
|
2800
|
-
const overflow = max && arr.length > max ? arr.length - max : 0;
|
|
2801
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2802
|
-
"div",
|
|
2803
|
-
{
|
|
2804
|
-
...rest,
|
|
2805
|
-
ref,
|
|
2806
|
-
className: cn(
|
|
2807
|
-
"ods-avatar-stack",
|
|
2808
|
-
`ods-avatar-stack--${direction}`,
|
|
2809
|
-
className
|
|
2810
|
-
),
|
|
2811
|
-
children: [
|
|
2812
|
-
visible,
|
|
2813
|
-
overflow > 0 && (renderOverflow ? renderOverflow(overflow) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2814
|
-
"div",
|
|
2815
|
-
{
|
|
2816
|
-
className: cn(
|
|
2817
|
-
"ods-avatar",
|
|
2818
|
-
`ods-avatar--${size}`,
|
|
2819
|
-
"ods-avatar--circle",
|
|
2820
|
-
"ods-avatar-stack__overflow"
|
|
2821
|
-
),
|
|
2822
|
-
role: "img",
|
|
2823
|
-
"aria-label": `${overflow} more`,
|
|
2824
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "ods-avatar__inner", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "ods-avatar__initials", "aria-hidden": "true", children: [
|
|
2825
|
-
"+",
|
|
2826
|
-
overflow
|
|
2827
|
-
] }) })
|
|
2828
|
-
}
|
|
2829
|
-
))
|
|
2830
|
-
]
|
|
2831
|
-
}
|
|
2832
|
-
);
|
|
2833
|
-
}
|
|
2834
|
-
);
|
|
2835
|
-
AvatarStack.displayName = "AvatarStack";
|
|
2671
|
+
return {
|
|
2672
|
+
active,
|
|
2673
|
+
text,
|
|
2674
|
+
start,
|
|
2675
|
+
end,
|
|
2676
|
+
rect,
|
|
2677
|
+
copy,
|
|
2678
|
+
cut,
|
|
2679
|
+
wrap,
|
|
2680
|
+
replace
|
|
2681
|
+
};
|
|
2682
|
+
}
|
|
2836
2683
|
|
|
2837
|
-
// src/
|
|
2838
|
-
var
|
|
2684
|
+
// src/hooks/useTextareaTools.tsx
|
|
2685
|
+
var import_icons3 = require("@octaviaflow/icons");
|
|
2839
2686
|
var import_react19 = require("react");
|
|
2840
|
-
var
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
{
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2687
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
2688
|
+
function useTextareaTools({
|
|
2689
|
+
textareaRef,
|
|
2690
|
+
value,
|
|
2691
|
+
onChange,
|
|
2692
|
+
tools
|
|
2693
|
+
}) {
|
|
2694
|
+
const valueRef = (0, import_react19.useRef)(value);
|
|
2695
|
+
valueRef.current = value;
|
|
2696
|
+
const helpers = (0, import_react19.useMemo)(() => {
|
|
2697
|
+
const getTa = () => textareaRef.current;
|
|
2698
|
+
const getSelection = () => {
|
|
2699
|
+
const ta = getTa();
|
|
2700
|
+
const s = ta?.selectionStart ?? 0;
|
|
2701
|
+
const e = ta?.selectionEnd ?? 0;
|
|
2702
|
+
return {
|
|
2703
|
+
text: valueRef.current.slice(s, e),
|
|
2704
|
+
start: s,
|
|
2705
|
+
end: e,
|
|
2706
|
+
active: s !== e
|
|
2707
|
+
};
|
|
2708
|
+
};
|
|
2709
|
+
const setValue = (next) => onChange(next);
|
|
2710
|
+
const replace = (text) => {
|
|
2711
|
+
const ta = getTa();
|
|
2712
|
+
if (!ta) return;
|
|
2713
|
+
const { start, end } = getSelection();
|
|
2714
|
+
const next = valueRef.current.slice(0, start) + text + valueRef.current.slice(end);
|
|
2715
|
+
onChange(next);
|
|
2716
|
+
requestAnimationFrame(() => {
|
|
2717
|
+
ta.focus();
|
|
2718
|
+
const caret = start + text.length;
|
|
2719
|
+
ta.setSelectionRange(caret, caret);
|
|
2720
|
+
});
|
|
2721
|
+
};
|
|
2722
|
+
const insert = (text) => replace(text);
|
|
2723
|
+
const wrap = (open, close) => {
|
|
2724
|
+
const ta = getTa();
|
|
2725
|
+
if (!ta) return;
|
|
2726
|
+
const closing = close ?? open;
|
|
2727
|
+
const { start, end } = getSelection();
|
|
2728
|
+
const sel = valueRef.current.slice(start, end);
|
|
2729
|
+
const next = valueRef.current.slice(0, start) + open + sel + closing + valueRef.current.slice(end);
|
|
2730
|
+
onChange(next);
|
|
2731
|
+
requestAnimationFrame(() => {
|
|
2732
|
+
ta.focus();
|
|
2733
|
+
if (start === end) {
|
|
2734
|
+
const caret = start + open.length;
|
|
2735
|
+
ta.setSelectionRange(caret, caret);
|
|
2736
|
+
} else {
|
|
2737
|
+
ta.setSelectionRange(start, end + open.length + closing.length);
|
|
2738
|
+
}
|
|
2739
|
+
});
|
|
2740
|
+
};
|
|
2741
|
+
const prependLines = (prefix) => {
|
|
2742
|
+
const ta = getTa();
|
|
2743
|
+
if (!ta) return;
|
|
2744
|
+
const { start, end } = getSelection();
|
|
2745
|
+
const v = valueRef.current;
|
|
2746
|
+
const lineStart = v.lastIndexOf("\n", start - 1) + 1;
|
|
2747
|
+
const lineEnd = (() => {
|
|
2748
|
+
const idx = v.indexOf("\n", end);
|
|
2749
|
+
return idx === -1 ? v.length : idx;
|
|
2750
|
+
})();
|
|
2751
|
+
const block = v.slice(lineStart, lineEnd);
|
|
2752
|
+
const updated = block.split("\n").map((line) => `${prefix}${line}`).join("\n");
|
|
2753
|
+
const next = v.slice(0, lineStart) + updated + v.slice(lineEnd);
|
|
2754
|
+
onChange(next);
|
|
2755
|
+
requestAnimationFrame(() => {
|
|
2756
|
+
ta.focus();
|
|
2757
|
+
ta.setSelectionRange(
|
|
2758
|
+
lineStart,
|
|
2759
|
+
lineStart + updated.length
|
|
2760
|
+
);
|
|
2761
|
+
});
|
|
2762
|
+
};
|
|
2763
|
+
const undo = () => {
|
|
2764
|
+
try {
|
|
2765
|
+
getTa()?.focus();
|
|
2766
|
+
document.execCommand("undo");
|
|
2767
|
+
} catch {
|
|
2888
2768
|
}
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
{
|
|
2895
|
-
...rest,
|
|
2896
|
-
ref,
|
|
2897
|
-
className: rootClassName,
|
|
2898
|
-
"aria-busy": "true",
|
|
2899
|
-
"aria-label": "Loading",
|
|
2900
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "ods-card__skeleton", "data-ods-animate": "shimmer" })
|
|
2769
|
+
};
|
|
2770
|
+
const redo = () => {
|
|
2771
|
+
try {
|
|
2772
|
+
getTa()?.focus();
|
|
2773
|
+
document.execCommand("redo");
|
|
2774
|
+
} catch {
|
|
2901
2775
|
}
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
}
|
|
2776
|
+
};
|
|
2777
|
+
return {
|
|
2778
|
+
get value() {
|
|
2779
|
+
return valueRef.current;
|
|
2780
|
+
},
|
|
2781
|
+
get selection() {
|
|
2782
|
+
return getSelection();
|
|
2783
|
+
},
|
|
2784
|
+
setValue,
|
|
2785
|
+
replace,
|
|
2786
|
+
insert,
|
|
2787
|
+
wrap,
|
|
2788
|
+
prependLines,
|
|
2789
|
+
undo,
|
|
2790
|
+
redo,
|
|
2791
|
+
getTextarea: getTa
|
|
2792
|
+
};
|
|
2793
|
+
}, [textareaRef, onChange]);
|
|
2794
|
+
const visibleTools = (0, import_react19.useMemo)(
|
|
2795
|
+
() => tools.filter((t) => t.isVisible ? t.isVisible(helpers) : true),
|
|
2796
|
+
[tools, helpers]
|
|
2919
2797
|
);
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { ...rest, ref, className: cn("ods-card__body", className), children });
|
|
2931
|
-
}
|
|
2932
|
-
);
|
|
2933
|
-
CardBody.displayName = "Card.Body";
|
|
2934
|
-
var CardFooter = (0, import_react19.forwardRef)(
|
|
2935
|
-
function CardFooter2({ className, children, ...rest }, ref) {
|
|
2936
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { ...rest, ref, className: cn("ods-card__footer", className), children });
|
|
2937
|
-
}
|
|
2938
|
-
);
|
|
2939
|
-
CardFooter.displayName = "Card.Footer";
|
|
2940
|
-
var CardTitle = (0, import_react19.forwardRef)(
|
|
2941
|
-
function CardTitle2({ as: Comp = "h3", className, children, ...rest }, ref) {
|
|
2942
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2943
|
-
Comp,
|
|
2944
|
-
{
|
|
2945
|
-
...rest,
|
|
2946
|
-
ref,
|
|
2947
|
-
className: cn("ods-card__title", className),
|
|
2948
|
-
children
|
|
2949
|
-
}
|
|
2950
|
-
);
|
|
2951
|
-
}
|
|
2952
|
-
);
|
|
2953
|
-
CardTitle.displayName = "Card.Title";
|
|
2954
|
-
var CardDescription = (0, import_react19.forwardRef)(function CardDescription2({ className, children, ...rest }, ref) {
|
|
2955
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { ...rest, ref, className: cn("ods-card__description", className), children });
|
|
2956
|
-
});
|
|
2957
|
-
CardDescription.displayName = "Card.Description";
|
|
2958
|
-
Card.Header = CardHeader;
|
|
2959
|
-
Card.Body = CardBody;
|
|
2960
|
-
Card.Footer = CardFooter;
|
|
2961
|
-
Card.Title = CardTitle;
|
|
2962
|
-
Card.Description = CardDescription;
|
|
2798
|
+
const runTool = (0, import_react19.useCallback)(
|
|
2799
|
+
async (id) => {
|
|
2800
|
+
const tool = tools.find((t) => t.id === id);
|
|
2801
|
+
if (!tool || tool.kind === "divider") return;
|
|
2802
|
+
await tool.onAction?.(helpers);
|
|
2803
|
+
},
|
|
2804
|
+
[tools, helpers]
|
|
2805
|
+
);
|
|
2806
|
+
return { tools: visibleTools, runTool, helpers };
|
|
2807
|
+
}
|
|
2963
2808
|
|
|
2964
|
-
// src/components/
|
|
2965
|
-
var
|
|
2966
|
-
var
|
|
2967
|
-
function
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2809
|
+
// src/components/Textarea/Textarea.tsx
|
|
2810
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
2811
|
+
var Textarea = (0, import_react20.forwardRef)(
|
|
2812
|
+
function Textarea2({
|
|
2813
|
+
label,
|
|
2814
|
+
error = false,
|
|
2815
|
+
errorMessage,
|
|
2816
|
+
helperText,
|
|
2817
|
+
resize = "vertical",
|
|
2818
|
+
autoResize = false,
|
|
2819
|
+
minRows,
|
|
2820
|
+
maxRows,
|
|
2821
|
+
maxHeight,
|
|
2822
|
+
maxWidth,
|
|
2823
|
+
minHeight,
|
|
2824
|
+
minWidth,
|
|
2825
|
+
maxLength,
|
|
2826
|
+
size = "md",
|
|
2827
|
+
rows = 3,
|
|
2828
|
+
disabled = false,
|
|
2984
2829
|
className,
|
|
2985
|
-
|
|
2986
|
-
|
|
2830
|
+
style: consumerStyle,
|
|
2831
|
+
defaultValue,
|
|
2832
|
+
value,
|
|
2833
|
+
onChange,
|
|
2834
|
+
id: providedId,
|
|
2835
|
+
commands,
|
|
2836
|
+
commandTrigger = "/",
|
|
2837
|
+
selectionToolbar = false,
|
|
2838
|
+
selectionActions,
|
|
2839
|
+
tools,
|
|
2840
|
+
toolbarPosition = "top",
|
|
2841
|
+
...props
|
|
2842
|
+
}, forwardedRef) {
|
|
2843
|
+
const innerRef = (0, import_react20.useRef)(null);
|
|
2844
|
+
const setRef = (node) => {
|
|
2845
|
+
innerRef.current = node;
|
|
2846
|
+
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
2847
|
+
else if (forwardedRef)
|
|
2848
|
+
forwardedRef.current = node;
|
|
2849
|
+
};
|
|
2987
2850
|
const reactId = (0, import_react20.useId)();
|
|
2988
|
-
const baseId = providedId ?? `ods-
|
|
2989
|
-
const
|
|
2990
|
-
const
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
2851
|
+
const baseId = providedId ?? `ods-textarea-${reactId}`;
|
|
2852
|
+
const hintId = error && errorMessage || helperText ? `${baseId}-hint` : void 0;
|
|
2853
|
+
const [charCount, setCharCount] = (0, import_react20.useState)(
|
|
2854
|
+
() => String(value ?? defaultValue ?? "").length
|
|
2855
|
+
);
|
|
2856
|
+
const ariaNameProps = resolveAccessibleName({
|
|
2857
|
+
label: typeof label === "string" ? label : void 0,
|
|
2858
|
+
ariaLabel: props["aria-label"],
|
|
2859
|
+
ariaLabelledby: props["aria-labelledby"],
|
|
2860
|
+
componentName: "Textarea"
|
|
2861
|
+
});
|
|
2862
|
+
const { labelProps, inputProps } = (0, import_react_aria4.useTextField)(
|
|
2863
|
+
{
|
|
2864
|
+
label: typeof label === "string" ? label : void 0,
|
|
2865
|
+
...ariaNameProps,
|
|
2866
|
+
isDisabled: disabled,
|
|
2867
|
+
errorMessage: typeof errorMessage === "string" ? errorMessage : void 0,
|
|
2868
|
+
validationState: error ? "invalid" : void 0,
|
|
2869
|
+
inputElementType: "textarea",
|
|
2870
|
+
value,
|
|
2871
|
+
defaultValue
|
|
2872
|
+
},
|
|
2873
|
+
innerRef
|
|
2874
|
+
);
|
|
2875
|
+
const describedBy = [
|
|
2876
|
+
props["aria-describedby"],
|
|
2877
|
+
hintId
|
|
2878
|
+
].filter(Boolean).join(" ") || void 0;
|
|
2879
|
+
const handleChange = (e) => {
|
|
2880
|
+
setCharCount(e.target.value.length);
|
|
2881
|
+
onChange?.(e);
|
|
2882
|
+
};
|
|
2883
|
+
const [liveValue, setLiveValue] = (0, import_react20.useState)(
|
|
2884
|
+
String(value ?? defaultValue ?? "")
|
|
2885
|
+
);
|
|
2886
|
+
(0, import_react20.useEffect)(() => {
|
|
2887
|
+
if (value != null) setLiveValue(String(value));
|
|
2888
|
+
}, [value]);
|
|
2889
|
+
const handleChangeWithMirror = (e) => {
|
|
2890
|
+
setLiveValue(e.target.value);
|
|
2891
|
+
handleChange(e);
|
|
2892
|
+
};
|
|
2893
|
+
const setLiveAndCommit = (next) => {
|
|
2894
|
+
setLiveValue(next);
|
|
2895
|
+
if (innerRef.current) innerRef.current.value = next;
|
|
2896
|
+
onChange?.({
|
|
2897
|
+
target: innerRef.current,
|
|
2898
|
+
currentTarget: innerRef.current
|
|
2899
|
+
});
|
|
2900
|
+
setCharCount(next.length);
|
|
2901
|
+
};
|
|
2902
|
+
const cmdPalette = useTextareaCommands({
|
|
2903
|
+
textareaRef: innerRef,
|
|
2904
|
+
value: liveValue,
|
|
2905
|
+
onChange: setLiveAndCommit,
|
|
2906
|
+
commands: commands ?? [],
|
|
2907
|
+
trigger: commandTrigger
|
|
2908
|
+
});
|
|
2909
|
+
const cmdEnabled = (commands?.length ?? 0) > 0;
|
|
2910
|
+
const sel = useTextareaSelection({
|
|
2911
|
+
textareaRef: innerRef,
|
|
2912
|
+
value: liveValue,
|
|
2913
|
+
onChange: setLiveAndCommit
|
|
2914
|
+
});
|
|
2915
|
+
const toolbar = useTextareaTools({
|
|
2916
|
+
textareaRef: innerRef,
|
|
2917
|
+
value: liveValue,
|
|
2918
|
+
onChange: setLiveAndCommit,
|
|
2919
|
+
tools: tools ?? []
|
|
2920
|
+
});
|
|
2921
|
+
const toolbarEnabled = (tools?.length ?? 0) > 0;
|
|
2922
|
+
const handleKeyDownWithCommands = (e) => {
|
|
2923
|
+
if (cmdEnabled) {
|
|
2924
|
+
const consumed = cmdPalette.onKeyDown(e);
|
|
2925
|
+
if (consumed) return;
|
|
2926
|
+
}
|
|
2927
|
+
props.onKeyDown?.(e);
|
|
2928
|
+
};
|
|
2929
|
+
(0, import_react20.useEffect)(() => {
|
|
2930
|
+
if (!autoResize) return;
|
|
2931
|
+
const el = innerRef.current;
|
|
2932
|
+
if (!el) return;
|
|
2933
|
+
const computed = window.getComputedStyle(el);
|
|
2934
|
+
const fontSize = parseFloat(computed.fontSize) || 16;
|
|
2935
|
+
const lhRaw = computed.lineHeight;
|
|
2936
|
+
const lh = lhRaw === "normal" ? fontSize * 1.2 : lhRaw.endsWith("px") ? parseFloat(lhRaw) : parseFloat(lhRaw) * fontSize;
|
|
2937
|
+
const padding = parseFloat(computed.paddingTop) + parseFloat(computed.paddingBottom);
|
|
2938
|
+
const rowCap = maxRows != null && Number.isFinite(maxRows) ? lh * maxRows + padding : Number.POSITIVE_INFINITY;
|
|
2939
|
+
const pixelCap = typeof maxHeight === "number" ? maxHeight : Number.POSITIVE_INFINITY;
|
|
2940
|
+
const effectiveMax = Math.min(rowCap, pixelCap);
|
|
2941
|
+
const rowFloor = lh * (minRows ?? rows) + padding;
|
|
2942
|
+
el.style.height = "auto";
|
|
2943
|
+
const target = Math.max(
|
|
2944
|
+
rowFloor,
|
|
2945
|
+
Math.min(effectiveMax, el.scrollHeight)
|
|
3074
2946
|
);
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
2947
|
+
el.style.height = `${target}px`;
|
|
2948
|
+
el.style.overflowY = el.scrollHeight > effectiveMax ? "auto" : "hidden";
|
|
2949
|
+
}, [autoResize, value, defaultValue, minRows, maxRows, maxHeight, rows]);
|
|
2950
|
+
const resolvedResize = typeof resize === "boolean" ? resize ? "vertical" : "none" : resize;
|
|
2951
|
+
const toCss = (v) => v == null ? void 0 : typeof v === "number" ? `${v}px` : v;
|
|
2952
|
+
const fieldStyle = {
|
|
2953
|
+
maxHeight: toCss(maxHeight),
|
|
2954
|
+
maxWidth: toCss(maxWidth),
|
|
2955
|
+
minHeight: toCss(minHeight),
|
|
2956
|
+
minWidth: toCss(minWidth),
|
|
2957
|
+
resize: resolvedResize
|
|
2958
|
+
};
|
|
2959
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2960
|
+
"div",
|
|
3078
2961
|
{
|
|
3079
|
-
...rest,
|
|
3080
|
-
ref,
|
|
3081
|
-
id: baseId,
|
|
3082
|
-
radius,
|
|
3083
|
-
padding: "none",
|
|
3084
|
-
onClick,
|
|
3085
2962
|
className: cn(
|
|
3086
|
-
"ods-
|
|
3087
|
-
`ods-
|
|
3088
|
-
|
|
2963
|
+
"ods-textarea",
|
|
2964
|
+
`ods-textarea--${size}`,
|
|
2965
|
+
`ods-textarea--resize-${resolvedResize}`,
|
|
2966
|
+
autoResize && "ods-textarea--auto-resize",
|
|
2967
|
+
error && "ods-textarea--error",
|
|
2968
|
+
disabled && "ods-textarea--disabled",
|
|
3089
2969
|
className
|
|
3090
2970
|
),
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
2971
|
+
style: consumerStyle,
|
|
2972
|
+
children: [
|
|
2973
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2974
|
+
"label",
|
|
2975
|
+
{
|
|
2976
|
+
...labelProps,
|
|
2977
|
+
htmlFor: baseId,
|
|
2978
|
+
className: "ods-textarea__label",
|
|
2979
|
+
children: label
|
|
2980
|
+
}
|
|
2981
|
+
),
|
|
2982
|
+
toolbarEnabled && toolbarPosition === "top" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2983
|
+
TextareaToolbar,
|
|
2984
|
+
{
|
|
2985
|
+
tools: toolbar.tools,
|
|
2986
|
+
onRun: toolbar.runTool
|
|
2987
|
+
}
|
|
2988
|
+
),
|
|
2989
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "ods-textarea__wrapper", children: [
|
|
2990
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2991
|
+
"textarea",
|
|
2992
|
+
{
|
|
2993
|
+
...props,
|
|
2994
|
+
...inputProps,
|
|
2995
|
+
ref: setRef,
|
|
2996
|
+
id: baseId,
|
|
2997
|
+
rows: autoResize ? minRows ?? rows : rows,
|
|
2998
|
+
disabled,
|
|
2999
|
+
maxLength,
|
|
3000
|
+
defaultValue,
|
|
3001
|
+
value,
|
|
3002
|
+
onChange: handleChangeWithMirror,
|
|
3003
|
+
onKeyDown: handleKeyDownWithCommands,
|
|
3004
|
+
className: "ods-textarea__field",
|
|
3005
|
+
style: fieldStyle,
|
|
3006
|
+
"aria-invalid": error || void 0,
|
|
3007
|
+
"aria-describedby": describedBy,
|
|
3008
|
+
"aria-autocomplete": cmdEnabled ? "list" : void 0,
|
|
3009
|
+
"aria-expanded": cmdEnabled ? cmdPalette.isOpen : void 0,
|
|
3010
|
+
"aria-controls": cmdEnabled && cmdPalette.isOpen ? `${baseId}-cmd-list` : void 0,
|
|
3011
|
+
"aria-activedescendant": cmdEnabled && cmdPalette.isOpen && cmdPalette.items[cmdPalette.activeIndex] ? `${baseId}-cmd-${cmdPalette.items[cmdPalette.activeIndex].id}` : void 0
|
|
3012
|
+
}
|
|
3013
|
+
),
|
|
3014
|
+
cmdEnabled && cmdPalette.isOpen && cmdPalette.items.length > 0 && typeof document !== "undefined" && (0, import_react_dom3.createPortal)(
|
|
3015
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3016
|
+
"ul",
|
|
3017
|
+
{
|
|
3018
|
+
id: `${baseId}-cmd-list`,
|
|
3019
|
+
role: "listbox",
|
|
3020
|
+
"aria-label": "Inline commands",
|
|
3021
|
+
className: "ods-textarea__cmd-popover",
|
|
3022
|
+
style: {
|
|
3023
|
+
position: "fixed",
|
|
3024
|
+
top: (cmdPalette.caretRect?.bottom ?? 0) + 6,
|
|
3025
|
+
left: cmdPalette.caretRect?.left ?? 0
|
|
3026
|
+
},
|
|
3027
|
+
children: cmdPalette.items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3028
|
+
"li",
|
|
3029
|
+
{
|
|
3030
|
+
id: `${baseId}-cmd-${c.id}`,
|
|
3031
|
+
role: "option",
|
|
3032
|
+
"aria-selected": i === cmdPalette.activeIndex,
|
|
3033
|
+
className: cn(
|
|
3034
|
+
"ods-textarea__cmd-item",
|
|
3035
|
+
i === cmdPalette.activeIndex && "ods-textarea__cmd-item--active"
|
|
3036
|
+
),
|
|
3037
|
+
onMouseDown: (e) => {
|
|
3038
|
+
e.preventDefault();
|
|
3039
|
+
cmdPalette.commit(c);
|
|
3040
|
+
},
|
|
3041
|
+
onMouseEnter: () => {
|
|
3042
|
+
},
|
|
3043
|
+
children: [
|
|
3044
|
+
c.icon && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "ods-textarea__cmd-icon", children: c.icon }),
|
|
3045
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "ods-textarea__cmd-text", children: [
|
|
3046
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "ods-textarea__cmd-label", children: c.label }),
|
|
3047
|
+
c.description && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "ods-textarea__cmd-desc", children: c.description })
|
|
3048
|
+
] })
|
|
3049
|
+
]
|
|
3050
|
+
},
|
|
3051
|
+
c.id
|
|
3052
|
+
))
|
|
3053
|
+
}
|
|
3054
|
+
),
|
|
3055
|
+
document.body
|
|
3056
|
+
),
|
|
3057
|
+
selectionToolbar && sel.active && sel.rect && typeof document !== "undefined" && (0, import_react_dom3.createPortal)(
|
|
3058
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3059
|
+
"div",
|
|
3060
|
+
{
|
|
3061
|
+
role: "toolbar",
|
|
3062
|
+
"aria-label": "Selection actions",
|
|
3063
|
+
className: "ods-textarea__sel-toolbar",
|
|
3064
|
+
style: {
|
|
3065
|
+
position: "fixed",
|
|
3066
|
+
top: sel.rect.top - 36,
|
|
3067
|
+
left: sel.rect.left
|
|
3068
|
+
},
|
|
3069
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
3070
|
+
children: [
|
|
3071
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3072
|
+
"button",
|
|
3073
|
+
{
|
|
3074
|
+
type: "button",
|
|
3075
|
+
className: "ods-textarea__sel-btn",
|
|
3076
|
+
onClick: () => sel.copy(),
|
|
3077
|
+
"aria-label": "Copy selection",
|
|
3078
|
+
title: "Copy",
|
|
3079
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_icons4.CopyIcon, { size: "xs" })
|
|
3080
|
+
}
|
|
3081
|
+
),
|
|
3082
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3083
|
+
"button",
|
|
3084
|
+
{
|
|
3085
|
+
type: "button",
|
|
3086
|
+
className: "ods-textarea__sel-btn",
|
|
3087
|
+
onClick: () => sel.cut(),
|
|
3088
|
+
"aria-label": "Cut selection",
|
|
3089
|
+
title: "Cut",
|
|
3090
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_icons4.CutIcon, { size: "xs" })
|
|
3091
|
+
}
|
|
3092
|
+
),
|
|
3093
|
+
selectionActions?.map((a) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3094
|
+
"button",
|
|
3095
|
+
{
|
|
3096
|
+
type: "button",
|
|
3097
|
+
className: "ods-textarea__sel-btn",
|
|
3098
|
+
onClick: () => a.onAction(sel.text, {
|
|
3099
|
+
replace: sel.replace,
|
|
3100
|
+
wrap: sel.wrap,
|
|
3101
|
+
copy: sel.copy,
|
|
3102
|
+
cut: sel.cut
|
|
3103
|
+
}),
|
|
3104
|
+
title: typeof a.label === "string" ? a.label : void 0,
|
|
3105
|
+
children: [
|
|
3106
|
+
a.icon,
|
|
3107
|
+
a.label && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "ods-textarea__sel-btn-label", children: a.label })
|
|
3108
|
+
]
|
|
3109
|
+
},
|
|
3110
|
+
a.id
|
|
3111
|
+
))
|
|
3112
|
+
]
|
|
3113
|
+
}
|
|
3114
|
+
),
|
|
3115
|
+
document.body
|
|
3116
|
+
),
|
|
3117
|
+
maxLength != null && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
3118
|
+
"span",
|
|
3119
|
+
{
|
|
3120
|
+
className: "ods-textarea__count",
|
|
3121
|
+
"aria-live": charCount > maxLength ? "polite" : "off",
|
|
3122
|
+
children: [
|
|
3123
|
+
charCount,
|
|
3124
|
+
"/",
|
|
3125
|
+
maxLength
|
|
3126
|
+
]
|
|
3127
|
+
}
|
|
3128
|
+
)
|
|
3129
|
+
] }),
|
|
3130
|
+
toolbarEnabled && toolbarPosition === "bottom" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3131
|
+
TextareaToolbar,
|
|
3132
|
+
{
|
|
3133
|
+
tools: toolbar.tools,
|
|
3134
|
+
onRun: toolbar.runTool
|
|
3135
|
+
}
|
|
3136
|
+
),
|
|
3137
|
+
error && errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3138
|
+
"div",
|
|
3139
|
+
{
|
|
3140
|
+
id: hintId,
|
|
3141
|
+
className: "ods-textarea__error-message",
|
|
3142
|
+
role: "alert",
|
|
3143
|
+
children: errorMessage
|
|
3144
|
+
}
|
|
3145
|
+
) : helperText ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { id: hintId, className: "ods-textarea__hint", children: helperText }) : null
|
|
3146
|
+
]
|
|
3147
|
+
}
|
|
3148
|
+
);
|
|
3149
|
+
}
|
|
3150
|
+
);
|
|
3151
|
+
Textarea.displayName = "Textarea";
|
|
3152
|
+
function TextareaToolbar({
|
|
3153
|
+
tools,
|
|
3154
|
+
onRun
|
|
3109
3155
|
}) {
|
|
3110
|
-
return /* @__PURE__ */ (0,
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
cover: post.cover,
|
|
3121
|
-
author: post.author
|
|
3156
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3157
|
+
"div",
|
|
3158
|
+
{
|
|
3159
|
+
role: "toolbar",
|
|
3160
|
+
"aria-label": "Formatting",
|
|
3161
|
+
className: "ods-textarea__toolbar",
|
|
3162
|
+
onMouseDown: (e) => {
|
|
3163
|
+
if (e.target.closest(".ods-textarea__toolbar-btn")) {
|
|
3164
|
+
e.preventDefault();
|
|
3165
|
+
}
|
|
3122
3166
|
},
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
if (i === 0 || before === " " || before === "\n" || before === " ") {
|
|
3148
|
-
return {
|
|
3149
|
-
triggerIndex: i,
|
|
3150
|
-
query: value.slice(i + trigger.length, caret)
|
|
3151
|
-
};
|
|
3152
|
-
}
|
|
3153
|
-
return null;
|
|
3167
|
+
children: tools.map((t) => {
|
|
3168
|
+
if (t.kind === "divider") {
|
|
3169
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3170
|
+
"span",
|
|
3171
|
+
{
|
|
3172
|
+
className: "ods-textarea__toolbar-divider",
|
|
3173
|
+
"aria-hidden": "true"
|
|
3174
|
+
},
|
|
3175
|
+
t.id
|
|
3176
|
+
);
|
|
3177
|
+
}
|
|
3178
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3179
|
+
"button",
|
|
3180
|
+
{
|
|
3181
|
+
type: "button",
|
|
3182
|
+
className: "ods-textarea__toolbar-btn",
|
|
3183
|
+
title: t.title ?? (typeof t.label === "string" ? t.label : void 0),
|
|
3184
|
+
"aria-label": typeof t.label === "string" ? t.label : t.id,
|
|
3185
|
+
onClick: () => onRun(t.id),
|
|
3186
|
+
children: t.icon ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "ods-textarea__toolbar-icon", children: t.icon }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "ods-textarea__toolbar-text", children: t.label })
|
|
3187
|
+
},
|
|
3188
|
+
t.id
|
|
3189
|
+
);
|
|
3190
|
+
})
|
|
3154
3191
|
}
|
|
3155
|
-
|
|
3156
|
-
}
|
|
3157
|
-
return null;
|
|
3192
|
+
);
|
|
3158
3193
|
}
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
"
|
|
3180
|
-
"
|
|
3181
|
-
"
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3194
|
+
|
|
3195
|
+
// src/marketing/components/WorkflowShowcase/showcaseEngine.ts
|
|
3196
|
+
var SETTLED_PHASES = [
|
|
3197
|
+
"done",
|
|
3198
|
+
"signup",
|
|
3199
|
+
"creating",
|
|
3200
|
+
"welcome"
|
|
3201
|
+
];
|
|
3202
|
+
var WORKFLOW_SHOWCASE_DEFAULT_CONNECTORS = [
|
|
3203
|
+
{ name: "Storefront", role: "source", aliases: ["store", "shop orders"] },
|
|
3204
|
+
{ name: "Payments", role: "source", aliases: ["payouts"] },
|
|
3205
|
+
{ name: "Orders DB", role: "source", aliases: ["orders database"] },
|
|
3206
|
+
{ name: "CRM", role: "source", aliases: ["crm leads"] },
|
|
3207
|
+
{ name: "Warehouse", role: "destination" },
|
|
3208
|
+
{ name: "Lakehouse", role: "destination" },
|
|
3209
|
+
{ name: "Campaigns", role: "action", aliases: ["campaign"] },
|
|
3210
|
+
{ name: "Team Chat", role: "notify", aliases: ["chat", "alert the team"] }
|
|
3211
|
+
];
|
|
3212
|
+
var WORKFLOW_SHOWCASE_DEFAULT_EXAMPLES = [
|
|
3213
|
+
{
|
|
3214
|
+
id: "hourly-sync",
|
|
3215
|
+
label: "Storefront orders \u2192 Warehouse, hourly",
|
|
3216
|
+
prompt: "Sync Storefront orders to Warehouse every hour, alert sales in Team Chat"
|
|
3217
|
+
},
|
|
3218
|
+
{
|
|
3219
|
+
id: "daily-load",
|
|
3220
|
+
label: "Payments payouts \u2192 Lakehouse, daily",
|
|
3221
|
+
prompt: "Load Payments payouts into Lakehouse daily"
|
|
3222
|
+
},
|
|
3223
|
+
{
|
|
3224
|
+
id: "realtime-stream",
|
|
3225
|
+
label: "Orders DB changes \u2192 Warehouse + Team Chat",
|
|
3226
|
+
prompt: "Stream Orders DB changes to Warehouse in real-time and notify Team Chat"
|
|
3186
3227
|
}
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3228
|
+
];
|
|
3229
|
+
var WORKFLOW_SHOWCASE_DEFAULT_METRICS = [
|
|
3230
|
+
{ id: "throughput", value: 2341, buildingValue: 842, unit: "rows/min", label: "THROUGHPUT" },
|
|
3231
|
+
{
|
|
3232
|
+
id: "latency",
|
|
3233
|
+
value: 0.8,
|
|
3234
|
+
buildingValue: 1.1,
|
|
3235
|
+
decimals: 1,
|
|
3236
|
+
unit: "s latency",
|
|
3237
|
+
label: "SYNC SPEED"
|
|
3238
|
+
},
|
|
3239
|
+
{ id: "cost", value: 43, suffix: "%", label: "SAVED VS BASELINE", tone: "success" }
|
|
3240
|
+
];
|
|
3241
|
+
var WORKFLOW_SHOWCASE_SCHEDULES = ["AUTO", "HOURLY", "DAILY", "REAL-TIME"];
|
|
3242
|
+
var WORKFLOW_SHOWCASE_TRIGGERS = ["SCHEDULE", "WEBHOOK", "APP EVENT", "MANUAL"];
|
|
3243
|
+
var WORKFLOW_SHOWCASE_DEFAULT_TILES = [
|
|
3244
|
+
"ELT",
|
|
3245
|
+
"CDC",
|
|
3246
|
+
"LLM",
|
|
3247
|
+
"RAG",
|
|
3248
|
+
"HEAL",
|
|
3249
|
+
"COST",
|
|
3250
|
+
"IDP",
|
|
3251
|
+
"VEC"
|
|
3252
|
+
];
|
|
3253
|
+
function escapeRegExp(value) {
|
|
3254
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3207
3255
|
}
|
|
3208
|
-
function
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
const
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
const
|
|
3223
|
-
|
|
3224
|
-
);
|
|
3225
|
-
const
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
return
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3256
|
+
function mentionsOf(catalog) {
|
|
3257
|
+
const out = [];
|
|
3258
|
+
for (const connector of catalog) {
|
|
3259
|
+
out.push({ connector, pattern: connector.name });
|
|
3260
|
+
for (const alias of connector.aliases ?? []) out.push({ connector, pattern: alias });
|
|
3261
|
+
}
|
|
3262
|
+
return out.sort((a, b) => b.pattern.length - a.pattern.length);
|
|
3263
|
+
}
|
|
3264
|
+
function detectConnectors(prompt, catalog) {
|
|
3265
|
+
const lower = prompt.toLowerCase();
|
|
3266
|
+
return catalog.filter((c) => [c.name, ...c.aliases ?? []].some((p) => lower.includes(p.toLowerCase()))).map((c) => c.name);
|
|
3267
|
+
}
|
|
3268
|
+
function segmentPrompt(prompt, catalog) {
|
|
3269
|
+
if (!prompt) return [];
|
|
3270
|
+
const mentions = mentionsOf(catalog);
|
|
3271
|
+
if (!mentions.length) return [{ text: prompt }];
|
|
3272
|
+
const re = new RegExp(`(${mentions.map((m) => escapeRegExp(m.pattern)).join("|")})`, "gi");
|
|
3273
|
+
const byPattern = new Map(mentions.map((m) => [m.pattern.toLowerCase(), m.connector]));
|
|
3274
|
+
return prompt.split(re).filter((part) => part !== "").map((part) => {
|
|
3275
|
+
const connector = byPattern.get(part.toLowerCase());
|
|
3276
|
+
return connector ? { text: part, connector } : { text: part };
|
|
3277
|
+
});
|
|
3278
|
+
}
|
|
3279
|
+
function scheduleFromPrompt(prompt) {
|
|
3280
|
+
const t = prompt.toLowerCase();
|
|
3281
|
+
if (/stream|real.?time|cdc/.test(t)) return "REAL-TIME";
|
|
3282
|
+
if (/hour/.test(t)) return "HOURLY";
|
|
3283
|
+
if (/dail|every day|nightly/.test(t)) return "DAILY";
|
|
3284
|
+
return null;
|
|
3285
|
+
}
|
|
3286
|
+
var RIGHT_ORDER = {
|
|
3287
|
+
source: -1,
|
|
3288
|
+
destination: 0,
|
|
3289
|
+
action: 1,
|
|
3290
|
+
notify: 2
|
|
3291
|
+
};
|
|
3292
|
+
function resolvePlan(selected, detected, catalog) {
|
|
3293
|
+
const byName = new Map(catalog.map((c) => [c.name, c]));
|
|
3294
|
+
let names = [.../* @__PURE__ */ new Set([...selected, ...detected])].filter((n) => byName.has(n));
|
|
3295
|
+
if (!names.length) {
|
|
3296
|
+
const fallback = [
|
|
3297
|
+
catalog.find((c) => c.role === "source"),
|
|
3298
|
+
catalog.find((c) => c.role === "destination"),
|
|
3299
|
+
catalog.find((c) => c.role === "notify")
|
|
3300
|
+
].filter((c) => Boolean(c));
|
|
3301
|
+
names = fallback.map((c) => c.name);
|
|
3302
|
+
}
|
|
3303
|
+
const has = (predicate) => names.some((n) => {
|
|
3304
|
+
const c = byName.get(n);
|
|
3305
|
+
return Boolean(c && predicate(c));
|
|
3306
|
+
});
|
|
3307
|
+
if (!has((c) => c.role === "source")) {
|
|
3308
|
+
const source = catalog.find((c) => c.role === "source");
|
|
3309
|
+
if (source) names = [source.name, ...names];
|
|
3310
|
+
}
|
|
3311
|
+
if (!has((c) => c.role !== "source")) {
|
|
3312
|
+
const sink = catalog.find((c) => c.role === "notify") ?? catalog.find((c) => c.role !== "source");
|
|
3313
|
+
if (sink) names = [...names, sink.name];
|
|
3314
|
+
}
|
|
3315
|
+
const picked = catalog.filter((c) => names.includes(c.name));
|
|
3316
|
+
const left = picked.filter((c) => c.role === "source");
|
|
3317
|
+
const right = picked.filter((c) => c.role !== "source").sort((a, b) => RIGHT_ORDER[a.role] - RIGHT_ORDER[b.role]);
|
|
3318
|
+
const all = [...left, ...right];
|
|
3319
|
+
return { left, right, all, totalSteps: all.length + 1 };
|
|
3320
|
+
}
|
|
3321
|
+
function stepVerb(role) {
|
|
3322
|
+
if (role === "notify") return "alert";
|
|
3323
|
+
if (role === "action") return "trigger";
|
|
3324
|
+
return "load";
|
|
3325
|
+
}
|
|
3326
|
+
function assembleSteps(plan) {
|
|
3327
|
+
return [
|
|
3328
|
+
...plan.left.map((c) => `${c.name.toLowerCase()} extract`),
|
|
3329
|
+
"schema map \xB7 14 fields",
|
|
3330
|
+
...plan.right.map((c) => `${c.name.toLowerCase()} ${stepVerb(c.role)}`)
|
|
3331
|
+
];
|
|
3332
|
+
}
|
|
3333
|
+
function buildActivity(args) {
|
|
3334
|
+
const { phase, shown, plan, selected, status } = args;
|
|
3335
|
+
const settled = SETTLED_PHASES.includes(phase);
|
|
3336
|
+
const lines = [];
|
|
3337
|
+
if (phase === "idle") {
|
|
3338
|
+
if (!selected.length) {
|
|
3339
|
+
lines.push({ id: "wait", text: "\u25B8 waiting for instructions\u2026", tone: "muted" });
|
|
3340
|
+
lines.push({ id: "hint", text: "\xB7 type a request or pick apps", tone: "faint" });
|
|
3245
3341
|
}
|
|
3246
|
-
const
|
|
3247
|
-
|
|
3248
|
-
if (isOpen) setIsOpen(false);
|
|
3249
|
-
setTriggerIndex(null);
|
|
3250
|
-
return;
|
|
3342
|
+
for (const name of selected.slice(-6)) {
|
|
3343
|
+
lines.push({ id: `sel-${name}`, text: `+ ${name.toLowerCase()} connected`, tone: "plain" });
|
|
3251
3344
|
}
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
setActiveIndex(0);
|
|
3258
|
-
setCaretRect(getCaretRect(ta, caret));
|
|
3345
|
+
return lines;
|
|
3346
|
+
}
|
|
3347
|
+
if (phase === "analyzing") {
|
|
3348
|
+
for (const name of selected.slice(-4)) {
|
|
3349
|
+
lines.push({ id: `sel-${name}`, text: `+ ${name.toLowerCase()} connected`, tone: "muted" });
|
|
3259
3350
|
}
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
(cmd) => {
|
|
3263
|
-
const ta = textareaRef.current;
|
|
3264
|
-
if (!ta || triggerIndex == null) return;
|
|
3265
|
-
const insertText = typeof cmd.insert === "function" ? cmd.insert(query) : cmd.insert;
|
|
3266
|
-
const caret = ta.selectionStart ?? value.length;
|
|
3267
|
-
const before = value.slice(0, triggerIndex);
|
|
3268
|
-
const after = value.slice(caret);
|
|
3269
|
-
const next = `${before}${insertText}${after}`;
|
|
3270
|
-
dismissedAtRef.current = {
|
|
3271
|
-
value,
|
|
3272
|
-
caret
|
|
3273
|
-
};
|
|
3274
|
-
onChange(next);
|
|
3275
|
-
setIsOpen(false);
|
|
3276
|
-
setTriggerIndex(null);
|
|
3277
|
-
requestAnimationFrame(() => {
|
|
3278
|
-
const pos = before.length + insertText.length;
|
|
3279
|
-
ta.focus();
|
|
3280
|
-
ta.setSelectionRange(pos, pos);
|
|
3281
|
-
});
|
|
3282
|
-
},
|
|
3283
|
-
[textareaRef, triggerIndex, query, value, onChange]
|
|
3284
|
-
);
|
|
3285
|
-
const dismiss = (0, import_react21.useCallback)(() => {
|
|
3286
|
-
const ta = textareaRef.current;
|
|
3287
|
-
dismissedAtRef.current = {
|
|
3288
|
-
value,
|
|
3289
|
-
caret: ta?.selectionStart ?? value.length
|
|
3290
|
-
};
|
|
3291
|
-
setIsOpen(false);
|
|
3292
|
-
setTriggerIndex(null);
|
|
3293
|
-
}, [textareaRef, value]);
|
|
3294
|
-
const onKeyDown = (0, import_react21.useCallback)(
|
|
3295
|
-
(e) => {
|
|
3296
|
-
if (!isOpen) return false;
|
|
3297
|
-
if (e.key === "ArrowDown") {
|
|
3298
|
-
e.preventDefault();
|
|
3299
|
-
setActiveIndex((i) => Math.min(items.length - 1, i + 1));
|
|
3300
|
-
return true;
|
|
3301
|
-
}
|
|
3302
|
-
if (e.key === "ArrowUp") {
|
|
3303
|
-
e.preventDefault();
|
|
3304
|
-
setActiveIndex((i) => Math.max(0, i - 1));
|
|
3305
|
-
return true;
|
|
3306
|
-
}
|
|
3307
|
-
if (e.key === "Enter" || e.key === "Tab") {
|
|
3308
|
-
const pick = items[activeIndex];
|
|
3309
|
-
if (pick) {
|
|
3310
|
-
e.preventDefault();
|
|
3311
|
-
commit(pick);
|
|
3312
|
-
return true;
|
|
3313
|
-
}
|
|
3314
|
-
}
|
|
3315
|
-
if (e.key === "Escape") {
|
|
3316
|
-
e.preventDefault();
|
|
3317
|
-
dismiss();
|
|
3318
|
-
return true;
|
|
3319
|
-
}
|
|
3320
|
-
return false;
|
|
3321
|
-
},
|
|
3322
|
-
[isOpen, items, activeIndex, commit, dismiss]
|
|
3323
|
-
);
|
|
3324
|
-
return {
|
|
3325
|
-
isOpen,
|
|
3326
|
-
query,
|
|
3327
|
-
activeIndex,
|
|
3328
|
-
items,
|
|
3329
|
-
onKeyDown,
|
|
3330
|
-
dismiss,
|
|
3331
|
-
commit,
|
|
3332
|
-
caretRect
|
|
3333
|
-
};
|
|
3334
|
-
}
|
|
3335
|
-
|
|
3336
|
-
// src/hooks/useTextareaSelection.ts
|
|
3337
|
-
var import_react22 = require("react");
|
|
3338
|
-
function getSelectionRect(textarea, start, end) {
|
|
3339
|
-
if (typeof document === "undefined") return null;
|
|
3340
|
-
if (start === end) return null;
|
|
3341
|
-
const mirror = document.createElement("div");
|
|
3342
|
-
const styles = window.getComputedStyle(textarea);
|
|
3343
|
-
for (const prop of [
|
|
3344
|
-
"boxSizing",
|
|
3345
|
-
"width",
|
|
3346
|
-
"fontFamily",
|
|
3347
|
-
"fontSize",
|
|
3348
|
-
"fontWeight",
|
|
3349
|
-
"fontStyle",
|
|
3350
|
-
"letterSpacing",
|
|
3351
|
-
"lineHeight",
|
|
3352
|
-
"paddingTop",
|
|
3353
|
-
"paddingRight",
|
|
3354
|
-
"paddingBottom",
|
|
3355
|
-
"paddingLeft",
|
|
3356
|
-
"borderTopWidth",
|
|
3357
|
-
"borderRightWidth",
|
|
3358
|
-
"borderBottomWidth",
|
|
3359
|
-
"borderLeftWidth",
|
|
3360
|
-
"textTransform",
|
|
3361
|
-
"wordSpacing",
|
|
3362
|
-
"tabSize",
|
|
3363
|
-
"whiteSpace"
|
|
3364
|
-
]) {
|
|
3365
|
-
mirror.style[prop] = styles[prop];
|
|
3351
|
+
lines.push({ id: "status", text: `\u27F3 ${status}`, tone: "active" });
|
|
3352
|
+
return lines;
|
|
3366
3353
|
}
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
const pre = document.createTextNode(textarea.value.slice(0, start));
|
|
3375
|
-
const range = document.createElement("span");
|
|
3376
|
-
range.textContent = textarea.value.slice(start, end) || "\u200B";
|
|
3377
|
-
const post = document.createTextNode(textarea.value.slice(end));
|
|
3378
|
-
mirror.appendChild(pre);
|
|
3379
|
-
mirror.appendChild(range);
|
|
3380
|
-
mirror.appendChild(post);
|
|
3381
|
-
document.body.appendChild(mirror);
|
|
3382
|
-
const taRect = textarea.getBoundingClientRect();
|
|
3383
|
-
const rangeRect = range.getBoundingClientRect();
|
|
3384
|
-
const mirrorRect = mirror.getBoundingClientRect();
|
|
3385
|
-
const out = new DOMRect(
|
|
3386
|
-
taRect.left + (rangeRect.left - mirrorRect.left) - textarea.scrollLeft,
|
|
3387
|
-
taRect.top + (rangeRect.top - mirrorRect.top) - textarea.scrollTop,
|
|
3388
|
-
rangeRect.width,
|
|
3389
|
-
rangeRect.height
|
|
3390
|
-
);
|
|
3391
|
-
document.body.removeChild(mirror);
|
|
3392
|
-
return out;
|
|
3354
|
+
assembleSteps(plan).forEach((step, i) => {
|
|
3355
|
+
if (settled || shown > i) lines.push({ id: `step-${i}`, text: `\u2713 ${step}`, tone: "done" });
|
|
3356
|
+
else if (shown === i) lines.push({ id: `step-${i}`, text: `\u27F3 ${step}\u2026`, tone: "active" });
|
|
3357
|
+
else lines.push({ id: `step-${i}`, text: `\xB7 ${step} queued`, tone: "muted" });
|
|
3358
|
+
});
|
|
3359
|
+
if (settled) lines.push({ id: "errors", text: "\u2713 error handling attached", tone: "done" });
|
|
3360
|
+
return lines.slice(-8);
|
|
3393
3361
|
}
|
|
3394
|
-
function
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
const [start, setStart] = (0, import_react22.useState)(0);
|
|
3400
|
-
const [end, setEnd] = (0, import_react22.useState)(0);
|
|
3401
|
-
const [rect, setRect] = (0, import_react22.useState)(null);
|
|
3402
|
-
(0, import_react22.useEffect)(() => {
|
|
3403
|
-
if (typeof document === "undefined") return;
|
|
3404
|
-
const handler = () => {
|
|
3405
|
-
const ta = textareaRef.current;
|
|
3406
|
-
if (!ta || document.activeElement !== ta) {
|
|
3407
|
-
setStart(0);
|
|
3408
|
-
setEnd(0);
|
|
3409
|
-
setRect(null);
|
|
3410
|
-
return;
|
|
3411
|
-
}
|
|
3412
|
-
const s = ta.selectionStart ?? 0;
|
|
3413
|
-
const e = ta.selectionEnd ?? 0;
|
|
3414
|
-
setStart(s);
|
|
3415
|
-
setEnd(e);
|
|
3416
|
-
setRect(s !== e ? getSelectionRect(ta, s, e) : null);
|
|
3417
|
-
};
|
|
3418
|
-
document.addEventListener("selectionchange", handler);
|
|
3419
|
-
return () => document.removeEventListener("selectionchange", handler);
|
|
3420
|
-
}, [textareaRef]);
|
|
3421
|
-
const active = start !== end;
|
|
3422
|
-
const text = active ? value.slice(start, end) : "";
|
|
3423
|
-
const writeToClipboard = (0, import_react22.useCallback)(
|
|
3424
|
-
async (str) => {
|
|
3425
|
-
try {
|
|
3426
|
-
if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) {
|
|
3427
|
-
await navigator.clipboard.writeText(str);
|
|
3428
|
-
return true;
|
|
3429
|
-
}
|
|
3430
|
-
} catch {
|
|
3431
|
-
}
|
|
3432
|
-
try {
|
|
3433
|
-
const tmp = document.createElement("textarea");
|
|
3434
|
-
tmp.value = str;
|
|
3435
|
-
tmp.style.position = "fixed";
|
|
3436
|
-
tmp.style.left = "-9999px";
|
|
3437
|
-
document.body.appendChild(tmp);
|
|
3438
|
-
tmp.select();
|
|
3439
|
-
const ok = document.execCommand("copy");
|
|
3440
|
-
document.body.removeChild(tmp);
|
|
3441
|
-
return ok;
|
|
3442
|
-
} catch {
|
|
3443
|
-
return false;
|
|
3444
|
-
}
|
|
3445
|
-
},
|
|
3446
|
-
[]
|
|
3447
|
-
);
|
|
3448
|
-
const copy = (0, import_react22.useCallback)(async () => {
|
|
3449
|
-
if (!active) return false;
|
|
3450
|
-
return writeToClipboard(text);
|
|
3451
|
-
}, [active, text, writeToClipboard]);
|
|
3452
|
-
const replace = (0, import_react22.useCallback)(
|
|
3453
|
-
(str) => {
|
|
3454
|
-
const ta = textareaRef.current;
|
|
3455
|
-
if (!ta) return;
|
|
3456
|
-
const next = value.slice(0, start) + str + value.slice(end);
|
|
3457
|
-
onChange(next);
|
|
3458
|
-
requestAnimationFrame(() => {
|
|
3459
|
-
ta.focus();
|
|
3460
|
-
const caret = start + str.length;
|
|
3461
|
-
ta.setSelectionRange(caret, caret);
|
|
3462
|
-
});
|
|
3463
|
-
},
|
|
3464
|
-
[textareaRef, value, start, end, onChange]
|
|
3465
|
-
);
|
|
3466
|
-
const cut = (0, import_react22.useCallback)(async () => {
|
|
3467
|
-
if (!active) return false;
|
|
3468
|
-
const ok = await writeToClipboard(text);
|
|
3469
|
-
if (ok) replace("");
|
|
3470
|
-
return ok;
|
|
3471
|
-
}, [active, text, writeToClipboard, replace]);
|
|
3472
|
-
const wrap = (0, import_react22.useCallback)(
|
|
3473
|
-
(open, close) => {
|
|
3474
|
-
const ta = textareaRef.current;
|
|
3475
|
-
if (!ta) return;
|
|
3476
|
-
const closing = close ?? open;
|
|
3477
|
-
const before = value.slice(0, start);
|
|
3478
|
-
const sel = value.slice(start, end);
|
|
3479
|
-
const after = value.slice(end);
|
|
3480
|
-
const next = `${before}${open}${sel}${closing}${after}`;
|
|
3481
|
-
onChange(next);
|
|
3482
|
-
requestAnimationFrame(() => {
|
|
3483
|
-
ta.focus();
|
|
3484
|
-
const newStart = start;
|
|
3485
|
-
const newEnd = end + open.length + closing.length;
|
|
3486
|
-
ta.setSelectionRange(newStart, newEnd);
|
|
3487
|
-
});
|
|
3488
|
-
},
|
|
3489
|
-
[textareaRef, value, start, end, onChange]
|
|
3490
|
-
);
|
|
3491
|
-
return {
|
|
3492
|
-
active,
|
|
3493
|
-
text,
|
|
3494
|
-
start,
|
|
3495
|
-
end,
|
|
3496
|
-
rect,
|
|
3497
|
-
copy,
|
|
3498
|
-
cut,
|
|
3499
|
-
wrap,
|
|
3500
|
-
replace
|
|
3501
|
-
};
|
|
3362
|
+
function slugify(value) {
|
|
3363
|
+
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "your-team";
|
|
3364
|
+
}
|
|
3365
|
+
function isValidEmail(value) {
|
|
3366
|
+
return /^\S+@\S+\.\S+$/.test(value.trim());
|
|
3502
3367
|
}
|
|
3503
3368
|
|
|
3504
|
-
// src/
|
|
3505
|
-
var
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3369
|
+
// src/marketing/components/BetaAccessForm/BetaAccessForm.tsx
|
|
3370
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
3371
|
+
function BetaAccessForm({
|
|
3372
|
+
title = "Request early access",
|
|
3373
|
+
subtitle = "CURRENTLY IN PRIVATE BETA \u2014 WE REVIEW ACCESS REQUESTS WEEKLY",
|
|
3374
|
+
fields = "email",
|
|
3375
|
+
appearance = "card",
|
|
3376
|
+
teamSizes,
|
|
3377
|
+
plans,
|
|
3378
|
+
defaultPlan,
|
|
3379
|
+
useCases,
|
|
3380
|
+
showDetails = false,
|
|
3381
|
+
detailsLabel = "Anything else we should know?",
|
|
3382
|
+
detailsPlaceholder = "Current stack, timelines, must-have connectors\u2026",
|
|
3383
|
+
submitLabel = "Request access \u2192",
|
|
3384
|
+
footnote = "NO CREDIT CARD \xB7 SSO & SELF-HOSTING AVAILABLE",
|
|
3385
|
+
onSubmit,
|
|
3386
|
+
successTitle = "Request received.",
|
|
3387
|
+
successBody = "We review access requests weekly \u2014 you'll hear from us by email.",
|
|
3388
|
+
disabled = false,
|
|
3389
|
+
className
|
|
3513
3390
|
}) {
|
|
3514
|
-
const
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
onChange(next);
|
|
3575
|
-
requestAnimationFrame(() => {
|
|
3576
|
-
ta.focus();
|
|
3577
|
-
ta.setSelectionRange(
|
|
3578
|
-
lineStart,
|
|
3579
|
-
lineStart + updated.length
|
|
3580
|
-
);
|
|
3581
|
-
});
|
|
3582
|
-
};
|
|
3583
|
-
const undo = () => {
|
|
3584
|
-
try {
|
|
3585
|
-
getTa()?.focus();
|
|
3586
|
-
document.execCommand("undo");
|
|
3587
|
-
} catch {
|
|
3588
|
-
}
|
|
3589
|
-
};
|
|
3590
|
-
const redo = () => {
|
|
3591
|
-
try {
|
|
3592
|
-
getTa()?.focus();
|
|
3593
|
-
document.execCommand("redo");
|
|
3594
|
-
} catch {
|
|
3391
|
+
const uid = (0, import_react21.useId)();
|
|
3392
|
+
const [values, setValues] = (0, import_react21.useState)({
|
|
3393
|
+
email: "",
|
|
3394
|
+
name: "",
|
|
3395
|
+
company: "",
|
|
3396
|
+
teamSize: "",
|
|
3397
|
+
plan: defaultPlan ?? "",
|
|
3398
|
+
useCase: "",
|
|
3399
|
+
details: ""
|
|
3400
|
+
});
|
|
3401
|
+
const [phase, setPhase] = (0, import_react21.useState)("idle");
|
|
3402
|
+
const [error, setError] = (0, import_react21.useState)(null);
|
|
3403
|
+
const handleSubmit = async (event) => {
|
|
3404
|
+
event.preventDefault();
|
|
3405
|
+
if (phase === "submitting") return;
|
|
3406
|
+
if (!isValidEmail(values.email)) {
|
|
3407
|
+
setError("Please enter a valid work email.");
|
|
3408
|
+
return;
|
|
3409
|
+
}
|
|
3410
|
+
if (fields === "full" && !values.name?.trim()) {
|
|
3411
|
+
setError("Please enter your name.");
|
|
3412
|
+
return;
|
|
3413
|
+
}
|
|
3414
|
+
if (fields === "full" && teamSizes?.length && !values.teamSize) {
|
|
3415
|
+
setError("Please select your team size.");
|
|
3416
|
+
return;
|
|
3417
|
+
}
|
|
3418
|
+
if (fields === "full" && useCases?.length && !values.useCase) {
|
|
3419
|
+
setError("Please select your primary use case.");
|
|
3420
|
+
return;
|
|
3421
|
+
}
|
|
3422
|
+
setError(null);
|
|
3423
|
+
setPhase("submitting");
|
|
3424
|
+
try {
|
|
3425
|
+
await onSubmit?.(values);
|
|
3426
|
+
setPhase("success");
|
|
3427
|
+
} catch {
|
|
3428
|
+
setError("Something went wrong \u2014 please try again.");
|
|
3429
|
+
setPhase("idle");
|
|
3430
|
+
}
|
|
3431
|
+
};
|
|
3432
|
+
const inline = appearance === "inline";
|
|
3433
|
+
if (phase === "success") {
|
|
3434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3435
|
+
"div",
|
|
3436
|
+
{
|
|
3437
|
+
className: cn(
|
|
3438
|
+
"ods-mkt-access",
|
|
3439
|
+
"ods-mkt-access--success",
|
|
3440
|
+
inline && "ods-mkt-access--inline",
|
|
3441
|
+
className
|
|
3442
|
+
),
|
|
3443
|
+
role: "status",
|
|
3444
|
+
children: [
|
|
3445
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("p", { className: "ods-mkt-access__success-mark", children: [
|
|
3446
|
+
"\u2713 ",
|
|
3447
|
+
successTitle
|
|
3448
|
+
] }),
|
|
3449
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "ods-mkt-access__success-body", children: successBody })
|
|
3450
|
+
]
|
|
3595
3451
|
}
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3452
|
+
);
|
|
3453
|
+
}
|
|
3454
|
+
const busy = disabled || phase === "submitting";
|
|
3455
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3456
|
+
"form",
|
|
3457
|
+
{
|
|
3458
|
+
className: cn("ods-mkt-access", inline && "ods-mkt-access--inline", className),
|
|
3459
|
+
onSubmit: handleSubmit,
|
|
3460
|
+
noValidate: true,
|
|
3461
|
+
children: [
|
|
3462
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__head", children: [
|
|
3463
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { className: "ods-mkt-access__title", children: title }),
|
|
3464
|
+
subtitle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "ods-mkt-access__subtitle", children: subtitle })
|
|
3465
|
+
] }),
|
|
3466
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3467
|
+
"div",
|
|
3468
|
+
{
|
|
3469
|
+
className: cn(
|
|
3470
|
+
"ods-mkt-access__fields",
|
|
3471
|
+
fields === "full" && "ods-mkt-access__fields--full"
|
|
3472
|
+
),
|
|
3473
|
+
children: [
|
|
3474
|
+
fields === "full" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3475
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: "ods-mkt-access__label", htmlFor: `${uid}-name`, children: "Full name" }),
|
|
3476
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3477
|
+
Input,
|
|
3478
|
+
{
|
|
3479
|
+
id: `${uid}-name`,
|
|
3480
|
+
autoComplete: "name",
|
|
3481
|
+
placeholder: "Ada Lovelace",
|
|
3482
|
+
value: values.name ?? "",
|
|
3483
|
+
onChange: (e) => setValues((v) => ({ ...v, name: e.target.value })),
|
|
3484
|
+
disabled: busy
|
|
3485
|
+
}
|
|
3486
|
+
)
|
|
3487
|
+
] }),
|
|
3488
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3489
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: "ods-mkt-access__label", htmlFor: `${uid}-email`, children: "Work email" }),
|
|
3490
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3491
|
+
Input,
|
|
3492
|
+
{
|
|
3493
|
+
id: `${uid}-email`,
|
|
3494
|
+
type: "email",
|
|
3495
|
+
autoComplete: "email",
|
|
3496
|
+
placeholder: "ada@company.com",
|
|
3497
|
+
value: values.email,
|
|
3498
|
+
onChange: (e) => setValues((v) => ({ ...v, email: e.target.value })),
|
|
3499
|
+
disabled: busy
|
|
3500
|
+
}
|
|
3501
|
+
)
|
|
3502
|
+
] }),
|
|
3503
|
+
fields === "full" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3504
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: "ods-mkt-access__label", htmlFor: `${uid}-company`, children: "Company" }),
|
|
3505
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3506
|
+
Input,
|
|
3507
|
+
{
|
|
3508
|
+
id: `${uid}-company`,
|
|
3509
|
+
autoComplete: "organization",
|
|
3510
|
+
placeholder: "Acme Inc.",
|
|
3511
|
+
value: values.company ?? "",
|
|
3512
|
+
onChange: (e) => setValues((v) => ({ ...v, company: e.target.value })),
|
|
3513
|
+
disabled: busy
|
|
3514
|
+
}
|
|
3515
|
+
)
|
|
3516
|
+
] }),
|
|
3517
|
+
fields === "full" && teamSizes && teamSizes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3518
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "ods-mkt-access__label", id: `${uid}-teamsize-label`, children: "Team size" }),
|
|
3519
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3520
|
+
Select,
|
|
3521
|
+
{
|
|
3522
|
+
"aria-labelledby": `${uid}-teamsize-label`,
|
|
3523
|
+
placeholder: "Select team size\u2026",
|
|
3524
|
+
options: teamSizes.map((size) => ({ value: size, label: size })),
|
|
3525
|
+
value: values.teamSize ?? "",
|
|
3526
|
+
onChange: (teamSize) => setValues((v) => ({ ...v, teamSize })),
|
|
3527
|
+
disabled: busy
|
|
3528
|
+
}
|
|
3529
|
+
)
|
|
3530
|
+
] }),
|
|
3531
|
+
fields === "full" && plans && plans.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3532
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "ods-mkt-access__label", id: `${uid}-plan-label`, children: "Plan (optional)" }),
|
|
3533
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3534
|
+
Select,
|
|
3535
|
+
{
|
|
3536
|
+
"aria-labelledby": `${uid}-plan-label`,
|
|
3537
|
+
placeholder: "Not sure yet",
|
|
3538
|
+
options: plans.map((plan) => ({ value: plan, label: plan })),
|
|
3539
|
+
value: values.plan ?? "",
|
|
3540
|
+
onChange: (plan) => setValues((v) => ({ ...v, plan })),
|
|
3541
|
+
disabled: busy
|
|
3542
|
+
}
|
|
3543
|
+
)
|
|
3544
|
+
] }),
|
|
3545
|
+
fields === "full" && useCases && useCases.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3546
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "ods-mkt-access__label", id: `${uid}-usecase-label`, children: "Primary use case" }),
|
|
3547
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3548
|
+
Select,
|
|
3549
|
+
{
|
|
3550
|
+
"aria-labelledby": `${uid}-usecase-label`,
|
|
3551
|
+
placeholder: "Select a use case\u2026",
|
|
3552
|
+
options: useCases.map((useCase) => ({ value: useCase, label: useCase })),
|
|
3553
|
+
value: values.useCase ?? "",
|
|
3554
|
+
onChange: (useCase) => setValues((v) => ({ ...v, useCase })),
|
|
3555
|
+
disabled: busy
|
|
3556
|
+
}
|
|
3557
|
+
)
|
|
3558
|
+
] }),
|
|
3559
|
+
fields === "full" && showDetails && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field ods-mkt-access__field--wide", children: [
|
|
3560
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3561
|
+
"label",
|
|
3562
|
+
{
|
|
3563
|
+
className: "ods-mkt-access__label",
|
|
3564
|
+
id: `${uid}-details-label`,
|
|
3565
|
+
htmlFor: `${uid}-details`,
|
|
3566
|
+
children: detailsLabel
|
|
3567
|
+
}
|
|
3568
|
+
),
|
|
3569
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3570
|
+
Textarea,
|
|
3571
|
+
{
|
|
3572
|
+
id: `${uid}-details`,
|
|
3573
|
+
"aria-labelledby": `${uid}-details-label`,
|
|
3574
|
+
placeholder: detailsPlaceholder,
|
|
3575
|
+
rows: 3,
|
|
3576
|
+
value: values.details ?? "",
|
|
3577
|
+
onChange: (e) => setValues((v) => ({ ...v, details: e.target.value })),
|
|
3578
|
+
disabled: busy
|
|
3579
|
+
}
|
|
3580
|
+
)
|
|
3581
|
+
] }),
|
|
3582
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3583
|
+
Button,
|
|
3584
|
+
{
|
|
3585
|
+
type: "submit",
|
|
3586
|
+
variant: "primary",
|
|
3587
|
+
loading: phase === "submitting",
|
|
3588
|
+
disabled,
|
|
3589
|
+
children: submitLabel
|
|
3590
|
+
}
|
|
3591
|
+
)
|
|
3592
|
+
]
|
|
3593
|
+
}
|
|
3594
|
+
),
|
|
3595
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "ods-mkt-access__error", role: "alert", children: error }),
|
|
3596
|
+
footnote && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "ods-mkt-access__footnote", children: footnote })
|
|
3597
|
+
]
|
|
3598
|
+
}
|
|
3625
3599
|
);
|
|
3626
|
-
return { tools: visibleTools, runTool, helpers };
|
|
3627
3600
|
}
|
|
3628
3601
|
|
|
3629
|
-
// src/components/
|
|
3630
|
-
var
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
const pixelCap = typeof maxHeight === "number" ? maxHeight : Number.POSITIVE_INFINITY;
|
|
3760
|
-
const effectiveMax = Math.min(rowCap, pixelCap);
|
|
3761
|
-
const rowFloor = lh * (minRows ?? rows) + padding;
|
|
3762
|
-
el.style.height = "auto";
|
|
3763
|
-
const target = Math.max(
|
|
3764
|
-
rowFloor,
|
|
3765
|
-
Math.min(effectiveMax, el.scrollHeight)
|
|
3766
|
-
);
|
|
3767
|
-
el.style.height = `${target}px`;
|
|
3768
|
-
el.style.overflowY = el.scrollHeight > effectiveMax ? "auto" : "hidden";
|
|
3769
|
-
}, [autoResize, value, defaultValue, minRows, maxRows, maxHeight, rows]);
|
|
3770
|
-
const resolvedResize = typeof resize === "boolean" ? resize ? "vertical" : "none" : resize;
|
|
3771
|
-
const toCss = (v) => v == null ? void 0 : typeof v === "number" ? `${v}px` : v;
|
|
3772
|
-
const fieldStyle = {
|
|
3773
|
-
maxHeight: toCss(maxHeight),
|
|
3774
|
-
maxWidth: toCss(maxWidth),
|
|
3775
|
-
minHeight: toCss(minHeight),
|
|
3776
|
-
minWidth: toCss(minWidth),
|
|
3777
|
-
resize: resolvedResize
|
|
3778
|
-
};
|
|
3779
|
-
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3602
|
+
// src/components/BlogCard/BlogCard.tsx
|
|
3603
|
+
var import_react24 = require("react");
|
|
3604
|
+
|
|
3605
|
+
// src/components/Avatar/Avatar.tsx
|
|
3606
|
+
var import_react22 = require("react");
|
|
3607
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
3608
|
+
var PALETTE_SIZE = 12;
|
|
3609
|
+
function djb2(str) {
|
|
3610
|
+
let h = 5381;
|
|
3611
|
+
for (let i = 0; i < str.length; i++) h = (h << 5) + h + str.charCodeAt(i);
|
|
3612
|
+
return h >>> 0;
|
|
3613
|
+
}
|
|
3614
|
+
function paletteIndexFor(seed) {
|
|
3615
|
+
return djb2(seed) % PALETTE_SIZE;
|
|
3616
|
+
}
|
|
3617
|
+
function normalizeInitials(raw) {
|
|
3618
|
+
const trimmed = raw.trim();
|
|
3619
|
+
if (!trimmed) return "";
|
|
3620
|
+
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
|
3621
|
+
if (tokens.length >= 2) {
|
|
3622
|
+
return (tokens[0].charAt(0) + tokens[1].charAt(0)).toUpperCase();
|
|
3623
|
+
}
|
|
3624
|
+
return trimmed.slice(0, 2).toUpperCase();
|
|
3625
|
+
}
|
|
3626
|
+
var STATUS_DEFAULT_LABEL = {
|
|
3627
|
+
online: "Online",
|
|
3628
|
+
offline: "Offline",
|
|
3629
|
+
busy: "Busy",
|
|
3630
|
+
away: "Away"
|
|
3631
|
+
};
|
|
3632
|
+
var Avatar = (0, import_react22.forwardRef)(function Avatar2({
|
|
3633
|
+
src,
|
|
3634
|
+
alt,
|
|
3635
|
+
initials,
|
|
3636
|
+
icon,
|
|
3637
|
+
fallback,
|
|
3638
|
+
seed,
|
|
3639
|
+
size = "md",
|
|
3640
|
+
shape = "circle",
|
|
3641
|
+
status,
|
|
3642
|
+
statusLabel,
|
|
3643
|
+
onClick,
|
|
3644
|
+
imgLoading = "lazy",
|
|
3645
|
+
referrerPolicy,
|
|
3646
|
+
className,
|
|
3647
|
+
...rest
|
|
3648
|
+
}, ref) {
|
|
3649
|
+
const [imgFailed, setImgFailed] = (0, import_react22.useState)(false);
|
|
3650
|
+
const handleImgError = (0, import_react22.useCallback)(() => setImgFailed(true), []);
|
|
3651
|
+
const showImage = Boolean(src) && !imgFailed;
|
|
3652
|
+
const normalizedInitials = (0, import_react22.useMemo)(
|
|
3653
|
+
() => initials ? normalizeInitials(initials) : "",
|
|
3654
|
+
[initials]
|
|
3655
|
+
);
|
|
3656
|
+
const paletteIdx = (0, import_react22.useMemo)(() => {
|
|
3657
|
+
const resolved = seed ?? initials ?? alt ?? "?";
|
|
3658
|
+
return paletteIndexFor(resolved);
|
|
3659
|
+
}, [seed, initials, alt]);
|
|
3660
|
+
const baseName = alt || normalizedInitials || "Avatar";
|
|
3661
|
+
const announcedStatus = status ? statusLabel ?? STATUS_DEFAULT_LABEL[status] : "";
|
|
3662
|
+
const accessibleName = announcedStatus ? `${baseName}, ${announcedStatus}` : baseName;
|
|
3663
|
+
const isClickable = Boolean(onClick);
|
|
3664
|
+
const handleKeyDown = (e) => {
|
|
3665
|
+
if (!isClickable) return;
|
|
3666
|
+
if ((e.key === "Enter" || e.key === " ") && !e.repeat) {
|
|
3667
|
+
e.preventDefault();
|
|
3668
|
+
onClick?.();
|
|
3669
|
+
}
|
|
3670
|
+
};
|
|
3671
|
+
const rootClassName = cn(
|
|
3672
|
+
"ods-avatar",
|
|
3673
|
+
`ods-avatar--${size}`,
|
|
3674
|
+
`ods-avatar--${shape}`,
|
|
3675
|
+
isClickable && "ods-avatar--clickable",
|
|
3676
|
+
className
|
|
3677
|
+
);
|
|
3678
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
3679
|
+
"div",
|
|
3680
|
+
{
|
|
3681
|
+
...rest,
|
|
3682
|
+
ref,
|
|
3683
|
+
className: rootClassName,
|
|
3684
|
+
role: isClickable ? "button" : "img",
|
|
3685
|
+
"aria-label": accessibleName,
|
|
3686
|
+
tabIndex: isClickable ? 0 : void 0,
|
|
3687
|
+
onClick,
|
|
3688
|
+
onKeyDown: isClickable ? handleKeyDown : void 0,
|
|
3689
|
+
"data-status": status,
|
|
3690
|
+
children: [
|
|
3691
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ods-avatar__inner", "data-palette": paletteIdx, children: showImage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
3692
|
+
"img",
|
|
3693
|
+
{
|
|
3694
|
+
src,
|
|
3695
|
+
alt: "",
|
|
3696
|
+
className: "ods-avatar__image",
|
|
3697
|
+
loading: imgLoading,
|
|
3698
|
+
decoding: "async",
|
|
3699
|
+
referrerPolicy,
|
|
3700
|
+
onError: handleImgError,
|
|
3701
|
+
draggable: false
|
|
3702
|
+
}
|
|
3703
|
+
) : icon ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ods-avatar__icon", "aria-hidden": "true", children: icon }) : normalizedInitials ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ods-avatar__initials", "aria-hidden": "true", children: normalizedInitials }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ods-avatar__initials", "aria-hidden": "true", children: fallback ?? "?" }) }),
|
|
3704
|
+
status && // Decorative — the textual status is folded into the wrapper's
|
|
3705
|
+
// aria-label above. `aria-hidden` keeps AT from double-announcing.
|
|
3706
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
3707
|
+
"span",
|
|
3708
|
+
{
|
|
3709
|
+
className: cn("ods-avatar__status", `ods-avatar__status--${status}`),
|
|
3710
|
+
"aria-hidden": "true"
|
|
3711
|
+
}
|
|
3712
|
+
)
|
|
3713
|
+
]
|
|
3714
|
+
}
|
|
3715
|
+
);
|
|
3716
|
+
});
|
|
3717
|
+
Avatar.displayName = "Avatar";
|
|
3718
|
+
var AvatarStack = (0, import_react22.forwardRef)(
|
|
3719
|
+
function AvatarStack2({
|
|
3720
|
+
children,
|
|
3721
|
+
max,
|
|
3722
|
+
size = "md",
|
|
3723
|
+
renderOverflow,
|
|
3724
|
+
direction = "ltr",
|
|
3725
|
+
className,
|
|
3726
|
+
...rest
|
|
3727
|
+
}, ref) {
|
|
3728
|
+
const arr = Array.isArray(children) ? children : [children];
|
|
3729
|
+
const visible = max && arr.length > max ? arr.slice(0, max) : arr;
|
|
3730
|
+
const overflow = max && arr.length > max ? arr.length - max : 0;
|
|
3731
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
3780
3732
|
"div",
|
|
3781
3733
|
{
|
|
3734
|
+
...rest,
|
|
3735
|
+
ref,
|
|
3782
3736
|
className: cn(
|
|
3783
|
-
"ods-
|
|
3784
|
-
`ods-
|
|
3785
|
-
`ods-textarea--resize-${resolvedResize}`,
|
|
3786
|
-
autoResize && "ods-textarea--auto-resize",
|
|
3787
|
-
error && "ods-textarea--error",
|
|
3788
|
-
disabled && "ods-textarea--disabled",
|
|
3737
|
+
"ods-avatar-stack",
|
|
3738
|
+
`ods-avatar-stack--${direction}`,
|
|
3789
3739
|
className
|
|
3790
3740
|
),
|
|
3791
|
-
style: consumerStyle,
|
|
3792
3741
|
children: [
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
...labelProps,
|
|
3797
|
-
htmlFor: baseId,
|
|
3798
|
-
className: "ods-textarea__label",
|
|
3799
|
-
children: label
|
|
3800
|
-
}
|
|
3801
|
-
),
|
|
3802
|
-
toolbarEnabled && toolbarPosition === "top" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3803
|
-
TextareaToolbar,
|
|
3742
|
+
visible,
|
|
3743
|
+
overflow > 0 && (renderOverflow ? renderOverflow(overflow) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
3744
|
+
"div",
|
|
3804
3745
|
{
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3811
|
-
"textarea",
|
|
3812
|
-
{
|
|
3813
|
-
...props,
|
|
3814
|
-
...inputProps,
|
|
3815
|
-
ref: setRef,
|
|
3816
|
-
id: baseId,
|
|
3817
|
-
rows: autoResize ? minRows ?? rows : rows,
|
|
3818
|
-
disabled,
|
|
3819
|
-
maxLength,
|
|
3820
|
-
defaultValue,
|
|
3821
|
-
value,
|
|
3822
|
-
onChange: handleChangeWithMirror,
|
|
3823
|
-
onKeyDown: handleKeyDownWithCommands,
|
|
3824
|
-
className: "ods-textarea__field",
|
|
3825
|
-
style: fieldStyle,
|
|
3826
|
-
"aria-invalid": error || void 0,
|
|
3827
|
-
"aria-describedby": describedBy,
|
|
3828
|
-
"aria-autocomplete": cmdEnabled ? "list" : void 0,
|
|
3829
|
-
"aria-expanded": cmdEnabled ? cmdPalette.isOpen : void 0,
|
|
3830
|
-
"aria-controls": cmdEnabled && cmdPalette.isOpen ? `${baseId}-cmd-list` : void 0,
|
|
3831
|
-
"aria-activedescendant": cmdEnabled && cmdPalette.isOpen && cmdPalette.items[cmdPalette.activeIndex] ? `${baseId}-cmd-${cmdPalette.items[cmdPalette.activeIndex].id}` : void 0
|
|
3832
|
-
}
|
|
3833
|
-
),
|
|
3834
|
-
cmdEnabled && cmdPalette.isOpen && cmdPalette.items.length > 0 && typeof document !== "undefined" && (0, import_react_dom3.createPortal)(
|
|
3835
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3836
|
-
"ul",
|
|
3837
|
-
{
|
|
3838
|
-
id: `${baseId}-cmd-list`,
|
|
3839
|
-
role: "listbox",
|
|
3840
|
-
"aria-label": "Inline commands",
|
|
3841
|
-
className: "ods-textarea__cmd-popover",
|
|
3842
|
-
style: {
|
|
3843
|
-
position: "fixed",
|
|
3844
|
-
top: (cmdPalette.caretRect?.bottom ?? 0) + 6,
|
|
3845
|
-
left: cmdPalette.caretRect?.left ?? 0
|
|
3846
|
-
},
|
|
3847
|
-
children: cmdPalette.items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3848
|
-
"li",
|
|
3849
|
-
{
|
|
3850
|
-
id: `${baseId}-cmd-${c.id}`,
|
|
3851
|
-
role: "option",
|
|
3852
|
-
"aria-selected": i === cmdPalette.activeIndex,
|
|
3853
|
-
className: cn(
|
|
3854
|
-
"ods-textarea__cmd-item",
|
|
3855
|
-
i === cmdPalette.activeIndex && "ods-textarea__cmd-item--active"
|
|
3856
|
-
),
|
|
3857
|
-
onMouseDown: (e) => {
|
|
3858
|
-
e.preventDefault();
|
|
3859
|
-
cmdPalette.commit(c);
|
|
3860
|
-
},
|
|
3861
|
-
onMouseEnter: () => {
|
|
3862
|
-
},
|
|
3863
|
-
children: [
|
|
3864
|
-
c.icon && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ods-textarea__cmd-icon", children: c.icon }),
|
|
3865
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "ods-textarea__cmd-text", children: [
|
|
3866
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ods-textarea__cmd-label", children: c.label }),
|
|
3867
|
-
c.description && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ods-textarea__cmd-desc", children: c.description })
|
|
3868
|
-
] })
|
|
3869
|
-
]
|
|
3870
|
-
},
|
|
3871
|
-
c.id
|
|
3872
|
-
))
|
|
3873
|
-
}
|
|
3874
|
-
),
|
|
3875
|
-
document.body
|
|
3876
|
-
),
|
|
3877
|
-
selectionToolbar && sel.active && sel.rect && typeof document !== "undefined" && (0, import_react_dom3.createPortal)(
|
|
3878
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3879
|
-
"div",
|
|
3880
|
-
{
|
|
3881
|
-
role: "toolbar",
|
|
3882
|
-
"aria-label": "Selection actions",
|
|
3883
|
-
className: "ods-textarea__sel-toolbar",
|
|
3884
|
-
style: {
|
|
3885
|
-
position: "fixed",
|
|
3886
|
-
top: sel.rect.top - 36,
|
|
3887
|
-
left: sel.rect.left
|
|
3888
|
-
},
|
|
3889
|
-
onMouseDown: (e) => e.preventDefault(),
|
|
3890
|
-
children: [
|
|
3891
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3892
|
-
"button",
|
|
3893
|
-
{
|
|
3894
|
-
type: "button",
|
|
3895
|
-
className: "ods-textarea__sel-btn",
|
|
3896
|
-
onClick: () => sel.copy(),
|
|
3897
|
-
"aria-label": "Copy selection",
|
|
3898
|
-
title: "Copy",
|
|
3899
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons4.CopyIcon, { size: "xs" })
|
|
3900
|
-
}
|
|
3901
|
-
),
|
|
3902
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3903
|
-
"button",
|
|
3904
|
-
{
|
|
3905
|
-
type: "button",
|
|
3906
|
-
className: "ods-textarea__sel-btn",
|
|
3907
|
-
onClick: () => sel.cut(),
|
|
3908
|
-
"aria-label": "Cut selection",
|
|
3909
|
-
title: "Cut",
|
|
3910
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons4.CutIcon, { size: "xs" })
|
|
3911
|
-
}
|
|
3912
|
-
),
|
|
3913
|
-
selectionActions?.map((a) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3914
|
-
"button",
|
|
3915
|
-
{
|
|
3916
|
-
type: "button",
|
|
3917
|
-
className: "ods-textarea__sel-btn",
|
|
3918
|
-
onClick: () => a.onAction(sel.text, {
|
|
3919
|
-
replace: sel.replace,
|
|
3920
|
-
wrap: sel.wrap,
|
|
3921
|
-
copy: sel.copy,
|
|
3922
|
-
cut: sel.cut
|
|
3923
|
-
}),
|
|
3924
|
-
title: typeof a.label === "string" ? a.label : void 0,
|
|
3925
|
-
children: [
|
|
3926
|
-
a.icon,
|
|
3927
|
-
a.label && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ods-textarea__sel-btn-label", children: a.label })
|
|
3928
|
-
]
|
|
3929
|
-
},
|
|
3930
|
-
a.id
|
|
3931
|
-
))
|
|
3932
|
-
]
|
|
3933
|
-
}
|
|
3746
|
+
className: cn(
|
|
3747
|
+
"ods-avatar",
|
|
3748
|
+
`ods-avatar--${size}`,
|
|
3749
|
+
"ods-avatar--circle",
|
|
3750
|
+
"ods-avatar-stack__overflow"
|
|
3934
3751
|
),
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3752
|
+
role: "img",
|
|
3753
|
+
"aria-label": `${overflow} more`,
|
|
3754
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ods-avatar__inner", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "ods-avatar__initials", "aria-hidden": "true", children: [
|
|
3755
|
+
"+",
|
|
3756
|
+
overflow
|
|
3757
|
+
] }) })
|
|
3758
|
+
}
|
|
3759
|
+
))
|
|
3760
|
+
]
|
|
3761
|
+
}
|
|
3762
|
+
);
|
|
3763
|
+
}
|
|
3764
|
+
);
|
|
3765
|
+
AvatarStack.displayName = "AvatarStack";
|
|
3766
|
+
|
|
3767
|
+
// src/components/Card/Card.tsx
|
|
3768
|
+
var import_framer_motion4 = require("framer-motion");
|
|
3769
|
+
var import_react23 = require("react");
|
|
3770
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
3771
|
+
var Card = (0, import_react23.forwardRef)(function Card2({
|
|
3772
|
+
variant = "default",
|
|
3773
|
+
padding = "md",
|
|
3774
|
+
radius = "md",
|
|
3775
|
+
hoverable = false,
|
|
3776
|
+
disabled = false,
|
|
3777
|
+
loading = false,
|
|
3778
|
+
asChild = false,
|
|
3779
|
+
onClick,
|
|
3780
|
+
onKeyDown,
|
|
3781
|
+
className,
|
|
3782
|
+
children,
|
|
3783
|
+
...rest
|
|
3784
|
+
}, ref) {
|
|
3785
|
+
const reducedMotion = (0, import_framer_motion4.useReducedMotion)();
|
|
3786
|
+
const isInteractive = Boolean(onClick) && !disabled && !loading;
|
|
3787
|
+
const handleKeyDown = (e) => {
|
|
3788
|
+
onKeyDown?.(e);
|
|
3789
|
+
if (e.defaultPrevented) return;
|
|
3790
|
+
if (!isInteractive) return;
|
|
3791
|
+
if ((e.key === "Enter" || e.key === " ") && !e.repeat) {
|
|
3792
|
+
e.preventDefault();
|
|
3793
|
+
onClick?.(e);
|
|
3794
|
+
}
|
|
3795
|
+
};
|
|
3796
|
+
const rootClassName = cn(
|
|
3797
|
+
"ods-card",
|
|
3798
|
+
`ods-card--${variant}`,
|
|
3799
|
+
`ods-card--pad-${padding}`,
|
|
3800
|
+
`ods-card--radius-${radius}`,
|
|
3801
|
+
(hoverable || isInteractive) && !loading && !disabled && "ods-card--hoverable",
|
|
3802
|
+
isInteractive && "ods-card--clickable",
|
|
3803
|
+
disabled && "ods-card--disabled",
|
|
3804
|
+
loading && "ods-card--loading",
|
|
3805
|
+
className
|
|
3806
|
+
);
|
|
3807
|
+
if (asChild) {
|
|
3808
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
3809
|
+
Slot,
|
|
3810
|
+
{
|
|
3811
|
+
...rest,
|
|
3812
|
+
ref,
|
|
3813
|
+
className: rootClassName,
|
|
3814
|
+
onClick: isInteractive ? onClick : void 0,
|
|
3815
|
+
onKeyDown: isInteractive ? handleKeyDown : onKeyDown,
|
|
3816
|
+
"aria-disabled": disabled || void 0,
|
|
3817
|
+
children
|
|
3818
|
+
}
|
|
3819
|
+
);
|
|
3820
|
+
}
|
|
3821
|
+
if (loading) {
|
|
3822
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
3823
|
+
"div",
|
|
3824
|
+
{
|
|
3825
|
+
...rest,
|
|
3826
|
+
ref,
|
|
3827
|
+
className: rootClassName,
|
|
3828
|
+
"aria-busy": "true",
|
|
3829
|
+
"aria-label": "Loading",
|
|
3830
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "ods-card__skeleton", "data-ods-animate": "shimmer" })
|
|
3831
|
+
}
|
|
3832
|
+
);
|
|
3833
|
+
}
|
|
3834
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
3835
|
+
import_framer_motion4.motion.div,
|
|
3836
|
+
{
|
|
3837
|
+
...rest,
|
|
3838
|
+
ref,
|
|
3839
|
+
onClick: isInteractive ? onClick : void 0,
|
|
3840
|
+
onKeyDown: isInteractive ? handleKeyDown : onKeyDown,
|
|
3841
|
+
className: rootClassName,
|
|
3842
|
+
whileHover: (hoverable || isInteractive) && !reducedMotion ? { y: -2, transition: { duration: 0.15 } } : void 0,
|
|
3843
|
+
whileTap: isInteractive && !reducedMotion ? { scale: 0.99 } : void 0,
|
|
3844
|
+
role: isInteractive ? "button" : rest.role,
|
|
3845
|
+
tabIndex: isInteractive ? rest.tabIndex ?? 0 : rest.tabIndex,
|
|
3846
|
+
"aria-disabled": disabled || void 0,
|
|
3847
|
+
children
|
|
3848
|
+
}
|
|
3849
|
+
);
|
|
3850
|
+
});
|
|
3851
|
+
Card.displayName = "Card";
|
|
3852
|
+
var CardHeader = (0, import_react23.forwardRef)(
|
|
3853
|
+
function CardHeader2({ className, children, ...rest }, ref) {
|
|
3854
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { ...rest, ref, className: cn("ods-card__header", className), children });
|
|
3855
|
+
}
|
|
3856
|
+
);
|
|
3857
|
+
CardHeader.displayName = "Card.Header";
|
|
3858
|
+
var CardBody = (0, import_react23.forwardRef)(
|
|
3859
|
+
function CardBody2({ className, children, ...rest }, ref) {
|
|
3860
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { ...rest, ref, className: cn("ods-card__body", className), children });
|
|
3861
|
+
}
|
|
3862
|
+
);
|
|
3863
|
+
CardBody.displayName = "Card.Body";
|
|
3864
|
+
var CardFooter = (0, import_react23.forwardRef)(
|
|
3865
|
+
function CardFooter2({ className, children, ...rest }, ref) {
|
|
3866
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { ...rest, ref, className: cn("ods-card__footer", className), children });
|
|
3867
|
+
}
|
|
3868
|
+
);
|
|
3869
|
+
CardFooter.displayName = "Card.Footer";
|
|
3870
|
+
var CardTitle = (0, import_react23.forwardRef)(
|
|
3871
|
+
function CardTitle2({ as: Comp = "h3", className, children, ...rest }, ref) {
|
|
3872
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
3873
|
+
Comp,
|
|
3874
|
+
{
|
|
3875
|
+
...rest,
|
|
3876
|
+
ref,
|
|
3877
|
+
className: cn("ods-card__title", className),
|
|
3878
|
+
children
|
|
3879
|
+
}
|
|
3880
|
+
);
|
|
3881
|
+
}
|
|
3882
|
+
);
|
|
3883
|
+
CardTitle.displayName = "Card.Title";
|
|
3884
|
+
var CardDescription = (0, import_react23.forwardRef)(function CardDescription2({ className, children, ...rest }, ref) {
|
|
3885
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { ...rest, ref, className: cn("ods-card__description", className), children });
|
|
3886
|
+
});
|
|
3887
|
+
CardDescription.displayName = "Card.Description";
|
|
3888
|
+
Card.Header = CardHeader;
|
|
3889
|
+
Card.Body = CardBody;
|
|
3890
|
+
Card.Footer = CardFooter;
|
|
3891
|
+
Card.Title = CardTitle;
|
|
3892
|
+
Card.Description = CardDescription;
|
|
3893
|
+
|
|
3894
|
+
// src/components/BlogCard/BlogCard.tsx
|
|
3895
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
3896
|
+
var BlogCard = (0, import_react24.forwardRef)(
|
|
3897
|
+
function BlogCard2({
|
|
3898
|
+
cover,
|
|
3899
|
+
coverAspect = "16/9",
|
|
3900
|
+
category,
|
|
3901
|
+
tags,
|
|
3902
|
+
meta,
|
|
3903
|
+
readingTime,
|
|
3904
|
+
title,
|
|
3905
|
+
titleAs = "h3",
|
|
3906
|
+
description,
|
|
3907
|
+
author,
|
|
3908
|
+
footer,
|
|
3909
|
+
radius = "md",
|
|
3910
|
+
orientation = "vertical",
|
|
3911
|
+
href,
|
|
3912
|
+
onClick,
|
|
3913
|
+
id: providedId,
|
|
3914
|
+
className,
|
|
3915
|
+
...rest
|
|
3916
|
+
}, ref) {
|
|
3917
|
+
const reactId = (0, import_react24.useId)();
|
|
3918
|
+
const baseId = providedId ?? `ods-blog-card-${reactId}`;
|
|
3919
|
+
const titleId = `${baseId}-title`;
|
|
3920
|
+
const descId = description ? `${baseId}-desc` : void 0;
|
|
3921
|
+
const tagList = tags ?? (category ? [category] : []);
|
|
3922
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
3923
|
+
cover && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3924
|
+
"div",
|
|
3925
|
+
{
|
|
3926
|
+
className: cn(
|
|
3927
|
+
"ods-blog-card__cover",
|
|
3928
|
+
`ods-blog-card__cover--aspect-${coverAspect.replace("/", "-")}`
|
|
3929
|
+
),
|
|
3930
|
+
"aria-hidden": "true",
|
|
3931
|
+
children: cover
|
|
3932
|
+
}
|
|
3933
|
+
),
|
|
3934
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ods-blog-card__body", children: [
|
|
3935
|
+
(tagList.length > 0 || meta || readingTime) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ods-blog-card__meta", children: [
|
|
3936
|
+
tagList.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ods-blog-card__tags", children: tagList.map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ods-blog-card__tag", children: t }, i)) }),
|
|
3937
|
+
meta && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ods-blog-card__date", children: meta }),
|
|
3938
|
+
readingTime && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ods-blog-card__reading", children: readingTime })
|
|
3939
|
+
] }),
|
|
3940
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3941
|
+
Card.Title,
|
|
3942
|
+
{
|
|
3943
|
+
as: titleAs,
|
|
3944
|
+
id: titleId,
|
|
3945
|
+
className: "ods-blog-card__title",
|
|
3946
|
+
children: title
|
|
3947
|
+
}
|
|
3948
|
+
),
|
|
3949
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3950
|
+
Card.Description,
|
|
3951
|
+
{
|
|
3952
|
+
id: descId,
|
|
3953
|
+
className: "ods-blog-card__desc",
|
|
3954
|
+
children: description
|
|
3955
|
+
}
|
|
3956
|
+
),
|
|
3957
|
+
(author || footer) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ods-blog-card__footer", children: [
|
|
3958
|
+
author && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ods-blog-card__author", children: [
|
|
3959
|
+
author.avatar && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3960
|
+
Avatar,
|
|
3939
3961
|
{
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
"/",
|
|
3945
|
-
maxLength
|
|
3946
|
-
]
|
|
3962
|
+
size: "sm",
|
|
3963
|
+
src: author.avatar.src,
|
|
3964
|
+
initials: author.avatar.initials,
|
|
3965
|
+
alt: author.avatar.alt ?? (typeof author.name === "string" ? author.name : void 0)
|
|
3947
3966
|
}
|
|
3948
|
-
)
|
|
3967
|
+
),
|
|
3968
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ods-blog-card__author-text", children: [
|
|
3969
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ods-blog-card__author-name", children: author.name }),
|
|
3970
|
+
author.byline && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ods-blog-card__author-byline", children: author.byline })
|
|
3971
|
+
] })
|
|
3949
3972
|
] }),
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3973
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ods-blog-card__action", children: footer })
|
|
3974
|
+
] })
|
|
3975
|
+
] })
|
|
3976
|
+
] });
|
|
3977
|
+
if (href) {
|
|
3978
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3979
|
+
Card,
|
|
3980
|
+
{
|
|
3981
|
+
asChild: true,
|
|
3982
|
+
radius,
|
|
3983
|
+
padding: "none",
|
|
3984
|
+
className: cn(
|
|
3985
|
+
"ods-blog-card",
|
|
3986
|
+
`ods-blog-card--${orientation}`,
|
|
3987
|
+
"ods-blog-card--interactive",
|
|
3988
|
+
className
|
|
3956
3989
|
),
|
|
3957
|
-
|
|
3958
|
-
|
|
3990
|
+
"aria-labelledby": titleId,
|
|
3991
|
+
"aria-describedby": descId,
|
|
3992
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3993
|
+
"a",
|
|
3959
3994
|
{
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3995
|
+
...rest,
|
|
3996
|
+
ref,
|
|
3997
|
+
href,
|
|
3998
|
+
id: baseId,
|
|
3999
|
+
onClick,
|
|
4000
|
+
children: body
|
|
3964
4001
|
}
|
|
3965
|
-
)
|
|
3966
|
-
|
|
4002
|
+
)
|
|
4003
|
+
}
|
|
4004
|
+
);
|
|
4005
|
+
}
|
|
4006
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4007
|
+
Card,
|
|
4008
|
+
{
|
|
4009
|
+
...rest,
|
|
4010
|
+
ref,
|
|
4011
|
+
id: baseId,
|
|
4012
|
+
radius,
|
|
4013
|
+
padding: "none",
|
|
4014
|
+
onClick,
|
|
4015
|
+
className: cn(
|
|
4016
|
+
"ods-blog-card",
|
|
4017
|
+
`ods-blog-card--${orientation}`,
|
|
4018
|
+
onClick && "ods-blog-card--interactive",
|
|
4019
|
+
className
|
|
4020
|
+
),
|
|
4021
|
+
"aria-labelledby": titleId,
|
|
4022
|
+
"aria-describedby": descId,
|
|
4023
|
+
children: body
|
|
3967
4024
|
}
|
|
3968
4025
|
);
|
|
3969
4026
|
}
|
|
3970
4027
|
);
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
4028
|
+
BlogCard.displayName = "BlogCard";
|
|
4029
|
+
|
|
4030
|
+
// src/marketing/components/BlogGrid/BlogGrid.tsx
|
|
4031
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
4032
|
+
function BlogGrid({
|
|
4033
|
+
posts,
|
|
4034
|
+
columns = 3,
|
|
4035
|
+
viewAllHref,
|
|
4036
|
+
viewAllLabel = "View all posts \u2192",
|
|
4037
|
+
className,
|
|
4038
|
+
...rest
|
|
3975
4039
|
}) {
|
|
3976
|
-
return /* @__PURE__ */ (0, import_jsx_runtime13.
|
|
3977
|
-
"div",
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
4040
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { ...rest, className: cn("ods-mkt-blog", className), children: [
|
|
4041
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("ods-mkt-blog__grid", `ods-mkt-blog__grid--${columns}`), children: posts.map((post) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
4042
|
+
BlogCard,
|
|
4043
|
+
{
|
|
4044
|
+
title: post.title,
|
|
4045
|
+
description: post.excerpt,
|
|
4046
|
+
href: post.href,
|
|
4047
|
+
meta: post.date,
|
|
4048
|
+
readingTime: post.readTime,
|
|
4049
|
+
tags: post.tags,
|
|
4050
|
+
cover: post.cover,
|
|
4051
|
+
author: post.author
|
|
3986
4052
|
},
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
{
|
|
3992
|
-
className: "ods-textarea__toolbar-divider",
|
|
3993
|
-
"aria-hidden": "true"
|
|
3994
|
-
},
|
|
3995
|
-
t.id
|
|
3996
|
-
);
|
|
3997
|
-
}
|
|
3998
|
-
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3999
|
-
"button",
|
|
4000
|
-
{
|
|
4001
|
-
type: "button",
|
|
4002
|
-
className: "ods-textarea__toolbar-btn",
|
|
4003
|
-
title: t.title ?? (typeof t.label === "string" ? t.label : void 0),
|
|
4004
|
-
"aria-label": typeof t.label === "string" ? t.label : t.id,
|
|
4005
|
-
onClick: () => onRun(t.id),
|
|
4006
|
-
children: t.icon ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ods-textarea__toolbar-icon", children: t.icon }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ods-textarea__toolbar-text", children: t.label })
|
|
4007
|
-
},
|
|
4008
|
-
t.id
|
|
4009
|
-
);
|
|
4010
|
-
})
|
|
4011
|
-
}
|
|
4012
|
-
);
|
|
4053
|
+
post.id
|
|
4054
|
+
)) }),
|
|
4055
|
+
viewAllHref && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ods-mkt-blog__more", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("a", { className: "ods-mkt-blog__more-link", href: viewAllHref, children: viewAllLabel }) })
|
|
4056
|
+
] });
|
|
4013
4057
|
}
|
|
4014
4058
|
|
|
4015
4059
|
// src/marketing/components/ContactForm/ContactForm.tsx
|
|
4060
|
+
var import_react25 = require("react");
|
|
4016
4061
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
4017
4062
|
function ContactForm({
|
|
4018
4063
|
title = "Talk to us",
|
|
@@ -4973,7 +5018,24 @@ function MarketingHero({
|
|
|
4973
5018
|
}
|
|
4974
5019
|
|
|
4975
5020
|
// src/marketing/components/MarketingNav/MarketingNav.tsx
|
|
5021
|
+
var import_react29 = require("react");
|
|
4976
5022
|
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
5023
|
+
function BurgerGlyph({ open }) {
|
|
5024
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5025
|
+
"svg",
|
|
5026
|
+
{
|
|
5027
|
+
viewBox: "0 0 24 24",
|
|
5028
|
+
width: "20",
|
|
5029
|
+
height: "20",
|
|
5030
|
+
fill: "none",
|
|
5031
|
+
stroke: "currentColor",
|
|
5032
|
+
strokeWidth: "2",
|
|
5033
|
+
strokeLinecap: "round",
|
|
5034
|
+
"aria-hidden": "true",
|
|
5035
|
+
children: open ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("path", { d: "M6 6l12 12M18 6 6 18" }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("path", { d: "M4 7h16M4 12h16M4 17h16" })
|
|
5036
|
+
}
|
|
5037
|
+
);
|
|
5038
|
+
}
|
|
4977
5039
|
function MarketingNav({
|
|
4978
5040
|
brand,
|
|
4979
5041
|
brandHref = "/",
|
|
@@ -4983,6 +5045,7 @@ function MarketingNav({
|
|
|
4983
5045
|
className,
|
|
4984
5046
|
...rest
|
|
4985
5047
|
}) {
|
|
5048
|
+
const [mobileOpen, setMobileOpen] = (0, import_react29.useState)(false);
|
|
4986
5049
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("header", { ...rest, className: cn("ods-mkt-nav", sticky && "ods-mkt-nav--sticky", className), children: [
|
|
4987
5050
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("a", { className: "ods-mkt-nav__brand", href: brandHref, children: brand ?? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
4988
5051
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(BrandMark, {}),
|
|
@@ -4998,7 +5061,35 @@ function MarketingNav({
|
|
|
4998
5061
|
},
|
|
4999
5062
|
link.href
|
|
5000
5063
|
)) }),
|
|
5001
|
-
actions && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "ods-mkt-nav__actions", children: actions })
|
|
5064
|
+
actions && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "ods-mkt-nav__actions", children: actions }),
|
|
5065
|
+
(links.length > 0 || actions) && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5066
|
+
"button",
|
|
5067
|
+
{
|
|
5068
|
+
type: "button",
|
|
5069
|
+
className: "ods-mkt-nav__toggle",
|
|
5070
|
+
"aria-expanded": mobileOpen,
|
|
5071
|
+
"aria-label": "Toggle menu",
|
|
5072
|
+
onClick: () => setMobileOpen((open) => !open),
|
|
5073
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(BurgerGlyph, { open: mobileOpen })
|
|
5074
|
+
}
|
|
5075
|
+
),
|
|
5076
|
+
mobileOpen && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("nav", { className: "ods-mkt-nav__mobile", "aria-label": "Main", children: [
|
|
5077
|
+
links.map((link) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5078
|
+
"a",
|
|
5079
|
+
{
|
|
5080
|
+
href: link.href,
|
|
5081
|
+
className: cn(
|
|
5082
|
+
"ods-mkt-nav__mobile-link",
|
|
5083
|
+
link.active && "ods-mkt-nav__mobile-link--active"
|
|
5084
|
+
),
|
|
5085
|
+
"aria-current": link.active ? "page" : void 0,
|
|
5086
|
+
onClick: () => setMobileOpen(false),
|
|
5087
|
+
children: link.label
|
|
5088
|
+
},
|
|
5089
|
+
link.href
|
|
5090
|
+
)),
|
|
5091
|
+
actions && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "ods-mkt-nav__mobile-actions", children: actions })
|
|
5092
|
+
] })
|
|
5002
5093
|
] });
|
|
5003
5094
|
}
|
|
5004
5095
|
|
|
@@ -5122,10 +5213,10 @@ function PricingTiers({ tiers, note, className, ...rest }) {
|
|
|
5122
5213
|
var import_framer_motion7 = require("framer-motion");
|
|
5123
5214
|
|
|
5124
5215
|
// src/components/CountUp/CountUp.tsx
|
|
5125
|
-
var
|
|
5216
|
+
var import_react30 = require("react");
|
|
5126
5217
|
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
5127
5218
|
var easeOutCubic = (t) => 1 - Math.pow(1 - t, 3);
|
|
5128
|
-
var CountUp = (0,
|
|
5219
|
+
var CountUp = (0, import_react30.forwardRef)(
|
|
5129
5220
|
function CountUp2({
|
|
5130
5221
|
value,
|
|
5131
5222
|
from = 0,
|
|
@@ -5141,9 +5232,9 @@ var CountUp = (0, import_react29.forwardRef)(
|
|
|
5141
5232
|
className,
|
|
5142
5233
|
...rest
|
|
5143
5234
|
}, ref) {
|
|
5144
|
-
const [n, setN] = (0,
|
|
5145
|
-
const lastRendered = (0,
|
|
5146
|
-
(0,
|
|
5235
|
+
const [n, setN] = (0, import_react30.useState)(disableAnimation ? value : from);
|
|
5236
|
+
const lastRendered = (0, import_react30.useRef)(disableAnimation ? value : from);
|
|
5237
|
+
(0, import_react30.useEffect)(() => {
|
|
5147
5238
|
const reduced = typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
5148
5239
|
if (disableAnimation || reduced) {
|
|
5149
5240
|
setN(value);
|
|
@@ -5241,13 +5332,13 @@ function StatBand({ items, orientation = "column", className, ...rest }) {
|
|
|
5241
5332
|
|
|
5242
5333
|
// src/components/TestimonialCard/TestimonialCard.tsx
|
|
5243
5334
|
var import_icons9 = require("@octaviaflow/icons");
|
|
5244
|
-
var
|
|
5335
|
+
var import_react31 = require("react");
|
|
5245
5336
|
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
5246
5337
|
function isAuthorObject(v) {
|
|
5247
5338
|
return typeof v === "object" && v !== null && !("type" in v) && // exclude React elements
|
|
5248
5339
|
"name" in v;
|
|
5249
5340
|
}
|
|
5250
|
-
var TestimonialCard = (0,
|
|
5341
|
+
var TestimonialCard = (0, import_react31.forwardRef)(function TestimonialCard2({
|
|
5251
5342
|
quote,
|
|
5252
5343
|
author,
|
|
5253
5344
|
role: legacyRole,
|
|
@@ -5261,7 +5352,7 @@ var TestimonialCard = (0, import_react30.forwardRef)(function TestimonialCard2({
|
|
|
5261
5352
|
className,
|
|
5262
5353
|
...rest
|
|
5263
5354
|
}, ref) {
|
|
5264
|
-
const reactId = (0,
|
|
5355
|
+
const reactId = (0, import_react31.useId)();
|
|
5265
5356
|
const baseId = providedId ?? `ods-testimonial-${reactId}`;
|
|
5266
5357
|
const quoteId = `${baseId}-quote`;
|
|
5267
5358
|
const authorId = `${baseId}-author`;
|
|
@@ -5383,10 +5474,10 @@ function TestimonialStrip({
|
|
|
5383
5474
|
|
|
5384
5475
|
// src/marketing/components/WorkflowShowcase/WorkflowShowcase.tsx
|
|
5385
5476
|
var import_framer_motion9 = require("framer-motion");
|
|
5386
|
-
var
|
|
5477
|
+
var import_react34 = require("react");
|
|
5387
5478
|
|
|
5388
5479
|
// src/marketing/components/WorkflowShowcase/ShowcaseScene.tsx
|
|
5389
|
-
var
|
|
5480
|
+
var import_react32 = require("react");
|
|
5390
5481
|
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
5391
5482
|
function slots(n) {
|
|
5392
5483
|
return Array.from({ length: n }, (_, i) => 208 + (i - (n - 1) / 2) * 80);
|
|
@@ -5459,9 +5550,9 @@ function ShowcaseScene({
|
|
|
5459
5550
|
caption,
|
|
5460
5551
|
onCoreClick
|
|
5461
5552
|
}) {
|
|
5462
|
-
const [pulse, setPulse] = (0,
|
|
5463
|
-
const pulseTimer = (0,
|
|
5464
|
-
(0,
|
|
5553
|
+
const [pulse, setPulse] = (0, import_react32.useState)(false);
|
|
5554
|
+
const pulseTimer = (0, import_react32.useRef)(null);
|
|
5555
|
+
(0, import_react32.useEffect)(
|
|
5465
5556
|
() => () => {
|
|
5466
5557
|
if (pulseTimer.current) clearTimeout(pulseTimer.current);
|
|
5467
5558
|
},
|
|
@@ -5692,7 +5783,7 @@ function ShowcaseScene({
|
|
|
5692
5783
|
|
|
5693
5784
|
// src/marketing/components/WorkflowShowcase/ShowcaseSignup.tsx
|
|
5694
5785
|
var import_framer_motion8 = require("framer-motion");
|
|
5695
|
-
var
|
|
5786
|
+
var import_react33 = require("react");
|
|
5696
5787
|
var import_react_aria5 = require("react-aria");
|
|
5697
5788
|
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
5698
5789
|
var OVERLAY_MOTION = {
|
|
@@ -5712,9 +5803,9 @@ function ShowcaseSignup({
|
|
|
5712
5803
|
onboardingHref = "#"
|
|
5713
5804
|
}) {
|
|
5714
5805
|
const reducedMotion = (0, import_framer_motion8.useReducedMotion)();
|
|
5715
|
-
const titleId = (0,
|
|
5716
|
-
const subtitleId = (0,
|
|
5717
|
-
const [values, setValues] = (0,
|
|
5806
|
+
const titleId = (0, import_react33.useId)();
|
|
5807
|
+
const subtitleId = (0, import_react33.useId)();
|
|
5808
|
+
const [values, setValues] = (0, import_react33.useState)({
|
|
5718
5809
|
name: "",
|
|
5719
5810
|
email: "",
|
|
5720
5811
|
company: "",
|
|
@@ -5932,53 +6023,53 @@ function WorkflowShowcase({
|
|
|
5932
6023
|
}) {
|
|
5933
6024
|
const reducedMotion = (0, import_framer_motion9.useReducedMotion)();
|
|
5934
6025
|
const rotationActive = rotatePrompts && !defaultPrompt && examples.length > 0;
|
|
5935
|
-
const [prompt, setPrompt] = (0,
|
|
6026
|
+
const [prompt, setPrompt] = (0, import_react34.useState)(
|
|
5936
6027
|
defaultPrompt || (rotationActive ? examples[0]?.prompt ?? "" : "")
|
|
5937
6028
|
);
|
|
5938
|
-
const [engagedWithPrompt, setEngagedWithPrompt] = (0,
|
|
5939
|
-
const [promptHovered, setPromptHovered] = (0,
|
|
5940
|
-
const [promptFocused, setPromptFocused] = (0,
|
|
5941
|
-
const rotateIdx = (0,
|
|
5942
|
-
const [selected, setSelected] = (0,
|
|
5943
|
-
const [phase, setPhase] = (0,
|
|
5944
|
-
const [shown, setShown] = (0,
|
|
5945
|
-
const [status, setStatus] = (0,
|
|
5946
|
-
const [pickerOpen, setPickerOpen] = (0,
|
|
5947
|
-
const [schedIdx, setSchedIdx] = (0,
|
|
5948
|
-
const [swap, setSwap] = (0,
|
|
5949
|
-
const [signupError, setSignupError] = (0,
|
|
5950
|
-
const signupReturnPhase = (0,
|
|
5951
|
-
const cardRef = (0,
|
|
5952
|
-
const timers = (0,
|
|
5953
|
-
const clearTimers = (0,
|
|
6029
|
+
const [engagedWithPrompt, setEngagedWithPrompt] = (0, import_react34.useState)(false);
|
|
6030
|
+
const [promptHovered, setPromptHovered] = (0, import_react34.useState)(false);
|
|
6031
|
+
const [promptFocused, setPromptFocused] = (0, import_react34.useState)(false);
|
|
6032
|
+
const rotateIdx = (0, import_react34.useRef)(0);
|
|
6033
|
+
const [selected, setSelected] = (0, import_react34.useState)([]);
|
|
6034
|
+
const [phase, setPhase] = (0, import_react34.useState)("idle");
|
|
6035
|
+
const [shown, setShown] = (0, import_react34.useState)(0);
|
|
6036
|
+
const [status, setStatus] = (0, import_react34.useState)("");
|
|
6037
|
+
const [pickerOpen, setPickerOpen] = (0, import_react34.useState)(false);
|
|
6038
|
+
const [schedIdx, setSchedIdx] = (0, import_react34.useState)(0);
|
|
6039
|
+
const [swap, setSwap] = (0, import_react34.useState)(null);
|
|
6040
|
+
const [signupError, setSignupError] = (0, import_react34.useState)(null);
|
|
6041
|
+
const signupReturnPhase = (0, import_react34.useRef)("done");
|
|
6042
|
+
const cardRef = (0, import_react34.useRef)(null);
|
|
6043
|
+
const timers = (0, import_react34.useRef)([]);
|
|
6044
|
+
const clearTimers = (0, import_react34.useCallback)(() => {
|
|
5954
6045
|
for (const t of timers.current) clearTimeout(t);
|
|
5955
6046
|
timers.current = [];
|
|
5956
6047
|
}, []);
|
|
5957
|
-
(0,
|
|
6048
|
+
(0, import_react34.useEffect)(() => clearTimers, [clearTimers]);
|
|
5958
6049
|
const tempo = reducedMotion ? 0.35 : 1;
|
|
5959
|
-
const at = (0,
|
|
6050
|
+
const at = (0, import_react34.useCallback)(
|
|
5960
6051
|
(ms, fn) => {
|
|
5961
6052
|
timers.current.push(setTimeout(fn, ms * tempo));
|
|
5962
6053
|
},
|
|
5963
6054
|
[tempo]
|
|
5964
6055
|
);
|
|
5965
|
-
const firstPhase = (0,
|
|
5966
|
-
(0,
|
|
6056
|
+
const firstPhase = (0, import_react34.useRef)(true);
|
|
6057
|
+
(0, import_react34.useEffect)(() => {
|
|
5967
6058
|
if (firstPhase.current) {
|
|
5968
6059
|
firstPhase.current = false;
|
|
5969
6060
|
return;
|
|
5970
6061
|
}
|
|
5971
6062
|
onPhaseChange?.(phase);
|
|
5972
6063
|
}, [phase, onPhaseChange]);
|
|
5973
|
-
const phaseRef = (0,
|
|
6064
|
+
const phaseRef = (0, import_react34.useRef)(phase);
|
|
5974
6065
|
phaseRef.current = phase;
|
|
5975
|
-
const byName = (0,
|
|
5976
|
-
const detected = (0,
|
|
5977
|
-
const union = (0,
|
|
6066
|
+
const byName = (0, import_react34.useMemo)(() => new Map(connectors.map((c) => [c.name, c])), [connectors]);
|
|
6067
|
+
const detected = (0, import_react34.useMemo)(() => detectConnectors(prompt, connectors), [prompt, connectors]);
|
|
6068
|
+
const union = (0, import_react34.useMemo)(() => [.../* @__PURE__ */ new Set([...selected, ...detected])], [selected, detected]);
|
|
5978
6069
|
const settled = SETTLED_PHASES.includes(phase);
|
|
5979
6070
|
const engaged = phase !== "idle";
|
|
5980
6071
|
const buildingNow = phase === "analyzing" || phase === "building";
|
|
5981
|
-
const plan = (0,
|
|
6072
|
+
const plan = (0, import_react34.useMemo)(() => {
|
|
5982
6073
|
if (!selected.length) return EMPTY_PLAN;
|
|
5983
6074
|
return resolvePlan(selected, [], connectors);
|
|
5984
6075
|
}, [selected, connectors]);
|
|
@@ -5987,10 +6078,10 @@ function WorkflowShowcase({
|
|
|
5987
6078
|
const manualSchedule = schedules[schedIdx];
|
|
5988
6079
|
const scheduleShown = inferredSchedule ?? (manualSchedule === "AUTO" ? "HOURLY" : manualSchedule);
|
|
5989
6080
|
const triggers = WORKFLOW_SHOWCASE_TRIGGERS;
|
|
5990
|
-
const [triggerIdx, setTriggerIdx] = (0,
|
|
6081
|
+
const [triggerIdx, setTriggerIdx] = (0, import_react34.useState)(0);
|
|
5991
6082
|
const manualTrigger = triggers[triggerIdx];
|
|
5992
6083
|
const cadenceShown = manualTrigger === "SCHEDULE" ? scheduleShown : manualTrigger;
|
|
5993
|
-
(0,
|
|
6084
|
+
(0, import_react34.useEffect)(() => {
|
|
5994
6085
|
if (!rotationActive || engagedWithPrompt || promptHovered || promptFocused || phase !== "idle") {
|
|
5995
6086
|
return;
|
|
5996
6087
|
}
|
|
@@ -6000,7 +6091,7 @@ function WorkflowShowcase({
|
|
|
6000
6091
|
}, 4200);
|
|
6001
6092
|
return () => clearInterval(timer);
|
|
6002
6093
|
}, [rotationActive, engagedWithPrompt, promptHovered, promptFocused, phase, examples]);
|
|
6003
|
-
const startBuild = (0,
|
|
6094
|
+
const startBuild = (0, import_react34.useCallback)(
|
|
6004
6095
|
(text, baseSelected) => {
|
|
6005
6096
|
if (phaseRef.current === "analyzing" || phaseRef.current === "building") return;
|
|
6006
6097
|
phaseRef.current = "analyzing";
|
|
@@ -6037,7 +6128,7 @@ function WorkflowShowcase({
|
|
|
6037
6128
|
},
|
|
6038
6129
|
[clearTimers, connectors, onBuild, scheduleShown, manualTrigger, at]
|
|
6039
6130
|
);
|
|
6040
|
-
const resetToIdle = (0,
|
|
6131
|
+
const resetToIdle = (0, import_react34.useCallback)(() => {
|
|
6041
6132
|
clearTimers();
|
|
6042
6133
|
phaseRef.current = "idle";
|
|
6043
6134
|
setPhase("idle");
|