@burdenoff/website-sdk 2026.925.2 → 2026.926.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/contact.js +8 -0
- package/dist/components/contact.js.map +1 -1
- package/dist/components/contact.mjs +8 -0
- package/dist/components/contact.mjs.map +1 -1
- package/dist/components/explore.d.mts +1 -1
- package/dist/components/explore.d.ts +1 -1
- package/dist/components/explore.js +1101 -518
- package/dist/components/explore.js.map +1 -1
- package/dist/components/explore.mjs +1103 -521
- package/dist/components/explore.mjs.map +1 -1
- package/dist/components/newsletter.js +8 -0
- package/dist/components/newsletter.js.map +1 -1
- package/dist/components/newsletter.mjs +8 -0
- package/dist/components/newsletter.mjs.map +1 -1
- package/dist/components/partners.js +11 -2
- package/dist/components/partners.js.map +1 -1
- package/dist/components/partners.mjs +11 -2
- package/dist/components/partners.mjs.map +1 -1
- package/dist/components/resource-links.js +8 -0
- package/dist/components/resource-links.js.map +1 -1
- package/dist/components/resource-links.mjs +8 -0
- package/dist/components/resource-links.mjs.map +1 -1
- package/dist/components/social-links.js +8 -0
- package/dist/components/social-links.js.map +1 -1
- package/dist/components/social-links.mjs +8 -0
- package/dist/components/social-links.mjs.map +1 -1
- package/dist/components/waitlist.js +8 -0
- package/dist/components/waitlist.js.map +1 -1
- package/dist/components/waitlist.mjs +8 -0
- package/dist/components/waitlist.mjs.map +1 -1
- package/dist/content/index.d.mts +1 -1
- package/dist/content/index.d.ts +1 -1
- package/dist/content/index.js +11 -2
- package/dist/content/index.js.map +1 -1
- package/dist/content/index.mjs +11 -2
- package/dist/content/index.mjs.map +1 -1
- package/dist/{explore-C0RFTKAi.d.ts → explore-Cam_ElSJ.d.ts} +70 -12
- package/dist/{explore-DzOf7n4m.d.mts → explore-hTQm-_SF.d.mts} +70 -12
- package/dist/hooks/index.js +51 -13
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +51 -13
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/{index-BMWQNZDX.d.mts → index-gm3pBCJT.d.mts} +8 -2
- package/dist/{index-BqHF-G-S.d.ts → index-ySbOLSD5.d.ts} +8 -2
- package/dist/index.d.mts +32 -11
- package/dist/index.d.ts +32 -11
- package/dist/index.js +901 -267
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +892 -269
- package/dist/index.mjs.map +1 -1
- package/dist/product/index.d.mts +16 -1
- package/dist/product/index.d.ts +16 -1
- package/dist/product/index.js +61 -17
- package/dist/product/index.js.map +1 -1
- package/dist/product/index.mjs +61 -18
- package/dist/product/index.mjs.map +1 -1
- package/dist/store/index.js +11 -2
- package/dist/store/index.js.map +1 -1
- package/dist/store/index.mjs +11 -2
- package/dist/store/index.mjs.map +1 -1
- package/dist/utils/index.d.mts +41 -1
- package/dist/utils/index.d.ts +41 -1
- package/dist/utils/index.js +42 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +35 -1
- package/dist/utils/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19,6 +19,7 @@ var zod$1 = require('@hookform/resolvers/zod');
|
|
|
19
19
|
var reactHookForm = require('react-hook-form');
|
|
20
20
|
var zod = require('zod');
|
|
21
21
|
var DropdownMenu = require('@radix-ui/react-dropdown-menu');
|
|
22
|
+
var reactDom = require('react-dom');
|
|
22
23
|
|
|
23
24
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
24
25
|
|
|
@@ -374,6 +375,40 @@ function useWebSDKConfig() {
|
|
|
374
375
|
const client = useWebSDK();
|
|
375
376
|
return client.getConfig();
|
|
376
377
|
}
|
|
378
|
+
|
|
379
|
+
// src/utils/product-slug.ts
|
|
380
|
+
var PRODUCT_SLUG_RENAMES = Object.freeze(
|
|
381
|
+
[Object.freeze({ legacy: "botlit", current: "botmanor" })]
|
|
382
|
+
);
|
|
383
|
+
var PRODUCT_SLUG_ALIASES = Object.freeze(
|
|
384
|
+
Object.fromEntries(PRODUCT_SLUG_RENAMES.map((r) => [r.legacy, r.current]))
|
|
385
|
+
);
|
|
386
|
+
var PRODUCT_SLUG_EMIT = Object.freeze({ productSlug: "legacy" });
|
|
387
|
+
function findRename(slug) {
|
|
388
|
+
const wanted = slug.toLowerCase();
|
|
389
|
+
return PRODUCT_SLUG_RENAMES.find(
|
|
390
|
+
(r) => r.legacy === wanted || r.current === wanted
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
function normalizeProductSlug(slug) {
|
|
394
|
+
if (slug == null) return slug;
|
|
395
|
+
return findRename(slug)?.current ?? slug;
|
|
396
|
+
}
|
|
397
|
+
function legacyProductSlug(slug) {
|
|
398
|
+
return findRename(slug)?.legacy ?? slug;
|
|
399
|
+
}
|
|
400
|
+
function productSlugVariants(slug) {
|
|
401
|
+
return [
|
|
402
|
+
.../* @__PURE__ */ new Set([slug, normalizeProductSlug(slug), legacyProductSlug(slug)])
|
|
403
|
+
];
|
|
404
|
+
}
|
|
405
|
+
function isSameProductSlug(a, b) {
|
|
406
|
+
if (a == null || b == null) return a === b;
|
|
407
|
+
return a === b || normalizeProductSlug(a) === normalizeProductSlug(b);
|
|
408
|
+
}
|
|
409
|
+
function emitProductSlug(slug) {
|
|
410
|
+
return PRODUCT_SLUG_EMIT.productSlug === "current" ? normalizeProductSlug(slug) : legacyProductSlug(slug);
|
|
411
|
+
}
|
|
377
412
|
var PRODUCT_FIELDS_BASE = `
|
|
378
413
|
id
|
|
379
414
|
name
|
|
@@ -421,6 +456,35 @@ var ProductContext = React.createContext({
|
|
|
421
456
|
refetch: () => {
|
|
422
457
|
}
|
|
423
458
|
});
|
|
459
|
+
async function queryPublicProduct(client, slug) {
|
|
460
|
+
const result = await client.query(
|
|
461
|
+
PUBLIC_PRODUCT_QUERY,
|
|
462
|
+
{ slug }
|
|
463
|
+
);
|
|
464
|
+
const schemaMissingResourceLinks = result.errors?.some(
|
|
465
|
+
(e) => /Cannot query field ["']?resourceLinks["']?/i.test(e?.message ?? "")
|
|
466
|
+
);
|
|
467
|
+
if (!schemaMissingResourceLinks) return result;
|
|
468
|
+
return client.query(
|
|
469
|
+
PUBLIC_PRODUCT_QUERY_FALLBACK,
|
|
470
|
+
{ slug }
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
async function fetchPublicProduct(client, slug) {
|
|
474
|
+
for (const candidate of productSlugVariants(slug)) {
|
|
475
|
+
const result = await queryPublicProduct(client, candidate);
|
|
476
|
+
if (result.errors?.length) {
|
|
477
|
+
return {
|
|
478
|
+
product: null,
|
|
479
|
+
error: result.errors[0]?.message ?? "Unknown error"
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
if (result.data?.publicProduct) {
|
|
483
|
+
return { product: result.data.publicProduct, error: null };
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return { product: null, error: null };
|
|
487
|
+
}
|
|
424
488
|
function ProductProvider({ children, fallback }) {
|
|
425
489
|
const client = useWebSDK();
|
|
426
490
|
const config = useWebSDKConfig();
|
|
@@ -437,23 +501,11 @@ function ProductProvider({ children, fallback }) {
|
|
|
437
501
|
setLoading(true);
|
|
438
502
|
setError(null);
|
|
439
503
|
try {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
)
|
|
444
|
-
|
|
445
|
-
(e) => /Cannot query field ["']?resourceLinks["']?/i.test(e?.message ?? "")
|
|
446
|
-
);
|
|
447
|
-
if (schemaMissingResourceLinks) {
|
|
448
|
-
result = await client.query(
|
|
449
|
-
PUBLIC_PRODUCT_QUERY_FALLBACK,
|
|
450
|
-
{ slug: config.productSlug }
|
|
451
|
-
);
|
|
452
|
-
}
|
|
453
|
-
if (result.errors?.length) {
|
|
454
|
-
setError(result.errors[0]?.message ?? "Unknown error");
|
|
455
|
-
} else if (result.data?.publicProduct) {
|
|
456
|
-
setProduct(result.data.publicProduct);
|
|
504
|
+
const outcome = await fetchPublicProduct(client, config.productSlug);
|
|
505
|
+
if (outcome.error) {
|
|
506
|
+
setError(outcome.error);
|
|
507
|
+
} else if (outcome.product) {
|
|
508
|
+
setProduct(outcome.product);
|
|
457
509
|
}
|
|
458
510
|
} catch (err) {
|
|
459
511
|
setError(err instanceof Error ? err.message : "Failed to fetch product");
|
|
@@ -1138,13 +1190,14 @@ function Markdown({
|
|
|
1138
1190
|
children,
|
|
1139
1191
|
className,
|
|
1140
1192
|
inline,
|
|
1141
|
-
components
|
|
1193
|
+
components,
|
|
1194
|
+
rehypePlugins
|
|
1142
1195
|
}) {
|
|
1143
1196
|
const content = /* @__PURE__ */ jsxRuntime.jsx(
|
|
1144
1197
|
ReactMarkdown__default.default,
|
|
1145
1198
|
{
|
|
1146
1199
|
remarkPlugins: [remarkGfm__default.default],
|
|
1147
|
-
rehypePlugins: [rehypeSanitize__default.default],
|
|
1200
|
+
rehypePlugins: [rehypeSanitize__default.default, ...rehypePlugins ?? []],
|
|
1148
1201
|
components: { ...defaultComponents, ...components },
|
|
1149
1202
|
...inline ? { disallowedElements: ["p"], unwrapDisallowed: true } : {},
|
|
1150
1203
|
children
|
|
@@ -6165,6 +6218,13 @@ var EN = {
|
|
|
6165
6218
|
readAloud: "Read aloud",
|
|
6166
6219
|
stopReading: "Stop reading",
|
|
6167
6220
|
answerTable: "Table",
|
|
6221
|
+
productVideo: "Product video",
|
|
6222
|
+
productVideoTitle: "{product} product video",
|
|
6223
|
+
playVideo: "Play {title}",
|
|
6224
|
+
closeVideo: "Close video",
|
|
6225
|
+
enterFullScreen: "Full screen",
|
|
6226
|
+
exitFullScreen: "Exit full screen",
|
|
6227
|
+
videoUnavailable: "This video can't be played right now.",
|
|
6168
6228
|
groundedIn: "What this answer is based on",
|
|
6169
6229
|
sourceCountOne: "1 source",
|
|
6170
6230
|
sourceCountMany: "{count} sources",
|
|
@@ -6266,6 +6326,13 @@ var ZH = {
|
|
|
6266
6326
|
readAloud: "\u6717\u8BFB",
|
|
6267
6327
|
stopReading: "\u505C\u6B62\u6717\u8BFB",
|
|
6268
6328
|
answerTable: "\u8868\u683C",
|
|
6329
|
+
productVideo: "\u4EA7\u54C1\u89C6\u9891",
|
|
6330
|
+
productVideoTitle: "{product} \u4EA7\u54C1\u89C6\u9891",
|
|
6331
|
+
playVideo: "\u64AD\u653E {title}",
|
|
6332
|
+
closeVideo: "\u5173\u95ED\u89C6\u9891",
|
|
6333
|
+
enterFullScreen: "\u5168\u5C4F",
|
|
6334
|
+
exitFullScreen: "\u9000\u51FA\u5168\u5C4F",
|
|
6335
|
+
videoUnavailable: "\u6682\u65F6\u65E0\u6CD5\u64AD\u653E\u6B64\u89C6\u9891\u3002",
|
|
6269
6336
|
groundedIn: "\u8FD9\u4E2A\u56DE\u7B54\u7684\u4F9D\u636E",
|
|
6270
6337
|
sourceCountOne: "1 \u4E2A\u6765\u6E90",
|
|
6271
6338
|
sourceCountMany: "{count} \u4E2A\u6765\u6E90",
|
|
@@ -6363,6 +6430,13 @@ var HI = {
|
|
|
6363
6430
|
readAloud: "\u091C\u093C\u094B\u0930 \u0938\u0947 \u092A\u0922\u093C\u0947\u0902",
|
|
6364
6431
|
stopReading: "\u092A\u0922\u093C\u0928\u093E \u092C\u0902\u0926 \u0915\u0930\u0947\u0902",
|
|
6365
6432
|
answerTable: "\u0924\u093E\u0932\u093F\u0915\u093E",
|
|
6433
|
+
productVideo: "\u0909\u0924\u094D\u092A\u093E\u0926 \u0935\u0940\u0921\u093F\u092F\u094B",
|
|
6434
|
+
productVideoTitle: "{product} \u0909\u0924\u094D\u092A\u093E\u0926 \u0935\u0940\u0921\u093F\u092F\u094B",
|
|
6435
|
+
playVideo: "{title} \u091A\u0932\u093E\u090F\u0901",
|
|
6436
|
+
closeVideo: "\u0935\u0940\u0921\u093F\u092F\u094B \u092C\u0902\u0926 \u0915\u0930\u0947\u0902",
|
|
6437
|
+
enterFullScreen: "\u092A\u0942\u0930\u094D\u0923 \u0938\u094D\u0915\u094D\u0930\u0940\u0928",
|
|
6438
|
+
exitFullScreen: "\u092A\u0942\u0930\u094D\u0923 \u0938\u094D\u0915\u094D\u0930\u0940\u0928 \u0938\u0947 \u092C\u093E\u0939\u0930 \u0928\u093F\u0915\u0932\u0947\u0902",
|
|
6439
|
+
videoUnavailable: "\u092F\u0939 \u0935\u0940\u0921\u093F\u092F\u094B \u0905\u092D\u0940 \u0928\u0939\u0940\u0902 \u091A\u0932 \u0938\u0915\u0924\u093E\u0964",
|
|
6366
6440
|
groundedIn: "\u092F\u0939 \u0909\u0924\u094D\u0924\u0930 \u0915\u093F\u0938 \u092A\u0930 \u0906\u0927\u093E\u0930\u093F\u0924 \u0939\u0948",
|
|
6367
6441
|
sourceCountOne: "1 \u0938\u094D\u0930\u094B\u0924",
|
|
6368
6442
|
sourceCountMany: "{count} \u0938\u094D\u0930\u094B\u0924",
|
|
@@ -6464,6 +6538,13 @@ var ES = {
|
|
|
6464
6538
|
readAloud: "Leer en voz alta",
|
|
6465
6539
|
stopReading: "Dejar de leer",
|
|
6466
6540
|
answerTable: "Tabla",
|
|
6541
|
+
productVideo: "V\xEDdeo del producto",
|
|
6542
|
+
productVideoTitle: "V\xEDdeo de {product}",
|
|
6543
|
+
playVideo: "Reproducir {title}",
|
|
6544
|
+
closeVideo: "Cerrar v\xEDdeo",
|
|
6545
|
+
enterFullScreen: "Pantalla completa",
|
|
6546
|
+
exitFullScreen: "Salir de pantalla completa",
|
|
6547
|
+
videoUnavailable: "Ahora mismo no se puede reproducir este v\xEDdeo.",
|
|
6467
6548
|
groundedIn: "En qu\xE9 se basa esta respuesta",
|
|
6468
6549
|
sourceCountOne: "1 fuente",
|
|
6469
6550
|
sourceCountMany: "{count} fuentes",
|
|
@@ -6565,6 +6646,13 @@ var AR = {
|
|
|
6565
6646
|
readAloud: "\u0627\u0642\u0631\u0623 \u0628\u0635\u0648\u062A \u0639\u0627\u0644\u064D",
|
|
6566
6647
|
stopReading: "\u0625\u064A\u0642\u0627\u0641 \u0627\u0644\u0642\u0631\u0627\u0621\u0629",
|
|
6567
6648
|
answerTable: "\u062C\u062F\u0648\u0644",
|
|
6649
|
+
productVideo: "\u0641\u064A\u062F\u064A\u0648 \u0627\u0644\u0645\u0646\u062A\u062C",
|
|
6650
|
+
productVideoTitle: "\u0641\u064A\u062F\u064A\u0648 {product}",
|
|
6651
|
+
playVideo: "\u062A\u0634\u063A\u064A\u0644 {title}",
|
|
6652
|
+
closeVideo: "\u0625\u063A\u0644\u0627\u0642 \u0627\u0644\u0641\u064A\u062F\u064A\u0648",
|
|
6653
|
+
enterFullScreen: "\u0645\u0644\u0621 \u0627\u0644\u0634\u0627\u0634\u0629",
|
|
6654
|
+
exitFullScreen: "\u0627\u0644\u062E\u0631\u0648\u062C \u0645\u0646 \u0645\u0644\u0621 \u0627\u0644\u0634\u0627\u0634\u0629",
|
|
6655
|
+
videoUnavailable: "\u062A\u0639\u0630\u0651\u0631 \u062A\u0634\u063A\u064A\u0644 \u0647\u0630\u0627 \u0627\u0644\u0641\u064A\u062F\u064A\u0648 \u0627\u0644\u0622\u0646.",
|
|
6568
6656
|
groundedIn: "\u0639\u0644\u0649 \u0645\u0627\u0630\u0627 \u062A\u0633\u062A\u0646\u062F \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629",
|
|
6569
6657
|
sourceCountOne: "\u0645\u0635\u062F\u0631 \u0648\u0627\u062D\u062F",
|
|
6570
6658
|
sourceCountMany: "{count} \u0645\u0635\u0627\u062F\u0631",
|
|
@@ -6666,6 +6754,13 @@ var TA = {
|
|
|
6666
6754
|
readAloud: "\u0B9A\u0BA4\u0BCD\u0BA4\u0BAE\u0BBE\u0B95\u0BAA\u0BCD \u0BAA\u0B9F\u0BBF",
|
|
6667
6755
|
stopReading: "\u0BAA\u0B9F\u0BBF\u0BAA\u0BCD\u0BAA\u0BA4\u0BC8 \u0BA8\u0BBF\u0BB1\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1",
|
|
6668
6756
|
answerTable: "\u0B85\u0B9F\u0BCD\u0B9F\u0BB5\u0BA3\u0BC8",
|
|
6757
|
+
productVideo: "\u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1 \u0BB5\u0BC0\u0B9F\u0BBF\u0BAF\u0BCB",
|
|
6758
|
+
productVideoTitle: "{product} \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1 \u0BB5\u0BC0\u0B9F\u0BBF\u0BAF\u0BCB",
|
|
6759
|
+
playVideo: "{title} \u0B87\u0BAF\u0B95\u0BCD\u0B95\u0BC1",
|
|
6760
|
+
closeVideo: "\u0BB5\u0BC0\u0B9F\u0BBF\u0BAF\u0BCB\u0BB5\u0BC8 \u0BAE\u0BC2\u0B9F\u0BC1",
|
|
6761
|
+
enterFullScreen: "\u0BAE\u0BC1\u0BB4\u0BC1\u0BA4\u0BCD \u0BA4\u0BBF\u0BB0\u0BC8",
|
|
6762
|
+
exitFullScreen: "\u0BAE\u0BC1\u0BB4\u0BC1\u0BA4\u0BCD \u0BA4\u0BBF\u0BB0\u0BC8\u0BAF\u0BBF\u0BB2\u0BBF\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1 \u0BB5\u0BC6\u0BB3\u0BBF\u0BAF\u0BC7\u0BB1\u0BC1",
|
|
6763
|
+
videoUnavailable: "\u0B87\u0BA8\u0BCD\u0BA4 \u0BB5\u0BC0\u0B9F\u0BBF\u0BAF\u0BCB\u0BB5\u0BC8 \u0B87\u0BAA\u0BCD\u0BAA\u0BCB\u0BA4\u0BC1 \u0B87\u0BAF\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8.",
|
|
6669
6764
|
groundedIn: "\u0B87\u0BA8\u0BCD\u0BA4\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0B8E\u0BA4\u0BC8 \u0B85\u0B9F\u0BBF\u0BAA\u0BCD\u0BAA\u0B9F\u0BC8\u0BAF\u0BBE\u0B95\u0B95\u0BCD \u0B95\u0BCA\u0BA3\u0BCD\u0B9F\u0BA4\u0BC1",
|
|
6670
6765
|
sourceCountOne: "1 \u0BAE\u0BC2\u0BB2\u0BAE\u0BCD",
|
|
6671
6766
|
sourceCountMany: "{count} \u0BAE\u0BC2\u0BB2\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
|
|
@@ -6955,7 +7050,14 @@ function answerStrings(locale) {
|
|
|
6955
7050
|
...chrome,
|
|
6956
7051
|
answerTable: explore.answerTable,
|
|
6957
7052
|
conceptIllustration: explore.conceptIllustration,
|
|
6958
|
-
opensInNewTab: explore.opensInNewTab
|
|
7053
|
+
opensInNewTab: explore.opensInNewTab,
|
|
7054
|
+
productVideo: explore.productVideo,
|
|
7055
|
+
productVideoTitle: explore.productVideoTitle,
|
|
7056
|
+
playVideo: explore.playVideo,
|
|
7057
|
+
closeVideo: explore.closeVideo,
|
|
7058
|
+
enterFullScreen: explore.enterFullScreen,
|
|
7059
|
+
exitFullScreen: explore.exitFullScreen,
|
|
7060
|
+
videoUnavailable: explore.videoUnavailable
|
|
6959
7061
|
};
|
|
6960
7062
|
}
|
|
6961
7063
|
var DATE_TAGS = {
|
|
@@ -7023,6 +7125,253 @@ function answerSourceHost(url) {
|
|
|
7023
7125
|
return "";
|
|
7024
7126
|
}
|
|
7025
7127
|
}
|
|
7128
|
+
function fullscreenSupport() {
|
|
7129
|
+
if (typeof document === "undefined") return null;
|
|
7130
|
+
if (document.fullscreenEnabled && typeof document.documentElement.requestFullscreen === "function") {
|
|
7131
|
+
return "element";
|
|
7132
|
+
}
|
|
7133
|
+
if (typeof HTMLVideoElement !== "undefined" && "webkitEnterFullscreen" in HTMLVideoElement.prototype) {
|
|
7134
|
+
return "video";
|
|
7135
|
+
}
|
|
7136
|
+
return null;
|
|
7137
|
+
}
|
|
7138
|
+
function ignoreRejection(result) {
|
|
7139
|
+
result?.catch(() => void 0);
|
|
7140
|
+
}
|
|
7141
|
+
var VIDEO_DIALOG_CSS = `
|
|
7142
|
+
.boff-explore-video-panel:fullscreen {
|
|
7143
|
+
display: flex;
|
|
7144
|
+
flex-direction: column;
|
|
7145
|
+
gap: 0.75rem;
|
|
7146
|
+
padding: 1rem;
|
|
7147
|
+
background-color: hsl(var(--background));
|
|
7148
|
+
color: hsl(var(--foreground));
|
|
7149
|
+
}
|
|
7150
|
+
.boff-explore-video-panel:fullscreen .boff-explore-video-frame {
|
|
7151
|
+
display: flex;
|
|
7152
|
+
flex: 1 1 auto;
|
|
7153
|
+
min-height: 0;
|
|
7154
|
+
align-items: center;
|
|
7155
|
+
justify-content: center;
|
|
7156
|
+
border: 0;
|
|
7157
|
+
border-radius: 0;
|
|
7158
|
+
box-shadow: none;
|
|
7159
|
+
background-color: hsl(var(--background));
|
|
7160
|
+
}
|
|
7161
|
+
.boff-explore-video-panel:fullscreen video {
|
|
7162
|
+
width: 100%;
|
|
7163
|
+
height: 100%;
|
|
7164
|
+
max-height: none;
|
|
7165
|
+
}
|
|
7166
|
+
`;
|
|
7167
|
+
var DIALOG_BUTTON = "inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-full border border-border bg-card text-foreground transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
|
|
7168
|
+
function ExploreVideoDialog({
|
|
7169
|
+
videoUrl,
|
|
7170
|
+
posterUrl,
|
|
7171
|
+
title,
|
|
7172
|
+
strings: T,
|
|
7173
|
+
dir,
|
|
7174
|
+
onClose
|
|
7175
|
+
}) {
|
|
7176
|
+
const dialogRef = React.useRef(null);
|
|
7177
|
+
const panelRef = React.useRef(null);
|
|
7178
|
+
const videoRef = React.useRef(null);
|
|
7179
|
+
const closeRef = React.useRef(null);
|
|
7180
|
+
const nativeModalRef = React.useRef(false);
|
|
7181
|
+
const titleId = React.useId();
|
|
7182
|
+
const [support] = React.useState(fullscreenSupport);
|
|
7183
|
+
const [fullscreen, setFullscreen] = React.useState(false);
|
|
7184
|
+
const [failed, setFailed] = React.useState(false);
|
|
7185
|
+
React.useEffect(() => {
|
|
7186
|
+
const dialog = dialogRef.current;
|
|
7187
|
+
if (!dialog) return;
|
|
7188
|
+
if (typeof dialog.showModal === "function") {
|
|
7189
|
+
if (!dialog.open) dialog.showModal();
|
|
7190
|
+
nativeModalRef.current = true;
|
|
7191
|
+
} else {
|
|
7192
|
+
dialog.setAttribute("open", "");
|
|
7193
|
+
nativeModalRef.current = false;
|
|
7194
|
+
}
|
|
7195
|
+
closeRef.current?.focus();
|
|
7196
|
+
ignoreRejection(videoRef.current?.play());
|
|
7197
|
+
return () => {
|
|
7198
|
+
if (dialog.open && typeof dialog.close === "function") dialog.close();
|
|
7199
|
+
};
|
|
7200
|
+
}, []);
|
|
7201
|
+
React.useEffect(() => {
|
|
7202
|
+
const sync = () => {
|
|
7203
|
+
const current = document.fullscreenElement;
|
|
7204
|
+
setFullscreen(
|
|
7205
|
+
current !== null && dialogRef.current?.contains(current) === true
|
|
7206
|
+
);
|
|
7207
|
+
};
|
|
7208
|
+
const enter = () => setFullscreen(true);
|
|
7209
|
+
const leave = () => setFullscreen(false);
|
|
7210
|
+
const video = videoRef.current;
|
|
7211
|
+
document.addEventListener("fullscreenchange", sync);
|
|
7212
|
+
video?.addEventListener("webkitbeginfullscreen", enter);
|
|
7213
|
+
video?.addEventListener("webkitendfullscreen", leave);
|
|
7214
|
+
return () => {
|
|
7215
|
+
document.removeEventListener("fullscreenchange", sync);
|
|
7216
|
+
video?.removeEventListener("webkitbeginfullscreen", enter);
|
|
7217
|
+
video?.removeEventListener("webkitendfullscreen", leave);
|
|
7218
|
+
};
|
|
7219
|
+
}, [failed]);
|
|
7220
|
+
const leaveFullscreen = React.useCallback(() => {
|
|
7221
|
+
const current = document.fullscreenElement;
|
|
7222
|
+
if (current && dialogRef.current?.contains(current) && typeof document.exitFullscreen === "function") {
|
|
7223
|
+
ignoreRejection(document.exitFullscreen());
|
|
7224
|
+
}
|
|
7225
|
+
const video = videoRef.current;
|
|
7226
|
+
if (video?.webkitDisplayingFullscreen) video.webkitExitFullscreen?.();
|
|
7227
|
+
}, []);
|
|
7228
|
+
const requestClose = React.useCallback(() => {
|
|
7229
|
+
videoRef.current?.pause();
|
|
7230
|
+
leaveFullscreen();
|
|
7231
|
+
onClose();
|
|
7232
|
+
}, [leaveFullscreen, onClose]);
|
|
7233
|
+
const toggleFullscreen = React.useCallback(() => {
|
|
7234
|
+
if (fullscreen) {
|
|
7235
|
+
leaveFullscreen();
|
|
7236
|
+
return;
|
|
7237
|
+
}
|
|
7238
|
+
if (support === "element") {
|
|
7239
|
+
const panel = panelRef.current;
|
|
7240
|
+
if (panel) ignoreRejection(panel.requestFullscreen());
|
|
7241
|
+
return;
|
|
7242
|
+
}
|
|
7243
|
+
const video = videoRef.current;
|
|
7244
|
+
video?.webkitEnterFullscreen?.();
|
|
7245
|
+
}, [fullscreen, leaveFullscreen, support]);
|
|
7246
|
+
const handleClose = React.useCallback(
|
|
7247
|
+
(event) => {
|
|
7248
|
+
if (event.currentTarget.open) return;
|
|
7249
|
+
requestClose();
|
|
7250
|
+
},
|
|
7251
|
+
[requestClose]
|
|
7252
|
+
);
|
|
7253
|
+
const handleKeyDown = React.useCallback(
|
|
7254
|
+
(event) => {
|
|
7255
|
+
if (event.key === "Escape" && !nativeModalRef.current) {
|
|
7256
|
+
event.preventDefault();
|
|
7257
|
+
requestClose();
|
|
7258
|
+
}
|
|
7259
|
+
},
|
|
7260
|
+
[requestClose]
|
|
7261
|
+
);
|
|
7262
|
+
const handleStageClick = React.useCallback(
|
|
7263
|
+
(event) => {
|
|
7264
|
+
if (event.target === event.currentTarget) requestClose();
|
|
7265
|
+
},
|
|
7266
|
+
[requestClose]
|
|
7267
|
+
);
|
|
7268
|
+
if (typeof document === "undefined") return null;
|
|
7269
|
+
const fullscreenLabel = fullscreen ? T.exitFullScreen : T.enterFullScreen;
|
|
7270
|
+
return reactDom.createPortal(
|
|
7271
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7272
|
+
"dialog",
|
|
7273
|
+
{
|
|
7274
|
+
ref: dialogRef,
|
|
7275
|
+
"data-boff-explore": "video-dialog",
|
|
7276
|
+
"aria-labelledby": titleId,
|
|
7277
|
+
dir,
|
|
7278
|
+
onClose: handleClose,
|
|
7279
|
+
onKeyDown: handleKeyDown,
|
|
7280
|
+
className: "fixed inset-0 z-50 m-0 h-full max-h-none w-full max-w-none overflow-y-auto overscroll-contain border-0 bg-background/95 p-0 text-foreground backdrop-blur-sm",
|
|
7281
|
+
children: [
|
|
7282
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: VIDEO_DIALOG_CSS } }),
|
|
7283
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7284
|
+
"div",
|
|
7285
|
+
{
|
|
7286
|
+
onClick: handleStageClick,
|
|
7287
|
+
className: "flex min-h-full items-center justify-center p-4 sm:p-6",
|
|
7288
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7289
|
+
"div",
|
|
7290
|
+
{
|
|
7291
|
+
ref: panelRef,
|
|
7292
|
+
className: "boff-explore-video-panel flex w-full min-w-0 max-w-[960px] flex-col gap-3",
|
|
7293
|
+
children: [
|
|
7294
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
7295
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7296
|
+
"h2",
|
|
7297
|
+
{
|
|
7298
|
+
id: titleId,
|
|
7299
|
+
className: "min-w-0 flex-1 truncate text-sm font-semibold text-foreground sm:text-base",
|
|
7300
|
+
children: title
|
|
7301
|
+
}
|
|
7302
|
+
),
|
|
7303
|
+
support !== null && !failed ? (
|
|
7304
|
+
// A plain button whose name says what pressing it does NOW, and no
|
|
7305
|
+
// `aria-pressed`: a toggle button's name must not change with its state, or it
|
|
7306
|
+
// announces "Exit full screen, pressed" — two answers to one question.
|
|
7307
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7308
|
+
"button",
|
|
7309
|
+
{
|
|
7310
|
+
type: "button",
|
|
7311
|
+
"data-boff-explore": "video-fullscreen",
|
|
7312
|
+
"aria-label": fullscreenLabel,
|
|
7313
|
+
title: fullscreenLabel,
|
|
7314
|
+
onClick: toggleFullscreen,
|
|
7315
|
+
className: DIALOG_BUTTON,
|
|
7316
|
+
children: fullscreen ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minimize, { "aria-hidden": "true", className: "h-5 w-5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize, { "aria-hidden": "true", className: "h-5 w-5" })
|
|
7317
|
+
}
|
|
7318
|
+
)
|
|
7319
|
+
) : null,
|
|
7320
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7321
|
+
"button",
|
|
7322
|
+
{
|
|
7323
|
+
ref: closeRef,
|
|
7324
|
+
type: "button",
|
|
7325
|
+
"data-boff-explore": "video-close",
|
|
7326
|
+
"aria-label": T.closeVideo,
|
|
7327
|
+
title: T.closeVideo,
|
|
7328
|
+
onClick: requestClose,
|
|
7329
|
+
className: DIALOG_BUTTON,
|
|
7330
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { "aria-hidden": "true", className: "h-5 w-5" })
|
|
7331
|
+
}
|
|
7332
|
+
)
|
|
7333
|
+
] }),
|
|
7334
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "boff-explore-video-frame overflow-hidden rounded-xl border border-border bg-muted shadow-lg", children: failed ? (
|
|
7335
|
+
// A black box with a spinning control tells the visitor nothing; this says
|
|
7336
|
+
// what happened, in their language.
|
|
7337
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7338
|
+
"div",
|
|
7339
|
+
{
|
|
7340
|
+
role: "alert",
|
|
7341
|
+
className: "flex aspect-video w-full flex-col items-center justify-center gap-2 p-6 text-center text-sm text-muted-foreground",
|
|
7342
|
+
children: [
|
|
7343
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.VideoOff, { "aria-hidden": "true", className: "h-6 w-6" }),
|
|
7344
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: T.videoUnavailable })
|
|
7345
|
+
]
|
|
7346
|
+
}
|
|
7347
|
+
)
|
|
7348
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
7349
|
+
"video",
|
|
7350
|
+
{
|
|
7351
|
+
ref: videoRef,
|
|
7352
|
+
"data-boff-explore": "video-player",
|
|
7353
|
+
src: videoUrl,
|
|
7354
|
+
poster: posterUrl,
|
|
7355
|
+
controls: true,
|
|
7356
|
+
controlsList: support === "element" ? "nofullscreen" : void 0,
|
|
7357
|
+
playsInline: true,
|
|
7358
|
+
autoPlay: true,
|
|
7359
|
+
preload: "metadata",
|
|
7360
|
+
onError: () => setFailed(true),
|
|
7361
|
+
className: "block max-h-[80vh] w-full bg-muted object-contain"
|
|
7362
|
+
}
|
|
7363
|
+
) })
|
|
7364
|
+
]
|
|
7365
|
+
}
|
|
7366
|
+
)
|
|
7367
|
+
}
|
|
7368
|
+
)
|
|
7369
|
+
]
|
|
7370
|
+
}
|
|
7371
|
+
),
|
|
7372
|
+
document.body
|
|
7373
|
+
);
|
|
7374
|
+
}
|
|
7026
7375
|
var EXPLORE_ANSWER_CSS = `
|
|
7027
7376
|
/* Nothing inside an answer may widen the page. Model output carries long URLs, code and
|
|
7028
7377
|
tables \u2014 each of those overflows a phone by default, and one overflowing child makes the
|
|
@@ -7055,6 +7404,14 @@ var EXPLORE_ANSWER_CSS = `
|
|
|
7055
7404
|
max-width: 100%;
|
|
7056
7405
|
height: auto;
|
|
7057
7406
|
}
|
|
7407
|
+
/* A product-video poster fills the card's reserved 16:9 frame and is cropped to it. The
|
|
7408
|
+
blanket \`img { height: auto }\` above \u2014 and ProseStyles' own \u2014 outrank a height utility,
|
|
7409
|
+
and would size it by its own aspect ratio instead, leaving a band of the frame showing
|
|
7410
|
+
whenever a poster is not exactly 16:9. */
|
|
7411
|
+
.boff-explore-body .boff-explore-video-poster {
|
|
7412
|
+
height: 100%;
|
|
7413
|
+
max-width: none;
|
|
7414
|
+
}
|
|
7058
7415
|
|
|
7059
7416
|
/* ---- Comparison and pricing tables ----------------------------------------------------
|
|
7060
7417
|
The harness emits a comparison, and a set of plans, as a GFM table whose FIRST column is
|
|
@@ -7185,28 +7542,81 @@ function inlineImageOrigins(products) {
|
|
|
7185
7542
|
}
|
|
7186
7543
|
return origins;
|
|
7187
7544
|
}
|
|
7188
|
-
|
|
7189
|
-
|
|
7545
|
+
var VIDEO_FILE_PATH = /\.(?:mp4|webm|m4v|mov|vtt)$/i;
|
|
7546
|
+
function catalogUrlOf(value, origins) {
|
|
7547
|
+
if (typeof value !== "string" || value === "") return null;
|
|
7190
7548
|
let url;
|
|
7191
7549
|
try {
|
|
7192
|
-
url = new URL(
|
|
7550
|
+
url = new URL(value);
|
|
7551
|
+
} catch {
|
|
7552
|
+
return null;
|
|
7553
|
+
}
|
|
7554
|
+
if (url.protocol !== "https:" || url.username || url.password) return null;
|
|
7555
|
+
return origins.has(url.origin) ? url : null;
|
|
7556
|
+
}
|
|
7557
|
+
function isInlineImageAllowed(src, origins) {
|
|
7558
|
+
const url = catalogUrlOf(src, origins);
|
|
7559
|
+
return url !== null && !VIDEO_FILE_PATH.test(url.pathname);
|
|
7560
|
+
}
|
|
7561
|
+
var INLINE_VIDEO_PATH = /\.(?:mp4|webm)$/i;
|
|
7562
|
+
function isInlineVideoAllowed(href, origins) {
|
|
7563
|
+
const url = catalogUrlOf(href, origins);
|
|
7564
|
+
return url !== null && INLINE_VIDEO_PATH.test(url.pathname);
|
|
7565
|
+
}
|
|
7566
|
+
function apexOriginOf(url) {
|
|
7567
|
+
const apex = url.hostname.replace(/^www\./, "");
|
|
7568
|
+
const port = url.port ? `:${url.port}` : "";
|
|
7569
|
+
return `https://${apex}${port}`;
|
|
7570
|
+
}
|
|
7571
|
+
function productSlugsByOrigin(products) {
|
|
7572
|
+
const slugs = /* @__PURE__ */ new Map();
|
|
7573
|
+
for (const product of products) {
|
|
7574
|
+
let url;
|
|
7575
|
+
try {
|
|
7576
|
+
url = new URL(product.website);
|
|
7577
|
+
} catch {
|
|
7578
|
+
continue;
|
|
7579
|
+
}
|
|
7580
|
+
if (url.protocol !== "https:") continue;
|
|
7581
|
+
const key = apexOriginOf(url);
|
|
7582
|
+
if (!slugs.has(key)) slugs.set(key, product.slug);
|
|
7583
|
+
}
|
|
7584
|
+
return slugs;
|
|
7585
|
+
}
|
|
7586
|
+
function videoProductOf(href, slugs) {
|
|
7587
|
+
const url = new URL(href);
|
|
7588
|
+
return slugs.get(apexOriginOf(url)) ?? url.hostname.replace(/^www\./, "");
|
|
7589
|
+
}
|
|
7590
|
+
function isVideoFileTarget(href) {
|
|
7591
|
+
if (typeof href !== "string") return false;
|
|
7592
|
+
try {
|
|
7593
|
+
return VIDEO_FILE_PATH.test(
|
|
7594
|
+
new URL(href, "https://answer.invalid").pathname
|
|
7595
|
+
);
|
|
7193
7596
|
} catch {
|
|
7194
7597
|
return false;
|
|
7195
7598
|
}
|
|
7196
|
-
if (url.protocol !== "https:" || url.username || url.password) return false;
|
|
7197
|
-
return origins.has(url.origin);
|
|
7198
7599
|
}
|
|
7199
7600
|
var CODE_FENCE = /^\s*(?:```|~~~)/;
|
|
7200
7601
|
var TABLE_ROW_LINE = /^\s{0,3}\|/;
|
|
7201
7602
|
var TABLE_DELIMITER_ROW = /^\s{0,3}\|[\s:|-]*-[\s:|-]*$/;
|
|
7603
|
+
var LINKED_IMAGE = /\[!\[([^[\]]*)\]\([^)\s]*(?:\s+"[^"]*")?\)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g;
|
|
7604
|
+
var IMAGE = /!\[[^[\]]*\]\([^)\s]*(?:\s+"[^"]*")?\)/g;
|
|
7605
|
+
var LINK = /\[([^[\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g;
|
|
7202
7606
|
function readableLine(raw, mode) {
|
|
7203
7607
|
let line = raw;
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7208
|
-
|
|
7209
|
-
|
|
7608
|
+
if (line.includes("](")) {
|
|
7609
|
+
line = line.replace(LINKED_IMAGE, (_match, alt, href) => {
|
|
7610
|
+
if (mode === "speech") return "";
|
|
7611
|
+
return alt.trim() === "" ? href : `${alt.trim()} (${href})`;
|
|
7612
|
+
});
|
|
7613
|
+
line = line.replace(IMAGE, "");
|
|
7614
|
+
line = mode === "speech" ? (
|
|
7615
|
+
// A voice reading "h-t-t-p-s colon slash slash…" mid-sentence is noise, and the
|
|
7616
|
+
// prompt asks for two to five links in every answer. The label IS the words.
|
|
7617
|
+
line.replace(LINK, "$1")
|
|
7618
|
+
) : line.replace(LINK, "$1 ($2)");
|
|
7619
|
+
}
|
|
7210
7620
|
line = mode === "speech" ? line.replace(/<(https?:\/\/[^>\s]+)>/g, "") : line.replace(/<(https?:\/\/[^>\s]+)>/g, "$1");
|
|
7211
7621
|
line = line.replace(/^\s{0,3}#{1,6}\s+/, "");
|
|
7212
7622
|
line = line.replace(/^\s{0,3}>\s?/, "");
|
|
@@ -7297,6 +7707,21 @@ function answerSpeechText(markdown) {
|
|
|
7297
7707
|
var AnswerScopeContext = React.createContext(null);
|
|
7298
7708
|
var InsideLinkContext = React.createContext(false);
|
|
7299
7709
|
function AnswerLink(props) {
|
|
7710
|
+
const scope = React.useContext(AnswerScopeContext);
|
|
7711
|
+
const role = videoRoleOf(props.node);
|
|
7712
|
+
if (role !== void 0 && scope !== null) {
|
|
7713
|
+
const video = role === "card" && scope.enabled ? productVideoOf(props.node) : null;
|
|
7714
|
+
if (video === null) return null;
|
|
7715
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7716
|
+
InlineVideoCard,
|
|
7717
|
+
{
|
|
7718
|
+
href: video.href,
|
|
7719
|
+
poster: video.poster,
|
|
7720
|
+
alt: video.alt,
|
|
7721
|
+
scope
|
|
7722
|
+
}
|
|
7723
|
+
);
|
|
7724
|
+
}
|
|
7300
7725
|
return /* @__PURE__ */ jsxRuntime.jsx(InsideLinkContext.Provider, { value: true, children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownLink, { ...props }) });
|
|
7301
7726
|
}
|
|
7302
7727
|
var INLINE_IMAGE_FRAME = "relative inline-block max-w-full overflow-hidden rounded-xl border border-border bg-muted align-top shadow-sm";
|
|
@@ -7408,16 +7833,173 @@ function AnswerTableRow({
|
|
|
7408
7833
|
});
|
|
7409
7834
|
return /* @__PURE__ */ jsxRuntime.jsx("tr", { ...props, children: cells });
|
|
7410
7835
|
}
|
|
7836
|
+
function linkedImageOf(node) {
|
|
7837
|
+
if (node?.tagName !== "a") return null;
|
|
7838
|
+
const content = (node.children ?? []).filter(
|
|
7839
|
+
(child) => child.tagName !== void 0 || (child.value ?? "").trim() !== ""
|
|
7840
|
+
);
|
|
7841
|
+
const image = content.length === 1 ? content[0] : void 0;
|
|
7842
|
+
if (image?.tagName !== "img") return null;
|
|
7843
|
+
const alt = image.properties?.alt;
|
|
7844
|
+
return {
|
|
7845
|
+
href: node.properties?.href,
|
|
7846
|
+
src: image.properties?.src,
|
|
7847
|
+
alt: typeof alt === "string" ? alt.trim() : ""
|
|
7848
|
+
};
|
|
7849
|
+
}
|
|
7850
|
+
function isCardableVideo(embed, origins) {
|
|
7851
|
+
if (!isInlineVideoAllowed(embed.href, origins) || !isInlineImageAllowed(embed.src, origins)) {
|
|
7852
|
+
return false;
|
|
7853
|
+
}
|
|
7854
|
+
return apexOriginOf(new URL(embed.href)) === apexOriginOf(new URL(embed.src));
|
|
7855
|
+
}
|
|
7856
|
+
var NO_VIDEO_CONTAINERS = /* @__PURE__ */ new Set(["li", "table"]);
|
|
7857
|
+
function rehypeProductVideo(options) {
|
|
7858
|
+
return (tree) => {
|
|
7859
|
+
let claimed = false;
|
|
7860
|
+
const visit = (node, parent, contained) => {
|
|
7861
|
+
const embed = linkedImageOf(node);
|
|
7862
|
+
if (embed !== null && isVideoFileTarget(embed.href)) {
|
|
7863
|
+
const card = !claimed && !contained && parent?.tagName === "p" && isCardableVideo(embed, options.origins);
|
|
7864
|
+
if (card) claimed = true;
|
|
7865
|
+
const data = typeof node.data === "object" ? node.data : null;
|
|
7866
|
+
node.data = { ...data, boffVideo: card ? "card" : "drop" };
|
|
7867
|
+
return;
|
|
7868
|
+
}
|
|
7869
|
+
const inside = contained || node.tagName !== void 0 && NO_VIDEO_CONTAINERS.has(node.tagName);
|
|
7870
|
+
for (const child of node.children ?? []) visit(child, node, inside);
|
|
7871
|
+
};
|
|
7872
|
+
visit(tree, null, false);
|
|
7873
|
+
};
|
|
7874
|
+
}
|
|
7875
|
+
function videoRoleOf(node) {
|
|
7876
|
+
const data = node?.data;
|
|
7877
|
+
if (typeof data !== "object" || data === null || !("boffVideo" in data)) {
|
|
7878
|
+
return void 0;
|
|
7879
|
+
}
|
|
7880
|
+
return data.boffVideo === "card" || data.boffVideo === "drop" ? data.boffVideo : void 0;
|
|
7881
|
+
}
|
|
7882
|
+
function productVideoOf(node) {
|
|
7883
|
+
const embed = linkedImageOf(node);
|
|
7884
|
+
if (embed === null || typeof embed.href !== "string" || typeof embed.src !== "string") {
|
|
7885
|
+
return null;
|
|
7886
|
+
}
|
|
7887
|
+
return { href: embed.href, poster: embed.src, alt: embed.alt };
|
|
7888
|
+
}
|
|
7889
|
+
var CANONICAL_VIDEO_ALT = /^(.+?)\s+product video$/i;
|
|
7890
|
+
function videoTitleOf(alt, T) {
|
|
7891
|
+
const product = CANONICAL_VIDEO_ALT.exec(alt)?.[1]?.trim();
|
|
7892
|
+
if (product) return fill(T.productVideoTitle, { product });
|
|
7893
|
+
return alt === "" ? T.productVideo : alt;
|
|
7894
|
+
}
|
|
7895
|
+
var INLINE_VIDEO_FRAME = "group relative block aspect-video w-full max-w-md overflow-hidden rounded-xl border border-border bg-muted shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
|
|
7896
|
+
function InlineVideoCard({
|
|
7897
|
+
href,
|
|
7898
|
+
poster,
|
|
7899
|
+
alt,
|
|
7900
|
+
scope
|
|
7901
|
+
}) {
|
|
7902
|
+
const { strings: T, failed, onFailed, productSlugs } = scope;
|
|
7903
|
+
const [dialogDir, setDialogDir] = React.useState(null);
|
|
7904
|
+
const buttonRef = React.useRef(null);
|
|
7905
|
+
const returnFocusRef = React.useRef(false);
|
|
7906
|
+
const open = dialogDir !== null;
|
|
7907
|
+
React.useEffect(() => {
|
|
7908
|
+
if (open || !returnFocusRef.current) return;
|
|
7909
|
+
returnFocusRef.current = false;
|
|
7910
|
+
const button = buttonRef.current;
|
|
7911
|
+
if (button?.isConnected) button.focus();
|
|
7912
|
+
}, [open]);
|
|
7913
|
+
const openPlayer = React.useCallback((event) => {
|
|
7914
|
+
const dir = event.currentTarget.closest("[dir]")?.getAttribute("dir");
|
|
7915
|
+
returnFocusRef.current = true;
|
|
7916
|
+
setDialogDir(dir === "rtl" ? "rtl" : "ltr");
|
|
7917
|
+
}, []);
|
|
7918
|
+
const closePlayer = React.useCallback(() => setDialogDir(null), []);
|
|
7919
|
+
const name = videoTitleOf(alt, T);
|
|
7920
|
+
const posterFailed = failed.has(poster);
|
|
7921
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7922
|
+
"span",
|
|
7923
|
+
{
|
|
7924
|
+
"data-boff-explore": "inline-video",
|
|
7925
|
+
"data-product": videoProductOf(href, productSlugs),
|
|
7926
|
+
className: "my-3 block",
|
|
7927
|
+
children: [
|
|
7928
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7929
|
+
"button",
|
|
7930
|
+
{
|
|
7931
|
+
ref: buttonRef,
|
|
7932
|
+
type: "button",
|
|
7933
|
+
"aria-haspopup": "dialog",
|
|
7934
|
+
"aria-label": fill(T.playVideo, { title: name }),
|
|
7935
|
+
onClick: openPlayer,
|
|
7936
|
+
className: INLINE_VIDEO_FRAME,
|
|
7937
|
+
children: [
|
|
7938
|
+
posterFailed ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
7939
|
+
"span",
|
|
7940
|
+
{
|
|
7941
|
+
"aria-hidden": "true",
|
|
7942
|
+
className: "absolute inset-0 flex items-center justify-center bg-muted text-muted-foreground",
|
|
7943
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Film, { className: "h-10 w-10" })
|
|
7944
|
+
}
|
|
7945
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
7946
|
+
"img",
|
|
7947
|
+
{
|
|
7948
|
+
src: poster,
|
|
7949
|
+
alt: "",
|
|
7950
|
+
loading: "lazy",
|
|
7951
|
+
decoding: "async",
|
|
7952
|
+
onError: () => onFailed(poster),
|
|
7953
|
+
className: "boff-explore-video-poster absolute inset-0 h-full w-full object-cover"
|
|
7954
|
+
}
|
|
7955
|
+
),
|
|
7956
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7957
|
+
"span",
|
|
7958
|
+
{
|
|
7959
|
+
"aria-hidden": "true",
|
|
7960
|
+
className: "pointer-events-none absolute inset-0 flex items-center justify-center",
|
|
7961
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-14 w-14 items-center justify-center rounded-full border border-border bg-background/90 text-foreground shadow-md transition-transform group-hover:scale-105", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { className: "h-6 w-6 fill-current" }) })
|
|
7962
|
+
}
|
|
7963
|
+
),
|
|
7964
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7965
|
+
"span",
|
|
7966
|
+
{
|
|
7967
|
+
"aria-hidden": "true",
|
|
7968
|
+
className: "pointer-events-none absolute start-2 top-2 rounded-full border border-border bg-background/90 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-foreground shadow-sm",
|
|
7969
|
+
children: T.productVideo
|
|
7970
|
+
}
|
|
7971
|
+
)
|
|
7972
|
+
]
|
|
7973
|
+
}
|
|
7974
|
+
),
|
|
7975
|
+
open ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
7976
|
+
ExploreVideoDialog,
|
|
7977
|
+
{
|
|
7978
|
+
videoUrl: href,
|
|
7979
|
+
posterUrl: poster,
|
|
7980
|
+
title: name,
|
|
7981
|
+
strings: T,
|
|
7982
|
+
dir: dialogDir,
|
|
7983
|
+
onClose: closePlayer
|
|
7984
|
+
}
|
|
7985
|
+
) : null
|
|
7986
|
+
]
|
|
7987
|
+
}
|
|
7988
|
+
);
|
|
7989
|
+
}
|
|
7411
7990
|
var ANSWER_MARKDOWN_COMPONENTS = {
|
|
7412
7991
|
a: AnswerLink,
|
|
7413
7992
|
img: InlineConceptImage,
|
|
7414
7993
|
table: AnswerTable,
|
|
7415
7994
|
tr: AnswerTableRow
|
|
7416
7995
|
};
|
|
7996
|
+
var NO_PRODUCT_SLUGS = /* @__PURE__ */ new Map();
|
|
7417
7997
|
function ExploreAnswerBody({
|
|
7418
7998
|
children,
|
|
7419
7999
|
strings,
|
|
7420
8000
|
imageOrigins,
|
|
8001
|
+
videoOrigins = imageOrigins,
|
|
8002
|
+
productSlugs = NO_PRODUCT_SLUGS,
|
|
7421
8003
|
enabled = true,
|
|
7422
8004
|
components,
|
|
7423
8005
|
className
|
|
@@ -7433,16 +8015,21 @@ function ExploreAnswerBody({
|
|
|
7433
8015
|
strings,
|
|
7434
8016
|
enabled,
|
|
7435
8017
|
origins: imageOrigins,
|
|
8018
|
+
productSlugs,
|
|
7436
8019
|
failed,
|
|
7437
8020
|
onFailed
|
|
7438
8021
|
}),
|
|
7439
|
-
[strings, enabled, imageOrigins, failed, onFailed]
|
|
8022
|
+
[strings, enabled, imageOrigins, productSlugs, failed, onFailed]
|
|
8023
|
+
);
|
|
8024
|
+
const rehypePlugins = React.useMemo(
|
|
8025
|
+
() => [[rehypeProductVideo, { origins: videoOrigins }]],
|
|
8026
|
+
[videoOrigins]
|
|
7440
8027
|
);
|
|
7441
8028
|
const overrides = React.useMemo(
|
|
7442
8029
|
() => components ? { ...ANSWER_MARKDOWN_COMPONENTS, ...components } : ANSWER_MARKDOWN_COMPONENTS,
|
|
7443
8030
|
[components]
|
|
7444
8031
|
);
|
|
7445
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("boff-prose boff-explore-body min-w-0", className), children: /* @__PURE__ */ jsxRuntime.jsx(AnswerScopeContext.Provider, { value: scope, children: /* @__PURE__ */ jsxRuntime.jsx(Markdown, { components: overrides, children }) }) });
|
|
8032
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("boff-prose boff-explore-body min-w-0", className), children: /* @__PURE__ */ jsxRuntime.jsx(AnswerScopeContext.Provider, { value: scope, children: /* @__PURE__ */ jsxRuntime.jsx(Markdown, { components: overrides, rehypePlugins, children }) }) });
|
|
7446
8033
|
}
|
|
7447
8034
|
var PROSE_CSS = `
|
|
7448
8035
|
.boff-prose {
|
|
@@ -7620,32 +8207,216 @@ var PROSE_CSS = `
|
|
|
7620
8207
|
function ProseStyles() {
|
|
7621
8208
|
return /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: PROSE_CSS } });
|
|
7622
8209
|
}
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
var
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
7643
|
-
}
|
|
7644
|
-
|
|
7645
|
-
|
|
7646
|
-
|
|
7647
|
-
|
|
7648
|
-
|
|
8210
|
+
|
|
8211
|
+
// src/data/products.ts
|
|
8212
|
+
var ECOSYSTEM_PRODUCTS = [
|
|
8213
|
+
{
|
|
8214
|
+
slug: "workspaces",
|
|
8215
|
+
name: "Workspaces",
|
|
8216
|
+
websiteUrl: "https://burdenoff.com"
|
|
8217
|
+
},
|
|
8218
|
+
{
|
|
8219
|
+
slug: "vibecontrols",
|
|
8220
|
+
name: "VibeControls",
|
|
8221
|
+
websiteUrl: "https://vibecontrols.com"
|
|
8222
|
+
},
|
|
8223
|
+
// FluidGrids ships on www.fluidgrids.ai — fluidgrids.com only redirects there. The explore
|
|
8224
|
+
// catalog and the site's own sitemap use this origin, and so must the fallback catalog
|
|
8225
|
+
// built from this list, or /explore rejects FluidGrids concept images until it loads.
|
|
8226
|
+
{
|
|
8227
|
+
slug: "fluidgrids",
|
|
8228
|
+
name: "FluidGrids",
|
|
8229
|
+
websiteUrl: "https://www.fluidgrids.ai"
|
|
8230
|
+
},
|
|
8231
|
+
// BotManor ships on www.botmanor.com (the apex redirects there; the old botlit.ai domain
|
|
8232
|
+
// still serves the same site but is no longer the name we link to).
|
|
8233
|
+
// The slug follows the botlit → botmanor rename switch (utils/product-slug.ts).
|
|
8234
|
+
{
|
|
8235
|
+
slug: emitProductSlug("botmanor"),
|
|
8236
|
+
name: "BotManor",
|
|
8237
|
+
websiteUrl: "https://www.botmanor.com"
|
|
8238
|
+
},
|
|
8239
|
+
{
|
|
8240
|
+
slug: "bigconsole",
|
|
8241
|
+
name: "BigConsole",
|
|
8242
|
+
websiteUrl: "https://bigconsole.com"
|
|
8243
|
+
},
|
|
8244
|
+
{
|
|
8245
|
+
slug: "semanticfed",
|
|
8246
|
+
name: "SemanticFed",
|
|
8247
|
+
websiteUrl: "https://semanticfed.com"
|
|
8248
|
+
},
|
|
8249
|
+
{
|
|
8250
|
+
slug: "intelwatchtower",
|
|
8251
|
+
name: "IntelWatchtower",
|
|
8252
|
+
websiteUrl: "https://intelwatchtower.com"
|
|
8253
|
+
},
|
|
8254
|
+
{ slug: "buildmyiq", name: "BuildMyIQ", websiteUrl: "https://buildmyiq.com" },
|
|
8255
|
+
{
|
|
8256
|
+
slug: "assethandler",
|
|
8257
|
+
name: "AssetHandler",
|
|
8258
|
+
websiteUrl: "https://assethandler.com"
|
|
8259
|
+
},
|
|
8260
|
+
{
|
|
8261
|
+
slug: "crewfoundry",
|
|
8262
|
+
name: "CrewFoundry",
|
|
8263
|
+
websiteUrl: "https://crewfoundry.com"
|
|
8264
|
+
},
|
|
8265
|
+
{
|
|
8266
|
+
slug: "planmagnet",
|
|
8267
|
+
name: "PlanMagnet",
|
|
8268
|
+
websiteUrl: "https://planmagnet.com"
|
|
8269
|
+
},
|
|
8270
|
+
{
|
|
8271
|
+
slug: "eventfullymanaged",
|
|
8272
|
+
name: "EventfullyManaged",
|
|
8273
|
+
websiteUrl: "https://eventfullymanaged.com"
|
|
8274
|
+
},
|
|
8275
|
+
{
|
|
8276
|
+
slug: "headshotmarketing",
|
|
8277
|
+
name: "HeadshotMarketing",
|
|
8278
|
+
websiteUrl: "https://headshotmarketing.com"
|
|
8279
|
+
},
|
|
8280
|
+
{
|
|
8281
|
+
slug: "technospam",
|
|
8282
|
+
name: "TechnoSpam",
|
|
8283
|
+
websiteUrl: "https://technospam.com"
|
|
8284
|
+
},
|
|
8285
|
+
{ slug: "kadaikodi", name: "Kadaikodi", websiteUrl: "https://kadaikodi.com" },
|
|
8286
|
+
{
|
|
8287
|
+
slug: "movethewheels",
|
|
8288
|
+
name: "MoveTheWheels",
|
|
8289
|
+
websiteUrl: "https://movethewheels.com"
|
|
8290
|
+
},
|
|
8291
|
+
{
|
|
8292
|
+
slug: "healthybowl",
|
|
8293
|
+
name: "Healthy Bowl",
|
|
8294
|
+
websiteUrl: "https://gethealthybowl.com"
|
|
8295
|
+
},
|
|
8296
|
+
{ slug: "ggnomad", name: "GGNomad", websiteUrl: "https://ggnomad.com" },
|
|
8297
|
+
{
|
|
8298
|
+
slug: "timecampus",
|
|
8299
|
+
name: "TimeCampus",
|
|
8300
|
+
websiteUrl: "https://timecampus.com"
|
|
8301
|
+
},
|
|
8302
|
+
{
|
|
8303
|
+
slug: "manufacturedops",
|
|
8304
|
+
name: "ManufacturedOps",
|
|
8305
|
+
websiteUrl: "https://manufacturedops.com"
|
|
8306
|
+
},
|
|
8307
|
+
{
|
|
8308
|
+
slug: "theglobalfuel",
|
|
8309
|
+
name: "TheGlobalFuel",
|
|
8310
|
+
websiteUrl: "https://theglobalfuel.com"
|
|
8311
|
+
},
|
|
8312
|
+
{
|
|
8313
|
+
slug: "housingvista",
|
|
8314
|
+
name: "HousingVista",
|
|
8315
|
+
websiteUrl: "https://housingvista.com"
|
|
8316
|
+
},
|
|
8317
|
+
{
|
|
8318
|
+
slug: "proserviceworld",
|
|
8319
|
+
name: "ProServiceWorld",
|
|
8320
|
+
websiteUrl: "https://proserviceworld.com"
|
|
8321
|
+
},
|
|
8322
|
+
{
|
|
8323
|
+
slug: "mybodyshield",
|
|
8324
|
+
name: "MyBodyShield",
|
|
8325
|
+
websiteUrl: "https://mybodyshield.com"
|
|
8326
|
+
},
|
|
8327
|
+
{
|
|
8328
|
+
slug: "artistrybase",
|
|
8329
|
+
name: "ArtistryBase",
|
|
8330
|
+
websiteUrl: "https://artistrybase.com"
|
|
8331
|
+
},
|
|
8332
|
+
{
|
|
8333
|
+
slug: "theculturepost",
|
|
8334
|
+
name: "TheCulturePost",
|
|
8335
|
+
websiteUrl: "https://theculturepost.com"
|
|
8336
|
+
},
|
|
8337
|
+
{ slug: "collabkin", name: "CollabKin", websiteUrl: "https://collabkin.com" },
|
|
8338
|
+
{
|
|
8339
|
+
slug: "comradecircle",
|
|
8340
|
+
name: "ComradeCircle",
|
|
8341
|
+
websiteUrl: "https://comradecircle.com"
|
|
8342
|
+
},
|
|
8343
|
+
{
|
|
8344
|
+
slug: "brainyrich",
|
|
8345
|
+
name: "BrainyRich",
|
|
8346
|
+
websiteUrl: "https://brainyrich.com"
|
|
8347
|
+
},
|
|
8348
|
+
{
|
|
8349
|
+
slug: "cosmicintersection",
|
|
8350
|
+
name: "CosmicIntersection",
|
|
8351
|
+
websiteUrl: "https://cosmicintersection.com"
|
|
8352
|
+
},
|
|
8353
|
+
{
|
|
8354
|
+
slug: "govcitizenhub",
|
|
8355
|
+
name: "GovCitizenHub",
|
|
8356
|
+
websiteUrl: "https://govcitizenhub.com"
|
|
8357
|
+
},
|
|
8358
|
+
{
|
|
8359
|
+
slug: "adaptercloud",
|
|
8360
|
+
name: "AdapterCloud",
|
|
8361
|
+
websiteUrl: "https://adaptercloud.com"
|
|
8362
|
+
},
|
|
8363
|
+
{
|
|
8364
|
+
slug: "subscriberbot",
|
|
8365
|
+
name: "Subscriber Bot",
|
|
8366
|
+
websiteUrl: "https://subscriberbot.com"
|
|
8367
|
+
},
|
|
8368
|
+
{
|
|
8369
|
+
slug: "hookmovies",
|
|
8370
|
+
name: "HookMovies",
|
|
8371
|
+
websiteUrl: "https://hookmovies.com"
|
|
8372
|
+
},
|
|
8373
|
+
{
|
|
8374
|
+
slug: "coolandlovely",
|
|
8375
|
+
name: "CoolAndLovely",
|
|
8376
|
+
websiteUrl: "https://coolandlovely.com"
|
|
8377
|
+
},
|
|
8378
|
+
{
|
|
8379
|
+
slug: "atheletebridge",
|
|
8380
|
+
name: "AthleteBridge",
|
|
8381
|
+
websiteUrl: "https://atheletebridge.com"
|
|
8382
|
+
},
|
|
8383
|
+
{
|
|
8384
|
+
slug: "labsofscience",
|
|
8385
|
+
name: "LabsOfScience",
|
|
8386
|
+
websiteUrl: "https://labsofscience.com"
|
|
8387
|
+
},
|
|
8388
|
+
{
|
|
8389
|
+
slug: "ecoimpacthub",
|
|
8390
|
+
name: "EcoImpactHub",
|
|
8391
|
+
websiteUrl: "https://ecoimpacthub.com"
|
|
8392
|
+
}
|
|
8393
|
+
];
|
|
8394
|
+
var META_DESCRIPTION_LIMIT2 = 160;
|
|
8395
|
+
var TITLE_LIMIT = 100;
|
|
8396
|
+
var RELATED_LIMIT2 = 4;
|
|
8397
|
+
function normaliseSiteUrl2(siteUrl) {
|
|
8398
|
+
return siteUrl.trim().replace(/\/+$/, "");
|
|
8399
|
+
}
|
|
8400
|
+
function absoluteUrl2(base, path) {
|
|
8401
|
+
if (/^https?:\/\//i.test(path)) return path;
|
|
8402
|
+
return `${base}${path.startsWith("/") ? path : `/${path}`}`;
|
|
8403
|
+
}
|
|
8404
|
+
function sortByOrder2(answers) {
|
|
8405
|
+
return [...answers].sort(
|
|
8406
|
+
(a, b) => a.order - b.order || a.slug.localeCompare(b.slug)
|
|
8407
|
+
);
|
|
8408
|
+
}
|
|
8409
|
+
function clampText2(text, limit) {
|
|
8410
|
+
if (text.length <= limit) return text;
|
|
8411
|
+
const cut = text.slice(0, limit - 1);
|
|
8412
|
+
const lastSpace = cut.lastIndexOf(" ");
|
|
8413
|
+
return `${(lastSpace > 0 ? cut.slice(0, lastSpace) : cut).replace(/[\s,;:—–-]+$/, "")}\u2026`;
|
|
8414
|
+
}
|
|
8415
|
+
function questionCount(T, count) {
|
|
8416
|
+
return count === 1 ? T.questionCountOne : fill(T.questionCountMany, { count: String(count) });
|
|
8417
|
+
}
|
|
8418
|
+
function sourceCount(T, count) {
|
|
8419
|
+
return count === 1 ? T.sourceCountOne : fill(T.sourceCountMany, { count: String(count) });
|
|
7649
8420
|
}
|
|
7650
8421
|
function slugifyAnchor2(value) {
|
|
7651
8422
|
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -7725,6 +8496,12 @@ var ANSWER_HEADING_SHIFT = {
|
|
|
7725
8496
|
h6: demoteHeading("h6")
|
|
7726
8497
|
};
|
|
7727
8498
|
var ENGLISH_TEXT = { lang: "en" };
|
|
8499
|
+
var ECOSYSTEM_SITES = ECOSYSTEM_PRODUCTS.map((product) => ({
|
|
8500
|
+
slug: product.slug,
|
|
8501
|
+
website: product.websiteUrl
|
|
8502
|
+
}));
|
|
8503
|
+
var ECOSYSTEM_PRODUCT_SLUGS = productSlugsByOrigin(ECOSYSTEM_SITES);
|
|
8504
|
+
var ECOSYSTEM_ORIGINS = inlineImageOrigins(ECOSYSTEM_SITES);
|
|
7728
8505
|
function DefaultAnswerLink({
|
|
7729
8506
|
href,
|
|
7730
8507
|
className,
|
|
@@ -8223,6 +9000,10 @@ function AnswerDetail({
|
|
|
8223
9000
|
]),
|
|
8224
9001
|
[base, sources, imageOrigins]
|
|
8225
9002
|
);
|
|
9003
|
+
const answerVideoOrigins = React.useMemo(
|
|
9004
|
+
() => /* @__PURE__ */ new Set([...answerImageOrigins, ...ECOSYSTEM_ORIGINS]),
|
|
9005
|
+
[answerImageOrigins]
|
|
9006
|
+
);
|
|
8226
9007
|
const canonical = absoluteUrl2(base, answerPath(answer.slug));
|
|
8227
9008
|
const answerText = React.useMemo(
|
|
8228
9009
|
() => answerSpeechText(answer.answer),
|
|
@@ -8384,6 +9165,8 @@ function AnswerDetail({
|
|
|
8384
9165
|
{
|
|
8385
9166
|
strings: T,
|
|
8386
9167
|
imageOrigins: answerImageOrigins,
|
|
9168
|
+
videoOrigins: answerVideoOrigins,
|
|
9169
|
+
productSlugs: ECOSYSTEM_PRODUCT_SLUGS,
|
|
8387
9170
|
components: ANSWER_HEADING_SHIFT,
|
|
8388
9171
|
className: "mt-4",
|
|
8389
9172
|
children: answer.answer
|
|
@@ -8745,185 +9528,6 @@ var EXPLORE_SHARED_CONVERSATION_QUERY = (
|
|
|
8745
9528
|
`
|
|
8746
9529
|
);
|
|
8747
9530
|
|
|
8748
|
-
// src/data/products.ts
|
|
8749
|
-
var ECOSYSTEM_PRODUCTS = [
|
|
8750
|
-
{
|
|
8751
|
-
slug: "workspaces",
|
|
8752
|
-
name: "Workspaces",
|
|
8753
|
-
websiteUrl: "https://burdenoff.com"
|
|
8754
|
-
},
|
|
8755
|
-
{
|
|
8756
|
-
slug: "vibecontrols",
|
|
8757
|
-
name: "VibeControls",
|
|
8758
|
-
websiteUrl: "https://vibecontrols.com"
|
|
8759
|
-
},
|
|
8760
|
-
// FluidGrids ships on www.fluidgrids.ai — fluidgrids.com only redirects there. The explore
|
|
8761
|
-
// catalog and the site's own sitemap use this origin, and so must the fallback catalog
|
|
8762
|
-
// built from this list, or /explore rejects FluidGrids concept images until it loads.
|
|
8763
|
-
{
|
|
8764
|
-
slug: "fluidgrids",
|
|
8765
|
-
name: "FluidGrids",
|
|
8766
|
-
websiteUrl: "https://www.fluidgrids.ai"
|
|
8767
|
-
},
|
|
8768
|
-
// BotManor ships on www.botmanor.com (the apex redirects there; the old botlit.ai domain
|
|
8769
|
-
// still serves the same site but is no longer the name we link to).
|
|
8770
|
-
{ slug: "botlit", name: "BotManor", websiteUrl: "https://www.botmanor.com" },
|
|
8771
|
-
{
|
|
8772
|
-
slug: "bigconsole",
|
|
8773
|
-
name: "BigConsole",
|
|
8774
|
-
websiteUrl: "https://bigconsole.com"
|
|
8775
|
-
},
|
|
8776
|
-
{
|
|
8777
|
-
slug: "semanticfed",
|
|
8778
|
-
name: "SemanticFed",
|
|
8779
|
-
websiteUrl: "https://semanticfed.com"
|
|
8780
|
-
},
|
|
8781
|
-
{
|
|
8782
|
-
slug: "intelwatchtower",
|
|
8783
|
-
name: "IntelWatchtower",
|
|
8784
|
-
websiteUrl: "https://intelwatchtower.com"
|
|
8785
|
-
},
|
|
8786
|
-
{ slug: "buildmyiq", name: "BuildMyIQ", websiteUrl: "https://buildmyiq.com" },
|
|
8787
|
-
{
|
|
8788
|
-
slug: "assethandler",
|
|
8789
|
-
name: "AssetHandler",
|
|
8790
|
-
websiteUrl: "https://assethandler.com"
|
|
8791
|
-
},
|
|
8792
|
-
{
|
|
8793
|
-
slug: "crewfoundry",
|
|
8794
|
-
name: "CrewFoundry",
|
|
8795
|
-
websiteUrl: "https://crewfoundry.com"
|
|
8796
|
-
},
|
|
8797
|
-
{
|
|
8798
|
-
slug: "planmagnet",
|
|
8799
|
-
name: "PlanMagnet",
|
|
8800
|
-
websiteUrl: "https://planmagnet.com"
|
|
8801
|
-
},
|
|
8802
|
-
{
|
|
8803
|
-
slug: "eventfullymanaged",
|
|
8804
|
-
name: "EventfullyManaged",
|
|
8805
|
-
websiteUrl: "https://eventfullymanaged.com"
|
|
8806
|
-
},
|
|
8807
|
-
{
|
|
8808
|
-
slug: "headshotmarketing",
|
|
8809
|
-
name: "HeadshotMarketing",
|
|
8810
|
-
websiteUrl: "https://headshotmarketing.com"
|
|
8811
|
-
},
|
|
8812
|
-
{
|
|
8813
|
-
slug: "technospam",
|
|
8814
|
-
name: "TechnoSpam",
|
|
8815
|
-
websiteUrl: "https://technospam.com"
|
|
8816
|
-
},
|
|
8817
|
-
{ slug: "kadaikodi", name: "Kadaikodi", websiteUrl: "https://kadaikodi.com" },
|
|
8818
|
-
{
|
|
8819
|
-
slug: "movethewheels",
|
|
8820
|
-
name: "MoveTheWheels",
|
|
8821
|
-
websiteUrl: "https://movethewheels.com"
|
|
8822
|
-
},
|
|
8823
|
-
{
|
|
8824
|
-
slug: "healthybowl",
|
|
8825
|
-
name: "Healthy Bowl",
|
|
8826
|
-
websiteUrl: "https://gethealthybowl.com"
|
|
8827
|
-
},
|
|
8828
|
-
{ slug: "ggnomad", name: "GGNomad", websiteUrl: "https://ggnomad.com" },
|
|
8829
|
-
{
|
|
8830
|
-
slug: "timecampus",
|
|
8831
|
-
name: "TimeCampus",
|
|
8832
|
-
websiteUrl: "https://timecampus.com"
|
|
8833
|
-
},
|
|
8834
|
-
{
|
|
8835
|
-
slug: "manufacturedops",
|
|
8836
|
-
name: "ManufacturedOps",
|
|
8837
|
-
websiteUrl: "https://manufacturedops.com"
|
|
8838
|
-
},
|
|
8839
|
-
{
|
|
8840
|
-
slug: "theglobalfuel",
|
|
8841
|
-
name: "TheGlobalFuel",
|
|
8842
|
-
websiteUrl: "https://theglobalfuel.com"
|
|
8843
|
-
},
|
|
8844
|
-
{
|
|
8845
|
-
slug: "housingvista",
|
|
8846
|
-
name: "HousingVista",
|
|
8847
|
-
websiteUrl: "https://housingvista.com"
|
|
8848
|
-
},
|
|
8849
|
-
{
|
|
8850
|
-
slug: "proserviceworld",
|
|
8851
|
-
name: "ProServiceWorld",
|
|
8852
|
-
websiteUrl: "https://proserviceworld.com"
|
|
8853
|
-
},
|
|
8854
|
-
{
|
|
8855
|
-
slug: "mybodyshield",
|
|
8856
|
-
name: "MyBodyShield",
|
|
8857
|
-
websiteUrl: "https://mybodyshield.com"
|
|
8858
|
-
},
|
|
8859
|
-
{
|
|
8860
|
-
slug: "artistrybase",
|
|
8861
|
-
name: "ArtistryBase",
|
|
8862
|
-
websiteUrl: "https://artistrybase.com"
|
|
8863
|
-
},
|
|
8864
|
-
{
|
|
8865
|
-
slug: "theculturepost",
|
|
8866
|
-
name: "TheCulturePost",
|
|
8867
|
-
websiteUrl: "https://theculturepost.com"
|
|
8868
|
-
},
|
|
8869
|
-
{ slug: "collabkin", name: "CollabKin", websiteUrl: "https://collabkin.com" },
|
|
8870
|
-
{
|
|
8871
|
-
slug: "comradecircle",
|
|
8872
|
-
name: "ComradeCircle",
|
|
8873
|
-
websiteUrl: "https://comradecircle.com"
|
|
8874
|
-
},
|
|
8875
|
-
{
|
|
8876
|
-
slug: "brainyrich",
|
|
8877
|
-
name: "BrainyRich",
|
|
8878
|
-
websiteUrl: "https://brainyrich.com"
|
|
8879
|
-
},
|
|
8880
|
-
{
|
|
8881
|
-
slug: "cosmicintersection",
|
|
8882
|
-
name: "CosmicIntersection",
|
|
8883
|
-
websiteUrl: "https://cosmicintersection.com"
|
|
8884
|
-
},
|
|
8885
|
-
{
|
|
8886
|
-
slug: "govcitizenhub",
|
|
8887
|
-
name: "GovCitizenHub",
|
|
8888
|
-
websiteUrl: "https://govcitizenhub.com"
|
|
8889
|
-
},
|
|
8890
|
-
{
|
|
8891
|
-
slug: "adaptercloud",
|
|
8892
|
-
name: "AdapterCloud",
|
|
8893
|
-
websiteUrl: "https://adaptercloud.com"
|
|
8894
|
-
},
|
|
8895
|
-
{
|
|
8896
|
-
slug: "subscriberbot",
|
|
8897
|
-
name: "Subscriber Bot",
|
|
8898
|
-
websiteUrl: "https://subscriberbot.com"
|
|
8899
|
-
},
|
|
8900
|
-
{
|
|
8901
|
-
slug: "hookmovies",
|
|
8902
|
-
name: "HookMovies",
|
|
8903
|
-
websiteUrl: "https://hookmovies.com"
|
|
8904
|
-
},
|
|
8905
|
-
{
|
|
8906
|
-
slug: "coolandlovely",
|
|
8907
|
-
name: "CoolAndLovely",
|
|
8908
|
-
websiteUrl: "https://coolandlovely.com"
|
|
8909
|
-
},
|
|
8910
|
-
{
|
|
8911
|
-
slug: "atheletebridge",
|
|
8912
|
-
name: "AthleteBridge",
|
|
8913
|
-
websiteUrl: "https://atheletebridge.com"
|
|
8914
|
-
},
|
|
8915
|
-
{
|
|
8916
|
-
slug: "labsofscience",
|
|
8917
|
-
name: "LabsOfScience",
|
|
8918
|
-
websiteUrl: "https://labsofscience.com"
|
|
8919
|
-
},
|
|
8920
|
-
{
|
|
8921
|
-
slug: "ecoimpacthub",
|
|
8922
|
-
name: "EcoImpactHub",
|
|
8923
|
-
websiteUrl: "https://ecoimpacthub.com"
|
|
8924
|
-
}
|
|
8925
|
-
];
|
|
8926
|
-
|
|
8927
9531
|
// src/utils/recaptcha-v3.ts
|
|
8928
9532
|
var SCRIPT_ID = "boff-recaptcha-v3";
|
|
8929
9533
|
var SCRIPT_SRC = "https://www.google.com/recaptcha/api.js?render=";
|
|
@@ -10041,7 +10645,7 @@ function isHighSurrogate(code) {
|
|
|
10041
10645
|
}
|
|
10042
10646
|
function safeInlineEnd(line) {
|
|
10043
10647
|
let codeSpan = null;
|
|
10044
|
-
|
|
10648
|
+
const links = [];
|
|
10045
10649
|
const emphasis = [];
|
|
10046
10650
|
let at = 0;
|
|
10047
10651
|
while (at < line.length) {
|
|
@@ -10050,6 +10654,13 @@ function safeInlineEnd(line) {
|
|
|
10050
10654
|
at += 2;
|
|
10051
10655
|
continue;
|
|
10052
10656
|
}
|
|
10657
|
+
const innermost = links[links.length - 1];
|
|
10658
|
+
if (innermost !== void 0 && innermost.kind !== "label") {
|
|
10659
|
+
if (char === "(") links.push({ kind: "paren", start: innermost.start });
|
|
10660
|
+
else if (char === ")") links.pop();
|
|
10661
|
+
at += 1;
|
|
10662
|
+
continue;
|
|
10663
|
+
}
|
|
10053
10664
|
if (char === "`") {
|
|
10054
10665
|
let run = 1;
|
|
10055
10666
|
while (line[at + run] === "`") run += 1;
|
|
@@ -10062,17 +10673,17 @@ function safeInlineEnd(line) {
|
|
|
10062
10673
|
continue;
|
|
10063
10674
|
}
|
|
10064
10675
|
if (char === "[") {
|
|
10065
|
-
|
|
10676
|
+
links.push({ kind: "label", start: line[at - 1] === "!" ? at - 1 : at });
|
|
10066
10677
|
at += 1;
|
|
10067
10678
|
continue;
|
|
10068
10679
|
}
|
|
10069
|
-
if (char === "]") {
|
|
10070
|
-
|
|
10071
|
-
at
|
|
10072
|
-
|
|
10073
|
-
|
|
10074
|
-
|
|
10075
|
-
|
|
10680
|
+
if (char === "]" && innermost !== void 0) {
|
|
10681
|
+
links.pop();
|
|
10682
|
+
if (line[at + 1] === "(") {
|
|
10683
|
+
links.push({ kind: "destination", start: innermost.start });
|
|
10684
|
+
at += 2;
|
|
10685
|
+
continue;
|
|
10686
|
+
}
|
|
10076
10687
|
at += 1;
|
|
10077
10688
|
continue;
|
|
10078
10689
|
}
|
|
@@ -10099,9 +10710,11 @@ function safeInlineEnd(line) {
|
|
|
10099
10710
|
}
|
|
10100
10711
|
at += 1;
|
|
10101
10712
|
}
|
|
10102
|
-
const open = [
|
|
10103
|
-
|
|
10104
|
-
|
|
10713
|
+
const open = [
|
|
10714
|
+
codeSpan,
|
|
10715
|
+
links[0]?.start ?? null,
|
|
10716
|
+
emphasis[0]?.start ?? null
|
|
10717
|
+
].filter((value) => value !== null);
|
|
10105
10718
|
return open.length === 0 ? line.length : Math.min(...open);
|
|
10106
10719
|
}
|
|
10107
10720
|
function revealBoundary(text, limit) {
|
|
@@ -11963,6 +12576,7 @@ function AssistantBubble({
|
|
|
11963
12576
|
message,
|
|
11964
12577
|
activity,
|
|
11965
12578
|
imageOrigins,
|
|
12579
|
+
productSlugs,
|
|
11966
12580
|
productNames,
|
|
11967
12581
|
speechLang,
|
|
11968
12582
|
onNavigate,
|
|
@@ -12077,6 +12691,7 @@ function AssistantBubble({
|
|
|
12077
12691
|
{
|
|
12078
12692
|
strings: T,
|
|
12079
12693
|
imageOrigins,
|
|
12694
|
+
productSlugs,
|
|
12080
12695
|
enabled: completed,
|
|
12081
12696
|
className: "boff-prose-sm text-card-foreground",
|
|
12082
12697
|
children: visible
|
|
@@ -12347,21 +12962,24 @@ function ProductStrip({
|
|
|
12347
12962
|
children: T.allProducts
|
|
12348
12963
|
}
|
|
12349
12964
|
),
|
|
12350
|
-
products.map((product) =>
|
|
12351
|
-
|
|
12352
|
-
|
|
12353
|
-
"
|
|
12354
|
-
|
|
12355
|
-
|
|
12356
|
-
|
|
12357
|
-
|
|
12358
|
-
|
|
12359
|
-
|
|
12360
|
-
|
|
12361
|
-
|
|
12362
|
-
|
|
12363
|
-
|
|
12364
|
-
|
|
12965
|
+
products.map((product) => {
|
|
12966
|
+
const focused = isSameProductSlug(focusProduct, product.slug);
|
|
12967
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12968
|
+
"button",
|
|
12969
|
+
{
|
|
12970
|
+
"data-boff-explore": "chip",
|
|
12971
|
+
"data-chip-kind": "product",
|
|
12972
|
+
"data-product": product.slug,
|
|
12973
|
+
type: "button",
|
|
12974
|
+
"aria-pressed": focused,
|
|
12975
|
+
title: product.tagline ?? product.name,
|
|
12976
|
+
onClick: () => onFocus(focused ? null : product.slug),
|
|
12977
|
+
className: chipClass(focused),
|
|
12978
|
+
children: product.name
|
|
12979
|
+
},
|
|
12980
|
+
product.slug
|
|
12981
|
+
);
|
|
12982
|
+
})
|
|
12365
12983
|
]
|
|
12366
12984
|
}
|
|
12367
12985
|
),
|
|
@@ -12819,11 +13437,11 @@ function ExplorePage({
|
|
|
12819
13437
|
const resolvedBody = welcomeBody ?? catalog.welcomeBody;
|
|
12820
13438
|
const prompts = catalog.examplePrompts;
|
|
12821
13439
|
const focusedProductName = React.useMemo(
|
|
12822
|
-
() => catalog.products.find((p) => p.slug
|
|
13440
|
+
() => catalog.products.find((p) => isSameProductSlug(p.slug, focusProduct))?.name ?? null,
|
|
12823
13441
|
[catalog.products, focusProduct]
|
|
12824
13442
|
);
|
|
12825
13443
|
const headProductName = React.useMemo(
|
|
12826
|
-
() => productSlug ? catalog.products.find((p) => p.slug
|
|
13444
|
+
() => productSlug ? catalog.products.find((p) => isSameProductSlug(p.slug, productSlug))?.name ?? null : null,
|
|
12827
13445
|
[catalog.products, productSlug]
|
|
12828
13446
|
);
|
|
12829
13447
|
const imageOrigins = React.useMemo(
|
|
@@ -12834,6 +13452,10 @@ function ExplorePage({
|
|
|
12834
13452
|
() => productNamesByOrigin(catalog.products),
|
|
12835
13453
|
[catalog.products]
|
|
12836
13454
|
);
|
|
13455
|
+
const productSlugs = React.useMemo(
|
|
13456
|
+
() => productSlugsByOrigin(catalog.products),
|
|
13457
|
+
[catalog.products]
|
|
13458
|
+
);
|
|
12837
13459
|
React.useEffect(() => {
|
|
12838
13460
|
const el = textareaRef.current;
|
|
12839
13461
|
if (!el) return;
|
|
@@ -13396,6 +14018,7 @@ function ExplorePage({
|
|
|
13396
14018
|
message,
|
|
13397
14019
|
activity,
|
|
13398
14020
|
imageOrigins,
|
|
14021
|
+
productSlugs,
|
|
13399
14022
|
productNames,
|
|
13400
14023
|
speechLang,
|
|
13401
14024
|
onNavigate,
|
|
@@ -18437,6 +19060,9 @@ exports.LaunchCountdown = LaunchCountdown;
|
|
|
18437
19060
|
exports.Markdown = Markdown;
|
|
18438
19061
|
exports.NewsletterForm = NewsletterForm;
|
|
18439
19062
|
exports.NewsletterPage = NewsletterPage;
|
|
19063
|
+
exports.PRODUCT_SLUG_ALIASES = PRODUCT_SLUG_ALIASES;
|
|
19064
|
+
exports.PRODUCT_SLUG_EMIT = PRODUCT_SLUG_EMIT;
|
|
19065
|
+
exports.PRODUCT_SLUG_RENAMES = PRODUCT_SLUG_RENAMES;
|
|
18440
19066
|
exports.PUBLISHED_ANSWER_FIELDS = PUBLISHED_ANSWER_FIELDS;
|
|
18441
19067
|
exports.PageHead = PageHead;
|
|
18442
19068
|
exports.PartnersPage = PartnersPage;
|
|
@@ -18473,10 +19099,12 @@ exports.classifyExploreError = classifyExploreError;
|
|
|
18473
19099
|
exports.cn = cn;
|
|
18474
19100
|
exports.conceptPath = conceptPath;
|
|
18475
19101
|
exports.detectElectronPlatform = detectElectronPlatform;
|
|
19102
|
+
exports.emitProductSlug = emitProductSlug;
|
|
18476
19103
|
exports.exploreQuestionHref = exploreQuestionHref;
|
|
18477
19104
|
exports.fetchPublicJobPosting = fetchPublicJobPosting;
|
|
18478
19105
|
exports.fetchPublicJobPostings = fetchPublicJobPostings;
|
|
18479
19106
|
exports.fetchPublicJobPostingsForSubmission = fetchPublicJobPostingsForSubmission;
|
|
19107
|
+
exports.fetchPublicProduct = fetchPublicProduct;
|
|
18480
19108
|
exports.formatAnswerDate = formatAnswerDate;
|
|
18481
19109
|
exports.formatDownloads = formatDownloads;
|
|
18482
19110
|
exports.formatPrice = formatPrice2;
|
|
@@ -18486,11 +19114,17 @@ exports.getRecaptchaV3Token = getRecaptchaV3Token;
|
|
|
18486
19114
|
exports.inlineImageOrigins = inlineImageOrigins;
|
|
18487
19115
|
exports.isFooterlessPath = isFooterlessPath;
|
|
18488
19116
|
exports.isInlineImageAllowed = isInlineImageAllowed;
|
|
19117
|
+
exports.isInlineVideoAllowed = isInlineVideoAllowed;
|
|
18489
19118
|
exports.isPublishedSourceUrl = isPublishedSourceUrl;
|
|
19119
|
+
exports.isSameProductSlug = isSameProductSlug;
|
|
18490
19120
|
exports.isValidUrl = isValidUrl;
|
|
19121
|
+
exports.legacyProductSlug = legacyProductSlug;
|
|
18491
19122
|
exports.loadRecaptchaV3 = loadRecaptchaV3;
|
|
18492
19123
|
exports.looksLikeDeliverableEmail = looksLikeDeliverableEmail;
|
|
19124
|
+
exports.normalizeProductSlug = normalizeProductSlug;
|
|
18493
19125
|
exports.normalizeRoutePath = normalizeRoutePath;
|
|
19126
|
+
exports.productSlugVariants = productSlugVariants;
|
|
19127
|
+
exports.productSlugsByOrigin = productSlugsByOrigin;
|
|
18494
19128
|
exports.shouldRenderSiteFooter = shouldRenderSiteFooter;
|
|
18495
19129
|
exports.speechLocaleOf = speechLocaleOf;
|
|
18496
19130
|
exports.stopSpeaking = stopSpeaking;
|