@strapi/content-type-builder 5.58.0 → 5.59.0
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/admin/components/AIChat/FeedbackModal.js +13 -7
- package/dist/admin/components/AIChat/FeedbackModal.js.map +1 -1
- package/dist/admin/components/AIChat/FeedbackModal.mjs +14 -8
- package/dist/admin/components/AIChat/FeedbackModal.mjs.map +1 -1
- package/dist/admin/components/AIChat/UploadCodeModal.js +12 -6
- package/dist/admin/components/AIChat/UploadCodeModal.js.map +1 -1
- package/dist/admin/components/AIChat/UploadCodeModal.mjs +13 -7
- package/dist/admin/components/AIChat/UploadCodeModal.mjs.map +1 -1
- package/dist/admin/components/AIChat/UploadFigmaModal.js +12 -6
- package/dist/admin/components/AIChat/UploadFigmaModal.js.map +1 -1
- package/dist/admin/components/AIChat/UploadFigmaModal.mjs +13 -7
- package/dist/admin/components/AIChat/UploadFigmaModal.mjs.map +1 -1
- package/dist/admin/components/AIChat/components/Attachments/components/Attachment.js +6 -3
- package/dist/admin/components/AIChat/components/Attachments/components/Attachment.js.map +1 -1
- package/dist/admin/components/AIChat/components/Attachments/components/Attachment.mjs +7 -4
- package/dist/admin/components/AIChat/components/Attachments/components/Attachment.mjs.map +1 -1
- package/dist/admin/components/AIChat/components/Collapsible.js +9 -4
- package/dist/admin/components/AIChat/components/Collapsible.js.map +1 -1
- package/dist/admin/components/AIChat/components/Collapsible.mjs +10 -5
- package/dist/admin/components/AIChat/components/Collapsible.mjs.map +1 -1
- package/dist/admin/components/AIChat/components/Dropzone.js +13 -6
- package/dist/admin/components/AIChat/components/Dropzone.js.map +1 -1
- package/dist/admin/components/AIChat/components/Dropzone.mjs +14 -7
- package/dist/admin/components/AIChat/components/Dropzone.mjs.map +1 -1
- package/dist/admin/components/AIChat/components/FloatingPanel.js +11 -4
- package/dist/admin/components/AIChat/components/FloatingPanel.js.map +1 -1
- package/dist/admin/components/AIChat/components/FloatingPanel.mjs +12 -5
- package/dist/admin/components/AIChat/components/FloatingPanel.mjs.map +1 -1
- package/dist/admin/components/AIChat/components/FullScreenImage.js +16 -8
- package/dist/admin/components/AIChat/components/FullScreenImage.js.map +1 -1
- package/dist/admin/components/AIChat/components/FullScreenImage.mjs +17 -9
- package/dist/admin/components/AIChat/components/FullScreenImage.mjs.map +1 -1
- package/dist/admin/components/AIChat/components/Input.js +6 -3
- package/dist/admin/components/AIChat/components/Input.js.map +1 -1
- package/dist/admin/components/AIChat/components/Input.mjs +7 -4
- package/dist/admin/components/AIChat/components/Input.mjs.map +1 -1
- package/dist/admin/components/AIChat/components/Messages/Message.js +88 -12
- package/dist/admin/components/AIChat/components/Messages/Message.js.map +1 -1
- package/dist/admin/components/AIChat/components/Messages/Message.mjs +87 -13
- package/dist/admin/components/AIChat/components/Messages/Message.mjs.map +1 -1
- package/dist/admin/components/AIChat/components/StepModal.js +44 -17
- package/dist/admin/components/AIChat/components/StepModal.js.map +1 -1
- package/dist/admin/components/AIChat/components/StepModal.mjs +45 -18
- package/dist/admin/components/AIChat/components/StepModal.mjs.map +1 -1
- package/dist/admin/components/AIChat/providers/ChatProvider.js +79 -27
- package/dist/admin/components/AIChat/providers/ChatProvider.js.map +1 -1
- package/dist/admin/components/AIChat/providers/ChatProvider.mjs +80 -28
- package/dist/admin/components/AIChat/providers/ChatProvider.mjs.map +1 -1
- package/dist/admin/components/AIChat/providers/SchemaProvider.js +6 -3
- package/dist/admin/components/AIChat/providers/SchemaProvider.js.map +1 -1
- package/dist/admin/components/AIChat/providers/SchemaProvider.mjs +7 -4
- package/dist/admin/components/AIChat/providers/SchemaProvider.mjs.map +1 -1
- package/dist/admin/components/AttributeOptions/AttributeOption.js +2 -2
- package/dist/admin/components/AttributeOptions/AttributeOption.js.map +1 -1
- package/dist/admin/components/AttributeOptions/AttributeOption.mjs +2 -2
- package/dist/admin/components/AttributeOptions/AttributeOption.mjs.map +1 -1
- package/dist/admin/components/ContentTypeBuilderNav/lib/buildFolderTree.js.map +1 -1
- package/dist/admin/components/ContentTypeBuilderNav/lib/buildFolderTree.mjs.map +1 -1
- package/dist/admin/components/ContentTypeBuilderNav/lib/dropProjection.js.map +1 -1
- package/dist/admin/components/ContentTypeBuilderNav/lib/dropProjection.mjs.map +1 -1
- package/dist/admin/components/CustomRadioGroup/CustomRadioGroup.js +2 -1
- package/dist/admin/components/CustomRadioGroup/CustomRadioGroup.js.map +1 -1
- package/dist/admin/components/CustomRadioGroup/CustomRadioGroup.mjs +2 -1
- package/dist/admin/components/CustomRadioGroup/CustomRadioGroup.mjs.map +1 -1
- package/dist/admin/components/DataManager/DataManagerProvider.js +317 -275
- package/dist/admin/components/DataManager/DataManagerProvider.js.map +1 -1
- package/dist/admin/components/DataManager/DataManagerProvider.mjs +319 -277
- package/dist/admin/components/DataManager/DataManagerProvider.mjs.map +1 -1
- package/dist/admin/components/DataManager/RenameMigrationModal.js.map +1 -1
- package/dist/admin/components/DataManager/RenameMigrationModal.mjs.map +1 -1
- package/dist/admin/components/DataManager/reducer.js +31 -4
- package/dist/admin/components/DataManager/reducer.js.map +1 -1
- package/dist/admin/components/DataManager/reducer.mjs +31 -4
- package/dist/admin/components/DataManager/reducer.mjs.map +1 -1
- package/dist/admin/components/DynamicZoneList.js +2 -1
- package/dist/admin/components/DynamicZoneList.js.map +1 -1
- package/dist/admin/components/DynamicZoneList.mjs +2 -1
- package/dist/admin/components/DynamicZoneList.mjs.map +1 -1
- package/dist/admin/components/FormModal/attributes/ConditionForm.js +2 -1
- package/dist/admin/components/FormModal/attributes/ConditionForm.js.map +1 -1
- package/dist/admin/components/FormModal/attributes/ConditionForm.mjs +2 -1
- package/dist/admin/components/FormModal/attributes/ConditionForm.mjs.map +1 -1
- package/dist/admin/components/FormModal/attributes/types.js +2 -2
- package/dist/admin/components/FormModal/attributes/types.js.map +1 -1
- package/dist/admin/components/FormModal/attributes/types.mjs +2 -2
- package/dist/admin/components/FormModal/attributes/types.mjs.map +1 -1
- package/dist/admin/components/FormModal/forms/forms.js +1 -1
- package/dist/admin/components/FormModal/forms/forms.js.map +1 -1
- package/dist/admin/components/FormModal/forms/forms.mjs +1 -1
- package/dist/admin/components/FormModal/forms/forms.mjs.map +1 -1
- package/dist/admin/components/GenericInputs.js +2 -1
- package/dist/admin/components/GenericInputs.js.map +1 -1
- package/dist/admin/components/GenericInputs.mjs +2 -1
- package/dist/admin/components/GenericInputs.mjs.map +1 -1
- package/dist/admin/components/TabForm.js.map +1 -1
- package/dist/admin/components/TabForm.mjs.map +1 -1
- package/dist/admin/src/components/AIChat/components/FullScreenImage.d.ts +8 -0
- package/dist/admin/src/components/AIChat/components/Messages/Message.d.ts +20 -0
- package/dist/admin/utils/folderTelemetry.js.map +1 -1
- package/dist/admin/utils/folderTelemetry.mjs.map +1 -1
- package/dist/admin/utils/formAPI.js.map +1 -1
- package/dist/admin/utils/formAPI.mjs.map +1 -1
- package/dist/server/controllers/validation/schema.js +3 -2
- package/dist/server/controllers/validation/schema.js.map +1 -1
- package/dist/server/controllers/validation/schema.mjs +4 -3
- package/dist/server/controllers/validation/schema.mjs.map +1 -1
- package/dist/server/register.js.map +1 -1
- package/dist/server/register.mjs.map +1 -1
- package/dist/server/services/migration-builder/index.js.map +1 -1
- package/dist/server/services/migration-builder/index.mjs.map +1 -1
- package/dist/server/services/schema.js +34 -1
- package/dist/server/services/schema.js.map +1 -1
- package/dist/server/services/schema.mjs +34 -1
- package/dist/server/services/schema.mjs.map +1 -1
- package/dist/server/src/controllers/validation/schema.d.ts.map +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/services/migration-builder/index.d.ts.map +1 -1
- package/dist/server/src/services/schema-builder/types.d.ts.map +1 -1
- package/dist/server/src/services/schema.d.ts.map +1 -1
- package/dist/server/src/utils/uid-target.d.ts +18 -0
- package/dist/server/src/utils/uid-target.d.ts.map +1 -0
- package/dist/server/utils/uid-target.js +34 -0
- package/dist/server/utils/uid-target.js.map +1 -0
- package/dist/server/utils/uid-target.mjs +31 -0
- package/dist/server/utils/uid-target.mjs.map +1 -0
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FullScreenImage.js","sources":["../../../../../admin/src/components/AIChat/components/FullScreenImage.tsx"],"sourcesContent":["import { useEffect, useRef, createContext, useContext, useState, ReactNode } from 'react';\n\nimport { createPortal } from 'react-dom';\nimport { styled } from 'styled-components';\n\nimport { ANIMATIONS } from './animations';\nimport { Base64Img } from './Base64Image';\n\n/* -------------------------------------------------------------------------------------------------\n * Context\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FullScreenImageContextType {\n isOpen: boolean;\n open: () => void;\n close: () => void;\n src: string;\n alt: string;\n}\n\nconst FullScreenImageContext = createContext<FullScreenImageContextType | undefined>(undefined);\n\n/* -------------------------------------------------------------------------------------------------\n * Types\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FullScreenImageProps {\n src: string;\n alt: string;\n onClose?: () => void;\n}\n\ninterface FullScreenImageRootProps extends FullScreenImageProps {\n children: ReactNode;\n defaultOpen?: boolean;\n}\n\ninterface FullScreenImageTriggerProps {\n children: ReactNode;\n asChild?: boolean;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Styles\n * -----------------------------------------------------------------------------------------------*/\nexport const setOpacity = (hex: string, alpha: number) =>\n `${hex}${Math.floor(alpha * 255)\n .toString(16)\n .padStart(2, '0')}`;\n\nconst Overlay = styled.div`\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n width: 100vw;\n height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 500;\n pointer-events: auto; /* Explicitly enable pointer events */\n background: ${(props) => setOpacity(props.theme.colors.neutral800, 0.2)};\n`;\n\nconst ImageWrapper = styled.div`\n max-width: 80vw;\n max-height: 90vh;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: auto; /* Explicitly enable pointer events */\n position: relative;\n animation: ${ANIMATIONS.scaleIn} 0.3s ease;\n`;\n\nconst StyledImg = styled(Base64Img)`\n max-width: 100%;\n max-height: 90vh;\n object-fit: contain;\n pointer-events: auto; /* Explicitly enable pointer events */\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Modal\n * -----------------------------------------------------------------------------------------------*/\n\n// Use the existing FullScreenImage as our modal component\nconst ImageModal = ({ src, alt, onClose }: FullScreenImageProps) => {\n const overlayRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n // Close on ESC key press\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n // Stop propagation to prevent closing parent modals\n e.preventDefault();\n e.stopPropagation();\n onClose?.();\n\n // The next 3 lines are critical: they completely stop the event\n e.stopImmediatePropagation();\n e.cancelBubble = true; // For older browsers\n return false;\n }\n };\n\n // Use capture phase to intercept event before it reaches other components\n window.addEventListener('keydown', handleKeyDown, true);\n return () => window.removeEventListener('keydown', handleKeyDown, true);\n }, [onClose]);\n\n // Setup click handlers\n useEffect(() => {\n const handleOverlayClick = (e: MouseEvent) => {\n // Only close if clicking directly on the overlay (not its children)\n if (e.target === overlayRef.current) {\n e.preventDefault();\n e.stopPropagation();\n onClose?.();\n }\n };\n\n const handleWrapperClick = (e: MouseEvent) => {\n // Stop propagation for clicks on the image wrapper\n e.stopPropagation();\n };\n\n const overlay = overlayRef.current;\n const wrapper = wrapperRef.current;\n\n if (overlay) {\n overlay.addEventListener('click', handleOverlayClick);\n }\n\n if (wrapper) {\n wrapper.addEventListener('click', handleWrapperClick);\n }\n\n return () => {\n if (overlay) {\n overlay.removeEventListener('click', handleOverlayClick);\n }\n\n if (wrapper) {\n wrapper.removeEventListener('click', handleWrapperClick);\n }\n };\n }, [onClose]);\n\n // Using createPortal to render directly at document body level\n return createPortal(\n <Overlay ref={overlayRef}>\n <ImageWrapper ref={wrapperRef}>\n <StyledImg src={src} alt={alt} />\n </ImageWrapper>\n </Overlay>,\n document.body\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Root\n * -----------------------------------------------------------------------------------------------*/\n\n// Root component that provides context\nconst Root = ({ children, src, alt, onClose, defaultOpen = false }: FullScreenImageRootProps) => {\n const [isOpen, setIsOpen] = useState(defaultOpen);\n\n const open = () => setIsOpen(true);\n const close = () => {\n setIsOpen(false);\n onClose?.();\n };\n\n return (\n <FullScreenImageContext.Provider value={{ isOpen, open, close, src, alt }}>\n {children}\n {isOpen && <ImageModal src={src} alt={alt} onClose={close} />}\n </FullScreenImageContext.Provider>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Hooks\n * -----------------------------------------------------------------------------------------------*/\n\n// Hook to use the context\nconst useFullScreenImage = () => {\n const context = useContext(FullScreenImageContext);\n if (!context) {\n throw new Error('useFullScreenImage must be used within a FullScreenImage.Root');\n }\n return context;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Trigger\n * -----------------------------------------------------------------------------------------------*/\n\n// Trigger component that opens the full screen image\nconst Trigger = ({ children, asChild = false }: FullScreenImageTriggerProps) => {\n const { open } = useFullScreenImage();\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n open();\n };\n\n if (asChild) {\n return (\n <div onClick={handleClick} style={{ cursor: 'pointer', display: 'contents' }}>\n {children}\n </div>\n );\n }\n\n return (\n <div onClick={handleClick} style={{ cursor: 'pointer' }}>\n {children}\n </div>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Export\n * -----------------------------------------------------------------------------------------------*/\n\nexport const FullScreenImage = {\n Root,\n Trigger,\n};\n"],"names":["FullScreenImageContext","createContext","undefined","setOpacity","hex","alpha","Math","floor","toString","padStart","Overlay","styled","div","props","theme","colors","neutral800","ImageWrapper","ANIMATIONS","scaleIn","StyledImg","Base64Img","ImageModal","src","alt","onClose","overlayRef","useRef","wrapperRef","useEffect","handleKeyDown","e","key","preventDefault","stopPropagation","stopImmediatePropagation","cancelBubble","window","addEventListener","removeEventListener","handleOverlayClick","target","current","handleWrapperClick","overlay","wrapper","createPortal","_jsx","ref","document","body","Root","children","defaultOpen","isOpen","setIsOpen","useState","open","close","_jsxs","Provider","value","useFullScreenImage","context","useContext","Error","Trigger","asChild","handleClick","onClick","style","cursor","display","FullScreenImage"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FullScreenImage.js","sources":["../../../../../admin/src/components/AIChat/components/FullScreenImage.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n createContext,\n useContext,\n useState,\n ReactNode,\n} from 'react';\n\nimport { createPortal } from 'react-dom';\nimport { styled } from 'styled-components';\n\nimport { ANIMATIONS } from './animations';\nimport { Base64Img } from './Base64Image';\n\n/* -------------------------------------------------------------------------------------------------\n * Context\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FullScreenImageContextType {\n isOpen: boolean;\n open: () => void;\n close: () => void;\n src: string;\n alt: string;\n}\n\nconst FullScreenImageContext = createContext<FullScreenImageContextType | undefined>(undefined);\n\n/* -------------------------------------------------------------------------------------------------\n * Types\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FullScreenImageProps {\n src: string;\n alt: string;\n onClose?: () => void;\n}\n\ninterface FullScreenImageRootProps extends FullScreenImageProps {\n children: ReactNode;\n defaultOpen?: boolean;\n}\n\ninterface FullScreenImageTriggerProps {\n children: ReactNode;\n asChild?: boolean;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Styles\n * -----------------------------------------------------------------------------------------------*/\nexport const setOpacity = (hex: string, alpha: number) =>\n `${hex}${Math.floor(alpha * 255)\n .toString(16)\n .padStart(2, '0')}`;\n\nconst Overlay = styled.div`\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n width: 100vw;\n height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 500;\n pointer-events: auto; /* Explicitly enable pointer events */\n background: ${(props) => setOpacity(props.theme.colors.neutral800, 0.2)};\n`;\n\nconst ImageWrapper = styled.div`\n max-width: 80vw;\n max-height: 90vh;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: auto; /* Explicitly enable pointer events */\n position: relative;\n animation: ${ANIMATIONS.scaleIn} 0.3s ease;\n`;\n\nconst StyledImg = styled(Base64Img)`\n max-width: 100%;\n max-height: 90vh;\n object-fit: contain;\n pointer-events: auto; /* Explicitly enable pointer events */\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Modal\n * -----------------------------------------------------------------------------------------------*/\n\n// Use the existing FullScreenImage as our modal component\nconst ImageModal = ({ src, alt, onClose }: FullScreenImageProps) => {\n const overlayRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n // Close on ESC key press\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n // Stop propagation to prevent closing parent modals\n e.preventDefault();\n e.stopPropagation();\n onClose?.();\n\n // The next 3 lines are critical: they completely stop the event\n e.stopImmediatePropagation();\n e.cancelBubble = true; // For older browsers\n return false;\n }\n };\n\n // Use capture phase to intercept event before it reaches other components\n window.addEventListener('keydown', handleKeyDown, true);\n return () => window.removeEventListener('keydown', handleKeyDown, true);\n }, [onClose]);\n\n // Setup click handlers\n useEffect(() => {\n const handleOverlayClick = (e: MouseEvent) => {\n // Only close if clicking directly on the overlay (not its children)\n if (e.target === overlayRef.current) {\n e.preventDefault();\n e.stopPropagation();\n onClose?.();\n }\n };\n\n const handleWrapperClick = (e: MouseEvent) => {\n // Stop propagation for clicks on the image wrapper\n e.stopPropagation();\n };\n\n const overlay = overlayRef.current;\n const wrapper = wrapperRef.current;\n\n if (overlay) {\n overlay.addEventListener('click', handleOverlayClick);\n }\n\n if (wrapper) {\n wrapper.addEventListener('click', handleWrapperClick);\n }\n\n return () => {\n if (overlay) {\n overlay.removeEventListener('click', handleOverlayClick);\n }\n\n if (wrapper) {\n wrapper.removeEventListener('click', handleWrapperClick);\n }\n };\n }, [onClose]);\n\n // Using createPortal to render directly at document body level\n return createPortal(\n <Overlay ref={overlayRef}>\n <ImageWrapper ref={wrapperRef}>\n <StyledImg src={src} alt={alt} />\n </ImageWrapper>\n </Overlay>,\n document.body\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Root\n * -----------------------------------------------------------------------------------------------*/\n\n// Root component that provides context\nconst Root = ({ children, src, alt, onClose, defaultOpen = false }: FullScreenImageRootProps) => {\n const [isOpen, setIsOpen] = useState(defaultOpen);\n\n const open = useCallback(() => setIsOpen(true), []);\n const close = useCallback(() => {\n setIsOpen(false);\n onClose?.();\n }, [onClose]);\n const contextValue = useMemo(\n () => ({ isOpen, open, close, src, alt }),\n [isOpen, open, close, src, alt]\n );\n\n return (\n <FullScreenImageContext.Provider value={contextValue}>\n {children}\n {isOpen && <ImageModal src={src} alt={alt} onClose={close} />}\n </FullScreenImageContext.Provider>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Hooks\n * -----------------------------------------------------------------------------------------------*/\n\n// Hook to use the context\nconst useFullScreenImage = () => {\n const context = useContext(FullScreenImageContext);\n if (!context) {\n throw new Error('useFullScreenImage must be used within a FullScreenImage.Root');\n }\n return context;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Trigger\n * -----------------------------------------------------------------------------------------------*/\n\n// Trigger component that opens the full screen image\nconst Trigger = ({ children, asChild = false }: FullScreenImageTriggerProps) => {\n const { open } = useFullScreenImage();\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n open();\n };\n\n if (asChild) {\n return (\n <div onClick={handleClick} style={{ cursor: 'pointer', display: 'contents' }}>\n {children}\n </div>\n );\n }\n\n return (\n <div onClick={handleClick} style={{ cursor: 'pointer' }}>\n {children}\n </div>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Export\n * -----------------------------------------------------------------------------------------------*/\n\nexport const FullScreenImage = {\n Root,\n Trigger,\n useFullScreenImage,\n};\n"],"names":["FullScreenImageContext","createContext","undefined","setOpacity","hex","alpha","Math","floor","toString","padStart","Overlay","styled","div","props","theme","colors","neutral800","ImageWrapper","ANIMATIONS","scaleIn","StyledImg","Base64Img","ImageModal","src","alt","onClose","overlayRef","useRef","wrapperRef","useEffect","handleKeyDown","e","key","preventDefault","stopPropagation","stopImmediatePropagation","cancelBubble","window","addEventListener","removeEventListener","handleOverlayClick","target","current","handleWrapperClick","overlay","wrapper","createPortal","_jsx","ref","document","body","Root","children","defaultOpen","isOpen","setIsOpen","useState","open","useCallback","close","contextValue","useMemo","_jsxs","Provider","value","useFullScreenImage","context","useContext","Error","Trigger","asChild","handleClick","onClick","style","cursor","display","FullScreenImage"],"mappings":";;;;;;;;;AA6BA,MAAMA,uCAAyBC,mBAAAA,CAAsDC,SAAAA,CAAAA;AAsBrF;;2GAGaC,UAAAA,GAAa,CAACC,KAAaC,KAAAA,GACtC,CAAA,EAAGD,MAAME,IAAAA,CAAKC,KAAK,CAACF,KAAAA,GAAQ,GAAA,CAAA,CACzBG,QAAQ,CAAC,EAAA,CAAA,CACTC,QAAQ,CAAC,CAAA,EAAG;AAEjB,MAAMC,OAAAA,GAAUC,uBAAAA,CAAOC,GAAG;;;;;;;;;;;;;cAaZ,EAAE,CAACC,KAAAA,GAAUV,UAAAA,CAAWU,KAAAA,CAAMC,KAAK,CAACC,MAAM,CAACC,UAAU,EAAE,GAAA,CAAA,CAAK;AAC1E,CAAC;AAED,MAAMC,YAAAA,GAAeN,uBAAAA,CAAOC,GAAG;;;;;;;;aAQlB,EAAEM,qBAAAA,CAAWC,OAAO,CAAC;AAClC,CAAC;AAED,MAAMC,SAAAA,GAAYT,uBAAAA,CAAOU,qBAAAA,CAAU;;;;;AAKnC,CAAC;AAED;;AAEkG;AAGlG,MAAMC,UAAAA,GAAa,CAAC,EAAEC,GAAG,EAAEC,GAAG,EAAEC,OAAO,EAAwB,GAAA;AAC7D,IAAA,MAAMC,aAAaC,YAAAA,CAAuB,IAAA,CAAA;AAC1C,IAAA,MAAMC,aAAaD,YAAAA,CAAuB,IAAA,CAAA;;IAG1CE,eAAAA,CAAU,IAAA;AACR,QAAA,MAAMC,gBAAgB,CAACC,CAAAA,GAAAA;YACrB,IAAIA,CAAAA,CAAEC,GAAG,KAAK,QAAA,EAAU;;AAEtBD,gBAAAA,CAAAA,CAAEE,cAAc,EAAA;AAChBF,gBAAAA,CAAAA,CAAEG,eAAe,EAAA;AACjBT,gBAAAA,OAAAA,IAAAA;;AAGAM,gBAAAA,CAAAA,CAAEI,wBAAwB,EAAA;gBAC1BJ,CAAAA,CAAEK,YAAY,GAAG,IAAA,CAAA;gBACjB,OAAO,KAAA;AACT,YAAA;AACF,QAAA,CAAA;;QAGAC,MAAAA,CAAOC,gBAAgB,CAAC,SAAA,EAAWR,aAAAA,EAAe,IAAA,CAAA;AAClD,QAAA,OAAO,IAAMO,MAAAA,CAAOE,mBAAmB,CAAC,WAAWT,aAAAA,EAAe,IAAA,CAAA;IACpE,CAAA,EAAG;AAACL,QAAAA;AAAQ,KAAA,CAAA;;IAGZI,eAAAA,CAAU,IAAA;AACR,QAAA,MAAMW,qBAAqB,CAACT,CAAAA,GAAAA;;AAE1B,YAAA,IAAIA,CAAAA,CAAEU,MAAM,KAAKf,UAAAA,CAAWgB,OAAO,EAAE;AACnCX,gBAAAA,CAAAA,CAAEE,cAAc,EAAA;AAChBF,gBAAAA,CAAAA,CAAEG,eAAe,EAAA;AACjBT,gBAAAA,OAAAA,IAAAA;AACF,YAAA;AACF,QAAA,CAAA;AAEA,QAAA,MAAMkB,qBAAqB,CAACZ,CAAAA,GAAAA;;AAE1BA,YAAAA,CAAAA,CAAEG,eAAe,EAAA;AACnB,QAAA,CAAA;QAEA,MAAMU,OAAAA,GAAUlB,WAAWgB,OAAO;QAClC,MAAMG,OAAAA,GAAUjB,WAAWc,OAAO;AAElC,QAAA,IAAIE,OAAAA,EAAS;YACXA,OAAAA,CAAQN,gBAAgB,CAAC,OAAA,EAASE,kBAAAA,CAAAA;AACpC,QAAA;AAEA,QAAA,IAAIK,OAAAA,EAAS;YACXA,OAAAA,CAAQP,gBAAgB,CAAC,OAAA,EAASK,kBAAAA,CAAAA;AACpC,QAAA;QAEA,OAAO,IAAA;AACL,YAAA,IAAIC,OAAAA,EAAS;gBACXA,OAAAA,CAAQL,mBAAmB,CAAC,OAAA,EAASC,kBAAAA,CAAAA;AACvC,YAAA;AAEA,YAAA,IAAIK,OAAAA,EAAS;gBACXA,OAAAA,CAAQN,mBAAmB,CAAC,OAAA,EAASI,kBAAAA,CAAAA;AACvC,YAAA;AACF,QAAA,CAAA;IACF,CAAA,EAAG;AAAClB,QAAAA;AAAQ,KAAA,CAAA;;AAGZ,IAAA,qBAAOqB,oCACLC,cAAA,CAACrC,OAAAA,EAAAA;QAAQsC,GAAAA,EAAKtB,UAAAA;AACZ,QAAA,QAAA,gBAAAqB,cAAA,CAAC9B,YAAAA,EAAAA;YAAa+B,GAAAA,EAAKpB,UAAAA;AACjB,YAAA,QAAA,gBAAAmB,cAAA,CAAC3B,SAAAA,EAAAA;gBAAUG,GAAAA,EAAKA,GAAAA;gBAAKC,GAAAA,EAAKA;;;AAG9ByB,KAAAA,CAAAA,EAAAA,QAAAA,CAASC,IAAI,CAAA;AAEjB,CAAA;AAEA;;AAEkG;AAGlG,MAAMC,IAAAA,GAAO,CAAC,EAAEC,QAAQ,EAAE7B,GAAG,EAAEC,GAAG,EAAEC,OAAO,EAAE4B,WAAAA,GAAc,KAAK,EAA4B,GAAA;AAC1F,IAAA,MAAM,CAACC,MAAAA,EAAQC,SAAAA,CAAU,GAAGC,cAAAA,CAASH,WAAAA,CAAAA;AAErC,IAAA,MAAMI,IAAAA,GAAOC,iBAAAA,CAAY,IAAMH,SAAAA,CAAU,OAAO,EAAE,CAAA;AAClD,IAAA,MAAMI,QAAQD,iBAAAA,CAAY,IAAA;QACxBH,SAAAA,CAAU,KAAA,CAAA;AACV9B,QAAAA,OAAAA,IAAAA;IACF,CAAA,EAAG;AAACA,QAAAA;AAAQ,KAAA,CAAA;IACZ,MAAMmC,YAAAA,GAAeC,aAAAA,CACnB,KAAO;AAAEP,YAAAA,MAAAA;AAAQG,YAAAA,IAAAA;AAAME,YAAAA,KAAAA;AAAOpC,YAAAA,GAAAA;AAAKC,YAAAA;AAAI,SAAA,CAAA,EACvC;AAAC8B,QAAAA,MAAAA;AAAQG,QAAAA,IAAAA;AAAME,QAAAA,KAAAA;AAAOpC,QAAAA,GAAAA;AAAKC,QAAAA;AAAI,KAAA,CAAA;IAGjC,qBACEsC,eAAA,CAAC9D,uBAAuB+D,QAAQ,EAAA;QAACC,KAAAA,EAAOJ,YAAAA;;AACrCR,YAAAA,QAAAA;AACAE,YAAAA,MAAAA,kBAAUP,cAAA,CAACzB,UAAAA,EAAAA;gBAAWC,GAAAA,EAAKA,GAAAA;gBAAKC,GAAAA,EAAKA,GAAAA;gBAAKC,OAAAA,EAASkC;;;;AAG1D,CAAA;AAEA;;AAEkG;AAGlG,MAAMM,kBAAAA,GAAqB,IAAA;AACzB,IAAA,MAAMC,UAAUC,gBAAAA,CAAWnE,sBAAAA,CAAAA;AAC3B,IAAA,IAAI,CAACkE,OAAAA,EAAS;AACZ,QAAA,MAAM,IAAIE,KAAAA,CAAM,+DAAA,CAAA;AAClB,IAAA;IACA,OAAOF,OAAAA;AACT,CAAA;AAEA;;AAEkG;AAGlG,MAAMG,UAAU,CAAC,EAAEjB,QAAQ,EAAEkB,OAAAA,GAAU,KAAK,EAA+B,GAAA;IACzE,MAAM,EAAEb,IAAI,EAAE,GAAGQ,kBAAAA,EAAAA;AAEjB,IAAA,MAAMM,cAAc,CAACxC,CAAAA,GAAAA;AACnBA,QAAAA,CAAAA,CAAEG,eAAe,EAAA;AACjBuB,QAAAA,IAAAA,EAAAA;AACF,IAAA,CAAA;AAEA,IAAA,IAAIa,OAAAA,EAAS;AACX,QAAA,qBACEvB,cAAA,CAACnC,KAAAA,EAAAA;YAAI4D,OAAAA,EAASD,WAAAA;YAAaE,KAAAA,EAAO;gBAAEC,MAAAA,EAAQ,SAAA;gBAAWC,OAAAA,EAAS;AAAW,aAAA;AACxEvB,YAAAA,QAAAA,EAAAA;;AAGP,IAAA;AAEA,IAAA,qBACEL,cAAA,CAACnC,KAAAA,EAAAA;QAAI4D,OAAAA,EAASD,WAAAA;QAAaE,KAAAA,EAAO;YAAEC,MAAAA,EAAQ;AAAU,SAAA;AACnDtB,QAAAA,QAAAA,EAAAA;;AAGP,CAAA;AAEA;;2GAIawB,eAAAA,GAAkB;AAC7BzB,IAAAA,IAAAA;AACAkB,IAAAA,OAEF;;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { useState, createContext, useRef, useEffect, useContext } from 'react';
|
|
2
|
+
import { useState, useCallback, useMemo, createContext, useRef, useEffect, useContext } from 'react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
import { styled } from 'styled-components';
|
|
5
5
|
import { ANIMATIONS } from './animations.mjs';
|
|
@@ -116,19 +116,28 @@ const ImageModal = ({ src, alt, onClose })=>{
|
|
|
116
116
|
* -----------------------------------------------------------------------------------------------*/ // Root component that provides context
|
|
117
117
|
const Root = ({ children, src, alt, onClose, defaultOpen = false })=>{
|
|
118
118
|
const [isOpen, setIsOpen] = useState(defaultOpen);
|
|
119
|
-
const open = ()=>setIsOpen(true);
|
|
120
|
-
const close = ()=>{
|
|
119
|
+
const open = useCallback(()=>setIsOpen(true), []);
|
|
120
|
+
const close = useCallback(()=>{
|
|
121
121
|
setIsOpen(false);
|
|
122
122
|
onClose?.();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
}, [
|
|
124
|
+
onClose
|
|
125
|
+
]);
|
|
126
|
+
const contextValue = useMemo(()=>({
|
|
126
127
|
isOpen,
|
|
127
128
|
open,
|
|
128
129
|
close,
|
|
129
130
|
src,
|
|
130
131
|
alt
|
|
131
|
-
},
|
|
132
|
+
}), [
|
|
133
|
+
isOpen,
|
|
134
|
+
open,
|
|
135
|
+
close,
|
|
136
|
+
src,
|
|
137
|
+
alt
|
|
138
|
+
]);
|
|
139
|
+
return /*#__PURE__*/ jsxs(FullScreenImageContext.Provider, {
|
|
140
|
+
value: contextValue,
|
|
132
141
|
children: [
|
|
133
142
|
children,
|
|
134
143
|
isOpen && /*#__PURE__*/ jsx(ImageModal, {
|
|
@@ -180,8 +189,7 @@ const Trigger = ({ children, asChild = false })=>{
|
|
|
180
189
|
* Export
|
|
181
190
|
* -----------------------------------------------------------------------------------------------*/ const FullScreenImage = {
|
|
182
191
|
Root,
|
|
183
|
-
Trigger
|
|
184
|
-
};
|
|
192
|
+
Trigger};
|
|
185
193
|
|
|
186
194
|
export { FullScreenImage, setOpacity };
|
|
187
195
|
//# sourceMappingURL=FullScreenImage.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FullScreenImage.mjs","sources":["../../../../../admin/src/components/AIChat/components/FullScreenImage.tsx"],"sourcesContent":["import { useEffect, useRef, createContext, useContext, useState, ReactNode } from 'react';\n\nimport { createPortal } from 'react-dom';\nimport { styled } from 'styled-components';\n\nimport { ANIMATIONS } from './animations';\nimport { Base64Img } from './Base64Image';\n\n/* -------------------------------------------------------------------------------------------------\n * Context\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FullScreenImageContextType {\n isOpen: boolean;\n open: () => void;\n close: () => void;\n src: string;\n alt: string;\n}\n\nconst FullScreenImageContext = createContext<FullScreenImageContextType | undefined>(undefined);\n\n/* -------------------------------------------------------------------------------------------------\n * Types\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FullScreenImageProps {\n src: string;\n alt: string;\n onClose?: () => void;\n}\n\ninterface FullScreenImageRootProps extends FullScreenImageProps {\n children: ReactNode;\n defaultOpen?: boolean;\n}\n\ninterface FullScreenImageTriggerProps {\n children: ReactNode;\n asChild?: boolean;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Styles\n * -----------------------------------------------------------------------------------------------*/\nexport const setOpacity = (hex: string, alpha: number) =>\n `${hex}${Math.floor(alpha * 255)\n .toString(16)\n .padStart(2, '0')}`;\n\nconst Overlay = styled.div`\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n width: 100vw;\n height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 500;\n pointer-events: auto; /* Explicitly enable pointer events */\n background: ${(props) => setOpacity(props.theme.colors.neutral800, 0.2)};\n`;\n\nconst ImageWrapper = styled.div`\n max-width: 80vw;\n max-height: 90vh;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: auto; /* Explicitly enable pointer events */\n position: relative;\n animation: ${ANIMATIONS.scaleIn} 0.3s ease;\n`;\n\nconst StyledImg = styled(Base64Img)`\n max-width: 100%;\n max-height: 90vh;\n object-fit: contain;\n pointer-events: auto; /* Explicitly enable pointer events */\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Modal\n * -----------------------------------------------------------------------------------------------*/\n\n// Use the existing FullScreenImage as our modal component\nconst ImageModal = ({ src, alt, onClose }: FullScreenImageProps) => {\n const overlayRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n // Close on ESC key press\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n // Stop propagation to prevent closing parent modals\n e.preventDefault();\n e.stopPropagation();\n onClose?.();\n\n // The next 3 lines are critical: they completely stop the event\n e.stopImmediatePropagation();\n e.cancelBubble = true; // For older browsers\n return false;\n }\n };\n\n // Use capture phase to intercept event before it reaches other components\n window.addEventListener('keydown', handleKeyDown, true);\n return () => window.removeEventListener('keydown', handleKeyDown, true);\n }, [onClose]);\n\n // Setup click handlers\n useEffect(() => {\n const handleOverlayClick = (e: MouseEvent) => {\n // Only close if clicking directly on the overlay (not its children)\n if (e.target === overlayRef.current) {\n e.preventDefault();\n e.stopPropagation();\n onClose?.();\n }\n };\n\n const handleWrapperClick = (e: MouseEvent) => {\n // Stop propagation for clicks on the image wrapper\n e.stopPropagation();\n };\n\n const overlay = overlayRef.current;\n const wrapper = wrapperRef.current;\n\n if (overlay) {\n overlay.addEventListener('click', handleOverlayClick);\n }\n\n if (wrapper) {\n wrapper.addEventListener('click', handleWrapperClick);\n }\n\n return () => {\n if (overlay) {\n overlay.removeEventListener('click', handleOverlayClick);\n }\n\n if (wrapper) {\n wrapper.removeEventListener('click', handleWrapperClick);\n }\n };\n }, [onClose]);\n\n // Using createPortal to render directly at document body level\n return createPortal(\n <Overlay ref={overlayRef}>\n <ImageWrapper ref={wrapperRef}>\n <StyledImg src={src} alt={alt} />\n </ImageWrapper>\n </Overlay>,\n document.body\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Root\n * -----------------------------------------------------------------------------------------------*/\n\n// Root component that provides context\nconst Root = ({ children, src, alt, onClose, defaultOpen = false }: FullScreenImageRootProps) => {\n const [isOpen, setIsOpen] = useState(defaultOpen);\n\n const open = () => setIsOpen(true);\n const close = () => {\n setIsOpen(false);\n onClose?.();\n };\n\n return (\n <FullScreenImageContext.Provider value={{ isOpen, open, close, src, alt }}>\n {children}\n {isOpen && <ImageModal src={src} alt={alt} onClose={close} />}\n </FullScreenImageContext.Provider>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Hooks\n * -----------------------------------------------------------------------------------------------*/\n\n// Hook to use the context\nconst useFullScreenImage = () => {\n const context = useContext(FullScreenImageContext);\n if (!context) {\n throw new Error('useFullScreenImage must be used within a FullScreenImage.Root');\n }\n return context;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Trigger\n * -----------------------------------------------------------------------------------------------*/\n\n// Trigger component that opens the full screen image\nconst Trigger = ({ children, asChild = false }: FullScreenImageTriggerProps) => {\n const { open } = useFullScreenImage();\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n open();\n };\n\n if (asChild) {\n return (\n <div onClick={handleClick} style={{ cursor: 'pointer', display: 'contents' }}>\n {children}\n </div>\n );\n }\n\n return (\n <div onClick={handleClick} style={{ cursor: 'pointer' }}>\n {children}\n </div>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Export\n * -----------------------------------------------------------------------------------------------*/\n\nexport const FullScreenImage = {\n Root,\n Trigger,\n};\n"],"names":["FullScreenImageContext","createContext","undefined","setOpacity","hex","alpha","Math","floor","toString","padStart","Overlay","styled","div","props","theme","colors","neutral800","ImageWrapper","ANIMATIONS","scaleIn","StyledImg","Base64Img","ImageModal","src","alt","onClose","overlayRef","useRef","wrapperRef","useEffect","handleKeyDown","e","key","preventDefault","stopPropagation","stopImmediatePropagation","cancelBubble","window","addEventListener","removeEventListener","handleOverlayClick","target","current","handleWrapperClick","overlay","wrapper","createPortal","_jsx","ref","document","body","Root","children","defaultOpen","isOpen","setIsOpen","useState","open","close","_jsxs","Provider","value","useFullScreenImage","context","useContext","Error","Trigger","asChild","handleClick","onClick","style","cursor","display","FullScreenImage"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FullScreenImage.mjs","sources":["../../../../../admin/src/components/AIChat/components/FullScreenImage.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n createContext,\n useContext,\n useState,\n ReactNode,\n} from 'react';\n\nimport { createPortal } from 'react-dom';\nimport { styled } from 'styled-components';\n\nimport { ANIMATIONS } from './animations';\nimport { Base64Img } from './Base64Image';\n\n/* -------------------------------------------------------------------------------------------------\n * Context\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FullScreenImageContextType {\n isOpen: boolean;\n open: () => void;\n close: () => void;\n src: string;\n alt: string;\n}\n\nconst FullScreenImageContext = createContext<FullScreenImageContextType | undefined>(undefined);\n\n/* -------------------------------------------------------------------------------------------------\n * Types\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FullScreenImageProps {\n src: string;\n alt: string;\n onClose?: () => void;\n}\n\ninterface FullScreenImageRootProps extends FullScreenImageProps {\n children: ReactNode;\n defaultOpen?: boolean;\n}\n\ninterface FullScreenImageTriggerProps {\n children: ReactNode;\n asChild?: boolean;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Styles\n * -----------------------------------------------------------------------------------------------*/\nexport const setOpacity = (hex: string, alpha: number) =>\n `${hex}${Math.floor(alpha * 255)\n .toString(16)\n .padStart(2, '0')}`;\n\nconst Overlay = styled.div`\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n width: 100vw;\n height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 500;\n pointer-events: auto; /* Explicitly enable pointer events */\n background: ${(props) => setOpacity(props.theme.colors.neutral800, 0.2)};\n`;\n\nconst ImageWrapper = styled.div`\n max-width: 80vw;\n max-height: 90vh;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: auto; /* Explicitly enable pointer events */\n position: relative;\n animation: ${ANIMATIONS.scaleIn} 0.3s ease;\n`;\n\nconst StyledImg = styled(Base64Img)`\n max-width: 100%;\n max-height: 90vh;\n object-fit: contain;\n pointer-events: auto; /* Explicitly enable pointer events */\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Modal\n * -----------------------------------------------------------------------------------------------*/\n\n// Use the existing FullScreenImage as our modal component\nconst ImageModal = ({ src, alt, onClose }: FullScreenImageProps) => {\n const overlayRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n // Close on ESC key press\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n // Stop propagation to prevent closing parent modals\n e.preventDefault();\n e.stopPropagation();\n onClose?.();\n\n // The next 3 lines are critical: they completely stop the event\n e.stopImmediatePropagation();\n e.cancelBubble = true; // For older browsers\n return false;\n }\n };\n\n // Use capture phase to intercept event before it reaches other components\n window.addEventListener('keydown', handleKeyDown, true);\n return () => window.removeEventListener('keydown', handleKeyDown, true);\n }, [onClose]);\n\n // Setup click handlers\n useEffect(() => {\n const handleOverlayClick = (e: MouseEvent) => {\n // Only close if clicking directly on the overlay (not its children)\n if (e.target === overlayRef.current) {\n e.preventDefault();\n e.stopPropagation();\n onClose?.();\n }\n };\n\n const handleWrapperClick = (e: MouseEvent) => {\n // Stop propagation for clicks on the image wrapper\n e.stopPropagation();\n };\n\n const overlay = overlayRef.current;\n const wrapper = wrapperRef.current;\n\n if (overlay) {\n overlay.addEventListener('click', handleOverlayClick);\n }\n\n if (wrapper) {\n wrapper.addEventListener('click', handleWrapperClick);\n }\n\n return () => {\n if (overlay) {\n overlay.removeEventListener('click', handleOverlayClick);\n }\n\n if (wrapper) {\n wrapper.removeEventListener('click', handleWrapperClick);\n }\n };\n }, [onClose]);\n\n // Using createPortal to render directly at document body level\n return createPortal(\n <Overlay ref={overlayRef}>\n <ImageWrapper ref={wrapperRef}>\n <StyledImg src={src} alt={alt} />\n </ImageWrapper>\n </Overlay>,\n document.body\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Root\n * -----------------------------------------------------------------------------------------------*/\n\n// Root component that provides context\nconst Root = ({ children, src, alt, onClose, defaultOpen = false }: FullScreenImageRootProps) => {\n const [isOpen, setIsOpen] = useState(defaultOpen);\n\n const open = useCallback(() => setIsOpen(true), []);\n const close = useCallback(() => {\n setIsOpen(false);\n onClose?.();\n }, [onClose]);\n const contextValue = useMemo(\n () => ({ isOpen, open, close, src, alt }),\n [isOpen, open, close, src, alt]\n );\n\n return (\n <FullScreenImageContext.Provider value={contextValue}>\n {children}\n {isOpen && <ImageModal src={src} alt={alt} onClose={close} />}\n </FullScreenImageContext.Provider>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Hooks\n * -----------------------------------------------------------------------------------------------*/\n\n// Hook to use the context\nconst useFullScreenImage = () => {\n const context = useContext(FullScreenImageContext);\n if (!context) {\n throw new Error('useFullScreenImage must be used within a FullScreenImage.Root');\n }\n return context;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Trigger\n * -----------------------------------------------------------------------------------------------*/\n\n// Trigger component that opens the full screen image\nconst Trigger = ({ children, asChild = false }: FullScreenImageTriggerProps) => {\n const { open } = useFullScreenImage();\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n open();\n };\n\n if (asChild) {\n return (\n <div onClick={handleClick} style={{ cursor: 'pointer', display: 'contents' }}>\n {children}\n </div>\n );\n }\n\n return (\n <div onClick={handleClick} style={{ cursor: 'pointer' }}>\n {children}\n </div>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Export\n * -----------------------------------------------------------------------------------------------*/\n\nexport const FullScreenImage = {\n Root,\n Trigger,\n useFullScreenImage,\n};\n"],"names":["FullScreenImageContext","createContext","undefined","setOpacity","hex","alpha","Math","floor","toString","padStart","Overlay","styled","div","props","theme","colors","neutral800","ImageWrapper","ANIMATIONS","scaleIn","StyledImg","Base64Img","ImageModal","src","alt","onClose","overlayRef","useRef","wrapperRef","useEffect","handleKeyDown","e","key","preventDefault","stopPropagation","stopImmediatePropagation","cancelBubble","window","addEventListener","removeEventListener","handleOverlayClick","target","current","handleWrapperClick","overlay","wrapper","createPortal","_jsx","ref","document","body","Root","children","defaultOpen","isOpen","setIsOpen","useState","open","useCallback","close","contextValue","useMemo","_jsxs","Provider","value","useFullScreenImage","context","useContext","Error","Trigger","asChild","handleClick","onClick","style","cursor","display","FullScreenImage"],"mappings":"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"}
|
|
@@ -7,10 +7,13 @@ var styledComponents = require('styled-components');
|
|
|
7
7
|
|
|
8
8
|
const InputContext = /*#__PURE__*/ React.createContext({});
|
|
9
9
|
const Root = ({ children, isLoading = false, ...props })=>{
|
|
10
|
-
|
|
11
|
-
value: {
|
|
10
|
+
const contextValue = React.useMemo(()=>({
|
|
12
11
|
isLoading
|
|
13
|
-
},
|
|
12
|
+
}), [
|
|
13
|
+
isLoading
|
|
14
|
+
]);
|
|
15
|
+
return /*#__PURE__*/ jsxRuntime.jsx(InputContext.Provider, {
|
|
16
|
+
value: contextValue,
|
|
14
17
|
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
|
15
18
|
direction: "column",
|
|
16
19
|
alignItems: 'flex-start',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.js","sources":["../../../../../admin/src/components/AIChat/components/Input.tsx"],"sourcesContent":["import { createContext, useContext } from 'react';\n\nimport { Box, Flex, Typography } from '@strapi/design-system';\nimport { styled } from 'styled-components';\n\n/* -------------------------------------------------------------------------------------------------\n * Input Context\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface InputContextValue {\n isLoading?: boolean;\n}\n\nexport const InputContext = createContext<InputContextValue>({});\n\nexport const useInput = () => useContext(InputContext);\n\n/* -------------------------------------------------------------------------------------------------\n * Input Root\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface InputRootProps extends React.ComponentPropsWithoutRef<typeof Flex> {\n children: React.ReactNode;\n isLoading?: boolean;\n}\n\nexport const Root = ({ children, isLoading = false, ...props }: InputRootProps) => {\n return (\n <InputContext.Provider
|
|
1
|
+
{"version":3,"file":"Input.js","sources":["../../../../../admin/src/components/AIChat/components/Input.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from 'react';\n\nimport { Box, Flex, Typography } from '@strapi/design-system';\nimport { styled } from 'styled-components';\n\n/* -------------------------------------------------------------------------------------------------\n * Input Context\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface InputContextValue {\n isLoading?: boolean;\n}\n\nexport const InputContext = createContext<InputContextValue>({});\n\nexport const useInput = () => useContext(InputContext);\n\n/* -------------------------------------------------------------------------------------------------\n * Input Root\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface InputRootProps extends React.ComponentPropsWithoutRef<typeof Flex> {\n children: React.ReactNode;\n isLoading?: boolean;\n}\n\nexport const Root = ({ children, isLoading = false, ...props }: InputRootProps) => {\n const contextValue = useMemo(() => ({ isLoading }), [isLoading]);\n\n return (\n <InputContext.Provider value={contextValue}>\n <Flex\n direction=\"column\"\n alignItems={'flex-start'}\n width=\"100%\"\n position=\"relative\"\n {...props}\n >\n {children}\n </Flex>\n </InputContext.Provider>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Input Header\n * -----------------------------------------------------------------------------------------------*/\n\ninterface HeaderProps extends React.ComponentPropsWithoutRef<typeof Box> {\n children: React.ReactNode;\n isThinking?: boolean;\n thinkingMessage?: string;\n}\n\nconst Header = ({ children, ...props }: HeaderProps) => {\n return (\n <Box\n position=\"absolute\"\n bottom={'102%'}\n left={0}\n right={0}\n background=\"neutral0\"\n width=\"100%\"\n {...props}\n >\n {children}\n </Box>\n );\n};\n\nconst HeaderItem = styled(Box)`\n padding: ${({ theme }) => theme.spaces[3]} 0};\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Input Attachments\n * -----------------------------------------------------------------------------------------------*/\ninterface InputAttachmentsProps extends React.ComponentPropsWithoutRef<typeof Flex> {\n children: React.ReactNode;\n}\n\nconst Attachments = ({ children, gap = 2, ...props }: InputAttachmentsProps) => {\n return (\n <Flex gap={gap} wrap=\"wrap\" paddingBottom={2} maxHeight=\"150px\" overflow=\"auto\" {...props}>\n {children}\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Input Content\n * -----------------------------------------------------------------------------------------------*/\n\nconst InputContainer = styled(Box)`\n outline: none;\n box-shadow: none;\n transition-property: border-color, box-shadow, fill;\n transition-duration: 0.2s;\n\n &:focus-within {\n border: 1px solid\n ${({ theme, $hasError }) => ($hasError ? theme.colors.danger600 : theme.colors.primary600)};\n box-shadow: ${({ theme, $hasError }) =>\n $hasError ? theme.colors.danger600 : theme.colors.primary600}\n 0px 0px 0px 2px;\n }\n`;\n\ninterface ContentProps extends React.ComponentPropsWithoutRef<typeof Box> {\n children: React.ReactNode;\n disclaimer?: string;\n error?: boolean;\n}\n\nconst Content = ({ children, disclaimer, error = false, ...props }: ContentProps) => {\n return (\n <InputContainer\n background=\"neutral0\"\n hasRadius\n borderColor={error ? 'danger600' : 'neutral200'}\n borderWidth=\"1px\"\n borderStyle=\"solid\"\n width=\"100%\"\n $hasError={error}\n {...props}\n >\n <Box padding={3}>{children}</Box>\n {disclaimer && (\n <Box\n background=\"neutral100\"\n padding={[2, 3]}\n borderColor=\"neutral200\"\n borderWidth=\"1px 0 0 0\"\n borderStyle=\"solid\"\n borderRadius={'0 0 4px 4px'}\n >\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {disclaimer}\n </Typography>\n </Box>\n )}\n </InputContainer>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Input Actions\n * -----------------------------------------------------------------------------------------------*/\n\nconst Actions = ({ children }: { children: React.ReactNode }) => {\n return (\n <Flex justifyContent=\"flex-end\" alignItems=\"center\" gap={2}>\n {children}\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Input Compound\n * -----------------------------------------------------------------------------------------------*/\n\nexport const Input = {\n Root,\n Header,\n HeaderItem,\n Attachments,\n Content,\n Actions,\n useInput,\n};\n"],"names":["InputContext","createContext","Root","children","isLoading","props","contextValue","useMemo","_jsx","Provider","value","Flex","direction","alignItems","width","position","Header","Box","bottom","left","right","background","HeaderItem","styled","theme","spaces","Attachments","gap","wrap","paddingBottom","maxHeight","overflow","InputContainer","$hasError","colors","danger600","primary600","Content","disclaimer","error","_jsxs","hasRadius","borderColor","borderWidth","borderStyle","padding","borderRadius","Typography","variant","textColor","Actions","justifyContent","Input"],"mappings":"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"}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { createContext } from 'react';
|
|
2
|
+
import { useMemo, createContext } from 'react';
|
|
3
3
|
import { Flex, Box, Typography } from '@strapi/design-system';
|
|
4
4
|
import { styled } from 'styled-components';
|
|
5
5
|
|
|
6
6
|
const InputContext = /*#__PURE__*/ createContext({});
|
|
7
7
|
const Root = ({ children, isLoading = false, ...props })=>{
|
|
8
|
-
|
|
9
|
-
value: {
|
|
8
|
+
const contextValue = useMemo(()=>({
|
|
10
9
|
isLoading
|
|
11
|
-
},
|
|
10
|
+
}), [
|
|
11
|
+
isLoading
|
|
12
|
+
]);
|
|
13
|
+
return /*#__PURE__*/ jsx(InputContext.Provider, {
|
|
14
|
+
value: contextValue,
|
|
12
15
|
children: /*#__PURE__*/ jsx(Flex, {
|
|
13
16
|
direction: "column",
|
|
14
17
|
alignItems: 'flex-start',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.mjs","sources":["../../../../../admin/src/components/AIChat/components/Input.tsx"],"sourcesContent":["import { createContext, useContext } from 'react';\n\nimport { Box, Flex, Typography } from '@strapi/design-system';\nimport { styled } from 'styled-components';\n\n/* -------------------------------------------------------------------------------------------------\n * Input Context\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface InputContextValue {\n isLoading?: boolean;\n}\n\nexport const InputContext = createContext<InputContextValue>({});\n\nexport const useInput = () => useContext(InputContext);\n\n/* -------------------------------------------------------------------------------------------------\n * Input Root\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface InputRootProps extends React.ComponentPropsWithoutRef<typeof Flex> {\n children: React.ReactNode;\n isLoading?: boolean;\n}\n\nexport const Root = ({ children, isLoading = false, ...props }: InputRootProps) => {\n return (\n <InputContext.Provider
|
|
1
|
+
{"version":3,"file":"Input.mjs","sources":["../../../../../admin/src/components/AIChat/components/Input.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from 'react';\n\nimport { Box, Flex, Typography } from '@strapi/design-system';\nimport { styled } from 'styled-components';\n\n/* -------------------------------------------------------------------------------------------------\n * Input Context\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface InputContextValue {\n isLoading?: boolean;\n}\n\nexport const InputContext = createContext<InputContextValue>({});\n\nexport const useInput = () => useContext(InputContext);\n\n/* -------------------------------------------------------------------------------------------------\n * Input Root\n * -----------------------------------------------------------------------------------------------*/\n\nexport interface InputRootProps extends React.ComponentPropsWithoutRef<typeof Flex> {\n children: React.ReactNode;\n isLoading?: boolean;\n}\n\nexport const Root = ({ children, isLoading = false, ...props }: InputRootProps) => {\n const contextValue = useMemo(() => ({ isLoading }), [isLoading]);\n\n return (\n <InputContext.Provider value={contextValue}>\n <Flex\n direction=\"column\"\n alignItems={'flex-start'}\n width=\"100%\"\n position=\"relative\"\n {...props}\n >\n {children}\n </Flex>\n </InputContext.Provider>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Input Header\n * -----------------------------------------------------------------------------------------------*/\n\ninterface HeaderProps extends React.ComponentPropsWithoutRef<typeof Box> {\n children: React.ReactNode;\n isThinking?: boolean;\n thinkingMessage?: string;\n}\n\nconst Header = ({ children, ...props }: HeaderProps) => {\n return (\n <Box\n position=\"absolute\"\n bottom={'102%'}\n left={0}\n right={0}\n background=\"neutral0\"\n width=\"100%\"\n {...props}\n >\n {children}\n </Box>\n );\n};\n\nconst HeaderItem = styled(Box)`\n padding: ${({ theme }) => theme.spaces[3]} 0};\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * Input Attachments\n * -----------------------------------------------------------------------------------------------*/\ninterface InputAttachmentsProps extends React.ComponentPropsWithoutRef<typeof Flex> {\n children: React.ReactNode;\n}\n\nconst Attachments = ({ children, gap = 2, ...props }: InputAttachmentsProps) => {\n return (\n <Flex gap={gap} wrap=\"wrap\" paddingBottom={2} maxHeight=\"150px\" overflow=\"auto\" {...props}>\n {children}\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Input Content\n * -----------------------------------------------------------------------------------------------*/\n\nconst InputContainer = styled(Box)`\n outline: none;\n box-shadow: none;\n transition-property: border-color, box-shadow, fill;\n transition-duration: 0.2s;\n\n &:focus-within {\n border: 1px solid\n ${({ theme, $hasError }) => ($hasError ? theme.colors.danger600 : theme.colors.primary600)};\n box-shadow: ${({ theme, $hasError }) =>\n $hasError ? theme.colors.danger600 : theme.colors.primary600}\n 0px 0px 0px 2px;\n }\n`;\n\ninterface ContentProps extends React.ComponentPropsWithoutRef<typeof Box> {\n children: React.ReactNode;\n disclaimer?: string;\n error?: boolean;\n}\n\nconst Content = ({ children, disclaimer, error = false, ...props }: ContentProps) => {\n return (\n <InputContainer\n background=\"neutral0\"\n hasRadius\n borderColor={error ? 'danger600' : 'neutral200'}\n borderWidth=\"1px\"\n borderStyle=\"solid\"\n width=\"100%\"\n $hasError={error}\n {...props}\n >\n <Box padding={3}>{children}</Box>\n {disclaimer && (\n <Box\n background=\"neutral100\"\n padding={[2, 3]}\n borderColor=\"neutral200\"\n borderWidth=\"1px 0 0 0\"\n borderStyle=\"solid\"\n borderRadius={'0 0 4px 4px'}\n >\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {disclaimer}\n </Typography>\n </Box>\n )}\n </InputContainer>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Input Actions\n * -----------------------------------------------------------------------------------------------*/\n\nconst Actions = ({ children }: { children: React.ReactNode }) => {\n return (\n <Flex justifyContent=\"flex-end\" alignItems=\"center\" gap={2}>\n {children}\n </Flex>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * Input Compound\n * -----------------------------------------------------------------------------------------------*/\n\nexport const Input = {\n Root,\n Header,\n HeaderItem,\n Attachments,\n Content,\n Actions,\n useInput,\n};\n"],"names":["InputContext","createContext","Root","children","isLoading","props","contextValue","useMemo","_jsx","Provider","value","Flex","direction","alignItems","width","position","Header","Box","bottom","left","right","background","HeaderItem","styled","theme","spaces","Attachments","gap","wrap","paddingBottom","maxHeight","overflow","InputContainer","$hasError","colors","danger600","primary600","Content","disclaimer","error","_jsxs","hasRadius","borderColor","borderWidth","borderStyle","padding","borderRadius","Typography","variant","textColor","Actions","justifyContent","Input"],"mappings":";;;;;AAaO,MAAMA,YAAAA,iBAAeC,aAAAA,CAAiC,EAAC;AAavD,MAAMC,IAAAA,GAAO,CAAC,EAAEC,QAAQ,EAAEC,SAAAA,GAAY,KAAK,EAAE,GAAGC,KAAAA,EAAuB,GAAA;IAC5E,MAAMC,YAAAA,GAAeC,OAAAA,CAAQ,KAAO;AAAEH,YAAAA;AAAU,SAAA,CAAA,EAAI;AAACA,QAAAA;AAAU,KAAA,CAAA;IAE/D,qBACEI,GAAA,CAACR,aAAaS,QAAQ,EAAA;QAACC,KAAAA,EAAOJ,YAAAA;AAC5B,QAAA,QAAA,gBAAAE,GAAA,CAACG,IAAAA,EAAAA;YACCC,SAAAA,EAAU,QAAA;YACVC,UAAAA,EAAY,YAAA;YACZC,KAAAA,EAAM,MAAA;YACNC,QAAAA,EAAS,UAAA;AACR,YAAA,GAAGV,KAAK;AAERF,YAAAA,QAAAA,EAAAA;;;AAIT;AAYA,MAAMa,SAAS,CAAC,EAAEb,QAAQ,EAAE,GAAGE,KAAAA,EAAoB,GAAA;AACjD,IAAA,qBACEG,GAAA,CAACS,GAAAA,EAAAA;QACCF,QAAAA,EAAS,UAAA;QACTG,MAAAA,EAAQ,MAAA;QACRC,IAAAA,EAAM,CAAA;QACNC,KAAAA,EAAO,CAAA;QACPC,UAAAA,EAAW,UAAA;QACXP,KAAAA,EAAM,MAAA;AACL,QAAA,GAAGT,KAAK;AAERF,QAAAA,QAAAA,EAAAA;;AAGP,CAAA;AAEA,MAAMmB,UAAAA,GAAaC,MAAAA,CAAON,GAAAA,CAAI;WACnB,EAAE,CAAC,EAAEO,KAAK,EAAE,GAAKA,KAAAA,CAAMC,MAAM,CAAC,CAAA,CAAE,CAAC;AAC5C,CAAC;AASD,MAAMC,WAAAA,GAAc,CAAC,EAAEvB,QAAQ,EAAEwB,GAAAA,GAAM,CAAC,EAAE,GAAGtB,KAAAA,EAA8B,GAAA;AACzE,IAAA,qBACEG,GAAA,CAACG,IAAAA,EAAAA;QAAKgB,GAAAA,EAAKA,GAAAA;QAAKC,IAAAA,EAAK,MAAA;QAAOC,aAAAA,EAAe,CAAA;QAAGC,SAAAA,EAAU,OAAA;QAAQC,QAAAA,EAAS,MAAA;AAAQ,QAAA,GAAG1B,KAAK;AACtFF,QAAAA,QAAAA,EAAAA;;AAGP,CAAA;AAEA;;AAEkG,qGAElG,MAAM6B,cAAAA,GAAiBT,MAAAA,CAAON,GAAAA,CAAI;;;;;;;;AAQ5B,MAAA,EAAE,CAAC,EAAEO,KAAK,EAAES,SAAS,EAAE,GAAMA,SAAAA,GAAYT,KAAAA,CAAMU,MAAM,CAACC,SAAS,GAAGX,MAAMU,MAAM,CAACE,UAAU,CAAE;AACjF,gBAAA,EAAE,CAAC,EAAEZ,KAAK,EAAES,SAAS,EAAE,GAC/BA,SAAAA,GAAYT,KAAAA,CAAMU,MAAM,CAACC,SAAS,GAAGX,MAAMU,MAAM,CAACE,UAAU;;;AAGpE,CAAC;AAQD,MAAMC,OAAAA,GAAU,CAAC,EAAElC,QAAQ,EAAEmC,UAAU,EAAEC,KAAAA,GAAQ,KAAK,EAAE,GAAGlC,KAAAA,EAAqB,GAAA;AAC9E,IAAA,qBACEmC,IAAA,CAACR,cAAAA,EAAAA;QACCX,UAAAA,EAAW,UAAA;QACXoB,SAAS,EAAA,IAAA;AACTC,QAAAA,WAAAA,EAAaH,QAAQ,WAAA,GAAc,YAAA;QACnCI,WAAAA,EAAY,KAAA;QACZC,WAAAA,EAAY,OAAA;QACZ9B,KAAAA,EAAM,MAAA;QACNmB,SAAAA,EAAWM,KAAAA;AACV,QAAA,GAAGlC,KAAK;;0BAETG,GAAA,CAACS,GAAAA,EAAAA;gBAAI4B,OAAAA,EAAS,CAAA;AAAI1C,gBAAAA,QAAAA,EAAAA;;AACjBmC,YAAAA,UAAAA,kBACC9B,GAAA,CAACS,GAAAA,EAAAA;gBACCI,UAAAA,EAAW,YAAA;gBACXwB,OAAAA,EAAS;AAAC,oBAAA,CAAA;AAAG,oBAAA;AAAE,iBAAA;gBACfH,WAAAA,EAAY,YAAA;gBACZC,WAAAA,EAAY,WAAA;gBACZC,WAAAA,EAAY,OAAA;gBACZE,YAAAA,EAAc,aAAA;AAEd,gBAAA,QAAA,gBAAAtC,GAAA,CAACuC,UAAAA,EAAAA;oBAAWC,OAAAA,EAAQ,IAAA;oBAAKC,SAAAA,EAAU,YAAA;AAChCX,oBAAAA,QAAAA,EAAAA;;;;;AAMb,CAAA;AAEA;;AAEkG,qGAElG,MAAMY,OAAAA,GAAU,CAAC,EAAE/C,QAAQ,EAAiC,GAAA;AAC1D,IAAA,qBACEK,GAAA,CAACG,IAAAA,EAAAA;QAAKwC,cAAAA,EAAe,UAAA;QAAWtC,UAAAA,EAAW,QAAA;QAASc,GAAAA,EAAK,CAAA;AACtDxB,QAAAA,QAAAA,EAAAA;;AAGP,CAAA;AAEA;;2GAIaiD,KAAAA,GAAQ;AACnBlD,IAAAA,IAAAA;AACAc,IAAAA,MAAAA;AACAM,IAAAA,UAAAA;AACAI,IAAAA,WAAAA;AACAW,IAAAA,OAAAA;AACAa,IAAAA,OAEF;;;;"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var React = require('react');
|
|
4
5
|
var designSystem = require('@strapi/design-system');
|
|
5
6
|
var Icons = require('@strapi/icons');
|
|
6
7
|
var Markdown = require('react-markdown');
|
|
@@ -87,6 +88,77 @@ const isSchemaToolPart = (part)=>{
|
|
|
87
88
|
}
|
|
88
89
|
return part.type === 'tool-schemaGenerationTool';
|
|
89
90
|
};
|
|
91
|
+
/**
|
|
92
|
+
* Exported for unit tests only. The AI chat needs a live AI backend, so no E2E
|
|
93
|
+
* run can reach this logic.
|
|
94
|
+
*/ const getPartFingerprint = (part)=>{
|
|
95
|
+
if (part.type === 'text') {
|
|
96
|
+
return `text:${part.text}`;
|
|
97
|
+
}
|
|
98
|
+
if (part.type === 'file') {
|
|
99
|
+
return `file:${part.filename ?? ''}:${part.mediaType}:${part.url}`;
|
|
100
|
+
}
|
|
101
|
+
if ('toolCallId' in part && typeof part.toolCallId === 'string') {
|
|
102
|
+
return `${part.type}:${part.toolCallId}`;
|
|
103
|
+
}
|
|
104
|
+
return part.type;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Gives each part a key that survives across renders. A key derived from the
|
|
108
|
+
* part content alone cannot work: a streaming text part changes on every chunk,
|
|
109
|
+
* so its fingerprint would change on every tick and remount the node mid
|
|
110
|
+
* stream. Hence the fallback chain below: exact fingerprint match first, then
|
|
111
|
+
* object identity, then same slot and same type for the streaming case.
|
|
112
|
+
*
|
|
113
|
+
* Exported for unit tests only. The AI chat needs a live AI backend, so no E2E
|
|
114
|
+
* run can reach this logic.
|
|
115
|
+
*/ const usePartsWithKeys = (parts)=>{
|
|
116
|
+
const keyPrefix = React.useId();
|
|
117
|
+
const nextKey = React.useRef(0);
|
|
118
|
+
const previousParts = React.useRef([]);
|
|
119
|
+
const matchedParts = new Set();
|
|
120
|
+
const exactMatches = parts.map((part)=>{
|
|
121
|
+
const fingerprint = getPartFingerprint(part);
|
|
122
|
+
const exactMatch = previousParts.current.find((candidate)=>candidate.fingerprint === fingerprint && !matchedParts.has(candidate));
|
|
123
|
+
const sameObject = previousParts.current.find((candidate)=>candidate.part === part && !matchedParts.has(candidate));
|
|
124
|
+
const previousPart = exactMatch ?? sameObject;
|
|
125
|
+
if (previousPart) {
|
|
126
|
+
matchedParts.add(previousPart);
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
fingerprint,
|
|
130
|
+
part,
|
|
131
|
+
previousPart
|
|
132
|
+
};
|
|
133
|
+
});
|
|
134
|
+
const keyedParts = exactMatches.map(({ fingerprint, part, previousPart }, index)=>{
|
|
135
|
+
const sameSlot = previousParts.current[index];
|
|
136
|
+
const streamingMatch = !previousPart && sameSlot && sameSlot.part.type === part.type && !matchedParts.has(sameSlot) ? sameSlot : undefined;
|
|
137
|
+
const matchedPart = previousPart ?? streamingMatch;
|
|
138
|
+
const key = matchedPart?.key ?? `${keyPrefix}-${nextKey.current}`;
|
|
139
|
+
if (streamingMatch) {
|
|
140
|
+
matchedParts.add(streamingMatch);
|
|
141
|
+
}
|
|
142
|
+
if (matchedPart) {
|
|
143
|
+
matchedParts.add(matchedPart);
|
|
144
|
+
} else {
|
|
145
|
+
nextKey.current += 1;
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
fingerprint,
|
|
149
|
+
key,
|
|
150
|
+
part
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
/**
|
|
154
|
+
* Both refs are written during render. The outcome depends only on the parts
|
|
155
|
+
* passed in, so re-invoking the render function is harmless: on the second
|
|
156
|
+
* pass of a StrictMode double render every part exact-matches the record the
|
|
157
|
+
* first pass stored here, the same keys come back out and `nextKey` does not
|
|
158
|
+
* advance.
|
|
159
|
+
*/ previousParts.current = keyedParts;
|
|
160
|
+
return keyedParts;
|
|
161
|
+
};
|
|
90
162
|
const capitalize = (s)=>s ? s.charAt(0).toUpperCase() + s.slice(1) : '';
|
|
91
163
|
const getSchemaLink = (schema)=>{
|
|
92
164
|
const isComponent = (schema.kind ?? schema.modelType) === 'component';
|
|
@@ -137,8 +209,9 @@ const MessageContent = ({ part })=>{
|
|
|
137
209
|
return null;
|
|
138
210
|
};
|
|
139
211
|
const UserMessage = ({ message })=>{
|
|
140
|
-
const
|
|
141
|
-
const
|
|
212
|
+
const partsWithKeys = usePartsWithKeys(message.parts);
|
|
213
|
+
const hasText = partsWithKeys.some(({ part })=>part.type === 'text' && part.text.trim() !== '');
|
|
214
|
+
const attachments = partsWithKeys.filter(({ part })=>part.type === 'file');
|
|
142
215
|
return /*#__PURE__*/ jsxRuntime.jsxs(AnimatedBox.AnimatedBox, {
|
|
143
216
|
as: designSystem.Flex,
|
|
144
217
|
direction: "column",
|
|
@@ -157,35 +230,36 @@ const UserMessage = ({ message })=>{
|
|
|
157
230
|
'16px'
|
|
158
231
|
],
|
|
159
232
|
hasRadius: true,
|
|
160
|
-
children:
|
|
161
|
-
if (
|
|
233
|
+
children: partsWithKeys.map(({ key, part })=>{
|
|
234
|
+
if (part.type !== 'text') return null;
|
|
162
235
|
return /*#__PURE__*/ jsxRuntime.jsx(UserMessageTypography, {
|
|
163
|
-
children:
|
|
164
|
-
},
|
|
236
|
+
children: part.text
|
|
237
|
+
}, key);
|
|
165
238
|
})
|
|
166
239
|
}) : null,
|
|
167
|
-
attachments.map((
|
|
240
|
+
attachments.map(({ key, part })=>/*#__PURE__*/ jsxRuntime.jsx(AttachmentPreview.AttachmentPreview, {
|
|
168
241
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
169
242
|
attachment: {
|
|
170
|
-
...
|
|
243
|
+
...part,
|
|
171
244
|
status: 'ready'
|
|
172
245
|
}
|
|
173
|
-
},
|
|
246
|
+
}, key))
|
|
174
247
|
]
|
|
175
248
|
});
|
|
176
249
|
};
|
|
177
250
|
const AssistantMessage = ({ message, isLoading })=>{
|
|
178
251
|
const { upvoteMessage } = useFeedback.useFeedback();
|
|
179
252
|
const { openFeedbackModal } = FeedbackModal.useFeedbackModal();
|
|
253
|
+
const partsWithKeys = usePartsWithKeys(message.parts);
|
|
180
254
|
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Box, {
|
|
181
255
|
style: {
|
|
182
256
|
alignSelf: 'flex-start'
|
|
183
257
|
},
|
|
184
258
|
maxWidth: "90%",
|
|
185
259
|
children: [
|
|
186
|
-
|
|
187
|
-
part:
|
|
188
|
-
},
|
|
260
|
+
partsWithKeys.map(({ key, part })=>/*#__PURE__*/ jsxRuntime.jsx(MessageContent, {
|
|
261
|
+
part: part
|
|
262
|
+
}, key)),
|
|
189
263
|
isLoading ? /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
190
264
|
gap: 1,
|
|
191
265
|
children: [
|
|
@@ -226,4 +300,6 @@ const ChatMessage = ({ message })=>{
|
|
|
226
300
|
};
|
|
227
301
|
|
|
228
302
|
exports.ChatMessage = ChatMessage;
|
|
303
|
+
exports.getPartFingerprint = getPartFingerprint;
|
|
304
|
+
exports.usePartsWithKeys = usePartsWithKeys;
|
|
229
305
|
//# sourceMappingURL=Message.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Message.js","sources":["../../../../../../admin/src/components/AIChat/components/Messages/Message.tsx"],"sourcesContent":["import { Typography, Box, IconButton, Flex } from '@strapi/design-system';\nimport { ThumbUp, ThumbDown } from '@strapi/icons';\nimport Markdown from 'react-markdown';\nimport { styled } from 'styled-components';\n\nimport { useFeedbackModal } from '../../FeedbackModal';\nimport { useFeedback } from '../../hooks/useFeedback';\nimport {\n AIMessage,\n type UserMessage as UserMessageType,\n AssistantMessage as AssistantMessageType,\n type MarkerContent as MarkerContentType,\n} from '../../lib/types/messages';\nimport { AnimatedBox } from '../AnimatedBox';\nimport { AttachmentPreview } from '../Attachments/AttachmentPreview';\n\nimport { Marker } from './Marker';\n\nconst MarkdownStyles = styled(Typography)`\n max-width: 65ch;\n margin: 0 auto;\n overflow-wrap: anywhere;\n word-break: break-word;\n\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n margin-top: 1.25em;\n margin-bottom: 0.5em;\n font-weight: bold;\n }\n\n p {\n margin-bottom: 1em;\n }\n\n ul,\n ol {\n padding-left: 1.5em; /* indentation for bullet points */\n margin-bottom: 1em;\n }\n\n li {\n margin-bottom: 0.5em;\n list-style-type: disc; /* or whatever style you prefer */\n }\n\n strong {\n font-weight: bold;\n }\n\n /* code blocks, blockquotes, etc. */\n code {\n background-color: ${({ theme }) => theme.colors.neutral100};\n padding: 0.2em 0.4em;\n border-radius: ${({ theme }) => theme.borderRadius};\n border-color: ${({ theme }) => theme.colors.neutral150};\n border-style: solid;\n font-family:\n 'SF Mono', SFMono-Regular, ui-monospace, 'DejaVu Sans Mono', Menlo, Consolas, monospace;\n }\n\n /* links */\n a {\n color: ${({ theme }) => theme.colors.primary500};\n background-color: ${({ theme }) => theme.colors.neutral100};\n padding: 0.2em 0.4em;\n border-radius: ${({ theme }) => theme.borderRadius};\n border-color: ${({ theme }) => theme.colors.neutral150};\n border-style: solid;\n text-decoration: none;\n\n &:hover {\n text-decoration: underline;\n }\n }\n`;\n\nconst UserMessageTypography = styled(Typography)`\n overflow-wrap: anywhere;\n word-break: break-word;\n`;\n\n// ---------------------------\n// Tool: schemaGenerationTool helpers\n// ---------------------------\n\ntype SchemaToolSchema = {\n action?: 'create' | 'update' | 'remove';\n uid?: string;\n name?: string;\n category?: string;\n kind?: 'collectionType' | 'singleType' | 'component';\n modelType?: 'component' | 'collectionType' | 'singleType';\n};\n\ntype SchemaToolPart = {\n type: 'tool-schemaGenerationTool';\n input?: { schemas?: SchemaToolSchema[] };\n output?: { schemas?: SchemaToolSchema[]; error?: unknown };\n toolCallId?: string;\n};\n\nconst isSchemaToolPart = (part: unknown): part is SchemaToolPart => {\n if (typeof part !== 'object' || part === null || !('type' in part)) {\n return false;\n }\n\n return part.type === 'tool-schemaGenerationTool';\n};\n\nconst capitalize = (s?: string) => (s ? s.charAt(0).toUpperCase() + s.slice(1) : '');\n\nconst getSchemaLink = (schema: SchemaToolSchema): string | undefined => {\n const isComponent = (schema.kind ?? schema.modelType) === 'component';\n if (!schema.uid) return undefined;\n return isComponent\n ? `/plugins/content-type-builder/component-categories/${schema.category ?? ''}/${schema.uid}`\n : `/plugins/content-type-builder/content-types/${schema.uid}`;\n};\n\nconst toMarkerFromSchemaTool = (part: SchemaToolPart): MarkerContentType => {\n const outSchemas = part.output?.schemas ?? [];\n const inSchemas = part.input?.schemas ?? [];\n\n const schemas = (outSchemas.length ? outSchemas : inSchemas) as SchemaToolSchema[];\n const numSchemas = schemas.length;\n\n const state: 'loading' | 'success' | 'error' = part.output\n ? part.output.error\n ? 'error'\n : 'success'\n : 'loading';\n\n const steps = schemas.map((schema, index) => ({\n id: `${part.toolCallId ?? 'schemaGenerationTool'}-${schema.uid ?? schema.name ?? index}`,\n description: capitalize(schema.name ?? schema.uid ?? 'Schema'),\n status:\n schema.action === 'create' || schema.action === 'update' || schema.action === 'remove'\n ? schema.action\n : ('update' as const),\n link: getSchemaLink(schema),\n }));\n\n const title =\n state === 'success'\n ? `Updated ${numSchemas} schema${numSchemas === 1 ? '' : 's'}`\n : state === 'error'\n ? `Failed to update schema${numSchemas === 1 ? '' : 's'}`\n : 'Updating schemas';\n\n return {\n type: 'marker',\n title,\n state,\n steps,\n };\n};\n\nconst MessageContent = ({\n part,\n}: {\n part: AIMessage['parts'][number];\n status?: 'loading' | 'success' | 'error';\n}) => {\n if (part.type === 'text') {\n return (\n <MarkdownStyles>\n <Markdown\n components={{\n a: ({ node: _node, ...props }) => (\n <a target=\"_blank\" rel=\"noopener noreferrer\" {...props} />\n ),\n }}\n >\n {part.text}\n </Markdown>\n </MarkdownStyles>\n );\n }\n\n if (isSchemaToolPart(part)) {\n const marker = toMarkerFromSchemaTool(part);\n return <Marker {...marker} />;\n }\n\n return null;\n};\n\nconst UserMessage = ({ message }: { message: UserMessageType }) => {\n const hasText = message.parts.some(\n (content) => content.type === 'text' && content.text.trim() !== ''\n );\n const attachments = message.parts.filter((content) => content.type === 'file');\n\n return (\n <AnimatedBox\n as={Flex}\n direction=\"column\"\n alignItems=\"flex-end\"\n style={{ alignSelf: 'flex-end' }}\n gap={2}\n maxWidth=\"80%\"\n >\n {hasText ? (\n <Box background=\"neutral150\" borderStyle=\"none\" padding={['10px', '16px']} hasRadius>\n {message.parts.map((content, index) => {\n if (content.type !== 'text') return null;\n return <UserMessageTypography key={index}>{content.text}</UserMessageTypography>;\n })}\n </Box>\n ) : null}\n\n {/* Attachments */}\n {attachments.map((attachment, idx) => (\n <AttachmentPreview\n key={`${attachment.type === 'file' ? attachment.filename : attachment.type}-${idx}`}\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n attachment={{ ...attachment, status: 'ready' } as any}\n />\n ))}\n </AnimatedBox>\n );\n};\n\nconst AssistantMessage = ({\n message,\n isLoading,\n}: {\n message: AssistantMessageType;\n isLoading?: boolean;\n}) => {\n const { upvoteMessage } = useFeedback();\n const { openFeedbackModal } = useFeedbackModal();\n\n return (\n <Box style={{ alignSelf: 'flex-start' }} maxWidth=\"90%\">\n {message.parts.map((content, index) => (\n <MessageContent key={index} part={content} />\n ))}\n {isLoading ? (\n <Flex gap={1}>\n <IconButton\n label=\"Upvote\"\n size=\"XS\"\n variant=\"ghost\"\n onClick={() => upvoteMessage(message.id)}\n >\n <ThumbUp />\n </IconButton>\n <IconButton\n label=\"Downvote\"\n size=\"XS\"\n variant=\"ghost\"\n // For downvoting, user must provide specific feedback\n onClick={() => openFeedbackModal(message.id)}\n >\n <ThumbDown />\n </IconButton>\n </Flex>\n ) : null}\n </Box>\n );\n};\n\nexport const ChatMessage = ({ message }: { message: AIMessage }) => {\n /**\n * IMPORTANT: Messages are rendered using react-markdown (heavy compute)\n * Component re-renders on each message update, but AI SDK v5 provides\n * throttling (experimental_throttle: 100ms) which batches updates and reduces\n * re-render frequency during streaming.\n */\n if (message.role === 'user') {\n return <UserMessage message={message as UserMessageType} />;\n }\n return <AssistantMessage message={message as AssistantMessageType} />;\n};\n"],"names":["MarkdownStyles","styled","Typography","theme","colors","neutral100","borderRadius","neutral150","primary500","UserMessageTypography","isSchemaToolPart","part","type","capitalize","s","charAt","toUpperCase","slice","getSchemaLink","schema","isComponent","kind","modelType","uid","undefined","category","toMarkerFromSchemaTool","outSchemas","output","schemas","inSchemas","input","length","numSchemas","state","error","steps","map","index","id","toolCallId","name","description","status","action","link","title","MessageContent","_jsx","Markdown","components","a","node","_node","props","target","rel","text","marker","Marker","UserMessage","message","hasText","parts","some","content","trim","attachments","filter","_jsxs","AnimatedBox","as","Flex","direction","alignItems","style","alignSelf","gap","maxWidth","Box","background","borderStyle","padding","hasRadius","attachment","idx","AttachmentPreview","filename","AssistantMessage","isLoading","upvoteMessage","useFeedback","openFeedbackModal","useFeedbackModal","IconButton","label","size","variant","onClick","ThumbUp","ThumbDown","ChatMessage","role"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Message.js","sources":["../../../../../../admin/src/components/AIChat/components/Messages/Message.tsx"],"sourcesContent":["import { useId, useRef } from 'react';\n\nimport { Typography, Box, IconButton, Flex } from '@strapi/design-system';\nimport { ThumbUp, ThumbDown } from '@strapi/icons';\nimport Markdown from 'react-markdown';\nimport { styled } from 'styled-components';\n\nimport { useFeedbackModal } from '../../FeedbackModal';\nimport { useFeedback } from '../../hooks/useFeedback';\nimport {\n AIMessage,\n type UserMessage as UserMessageType,\n AssistantMessage as AssistantMessageType,\n type MarkerContent as MarkerContentType,\n} from '../../lib/types/messages';\nimport { AnimatedBox } from '../AnimatedBox';\nimport { AttachmentPreview } from '../Attachments/AttachmentPreview';\n\nimport { Marker } from './Marker';\n\nconst MarkdownStyles = styled(Typography)`\n max-width: 65ch;\n margin: 0 auto;\n overflow-wrap: anywhere;\n word-break: break-word;\n\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n margin-top: 1.25em;\n margin-bottom: 0.5em;\n font-weight: bold;\n }\n\n p {\n margin-bottom: 1em;\n }\n\n ul,\n ol {\n padding-left: 1.5em; /* indentation for bullet points */\n margin-bottom: 1em;\n }\n\n li {\n margin-bottom: 0.5em;\n list-style-type: disc; /* or whatever style you prefer */\n }\n\n strong {\n font-weight: bold;\n }\n\n /* code blocks, blockquotes, etc. */\n code {\n background-color: ${({ theme }) => theme.colors.neutral100};\n padding: 0.2em 0.4em;\n border-radius: ${({ theme }) => theme.borderRadius};\n border-color: ${({ theme }) => theme.colors.neutral150};\n border-style: solid;\n font-family:\n 'SF Mono', SFMono-Regular, ui-monospace, 'DejaVu Sans Mono', Menlo, Consolas, monospace;\n }\n\n /* links */\n a {\n color: ${({ theme }) => theme.colors.primary500};\n background-color: ${({ theme }) => theme.colors.neutral100};\n padding: 0.2em 0.4em;\n border-radius: ${({ theme }) => theme.borderRadius};\n border-color: ${({ theme }) => theme.colors.neutral150};\n border-style: solid;\n text-decoration: none;\n\n &:hover {\n text-decoration: underline;\n }\n }\n`;\n\nconst UserMessageTypography = styled(Typography)`\n overflow-wrap: anywhere;\n word-break: break-word;\n`;\n\n// ---------------------------\n// Tool: schemaGenerationTool helpers\n// ---------------------------\n\ntype SchemaToolSchema = {\n action?: 'create' | 'update' | 'remove';\n uid?: string;\n name?: string;\n category?: string;\n kind?: 'collectionType' | 'singleType' | 'component';\n modelType?: 'component' | 'collectionType' | 'singleType';\n};\n\ntype SchemaToolPart = {\n type: 'tool-schemaGenerationTool';\n input?: { schemas?: SchemaToolSchema[] };\n output?: { schemas?: SchemaToolSchema[]; error?: unknown };\n toolCallId?: string;\n};\n\nconst isSchemaToolPart = (part: unknown): part is SchemaToolPart => {\n if (typeof part !== 'object' || part === null || !('type' in part)) {\n return false;\n }\n\n return part.type === 'tool-schemaGenerationTool';\n};\n\n/**\n * Exported for unit tests only. The AI chat needs a live AI backend, so no E2E\n * run can reach this logic.\n */\nexport const getPartFingerprint = (part: AIMessage['parts'][number]) => {\n if (part.type === 'text') {\n return `text:${part.text}`;\n }\n\n if (part.type === 'file') {\n return `file:${part.filename ?? ''}:${part.mediaType}:${part.url}`;\n }\n\n if ('toolCallId' in part && typeof part.toolCallId === 'string') {\n return `${part.type}:${part.toolCallId}`;\n }\n\n return part.type;\n};\n\ntype PartRecord = {\n fingerprint: string;\n key: string;\n part: AIMessage['parts'][number];\n};\n\n/**\n * Gives each part a key that survives across renders. A key derived from the\n * part content alone cannot work: a streaming text part changes on every chunk,\n * so its fingerprint would change on every tick and remount the node mid\n * stream. Hence the fallback chain below: exact fingerprint match first, then\n * object identity, then same slot and same type for the streaming case.\n *\n * Exported for unit tests only. The AI chat needs a live AI backend, so no E2E\n * run can reach this logic.\n */\nexport const usePartsWithKeys = (parts: AIMessage['parts']) => {\n const keyPrefix = useId();\n const nextKey = useRef(0);\n const previousParts = useRef<PartRecord[]>([]);\n const matchedParts = new Set<PartRecord>();\n\n const exactMatches = parts.map((part) => {\n const fingerprint = getPartFingerprint(part);\n const exactMatch = previousParts.current.find(\n (candidate) => candidate.fingerprint === fingerprint && !matchedParts.has(candidate)\n );\n const sameObject = previousParts.current.find(\n (candidate) => candidate.part === part && !matchedParts.has(candidate)\n );\n const previousPart = exactMatch ?? sameObject;\n\n if (previousPart) {\n matchedParts.add(previousPart);\n }\n\n return { fingerprint, part, previousPart };\n });\n\n const keyedParts = exactMatches.map(({ fingerprint, part, previousPart }, index) => {\n const sameSlot = previousParts.current[index];\n const streamingMatch =\n !previousPart && sameSlot && sameSlot.part.type === part.type && !matchedParts.has(sameSlot)\n ? sameSlot\n : undefined;\n const matchedPart = previousPart ?? streamingMatch;\n const key = matchedPart?.key ?? `${keyPrefix}-${nextKey.current}`;\n\n if (streamingMatch) {\n matchedParts.add(streamingMatch);\n }\n\n if (matchedPart) {\n matchedParts.add(matchedPart);\n } else {\n nextKey.current += 1;\n }\n\n return { fingerprint, key, part };\n });\n\n /**\n * Both refs are written during render. The outcome depends only on the parts\n * passed in, so re-invoking the render function is harmless: on the second\n * pass of a StrictMode double render every part exact-matches the record the\n * first pass stored here, the same keys come back out and `nextKey` does not\n * advance.\n */\n previousParts.current = keyedParts;\n\n return keyedParts;\n};\n\nconst capitalize = (s?: string) => (s ? s.charAt(0).toUpperCase() + s.slice(1) : '');\n\nconst getSchemaLink = (schema: SchemaToolSchema): string | undefined => {\n const isComponent = (schema.kind ?? schema.modelType) === 'component';\n if (!schema.uid) return undefined;\n return isComponent\n ? `/plugins/content-type-builder/component-categories/${schema.category ?? ''}/${schema.uid}`\n : `/plugins/content-type-builder/content-types/${schema.uid}`;\n};\n\nconst toMarkerFromSchemaTool = (part: SchemaToolPart): MarkerContentType => {\n const outSchemas = part.output?.schemas ?? [];\n const inSchemas = part.input?.schemas ?? [];\n\n const schemas = (outSchemas.length ? outSchemas : inSchemas) as SchemaToolSchema[];\n const numSchemas = schemas.length;\n\n const state: 'loading' | 'success' | 'error' = part.output\n ? part.output.error\n ? 'error'\n : 'success'\n : 'loading';\n\n const steps = schemas.map((schema, index) => ({\n id: `${part.toolCallId ?? 'schemaGenerationTool'}-${schema.uid ?? schema.name ?? index}`,\n description: capitalize(schema.name ?? schema.uid ?? 'Schema'),\n status:\n schema.action === 'create' || schema.action === 'update' || schema.action === 'remove'\n ? schema.action\n : ('update' as const),\n link: getSchemaLink(schema),\n }));\n\n const title =\n state === 'success'\n ? `Updated ${numSchemas} schema${numSchemas === 1 ? '' : 's'}`\n : state === 'error'\n ? `Failed to update schema${numSchemas === 1 ? '' : 's'}`\n : 'Updating schemas';\n\n return {\n type: 'marker',\n title,\n state,\n steps,\n };\n};\n\nconst MessageContent = ({\n part,\n}: {\n part: AIMessage['parts'][number];\n status?: 'loading' | 'success' | 'error';\n}) => {\n if (part.type === 'text') {\n return (\n <MarkdownStyles>\n <Markdown\n components={{\n a: ({ node: _node, ...props }) => (\n <a target=\"_blank\" rel=\"noopener noreferrer\" {...props} />\n ),\n }}\n >\n {part.text}\n </Markdown>\n </MarkdownStyles>\n );\n }\n\n if (isSchemaToolPart(part)) {\n const marker = toMarkerFromSchemaTool(part);\n return <Marker {...marker} />;\n }\n\n return null;\n};\n\nconst UserMessage = ({ message }: { message: UserMessageType }) => {\n const partsWithKeys = usePartsWithKeys(message.parts);\n const hasText = partsWithKeys.some(({ part }) => part.type === 'text' && part.text.trim() !== '');\n const attachments = partsWithKeys.filter(({ part }) => part.type === 'file');\n\n return (\n <AnimatedBox\n as={Flex}\n direction=\"column\"\n alignItems=\"flex-end\"\n style={{ alignSelf: 'flex-end' }}\n gap={2}\n maxWidth=\"80%\"\n >\n {hasText ? (\n <Box background=\"neutral150\" borderStyle=\"none\" padding={['10px', '16px']} hasRadius>\n {partsWithKeys.map(({ key, part }) => {\n if (part.type !== 'text') return null;\n return <UserMessageTypography key={key}>{part.text}</UserMessageTypography>;\n })}\n </Box>\n ) : null}\n\n {/* Attachments */}\n {attachments.map(({ key, part }) => (\n <AttachmentPreview\n key={key}\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n attachment={{ ...part, status: 'ready' } as any}\n />\n ))}\n </AnimatedBox>\n );\n};\n\nconst AssistantMessage = ({\n message,\n isLoading,\n}: {\n message: AssistantMessageType;\n isLoading?: boolean;\n}) => {\n const { upvoteMessage } = useFeedback();\n const { openFeedbackModal } = useFeedbackModal();\n const partsWithKeys = usePartsWithKeys(message.parts);\n\n return (\n <Box style={{ alignSelf: 'flex-start' }} maxWidth=\"90%\">\n {partsWithKeys.map(({ key, part }) => (\n <MessageContent key={key} part={part} />\n ))}\n {isLoading ? (\n <Flex gap={1}>\n <IconButton\n label=\"Upvote\"\n size=\"XS\"\n variant=\"ghost\"\n onClick={() => upvoteMessage(message.id)}\n >\n <ThumbUp />\n </IconButton>\n <IconButton\n label=\"Downvote\"\n size=\"XS\"\n variant=\"ghost\"\n // For downvoting, user must provide specific feedback\n onClick={() => openFeedbackModal(message.id)}\n >\n <ThumbDown />\n </IconButton>\n </Flex>\n ) : null}\n </Box>\n );\n};\n\nexport const ChatMessage = ({ message }: { message: AIMessage }) => {\n /**\n * IMPORTANT: Messages are rendered using react-markdown (heavy compute)\n * Component re-renders on each message update, but AI SDK v5 provides\n * throttling (experimental_throttle: 100ms) which batches updates and reduces\n * re-render frequency during streaming.\n */\n if (message.role === 'user') {\n return <UserMessage message={message as UserMessageType} />;\n }\n return <AssistantMessage message={message as AssistantMessageType} />;\n};\n"],"names":["MarkdownStyles","styled","Typography","theme","colors","neutral100","borderRadius","neutral150","primary500","UserMessageTypography","isSchemaToolPart","part","type","getPartFingerprint","text","filename","mediaType","url","toolCallId","usePartsWithKeys","parts","keyPrefix","useId","nextKey","useRef","previousParts","matchedParts","Set","exactMatches","map","fingerprint","exactMatch","current","find","candidate","has","sameObject","previousPart","add","keyedParts","index","sameSlot","streamingMatch","undefined","matchedPart","key","capitalize","s","charAt","toUpperCase","slice","getSchemaLink","schema","isComponent","kind","modelType","uid","category","toMarkerFromSchemaTool","outSchemas","output","schemas","inSchemas","input","length","numSchemas","state","error","steps","id","name","description","status","action","link","title","MessageContent","_jsx","Markdown","components","a","node","_node","props","target","rel","marker","Marker","UserMessage","message","partsWithKeys","hasText","some","trim","attachments","filter","_jsxs","AnimatedBox","as","Flex","direction","alignItems","style","alignSelf","gap","maxWidth","Box","background","borderStyle","padding","hasRadius","AttachmentPreview","attachment","AssistantMessage","isLoading","upvoteMessage","useFeedback","openFeedbackModal","useFeedbackModal","IconButton","label","size","variant","onClick","ThumbUp","ThumbDown","ChatMessage","role"],"mappings":"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"}
|