@wix/web5-core 1.63.25 → 1.63.27
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/cjs/components/ui/UserQuery.css +10 -7
- package/dist/cjs/components/ui/UserQuery.js +17 -33
- package/dist/cjs/components/ui/UserQuery.js.map +1 -1
- package/dist/cjs/context/ComponentDependenciesContext.js +15 -1
- package/dist/cjs/context/ComponentDependenciesContext.js.map +1 -1
- package/dist/cjs/context/ImageSlotContext.js +210 -0
- package/dist/cjs/context/ImageSlotContext.js.map +1 -0
- package/dist/cjs/hooks/useImageSlot.js +182 -0
- package/dist/cjs/hooks/useImageSlot.js.map +1 -0
- package/dist/cjs/image/composeSemantic.js +94 -0
- package/dist/cjs/image/composeSemantic.js.map +1 -0
- package/dist/cjs/image/imageSlotTypes.js +4 -0
- package/dist/cjs/image/imageSlotTypes.js.map +1 -0
- package/dist/cjs/index.js +11 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/dependencies.js.map +1 -1
- package/dist/esm/components/ui/UserQuery.css +10 -7
- package/dist/esm/components/ui/UserQuery.js +5 -9
- package/dist/esm/components/ui/UserQuery.js.map +1 -1
- package/dist/esm/context/ComponentDependenciesContext.js +13 -0
- package/dist/esm/context/ComponentDependenciesContext.js.map +1 -1
- package/dist/esm/context/ImageSlotContext.js +197 -0
- package/dist/esm/context/ImageSlotContext.js.map +1 -0
- package/dist/esm/hooks/useImageSlot.js +177 -0
- package/dist/esm/hooks/useImageSlot.js.map +1 -0
- package/dist/esm/image/composeSemantic.js +91 -0
- package/dist/esm/image/composeSemantic.js.map +1 -0
- package/dist/esm/image/imageSlotTypes.js +2 -0
- package/dist/esm/image/imageSlotTypes.js.map +1 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/dependencies.js.map +1 -1
- package/dist/types/components/ui/UserQuery.d.ts.map +1 -1
- package/dist/types/context/ComponentDependenciesContext.d.ts +10 -0
- package/dist/types/context/ComponentDependenciesContext.d.ts.map +1 -1
- package/dist/types/context/ImageSlotContext.d.ts +63 -0
- package/dist/types/context/ImageSlotContext.d.ts.map +1 -0
- package/dist/types/hooks/useImageSlot.d.ts +35 -0
- package/dist/types/hooks/useImageSlot.d.ts.map +1 -0
- package/dist/types/image/composeSemantic.d.ts +37 -0
- package/dist/types/image/composeSemantic.d.ts.map +1 -0
- package/dist/types/image/imageSlotTypes.d.ts +112 -0
- package/dist/types/image/imageSlotTypes.d.ts.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types/dependencies.d.ts +11 -0
- package/dist/types/types/dependencies.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/components/ui/UserQuery.css +10 -7
|
@@ -130,9 +130,10 @@
|
|
|
130
130
|
* deliberately keeps its own near-black, because that one is a status message
|
|
131
131
|
* rather than a label and should not read as an action.
|
|
132
132
|
*
|
|
133
|
-
*
|
|
134
|
-
* the
|
|
135
|
-
*
|
|
133
|
+
* The buttons are icon-only at every width, so this bubble is the only place
|
|
134
|
+
* the actions are spelled out on a pointer device. Hover and focus-within
|
|
135
|
+
* both, so a keyboard user tabbing through the header gets the same
|
|
136
|
+
* affordance instead of two unexplained icons.
|
|
136
137
|
*/
|
|
137
138
|
.web5-user-query__tooltip {
|
|
138
139
|
position: absolute;
|
|
@@ -161,11 +162,13 @@
|
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
/*
|
|
164
|
-
*
|
|
165
|
-
* permanently in the way.
|
|
166
|
-
* actually names them for anyone who needs
|
|
165
|
+
* Mobile: no hover to open the bubble on, so it would be either permanently
|
|
166
|
+
* invisible or permanently in the way. Nothing is shown there — the buttons
|
|
167
|
+
* carry `aria-label`, which is what actually names them for anyone who needs
|
|
168
|
+
* it. Both queries, because `hover: none` is the precise question and
|
|
169
|
+
* `pointer: coarse` is the one older engines answer.
|
|
167
170
|
*/
|
|
168
|
-
@media (pointer: coarse) {
|
|
171
|
+
@media (hover: none), (pointer: coarse) {
|
|
169
172
|
.web5-user-query__tooltip {
|
|
170
173
|
display: none;
|
|
171
174
|
}
|
|
@@ -378,44 +378,36 @@ const UserQuery = ({
|
|
|
378
378
|
lineNumber: 324,
|
|
379
379
|
columnNumber: 41
|
|
380
380
|
}
|
|
381
|
-
}), /*#__PURE__*/_react.default.createElement("span", {
|
|
382
|
-
className: "hidden sm:inline",
|
|
383
|
-
__self: void 0,
|
|
384
|
-
__source: {
|
|
385
|
-
fileName: _jsxFileName,
|
|
386
|
-
lineNumber: 325,
|
|
387
|
-
columnNumber: 13
|
|
388
|
-
}
|
|
389
|
-
}, isLoading ? 'Sharing…' : isCopied ? copiedLabel : 'Share')), !isCopied && /*#__PURE__*/_react.default.createElement("span", {
|
|
381
|
+
})), shareState === 'idle' && /*#__PURE__*/_react.default.createElement("span", {
|
|
390
382
|
className: "web5-user-query__tooltip",
|
|
391
383
|
role: "tooltip",
|
|
392
384
|
__self: void 0,
|
|
393
385
|
__source: {
|
|
394
386
|
fileName: _jsxFileName,
|
|
395
|
-
lineNumber:
|
|
387
|
+
lineNumber: 333,
|
|
396
388
|
columnNumber: 13
|
|
397
389
|
}
|
|
398
|
-
}, "Share this"),
|
|
399
|
-
className: "web5-user-query__copied-toast
|
|
390
|
+
}, "Share this"), shareState !== 'idle' && /*#__PURE__*/_react.default.createElement("div", {
|
|
391
|
+
className: "web5-user-query__copied-toast absolute top-full right-0 mt-1 flex items-center gap-2 bg-[#2b2b2b] text-white text-[12px] leading-none px-3 py-2 rounded-[8px] whitespace-nowrap",
|
|
400
392
|
__self: void 0,
|
|
401
393
|
__source: {
|
|
402
394
|
fileName: _jsxFileName,
|
|
403
|
-
lineNumber:
|
|
395
|
+
lineNumber: 345,
|
|
404
396
|
columnNumber: 13
|
|
405
397
|
}
|
|
406
|
-
}, /*#__PURE__*/_react.default.createElement(_CheckIcon.CheckIcon, {
|
|
398
|
+
}, isCopied && /*#__PURE__*/_react.default.createElement(_CheckIcon.CheckIcon, {
|
|
407
399
|
__self: void 0,
|
|
408
400
|
__source: {
|
|
409
401
|
fileName: _jsxFileName,
|
|
410
|
-
lineNumber:
|
|
411
|
-
columnNumber:
|
|
402
|
+
lineNumber: 346,
|
|
403
|
+
columnNumber: 28
|
|
412
404
|
}
|
|
413
|
-
}), copiedLabel)), onNewConversation && /*#__PURE__*/_react.default.createElement("div", {
|
|
405
|
+
}), isLoading ? 'Sharing…' : copiedLabel)), onNewConversation && /*#__PURE__*/_react.default.createElement("div", {
|
|
414
406
|
className: "web5-user-query__action group relative",
|
|
415
407
|
__self: void 0,
|
|
416
408
|
__source: {
|
|
417
409
|
fileName: _jsxFileName,
|
|
418
|
-
lineNumber:
|
|
410
|
+
lineNumber: 352,
|
|
419
411
|
columnNumber: 11
|
|
420
412
|
}
|
|
421
413
|
}, /*#__PURE__*/_react.default.createElement("button", {
|
|
@@ -426,31 +418,23 @@ const UserQuery = ({
|
|
|
426
418
|
__self: void 0,
|
|
427
419
|
__source: {
|
|
428
420
|
fileName: _jsxFileName,
|
|
429
|
-
lineNumber:
|
|
421
|
+
lineNumber: 353,
|
|
430
422
|
columnNumber: 13
|
|
431
423
|
}
|
|
432
424
|
}, /*#__PURE__*/_react.default.createElement(_PlusIcon.PlusIcon, {
|
|
433
425
|
__self: void 0,
|
|
434
426
|
__source: {
|
|
435
427
|
fileName: _jsxFileName,
|
|
436
|
-
lineNumber:
|
|
437
|
-
columnNumber: 15
|
|
438
|
-
}
|
|
439
|
-
}), /*#__PURE__*/_react.default.createElement("span", {
|
|
440
|
-
className: "hidden sm:inline",
|
|
441
|
-
__self: void 0,
|
|
442
|
-
__source: {
|
|
443
|
-
fileName: _jsxFileName,
|
|
444
|
-
lineNumber: 356,
|
|
428
|
+
lineNumber: 359,
|
|
445
429
|
columnNumber: 15
|
|
446
430
|
}
|
|
447
|
-
}
|
|
431
|
+
})), /*#__PURE__*/_react.default.createElement("span", {
|
|
448
432
|
className: "web5-user-query__tooltip",
|
|
449
433
|
role: "tooltip",
|
|
450
434
|
__self: void 0,
|
|
451
435
|
__source: {
|
|
452
436
|
fileName: _jsxFileName,
|
|
453
|
-
lineNumber:
|
|
437
|
+
lineNumber: 361,
|
|
454
438
|
columnNumber: 13
|
|
455
439
|
}
|
|
456
440
|
}, newConversationLabel)), onToggleCommentMode && /*#__PURE__*/_react.default.createElement("button", {
|
|
@@ -463,14 +447,14 @@ const UserQuery = ({
|
|
|
463
447
|
__self: void 0,
|
|
464
448
|
__source: {
|
|
465
449
|
fileName: _jsxFileName,
|
|
466
|
-
lineNumber:
|
|
450
|
+
lineNumber: 367,
|
|
467
451
|
columnNumber: 11
|
|
468
452
|
}
|
|
469
453
|
}, /*#__PURE__*/_react.default.createElement(_CommentIcon.CommentIcon, {
|
|
470
454
|
__self: void 0,
|
|
471
455
|
__source: {
|
|
472
456
|
fileName: _jsxFileName,
|
|
473
|
-
lineNumber:
|
|
457
|
+
lineNumber: 379,
|
|
474
458
|
columnNumber: 13
|
|
475
459
|
}
|
|
476
460
|
}), commentCount > 0 && /*#__PURE__*/_react.default.createElement("span", {
|
|
@@ -478,7 +462,7 @@ const UserQuery = ({
|
|
|
478
462
|
__self: void 0,
|
|
479
463
|
__source: {
|
|
480
464
|
fileName: _jsxFileName,
|
|
481
|
-
lineNumber:
|
|
465
|
+
lineNumber: 381,
|
|
482
466
|
columnNumber: 15
|
|
483
467
|
}
|
|
484
468
|
}, commentCount))));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_ShareIcon","_CheckIcon","_PlusIcon","_UndoIcon","_RedoIcon","_CommentIcon","_navigationStack","_jsxFileName","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","DEFAULT_LOADING_MESSAGES","headerClassName","UserQuery","query","onNewConversation","onNavigateToTriggerId","predecessorTriggerId","currentTriggerId","onShare","onToggleCommentMode","commentMode","commentCount","loading","newConversationLabel","copiedLabel","copiedDurationMs","productBackContext","onBackToProduct","forwardStack","useMemo","getForwardStack","canGoForward","length","canGoBack","hasNavigation","handleBack","useCallback","pushToForwardStack","handleForward","nextTid","popFromForwardStack","handleNewConversation","clearForwardStack","shareState","setShareState","useState","productImageError","setProductImageError","useEffect","imageUrl","handleShare","urlToCopy","window","location","href","err","console","warn","navigator","clipboard","writeText","catch","setTimeout","cyclingMessages","messages","cycledMessage","setCycledMessage","progressMessage","index","interval","setInterval","clearInterval","isCopied","isLoading","productBadge","title","backUrl","label","canNavigateBack","content","createElement","Fragment","UndoIcon","className","__self","__source","fileName","lineNumber","columnNumber","src","alt","onError","type","onClick","progressText","role","pendingQuery","disabled","RedoIcon","CheckIcon","ShareIcon","PlusIcon","CommentIcon","exports"],"sources":["../../../../src/components/ui/UserQuery.tsx"],"sourcesContent":["import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';\nimport { ShareIcon } from './icons/ShareIcon';\nimport { CheckIcon } from './icons/CheckIcon';\nimport { PlusIcon } from './icons/PlusIcon';\nimport { UndoIcon } from './icons/UndoIcon';\nimport { RedoIcon } from './icons/RedoIcon';\nimport { CommentIcon } from './icons/CommentIcon';\nimport {\n getForwardStack,\n pushToForwardStack,\n popFromForwardStack,\n clearForwardStack,\n} from '../../utils/navigationStack';\n\ntype ShareState = 'idle' | 'loading' | 'copied';\n\nconst DEFAULT_LOADING_MESSAGES = [\n 'Thinking…',\n 'Recognizing intent…',\n 'Connecting the dots…',\n 'Synthesizing insights…',\n 'Formulating a response…',\n];\n\nconst headerClassName =\n 'web5-user-query sticky top-0 z-10 flex items-center justify-between bg-white/60 backdrop-blur-sm pl-5 pr-[10px] py-[7px] sm:px-[30px] sm:py-[17px]';\n\nexport interface UserQueryLoadingState {\n pendingQuery: string;\n /** Static progress message. If omitted, falls back to cycling through `messages`. */\n progressMessage?: string;\n /** Messages cycled while loading when `progressMessage` is not set. */\n messages?: string[];\n}\n\n/**\n * Product the visitor was redirected from (DL #114). Rendered as a back badge\n * above the query: back arrow + thumbnail + product name. All fields are\n * resolved and validated app-side (allowed-domain `backUrl`, `https:`\n * `imageUrl`) before reaching this presentational component.\n */\nexport interface ProductBackContext {\n /** Product display name. Required — without it the badge does not render. */\n title: string;\n /** Validated product thumbnail URL. Omitted/failed to load → arrow + title only. */\n imageUrl?: string;\n /** Validated product-page URL to return to. Omitted → badge is non-clickable. */\n backUrl?: string;\n /** Accessible label override. Defaults to `Back to ${title}`. */\n label?: string;\n}\n\nexport interface UserQueryProps {\n query: string;\n onNewConversation?: () => void;\n onNavigateToTriggerId?: (triggerId: string) => void;\n predecessorTriggerId?: string;\n currentTriggerId?: string;\n onShare?: (triggerId: string) => Promise<string>;\n /** Optional comment-mode toggle. When provided, render the chat-bubble\n * toggle button next to Share. The button reflects `commentMode` via\n * `is-on` styling and `aria-pressed`. */\n onToggleCommentMode?: () => void;\n commentMode?: boolean;\n /** Total number of comments on this response — shown as a badge next to the\n * toggle when > 0. */\n commentCount?: number;\n loading?: UserQueryLoadingState;\n /** Label for the \"new conversation\" action. Defaults to \"New conversation\". */\n newConversationLabel?: string;\n /** Label shown after the share link is copied. Defaults to \"Link Copied\". */\n copiedLabel?: string;\n /** How long the copied state stays visible, in ms. Defaults to 2000. */\n copiedDurationMs?: number;\n /** When set (visitor arrived from a product page), render a back-to-product\n * badge above the query (DL #114). */\n productBackContext?: ProductBackContext;\n /** Invoked with the validated `backUrl` when the badge is activated. */\n onBackToProduct?: (backUrl: string) => void;\n}\n\nexport const UserQuery: FC<UserQueryProps> = ({\n query,\n onNewConversation,\n onNavigateToTriggerId,\n predecessorTriggerId,\n currentTriggerId,\n onShare,\n onToggleCommentMode,\n commentMode = false,\n commentCount = 0,\n loading,\n newConversationLabel = 'New conversation',\n copiedLabel = 'Link Copied',\n copiedDurationMs = 2000,\n productBackContext,\n onBackToProduct,\n}) => {\n const forwardStack = useMemo(() => getForwardStack(), [currentTriggerId]);\n const canGoForward = forwardStack.length > 0;\n const canGoBack = !!predecessorTriggerId;\n const hasNavigation = canGoBack || canGoForward;\n\n const handleBack = useCallback(() => {\n if (!predecessorTriggerId || !currentTriggerId || !onNavigateToTriggerId) {\n return;\n }\n pushToForwardStack(currentTriggerId);\n onNavigateToTriggerId(predecessorTriggerId);\n }, [predecessorTriggerId, currentTriggerId, onNavigateToTriggerId]);\n\n const handleForward = useCallback(() => {\n if (!onNavigateToTriggerId) {\n return;\n }\n const nextTid = popFromForwardStack();\n if (!nextTid) {\n return;\n }\n onNavigateToTriggerId(nextTid);\n }, [onNavigateToTriggerId]);\n\n const handleNewConversation = useCallback(() => {\n clearForwardStack();\n onNewConversation?.();\n }, [onNewConversation]);\n\n const [shareState, setShareState] = useState<ShareState>('idle');\n\n const [productImageError, setProductImageError] = useState(false);\n useEffect(() => {\n setProductImageError(false);\n }, [productBackContext?.imageUrl]);\n\n const handleShare = useCallback(async () => {\n if (shareState !== 'idle') {\n return;\n }\n setShareState('loading');\n let urlToCopy = window.location.href;\n try {\n if (onShare && currentTriggerId) {\n urlToCopy = await onShare(currentTriggerId);\n }\n } catch (err) {\n console.warn('[share] failed, falling back to current URL:', err);\n }\n navigator.clipboard\n .writeText(urlToCopy)\n .catch((err) => console.warn('[share] clipboard write failed:', err));\n setShareState('copied');\n setTimeout(() => setShareState('idle'), copiedDurationMs);\n }, [shareState, onShare, currentTriggerId, copiedDurationMs]);\n\n const cyclingMessages = useMemo(\n () =>\n loading?.messages && loading.messages.length > 0\n ? loading.messages\n : DEFAULT_LOADING_MESSAGES,\n [loading?.messages],\n );\n const [cycledMessage, setCycledMessage] = useState(cyclingMessages[0]);\n\n useEffect(() => {\n if (!loading || loading.progressMessage) {\n return;\n }\n setCycledMessage(cyclingMessages[0]);\n if (cyclingMessages.length <= 1) {\n return;\n }\n let index = 0;\n const interval = setInterval(() => {\n index = (index + 1) % cyclingMessages.length;\n setCycledMessage(cyclingMessages[index]);\n }, 4000);\n return () => clearInterval(interval);\n }, [loading, cyclingMessages]);\n\n if (!query && !loading) {\n return null;\n }\n\n const isCopied = shareState === 'copied';\n const isLoading = shareState === 'loading';\n\n const productBadge = productBackContext\n ? (() => {\n const { title, imageUrl, backUrl, label } = productBackContext;\n const canNavigateBack = !!backUrl && !!onBackToProduct;\n const content = (\n <>\n <UndoIcon className=\"web5-user-query__product-back-icon\" />\n {imageUrl && !productImageError && (\n <span className=\"web5-user-query__product-back-thumb\">\n <img\n src={imageUrl}\n alt=\"\"\n onError={() => setProductImageError(true)}\n />\n </span>\n )}\n <span className=\"web5-user-query__product-back-title\">{title}</span>\n </>\n );\n return canNavigateBack ? (\n <button\n type=\"button\"\n onClick={() => onBackToProduct?.(backUrl!)}\n aria-label={label ?? `Back to ${title}`}\n className=\"web5-user-query__product-back\"\n >\n {content}\n </button>\n ) : (\n <div className=\"web5-user-query__product-back web5-user-query__product-back--static\">\n {content}\n </div>\n );\n })()\n : null;\n\n if (loading) {\n const progressText = loading.progressMessage ?? cycledMessage;\n return (\n <div\n className={headerClassName}\n role=\"status\"\n aria-busy=\"true\"\n aria-live=\"polite\"\n >\n <div className=\"web5-user-query__left flex-1\">\n {productBadge}\n <p\n className=\"text-[14px] leading-5 text-text-body truncate min-w-0 max-w-[700px]\"\n title={`Asking: ${loading.pendingQuery}`}\n >\n <span className=\"text-text-body/70\">Asking: </span>\n {loading.pendingQuery}\n </p>\n </div>\n {progressText && (\n <div className=\"hidden sm:flex items-center gap-2 ml-[10px] shrink-0 min-w-0\">\n <div\n className=\"w-4 h-4 shrink-0 animate-spin inline-block border-[2px] border-current border-t-transparent text-blue-600 dark:text-blue-500 rounded-full\"\n aria-hidden=\"true\"\n />\n <p className=\"text-[13px] leading-5 text-text-body/70 truncate max-w-[240px]\">\n {progressText}\n </p>\n </div>\n )}\n </div>\n );\n }\n\n return (\n <div className={headerClassName}>\n <div className=\"flex items-center gap-[30px] flex-1 min-w-0\">\n <div className=\"web5-user-query__left\">\n {productBadge}\n <p\n className=\"web5-user-query__title text-[14px] leading-5 text-text-body truncate min-w-0 max-w-[700px]\"\n title={query}\n >\n {query}\n </p>\n </div>\n {hasNavigation && (\n <div className=\"flex items-center gap-[9px]\">\n <button\n type=\"button\"\n onClick={handleBack}\n disabled={!canGoBack}\n title=\"Go to previous conversation\"\n aria-label=\"Go to previous conversation\"\n className=\"w-6 h-6 flex items-center justify-center text-text-body hover:text-black transition-colors bg-transparent border-0 cursor-pointer disabled:opacity-30 disabled:cursor-default\"\n >\n <UndoIcon />\n </button>\n <button\n type=\"button\"\n onClick={handleForward}\n disabled={!canGoForward}\n title=\"Go to next conversation\"\n aria-label=\"Go to next conversation\"\n className=\"w-6 h-6 flex items-center justify-center text-text-body hover:text-black transition-colors bg-transparent border-0 cursor-pointer disabled:opacity-30 disabled:cursor-default\"\n >\n <RedoIcon />\n </button>\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-[10px] ml-[10px] sm:ml-0 shrink-0\">\n {/*\n Keyboard hint. It used to sit inside the prompt field, which was the\n wrong home for it twice over: it competed with the placeholder for the\n same space, and it disappeared exactly when the reader engaged with\n the input — so the shortcut was only ever advertised to someone who\n was not using it. Here it sits with the other page-level affordances\n and stays legible while the reader types.\n\n `aria-hidden` because the shortcut is already announced on the input\n itself via `aria-keyshortcuts`; this is the visual reminder, and\n repeating it to assistive tech would just be noise.\n */}\n <span className=\"web5-prompt-hint\" aria-hidden=\"true\">\n Press <kbd className=\"web5-prompt-hint__key\">/</kbd> to search\n </span>\n {/* Share button — wraps button + tooltips in a relative container */}\n <div className=\"web5-user-query__action group relative\">\n <button\n type=\"button\"\n aria-label=\"Share this\"\n onClick={handleShare}\n disabled={isLoading || isCopied}\n className={`web5-user-query__share flex items-center gap-2 p-[6px] sm:px-[13px] sm:py-[5px] rounded-[30px] text-[13px] leading-5 border-0 cursor-pointer transition-colors disabled:cursor-default\n ${\n isCopied\n ? 'is-copied bg-[#2b2b2b] text-white'\n : 'text-text-body bg-white hover:bg-gray-50'\n }`}\n >\n {isCopied ? <CheckIcon /> : <ShareIcon />}\n <span className=\"hidden sm:inline\">\n {isLoading ? 'Sharing…' : isCopied ? copiedLabel : 'Share'}\n </span>\n </button>\n {/*\n Hover tooltip. Suppressed once the link is copied, because the\n copied state is its own message and two overlapping bubbles saying\n different things is worse than none.\n */}\n {!isCopied && (\n <span className=\"web5-user-query__tooltip\" role=\"tooltip\">\n Share this\n </span>\n )}\n {/* Mobile-only tooltip: drops below the button when link is copied */}\n {isCopied && (\n <div className=\"web5-user-query__copied-toast sm:hidden absolute top-full right-0 mt-1 flex items-center gap-2 bg-[#2b2b2b] text-white text-[12px] leading-none px-3 py-2 rounded-[8px] whitespace-nowrap\">\n <CheckIcon />\n {copiedLabel}\n </div>\n )}\n </div>\n {onNewConversation && (\n <div className=\"web5-user-query__action group relative\">\n <button\n type=\"button\"\n aria-label={newConversationLabel}\n onClick={handleNewConversation}\n className=\"web5-user-query__new-conversation flex items-center gap-2 p-[6px] sm:px-[13px] sm:py-[5px] rounded-[30px] text-[13px] leading-5 text-text-body bg-white border-0 cursor-pointer hover:bg-gray-50 transition-colors\"\n >\n <PlusIcon />\n <span className=\"hidden sm:inline\">{newConversationLabel}</span>\n </button>\n <span className=\"web5-user-query__tooltip\" role=\"tooltip\">\n {newConversationLabel}\n </span>\n </div>\n )}\n {onToggleCommentMode && (\n <button\n type=\"button\"\n onClick={onToggleCommentMode}\n aria-pressed={commentMode}\n title=\"Add a comment\"\n aria-label=\"Add a comment\"\n className={`relative flex items-center gap-2 p-[6px] sm:px-[13px] sm:py-[5px] rounded-[30px] text-[13px] leading-5 border-0 cursor-pointer transition-colors ${\n commentMode\n ? 'bg-[#2b2b2b] text-white'\n : 'text-text-body bg-white hover:bg-gray-50'\n }`}\n >\n <CommentIcon />\n {commentCount > 0 && (\n <span\n className={`absolute -top-1 -right-1 min-w-[18px] h-[18px] px-1 rounded-full text-[10px] leading-[18px] text-center font-semibold ${\n commentMode ? 'bg-white text-[#2b2b2b]' : 'bg-[#2b2b2b] text-white'\n }`}\n >\n {commentCount}\n </span>\n )}\n </button>\n )}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;AAAA,IAAAA,MAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,UAAA,GAAAD,OAAA;AACA,IAAAE,UAAA,GAAAF,OAAA;AACA,IAAAG,SAAA,GAAAH,OAAA;AACA,IAAAI,SAAA,GAAAJ,OAAA;AACA,IAAAK,SAAA,GAAAL,OAAA;AACA,IAAAM,YAAA,GAAAN,OAAA;AACA,IAAAO,gBAAA,GAAAP,OAAA;AAKqC,IAAAQ,YAAA;AAAA,SAAAT,wBAAAU,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAZ,uBAAA,YAAAA,CAAAU,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAIrC,MAAMkB,wBAAwB,GAAG,CAC/B,WAAW,EACX,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,yBAAyB,CAC1B;AAED,MAAMC,eAAe,GACnB,oJAAoJ;;AAUtJ;AACA;AACA;AACA;AACA;AACA;;AAyCO,MAAMC,SAA6B,GAAGA,CAAC;EAC5CC,KAAK;EACLC,iBAAiB;EACjBC,qBAAqB;EACrBC,oBAAoB;EACpBC,gBAAgB;EAChBC,OAAO;EACPC,mBAAmB;EACnBC,WAAW,GAAG,KAAK;EACnBC,YAAY,GAAG,CAAC;EAChBC,OAAO;EACPC,oBAAoB,GAAG,kBAAkB;EACzCC,WAAW,GAAG,aAAa;EAC3BC,gBAAgB,GAAG,IAAI;EACvBC,kBAAkB;EAClBC;AACF,CAAC,KAAK;EACJ,MAAMC,YAAY,GAAG,IAAAC,cAAO,EAAC,MAAM,IAAAC,gCAAe,EAAC,CAAC,EAAE,CAACb,gBAAgB,CAAC,CAAC;EACzE,MAAMc,YAAY,GAAGH,YAAY,CAACI,MAAM,GAAG,CAAC;EAC5C,MAAMC,SAAS,GAAG,CAAC,CAACjB,oBAAoB;EACxC,MAAMkB,aAAa,GAAGD,SAAS,IAAIF,YAAY;EAE/C,MAAMI,UAAU,GAAG,IAAAC,kBAAW,EAAC,MAAM;IACnC,IAAI,CAACpB,oBAAoB,IAAI,CAACC,gBAAgB,IAAI,CAACF,qBAAqB,EAAE;MACxE;IACF;IACA,IAAAsB,mCAAkB,EAACpB,gBAAgB,CAAC;IACpCF,qBAAqB,CAACC,oBAAoB,CAAC;EAC7C,CAAC,EAAE,CAACA,oBAAoB,EAAEC,gBAAgB,EAAEF,qBAAqB,CAAC,CAAC;EAEnE,MAAMuB,aAAa,GAAG,IAAAF,kBAAW,EAAC,MAAM;IACtC,IAAI,CAACrB,qBAAqB,EAAE;MAC1B;IACF;IACA,MAAMwB,OAAO,GAAG,IAAAC,oCAAmB,EAAC,CAAC;IACrC,IAAI,CAACD,OAAO,EAAE;MACZ;IACF;IACAxB,qBAAqB,CAACwB,OAAO,CAAC;EAChC,CAAC,EAAE,CAACxB,qBAAqB,CAAC,CAAC;EAE3B,MAAM0B,qBAAqB,GAAG,IAAAL,kBAAW,EAAC,MAAM;IAC9C,IAAAM,kCAAiB,EAAC,CAAC;IACnB5B,iBAAiB,YAAjBA,iBAAiB,CAAG,CAAC;EACvB,CAAC,EAAE,CAACA,iBAAiB,CAAC,CAAC;EAEvB,MAAM,CAAC6B,UAAU,EAAEC,aAAa,CAAC,GAAG,IAAAC,eAAQ,EAAa,MAAM,CAAC;EAEhE,MAAM,CAACC,iBAAiB,EAAEC,oBAAoB,CAAC,GAAG,IAAAF,eAAQ,EAAC,KAAK,CAAC;EACjE,IAAAG,gBAAS,EAAC,MAAM;IACdD,oBAAoB,CAAC,KAAK,CAAC;EAC7B,CAAC,EAAE,CAACrB,kBAAkB,oBAAlBA,kBAAkB,CAAEuB,QAAQ,CAAC,CAAC;EAElC,MAAMC,WAAW,GAAG,IAAAd,kBAAW,EAAC,YAAY;IAC1C,IAAIO,UAAU,KAAK,MAAM,EAAE;MACzB;IACF;IACAC,aAAa,CAAC,SAAS,CAAC;IACxB,IAAIO,SAAS,GAAGC,MAAM,CAACC,QAAQ,CAACC,IAAI;IACpC,IAAI;MACF,IAAIpC,OAAO,IAAID,gBAAgB,EAAE;QAC/BkC,SAAS,GAAG,MAAMjC,OAAO,CAACD,gBAAgB,CAAC;MAC7C;IACF,CAAC,CAAC,OAAOsC,GAAG,EAAE;MACZC,OAAO,CAACC,IAAI,CAAC,8CAA8C,EAAEF,GAAG,CAAC;IACnE;IACAG,SAAS,CAACC,SAAS,CAChBC,SAAS,CAACT,SAAS,CAAC,CACpBU,KAAK,CAAEN,GAAG,IAAKC,OAAO,CAACC,IAAI,CAAC,iCAAiC,EAAEF,GAAG,CAAC,CAAC;IACvEX,aAAa,CAAC,QAAQ,CAAC;IACvBkB,UAAU,CAAC,MAAMlB,aAAa,CAAC,MAAM,CAAC,EAAEnB,gBAAgB,CAAC;EAC3D,CAAC,EAAE,CAACkB,UAAU,EAAEzB,OAAO,EAAED,gBAAgB,EAAEQ,gBAAgB,CAAC,CAAC;EAE7D,MAAMsC,eAAe,GAAG,IAAAlC,cAAO,EAC7B,MACEP,OAAO,YAAPA,OAAO,CAAE0C,QAAQ,IAAI1C,OAAO,CAAC0C,QAAQ,CAAChC,MAAM,GAAG,CAAC,GAC5CV,OAAO,CAAC0C,QAAQ,GAChBtD,wBAAwB,EAC9B,CAACY,OAAO,oBAAPA,OAAO,CAAE0C,QAAQ,CACpB,CAAC;EACD,MAAM,CAACC,aAAa,EAAEC,gBAAgB,CAAC,GAAG,IAAArB,eAAQ,EAACkB,eAAe,CAAC,CAAC,CAAC,CAAC;EAEtE,IAAAf,gBAAS,EAAC,MAAM;IACd,IAAI,CAAC1B,OAAO,IAAIA,OAAO,CAAC6C,eAAe,EAAE;MACvC;IACF;IACAD,gBAAgB,CAACH,eAAe,CAAC,CAAC,CAAC,CAAC;IACpC,IAAIA,eAAe,CAAC/B,MAAM,IAAI,CAAC,EAAE;MAC/B;IACF;IACA,IAAIoC,KAAK,GAAG,CAAC;IACb,MAAMC,QAAQ,GAAGC,WAAW,CAAC,MAAM;MACjCF,KAAK,GAAG,CAACA,KAAK,GAAG,CAAC,IAAIL,eAAe,CAAC/B,MAAM;MAC5CkC,gBAAgB,CAACH,eAAe,CAACK,KAAK,CAAC,CAAC;IAC1C,CAAC,EAAE,IAAI,CAAC;IACR,OAAO,MAAMG,aAAa,CAACF,QAAQ,CAAC;EACtC,CAAC,EAAE,CAAC/C,OAAO,EAAEyC,eAAe,CAAC,CAAC;EAE9B,IAAI,CAAClD,KAAK,IAAI,CAACS,OAAO,EAAE;IACtB,OAAO,IAAI;EACb;EAEA,MAAMkD,QAAQ,GAAG7B,UAAU,KAAK,QAAQ;EACxC,MAAM8B,SAAS,GAAG9B,UAAU,KAAK,SAAS;EAE1C,MAAM+B,YAAY,GAAGhD,kBAAkB,GACnC,CAAC,MAAM;IACL,MAAM;MAAEiD,KAAK;MAAE1B,QAAQ;MAAE2B,OAAO;MAAEC;IAAM,CAAC,GAAGnD,kBAAkB;IAC9D,MAAMoD,eAAe,GAAG,CAAC,CAACF,OAAO,IAAI,CAAC,CAACjD,eAAe;IACtD,MAAMoD,OAAO,gBACXnG,MAAA,CAAAqB,OAAA,CAAA+E,aAAA,CAAApG,MAAA,CAAAqB,OAAA,CAAAgF,QAAA,qBACErG,MAAA,CAAAqB,OAAA,CAAA+E,aAAA,CAAC9F,SAAA,CAAAgG,QAAQ;MAACC,SAAS,EAAC,oCAAoC;MAAAC,MAAA;MAAAC,QAAA;QAAAC,QAAA,EAAAhG,YAAA;QAAAiG,UAAA;QAAAC,YAAA;MAAA;IAAA,CAAE,CAAC,EAC1DvC,QAAQ,IAAI,CAACH,iBAAiB,iBAC7BlE,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;MAAMG,SAAS,EAAC,qCAAqC;MAAAC,MAAA;MAAAC,QAAA;QAAAC,QAAA,EAAAhG,YAAA;QAAAiG,UAAA;QAAAC,YAAA;MAAA;IAAA,gBACnD5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;MACES,GAAG,EAAExC,QAAS;MACdyC,GAAG,EAAC,EAAE;MACNC,OAAO,EAAEA,CAAA,KAAM5C,oBAAoB,CAAC,IAAI,CAAE;MAAAqC,MAAA;MAAAC,QAAA;QAAAC,QAAA,EAAAhG,YAAA;QAAAiG,UAAA;QAAAC,YAAA;MAAA;IAAA,CAC3C,CACG,CACP,eACD5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;MAAMG,SAAS,EAAC,qCAAqC;MAAAC,MAAA;MAAAC,QAAA;QAAAC,QAAA,EAAAhG,YAAA;QAAAiG,UAAA;QAAAC,YAAA;MAAA;IAAA,GAAEb,KAAY,CACnE,CACH;IACD,OAAOG,eAAe,gBACpBlG,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;MACEY,IAAI,EAAC,QAAQ;MACbC,OAAO,EAAEA,CAAA,KAAMlE,eAAe,oBAAfA,eAAe,CAAGiD,OAAQ,CAAE;MAC3C,cAAYC,KAAK,IAAI,WAAWF,KAAK,EAAG;MACxCQ,SAAS,EAAC,+BAA+B;MAAAC,MAAA;MAAAC,QAAA;QAAAC,QAAA,EAAAhG,YAAA;QAAAiG,UAAA;QAAAC,YAAA;MAAA;IAAA,GAExCT,OACK,CAAC,gBAETnG,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;MAAKG,SAAS,EAAC,qEAAqE;MAAAC,MAAA;MAAAC,QAAA;QAAAC,QAAA,EAAAhG,YAAA;QAAAiG,UAAA;QAAAC,YAAA;MAAA;IAAA,GACjFT,OACE,CACN;EACH,CAAC,EAAE,CAAC,GACJ,IAAI;EAER,IAAIzD,OAAO,EAAE;IACX,MAAMwE,YAAY,GAAGxE,OAAO,CAAC6C,eAAe,IAAIF,aAAa;IAC7D,oBACErF,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;MACEG,SAAS,EAAExE,eAAgB;MAC3BoF,IAAI,EAAC,QAAQ;MACb,aAAU,MAAM;MAChB,aAAU,QAAQ;MAAAX,MAAA;MAAAC,QAAA;QAAAC,QAAA,EAAAhG,YAAA;QAAAiG,UAAA;QAAAC,YAAA;MAAA;IAAA,gBAElB5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;MAAKG,SAAS,EAAC,8BAA8B;MAAAC,MAAA;MAAAC,QAAA;QAAAC,QAAA,EAAAhG,YAAA;QAAAiG,UAAA;QAAAC,YAAA;MAAA;IAAA,GAC1Cd,YAAY,eACb9F,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;MACEG,SAAS,EAAC,qEAAqE;MAC/ER,KAAK,EAAE,WAAWrD,OAAO,CAAC0E,YAAY,EAAG;MAAAZ,MAAA;MAAAC,QAAA;QAAAC,QAAA,EAAAhG,YAAA;QAAAiG,UAAA;QAAAC,YAAA;MAAA;IAAA,gBAEzC5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;MAAMG,SAAS,EAAC,mBAAmB;MAAAC,MAAA;MAAAC,QAAA;QAAAC,QAAA,EAAAhG,YAAA;QAAAiG,UAAA;QAAAC,YAAA;MAAA;IAAA,GAAC,UAAc,CAAC,EAClDlE,OAAO,CAAC0E,YACR,CACA,CAAC,EACLF,YAAY,iBACXlH,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;MAAKG,SAAS,EAAC,8DAA8D;MAAAC,MAAA;MAAAC,QAAA;QAAAC,QAAA,EAAAhG,YAAA;QAAAiG,UAAA;QAAAC,YAAA;MAAA;IAAA,gBAC3E5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;MACEG,SAAS,EAAC,2IAA2I;MACrJ,eAAY,MAAM;MAAAC,MAAA;MAAAC,QAAA;QAAAC,QAAA,EAAAhG,YAAA;QAAAiG,UAAA;QAAAC,YAAA;MAAA;IAAA,CACnB,CAAC,eACF5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;MAAGG,SAAS,EAAC,gEAAgE;MAAAC,MAAA;MAAAC,QAAA;QAAAC,QAAA,EAAAhG,YAAA;QAAAiG,UAAA;QAAAC,YAAA;MAAA;IAAA,GAC1EM,YACA,CACA,CAEJ,CAAC;EAEV;EAEA,oBACElH,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAKG,SAAS,EAAExE,eAAgB;IAAAyE,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,gBAC9B5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAKG,SAAS,EAAC,6CAA6C;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,gBAC1D5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAKG,SAAS,EAAC,uBAAuB;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,GACnCd,YAAY,eACb9F,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IACEG,SAAS,EAAC,4FAA4F;IACtGR,KAAK,EAAE9D,KAAM;IAAAuE,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,GAEZ3E,KACA,CACA,CAAC,EACLqB,aAAa,iBACZtD,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAKG,SAAS,EAAC,6BAA6B;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,gBAC1C5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IACEY,IAAI,EAAC,QAAQ;IACbC,OAAO,EAAE1D,UAAW;IACpB8D,QAAQ,EAAE,CAAChE,SAAU;IACrB0C,KAAK,EAAC,6BAA6B;IACnC,cAAW,6BAA6B;IACxCQ,SAAS,EAAC,+KAA+K;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,gBAEzL5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA,CAAC9F,SAAA,CAAAgG,QAAQ;IAAAE,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,CAAE,CACL,CAAC,eACT5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IACEY,IAAI,EAAC,QAAQ;IACbC,OAAO,EAAEvD,aAAc;IACvB2D,QAAQ,EAAE,CAAClE,YAAa;IACxB4C,KAAK,EAAC,yBAAyB;IAC/B,cAAW,yBAAyB;IACpCQ,SAAS,EAAC,+KAA+K;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,gBAEzL5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA,CAAC7F,SAAA,CAAA+G,QAAQ;IAAAd,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,CAAE,CACL,CACL,CAEJ,CAAC,eACN5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAKG,SAAS,EAAC,yDAAyD;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,gBAatE5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAMG,SAAS,EAAC,kBAAkB;IAAC,eAAY,MAAM;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,GAAC,QAC9C,eAAA5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAKG,SAAS,EAAC,uBAAuB;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,GAAC,GAAM,CAAC,cAChD,CAAC,eAEP5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAKG,SAAS,EAAC,wCAAwC;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,gBACrD5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IACEY,IAAI,EAAC,QAAQ;IACb,cAAW,YAAY;IACvBC,OAAO,EAAE3C,WAAY;IACrB+C,QAAQ,EAAExB,SAAS,IAAID,QAAS;IAChCW,SAAS,EAAE;AACvB,gBACgBX,QAAQ,GACJ,mCAAmC,GACnC,0CAA0C,EAC7C;IAAAY,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,GAEJhB,QAAQ,gBAAG5F,MAAA,CAAAqB,OAAA,CAAA+E,aAAA,CAAChG,UAAA,CAAAmH,SAAS;IAAAf,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,CAAE,CAAC,gBAAG5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA,CAACjG,UAAA,CAAAqH,SAAS;IAAAhB,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,CAAE,CAAC,eACzC5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAMG,SAAS,EAAC,kBAAkB;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,GAC/Bf,SAAS,GAAG,UAAU,GAAGD,QAAQ,GAAGhD,WAAW,GAAG,OAC/C,CACA,CAAC,EAMR,CAACgD,QAAQ,iBACR5F,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAMG,SAAS,EAAC,0BAA0B;IAACY,IAAI,EAAC,SAAS;IAAAX,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,GAAC,YAEpD,CACP,EAEAhB,QAAQ,iBACP5F,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAKG,SAAS,EAAC,2LAA2L;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,gBACxM5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA,CAAChG,UAAA,CAAAmH,SAAS;IAAAf,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,CAAE,CAAC,EACZhE,WACE,CAEJ,CAAC,EACLV,iBAAiB,iBAChBlC,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAKG,SAAS,EAAC,wCAAwC;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,gBACrD5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IACEY,IAAI,EAAC,QAAQ;IACb,cAAYrE,oBAAqB;IACjCsE,OAAO,EAAEpD,qBAAsB;IAC/B0C,SAAS,EAAC,oNAAoN;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,gBAE9N5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA,CAAC/F,SAAA,CAAAoH,QAAQ;IAAAjB,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,CAAE,CAAC,eACZ5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAMG,SAAS,EAAC,kBAAkB;IAAAC,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,GAAEjE,oBAA2B,CACzD,CAAC,eACT3C,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IAAMG,SAAS,EAAC,0BAA0B;IAACY,IAAI,EAAC,SAAS;IAAAX,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,GACtDjE,oBACG,CACH,CACN,EACAJ,mBAAmB,iBAClBvC,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IACEY,IAAI,EAAC,QAAQ;IACbC,OAAO,EAAE1E,mBAAoB;IAC7B,gBAAcC,WAAY;IAC1BuD,KAAK,EAAC,eAAe;IACrB,cAAW,eAAe;IAC1BQ,SAAS,EAAE,oJACT/D,WAAW,GACP,yBAAyB,GACzB,0CAA0C,EAC7C;IAAAgE,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,gBAEH5G,MAAA,CAAAqB,OAAA,CAAA+E,aAAA,CAAC5F,YAAA,CAAAkH,WAAW;IAAAlB,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,CAAE,CAAC,EACdnE,YAAY,GAAG,CAAC,iBACfzC,MAAA,CAAAqB,OAAA,CAAA+E,aAAA;IACEG,SAAS,EAAE,yHACT/D,WAAW,GAAG,yBAAyB,GAAG,yBAAyB,EAClE;IAAAgE,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAhG,YAAA;MAAAiG,UAAA;MAAAC,YAAA;IAAA;EAAA,GAEFnE,YACG,CAEF,CAEP,CACF,CAAC;AAEV,CAAC;AAACkF,OAAA,CAAA3F,SAAA,GAAAA,SAAA","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_ShareIcon","_CheckIcon","_PlusIcon","_UndoIcon","_RedoIcon","_CommentIcon","_navigationStack","_jsxFileName","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","DEFAULT_LOADING_MESSAGES","headerClassName","UserQuery","query","onNewConversation","onNavigateToTriggerId","predecessorTriggerId","currentTriggerId","onShare","onToggleCommentMode","commentMode","commentCount","loading","newConversationLabel","copiedLabel","copiedDurationMs","productBackContext","onBackToProduct","forwardStack","useMemo","getForwardStack","canGoForward","length","canGoBack","hasNavigation","handleBack","useCallback","pushToForwardStack","handleForward","nextTid","popFromForwardStack","handleNewConversation","clearForwardStack","shareState","setShareState","useState","productImageError","setProductImageError","useEffect","imageUrl","handleShare","urlToCopy","window","location","href","err","console","warn","navigator","clipboard","writeText","catch","setTimeout","cyclingMessages","messages","cycledMessage","setCycledMessage","progressMessage","index","interval","setInterval","clearInterval","isCopied","isLoading","productBadge","title","backUrl","label","canNavigateBack","content","createElement","Fragment","UndoIcon","className","__self","__source","fileName","lineNumber","columnNumber","src","alt","onError","type","onClick","progressText","role","pendingQuery","disabled","RedoIcon","CheckIcon","ShareIcon","PlusIcon","CommentIcon","exports"],"sources":["../../../../src/components/ui/UserQuery.tsx"],"sourcesContent":["import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';\nimport { ShareIcon } from './icons/ShareIcon';\nimport { CheckIcon } from './icons/CheckIcon';\nimport { PlusIcon } from './icons/PlusIcon';\nimport { UndoIcon } from './icons/UndoIcon';\nimport { RedoIcon } from './icons/RedoIcon';\nimport { CommentIcon } from './icons/CommentIcon';\nimport {\n getForwardStack,\n pushToForwardStack,\n popFromForwardStack,\n clearForwardStack,\n} from '../../utils/navigationStack';\n\ntype ShareState = 'idle' | 'loading' | 'copied';\n\nconst DEFAULT_LOADING_MESSAGES = [\n 'Thinking…',\n 'Recognizing intent…',\n 'Connecting the dots…',\n 'Synthesizing insights…',\n 'Formulating a response…',\n];\n\nconst headerClassName =\n 'web5-user-query sticky top-0 z-10 flex items-center justify-between bg-white/60 backdrop-blur-sm pl-5 pr-[10px] py-[7px] sm:px-[30px] sm:py-[17px]';\n\nexport interface UserQueryLoadingState {\n pendingQuery: string;\n /** Static progress message. If omitted, falls back to cycling through `messages`. */\n progressMessage?: string;\n /** Messages cycled while loading when `progressMessage` is not set. */\n messages?: string[];\n}\n\n/**\n * Product the visitor was redirected from (DL #114). Rendered as a back badge\n * above the query: back arrow + thumbnail + product name. All fields are\n * resolved and validated app-side (allowed-domain `backUrl`, `https:`\n * `imageUrl`) before reaching this presentational component.\n */\nexport interface ProductBackContext {\n /** Product display name. Required — without it the badge does not render. */\n title: string;\n /** Validated product thumbnail URL. Omitted/failed to load → arrow + title only. */\n imageUrl?: string;\n /** Validated product-page URL to return to. Omitted → badge is non-clickable. */\n backUrl?: string;\n /** Accessible label override. Defaults to `Back to ${title}`. */\n label?: string;\n}\n\nexport interface UserQueryProps {\n query: string;\n onNewConversation?: () => void;\n onNavigateToTriggerId?: (triggerId: string) => void;\n predecessorTriggerId?: string;\n currentTriggerId?: string;\n onShare?: (triggerId: string) => Promise<string>;\n /** Optional comment-mode toggle. When provided, render the chat-bubble\n * toggle button next to Share. The button reflects `commentMode` via\n * `is-on` styling and `aria-pressed`. */\n onToggleCommentMode?: () => void;\n commentMode?: boolean;\n /** Total number of comments on this response — shown as a badge next to the\n * toggle when > 0. */\n commentCount?: number;\n loading?: UserQueryLoadingState;\n /** Label for the \"new conversation\" action. Defaults to \"New conversation\". */\n newConversationLabel?: string;\n /** Label shown after the share link is copied. Defaults to \"Link Copied\". */\n copiedLabel?: string;\n /** How long the copied state stays visible, in ms. Defaults to 2000. */\n copiedDurationMs?: number;\n /** When set (visitor arrived from a product page), render a back-to-product\n * badge above the query (DL #114). */\n productBackContext?: ProductBackContext;\n /** Invoked with the validated `backUrl` when the badge is activated. */\n onBackToProduct?: (backUrl: string) => void;\n}\n\nexport const UserQuery: FC<UserQueryProps> = ({\n query,\n onNewConversation,\n onNavigateToTriggerId,\n predecessorTriggerId,\n currentTriggerId,\n onShare,\n onToggleCommentMode,\n commentMode = false,\n commentCount = 0,\n loading,\n newConversationLabel = 'New conversation',\n copiedLabel = 'Link Copied',\n copiedDurationMs = 2000,\n productBackContext,\n onBackToProduct,\n}) => {\n const forwardStack = useMemo(() => getForwardStack(), [currentTriggerId]);\n const canGoForward = forwardStack.length > 0;\n const canGoBack = !!predecessorTriggerId;\n const hasNavigation = canGoBack || canGoForward;\n\n const handleBack = useCallback(() => {\n if (!predecessorTriggerId || !currentTriggerId || !onNavigateToTriggerId) {\n return;\n }\n pushToForwardStack(currentTriggerId);\n onNavigateToTriggerId(predecessorTriggerId);\n }, [predecessorTriggerId, currentTriggerId, onNavigateToTriggerId]);\n\n const handleForward = useCallback(() => {\n if (!onNavigateToTriggerId) {\n return;\n }\n const nextTid = popFromForwardStack();\n if (!nextTid) {\n return;\n }\n onNavigateToTriggerId(nextTid);\n }, [onNavigateToTriggerId]);\n\n const handleNewConversation = useCallback(() => {\n clearForwardStack();\n onNewConversation?.();\n }, [onNewConversation]);\n\n const [shareState, setShareState] = useState<ShareState>('idle');\n\n const [productImageError, setProductImageError] = useState(false);\n useEffect(() => {\n setProductImageError(false);\n }, [productBackContext?.imageUrl]);\n\n const handleShare = useCallback(async () => {\n if (shareState !== 'idle') {\n return;\n }\n setShareState('loading');\n let urlToCopy = window.location.href;\n try {\n if (onShare && currentTriggerId) {\n urlToCopy = await onShare(currentTriggerId);\n }\n } catch (err) {\n console.warn('[share] failed, falling back to current URL:', err);\n }\n navigator.clipboard\n .writeText(urlToCopy)\n .catch((err) => console.warn('[share] clipboard write failed:', err));\n setShareState('copied');\n setTimeout(() => setShareState('idle'), copiedDurationMs);\n }, [shareState, onShare, currentTriggerId, copiedDurationMs]);\n\n const cyclingMessages = useMemo(\n () =>\n loading?.messages && loading.messages.length > 0\n ? loading.messages\n : DEFAULT_LOADING_MESSAGES,\n [loading?.messages],\n );\n const [cycledMessage, setCycledMessage] = useState(cyclingMessages[0]);\n\n useEffect(() => {\n if (!loading || loading.progressMessage) {\n return;\n }\n setCycledMessage(cyclingMessages[0]);\n if (cyclingMessages.length <= 1) {\n return;\n }\n let index = 0;\n const interval = setInterval(() => {\n index = (index + 1) % cyclingMessages.length;\n setCycledMessage(cyclingMessages[index]);\n }, 4000);\n return () => clearInterval(interval);\n }, [loading, cyclingMessages]);\n\n if (!query && !loading) {\n return null;\n }\n\n const isCopied = shareState === 'copied';\n const isLoading = shareState === 'loading';\n\n const productBadge = productBackContext\n ? (() => {\n const { title, imageUrl, backUrl, label } = productBackContext;\n const canNavigateBack = !!backUrl && !!onBackToProduct;\n const content = (\n <>\n <UndoIcon className=\"web5-user-query__product-back-icon\" />\n {imageUrl && !productImageError && (\n <span className=\"web5-user-query__product-back-thumb\">\n <img\n src={imageUrl}\n alt=\"\"\n onError={() => setProductImageError(true)}\n />\n </span>\n )}\n <span className=\"web5-user-query__product-back-title\">{title}</span>\n </>\n );\n return canNavigateBack ? (\n <button\n type=\"button\"\n onClick={() => onBackToProduct?.(backUrl!)}\n aria-label={label ?? `Back to ${title}`}\n className=\"web5-user-query__product-back\"\n >\n {content}\n </button>\n ) : (\n <div className=\"web5-user-query__product-back web5-user-query__product-back--static\">\n {content}\n </div>\n );\n })()\n : null;\n\n if (loading) {\n const progressText = loading.progressMessage ?? cycledMessage;\n return (\n <div\n className={headerClassName}\n role=\"status\"\n aria-busy=\"true\"\n aria-live=\"polite\"\n >\n <div className=\"web5-user-query__left flex-1\">\n {productBadge}\n <p\n className=\"text-[14px] leading-5 text-text-body truncate min-w-0 max-w-[700px]\"\n title={`Asking: ${loading.pendingQuery}`}\n >\n <span className=\"text-text-body/70\">Asking: </span>\n {loading.pendingQuery}\n </p>\n </div>\n {progressText && (\n <div className=\"hidden sm:flex items-center gap-2 ml-[10px] shrink-0 min-w-0\">\n <div\n className=\"w-4 h-4 shrink-0 animate-spin inline-block border-[2px] border-current border-t-transparent text-blue-600 dark:text-blue-500 rounded-full\"\n aria-hidden=\"true\"\n />\n <p className=\"text-[13px] leading-5 text-text-body/70 truncate max-w-[240px]\">\n {progressText}\n </p>\n </div>\n )}\n </div>\n );\n }\n\n return (\n <div className={headerClassName}>\n <div className=\"flex items-center gap-[30px] flex-1 min-w-0\">\n <div className=\"web5-user-query__left\">\n {productBadge}\n <p\n className=\"web5-user-query__title text-[14px] leading-5 text-text-body truncate min-w-0 max-w-[700px]\"\n title={query}\n >\n {query}\n </p>\n </div>\n {hasNavigation && (\n <div className=\"flex items-center gap-[9px]\">\n <button\n type=\"button\"\n onClick={handleBack}\n disabled={!canGoBack}\n title=\"Go to previous conversation\"\n aria-label=\"Go to previous conversation\"\n className=\"w-6 h-6 flex items-center justify-center text-text-body hover:text-black transition-colors bg-transparent border-0 cursor-pointer disabled:opacity-30 disabled:cursor-default\"\n >\n <UndoIcon />\n </button>\n <button\n type=\"button\"\n onClick={handleForward}\n disabled={!canGoForward}\n title=\"Go to next conversation\"\n aria-label=\"Go to next conversation\"\n className=\"w-6 h-6 flex items-center justify-center text-text-body hover:text-black transition-colors bg-transparent border-0 cursor-pointer disabled:opacity-30 disabled:cursor-default\"\n >\n <RedoIcon />\n </button>\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-[10px] ml-[10px] sm:ml-0 shrink-0\">\n {/*\n Keyboard hint. It used to sit inside the prompt field, which was the\n wrong home for it twice over: it competed with the placeholder for the\n same space, and it disappeared exactly when the reader engaged with\n the input — so the shortcut was only ever advertised to someone who\n was not using it. Here it sits with the other page-level affordances\n and stays legible while the reader types.\n\n `aria-hidden` because the shortcut is already announced on the input\n itself via `aria-keyshortcuts`; this is the visual reminder, and\n repeating it to assistive tech would just be noise.\n */}\n <span className=\"web5-prompt-hint\" aria-hidden=\"true\">\n Press <kbd className=\"web5-prompt-hint__key\">/</kbd> to search\n </span>\n {/* Share button — wraps button + tooltips in a relative container */}\n <div className=\"web5-user-query__action group relative\">\n <button\n type=\"button\"\n aria-label=\"Share this\"\n onClick={handleShare}\n disabled={isLoading || isCopied}\n className={`web5-user-query__share flex items-center gap-2 p-[6px] sm:px-[13px] sm:py-[5px] rounded-[30px] text-[13px] leading-5 border-0 cursor-pointer transition-colors disabled:cursor-default\n ${\n isCopied\n ? 'is-copied bg-[#2b2b2b] text-white'\n : 'text-text-body bg-white hover:bg-gray-50'\n }`}\n >\n {isCopied ? <CheckIcon /> : <ShareIcon />}\n </button>\n {/*\n Hover tooltip — the only place this action is named now that the\n button is icon-only at every width. Shown solely while the share is\n idle: the status bubble below drops into the same slot, and two\n overlapping bubbles saying different things is worse than one.\n */}\n {shareState === 'idle' && (\n <span className=\"web5-user-query__tooltip\" role=\"tooltip\">\n Share this\n </span>\n )}\n {/*\n Status bubble — while the link is being built, and once it is on the\n clipboard. It used to be mobile-only, because the desktop button\n carried \"Sharing…\" / \"Link Copied\" in its own label; with the label\n gone this is the only thing reporting the outcome, so it shows at\n every width.\n */}\n {shareState !== 'idle' && (\n <div className=\"web5-user-query__copied-toast absolute top-full right-0 mt-1 flex items-center gap-2 bg-[#2b2b2b] text-white text-[12px] leading-none px-3 py-2 rounded-[8px] whitespace-nowrap\">\n {isCopied && <CheckIcon />}\n {isLoading ? 'Sharing…' : copiedLabel}\n </div>\n )}\n </div>\n {onNewConversation && (\n <div className=\"web5-user-query__action group relative\">\n <button\n type=\"button\"\n aria-label={newConversationLabel}\n onClick={handleNewConversation}\n className=\"web5-user-query__new-conversation flex items-center gap-2 p-[6px] sm:px-[13px] sm:py-[5px] rounded-[30px] text-[13px] leading-5 text-text-body bg-white border-0 cursor-pointer hover:bg-gray-50 transition-colors\"\n >\n <PlusIcon />\n </button>\n <span className=\"web5-user-query__tooltip\" role=\"tooltip\">\n {newConversationLabel}\n </span>\n </div>\n )}\n {onToggleCommentMode && (\n <button\n type=\"button\"\n onClick={onToggleCommentMode}\n aria-pressed={commentMode}\n title=\"Add a comment\"\n aria-label=\"Add a comment\"\n className={`relative flex items-center gap-2 p-[6px] sm:px-[13px] sm:py-[5px] rounded-[30px] text-[13px] leading-5 border-0 cursor-pointer transition-colors ${\n commentMode\n ? 'bg-[#2b2b2b] text-white'\n : 'text-text-body bg-white hover:bg-gray-50'\n }`}\n >\n <CommentIcon />\n {commentCount > 0 && (\n <span\n className={`absolute -top-1 -right-1 min-w-[18px] h-[18px] px-1 rounded-full text-[10px] leading-[18px] text-center font-semibold ${\n commentMode ? 'bg-white text-[#2b2b2b]' : 'bg-[#2b2b2b] text-white'\n }`}\n >\n {commentCount}\n </span>\n )}\n </button>\n )}\n </div>\n </div>\n );\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.ComponentDependenciesProvider = void 0;
|
|
5
5
|
exports.useComponentDependencies = useComponentDependencies;
|
|
6
|
+
exports.useOptionalComponentDependencies = useOptionalComponentDependencies;
|
|
6
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
7
8
|
var _jsxFileName = "/home/builduser/work/c2b6ca0b3fa984ee/packages/web5-core/dist/cjs/context/ComponentDependenciesContext.tsx";
|
|
8
9
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
@@ -14,6 +15,19 @@ function useComponentDependencies() {
|
|
|
14
15
|
}
|
|
15
16
|
return ctx;
|
|
16
17
|
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The same context, without the throw.
|
|
21
|
+
*
|
|
22
|
+
* For providers the HOST mounts around every section rather than a component
|
|
23
|
+
* opting in: those sit above trees that may legitimately have no dependencies
|
|
24
|
+
* configured — a layout test, a storybook story — and hard-crashing them would
|
|
25
|
+
* make an unrelated feature's provider a global requirement. A consumer that
|
|
26
|
+
* genuinely needs deps should still use `useComponentDependencies`.
|
|
27
|
+
*/
|
|
28
|
+
function useOptionalComponentDependencies() {
|
|
29
|
+
return (0, _react.useContext)(ComponentDependenciesContext);
|
|
30
|
+
}
|
|
17
31
|
const ComponentDependenciesProvider = ({
|
|
18
32
|
deps,
|
|
19
33
|
children
|
|
@@ -23,7 +37,7 @@ const ComponentDependenciesProvider = ({
|
|
|
23
37
|
__self: void 0,
|
|
24
38
|
__source: {
|
|
25
39
|
fileName: _jsxFileName,
|
|
26
|
-
lineNumber:
|
|
40
|
+
lineNumber: 44,
|
|
27
41
|
columnNumber: 5
|
|
28
42
|
}
|
|
29
43
|
}, children);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_jsxFileName","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ComponentDependenciesContext","createContext","useComponentDependencies","ctx","useContext","Error","ComponentDependenciesProvider","deps","children","createElement","Provider","value","__self","__source","fileName","lineNumber","columnNumber","exports"],"sources":["../../../src/context/ComponentDependenciesContext.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n type FC,\n type PropsWithChildren,\n} from 'react';\nimport type { ComponentDependencies } from '../types/dependencies';\n\nconst ComponentDependenciesContext =\n createContext<ComponentDependencies | null>(null);\n\nexport function useComponentDependencies(): ComponentDependencies {\n const ctx = useContext(ComponentDependenciesContext);\n if (!ctx) {\n throw new Error(\n 'useComponentDependencies must be used within a ComponentDependenciesProvider. ' +\n 'Wrap your app with <ComponentDependenciesProvider deps={...}>.',\n );\n }\n return ctx;\n}\n\nexport interface ComponentDependenciesProviderProps extends PropsWithChildren {\n deps: ComponentDependencies;\n}\n\nexport const ComponentDependenciesProvider: FC<\n ComponentDependenciesProviderProps\n> = ({ deps, children }) => {\n return (\n <ComponentDependenciesContext.Provider value={deps}>\n {children}\n </ComponentDependenciesContext.Provider>\n );\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_jsxFileName","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ComponentDependenciesContext","createContext","useComponentDependencies","ctx","useContext","Error","useOptionalComponentDependencies","ComponentDependenciesProvider","deps","children","createElement","Provider","value","__self","__source","fileName","lineNumber","columnNumber","exports"],"sources":["../../../src/context/ComponentDependenciesContext.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n type FC,\n type PropsWithChildren,\n} from 'react';\nimport type { ComponentDependencies } from '../types/dependencies';\n\nconst ComponentDependenciesContext =\n createContext<ComponentDependencies | null>(null);\n\nexport function useComponentDependencies(): ComponentDependencies {\n const ctx = useContext(ComponentDependenciesContext);\n if (!ctx) {\n throw new Error(\n 'useComponentDependencies must be used within a ComponentDependenciesProvider. ' +\n 'Wrap your app with <ComponentDependenciesProvider deps={...}>.',\n );\n }\n return ctx;\n}\n\n/**\n * The same context, without the throw.\n *\n * For providers the HOST mounts around every section rather than a component\n * opting in: those sit above trees that may legitimately have no dependencies\n * configured — a layout test, a storybook story — and hard-crashing them would\n * make an unrelated feature's provider a global requirement. A consumer that\n * genuinely needs deps should still use `useComponentDependencies`.\n */\nexport function useOptionalComponentDependencies(): ComponentDependencies | null {\n return useContext(ComponentDependenciesContext);\n}\n\nexport interface ComponentDependenciesProviderProps extends PropsWithChildren {\n deps: ComponentDependencies;\n}\n\nexport const ComponentDependenciesProvider: FC<\n ComponentDependenciesProviderProps\n> = ({ deps, children }) => {\n return (\n <ComponentDependenciesContext.Provider value={deps}>\n {children}\n </ComponentDependenciesContext.Provider>\n );\n};\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,uBAAA,CAAAC,OAAA;AAKe,IAAAC,YAAA;AAAA,SAAAF,wBAAAG,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAL,uBAAA,YAAAA,CAAAG,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAGf,MAAMkB,4BAA4B,gBAChC,IAAAC,oBAAa,EAA+B,IAAI,CAAC;AAE5C,SAASC,wBAAwBA,CAAA,EAA0B;EAChE,MAAMC,GAAG,GAAG,IAAAC,iBAAU,EAACJ,4BAA4B,CAAC;EACpD,IAAI,CAACG,GAAG,EAAE;IACR,MAAM,IAAIE,KAAK,CACb,gFAAgF,GAC9E,gEACJ,CAAC;EACH;EACA,OAAOF,GAAG;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASG,gCAAgCA,CAAA,EAAiC;EAC/E,OAAO,IAAAF,iBAAU,EAACJ,4BAA4B,CAAC;AACjD;AAMO,MAAMO,6BAEZ,GAAGA,CAAC;EAAEC,IAAI;EAAEC;AAAS,CAAC,KAAK;EAC1B,oBACEhC,MAAA,CAAAc,OAAA,CAAAmB,aAAA,CAACV,4BAA4B,CAACW,QAAQ;IAACC,KAAK,EAAEJ,IAAK;IAAAK,MAAA;IAAAC,QAAA;MAAAC,QAAA,EAAAnC,YAAA;MAAAoC,UAAA;MAAAC,YAAA;IAAA;EAAA,GAChDR,QACoC,CAAC;AAE5C,CAAC;AAACS,OAAA,CAAAX,6BAAA,GAAAA,6BAAA","ignoreList":[]}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.useImageSlotCollector = exports.ImageSlotProvider = void 0;
|
|
5
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
6
|
+
var _ComponentDependenciesContext = require("./ComponentDependenciesContext");
|
|
7
|
+
var _diagnosticTypes = require("../component/diagnosticTypes");
|
|
8
|
+
var _jsxFileName = "/home/builduser/work/c2b6ca0b3fa984ee/packages/web5-core/dist/cjs/context/ImageSlotContext.tsx";
|
|
9
|
+
/**
|
|
10
|
+
* The section-scoped image slot collector.
|
|
11
|
+
*
|
|
12
|
+
* A section declares the holes in its layout; it never makes a request. This
|
|
13
|
+
* gathers every declaration made inside one section's subtree, fires ONE
|
|
14
|
+
* `ResolveImageSet` through the injected port, and hands each declaration its
|
|
15
|
+
* answer back by `slotId`. Sections stay ignorant of each other — no section
|
|
16
|
+
* imports another, no ordering rules, no exclusion lists threaded through
|
|
17
|
+
* props — and the network still sees the joint solve that distinctness depends
|
|
18
|
+
* on.
|
|
19
|
+
*
|
|
20
|
+
* WHY THE BOUNDARY IS THE SECTION
|
|
21
|
+
* -------------------------------
|
|
22
|
+
* The resolver solves a maximum-weight one-to-one assignment across everything
|
|
23
|
+
* in one request, so distinctness and palette cohesion are properties of that
|
|
24
|
+
* solve and stop at its edge. Drawing the boundary at the page would buy
|
|
25
|
+
* cross-section distinctness at the cost of making every section's pictures
|
|
26
|
+
* wait on the slowest declaration on the page; drawing it at the section keeps
|
|
27
|
+
* each section independent and accepts that two sections may land on the same
|
|
28
|
+
* photograph. The most visible case — four identical photos in one grid — is
|
|
29
|
+
* still prevented for free, because those slots share a request.
|
|
30
|
+
*
|
|
31
|
+
* WHY THERE IS NO READINESS POLICY
|
|
32
|
+
* --------------------------------
|
|
33
|
+
* There is nothing to wait for. A section component is never constructed from
|
|
34
|
+
* partial markdown: a declared-but-unstreamed section is a `PageSection` with
|
|
35
|
+
* `isSkeleton: true` and `component: null`, and the real element is built only
|
|
36
|
+
* once its body has finished streaming. So a section's props are final the
|
|
37
|
+
* moment it exists, and the flush is simply "after this section's first render
|
|
38
|
+
* commit" — one effect, not a scheduler.
|
|
39
|
+
*
|
|
40
|
+
* The same fact bounds the win honestly: because only a *mounted* section
|
|
41
|
+
* declares, no section can ask for a picture before its own body has streamed,
|
|
42
|
+
* including a background whose subject needed nothing from that body.
|
|
43
|
+
*/
|
|
44
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
45
|
+
const ImageSlotContext = /*#__PURE__*/(0, _react.createContext)(null);
|
|
46
|
+
/**
|
|
47
|
+
* Mounted once per section by the host's section wrapper, so every section in
|
|
48
|
+
* every client package gets a collector without opting in.
|
|
49
|
+
*/
|
|
50
|
+
const ImageSlotProvider = ({
|
|
51
|
+
sectionId,
|
|
52
|
+
children
|
|
53
|
+
}) => {
|
|
54
|
+
// Optional on purpose: this is mounted by the host around EVERY section, so
|
|
55
|
+
// it sits above trees that may have no dependencies configured at all (a
|
|
56
|
+
// layout test, a story). Throwing there would make the image feature's
|
|
57
|
+
// provider a global requirement for rendering any section.
|
|
58
|
+
const deps = (0, _ComponentDependenciesContext.useOptionalComponentDependencies)();
|
|
59
|
+
const resolve = deps == null ? void 0 : deps.resolveImageSet;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Slot state lives in a ref, NOT in React state, and the context value never
|
|
63
|
+
* changes. Holding it in state put it inside the provider's value, so every
|
|
64
|
+
* resolution produced a new value and re-rendered every consumer in the
|
|
65
|
+
* section — free at one slot, twelve re-renders per resolution in a
|
|
66
|
+
* twelve-card grid, which is exactly the shape this boundary exists to serve.
|
|
67
|
+
* Consumers now subscribe to their own id and nothing else.
|
|
68
|
+
*/
|
|
69
|
+
const statesRef = (0, _react.useRef)({});
|
|
70
|
+
const listenersRef = (0, _react.useRef)(new Map());
|
|
71
|
+
|
|
72
|
+
// Declarations arriving during this commit. A ref, not state: collecting a
|
|
73
|
+
// declaration must not itself cause a render, or every hook that declares
|
|
74
|
+
// would re-render every sibling before the batch is even sent.
|
|
75
|
+
const pendingRef = (0, _react.useRef)(new Map());
|
|
76
|
+
// Ids already sent. A re-render re-declares the same content-derived id, and
|
|
77
|
+
// that must be a no-op rather than a second request.
|
|
78
|
+
const sentRef = (0, _react.useRef)(new Set());
|
|
79
|
+
const flushScheduled = (0, _react.useRef)(false);
|
|
80
|
+
const aliveRef = (0, _react.useRef)(true);
|
|
81
|
+
(0, _react.useEffect)(() => {
|
|
82
|
+
aliveRef.current = true;
|
|
83
|
+
return () => {
|
|
84
|
+
aliveRef.current = false;
|
|
85
|
+
};
|
|
86
|
+
}, []);
|
|
87
|
+
const publish = (0, _react.useCallback)(next => {
|
|
88
|
+
const changed = [];
|
|
89
|
+
for (const [id, state] of Object.entries(next)) {
|
|
90
|
+
if (statesRef.current[id] !== state) {
|
|
91
|
+
statesRef.current[id] = state;
|
|
92
|
+
changed.push(id);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
for (const id of changed) {
|
|
96
|
+
var _listenersRef$current;
|
|
97
|
+
(_listenersRef$current = listenersRef.current.get(id)) == null || _listenersRef$current.forEach(fn => fn());
|
|
98
|
+
}
|
|
99
|
+
}, []);
|
|
100
|
+
const markUnavailable = (0, _react.useCallback)(batch => {
|
|
101
|
+
if (!aliveRef.current) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
publish(Object.fromEntries(batch.map(s => [s.id, {
|
|
105
|
+
status: 'unavailable'
|
|
106
|
+
}])));
|
|
107
|
+
}, [publish]);
|
|
108
|
+
const flush = (0, _react.useCallback)(async () => {
|
|
109
|
+
flushScheduled.current = false;
|
|
110
|
+
const batch = [...pendingRef.current.values()].filter(s => !sentRef.current.has(s.id));
|
|
111
|
+
pendingRef.current.clear();
|
|
112
|
+
if (batch.length === 0) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
batch.forEach(s => sentRef.current.add(s.id));
|
|
116
|
+
|
|
117
|
+
// No port means the host has not injected a resolver. Fail the batch closed
|
|
118
|
+
// rather than silently leaving slots pending forever.
|
|
119
|
+
if (!resolve) {
|
|
120
|
+
markUnavailable(batch);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
const res = await resolve(batch);
|
|
125
|
+
if (!aliveRef.current) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const bySlotId = new Map(res.slots.map(s => [s.slotId, s]));
|
|
129
|
+
const next = {};
|
|
130
|
+
for (const req of batch) {
|
|
131
|
+
const got = bySlotId.get(req.id);
|
|
132
|
+
// A slot the resolver could not fill comes back with a null url. That
|
|
133
|
+
// is `unavailable` to a layout, not a resolved picture.
|
|
134
|
+
next[req.id] = got && got.imageUrl ? {
|
|
135
|
+
status: 'resolved',
|
|
136
|
+
slot: got
|
|
137
|
+
} : {
|
|
138
|
+
status: 'unavailable'
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
publish(next);
|
|
142
|
+
} catch (err) {
|
|
143
|
+
// Failure is contained to this section: one bad request costs this
|
|
144
|
+
// section its pictures and nothing else on the page.
|
|
145
|
+
deps == null || deps.reportDiagnostic == null || deps.reportDiagnostic(_diagnosticTypes.DIAGNOSTIC_TYPES.IMAGE_RESOLUTION_FAILED, sectionId, `ResolveImageSet failed for ${batch.length} slot(s): ${err instanceof Error ? err.message : String(err)}`);
|
|
146
|
+
markUnavailable(batch);
|
|
147
|
+
}
|
|
148
|
+
}, [resolve, deps, sectionId, publish, markUnavailable]);
|
|
149
|
+
const declare = (0, _react.useCallback)(slot => {
|
|
150
|
+
if (sentRef.current.has(slot.id)) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
pendingRef.current.set(slot.id, slot);
|
|
154
|
+
// Flush on a microtask, so every declaration made during this commit —
|
|
155
|
+
// the background, the cards, an inline image — lands in the same batch.
|
|
156
|
+
if (!flushScheduled.current) {
|
|
157
|
+
flushScheduled.current = true;
|
|
158
|
+
queueMicrotask(() => {
|
|
159
|
+
void flush();
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}, [flush]);
|
|
163
|
+
const read = (0, _react.useCallback)(slotId => statesRef.current[slotId] ?? {
|
|
164
|
+
status: 'pending'
|
|
165
|
+
}, []);
|
|
166
|
+
const subscribe = (0, _react.useCallback)((slotId, onChange) => {
|
|
167
|
+
let set = listenersRef.current.get(slotId);
|
|
168
|
+
if (!set) {
|
|
169
|
+
set = new Set();
|
|
170
|
+
listenersRef.current.set(slotId, set);
|
|
171
|
+
}
|
|
172
|
+
set.add(onChange);
|
|
173
|
+
return () => {
|
|
174
|
+
var _set;
|
|
175
|
+
(_set = set) == null || _set.delete(onChange);
|
|
176
|
+
if (set && set.size === 0) {
|
|
177
|
+
listenersRef.current.delete(slotId);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}, []);
|
|
181
|
+
|
|
182
|
+
// Stable for the provider's lifetime: every member is a `useCallback` with no
|
|
183
|
+
// reactive deps, so mounting this around a section costs its consumers
|
|
184
|
+
// nothing after first render.
|
|
185
|
+
const api = (0, _react.useMemo)(() => ({
|
|
186
|
+
declare,
|
|
187
|
+
read,
|
|
188
|
+
subscribe
|
|
189
|
+
}), [declare, read, subscribe]);
|
|
190
|
+
return /*#__PURE__*/_react.default.createElement(ImageSlotContext.Provider, {
|
|
191
|
+
value: api,
|
|
192
|
+
__self: void 0,
|
|
193
|
+
__source: {
|
|
194
|
+
fileName: _jsxFileName,
|
|
195
|
+
lineNumber: 236,
|
|
196
|
+
columnNumber: 5
|
|
197
|
+
}
|
|
198
|
+
}, children);
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Null when no provider is mounted above — a host that has not adopted the
|
|
203
|
+
* section wrapper's collector. `useImageSlot` handles that by resolving each
|
|
204
|
+
* slot on its own, so a section still gets its picture and only loses batching
|
|
205
|
+
* with its siblings.
|
|
206
|
+
*/
|
|
207
|
+
exports.ImageSlotProvider = ImageSlotProvider;
|
|
208
|
+
const useImageSlotCollector = () => (0, _react.useContext)(ImageSlotContext);
|
|
209
|
+
exports.useImageSlotCollector = useImageSlotCollector;
|
|
210
|
+
//# sourceMappingURL=ImageSlotContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_ComponentDependenciesContext","_diagnosticTypes","_jsxFileName","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ImageSlotContext","createContext","ImageSlotProvider","sectionId","children","deps","useOptionalComponentDependencies","resolve","resolveImageSet","statesRef","useRef","listenersRef","Map","pendingRef","sentRef","Set","flushScheduled","aliveRef","useEffect","current","publish","useCallback","next","changed","id","state","entries","push","_listenersRef$current","forEach","fn","markUnavailable","batch","fromEntries","map","s","status","flush","values","filter","clear","length","add","res","bySlotId","slots","slotId","req","got","imageUrl","slot","err","reportDiagnostic","DIAGNOSTIC_TYPES","IMAGE_RESOLUTION_FAILED","Error","message","String","declare","queueMicrotask","read","subscribe","onChange","_set","delete","size","api","useMemo","createElement","Provider","value","__self","__source","fileName","lineNumber","columnNumber","exports","useImageSlotCollector","useContext"],"sources":["../../../src/context/ImageSlotContext.tsx"],"sourcesContent":["/**\n * The section-scoped image slot collector.\n *\n * A section declares the holes in its layout; it never makes a request. This\n * gathers every declaration made inside one section's subtree, fires ONE\n * `ResolveImageSet` through the injected port, and hands each declaration its\n * answer back by `slotId`. Sections stay ignorant of each other — no section\n * imports another, no ordering rules, no exclusion lists threaded through\n * props — and the network still sees the joint solve that distinctness depends\n * on.\n *\n * WHY THE BOUNDARY IS THE SECTION\n * -------------------------------\n * The resolver solves a maximum-weight one-to-one assignment across everything\n * in one request, so distinctness and palette cohesion are properties of that\n * solve and stop at its edge. Drawing the boundary at the page would buy\n * cross-section distinctness at the cost of making every section's pictures\n * wait on the slowest declaration on the page; drawing it at the section keeps\n * each section independent and accepts that two sections may land on the same\n * photograph. The most visible case — four identical photos in one grid — is\n * still prevented for free, because those slots share a request.\n *\n * WHY THERE IS NO READINESS POLICY\n * --------------------------------\n * There is nothing to wait for. A section component is never constructed from\n * partial markdown: a declared-but-unstreamed section is a `PageSection` with\n * `isSkeleton: true` and `component: null`, and the real element is built only\n * once its body has finished streaming. So a section's props are final the\n * moment it exists, and the flush is simply \"after this section's first render\n * commit\" — one effect, not a scheduler.\n *\n * The same fact bounds the win honestly: because only a *mounted* section\n * declares, no section can ask for a picture before its own body has streamed,\n * including a background whose subject needed nothing from that body.\n */\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\nimport { useOptionalComponentDependencies } from './ComponentDependenciesContext';\nimport { DIAGNOSTIC_TYPES } from '../component/diagnosticTypes';\nimport type {\n ImageSlotRequest,\n SlotState,\n} from '../image/imageSlotTypes';\n\nexport interface ImageSlotCollector {\n /** Register a slot for this batch. Idempotent per content-derived id. */\n declare: (slot: ImageSlotRequest) => void;\n /** Current state for one slot. Not reactive alone — pair with `subscribe`. */\n read: (slotId: string) => SlotState;\n /** Notify only when THIS slot changes. Returns an unsubscribe. */\n subscribe: (slotId: string, onChange: () => void) => () => void;\n}\n\nconst ImageSlotContext = createContext<ImageSlotCollector | null>(null);\n\nexport interface ImageSlotProviderProps {\n /** Identifies the section in diagnostics. */\n sectionId: string;\n children: React.ReactNode;\n}\n\n/**\n * Mounted once per section by the host's section wrapper, so every section in\n * every client package gets a collector without opting in.\n */\nexport const ImageSlotProvider: React.FC<ImageSlotProviderProps> = ({\n sectionId,\n children,\n}) => {\n // Optional on purpose: this is mounted by the host around EVERY section, so\n // it sits above trees that may have no dependencies configured at all (a\n // layout test, a story). Throwing there would make the image feature's\n // provider a global requirement for rendering any section.\n const deps = useOptionalComponentDependencies();\n const resolve = deps?.resolveImageSet;\n\n /**\n * Slot state lives in a ref, NOT in React state, and the context value never\n * changes. Holding it in state put it inside the provider's value, so every\n * resolution produced a new value and re-rendered every consumer in the\n * section — free at one slot, twelve re-renders per resolution in a\n * twelve-card grid, which is exactly the shape this boundary exists to serve.\n * Consumers now subscribe to their own id and nothing else.\n */\n const statesRef = useRef<Record<string, SlotState>>({});\n const listenersRef = useRef<Map<string, Set<() => void>>>(new Map());\n\n // Declarations arriving during this commit. A ref, not state: collecting a\n // declaration must not itself cause a render, or every hook that declares\n // would re-render every sibling before the batch is even sent.\n const pendingRef = useRef<Map<string, ImageSlotRequest>>(new Map());\n // Ids already sent. A re-render re-declares the same content-derived id, and\n // that must be a no-op rather than a second request.\n const sentRef = useRef<Set<string>>(new Set());\n const flushScheduled = useRef(false);\n const aliveRef = useRef(true);\n\n useEffect(() => {\n aliveRef.current = true;\n return () => {\n aliveRef.current = false;\n };\n }, []);\n\n const publish = useCallback((next: Record<string, SlotState>) => {\n const changed: string[] = [];\n for (const [id, state] of Object.entries(next)) {\n if (statesRef.current[id] !== state) {\n statesRef.current[id] = state;\n changed.push(id);\n }\n }\n for (const id of changed) {\n listenersRef.current.get(id)?.forEach((fn) => fn());\n }\n }, []);\n\n const markUnavailable = useCallback(\n (batch: ImageSlotRequest[]) => {\n if (!aliveRef.current) {\n return;\n }\n publish(\n Object.fromEntries(\n batch.map((s) => [s.id, { status: 'unavailable' } as SlotState]),\n ),\n );\n },\n [publish],\n );\n\n const flush = useCallback(async () => {\n flushScheduled.current = false;\n\n const batch = [...pendingRef.current.values()].filter(\n (s) => !sentRef.current.has(s.id),\n );\n pendingRef.current.clear();\n if (batch.length === 0) {\n return;\n }\n batch.forEach((s) => sentRef.current.add(s.id));\n\n // No port means the host has not injected a resolver. Fail the batch closed\n // rather than silently leaving slots pending forever.\n if (!resolve) {\n markUnavailable(batch);\n return;\n }\n\n try {\n const res = await resolve(batch);\n if (!aliveRef.current) {\n return;\n }\n const bySlotId = new Map(res.slots.map((s) => [s.slotId, s]));\n const next: Record<string, SlotState> = {};\n for (const req of batch) {\n const got = bySlotId.get(req.id);\n // A slot the resolver could not fill comes back with a null url. That\n // is `unavailable` to a layout, not a resolved picture.\n next[req.id] =\n got && got.imageUrl\n ? { status: 'resolved', slot: got }\n : { status: 'unavailable' };\n }\n publish(next);\n } catch (err) {\n // Failure is contained to this section: one bad request costs this\n // section its pictures and nothing else on the page.\n deps?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.IMAGE_RESOLUTION_FAILED,\n sectionId,\n `ResolveImageSet failed for ${batch.length} slot(s): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n markUnavailable(batch);\n }\n }, [resolve, deps, sectionId, publish, markUnavailable]);\n\n const declare = useCallback(\n (slot: ImageSlotRequest) => {\n if (sentRef.current.has(slot.id)) {\n return;\n }\n pendingRef.current.set(slot.id, slot);\n // Flush on a microtask, so every declaration made during this commit —\n // the background, the cards, an inline image — lands in the same batch.\n if (!flushScheduled.current) {\n flushScheduled.current = true;\n queueMicrotask(() => {\n void flush();\n });\n }\n },\n [flush],\n );\n\n const read = useCallback(\n (slotId: string): SlotState =>\n statesRef.current[slotId] ?? { status: 'pending' },\n [],\n );\n\n const subscribe = useCallback((slotId: string, onChange: () => void) => {\n let set = listenersRef.current.get(slotId);\n if (!set) {\n set = new Set();\n listenersRef.current.set(slotId, set);\n }\n set.add(onChange);\n return () => {\n set?.delete(onChange);\n if (set && set.size === 0) {\n listenersRef.current.delete(slotId);\n }\n };\n }, []);\n\n // Stable for the provider's lifetime: every member is a `useCallback` with no\n // reactive deps, so mounting this around a section costs its consumers\n // nothing after first render.\n const api = useMemo<ImageSlotCollector>(\n () => ({ declare, read, subscribe }),\n [declare, read, subscribe],\n );\n\n return (\n <ImageSlotContext.Provider value={api}>{children}</ImageSlotContext.Provider>\n );\n};\n\n/**\n * Null when no provider is mounted above — a host that has not adopted the\n * section wrapper's collector. `useImageSlot` handles that by resolving each\n * slot on its own, so a section still gets its picture and only loses batching\n * with its siblings.\n */\nexport const useImageSlotCollector = (): ImageSlotCollector | null =>\n useContext(ImageSlotContext);\n"],"mappings":"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","ignoreList":[]}
|