@octaviaflow/core 3.1.0-beta.70 → 3.1.0-beta.72
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 +17 -1
- package/dist/marketing/components/BetaAccessForm/BetaAccessForm.d.ts.map +1 -1
- package/dist/marketing/components/ContactForm/ContactForm.d.ts +2 -0
- package/dist/marketing/components/ContactForm/ContactForm.d.ts.map +1 -1
- package/dist/marketing/components/MarketingNav/MarketingNav.d.ts.map +1 -1
- package/dist/marketing.cjs +1810 -1682
- package/dist/marketing.cjs.map +1 -1
- package/dist/marketing.js +165 -35
- package/dist/marketing.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
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,1792 @@ 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
|
+
nameLayout = "single",
|
|
3376
|
+
appearance = "card",
|
|
3377
|
+
teamSizes,
|
|
3378
|
+
plans,
|
|
3379
|
+
defaultPlan,
|
|
3380
|
+
useCases,
|
|
3381
|
+
showDetails = false,
|
|
3382
|
+
detailsLabel = "Anything else we should know?",
|
|
3383
|
+
detailsPlaceholder = "Current stack, timelines, must-have connectors\u2026",
|
|
3384
|
+
submitLabel = "Request access \u2192",
|
|
3385
|
+
footnote = "NO CREDIT CARD \xB7 SSO & SELF-HOSTING AVAILABLE",
|
|
3386
|
+
onSubmit,
|
|
3387
|
+
successTitle = "Request received.",
|
|
3388
|
+
successBody = "We review access requests weekly \u2014 you'll hear from us by email.",
|
|
3389
|
+
disabled = false,
|
|
3390
|
+
className
|
|
3513
3391
|
}) {
|
|
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
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
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 {
|
|
3392
|
+
const uid = (0, import_react21.useId)();
|
|
3393
|
+
const [values, setValues] = (0, import_react21.useState)({
|
|
3394
|
+
email: "",
|
|
3395
|
+
name: "",
|
|
3396
|
+
firstName: "",
|
|
3397
|
+
lastName: "",
|
|
3398
|
+
company: "",
|
|
3399
|
+
teamSize: "",
|
|
3400
|
+
plan: defaultPlan ?? "",
|
|
3401
|
+
useCase: "",
|
|
3402
|
+
details: ""
|
|
3403
|
+
});
|
|
3404
|
+
const [phase, setPhase] = (0, import_react21.useState)("idle");
|
|
3405
|
+
const [error, setError] = (0, import_react21.useState)(null);
|
|
3406
|
+
const handleSubmit = async (event) => {
|
|
3407
|
+
event.preventDefault();
|
|
3408
|
+
if (phase === "submitting") return;
|
|
3409
|
+
if (!isValidEmail(values.email)) {
|
|
3410
|
+
setError("Please enter a valid work email.");
|
|
3411
|
+
return;
|
|
3412
|
+
}
|
|
3413
|
+
if (fields === "full" && nameLayout === "single" && !values.name?.trim()) {
|
|
3414
|
+
setError("Please enter your name.");
|
|
3415
|
+
return;
|
|
3416
|
+
}
|
|
3417
|
+
if (fields === "full" && nameLayout === "split" && !values.firstName?.trim()) {
|
|
3418
|
+
setError("Please enter your first name.");
|
|
3419
|
+
return;
|
|
3420
|
+
}
|
|
3421
|
+
if (fields === "full" && teamSizes?.length && !values.teamSize) {
|
|
3422
|
+
setError("Please select your team size.");
|
|
3423
|
+
return;
|
|
3424
|
+
}
|
|
3425
|
+
if (fields === "full" && useCases?.length && !values.useCase) {
|
|
3426
|
+
setError("Please select your primary use case.");
|
|
3427
|
+
return;
|
|
3428
|
+
}
|
|
3429
|
+
setError(null);
|
|
3430
|
+
setPhase("submitting");
|
|
3431
|
+
try {
|
|
3432
|
+
await onSubmit?.(values);
|
|
3433
|
+
setPhase("success");
|
|
3434
|
+
} catch {
|
|
3435
|
+
setError("Something went wrong \u2014 please try again.");
|
|
3436
|
+
setPhase("idle");
|
|
3437
|
+
}
|
|
3438
|
+
};
|
|
3439
|
+
const inline = appearance === "inline";
|
|
3440
|
+
if (phase === "success") {
|
|
3441
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3442
|
+
"div",
|
|
3443
|
+
{
|
|
3444
|
+
className: cn(
|
|
3445
|
+
"ods-mkt-access",
|
|
3446
|
+
"ods-mkt-access--success",
|
|
3447
|
+
inline && "ods-mkt-access--inline",
|
|
3448
|
+
className
|
|
3449
|
+
),
|
|
3450
|
+
role: "status",
|
|
3451
|
+
children: [
|
|
3452
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("p", { className: "ods-mkt-access__success-mark", children: [
|
|
3453
|
+
"\u2713 ",
|
|
3454
|
+
successTitle
|
|
3455
|
+
] }),
|
|
3456
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "ods-mkt-access__success-body", children: successBody })
|
|
3457
|
+
]
|
|
3595
3458
|
}
|
|
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
|
-
|
|
3459
|
+
);
|
|
3460
|
+
}
|
|
3461
|
+
const busy = disabled || phase === "submitting";
|
|
3462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3463
|
+
"form",
|
|
3464
|
+
{
|
|
3465
|
+
className: cn("ods-mkt-access", inline && "ods-mkt-access--inline", className),
|
|
3466
|
+
onSubmit: handleSubmit,
|
|
3467
|
+
noValidate: true,
|
|
3468
|
+
children: [
|
|
3469
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__head", children: [
|
|
3470
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { className: "ods-mkt-access__title", children: title }),
|
|
3471
|
+
subtitle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "ods-mkt-access__subtitle", children: subtitle })
|
|
3472
|
+
] }),
|
|
3473
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3474
|
+
"div",
|
|
3475
|
+
{
|
|
3476
|
+
className: cn(
|
|
3477
|
+
"ods-mkt-access__fields",
|
|
3478
|
+
fields === "full" && "ods-mkt-access__fields--full"
|
|
3479
|
+
),
|
|
3480
|
+
children: [
|
|
3481
|
+
fields === "full" && nameLayout === "single" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3482
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: "ods-mkt-access__label", htmlFor: `${uid}-name`, children: "Full name" }),
|
|
3483
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3484
|
+
Input,
|
|
3485
|
+
{
|
|
3486
|
+
id: `${uid}-name`,
|
|
3487
|
+
autoComplete: "name",
|
|
3488
|
+
placeholder: "Ada Lovelace",
|
|
3489
|
+
value: values.name ?? "",
|
|
3490
|
+
onChange: (e) => setValues((v) => ({ ...v, name: e.target.value })),
|
|
3491
|
+
disabled: busy
|
|
3492
|
+
}
|
|
3493
|
+
)
|
|
3494
|
+
] }),
|
|
3495
|
+
fields === "full" && nameLayout === "split" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
3496
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3497
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: "ods-mkt-access__label", htmlFor: `${uid}-firstname`, children: "First name" }),
|
|
3498
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3499
|
+
Input,
|
|
3500
|
+
{
|
|
3501
|
+
id: `${uid}-firstname`,
|
|
3502
|
+
autoComplete: "given-name",
|
|
3503
|
+
placeholder: "Ada",
|
|
3504
|
+
value: values.firstName ?? "",
|
|
3505
|
+
onChange: (e) => setValues((v) => ({ ...v, firstName: e.target.value })),
|
|
3506
|
+
disabled: busy
|
|
3507
|
+
}
|
|
3508
|
+
)
|
|
3509
|
+
] }),
|
|
3510
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3511
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: "ods-mkt-access__label", htmlFor: `${uid}-lastname`, children: "Last name" }),
|
|
3512
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3513
|
+
Input,
|
|
3514
|
+
{
|
|
3515
|
+
id: `${uid}-lastname`,
|
|
3516
|
+
autoComplete: "family-name",
|
|
3517
|
+
placeholder: "Lovelace",
|
|
3518
|
+
value: values.lastName ?? "",
|
|
3519
|
+
onChange: (e) => setValues((v) => ({ ...v, lastName: e.target.value })),
|
|
3520
|
+
disabled: busy
|
|
3521
|
+
}
|
|
3522
|
+
)
|
|
3523
|
+
] })
|
|
3524
|
+
] }),
|
|
3525
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3526
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: "ods-mkt-access__label", htmlFor: `${uid}-email`, children: "Work email" }),
|
|
3527
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3528
|
+
Input,
|
|
3529
|
+
{
|
|
3530
|
+
id: `${uid}-email`,
|
|
3531
|
+
type: "email",
|
|
3532
|
+
autoComplete: "email",
|
|
3533
|
+
placeholder: "ada@company.com",
|
|
3534
|
+
value: values.email,
|
|
3535
|
+
onChange: (e) => setValues((v) => ({ ...v, email: e.target.value })),
|
|
3536
|
+
disabled: busy
|
|
3537
|
+
}
|
|
3538
|
+
)
|
|
3539
|
+
] }),
|
|
3540
|
+
fields === "full" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3541
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: "ods-mkt-access__label", htmlFor: `${uid}-company`, children: "Company" }),
|
|
3542
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3543
|
+
Input,
|
|
3544
|
+
{
|
|
3545
|
+
id: `${uid}-company`,
|
|
3546
|
+
autoComplete: "organization",
|
|
3547
|
+
placeholder: "Acme Inc.",
|
|
3548
|
+
value: values.company ?? "",
|
|
3549
|
+
onChange: (e) => setValues((v) => ({ ...v, company: e.target.value })),
|
|
3550
|
+
disabled: busy
|
|
3551
|
+
}
|
|
3552
|
+
)
|
|
3553
|
+
] }),
|
|
3554
|
+
fields === "full" && teamSizes && teamSizes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3555
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "ods-mkt-access__label", id: `${uid}-teamsize-label`, children: "Team size" }),
|
|
3556
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3557
|
+
Select,
|
|
3558
|
+
{
|
|
3559
|
+
"aria-labelledby": `${uid}-teamsize-label`,
|
|
3560
|
+
placeholder: "Select team size\u2026",
|
|
3561
|
+
options: teamSizes.map((size) => ({ value: size, label: size })),
|
|
3562
|
+
value: values.teamSize ?? "",
|
|
3563
|
+
onChange: (teamSize) => setValues((v) => ({ ...v, teamSize })),
|
|
3564
|
+
disabled: busy
|
|
3565
|
+
}
|
|
3566
|
+
)
|
|
3567
|
+
] }),
|
|
3568
|
+
fields === "full" && plans && plans.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3569
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "ods-mkt-access__label", id: `${uid}-plan-label`, children: "Plan (optional)" }),
|
|
3570
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3571
|
+
Select,
|
|
3572
|
+
{
|
|
3573
|
+
"aria-labelledby": `${uid}-plan-label`,
|
|
3574
|
+
placeholder: "Not sure yet",
|
|
3575
|
+
options: plans.map((plan) => ({ value: plan, label: plan })),
|
|
3576
|
+
value: values.plan ?? "",
|
|
3577
|
+
onChange: (plan) => setValues((v) => ({ ...v, plan })),
|
|
3578
|
+
disabled: busy
|
|
3579
|
+
}
|
|
3580
|
+
)
|
|
3581
|
+
] }),
|
|
3582
|
+
fields === "full" && useCases && useCases.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field", children: [
|
|
3583
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "ods-mkt-access__label", id: `${uid}-usecase-label`, children: "Primary use case" }),
|
|
3584
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3585
|
+
Select,
|
|
3586
|
+
{
|
|
3587
|
+
"aria-labelledby": `${uid}-usecase-label`,
|
|
3588
|
+
placeholder: "Select a use case\u2026",
|
|
3589
|
+
options: useCases.map((useCase) => ({ value: useCase, label: useCase })),
|
|
3590
|
+
value: values.useCase ?? "",
|
|
3591
|
+
onChange: (useCase) => setValues((v) => ({ ...v, useCase })),
|
|
3592
|
+
disabled: busy
|
|
3593
|
+
}
|
|
3594
|
+
)
|
|
3595
|
+
] }),
|
|
3596
|
+
fields === "full" && showDetails && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "ods-mkt-access__field ods-mkt-access__field--wide", children: [
|
|
3597
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3598
|
+
"label",
|
|
3599
|
+
{
|
|
3600
|
+
className: "ods-mkt-access__label",
|
|
3601
|
+
id: `${uid}-details-label`,
|
|
3602
|
+
htmlFor: `${uid}-details`,
|
|
3603
|
+
children: detailsLabel
|
|
3604
|
+
}
|
|
3605
|
+
),
|
|
3606
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3607
|
+
Textarea,
|
|
3608
|
+
{
|
|
3609
|
+
id: `${uid}-details`,
|
|
3610
|
+
"aria-labelledby": `${uid}-details-label`,
|
|
3611
|
+
placeholder: detailsPlaceholder,
|
|
3612
|
+
rows: 3,
|
|
3613
|
+
value: values.details ?? "",
|
|
3614
|
+
onChange: (e) => setValues((v) => ({ ...v, details: e.target.value })),
|
|
3615
|
+
disabled: busy
|
|
3616
|
+
}
|
|
3617
|
+
)
|
|
3618
|
+
] }),
|
|
3619
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3620
|
+
Button,
|
|
3621
|
+
{
|
|
3622
|
+
type: "submit",
|
|
3623
|
+
variant: "primary",
|
|
3624
|
+
loading: phase === "submitting",
|
|
3625
|
+
disabled,
|
|
3626
|
+
children: submitLabel
|
|
3627
|
+
}
|
|
3628
|
+
)
|
|
3629
|
+
]
|
|
3630
|
+
}
|
|
3631
|
+
),
|
|
3632
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "ods-mkt-access__error", role: "alert", children: error }),
|
|
3633
|
+
footnote && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "ods-mkt-access__footnote", children: footnote })
|
|
3634
|
+
]
|
|
3635
|
+
}
|
|
3625
3636
|
);
|
|
3626
|
-
return { tools: visibleTools, runTool, helpers };
|
|
3627
3637
|
}
|
|
3628
3638
|
|
|
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)(
|
|
3639
|
+
// src/components/BlogCard/BlogCard.tsx
|
|
3640
|
+
var import_react24 = require("react");
|
|
3641
|
+
|
|
3642
|
+
// src/components/Avatar/Avatar.tsx
|
|
3643
|
+
var import_react22 = require("react");
|
|
3644
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
3645
|
+
var PALETTE_SIZE = 12;
|
|
3646
|
+
function djb2(str) {
|
|
3647
|
+
let h = 5381;
|
|
3648
|
+
for (let i = 0; i < str.length; i++) h = (h << 5) + h + str.charCodeAt(i);
|
|
3649
|
+
return h >>> 0;
|
|
3650
|
+
}
|
|
3651
|
+
function paletteIndexFor(seed) {
|
|
3652
|
+
return djb2(seed) % PALETTE_SIZE;
|
|
3653
|
+
}
|
|
3654
|
+
function normalizeInitials(raw) {
|
|
3655
|
+
const trimmed = raw.trim();
|
|
3656
|
+
if (!trimmed) return "";
|
|
3657
|
+
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
|
3658
|
+
if (tokens.length >= 2) {
|
|
3659
|
+
return (tokens[0].charAt(0) + tokens[1].charAt(0)).toUpperCase();
|
|
3660
|
+
}
|
|
3661
|
+
return trimmed.slice(0, 2).toUpperCase();
|
|
3662
|
+
}
|
|
3663
|
+
var STATUS_DEFAULT_LABEL = {
|
|
3664
|
+
online: "Online",
|
|
3665
|
+
offline: "Offline",
|
|
3666
|
+
busy: "Busy",
|
|
3667
|
+
away: "Away"
|
|
3668
|
+
};
|
|
3669
|
+
var Avatar = (0, import_react22.forwardRef)(function Avatar2({
|
|
3670
|
+
src,
|
|
3671
|
+
alt,
|
|
3672
|
+
initials,
|
|
3673
|
+
icon,
|
|
3674
|
+
fallback,
|
|
3675
|
+
seed,
|
|
3676
|
+
size = "md",
|
|
3677
|
+
shape = "circle",
|
|
3678
|
+
status,
|
|
3679
|
+
statusLabel,
|
|
3680
|
+
onClick,
|
|
3681
|
+
imgLoading = "lazy",
|
|
3682
|
+
referrerPolicy,
|
|
3683
|
+
className,
|
|
3684
|
+
...rest
|
|
3685
|
+
}, ref) {
|
|
3686
|
+
const [imgFailed, setImgFailed] = (0, import_react22.useState)(false);
|
|
3687
|
+
const handleImgError = (0, import_react22.useCallback)(() => setImgFailed(true), []);
|
|
3688
|
+
const showImage = Boolean(src) && !imgFailed;
|
|
3689
|
+
const normalizedInitials = (0, import_react22.useMemo)(
|
|
3690
|
+
() => initials ? normalizeInitials(initials) : "",
|
|
3691
|
+
[initials]
|
|
3692
|
+
);
|
|
3693
|
+
const paletteIdx = (0, import_react22.useMemo)(() => {
|
|
3694
|
+
const resolved = seed ?? initials ?? alt ?? "?";
|
|
3695
|
+
return paletteIndexFor(resolved);
|
|
3696
|
+
}, [seed, initials, alt]);
|
|
3697
|
+
const baseName = alt || normalizedInitials || "Avatar";
|
|
3698
|
+
const announcedStatus = status ? statusLabel ?? STATUS_DEFAULT_LABEL[status] : "";
|
|
3699
|
+
const accessibleName = announcedStatus ? `${baseName}, ${announcedStatus}` : baseName;
|
|
3700
|
+
const isClickable = Boolean(onClick);
|
|
3701
|
+
const handleKeyDown = (e) => {
|
|
3702
|
+
if (!isClickable) return;
|
|
3703
|
+
if ((e.key === "Enter" || e.key === " ") && !e.repeat) {
|
|
3704
|
+
e.preventDefault();
|
|
3705
|
+
onClick?.();
|
|
3706
|
+
}
|
|
3707
|
+
};
|
|
3708
|
+
const rootClassName = cn(
|
|
3709
|
+
"ods-avatar",
|
|
3710
|
+
`ods-avatar--${size}`,
|
|
3711
|
+
`ods-avatar--${shape}`,
|
|
3712
|
+
isClickable && "ods-avatar--clickable",
|
|
3713
|
+
className
|
|
3714
|
+
);
|
|
3715
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
3716
|
+
"div",
|
|
3717
|
+
{
|
|
3718
|
+
...rest,
|
|
3719
|
+
ref,
|
|
3720
|
+
className: rootClassName,
|
|
3721
|
+
role: isClickable ? "button" : "img",
|
|
3722
|
+
"aria-label": accessibleName,
|
|
3723
|
+
tabIndex: isClickable ? 0 : void 0,
|
|
3724
|
+
onClick,
|
|
3725
|
+
onKeyDown: isClickable ? handleKeyDown : void 0,
|
|
3726
|
+
"data-status": status,
|
|
3727
|
+
children: [
|
|
3728
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "ods-avatar__inner", "data-palette": paletteIdx, children: showImage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
3729
|
+
"img",
|
|
3730
|
+
{
|
|
3731
|
+
src,
|
|
3732
|
+
alt: "",
|
|
3733
|
+
className: "ods-avatar__image",
|
|
3734
|
+
loading: imgLoading,
|
|
3735
|
+
decoding: "async",
|
|
3736
|
+
referrerPolicy,
|
|
3737
|
+
onError: handleImgError,
|
|
3738
|
+
draggable: false
|
|
3739
|
+
}
|
|
3740
|
+
) : 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 ?? "?" }) }),
|
|
3741
|
+
status && // Decorative — the textual status is folded into the wrapper's
|
|
3742
|
+
// aria-label above. `aria-hidden` keeps AT from double-announcing.
|
|
3743
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
3744
|
+
"span",
|
|
3745
|
+
{
|
|
3746
|
+
className: cn("ods-avatar__status", `ods-avatar__status--${status}`),
|
|
3747
|
+
"aria-hidden": "true"
|
|
3748
|
+
}
|
|
3749
|
+
)
|
|
3750
|
+
]
|
|
3751
|
+
}
|
|
3752
|
+
);
|
|
3753
|
+
});
|
|
3754
|
+
Avatar.displayName = "Avatar";
|
|
3755
|
+
var AvatarStack = (0, import_react22.forwardRef)(
|
|
3756
|
+
function AvatarStack2({
|
|
3757
|
+
children,
|
|
3758
|
+
max,
|
|
3759
|
+
size = "md",
|
|
3760
|
+
renderOverflow,
|
|
3761
|
+
direction = "ltr",
|
|
3762
|
+
className,
|
|
3763
|
+
...rest
|
|
3764
|
+
}, ref) {
|
|
3765
|
+
const arr = Array.isArray(children) ? children : [children];
|
|
3766
|
+
const visible = max && arr.length > max ? arr.slice(0, max) : arr;
|
|
3767
|
+
const overflow = max && arr.length > max ? arr.length - max : 0;
|
|
3768
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
3780
3769
|
"div",
|
|
3781
3770
|
{
|
|
3771
|
+
...rest,
|
|
3772
|
+
ref,
|
|
3782
3773
|
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",
|
|
3774
|
+
"ods-avatar-stack",
|
|
3775
|
+
`ods-avatar-stack--${direction}`,
|
|
3789
3776
|
className
|
|
3790
3777
|
),
|
|
3791
|
-
style: consumerStyle,
|
|
3792
3778
|
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,
|
|
3779
|
+
visible,
|
|
3780
|
+
overflow > 0 && (renderOverflow ? renderOverflow(overflow) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
3781
|
+
"div",
|
|
3804
3782
|
{
|
|
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
|
-
}
|
|
3783
|
+
className: cn(
|
|
3784
|
+
"ods-avatar",
|
|
3785
|
+
`ods-avatar--${size}`,
|
|
3786
|
+
"ods-avatar--circle",
|
|
3787
|
+
"ods-avatar-stack__overflow"
|
|
3934
3788
|
),
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3789
|
+
role: "img",
|
|
3790
|
+
"aria-label": `${overflow} more`,
|
|
3791
|
+
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: [
|
|
3792
|
+
"+",
|
|
3793
|
+
overflow
|
|
3794
|
+
] }) })
|
|
3795
|
+
}
|
|
3796
|
+
))
|
|
3797
|
+
]
|
|
3798
|
+
}
|
|
3799
|
+
);
|
|
3800
|
+
}
|
|
3801
|
+
);
|
|
3802
|
+
AvatarStack.displayName = "AvatarStack";
|
|
3803
|
+
|
|
3804
|
+
// src/components/Card/Card.tsx
|
|
3805
|
+
var import_framer_motion4 = require("framer-motion");
|
|
3806
|
+
var import_react23 = require("react");
|
|
3807
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
3808
|
+
var Card = (0, import_react23.forwardRef)(function Card2({
|
|
3809
|
+
variant = "default",
|
|
3810
|
+
padding = "md",
|
|
3811
|
+
radius = "md",
|
|
3812
|
+
hoverable = false,
|
|
3813
|
+
disabled = false,
|
|
3814
|
+
loading = false,
|
|
3815
|
+
asChild = false,
|
|
3816
|
+
onClick,
|
|
3817
|
+
onKeyDown,
|
|
3818
|
+
className,
|
|
3819
|
+
children,
|
|
3820
|
+
...rest
|
|
3821
|
+
}, ref) {
|
|
3822
|
+
const reducedMotion = (0, import_framer_motion4.useReducedMotion)();
|
|
3823
|
+
const isInteractive = Boolean(onClick) && !disabled && !loading;
|
|
3824
|
+
const handleKeyDown = (e) => {
|
|
3825
|
+
onKeyDown?.(e);
|
|
3826
|
+
if (e.defaultPrevented) return;
|
|
3827
|
+
if (!isInteractive) return;
|
|
3828
|
+
if ((e.key === "Enter" || e.key === " ") && !e.repeat) {
|
|
3829
|
+
e.preventDefault();
|
|
3830
|
+
onClick?.(e);
|
|
3831
|
+
}
|
|
3832
|
+
};
|
|
3833
|
+
const rootClassName = cn(
|
|
3834
|
+
"ods-card",
|
|
3835
|
+
`ods-card--${variant}`,
|
|
3836
|
+
`ods-card--pad-${padding}`,
|
|
3837
|
+
`ods-card--radius-${radius}`,
|
|
3838
|
+
(hoverable || isInteractive) && !loading && !disabled && "ods-card--hoverable",
|
|
3839
|
+
isInteractive && "ods-card--clickable",
|
|
3840
|
+
disabled && "ods-card--disabled",
|
|
3841
|
+
loading && "ods-card--loading",
|
|
3842
|
+
className
|
|
3843
|
+
);
|
|
3844
|
+
if (asChild) {
|
|
3845
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
3846
|
+
Slot,
|
|
3847
|
+
{
|
|
3848
|
+
...rest,
|
|
3849
|
+
ref,
|
|
3850
|
+
className: rootClassName,
|
|
3851
|
+
onClick: isInteractive ? onClick : void 0,
|
|
3852
|
+
onKeyDown: isInteractive ? handleKeyDown : onKeyDown,
|
|
3853
|
+
"aria-disabled": disabled || void 0,
|
|
3854
|
+
children
|
|
3855
|
+
}
|
|
3856
|
+
);
|
|
3857
|
+
}
|
|
3858
|
+
if (loading) {
|
|
3859
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
3860
|
+
"div",
|
|
3861
|
+
{
|
|
3862
|
+
...rest,
|
|
3863
|
+
ref,
|
|
3864
|
+
className: rootClassName,
|
|
3865
|
+
"aria-busy": "true",
|
|
3866
|
+
"aria-label": "Loading",
|
|
3867
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "ods-card__skeleton", "data-ods-animate": "shimmer" })
|
|
3868
|
+
}
|
|
3869
|
+
);
|
|
3870
|
+
}
|
|
3871
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
3872
|
+
import_framer_motion4.motion.div,
|
|
3873
|
+
{
|
|
3874
|
+
...rest,
|
|
3875
|
+
ref,
|
|
3876
|
+
onClick: isInteractive ? onClick : void 0,
|
|
3877
|
+
onKeyDown: isInteractive ? handleKeyDown : onKeyDown,
|
|
3878
|
+
className: rootClassName,
|
|
3879
|
+
whileHover: (hoverable || isInteractive) && !reducedMotion ? { y: -2, transition: { duration: 0.15 } } : void 0,
|
|
3880
|
+
whileTap: isInteractive && !reducedMotion ? { scale: 0.99 } : void 0,
|
|
3881
|
+
role: isInteractive ? "button" : rest.role,
|
|
3882
|
+
tabIndex: isInteractive ? rest.tabIndex ?? 0 : rest.tabIndex,
|
|
3883
|
+
"aria-disabled": disabled || void 0,
|
|
3884
|
+
children
|
|
3885
|
+
}
|
|
3886
|
+
);
|
|
3887
|
+
});
|
|
3888
|
+
Card.displayName = "Card";
|
|
3889
|
+
var CardHeader = (0, import_react23.forwardRef)(
|
|
3890
|
+
function CardHeader2({ className, children, ...rest }, ref) {
|
|
3891
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { ...rest, ref, className: cn("ods-card__header", className), children });
|
|
3892
|
+
}
|
|
3893
|
+
);
|
|
3894
|
+
CardHeader.displayName = "Card.Header";
|
|
3895
|
+
var CardBody = (0, import_react23.forwardRef)(
|
|
3896
|
+
function CardBody2({ className, children, ...rest }, ref) {
|
|
3897
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { ...rest, ref, className: cn("ods-card__body", className), children });
|
|
3898
|
+
}
|
|
3899
|
+
);
|
|
3900
|
+
CardBody.displayName = "Card.Body";
|
|
3901
|
+
var CardFooter = (0, import_react23.forwardRef)(
|
|
3902
|
+
function CardFooter2({ className, children, ...rest }, ref) {
|
|
3903
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { ...rest, ref, className: cn("ods-card__footer", className), children });
|
|
3904
|
+
}
|
|
3905
|
+
);
|
|
3906
|
+
CardFooter.displayName = "Card.Footer";
|
|
3907
|
+
var CardTitle = (0, import_react23.forwardRef)(
|
|
3908
|
+
function CardTitle2({ as: Comp = "h3", className, children, ...rest }, ref) {
|
|
3909
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
3910
|
+
Comp,
|
|
3911
|
+
{
|
|
3912
|
+
...rest,
|
|
3913
|
+
ref,
|
|
3914
|
+
className: cn("ods-card__title", className),
|
|
3915
|
+
children
|
|
3916
|
+
}
|
|
3917
|
+
);
|
|
3918
|
+
}
|
|
3919
|
+
);
|
|
3920
|
+
CardTitle.displayName = "Card.Title";
|
|
3921
|
+
var CardDescription = (0, import_react23.forwardRef)(function CardDescription2({ className, children, ...rest }, ref) {
|
|
3922
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { ...rest, ref, className: cn("ods-card__description", className), children });
|
|
3923
|
+
});
|
|
3924
|
+
CardDescription.displayName = "Card.Description";
|
|
3925
|
+
Card.Header = CardHeader;
|
|
3926
|
+
Card.Body = CardBody;
|
|
3927
|
+
Card.Footer = CardFooter;
|
|
3928
|
+
Card.Title = CardTitle;
|
|
3929
|
+
Card.Description = CardDescription;
|
|
3930
|
+
|
|
3931
|
+
// src/components/BlogCard/BlogCard.tsx
|
|
3932
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
3933
|
+
var BlogCard = (0, import_react24.forwardRef)(
|
|
3934
|
+
function BlogCard2({
|
|
3935
|
+
cover,
|
|
3936
|
+
coverAspect = "16/9",
|
|
3937
|
+
category,
|
|
3938
|
+
tags,
|
|
3939
|
+
meta,
|
|
3940
|
+
readingTime,
|
|
3941
|
+
title,
|
|
3942
|
+
titleAs = "h3",
|
|
3943
|
+
description,
|
|
3944
|
+
author,
|
|
3945
|
+
footer,
|
|
3946
|
+
radius = "md",
|
|
3947
|
+
orientation = "vertical",
|
|
3948
|
+
href,
|
|
3949
|
+
onClick,
|
|
3950
|
+
id: providedId,
|
|
3951
|
+
className,
|
|
3952
|
+
...rest
|
|
3953
|
+
}, ref) {
|
|
3954
|
+
const reactId = (0, import_react24.useId)();
|
|
3955
|
+
const baseId = providedId ?? `ods-blog-card-${reactId}`;
|
|
3956
|
+
const titleId = `${baseId}-title`;
|
|
3957
|
+
const descId = description ? `${baseId}-desc` : void 0;
|
|
3958
|
+
const tagList = tags ?? (category ? [category] : []);
|
|
3959
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
3960
|
+
cover && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3961
|
+
"div",
|
|
3962
|
+
{
|
|
3963
|
+
className: cn(
|
|
3964
|
+
"ods-blog-card__cover",
|
|
3965
|
+
`ods-blog-card__cover--aspect-${coverAspect.replace("/", "-")}`
|
|
3966
|
+
),
|
|
3967
|
+
"aria-hidden": "true",
|
|
3968
|
+
children: cover
|
|
3969
|
+
}
|
|
3970
|
+
),
|
|
3971
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ods-blog-card__body", children: [
|
|
3972
|
+
(tagList.length > 0 || meta || readingTime) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ods-blog-card__meta", children: [
|
|
3973
|
+
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)) }),
|
|
3974
|
+
meta && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ods-blog-card__date", children: meta }),
|
|
3975
|
+
readingTime && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ods-blog-card__reading", children: readingTime })
|
|
3976
|
+
] }),
|
|
3977
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3978
|
+
Card.Title,
|
|
3979
|
+
{
|
|
3980
|
+
as: titleAs,
|
|
3981
|
+
id: titleId,
|
|
3982
|
+
className: "ods-blog-card__title",
|
|
3983
|
+
children: title
|
|
3984
|
+
}
|
|
3985
|
+
),
|
|
3986
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3987
|
+
Card.Description,
|
|
3988
|
+
{
|
|
3989
|
+
id: descId,
|
|
3990
|
+
className: "ods-blog-card__desc",
|
|
3991
|
+
children: description
|
|
3992
|
+
}
|
|
3993
|
+
),
|
|
3994
|
+
(author || footer) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ods-blog-card__footer", children: [
|
|
3995
|
+
author && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ods-blog-card__author", children: [
|
|
3996
|
+
author.avatar && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3997
|
+
Avatar,
|
|
3939
3998
|
{
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
"/",
|
|
3945
|
-
maxLength
|
|
3946
|
-
]
|
|
3999
|
+
size: "sm",
|
|
4000
|
+
src: author.avatar.src,
|
|
4001
|
+
initials: author.avatar.initials,
|
|
4002
|
+
alt: author.avatar.alt ?? (typeof author.name === "string" ? author.name : void 0)
|
|
3947
4003
|
}
|
|
3948
|
-
)
|
|
4004
|
+
),
|
|
4005
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "ods-blog-card__author-text", children: [
|
|
4006
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ods-blog-card__author-name", children: author.name }),
|
|
4007
|
+
author.byline && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ods-blog-card__author-byline", children: author.byline })
|
|
4008
|
+
] })
|
|
3949
4009
|
] }),
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
4010
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ods-blog-card__action", children: footer })
|
|
4011
|
+
] })
|
|
4012
|
+
] })
|
|
4013
|
+
] });
|
|
4014
|
+
if (href) {
|
|
4015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4016
|
+
Card,
|
|
4017
|
+
{
|
|
4018
|
+
asChild: true,
|
|
4019
|
+
radius,
|
|
4020
|
+
padding: "none",
|
|
4021
|
+
className: cn(
|
|
4022
|
+
"ods-blog-card",
|
|
4023
|
+
`ods-blog-card--${orientation}`,
|
|
4024
|
+
"ods-blog-card--interactive",
|
|
4025
|
+
className
|
|
3956
4026
|
),
|
|
3957
|
-
|
|
3958
|
-
|
|
4027
|
+
"aria-labelledby": titleId,
|
|
4028
|
+
"aria-describedby": descId,
|
|
4029
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4030
|
+
"a",
|
|
3959
4031
|
{
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
4032
|
+
...rest,
|
|
4033
|
+
ref,
|
|
4034
|
+
href,
|
|
4035
|
+
id: baseId,
|
|
4036
|
+
onClick,
|
|
4037
|
+
children: body
|
|
3964
4038
|
}
|
|
3965
|
-
)
|
|
3966
|
-
|
|
4039
|
+
)
|
|
4040
|
+
}
|
|
4041
|
+
);
|
|
4042
|
+
}
|
|
4043
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4044
|
+
Card,
|
|
4045
|
+
{
|
|
4046
|
+
...rest,
|
|
4047
|
+
ref,
|
|
4048
|
+
id: baseId,
|
|
4049
|
+
radius,
|
|
4050
|
+
padding: "none",
|
|
4051
|
+
onClick,
|
|
4052
|
+
className: cn(
|
|
4053
|
+
"ods-blog-card",
|
|
4054
|
+
`ods-blog-card--${orientation}`,
|
|
4055
|
+
onClick && "ods-blog-card--interactive",
|
|
4056
|
+
className
|
|
4057
|
+
),
|
|
4058
|
+
"aria-labelledby": titleId,
|
|
4059
|
+
"aria-describedby": descId,
|
|
4060
|
+
children: body
|
|
3967
4061
|
}
|
|
3968
4062
|
);
|
|
3969
4063
|
}
|
|
3970
4064
|
);
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
4065
|
+
BlogCard.displayName = "BlogCard";
|
|
4066
|
+
|
|
4067
|
+
// src/marketing/components/BlogGrid/BlogGrid.tsx
|
|
4068
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
4069
|
+
function BlogGrid({
|
|
4070
|
+
posts,
|
|
4071
|
+
columns = 3,
|
|
4072
|
+
viewAllHref,
|
|
4073
|
+
viewAllLabel = "View all posts \u2192",
|
|
4074
|
+
className,
|
|
4075
|
+
...rest
|
|
3975
4076
|
}) {
|
|
3976
|
-
return /* @__PURE__ */ (0, import_jsx_runtime13.
|
|
3977
|
-
"div",
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
4077
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { ...rest, className: cn("ods-mkt-blog", className), children: [
|
|
4078
|
+
/* @__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)(
|
|
4079
|
+
BlogCard,
|
|
4080
|
+
{
|
|
4081
|
+
title: post.title,
|
|
4082
|
+
description: post.excerpt,
|
|
4083
|
+
href: post.href,
|
|
4084
|
+
meta: post.date,
|
|
4085
|
+
readingTime: post.readTime,
|
|
4086
|
+
tags: post.tags,
|
|
4087
|
+
cover: post.cover,
|
|
4088
|
+
author: post.author
|
|
3986
4089
|
},
|
|
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
|
-
);
|
|
4090
|
+
post.id
|
|
4091
|
+
)) }),
|
|
4092
|
+
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 }) })
|
|
4093
|
+
] });
|
|
4013
4094
|
}
|
|
4014
4095
|
|
|
4015
4096
|
// src/marketing/components/ContactForm/ContactForm.tsx
|
|
4097
|
+
var import_react25 = require("react");
|
|
4016
4098
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
4017
4099
|
function ContactForm({
|
|
4018
4100
|
title = "Talk to us",
|
|
@@ -4158,7 +4240,7 @@ function ContactForm({
|
|
|
4158
4240
|
{
|
|
4159
4241
|
id: `${uid}-message`,
|
|
4160
4242
|
"aria-labelledby": `${uid}-message-label`,
|
|
4161
|
-
placeholder: "What are you trying to build?",
|
|
4243
|
+
placeholder: selectedTopic?.messagePlaceholder ?? "What are you trying to build?",
|
|
4162
4244
|
rows: 4,
|
|
4163
4245
|
value: values.message,
|
|
4164
4246
|
onChange: (e) => setValues((v) => ({ ...v, message: e.target.value })),
|
|
@@ -4973,7 +5055,24 @@ function MarketingHero({
|
|
|
4973
5055
|
}
|
|
4974
5056
|
|
|
4975
5057
|
// src/marketing/components/MarketingNav/MarketingNav.tsx
|
|
5058
|
+
var import_react29 = require("react");
|
|
4976
5059
|
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
5060
|
+
function BurgerGlyph({ open }) {
|
|
5061
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5062
|
+
"svg",
|
|
5063
|
+
{
|
|
5064
|
+
viewBox: "0 0 24 24",
|
|
5065
|
+
width: "20",
|
|
5066
|
+
height: "20",
|
|
5067
|
+
fill: "none",
|
|
5068
|
+
stroke: "currentColor",
|
|
5069
|
+
strokeWidth: "2",
|
|
5070
|
+
strokeLinecap: "round",
|
|
5071
|
+
"aria-hidden": "true",
|
|
5072
|
+
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" })
|
|
5073
|
+
}
|
|
5074
|
+
);
|
|
5075
|
+
}
|
|
4977
5076
|
function MarketingNav({
|
|
4978
5077
|
brand,
|
|
4979
5078
|
brandHref = "/",
|
|
@@ -4983,6 +5082,7 @@ function MarketingNav({
|
|
|
4983
5082
|
className,
|
|
4984
5083
|
...rest
|
|
4985
5084
|
}) {
|
|
5085
|
+
const [mobileOpen, setMobileOpen] = (0, import_react29.useState)(false);
|
|
4986
5086
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("header", { ...rest, className: cn("ods-mkt-nav", sticky && "ods-mkt-nav--sticky", className), children: [
|
|
4987
5087
|
/* @__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
5088
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(BrandMark, {}),
|
|
@@ -4998,7 +5098,35 @@ function MarketingNav({
|
|
|
4998
5098
|
},
|
|
4999
5099
|
link.href
|
|
5000
5100
|
)) }),
|
|
5001
|
-
actions && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "ods-mkt-nav__actions", children: actions })
|
|
5101
|
+
actions && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "ods-mkt-nav__actions", children: actions }),
|
|
5102
|
+
(links.length > 0 || actions) && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5103
|
+
"button",
|
|
5104
|
+
{
|
|
5105
|
+
type: "button",
|
|
5106
|
+
className: "ods-mkt-nav__toggle",
|
|
5107
|
+
"aria-expanded": mobileOpen,
|
|
5108
|
+
"aria-label": "Toggle menu",
|
|
5109
|
+
onClick: () => setMobileOpen((open) => !open),
|
|
5110
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(BurgerGlyph, { open: mobileOpen })
|
|
5111
|
+
}
|
|
5112
|
+
),
|
|
5113
|
+
mobileOpen && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("nav", { className: "ods-mkt-nav__mobile", "aria-label": "Main", children: [
|
|
5114
|
+
links.map((link) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
5115
|
+
"a",
|
|
5116
|
+
{
|
|
5117
|
+
href: link.href,
|
|
5118
|
+
className: cn(
|
|
5119
|
+
"ods-mkt-nav__mobile-link",
|
|
5120
|
+
link.active && "ods-mkt-nav__mobile-link--active"
|
|
5121
|
+
),
|
|
5122
|
+
"aria-current": link.active ? "page" : void 0,
|
|
5123
|
+
onClick: () => setMobileOpen(false),
|
|
5124
|
+
children: link.label
|
|
5125
|
+
},
|
|
5126
|
+
link.href
|
|
5127
|
+
)),
|
|
5128
|
+
actions && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "ods-mkt-nav__mobile-actions", children: actions })
|
|
5129
|
+
] })
|
|
5002
5130
|
] });
|
|
5003
5131
|
}
|
|
5004
5132
|
|
|
@@ -5122,10 +5250,10 @@ function PricingTiers({ tiers, note, className, ...rest }) {
|
|
|
5122
5250
|
var import_framer_motion7 = require("framer-motion");
|
|
5123
5251
|
|
|
5124
5252
|
// src/components/CountUp/CountUp.tsx
|
|
5125
|
-
var
|
|
5253
|
+
var import_react30 = require("react");
|
|
5126
5254
|
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
5127
5255
|
var easeOutCubic = (t) => 1 - Math.pow(1 - t, 3);
|
|
5128
|
-
var CountUp = (0,
|
|
5256
|
+
var CountUp = (0, import_react30.forwardRef)(
|
|
5129
5257
|
function CountUp2({
|
|
5130
5258
|
value,
|
|
5131
5259
|
from = 0,
|
|
@@ -5141,9 +5269,9 @@ var CountUp = (0, import_react29.forwardRef)(
|
|
|
5141
5269
|
className,
|
|
5142
5270
|
...rest
|
|
5143
5271
|
}, ref) {
|
|
5144
|
-
const [n, setN] = (0,
|
|
5145
|
-
const lastRendered = (0,
|
|
5146
|
-
(0,
|
|
5272
|
+
const [n, setN] = (0, import_react30.useState)(disableAnimation ? value : from);
|
|
5273
|
+
const lastRendered = (0, import_react30.useRef)(disableAnimation ? value : from);
|
|
5274
|
+
(0, import_react30.useEffect)(() => {
|
|
5147
5275
|
const reduced = typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
5148
5276
|
if (disableAnimation || reduced) {
|
|
5149
5277
|
setN(value);
|
|
@@ -5241,13 +5369,13 @@ function StatBand({ items, orientation = "column", className, ...rest }) {
|
|
|
5241
5369
|
|
|
5242
5370
|
// src/components/TestimonialCard/TestimonialCard.tsx
|
|
5243
5371
|
var import_icons9 = require("@octaviaflow/icons");
|
|
5244
|
-
var
|
|
5372
|
+
var import_react31 = require("react");
|
|
5245
5373
|
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
5246
5374
|
function isAuthorObject(v) {
|
|
5247
5375
|
return typeof v === "object" && v !== null && !("type" in v) && // exclude React elements
|
|
5248
5376
|
"name" in v;
|
|
5249
5377
|
}
|
|
5250
|
-
var TestimonialCard = (0,
|
|
5378
|
+
var TestimonialCard = (0, import_react31.forwardRef)(function TestimonialCard2({
|
|
5251
5379
|
quote,
|
|
5252
5380
|
author,
|
|
5253
5381
|
role: legacyRole,
|
|
@@ -5261,7 +5389,7 @@ var TestimonialCard = (0, import_react30.forwardRef)(function TestimonialCard2({
|
|
|
5261
5389
|
className,
|
|
5262
5390
|
...rest
|
|
5263
5391
|
}, ref) {
|
|
5264
|
-
const reactId = (0,
|
|
5392
|
+
const reactId = (0, import_react31.useId)();
|
|
5265
5393
|
const baseId = providedId ?? `ods-testimonial-${reactId}`;
|
|
5266
5394
|
const quoteId = `${baseId}-quote`;
|
|
5267
5395
|
const authorId = `${baseId}-author`;
|
|
@@ -5383,10 +5511,10 @@ function TestimonialStrip({
|
|
|
5383
5511
|
|
|
5384
5512
|
// src/marketing/components/WorkflowShowcase/WorkflowShowcase.tsx
|
|
5385
5513
|
var import_framer_motion9 = require("framer-motion");
|
|
5386
|
-
var
|
|
5514
|
+
var import_react34 = require("react");
|
|
5387
5515
|
|
|
5388
5516
|
// src/marketing/components/WorkflowShowcase/ShowcaseScene.tsx
|
|
5389
|
-
var
|
|
5517
|
+
var import_react32 = require("react");
|
|
5390
5518
|
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
5391
5519
|
function slots(n) {
|
|
5392
5520
|
return Array.from({ length: n }, (_, i) => 208 + (i - (n - 1) / 2) * 80);
|
|
@@ -5459,9 +5587,9 @@ function ShowcaseScene({
|
|
|
5459
5587
|
caption,
|
|
5460
5588
|
onCoreClick
|
|
5461
5589
|
}) {
|
|
5462
|
-
const [pulse, setPulse] = (0,
|
|
5463
|
-
const pulseTimer = (0,
|
|
5464
|
-
(0,
|
|
5590
|
+
const [pulse, setPulse] = (0, import_react32.useState)(false);
|
|
5591
|
+
const pulseTimer = (0, import_react32.useRef)(null);
|
|
5592
|
+
(0, import_react32.useEffect)(
|
|
5465
5593
|
() => () => {
|
|
5466
5594
|
if (pulseTimer.current) clearTimeout(pulseTimer.current);
|
|
5467
5595
|
},
|
|
@@ -5692,7 +5820,7 @@ function ShowcaseScene({
|
|
|
5692
5820
|
|
|
5693
5821
|
// src/marketing/components/WorkflowShowcase/ShowcaseSignup.tsx
|
|
5694
5822
|
var import_framer_motion8 = require("framer-motion");
|
|
5695
|
-
var
|
|
5823
|
+
var import_react33 = require("react");
|
|
5696
5824
|
var import_react_aria5 = require("react-aria");
|
|
5697
5825
|
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
5698
5826
|
var OVERLAY_MOTION = {
|
|
@@ -5712,9 +5840,9 @@ function ShowcaseSignup({
|
|
|
5712
5840
|
onboardingHref = "#"
|
|
5713
5841
|
}) {
|
|
5714
5842
|
const reducedMotion = (0, import_framer_motion8.useReducedMotion)();
|
|
5715
|
-
const titleId = (0,
|
|
5716
|
-
const subtitleId = (0,
|
|
5717
|
-
const [values, setValues] = (0,
|
|
5843
|
+
const titleId = (0, import_react33.useId)();
|
|
5844
|
+
const subtitleId = (0, import_react33.useId)();
|
|
5845
|
+
const [values, setValues] = (0, import_react33.useState)({
|
|
5718
5846
|
name: "",
|
|
5719
5847
|
email: "",
|
|
5720
5848
|
company: "",
|
|
@@ -5932,53 +6060,53 @@ function WorkflowShowcase({
|
|
|
5932
6060
|
}) {
|
|
5933
6061
|
const reducedMotion = (0, import_framer_motion9.useReducedMotion)();
|
|
5934
6062
|
const rotationActive = rotatePrompts && !defaultPrompt && examples.length > 0;
|
|
5935
|
-
const [prompt, setPrompt] = (0,
|
|
6063
|
+
const [prompt, setPrompt] = (0, import_react34.useState)(
|
|
5936
6064
|
defaultPrompt || (rotationActive ? examples[0]?.prompt ?? "" : "")
|
|
5937
6065
|
);
|
|
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,
|
|
6066
|
+
const [engagedWithPrompt, setEngagedWithPrompt] = (0, import_react34.useState)(false);
|
|
6067
|
+
const [promptHovered, setPromptHovered] = (0, import_react34.useState)(false);
|
|
6068
|
+
const [promptFocused, setPromptFocused] = (0, import_react34.useState)(false);
|
|
6069
|
+
const rotateIdx = (0, import_react34.useRef)(0);
|
|
6070
|
+
const [selected, setSelected] = (0, import_react34.useState)([]);
|
|
6071
|
+
const [phase, setPhase] = (0, import_react34.useState)("idle");
|
|
6072
|
+
const [shown, setShown] = (0, import_react34.useState)(0);
|
|
6073
|
+
const [status, setStatus] = (0, import_react34.useState)("");
|
|
6074
|
+
const [pickerOpen, setPickerOpen] = (0, import_react34.useState)(false);
|
|
6075
|
+
const [schedIdx, setSchedIdx] = (0, import_react34.useState)(0);
|
|
6076
|
+
const [swap, setSwap] = (0, import_react34.useState)(null);
|
|
6077
|
+
const [signupError, setSignupError] = (0, import_react34.useState)(null);
|
|
6078
|
+
const signupReturnPhase = (0, import_react34.useRef)("done");
|
|
6079
|
+
const cardRef = (0, import_react34.useRef)(null);
|
|
6080
|
+
const timers = (0, import_react34.useRef)([]);
|
|
6081
|
+
const clearTimers = (0, import_react34.useCallback)(() => {
|
|
5954
6082
|
for (const t of timers.current) clearTimeout(t);
|
|
5955
6083
|
timers.current = [];
|
|
5956
6084
|
}, []);
|
|
5957
|
-
(0,
|
|
6085
|
+
(0, import_react34.useEffect)(() => clearTimers, [clearTimers]);
|
|
5958
6086
|
const tempo = reducedMotion ? 0.35 : 1;
|
|
5959
|
-
const at = (0,
|
|
6087
|
+
const at = (0, import_react34.useCallback)(
|
|
5960
6088
|
(ms, fn) => {
|
|
5961
6089
|
timers.current.push(setTimeout(fn, ms * tempo));
|
|
5962
6090
|
},
|
|
5963
6091
|
[tempo]
|
|
5964
6092
|
);
|
|
5965
|
-
const firstPhase = (0,
|
|
5966
|
-
(0,
|
|
6093
|
+
const firstPhase = (0, import_react34.useRef)(true);
|
|
6094
|
+
(0, import_react34.useEffect)(() => {
|
|
5967
6095
|
if (firstPhase.current) {
|
|
5968
6096
|
firstPhase.current = false;
|
|
5969
6097
|
return;
|
|
5970
6098
|
}
|
|
5971
6099
|
onPhaseChange?.(phase);
|
|
5972
6100
|
}, [phase, onPhaseChange]);
|
|
5973
|
-
const phaseRef = (0,
|
|
6101
|
+
const phaseRef = (0, import_react34.useRef)(phase);
|
|
5974
6102
|
phaseRef.current = phase;
|
|
5975
|
-
const byName = (0,
|
|
5976
|
-
const detected = (0,
|
|
5977
|
-
const union = (0,
|
|
6103
|
+
const byName = (0, import_react34.useMemo)(() => new Map(connectors.map((c) => [c.name, c])), [connectors]);
|
|
6104
|
+
const detected = (0, import_react34.useMemo)(() => detectConnectors(prompt, connectors), [prompt, connectors]);
|
|
6105
|
+
const union = (0, import_react34.useMemo)(() => [.../* @__PURE__ */ new Set([...selected, ...detected])], [selected, detected]);
|
|
5978
6106
|
const settled = SETTLED_PHASES.includes(phase);
|
|
5979
6107
|
const engaged = phase !== "idle";
|
|
5980
6108
|
const buildingNow = phase === "analyzing" || phase === "building";
|
|
5981
|
-
const plan = (0,
|
|
6109
|
+
const plan = (0, import_react34.useMemo)(() => {
|
|
5982
6110
|
if (!selected.length) return EMPTY_PLAN;
|
|
5983
6111
|
return resolvePlan(selected, [], connectors);
|
|
5984
6112
|
}, [selected, connectors]);
|
|
@@ -5987,10 +6115,10 @@ function WorkflowShowcase({
|
|
|
5987
6115
|
const manualSchedule = schedules[schedIdx];
|
|
5988
6116
|
const scheduleShown = inferredSchedule ?? (manualSchedule === "AUTO" ? "HOURLY" : manualSchedule);
|
|
5989
6117
|
const triggers = WORKFLOW_SHOWCASE_TRIGGERS;
|
|
5990
|
-
const [triggerIdx, setTriggerIdx] = (0,
|
|
6118
|
+
const [triggerIdx, setTriggerIdx] = (0, import_react34.useState)(0);
|
|
5991
6119
|
const manualTrigger = triggers[triggerIdx];
|
|
5992
6120
|
const cadenceShown = manualTrigger === "SCHEDULE" ? scheduleShown : manualTrigger;
|
|
5993
|
-
(0,
|
|
6121
|
+
(0, import_react34.useEffect)(() => {
|
|
5994
6122
|
if (!rotationActive || engagedWithPrompt || promptHovered || promptFocused || phase !== "idle") {
|
|
5995
6123
|
return;
|
|
5996
6124
|
}
|
|
@@ -6000,7 +6128,7 @@ function WorkflowShowcase({
|
|
|
6000
6128
|
}, 4200);
|
|
6001
6129
|
return () => clearInterval(timer);
|
|
6002
6130
|
}, [rotationActive, engagedWithPrompt, promptHovered, promptFocused, phase, examples]);
|
|
6003
|
-
const startBuild = (0,
|
|
6131
|
+
const startBuild = (0, import_react34.useCallback)(
|
|
6004
6132
|
(text, baseSelected) => {
|
|
6005
6133
|
if (phaseRef.current === "analyzing" || phaseRef.current === "building") return;
|
|
6006
6134
|
phaseRef.current = "analyzing";
|
|
@@ -6037,7 +6165,7 @@ function WorkflowShowcase({
|
|
|
6037
6165
|
},
|
|
6038
6166
|
[clearTimers, connectors, onBuild, scheduleShown, manualTrigger, at]
|
|
6039
6167
|
);
|
|
6040
|
-
const resetToIdle = (0,
|
|
6168
|
+
const resetToIdle = (0, import_react34.useCallback)(() => {
|
|
6041
6169
|
clearTimers();
|
|
6042
6170
|
phaseRef.current = "idle";
|
|
6043
6171
|
setPhase("idle");
|