@strapi/content-type-builder 5.29.0 → 5.30.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/components/AIChat/Chat.js +1 -0
- package/dist/admin/components/AIChat/Chat.js.map +1 -1
- package/dist/admin/components/AIChat/Chat.mjs +1 -0
- package/dist/admin/components/AIChat/Chat.mjs.map +1 -1
- package/dist/admin/components/AIChat/FeedbackModal.js.map +1 -1
- package/dist/admin/components/AIChat/FeedbackModal.mjs.map +1 -1
- package/dist/admin/components/AIChat/UploadFigmaModal.js +2 -1
- package/dist/admin/components/AIChat/UploadFigmaModal.js.map +1 -1
- package/dist/admin/components/AIChat/UploadFigmaModal.mjs +2 -1
- package/dist/admin/components/AIChat/UploadFigmaModal.mjs.map +1 -1
- package/dist/admin/components/AIChat/components/Base64Image.js.map +1 -1
- package/dist/admin/components/AIChat/components/Base64Image.mjs.map +1 -1
- package/dist/admin/components/AIChat/components/Collapsible.js.map +1 -1
- package/dist/admin/components/AIChat/components/Collapsible.mjs.map +1 -1
- package/dist/admin/components/AIChat/components/FullScreenImage.js.map +1 -1
- package/dist/admin/components/AIChat/components/FullScreenImage.mjs.map +1 -1
- package/dist/admin/components/AIChat/components/Messages/Message.js.map +1 -1
- package/dist/admin/components/AIChat/components/Messages/Message.mjs.map +1 -1
- package/dist/admin/components/AIChat/hooks/useAIFetch.js.map +1 -1
- package/dist/admin/components/AIChat/hooks/useAIFetch.mjs.map +1 -1
- package/dist/admin/components/AIChat/hooks/useCodeUpload.js.map +1 -1
- package/dist/admin/components/AIChat/hooks/useCodeUpload.mjs.map +1 -1
- package/dist/admin/components/AIChat/hooks/useFigmaUpload.js.map +1 -1
- package/dist/admin/components/AIChat/hooks/useFigmaUpload.mjs.map +1 -1
- package/dist/admin/components/AIChat/lib/aiClient.js.map +1 -1
- package/dist/admin/components/AIChat/lib/aiClient.mjs.map +1 -1
- package/dist/admin/components/AIChat/lib/constants.js.map +1 -1
- package/dist/admin/components/AIChat/lib/constants.mjs.map +1 -1
- package/dist/admin/components/AIChat/providers/SchemaProvider.js.map +1 -1
- package/dist/admin/components/AIChat/providers/SchemaProvider.mjs.map +1 -1
- package/dist/admin/components/AttributeOptions/AttributeOption.js.map +1 -1
- package/dist/admin/components/AttributeOptions/AttributeOption.mjs.map +1 -1
- package/dist/admin/components/AttributeOptions/AttributeOptions.js.map +1 -1
- package/dist/admin/components/AttributeOptions/AttributeOptions.mjs.map +1 -1
- package/dist/admin/components/AttributeOptions/EmptyAttributes.js.map +1 -1
- package/dist/admin/components/AttributeOptions/EmptyAttributes.mjs.map +1 -1
- package/dist/admin/components/AttributeRow.js.map +1 -1
- package/dist/admin/components/AttributeRow.mjs.map +1 -1
- package/dist/admin/components/CheckboxWithNumberField.js +2 -1
- package/dist/admin/components/CheckboxWithNumberField.js.map +1 -1
- package/dist/admin/components/CheckboxWithNumberField.mjs +2 -1
- package/dist/admin/components/CheckboxWithNumberField.mjs.map +1 -1
- package/dist/admin/components/ComponentCard/ComponentCard.js.map +1 -1
- package/dist/admin/components/ComponentCard/ComponentCard.mjs.map +1 -1
- package/dist/admin/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.js.map +1 -1
- package/dist/admin/components/ContentTypeBuilderNav/useContentTypeBuilderMenu.mjs.map +1 -1
- package/dist/admin/components/DataManager/utils/cleanData.js.map +1 -1
- package/dist/admin/components/DataManager/utils/cleanData.mjs.map +1 -1
- package/dist/admin/components/DisplayedType.js.map +1 -1
- package/dist/admin/components/DisplayedType.mjs.map +1 -1
- package/dist/admin/components/DynamicZoneList.js.map +1 -1
- package/dist/admin/components/DynamicZoneList.mjs.map +1 -1
- package/dist/admin/components/Footers.js.map +1 -1
- package/dist/admin/components/Footers.mjs.map +1 -1
- package/dist/admin/components/FormModal/FormModal.js.map +1 -1
- package/dist/admin/components/FormModal/FormModal.mjs.map +1 -1
- package/dist/admin/components/FormModal/attributes/ConditionForm.js.map +1 -1
- package/dist/admin/components/FormModal/attributes/ConditionForm.mjs.map +1 -1
- package/dist/admin/components/FormModal/attributes/advancedForm.js.map +1 -1
- package/dist/admin/components/FormModal/attributes/advancedForm.mjs.map +1 -1
- package/dist/admin/components/FormModal/attributes/baseForm.js.map +1 -1
- package/dist/admin/components/FormModal/attributes/baseForm.mjs.map +1 -1
- package/dist/admin/components/FormModal/component/componentForm.js.map +1 -1
- package/dist/admin/components/FormModal/component/componentForm.mjs.map +1 -1
- package/dist/admin/components/FormModal/forms/utils/createCollectionName.js.map +1 -1
- package/dist/admin/components/FormModal/forms/utils/createCollectionName.mjs.map +1 -1
- package/dist/admin/components/FormModal/utils/createUid.js.map +1 -1
- package/dist/admin/components/FormModal/utils/createUid.mjs.map +1 -1
- package/dist/admin/components/FormModalHeader.js.map +1 -1
- package/dist/admin/components/FormModalHeader.mjs.map +1 -1
- package/dist/admin/components/FormModalSubHeader.js.map +1 -1
- package/dist/admin/components/FormModalSubHeader.mjs.map +1 -1
- package/dist/admin/components/IconPicker/constants.js +3 -0
- package/dist/admin/components/IconPicker/constants.js.map +1 -1
- package/dist/admin/components/IconPicker/constants.mjs +3 -0
- package/dist/admin/components/IconPicker/constants.mjs.map +1 -1
- package/dist/admin/components/List.js.map +1 -1
- package/dist/admin/components/List.mjs.map +1 -1
- package/dist/admin/components/PluralName.js +2 -1
- package/dist/admin/components/PluralName.js.map +1 -1
- package/dist/admin/components/PluralName.mjs +2 -1
- package/dist/admin/components/PluralName.mjs.map +1 -1
- package/dist/admin/components/Relation/RelationField/RelationTargetPicker/RelationTargetPicker.js.map +1 -1
- package/dist/admin/components/Relation/RelationField/RelationTargetPicker/RelationTargetPicker.mjs.map +1 -1
- package/dist/admin/components/Relation/RelationNaturePicker/RelationNaturePicker.js.map +1 -1
- package/dist/admin/components/Relation/RelationNaturePicker/RelationNaturePicker.mjs.map +1 -1
- package/dist/admin/components/SelectComponent.js.map +1 -1
- package/dist/admin/components/SelectComponent.mjs.map +1 -1
- package/dist/admin/components/SingularName.js +2 -1
- package/dist/admin/components/SingularName.js.map +1 -1
- package/dist/admin/components/SingularName.mjs +2 -1
- package/dist/admin/components/SingularName.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/index.js.map +1 -1
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/pages/App/index.js.map +1 -1
- package/dist/admin/pages/App/index.mjs.map +1 -1
- package/dist/admin/pages/ListView/ListView.js.map +1 -1
- package/dist/admin/pages/ListView/ListView.mjs.map +1 -1
- package/dist/admin/utils/conditions.js.map +1 -1
- package/dist/admin/utils/conditions.mjs.map +1 -1
- package/dist/admin/utils/getTrad.js.map +1 -1
- package/dist/admin/utils/getTrad.mjs.map +1 -1
- package/dist/admin/utils/prefixPluginTranslations.js.map +1 -1
- package/dist/admin/utils/prefixPluginTranslations.mjs.map +1 -1
- package/dist/admin/utils/timeFormat.js.map +1 -1
- package/dist/admin/utils/timeFormat.mjs.map +1 -1
- package/dist/server/controllers/validation/common.js.map +1 -1
- package/dist/server/controllers/validation/common.mjs.map +1 -1
- package/dist/server/controllers/validation/content-type.js.map +1 -1
- package/dist/server/controllers/validation/content-type.mjs.map +1 -1
- package/dist/server/controllers/validation/model-schema.js.map +1 -1
- package/dist/server/controllers/validation/model-schema.mjs.map +1 -1
- package/dist/server/controllers/validation/relations.js.map +1 -1
- package/dist/server/controllers/validation/relations.mjs.map +1 -1
- package/dist/server/register.js +30 -89
- package/dist/server/register.js.map +1 -1
- package/dist/server/register.mjs +30 -89
- package/dist/server/register.mjs.map +1 -1
- package/dist/server/services/api-handler.js.map +1 -1
- package/dist/server/services/api-handler.mjs.map +1 -1
- package/dist/server/services/component-categories.js.map +1 -1
- package/dist/server/services/component-categories.mjs.map +1 -1
- package/dist/server/services/schema-builder/component-builder.js.map +1 -1
- package/dist/server/services/schema-builder/component-builder.mjs.map +1 -1
- package/dist/server/services/schema-builder/content-type-builder.js.map +1 -1
- package/dist/server/services/schema-builder/content-type-builder.mjs.map +1 -1
- package/dist/server/src/index.d.ts +3 -1
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/register.d.ts +4 -9
- package/dist/server/src/register.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFigmaUpload.mjs","sources":["../../../../../admin/src/components/AIChat/hooks/useFigmaUpload.ts"],"sourcesContent":["import { useState } from 'react';\n\nimport type { Attachment } from '../lib/types/attachments';\n\n/**================================================================================\n * Constants\n *================================================================================*/\nexport const FIGMA_TOKEN_STORAGE_KEY = 'strapi-ai-figma-token';\n\n/**================================================================================\n * Types\n *================================================================================*/\nexport interface FigmaNodeData {\n id: string;\n name: string;\n type: string;\n children?: FigmaNodeData[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any; // For other properties that Figma nodes may have\n}\n\nexport interface FigmaFileData {\n document: FigmaNodeData;\n schemaVersion: number;\n name: string;\n lastModified: string;\n thumbnailUrl: string;\n version: string;\n role: string;\n}\n\nexport interface FigmaImage extends Attachment {}\n\ninterface UseFigmaUploadOptions {\n onSuccess?: (attachments: FigmaImage[]) => void;\n onError?: (error: string) => void;\n}\n\n/**================================================================================\n * Token Storage Utils\n *================================================================================*/\n\n/**\n * Get Figma token from localStorage\n */\nexport const getFigmaToken = (): string => {\n try {\n return localStorage.getItem(FIGMA_TOKEN_STORAGE_KEY) || '';\n } catch (error) {\n console.error('Error accessing localStorage:', error);\n return '';\n }\n};\n\n/**\n * Save Figma token to localStorage\n */\nexport const saveFigmaToken = (token: string): void => {\n try {\n localStorage.setItem(FIGMA_TOKEN_STORAGE_KEY, token);\n } catch (error) {\n console.error('Error saving to localStorage:', error);\n }\n};\n\n/**\n * Check if Figma token exists in localStorage\n */\nexport const hasFigmaToken = (): boolean => {\n return !!getFigmaToken();\n};\n\n/**================================================================================\n * Utils\n *================================================================================*/\n\n/**\n * Extract file key and node ID from Figma URL\n * @param figmaUrl - Figma URL (e.g., https://www.figma.com/file/KEY/Title)\n */\nconst extractNodeFromFigmaUrl = (figmaUrl: string) => {\n const figmaUrlPattern = /figma\\.com\\/(?:file|design)\\/([a-zA-Z0-9]+)\\/.*[?&]node-id=([^&]+)/;\n const match = figmaUrl.match(figmaUrlPattern);\n\n if (!match) {\n throw new Error('Invalid Figma URL');\n }\n\n const fileKey = match[1];\n const nodeId = decodeURIComponent(match[2]).replace(/-/g, ':');\n\n return { fileKey, nodeId };\n};\n\n/**\n * Get token and validate it's available\n * @throws Error if token is not available\n */\nconst getValidToken = (): string => {\n const token = getFigmaToken();\n if (!token) {\n throw new Error('Figma API token is required');\n }\n return token;\n};\n\n/**\n * Fetch Figma file data using the API\n * @param fileKey - Figma file key\n * @param nodeId - Figma node ID\n */\nconst fetchFigmaNode = async (fileKey: string, nodeId: string): Promise<FigmaFileData> => {\n const token = getValidToken();\n\n try {\n const apiUrl = `https://api.figma.com/v1/files/${fileKey}/nodes?ids=${nodeId}`;\n\n const response = await fetch(apiUrl, {\n headers: {\n 'X-Figma-Token': token,\n },\n });\n\n if (!response.ok) {\n throw new Error(`Figma API error: ${response.status} ${response.statusText}`);\n }\n\n const nodes = await response.json();\n\n return nodes.nodes[nodeId];\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Failed to fetch Figma data';\n throw new Error(errorMessage);\n }\n};\n\n/**\n * Recursively searches the node tree for FRAME nodes.\n * It stops searching within a branch once a FRAME is found.\n * @param node - The current FigmaNodeData to inspect.\n */\ninterface FrameInfo {\n id: string;\n name: string;\n}\n\nconst findFramesInNode = (node: FigmaNodeData): FrameInfo[] => {\n const frames: FrameInfo[] = [];\n if (node.type === 'FRAME') {\n frames.push({\n id: node.id,\n name: node.name,\n });\n return frames;\n }\n\n if (node.children && node.children.length > 0) {\n for (const child of node.children) {\n // Continue searching in children if the current node is not a FRAME\n frames.push(...findFramesInNode(child));\n }\n }\n\n return frames;\n};\n\n/**\n * Fetch images for specific nodes from the Figma API\n * @param fileKey - Figma file key\n * @param nodeIds - Array of node IDs to render\n */\nconst fetchFigmaNodeImages = async (\n fileKey: string,\n nodeIds: string[]\n): Promise<{ images: Record<string, string> }> => {\n const token = getValidToken();\n\n if (nodeIds.length === 0) {\n return { images: {} };\n }\n try {\n // Max 50 node IDs per request according to Figma API docs\n // We might need to chunk requests if nodeIds is very large\n const idsQueryParam = nodeIds.slice(0, 50).join(',');\n const apiUrl = `https://api.figma.com/v1/images/${fileKey}?ids=${idsQueryParam}&format=png&scale=0.4`;\n\n const response = await fetch(apiUrl, {\n headers: { 'X-Figma-Token': token },\n });\n\n if (!response.ok) {\n const errorData = await response.text();\n throw new Error(\n `Figma API image error: ${response.status} ${response.statusText} - ${errorData}`\n );\n }\n\n const result = await response.json();\n if (result.err) {\n throw new Error(`Figma API image error: ${result.err}`);\n }\n\n return result as { images: Record<string, string> };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Failed to fetch Figma node images';\n throw new Error(errorMessage);\n }\n};\n\n/**================================================================================\n * Hooks\n *================================================================================*/\nexport function useFigmaUpload({ onSuccess, onError }: UseFigmaUploadOptions = {}) {\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n /**\n * Main method to process a Figma URL\n * @param figmaUrl - Figma URL to process\n */\n const processFigmaUrl = async (figmaUrl: string) => {\n try {\n // Check if token exists before proceeding\n if (!hasFigmaToken()) {\n const errorMessage = 'Figma API token is required';\n setError(errorMessage);\n onError?.(errorMessage);\n throw new Error(errorMessage);\n }\n\n setIsLoading(true);\n setError(null);\n\n // 1. Extract file key from URL\n const { fileKey, nodeId: selectedNode } = extractNodeFromFigmaUrl(figmaUrl);\n\n // 2. Fetch base data from Figma API to get structure\n const figmaData = await fetchFigmaNode(fileKey, selectedNode);\n if (!figmaData.document) return;\n\n // 3. Find frame nodes with their names\n const frames = findFramesInNode(figmaData.document);\n // Create a map of ID to name for later use\n const frameNameMap = new Map(frames.map((frame) => [frame.id, frame.name]));\n // Get just the IDs for the API call\n const frameIds = frames.map((frame) => frame.id);\n\n // 4. Fetch images for the identified nodes\n const imageResponse = await fetchFigmaNodeImages(fileKey, frameIds);\n const images = imageResponse.images;\n\n // Use the name from our map instead of just the ID\n const figmaImages = Object.entries(images).map(\n ([id, url]) =>\n ({\n id,\n type: 'file',\n filename: frameNameMap.get(id),\n mediaType: 'image/png',\n url,\n status: 'ready',\n }) satisfies FigmaImage\n );\n\n onSuccess?.(figmaImages);\n return figmaImages;\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'Unknown error processing Figma URL';\n setError(errorMessage);\n onError?.(errorMessage);\n console.error('Error processing Figma URL:', err);\n throw err;\n } finally {\n setIsLoading(false);\n }\n };\n\n return {\n processFigmaUrl,\n isLoading: isLoading,\n error: error,\n };\n}\n"],"names":["FIGMA_TOKEN_STORAGE_KEY","getFigmaToken","localStorage","getItem","error","console","saveFigmaToken","token","setItem","hasFigmaToken","extractNodeFromFigmaUrl","figmaUrl","figmaUrlPattern","match","Error","fileKey","nodeId","decodeURIComponent","replace","getValidToken","fetchFigmaNode","apiUrl","response","fetch","headers","ok","status","statusText","nodes","json","err","errorMessage","message","findFramesInNode","node","frames","type","push","id","name","children","length","child","fetchFigmaNodeImages","nodeIds","images","idsQueryParam","slice","join","errorData","text","result","useFigmaUpload","onSuccess","onError","isLoading","setIsLoading","useState","setError","processFigmaUrl","selectedNode","figmaData","document","frameNameMap","Map","map","frame","frameIds","imageResponse","figmaImages","Object","entries","url","filename","get","mediaType"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useFigmaUpload.mjs","sources":["../../../../../admin/src/components/AIChat/hooks/useFigmaUpload.ts"],"sourcesContent":["import { useState } from 'react';\n\nimport type { Attachment } from '../lib/types/attachments';\n\n/**================================================================================\n * Constants\n *================================================================================*/\nexport const FIGMA_TOKEN_STORAGE_KEY = 'strapi-ai-figma-token';\n\n/**================================================================================\n * Types\n *================================================================================*/\nexport interface FigmaNodeData {\n id: string;\n name: string;\n type: string;\n children?: FigmaNodeData[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any; // For other properties that Figma nodes may have\n}\n\nexport interface FigmaFileData {\n document: FigmaNodeData;\n schemaVersion: number;\n name: string;\n lastModified: string;\n thumbnailUrl: string;\n version: string;\n role: string;\n}\n\nexport interface FigmaImage extends Attachment {}\n\ninterface UseFigmaUploadOptions {\n onSuccess?: (attachments: FigmaImage[]) => void;\n onError?: (error: string) => void;\n}\n\n/**================================================================================\n * Token Storage Utils\n *================================================================================*/\n\n/**\n * Get Figma token from localStorage\n */\nexport const getFigmaToken = (): string => {\n try {\n return localStorage.getItem(FIGMA_TOKEN_STORAGE_KEY) || '';\n } catch (error) {\n console.error('Error accessing localStorage:', error);\n return '';\n }\n};\n\n/**\n * Save Figma token to localStorage\n */\nexport const saveFigmaToken = (token: string): void => {\n try {\n localStorage.setItem(FIGMA_TOKEN_STORAGE_KEY, token);\n } catch (error) {\n console.error('Error saving to localStorage:', error);\n }\n};\n\n/**\n * Check if Figma token exists in localStorage\n */\nexport const hasFigmaToken = (): boolean => {\n return !!getFigmaToken();\n};\n\n/**================================================================================\n * Utils\n *================================================================================*/\n\n/**\n * Extract file key and node ID from Figma URL\n * @param figmaUrl - Figma URL (e.g., https://www.figma.com/file/KEY/Title)\n */\nconst extractNodeFromFigmaUrl = (figmaUrl: string) => {\n const figmaUrlPattern = /figma\\.com\\/(?:file|design)\\/([a-zA-Z0-9]+)\\/.*[?&]node-id=([^&]+)/;\n const match = figmaUrl.match(figmaUrlPattern);\n\n if (!match) {\n throw new Error('Invalid Figma URL');\n }\n\n const fileKey = match[1];\n const nodeId = decodeURIComponent(match[2]).replace(/-/g, ':');\n\n return { fileKey, nodeId };\n};\n\n/**\n * Get token and validate it's available\n * @throws Error if token is not available\n */\nconst getValidToken = (): string => {\n const token = getFigmaToken();\n if (!token) {\n throw new Error('Figma API token is required');\n }\n return token;\n};\n\n/**\n * Fetch Figma file data using the API\n * @param fileKey - Figma file key\n * @param nodeId - Figma node ID\n */\nconst fetchFigmaNode = async (fileKey: string, nodeId: string): Promise<FigmaFileData> => {\n const token = getValidToken();\n\n try {\n const apiUrl = `https://api.figma.com/v1/files/${fileKey}/nodes?ids=${nodeId}`;\n\n const response = await fetch(apiUrl, {\n headers: {\n 'X-Figma-Token': token,\n },\n });\n\n if (!response.ok) {\n throw new Error(`Figma API error: ${response.status} ${response.statusText}`);\n }\n\n const nodes = await response.json();\n\n return nodes.nodes[nodeId];\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Failed to fetch Figma data';\n throw new Error(errorMessage);\n }\n};\n\n/**\n * Recursively searches the node tree for FRAME nodes.\n * It stops searching within a branch once a FRAME is found.\n * @param node - The current FigmaNodeData to inspect.\n */\ninterface FrameInfo {\n id: string;\n name: string;\n}\n\nconst findFramesInNode = (node: FigmaNodeData): FrameInfo[] => {\n const frames: FrameInfo[] = [];\n if (node.type === 'FRAME') {\n frames.push({\n id: node.id,\n name: node.name,\n });\n return frames;\n }\n\n if (node.children && node.children.length > 0) {\n for (const child of node.children) {\n // Continue searching in children if the current node is not a FRAME\n frames.push(...findFramesInNode(child));\n }\n }\n\n return frames;\n};\n\n/**\n * Fetch images for specific nodes from the Figma API\n * @param fileKey - Figma file key\n * @param nodeIds - Array of node IDs to render\n */\nconst fetchFigmaNodeImages = async (\n fileKey: string,\n nodeIds: string[]\n): Promise<{ images: Record<string, string> }> => {\n const token = getValidToken();\n\n if (nodeIds.length === 0) {\n return { images: {} };\n }\n try {\n // Max 50 node IDs per request according to Figma API docs\n // We might need to chunk requests if nodeIds is very large\n const idsQueryParam = nodeIds.slice(0, 50).join(',');\n const apiUrl = `https://api.figma.com/v1/images/${fileKey}?ids=${idsQueryParam}&format=png&scale=0.4`;\n\n const response = await fetch(apiUrl, {\n headers: { 'X-Figma-Token': token },\n });\n\n if (!response.ok) {\n const errorData = await response.text();\n throw new Error(\n `Figma API image error: ${response.status} ${response.statusText} - ${errorData}`\n );\n }\n\n const result = await response.json();\n if (result.err) {\n throw new Error(`Figma API image error: ${result.err}`);\n }\n\n return result as { images: Record<string, string> };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Failed to fetch Figma node images';\n throw new Error(errorMessage);\n }\n};\n\n/**================================================================================\n * Hooks\n *================================================================================*/\nexport function useFigmaUpload({ onSuccess, onError }: UseFigmaUploadOptions = {}) {\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n /**\n * Main method to process a Figma URL\n * @param figmaUrl - Figma URL to process\n */\n const processFigmaUrl = async (figmaUrl: string) => {\n try {\n // Check if token exists before proceeding\n if (!hasFigmaToken()) {\n const errorMessage = 'Figma API token is required';\n setError(errorMessage);\n onError?.(errorMessage);\n throw new Error(errorMessage);\n }\n\n setIsLoading(true);\n setError(null);\n\n // 1. Extract file key from URL\n const { fileKey, nodeId: selectedNode } = extractNodeFromFigmaUrl(figmaUrl);\n\n // 2. Fetch base data from Figma API to get structure\n const figmaData = await fetchFigmaNode(fileKey, selectedNode);\n if (!figmaData.document) return;\n\n // 3. Find frame nodes with their names\n const frames = findFramesInNode(figmaData.document);\n // Create a map of ID to name for later use\n const frameNameMap = new Map(frames.map((frame) => [frame.id, frame.name]));\n // Get just the IDs for the API call\n const frameIds = frames.map((frame) => frame.id);\n\n // 4. Fetch images for the identified nodes\n const imageResponse = await fetchFigmaNodeImages(fileKey, frameIds);\n const images = imageResponse.images;\n\n // Use the name from our map instead of just the ID\n const figmaImages = Object.entries(images).map(\n ([id, url]) =>\n ({\n id,\n type: 'file',\n filename: frameNameMap.get(id),\n mediaType: 'image/png',\n url,\n status: 'ready',\n }) satisfies FigmaImage\n );\n\n onSuccess?.(figmaImages);\n return figmaImages;\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'Unknown error processing Figma URL';\n setError(errorMessage);\n onError?.(errorMessage);\n console.error('Error processing Figma URL:', err);\n throw err;\n } finally {\n setIsLoading(false);\n }\n };\n\n return {\n processFigmaUrl,\n isLoading: isLoading,\n error: error,\n };\n}\n"],"names":["FIGMA_TOKEN_STORAGE_KEY","getFigmaToken","localStorage","getItem","error","console","saveFigmaToken","token","setItem","hasFigmaToken","extractNodeFromFigmaUrl","figmaUrl","figmaUrlPattern","match","Error","fileKey","nodeId","decodeURIComponent","replace","getValidToken","fetchFigmaNode","apiUrl","response","fetch","headers","ok","status","statusText","nodes","json","err","errorMessage","message","findFramesInNode","node","frames","type","push","id","name","children","length","child","fetchFigmaNodeImages","nodeIds","images","idsQueryParam","slice","join","errorData","text","result","useFigmaUpload","onSuccess","onError","isLoading","setIsLoading","useState","setError","processFigmaUrl","selectedNode","figmaData","document","frameNameMap","Map","map","frame","frameIds","imageResponse","figmaImages","Object","entries","url","filename","get","mediaType"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aiClient.js","sources":["../../../../../admin/src/components/AIChat/lib/aiClient.ts"],"sourcesContent":["import { getFetchClient } from '@strapi/admin/strapi-admin';\n\n/**\n * Centralized AI client utilities:\n * - Token retrieval via admin endpoint using getFetchClient\n * - In-memory + sessionStorage caching with near-expiry buffer\n * - Safe JSON parsing for error handling\n * - Single-retry policy on token invalidation\n */\n\nexport interface AITokenData {\n token: string;\n expiresAt: string;\n}\n\nlet aiTokenCache: AITokenData | null = null;\nconst SESSION_STORAGE_KEY = 'strapi-ai-token';\nconst EXPIRY_BUFFER_MS = 60 * 1000;\n\nconst parseExpiryMs = (expiresAt: string): number | null => {\n const ms = Date.parse(expiresAt);\n return Number.isFinite(ms) ? ms : null;\n};\n\ntype TokenState = 'valid' | 'stale' | 'expired';\n\nconst getTokenState = (\n expiresAt: string,\n bufferMs = EXPIRY_BUFFER_MS,\n now = Date.now()\n): TokenState => {\n const expMs = parseExpiryMs(expiresAt);\n if (expMs === null) {\n return 'expired';\n }\n if (expMs <= now) {\n return 'expired';\n }\n if (expMs - bufferMs <= now) {\n return 'stale';\n }\n\n return 'valid';\n};\n\nconst isTokenUsable = (expiresAt: string, bufferMs = EXPIRY_BUFFER_MS, now = Date.now()): boolean =>\n getTokenState(expiresAt, bufferMs, now) === 'valid';\n\nexport const clearAIJwt = () => {\n aiTokenCache = null;\n sessionStorage.removeItem(SESSION_STORAGE_KEY);\n};\n\nconst readFromSession = (): AITokenData | null => {\n try {\n const raw = sessionStorage.getItem(SESSION_STORAGE_KEY);\n if (!raw) {\n return null;\n }\n\n const parsed = JSON.parse(raw) as AITokenData;\n return parsed;\n } catch {\n return null;\n }\n};\n\nconst writeToSession = (data: AITokenData) => {\n sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(data));\n};\n\nexport const getAIJwt = async (): Promise<AITokenData | null> => {\n // Check memory cache\n if (aiTokenCache && isTokenUsable(aiTokenCache.expiresAt)) {\n return aiTokenCache;\n }\n\n // Check session storage\n const fromSession = readFromSession();\n if (fromSession && isTokenUsable(fromSession.expiresAt)) {\n aiTokenCache = fromSession;\n\n return aiTokenCache;\n }\n\n // Fetch from admin endpoint\n try {\n const { get } = getFetchClient();\n const { data } = await get('/admin/ai-token');\n\n const token = data?.token || data?.data?.token;\n const expiresAt = data?.expiresAt || data?.data?.expiresAt;\n\n if (token && expiresAt) {\n aiTokenCache = { token, expiresAt };\n writeToSession(aiTokenCache);\n\n return aiTokenCache;\n }\n return null;\n } catch {\n return null;\n }\n};\n\nexport const prefetchAIToken = async (): Promise<void> => {\n try {\n // If we already have a valid token (not expiring soon), do nothing\n const existing = await getAIJwt();\n if (existing) {\n return;\n }\n\n // Attempt a fetch to populate cache\n await getAIJwt();\n } catch {\n // no-op\n }\n};\n\nexport const safeParseJson = async (response: Response): Promise<any> => {\n try {\n return await response.json();\n } catch {\n try {\n const text = await response.text();\n\n return { error: text };\n } catch {\n return undefined;\n }\n }\n};\n\nexport interface StrapiContextHeaders {\n strapiVersion?: string | null;\n projectId?: string | null;\n userId?: string | null;\n}\n\nconst buildHeaders = (\n token: string,\n ctx?: StrapiContextHeaders,\n extra?: HeadersInit\n): Record<string, string> => {\n return {\n Authorization: `Bearer ${token}`,\n 'X-Strapi-Version': ctx?.strapiVersion || 'latest',\n 'X-Strapi-User': ctx?.userId || 'unknown',\n 'X-Strapi-Project-Id': ctx?.projectId || 'unknown',\n ...(extra as Record<string, string>),\n };\n};\n\nconst shouldRetryForToken = (status: number, body: any): boolean => {\n if (status === 401 || status === 403) {\n return true;\n }\n\n const msg = (body?.error || '').toString().toLowerCase();\n return msg.includes('expired') || msg.includes('invalid token');\n};\n\nexport interface FetchAIOptions extends RequestInit {\n ctx?: StrapiContextHeaders;\n}\n\n/**\n * Generic fetch wrapper for AI endpoints with token injection and single retry on invalidation\n */\nexport const fetchAI = async (\n input: RequestInfo | URL,\n options: FetchAIOptions = {}\n): Promise<Response> => {\n // Get token\n const tokenData = await getAIJwt();\n\n if (!tokenData?.token) {\n const error = new Error(\n 'Could not authorize with AI Server. Please contact your administrator.'\n );\n\n throw error;\n }\n\n const make = async (token: string): Promise<Response> => {\n const headers = buildHeaders(token, options.ctx, options.headers);\n return fetch(input, {\n ...options,\n headers,\n });\n };\n\n let response = await make(tokenData.token);\n\n let body: unknown | undefined = undefined;\n try {\n body = await safeParseJson(response.clone());\n } catch {\n // no-op\n }\n\n if (shouldRetryForToken(response.status, body)) {\n clearAIJwt();\n\n const refreshed = await getAIJwt();\n\n if (refreshed?.token && refreshed.token !== tokenData.token) {\n response = await make(refreshed.token);\n }\n }\n\n return response;\n};\n\n/**\n * Factory to provide a fetch implementation compatible with AI SDK useChat\n * that injects AI JWT + Strapi context headers and retries on token invalidation once.\n */\nexport const makeChatFetch = (ctx: StrapiContextHeaders) => {\n return async (input: RequestInfo | URL, options: RequestInit = {}): Promise<Response> => {\n return fetchAI(input, { ...options, ctx });\n };\n};\n"],"names":["aiTokenCache","SESSION_STORAGE_KEY","EXPIRY_BUFFER_MS","parseExpiryMs","expiresAt","ms","Date","parse","Number","isFinite","getTokenState","bufferMs","now","expMs","isTokenUsable","clearAIJwt","sessionStorage","removeItem","readFromSession","raw","getItem","parsed","JSON","writeToSession","data","setItem","stringify","getAIJwt","fromSession","get","getFetchClient","token","prefetchAIToken","existing","safeParseJson","response","json","text","error","undefined","buildHeaders","ctx","extra","Authorization","strapiVersion","userId","projectId","shouldRetryForToken","status","body","msg","toString","toLowerCase","includes","fetchAI","input","options","tokenData","Error","make","headers","fetch","clone","refreshed","makeChatFetch"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"aiClient.js","sources":["../../../../../admin/src/components/AIChat/lib/aiClient.ts"],"sourcesContent":["import { getFetchClient } from '@strapi/admin/strapi-admin';\n\n/**\n * Centralized AI client utilities:\n * - Token retrieval via admin endpoint using getFetchClient\n * - In-memory + sessionStorage caching with near-expiry buffer\n * - Safe JSON parsing for error handling\n * - Single-retry policy on token invalidation\n */\n\nexport interface AITokenData {\n token: string;\n expiresAt: string;\n}\n\nlet aiTokenCache: AITokenData | null = null;\nconst SESSION_STORAGE_KEY = 'strapi-ai-token';\nconst EXPIRY_BUFFER_MS = 60 * 1000;\n\nconst parseExpiryMs = (expiresAt: string): number | null => {\n const ms = Date.parse(expiresAt);\n return Number.isFinite(ms) ? ms : null;\n};\n\ntype TokenState = 'valid' | 'stale' | 'expired';\n\nconst getTokenState = (\n expiresAt: string,\n bufferMs = EXPIRY_BUFFER_MS,\n now = Date.now()\n): TokenState => {\n const expMs = parseExpiryMs(expiresAt);\n if (expMs === null) {\n return 'expired';\n }\n if (expMs <= now) {\n return 'expired';\n }\n if (expMs - bufferMs <= now) {\n return 'stale';\n }\n\n return 'valid';\n};\n\nconst isTokenUsable = (expiresAt: string, bufferMs = EXPIRY_BUFFER_MS, now = Date.now()): boolean =>\n getTokenState(expiresAt, bufferMs, now) === 'valid';\n\nexport const clearAIJwt = () => {\n aiTokenCache = null;\n sessionStorage.removeItem(SESSION_STORAGE_KEY);\n};\n\nconst readFromSession = (): AITokenData | null => {\n try {\n const raw = sessionStorage.getItem(SESSION_STORAGE_KEY);\n if (!raw) {\n return null;\n }\n\n const parsed = JSON.parse(raw) as AITokenData;\n return parsed;\n } catch {\n return null;\n }\n};\n\nconst writeToSession = (data: AITokenData) => {\n sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(data));\n};\n\nexport const getAIJwt = async (): Promise<AITokenData | null> => {\n // Check memory cache\n if (aiTokenCache && isTokenUsable(aiTokenCache.expiresAt)) {\n return aiTokenCache;\n }\n\n // Check session storage\n const fromSession = readFromSession();\n if (fromSession && isTokenUsable(fromSession.expiresAt)) {\n aiTokenCache = fromSession;\n\n return aiTokenCache;\n }\n\n // Fetch from admin endpoint\n try {\n const { get } = getFetchClient();\n const { data } = await get('/admin/ai-token');\n\n const token = data?.token || data?.data?.token;\n const expiresAt = data?.expiresAt || data?.data?.expiresAt;\n\n if (token && expiresAt) {\n aiTokenCache = { token, expiresAt };\n writeToSession(aiTokenCache);\n\n return aiTokenCache;\n }\n return null;\n } catch {\n return null;\n }\n};\n\nexport const prefetchAIToken = async (): Promise<void> => {\n try {\n // If we already have a valid token (not expiring soon), do nothing\n const existing = await getAIJwt();\n if (existing) {\n return;\n }\n\n // Attempt a fetch to populate cache\n await getAIJwt();\n } catch {\n // no-op\n }\n};\n\nexport const safeParseJson = async (response: Response): Promise<any> => {\n try {\n return await response.json();\n } catch {\n try {\n const text = await response.text();\n\n return { error: text };\n } catch {\n return undefined;\n }\n }\n};\n\nexport interface StrapiContextHeaders {\n strapiVersion?: string | null;\n projectId?: string | null;\n userId?: string | null;\n}\n\nconst buildHeaders = (\n token: string,\n ctx?: StrapiContextHeaders,\n extra?: HeadersInit\n): Record<string, string> => {\n return {\n Authorization: `Bearer ${token}`,\n 'X-Strapi-Version': ctx?.strapiVersion || 'latest',\n 'X-Strapi-User': ctx?.userId || 'unknown',\n 'X-Strapi-Project-Id': ctx?.projectId || 'unknown',\n ...(extra as Record<string, string>),\n };\n};\n\nconst shouldRetryForToken = (status: number, body: any): boolean => {\n if (status === 401 || status === 403) {\n return true;\n }\n\n const msg = (body?.error || '').toString().toLowerCase();\n return msg.includes('expired') || msg.includes('invalid token');\n};\n\nexport interface FetchAIOptions extends RequestInit {\n ctx?: StrapiContextHeaders;\n}\n\n/**\n * Generic fetch wrapper for AI endpoints with token injection and single retry on invalidation\n */\nexport const fetchAI = async (\n input: RequestInfo | URL,\n options: FetchAIOptions = {}\n): Promise<Response> => {\n // Get token\n const tokenData = await getAIJwt();\n\n if (!tokenData?.token) {\n const error = new Error(\n 'Could not authorize with AI Server. Please contact your administrator.'\n );\n\n throw error;\n }\n\n const make = async (token: string): Promise<Response> => {\n const headers = buildHeaders(token, options.ctx, options.headers);\n return fetch(input, {\n ...options,\n headers,\n });\n };\n\n let response = await make(tokenData.token);\n\n let body: unknown | undefined = undefined;\n try {\n body = await safeParseJson(response.clone());\n } catch {\n // no-op\n }\n\n if (shouldRetryForToken(response.status, body)) {\n clearAIJwt();\n\n const refreshed = await getAIJwt();\n\n if (refreshed?.token && refreshed.token !== tokenData.token) {\n response = await make(refreshed.token);\n }\n }\n\n return response;\n};\n\n/**\n * Factory to provide a fetch implementation compatible with AI SDK useChat\n * that injects AI JWT + Strapi context headers and retries on token invalidation once.\n */\nexport const makeChatFetch = (ctx: StrapiContextHeaders) => {\n return async (input: RequestInfo | URL, options: RequestInit = {}): Promise<Response> => {\n return fetchAI(input, { ...options, ctx });\n };\n};\n"],"names":["aiTokenCache","SESSION_STORAGE_KEY","EXPIRY_BUFFER_MS","parseExpiryMs","expiresAt","ms","Date","parse","Number","isFinite","getTokenState","bufferMs","now","expMs","isTokenUsable","clearAIJwt","sessionStorage","removeItem","readFromSession","raw","getItem","parsed","JSON","writeToSession","data","setItem","stringify","getAIJwt","fromSession","get","getFetchClient","token","prefetchAIToken","existing","safeParseJson","response","json","text","error","undefined","buildHeaders","ctx","extra","Authorization","strapiVersion","userId","projectId","shouldRetryForToken","status","body","msg","toString","toLowerCase","includes","fetchAI","input","options","tokenData","Error","make","headers","fetch","clone","refreshed","makeChatFetch"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aiClient.mjs","sources":["../../../../../admin/src/components/AIChat/lib/aiClient.ts"],"sourcesContent":["import { getFetchClient } from '@strapi/admin/strapi-admin';\n\n/**\n * Centralized AI client utilities:\n * - Token retrieval via admin endpoint using getFetchClient\n * - In-memory + sessionStorage caching with near-expiry buffer\n * - Safe JSON parsing for error handling\n * - Single-retry policy on token invalidation\n */\n\nexport interface AITokenData {\n token: string;\n expiresAt: string;\n}\n\nlet aiTokenCache: AITokenData | null = null;\nconst SESSION_STORAGE_KEY = 'strapi-ai-token';\nconst EXPIRY_BUFFER_MS = 60 * 1000;\n\nconst parseExpiryMs = (expiresAt: string): number | null => {\n const ms = Date.parse(expiresAt);\n return Number.isFinite(ms) ? ms : null;\n};\n\ntype TokenState = 'valid' | 'stale' | 'expired';\n\nconst getTokenState = (\n expiresAt: string,\n bufferMs = EXPIRY_BUFFER_MS,\n now = Date.now()\n): TokenState => {\n const expMs = parseExpiryMs(expiresAt);\n if (expMs === null) {\n return 'expired';\n }\n if (expMs <= now) {\n return 'expired';\n }\n if (expMs - bufferMs <= now) {\n return 'stale';\n }\n\n return 'valid';\n};\n\nconst isTokenUsable = (expiresAt: string, bufferMs = EXPIRY_BUFFER_MS, now = Date.now()): boolean =>\n getTokenState(expiresAt, bufferMs, now) === 'valid';\n\nexport const clearAIJwt = () => {\n aiTokenCache = null;\n sessionStorage.removeItem(SESSION_STORAGE_KEY);\n};\n\nconst readFromSession = (): AITokenData | null => {\n try {\n const raw = sessionStorage.getItem(SESSION_STORAGE_KEY);\n if (!raw) {\n return null;\n }\n\n const parsed = JSON.parse(raw) as AITokenData;\n return parsed;\n } catch {\n return null;\n }\n};\n\nconst writeToSession = (data: AITokenData) => {\n sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(data));\n};\n\nexport const getAIJwt = async (): Promise<AITokenData | null> => {\n // Check memory cache\n if (aiTokenCache && isTokenUsable(aiTokenCache.expiresAt)) {\n return aiTokenCache;\n }\n\n // Check session storage\n const fromSession = readFromSession();\n if (fromSession && isTokenUsable(fromSession.expiresAt)) {\n aiTokenCache = fromSession;\n\n return aiTokenCache;\n }\n\n // Fetch from admin endpoint\n try {\n const { get } = getFetchClient();\n const { data } = await get('/admin/ai-token');\n\n const token = data?.token || data?.data?.token;\n const expiresAt = data?.expiresAt || data?.data?.expiresAt;\n\n if (token && expiresAt) {\n aiTokenCache = { token, expiresAt };\n writeToSession(aiTokenCache);\n\n return aiTokenCache;\n }\n return null;\n } catch {\n return null;\n }\n};\n\nexport const prefetchAIToken = async (): Promise<void> => {\n try {\n // If we already have a valid token (not expiring soon), do nothing\n const existing = await getAIJwt();\n if (existing) {\n return;\n }\n\n // Attempt a fetch to populate cache\n await getAIJwt();\n } catch {\n // no-op\n }\n};\n\nexport const safeParseJson = async (response: Response): Promise<any> => {\n try {\n return await response.json();\n } catch {\n try {\n const text = await response.text();\n\n return { error: text };\n } catch {\n return undefined;\n }\n }\n};\n\nexport interface StrapiContextHeaders {\n strapiVersion?: string | null;\n projectId?: string | null;\n userId?: string | null;\n}\n\nconst buildHeaders = (\n token: string,\n ctx?: StrapiContextHeaders,\n extra?: HeadersInit\n): Record<string, string> => {\n return {\n Authorization: `Bearer ${token}`,\n 'X-Strapi-Version': ctx?.strapiVersion || 'latest',\n 'X-Strapi-User': ctx?.userId || 'unknown',\n 'X-Strapi-Project-Id': ctx?.projectId || 'unknown',\n ...(extra as Record<string, string>),\n };\n};\n\nconst shouldRetryForToken = (status: number, body: any): boolean => {\n if (status === 401 || status === 403) {\n return true;\n }\n\n const msg = (body?.error || '').toString().toLowerCase();\n return msg.includes('expired') || msg.includes('invalid token');\n};\n\nexport interface FetchAIOptions extends RequestInit {\n ctx?: StrapiContextHeaders;\n}\n\n/**\n * Generic fetch wrapper for AI endpoints with token injection and single retry on invalidation\n */\nexport const fetchAI = async (\n input: RequestInfo | URL,\n options: FetchAIOptions = {}\n): Promise<Response> => {\n // Get token\n const tokenData = await getAIJwt();\n\n if (!tokenData?.token) {\n const error = new Error(\n 'Could not authorize with AI Server. Please contact your administrator.'\n );\n\n throw error;\n }\n\n const make = async (token: string): Promise<Response> => {\n const headers = buildHeaders(token, options.ctx, options.headers);\n return fetch(input, {\n ...options,\n headers,\n });\n };\n\n let response = await make(tokenData.token);\n\n let body: unknown | undefined = undefined;\n try {\n body = await safeParseJson(response.clone());\n } catch {\n // no-op\n }\n\n if (shouldRetryForToken(response.status, body)) {\n clearAIJwt();\n\n const refreshed = await getAIJwt();\n\n if (refreshed?.token && refreshed.token !== tokenData.token) {\n response = await make(refreshed.token);\n }\n }\n\n return response;\n};\n\n/**\n * Factory to provide a fetch implementation compatible with AI SDK useChat\n * that injects AI JWT + Strapi context headers and retries on token invalidation once.\n */\nexport const makeChatFetch = (ctx: StrapiContextHeaders) => {\n return async (input: RequestInfo | URL, options: RequestInit = {}): Promise<Response> => {\n return fetchAI(input, { ...options, ctx });\n };\n};\n"],"names":["aiTokenCache","SESSION_STORAGE_KEY","EXPIRY_BUFFER_MS","parseExpiryMs","expiresAt","ms","Date","parse","Number","isFinite","getTokenState","bufferMs","now","expMs","isTokenUsable","clearAIJwt","sessionStorage","removeItem","readFromSession","raw","getItem","parsed","JSON","writeToSession","data","setItem","stringify","getAIJwt","fromSession","get","getFetchClient","token","prefetchAIToken","existing","safeParseJson","response","json","text","error","undefined","buildHeaders","ctx","extra","Authorization","strapiVersion","userId","projectId","shouldRetryForToken","status","body","msg","toString","toLowerCase","includes","fetchAI","input","options","tokenData","Error","make","headers","fetch","clone","refreshed","makeChatFetch"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"aiClient.mjs","sources":["../../../../../admin/src/components/AIChat/lib/aiClient.ts"],"sourcesContent":["import { getFetchClient } from '@strapi/admin/strapi-admin';\n\n/**\n * Centralized AI client utilities:\n * - Token retrieval via admin endpoint using getFetchClient\n * - In-memory + sessionStorage caching with near-expiry buffer\n * - Safe JSON parsing for error handling\n * - Single-retry policy on token invalidation\n */\n\nexport interface AITokenData {\n token: string;\n expiresAt: string;\n}\n\nlet aiTokenCache: AITokenData | null = null;\nconst SESSION_STORAGE_KEY = 'strapi-ai-token';\nconst EXPIRY_BUFFER_MS = 60 * 1000;\n\nconst parseExpiryMs = (expiresAt: string): number | null => {\n const ms = Date.parse(expiresAt);\n return Number.isFinite(ms) ? ms : null;\n};\n\ntype TokenState = 'valid' | 'stale' | 'expired';\n\nconst getTokenState = (\n expiresAt: string,\n bufferMs = EXPIRY_BUFFER_MS,\n now = Date.now()\n): TokenState => {\n const expMs = parseExpiryMs(expiresAt);\n if (expMs === null) {\n return 'expired';\n }\n if (expMs <= now) {\n return 'expired';\n }\n if (expMs - bufferMs <= now) {\n return 'stale';\n }\n\n return 'valid';\n};\n\nconst isTokenUsable = (expiresAt: string, bufferMs = EXPIRY_BUFFER_MS, now = Date.now()): boolean =>\n getTokenState(expiresAt, bufferMs, now) === 'valid';\n\nexport const clearAIJwt = () => {\n aiTokenCache = null;\n sessionStorage.removeItem(SESSION_STORAGE_KEY);\n};\n\nconst readFromSession = (): AITokenData | null => {\n try {\n const raw = sessionStorage.getItem(SESSION_STORAGE_KEY);\n if (!raw) {\n return null;\n }\n\n const parsed = JSON.parse(raw) as AITokenData;\n return parsed;\n } catch {\n return null;\n }\n};\n\nconst writeToSession = (data: AITokenData) => {\n sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(data));\n};\n\nexport const getAIJwt = async (): Promise<AITokenData | null> => {\n // Check memory cache\n if (aiTokenCache && isTokenUsable(aiTokenCache.expiresAt)) {\n return aiTokenCache;\n }\n\n // Check session storage\n const fromSession = readFromSession();\n if (fromSession && isTokenUsable(fromSession.expiresAt)) {\n aiTokenCache = fromSession;\n\n return aiTokenCache;\n }\n\n // Fetch from admin endpoint\n try {\n const { get } = getFetchClient();\n const { data } = await get('/admin/ai-token');\n\n const token = data?.token || data?.data?.token;\n const expiresAt = data?.expiresAt || data?.data?.expiresAt;\n\n if (token && expiresAt) {\n aiTokenCache = { token, expiresAt };\n writeToSession(aiTokenCache);\n\n return aiTokenCache;\n }\n return null;\n } catch {\n return null;\n }\n};\n\nexport const prefetchAIToken = async (): Promise<void> => {\n try {\n // If we already have a valid token (not expiring soon), do nothing\n const existing = await getAIJwt();\n if (existing) {\n return;\n }\n\n // Attempt a fetch to populate cache\n await getAIJwt();\n } catch {\n // no-op\n }\n};\n\nexport const safeParseJson = async (response: Response): Promise<any> => {\n try {\n return await response.json();\n } catch {\n try {\n const text = await response.text();\n\n return { error: text };\n } catch {\n return undefined;\n }\n }\n};\n\nexport interface StrapiContextHeaders {\n strapiVersion?: string | null;\n projectId?: string | null;\n userId?: string | null;\n}\n\nconst buildHeaders = (\n token: string,\n ctx?: StrapiContextHeaders,\n extra?: HeadersInit\n): Record<string, string> => {\n return {\n Authorization: `Bearer ${token}`,\n 'X-Strapi-Version': ctx?.strapiVersion || 'latest',\n 'X-Strapi-User': ctx?.userId || 'unknown',\n 'X-Strapi-Project-Id': ctx?.projectId || 'unknown',\n ...(extra as Record<string, string>),\n };\n};\n\nconst shouldRetryForToken = (status: number, body: any): boolean => {\n if (status === 401 || status === 403) {\n return true;\n }\n\n const msg = (body?.error || '').toString().toLowerCase();\n return msg.includes('expired') || msg.includes('invalid token');\n};\n\nexport interface FetchAIOptions extends RequestInit {\n ctx?: StrapiContextHeaders;\n}\n\n/**\n * Generic fetch wrapper for AI endpoints with token injection and single retry on invalidation\n */\nexport const fetchAI = async (\n input: RequestInfo | URL,\n options: FetchAIOptions = {}\n): Promise<Response> => {\n // Get token\n const tokenData = await getAIJwt();\n\n if (!tokenData?.token) {\n const error = new Error(\n 'Could not authorize with AI Server. Please contact your administrator.'\n );\n\n throw error;\n }\n\n const make = async (token: string): Promise<Response> => {\n const headers = buildHeaders(token, options.ctx, options.headers);\n return fetch(input, {\n ...options,\n headers,\n });\n };\n\n let response = await make(tokenData.token);\n\n let body: unknown | undefined = undefined;\n try {\n body = await safeParseJson(response.clone());\n } catch {\n // no-op\n }\n\n if (shouldRetryForToken(response.status, body)) {\n clearAIJwt();\n\n const refreshed = await getAIJwt();\n\n if (refreshed?.token && refreshed.token !== tokenData.token) {\n response = await make(refreshed.token);\n }\n }\n\n return response;\n};\n\n/**\n * Factory to provide a fetch implementation compatible with AI SDK useChat\n * that injects AI JWT + Strapi context headers and retries on token invalidation once.\n */\nexport const makeChatFetch = (ctx: StrapiContextHeaders) => {\n return async (input: RequestInfo | URL, options: RequestInit = {}): Promise<Response> => {\n return fetchAI(input, { ...options, ctx });\n };\n};\n"],"names":["aiTokenCache","SESSION_STORAGE_KEY","EXPIRY_BUFFER_MS","parseExpiryMs","expiresAt","ms","Date","parse","Number","isFinite","getTokenState","bufferMs","now","expMs","isTokenUsable","clearAIJwt","sessionStorage","removeItem","readFromSession","raw","getItem","parsed","JSON","writeToSession","data","setItem","stringify","getAIJwt","fromSession","get","getFetchClient","token","prefetchAIToken","existing","safeParseJson","response","json","text","error","undefined","buildHeaders","ctx","extra","Authorization","strapiVersion","userId","projectId","shouldRetryForToken","status","body","msg","toString","toLowerCase","includes","fetchAI","input","options","tokenData","Error","make","headers","fetch","clone","refreshed","makeChatFetch"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sources":["../../../../../admin/src/components/AIChat/lib/constants.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\nimport type { Schema } from './types/schema';\n\nexport const STRAPI_CODE_MIME_TYPE = 'application/vnd.strapi.code';\nexport const STRAPI_MAX_ATTACHMENTS = 15;\nexport const STRAPI_MAX_ATTACHMENT_SIZE = 15 * 1024 * 1024; // 15MB\n\n/* -------------------------------------------------------------------------------------------------\n * APIs\n * -----------------------------------------------------------------------------------------------*/\nexport const STRAPI_AI_URL =\n process.env.STRAPI_AI_URL?.replace(/\\/+$/, '') ?? 'https://strapi-ai.apps.strapi.io';\nexport const STRAPI_AI_CHAT_URL = `${STRAPI_AI_URL}/schemas/chat`;\nexport const STRAPI_AI_TITLE_URL = `/schemas/chat/generate-title` as const;\nexport const STRAPI_AI_FEEDBACK_URL = `/schemas/chat/feedback` as const;\nexport const STRAPI_AI_PROJECT_URL = `/schemas/chat/attachment` as const;\n\n// AI SDK will also send messages and other relevant data\nexport interface ChatBody {\n schemas: Schema[];\n}\n"],"names":["STRAPI_CODE_MIME_TYPE","STRAPI_MAX_ATTACHMENTS","STRAPI_MAX_ATTACHMENT_SIZE","STRAPI_AI_URL","process","env","replace","STRAPI_AI_CHAT_URL"],"mappings":";;AAAA,qDAGaA,MAAAA,qBAAAA,GAAwB;AAC9B,MAAMC,yBAAyB;MACzBC,0BAA6B,GAAA,EAAA,GAAK,IAAO,GAAA,KAAK;AAE3D;;qGAGaC,MAAAA,aAAAA,GACXC,OAAQC,CAAAA,GAAG,CAACF,aAAa,EAAEG,OAAAA,CAAQ,MAAQ,EAAA,EAAA,CAAA,IAAO;MACvCC,kBAAqB,GAAA,
|
|
1
|
+
{"version":3,"file":"constants.js","sources":["../../../../../admin/src/components/AIChat/lib/constants.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\nimport type { Schema } from './types/schema';\n\nexport const STRAPI_CODE_MIME_TYPE = 'application/vnd.strapi.code';\nexport const STRAPI_MAX_ATTACHMENTS = 15;\nexport const STRAPI_MAX_ATTACHMENT_SIZE = 15 * 1024 * 1024; // 15MB\n\n/* -------------------------------------------------------------------------------------------------\n * APIs\n * -----------------------------------------------------------------------------------------------*/\nexport const STRAPI_AI_URL =\n process.env.STRAPI_AI_URL?.replace(/\\/+$/, '') ?? 'https://strapi-ai.apps.strapi.io';\nexport const STRAPI_AI_CHAT_URL = `${STRAPI_AI_URL}/schemas/chat`;\nexport const STRAPI_AI_TITLE_URL = `/schemas/chat/generate-title` as const;\nexport const STRAPI_AI_FEEDBACK_URL = `/schemas/chat/feedback` as const;\nexport const STRAPI_AI_PROJECT_URL = `/schemas/chat/attachment` as const;\n\n// AI SDK will also send messages and other relevant data\nexport interface ChatBody {\n schemas: Schema[];\n}\n"],"names":["STRAPI_CODE_MIME_TYPE","STRAPI_MAX_ATTACHMENTS","STRAPI_MAX_ATTACHMENT_SIZE","STRAPI_AI_URL","process","env","replace","STRAPI_AI_CHAT_URL"],"mappings":";;AAAA,qDAGaA,MAAAA,qBAAAA,GAAwB;AAC9B,MAAMC,yBAAyB;MACzBC,0BAA6B,GAAA,EAAA,GAAK,IAAO,GAAA,KAAK;AAE3D;;qGAGaC,MAAAA,aAAAA,GACXC,OAAQC,CAAAA,GAAG,CAACF,aAAa,EAAEG,OAAAA,CAAQ,MAAQ,EAAA,EAAA,CAAA,IAAO;MACvCC,kBAAqB,GAAA,CAAA,EAAGJ,aAAc,CAAA,aAAa;;;;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.mjs","sources":["../../../../../admin/src/components/AIChat/lib/constants.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\nimport type { Schema } from './types/schema';\n\nexport const STRAPI_CODE_MIME_TYPE = 'application/vnd.strapi.code';\nexport const STRAPI_MAX_ATTACHMENTS = 15;\nexport const STRAPI_MAX_ATTACHMENT_SIZE = 15 * 1024 * 1024; // 15MB\n\n/* -------------------------------------------------------------------------------------------------\n * APIs\n * -----------------------------------------------------------------------------------------------*/\nexport const STRAPI_AI_URL =\n process.env.STRAPI_AI_URL?.replace(/\\/+$/, '') ?? 'https://strapi-ai.apps.strapi.io';\nexport const STRAPI_AI_CHAT_URL = `${STRAPI_AI_URL}/schemas/chat`;\nexport const STRAPI_AI_TITLE_URL = `/schemas/chat/generate-title` as const;\nexport const STRAPI_AI_FEEDBACK_URL = `/schemas/chat/feedback` as const;\nexport const STRAPI_AI_PROJECT_URL = `/schemas/chat/attachment` as const;\n\n// AI SDK will also send messages and other relevant data\nexport interface ChatBody {\n schemas: Schema[];\n}\n"],"names":["STRAPI_CODE_MIME_TYPE","STRAPI_MAX_ATTACHMENTS","STRAPI_MAX_ATTACHMENT_SIZE","STRAPI_AI_URL","process","env","replace","STRAPI_AI_CHAT_URL"],"mappings":"AAAA,qDAGaA,MAAAA,qBAAAA,GAAwB;AAC9B,MAAMC,yBAAyB;MACzBC,0BAA6B,GAAA,EAAA,GAAK,IAAO,GAAA,KAAK;AAE3D;;qGAGaC,MAAAA,aAAAA,GACXC,OAAQC,CAAAA,GAAG,CAACF,aAAa,EAAEG,OAAAA,CAAQ,MAAQ,EAAA,EAAA,CAAA,IAAO;MACvCC,kBAAqB,GAAA,
|
|
1
|
+
{"version":3,"file":"constants.mjs","sources":["../../../../../admin/src/components/AIChat/lib/constants.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-namespace */\nimport type { Schema } from './types/schema';\n\nexport const STRAPI_CODE_MIME_TYPE = 'application/vnd.strapi.code';\nexport const STRAPI_MAX_ATTACHMENTS = 15;\nexport const STRAPI_MAX_ATTACHMENT_SIZE = 15 * 1024 * 1024; // 15MB\n\n/* -------------------------------------------------------------------------------------------------\n * APIs\n * -----------------------------------------------------------------------------------------------*/\nexport const STRAPI_AI_URL =\n process.env.STRAPI_AI_URL?.replace(/\\/+$/, '') ?? 'https://strapi-ai.apps.strapi.io';\nexport const STRAPI_AI_CHAT_URL = `${STRAPI_AI_URL}/schemas/chat`;\nexport const STRAPI_AI_TITLE_URL = `/schemas/chat/generate-title` as const;\nexport const STRAPI_AI_FEEDBACK_URL = `/schemas/chat/feedback` as const;\nexport const STRAPI_AI_PROJECT_URL = `/schemas/chat/attachment` as const;\n\n// AI SDK will also send messages and other relevant data\nexport interface ChatBody {\n schemas: Schema[];\n}\n"],"names":["STRAPI_CODE_MIME_TYPE","STRAPI_MAX_ATTACHMENTS","STRAPI_MAX_ATTACHMENT_SIZE","STRAPI_AI_URL","process","env","replace","STRAPI_AI_CHAT_URL"],"mappings":"AAAA,qDAGaA,MAAAA,qBAAAA,GAAwB;AAC9B,MAAMC,yBAAyB;MACzBC,0BAA6B,GAAA,EAAA,GAAK,IAAO,GAAA,KAAK;AAE3D;;qGAGaC,MAAAA,aAAAA,GACXC,OAAQC,CAAAA,GAAG,CAACF,aAAa,EAAEG,OAAAA,CAAQ,MAAQ,EAAA,EAAA,CAAA,IAAO;MACvCC,kBAAqB,GAAA,CAAA,EAAGJ,aAAc,CAAA,aAAa;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SchemaProvider.js","sources":["../../../../../admin/src/components/AIChat/providers/SchemaProvider.tsx"],"sourcesContent":["import { createContext, useContext, ReactNode, useEffect, useState } from 'react';\n\nimport { GUIDED_TOUR_REQUIRED_ACTIONS, useGuidedTour } from '@strapi/admin/strapi-admin';\n\nimport { useDataManager } from '../../DataManager/useDataManager';\nimport { transformChatToCTB } from '../lib/transforms/schemas/toCTB';\nimport { SchemaChange } from '../lib/types/annotations';\nimport { AIMessage } from '../lib/types/messages';\n\nimport { useStrapiChat } from './ChatProvider';\n\ninterface SchemaContextType {\n lastRevisedId: string | null;\n setLastRevisedId: (id: string | null) => void;\n}\n\nconst SchemaContext = createContext<SchemaContextType | undefined>(undefined);\n\nconst TYPE_TO_ACTION: Record<string, 'add' | 'update' | 'delete'> = {\n create: 'add',\n update: 'update',\n remove: 'delete',\n};\n\nfunction extractSchemaChangesFromMessage(message: AIMessage): SchemaChange[] {\n if (message.role !== 'assistant') return [];\n\n const changes: SchemaChange[] = [];\n\n message.parts?.forEach((part, partIndex) => {\n // We only care about the schema generation tool\n if (part && typeof part === 'object' && part.type === 'tool-schemaGenerationTool') {\n // Prefer validated schemas from output; ignore if there's an error or no output yet\n const output = part.output as { schemas?: any[]; error?: unknown } | undefined;\n if (!output || output.error || !Array.isArray(output.schemas)) return;\n\n const baseId = part.toolCallId ?? `${message.id}-${partIndex}`;\n\n output.schemas.forEach((schema, schemaIndex) => {\n const revisionId = `${baseId}-${schema.uid ?? schema.name ?? schemaIndex}`;\n const type = (schema.action as SchemaChange['type']) || 'update';\n changes.push({ type, schema, revisionId });\n });\n }\n });\n\n return changes;\n}\n\nexport const SchemaChatProvider = ({ children }: { children: ReactNode }) => {\n const [lastRevisedId, setLastRevisedId] = useState<string | null>(null);\n const { messages, status } = useStrapiChat();\n const { contentTypes, components, applyChange } = useDataManager();\n const dispatch = useGuidedTour('SchemaChatProvider', (s) => s.dispatch);\n const state = useGuidedTour('SchemaChatProvider', (s) => s.state);\n\n useEffect(() => {\n const latestMessage = messages[messages.length - 1];\n if (!latestMessage) return;\n if (latestMessage.role !== 'assistant') return;\n // Wait until message streaming has finished\n if (status !== 'ready') return;\n\n // const schemaChanges = latestMessage.schemaChanges;\n const schemaChanges = extractSchemaChangesFromMessage(latestMessage);\n\n // Check if addField action is already completed\n const isAddFieldCompleted = state.completedActions.includes(\n GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField\n );\n\n schemaChanges.forEach((change: SchemaChange) => {\n const oldSchema =\n contentTypes[change.schema.uid as any] || components[change.schema.uid as any];\n const newSchema = transformChatToCTB(change.schema, oldSchema);\n\n // Check if any attributes/fields are being added to any schema (existing or new)\n if (!isAddFieldCompleted && change.schema.attributes) {\n // If a field is being added or updated, dispatch guided tour action to show Save tooltip\n if (change.type !== 'remove' && Object.keys(change.schema.attributes).length > 0) {\n dispatch({\n type: 'set_completed_actions',\n payload: [GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField],\n });\n }\n }\n\n applyChange({\n action: TYPE_TO_ACTION[change.type]!,\n schema: newSchema,\n });\n });\n setLastRevisedId(latestMessage.id);\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [messages]);\n\n return (\n <SchemaContext.Provider value={{ lastRevisedId, setLastRevisedId }}>\n {children}\n </SchemaContext.Provider>\n );\n};\n\nexport const useChatSchema = () => {\n const context = useContext(SchemaContext);\n if (context === undefined) {\n throw new Error('useSchema must be used within a SchemaProvider');\n }\n return context;\n};\n"],"names":["SchemaContext","createContext","undefined","TYPE_TO_ACTION","create","update","remove","extractSchemaChangesFromMessage","message","role","changes","parts","forEach","part","partIndex","type","output","error","Array","isArray","schemas","baseId","toolCallId","id","schema","schemaIndex","revisionId","uid","name","action","push","SchemaChatProvider","children","lastRevisedId","setLastRevisedId","useState","messages","status","useStrapiChat","contentTypes","components","applyChange","useDataManager","dispatch","useGuidedTour","s","state","useEffect","latestMessage","length","schemaChanges","isAddFieldCompleted","completedActions","includes","GUIDED_TOUR_REQUIRED_ACTIONS","contentTypeBuilder","addField","change","oldSchema","newSchema","transformChatToCTB","attributes","Object","keys","payload","_jsx","Provider","value"],"mappings":";;;;;;;;;AAgBA,MAAMA,8BAAgBC,mBAA6CC,CAAAA,SAAAA,CAAAA;AAEnE,MAAMC,cAA8D,GAAA;IAClEC,MAAQ,EAAA,KAAA;IACRC,MAAQ,EAAA,QAAA;IACRC,MAAQ,EAAA;AACV,CAAA;AAEA,SAASC,gCAAgCC,OAAkB,EAAA;AACzD,IAAA,IAAIA,OAAQC,CAAAA,IAAI,KAAK,WAAA,EAAa,OAAO,EAAE;AAE3C,IAAA,MAAMC,UAA0B,EAAE;AAElCF,IAAAA,OAAAA,CAAQG,KAAK,EAAEC,OAAQ,CAAA,CAACC,IAAMC,EAAAA,SAAAA,GAAAA;;AAE5B,QAAA,IAAID,QAAQ,OAAOA,IAAAA,KAAS,YAAYA,IAAKE,CAAAA,IAAI,KAAK,2BAA6B,EAAA;;YAEjF,MAAMC,MAAAA,GAASH,KAAKG,MAAM;YAC1B,IAAI,CAACA,MAAUA,IAAAA,MAAAA,CAAOC,KAAK,IAAI,CAACC,KAAAA,CAAMC,OAAO,CAACH,MAAOI,CAAAA,OAAO,CAAG,EAAA;
|
|
1
|
+
{"version":3,"file":"SchemaProvider.js","sources":["../../../../../admin/src/components/AIChat/providers/SchemaProvider.tsx"],"sourcesContent":["import { createContext, useContext, ReactNode, useEffect, useState } from 'react';\n\nimport { GUIDED_TOUR_REQUIRED_ACTIONS, useGuidedTour } from '@strapi/admin/strapi-admin';\n\nimport { useDataManager } from '../../DataManager/useDataManager';\nimport { transformChatToCTB } from '../lib/transforms/schemas/toCTB';\nimport { SchemaChange } from '../lib/types/annotations';\nimport { AIMessage } from '../lib/types/messages';\n\nimport { useStrapiChat } from './ChatProvider';\n\ninterface SchemaContextType {\n lastRevisedId: string | null;\n setLastRevisedId: (id: string | null) => void;\n}\n\nconst SchemaContext = createContext<SchemaContextType | undefined>(undefined);\n\nconst TYPE_TO_ACTION: Record<string, 'add' | 'update' | 'delete'> = {\n create: 'add',\n update: 'update',\n remove: 'delete',\n};\n\nfunction extractSchemaChangesFromMessage(message: AIMessage): SchemaChange[] {\n if (message.role !== 'assistant') return [];\n\n const changes: SchemaChange[] = [];\n\n message.parts?.forEach((part, partIndex) => {\n // We only care about the schema generation tool\n if (part && typeof part === 'object' && part.type === 'tool-schemaGenerationTool') {\n // Prefer validated schemas from output; ignore if there's an error or no output yet\n const output = part.output as { schemas?: any[]; error?: unknown } | undefined;\n if (!output || output.error || !Array.isArray(output.schemas)) return;\n\n const baseId = part.toolCallId ?? `${message.id}-${partIndex}`;\n\n output.schemas.forEach((schema, schemaIndex) => {\n const revisionId = `${baseId}-${schema.uid ?? schema.name ?? schemaIndex}`;\n const type = (schema.action as SchemaChange['type']) || 'update';\n changes.push({ type, schema, revisionId });\n });\n }\n });\n\n return changes;\n}\n\nexport const SchemaChatProvider = ({ children }: { children: ReactNode }) => {\n const [lastRevisedId, setLastRevisedId] = useState<string | null>(null);\n const { messages, status } = useStrapiChat();\n const { contentTypes, components, applyChange } = useDataManager();\n const dispatch = useGuidedTour('SchemaChatProvider', (s) => s.dispatch);\n const state = useGuidedTour('SchemaChatProvider', (s) => s.state);\n\n useEffect(() => {\n const latestMessage = messages[messages.length - 1];\n if (!latestMessage) return;\n if (latestMessage.role !== 'assistant') return;\n // Wait until message streaming has finished\n if (status !== 'ready') return;\n\n // const schemaChanges = latestMessage.schemaChanges;\n const schemaChanges = extractSchemaChangesFromMessage(latestMessage);\n\n // Check if addField action is already completed\n const isAddFieldCompleted = state.completedActions.includes(\n GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField\n );\n\n schemaChanges.forEach((change: SchemaChange) => {\n const oldSchema =\n contentTypes[change.schema.uid as any] || components[change.schema.uid as any];\n const newSchema = transformChatToCTB(change.schema, oldSchema);\n\n // Check if any attributes/fields are being added to any schema (existing or new)\n if (!isAddFieldCompleted && change.schema.attributes) {\n // If a field is being added or updated, dispatch guided tour action to show Save tooltip\n if (change.type !== 'remove' && Object.keys(change.schema.attributes).length > 0) {\n dispatch({\n type: 'set_completed_actions',\n payload: [GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField],\n });\n }\n }\n\n applyChange({\n action: TYPE_TO_ACTION[change.type]!,\n schema: newSchema,\n });\n });\n setLastRevisedId(latestMessage.id);\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [messages]);\n\n return (\n <SchemaContext.Provider value={{ lastRevisedId, setLastRevisedId }}>\n {children}\n </SchemaContext.Provider>\n );\n};\n\nexport const useChatSchema = () => {\n const context = useContext(SchemaContext);\n if (context === undefined) {\n throw new Error('useSchema must be used within a SchemaProvider');\n }\n return context;\n};\n"],"names":["SchemaContext","createContext","undefined","TYPE_TO_ACTION","create","update","remove","extractSchemaChangesFromMessage","message","role","changes","parts","forEach","part","partIndex","type","output","error","Array","isArray","schemas","baseId","toolCallId","id","schema","schemaIndex","revisionId","uid","name","action","push","SchemaChatProvider","children","lastRevisedId","setLastRevisedId","useState","messages","status","useStrapiChat","contentTypes","components","applyChange","useDataManager","dispatch","useGuidedTour","s","state","useEffect","latestMessage","length","schemaChanges","isAddFieldCompleted","completedActions","includes","GUIDED_TOUR_REQUIRED_ACTIONS","contentTypeBuilder","addField","change","oldSchema","newSchema","transformChatToCTB","attributes","Object","keys","payload","_jsx","Provider","value"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SchemaProvider.mjs","sources":["../../../../../admin/src/components/AIChat/providers/SchemaProvider.tsx"],"sourcesContent":["import { createContext, useContext, ReactNode, useEffect, useState } from 'react';\n\nimport { GUIDED_TOUR_REQUIRED_ACTIONS, useGuidedTour } from '@strapi/admin/strapi-admin';\n\nimport { useDataManager } from '../../DataManager/useDataManager';\nimport { transformChatToCTB } from '../lib/transforms/schemas/toCTB';\nimport { SchemaChange } from '../lib/types/annotations';\nimport { AIMessage } from '../lib/types/messages';\n\nimport { useStrapiChat } from './ChatProvider';\n\ninterface SchemaContextType {\n lastRevisedId: string | null;\n setLastRevisedId: (id: string | null) => void;\n}\n\nconst SchemaContext = createContext<SchemaContextType | undefined>(undefined);\n\nconst TYPE_TO_ACTION: Record<string, 'add' | 'update' | 'delete'> = {\n create: 'add',\n update: 'update',\n remove: 'delete',\n};\n\nfunction extractSchemaChangesFromMessage(message: AIMessage): SchemaChange[] {\n if (message.role !== 'assistant') return [];\n\n const changes: SchemaChange[] = [];\n\n message.parts?.forEach((part, partIndex) => {\n // We only care about the schema generation tool\n if (part && typeof part === 'object' && part.type === 'tool-schemaGenerationTool') {\n // Prefer validated schemas from output; ignore if there's an error or no output yet\n const output = part.output as { schemas?: any[]; error?: unknown } | undefined;\n if (!output || output.error || !Array.isArray(output.schemas)) return;\n\n const baseId = part.toolCallId ?? `${message.id}-${partIndex}`;\n\n output.schemas.forEach((schema, schemaIndex) => {\n const revisionId = `${baseId}-${schema.uid ?? schema.name ?? schemaIndex}`;\n const type = (schema.action as SchemaChange['type']) || 'update';\n changes.push({ type, schema, revisionId });\n });\n }\n });\n\n return changes;\n}\n\nexport const SchemaChatProvider = ({ children }: { children: ReactNode }) => {\n const [lastRevisedId, setLastRevisedId] = useState<string | null>(null);\n const { messages, status } = useStrapiChat();\n const { contentTypes, components, applyChange } = useDataManager();\n const dispatch = useGuidedTour('SchemaChatProvider', (s) => s.dispatch);\n const state = useGuidedTour('SchemaChatProvider', (s) => s.state);\n\n useEffect(() => {\n const latestMessage = messages[messages.length - 1];\n if (!latestMessage) return;\n if (latestMessage.role !== 'assistant') return;\n // Wait until message streaming has finished\n if (status !== 'ready') return;\n\n // const schemaChanges = latestMessage.schemaChanges;\n const schemaChanges = extractSchemaChangesFromMessage(latestMessage);\n\n // Check if addField action is already completed\n const isAddFieldCompleted = state.completedActions.includes(\n GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField\n );\n\n schemaChanges.forEach((change: SchemaChange) => {\n const oldSchema =\n contentTypes[change.schema.uid as any] || components[change.schema.uid as any];\n const newSchema = transformChatToCTB(change.schema, oldSchema);\n\n // Check if any attributes/fields are being added to any schema (existing or new)\n if (!isAddFieldCompleted && change.schema.attributes) {\n // If a field is being added or updated, dispatch guided tour action to show Save tooltip\n if (change.type !== 'remove' && Object.keys(change.schema.attributes).length > 0) {\n dispatch({\n type: 'set_completed_actions',\n payload: [GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField],\n });\n }\n }\n\n applyChange({\n action: TYPE_TO_ACTION[change.type]!,\n schema: newSchema,\n });\n });\n setLastRevisedId(latestMessage.id);\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [messages]);\n\n return (\n <SchemaContext.Provider value={{ lastRevisedId, setLastRevisedId }}>\n {children}\n </SchemaContext.Provider>\n );\n};\n\nexport const useChatSchema = () => {\n const context = useContext(SchemaContext);\n if (context === undefined) {\n throw new Error('useSchema must be used within a SchemaProvider');\n }\n return context;\n};\n"],"names":["SchemaContext","createContext","undefined","TYPE_TO_ACTION","create","update","remove","extractSchemaChangesFromMessage","message","role","changes","parts","forEach","part","partIndex","type","output","error","Array","isArray","schemas","baseId","toolCallId","id","schema","schemaIndex","revisionId","uid","name","action","push","SchemaChatProvider","children","lastRevisedId","setLastRevisedId","useState","messages","status","useStrapiChat","contentTypes","components","applyChange","useDataManager","dispatch","useGuidedTour","s","state","useEffect","latestMessage","length","schemaChanges","isAddFieldCompleted","completedActions","includes","GUIDED_TOUR_REQUIRED_ACTIONS","contentTypeBuilder","addField","change","oldSchema","newSchema","transformChatToCTB","attributes","Object","keys","payload","_jsx","Provider","value"],"mappings":";;;;;;;AAgBA,MAAMA,8BAAgBC,aAA6CC,CAAAA,SAAAA,CAAAA;AAEnE,MAAMC,cAA8D,GAAA;IAClEC,MAAQ,EAAA,KAAA;IACRC,MAAQ,EAAA,QAAA;IACRC,MAAQ,EAAA;AACV,CAAA;AAEA,SAASC,gCAAgCC,OAAkB,EAAA;AACzD,IAAA,IAAIA,OAAQC,CAAAA,IAAI,KAAK,WAAA,EAAa,OAAO,EAAE;AAE3C,IAAA,MAAMC,UAA0B,EAAE;AAElCF,IAAAA,OAAAA,CAAQG,KAAK,EAAEC,OAAQ,CAAA,CAACC,IAAMC,EAAAA,SAAAA,GAAAA;;AAE5B,QAAA,IAAID,QAAQ,OAAOA,IAAAA,KAAS,YAAYA,IAAKE,CAAAA,IAAI,KAAK,2BAA6B,EAAA;;YAEjF,MAAMC,MAAAA,GAASH,KAAKG,MAAM;YAC1B,IAAI,CAACA,MAAUA,IAAAA,MAAAA,CAAOC,KAAK,IAAI,CAACC,KAAAA,CAAMC,OAAO,CAACH,MAAOI,CAAAA,OAAO,CAAG,EAAA;
|
|
1
|
+
{"version":3,"file":"SchemaProvider.mjs","sources":["../../../../../admin/src/components/AIChat/providers/SchemaProvider.tsx"],"sourcesContent":["import { createContext, useContext, ReactNode, useEffect, useState } from 'react';\n\nimport { GUIDED_TOUR_REQUIRED_ACTIONS, useGuidedTour } from '@strapi/admin/strapi-admin';\n\nimport { useDataManager } from '../../DataManager/useDataManager';\nimport { transformChatToCTB } from '../lib/transforms/schemas/toCTB';\nimport { SchemaChange } from '../lib/types/annotations';\nimport { AIMessage } from '../lib/types/messages';\n\nimport { useStrapiChat } from './ChatProvider';\n\ninterface SchemaContextType {\n lastRevisedId: string | null;\n setLastRevisedId: (id: string | null) => void;\n}\n\nconst SchemaContext = createContext<SchemaContextType | undefined>(undefined);\n\nconst TYPE_TO_ACTION: Record<string, 'add' | 'update' | 'delete'> = {\n create: 'add',\n update: 'update',\n remove: 'delete',\n};\n\nfunction extractSchemaChangesFromMessage(message: AIMessage): SchemaChange[] {\n if (message.role !== 'assistant') return [];\n\n const changes: SchemaChange[] = [];\n\n message.parts?.forEach((part, partIndex) => {\n // We only care about the schema generation tool\n if (part && typeof part === 'object' && part.type === 'tool-schemaGenerationTool') {\n // Prefer validated schemas from output; ignore if there's an error or no output yet\n const output = part.output as { schemas?: any[]; error?: unknown } | undefined;\n if (!output || output.error || !Array.isArray(output.schemas)) return;\n\n const baseId = part.toolCallId ?? `${message.id}-${partIndex}`;\n\n output.schemas.forEach((schema, schemaIndex) => {\n const revisionId = `${baseId}-${schema.uid ?? schema.name ?? schemaIndex}`;\n const type = (schema.action as SchemaChange['type']) || 'update';\n changes.push({ type, schema, revisionId });\n });\n }\n });\n\n return changes;\n}\n\nexport const SchemaChatProvider = ({ children }: { children: ReactNode }) => {\n const [lastRevisedId, setLastRevisedId] = useState<string | null>(null);\n const { messages, status } = useStrapiChat();\n const { contentTypes, components, applyChange } = useDataManager();\n const dispatch = useGuidedTour('SchemaChatProvider', (s) => s.dispatch);\n const state = useGuidedTour('SchemaChatProvider', (s) => s.state);\n\n useEffect(() => {\n const latestMessage = messages[messages.length - 1];\n if (!latestMessage) return;\n if (latestMessage.role !== 'assistant') return;\n // Wait until message streaming has finished\n if (status !== 'ready') return;\n\n // const schemaChanges = latestMessage.schemaChanges;\n const schemaChanges = extractSchemaChangesFromMessage(latestMessage);\n\n // Check if addField action is already completed\n const isAddFieldCompleted = state.completedActions.includes(\n GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField\n );\n\n schemaChanges.forEach((change: SchemaChange) => {\n const oldSchema =\n contentTypes[change.schema.uid as any] || components[change.schema.uid as any];\n const newSchema = transformChatToCTB(change.schema, oldSchema);\n\n // Check if any attributes/fields are being added to any schema (existing or new)\n if (!isAddFieldCompleted && change.schema.attributes) {\n // If a field is being added or updated, dispatch guided tour action to show Save tooltip\n if (change.type !== 'remove' && Object.keys(change.schema.attributes).length > 0) {\n dispatch({\n type: 'set_completed_actions',\n payload: [GUIDED_TOUR_REQUIRED_ACTIONS.contentTypeBuilder.addField],\n });\n }\n }\n\n applyChange({\n action: TYPE_TO_ACTION[change.type]!,\n schema: newSchema,\n });\n });\n setLastRevisedId(latestMessage.id);\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [messages]);\n\n return (\n <SchemaContext.Provider value={{ lastRevisedId, setLastRevisedId }}>\n {children}\n </SchemaContext.Provider>\n );\n};\n\nexport const useChatSchema = () => {\n const context = useContext(SchemaContext);\n if (context === undefined) {\n throw new Error('useSchema must be used within a SchemaProvider');\n }\n return context;\n};\n"],"names":["SchemaContext","createContext","undefined","TYPE_TO_ACTION","create","update","remove","extractSchemaChangesFromMessage","message","role","changes","parts","forEach","part","partIndex","type","output","error","Array","isArray","schemas","baseId","toolCallId","id","schema","schemaIndex","revisionId","uid","name","action","push","SchemaChatProvider","children","lastRevisedId","setLastRevisedId","useState","messages","status","useStrapiChat","contentTypes","components","applyChange","useDataManager","dispatch","useGuidedTour","s","state","useEffect","latestMessage","length","schemaChanges","isAddFieldCompleted","completedActions","includes","GUIDED_TOUR_REQUIRED_ACTIONS","contentTypeBuilder","addField","change","oldSchema","newSchema","transformChatToCTB","attributes","Object","keys","payload","_jsx","Provider","value"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AttributeOption.js","sources":["../../../../admin/src/components/AttributeOptions/AttributeOption.tsx"],"sourcesContent":["/**\n *\n * AttributeOption\n *\n */\n\nimport { Box, Flex, Typography } from '@strapi/design-system';\nimport { Sparkle } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { getTrad } from '../../utils/getTrad';\nimport { AttributeIcon, IconByType } from '../AttributeIcon';\nimport { useFormModalNavigation } from '../FormModalNavigation/useFormModalNavigation';\n\nimport { OptionBoxWrapper } from './OptionBoxWrapper';\n\nconst newAttributes: string[] = [];\n\nconst NewBadge = () => (\n <Flex grow={1} justifyContent=\"flex-end\">\n <Flex gap={1} hasRadius background=\"alternative100\" padding={`0.2rem 0.4rem`}>\n <Sparkle width={`1rem`} height={`1rem`} fill=\"alternative600\" />\n <Typography textColor=\"alternative600\" variant=\"sigma\">\n New\n </Typography>\n </Flex>\n </Flex>\n);\n\ntype AttributeOptionProps = {\n type: IconByType;\n};\n\nexport const AttributeOption = ({ type = 'text' }: AttributeOptionProps) => {\n const { formatMessage } = useIntl();\n\n const { onClickSelectField } = useFormModalNavigation();\n\n const handleClick = () => {\n const step = type === 'component' ? '1' : null;\n\n onClickSelectField({\n attributeType: type,\n step,\n });\n };\n\n return (\n <OptionBoxWrapper padding={4} tag=\"button\" hasRadius type=\"button\" onClick={handleClick}>\n <Flex>\n <AttributeIcon type={type} />\n <Box paddingLeft={4} width=\"100%\">\n <Flex justifyContent=\"space-between\">\n <Typography fontWeight=\"bold\" textColor=\"neutral800\">\n {formatMessage({ id: getTrad(`attribute.${type}`), defaultMessage: type })}\n </Typography>\n {newAttributes.includes(type) && <NewBadge />}\n </Flex>\n <Flex>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {formatMessage({\n id: getTrad(`attribute.${type}.description`),\n defaultMessage: 'A type for modeling data',\n })}\n </Typography>\n </Flex>\n </Box>\n </Flex>\n </OptionBoxWrapper>\n );\n};\n"],"names":["newAttributes","NewBadge","_jsx","Flex","grow","justifyContent","_jsxs","gap","hasRadius","background","padding","Sparkle","width","height","fill","Typography","textColor","variant","AttributeOption","type","formatMessage","useIntl","onClickSelectField","useFormModalNavigation","handleClick","step","attributeType","OptionBoxWrapper","tag","onClick","AttributeIcon","Box","paddingLeft","fontWeight","id","getTrad","defaultMessage","includes"],"mappings":";;;;;;;;;;;AAgBA,MAAMA,gBAA0B,EAAE;AAElC,MAAMC,QAAAA,GAAW,kBACfC,cAACC,CAAAA,iBAAAA,EAAAA;QAAKC,IAAM,EAAA,CAAA;QAAGC,cAAe,EAAA,UAAA;AAC5B,QAAA,QAAA,gBAAAC,eAACH,CAAAA,iBAAAA,EAAAA;YAAKI,GAAK,EAAA,CAAA;YAAGC,SAAS,EAAA,IAAA;YAACC,UAAW,EAAA,gBAAA;YAAiBC,OAAS,EAAA,CAAC,aAAa,CAAC;;8BAC1ER,cAACS,CAAAA,aAAAA,EAAAA;oBAAQC,KAAO,EAAA,CAAC,IAAI,CAAC;oBAAEC,MAAQ,EAAA,CAAC,IAAI,CAAC;oBAAEC,IAAK,EAAA;;8BAC7CZ,cAACa,CAAAA,uBAAAA,EAAAA;oBAAWC,SAAU,EAAA,gBAAA;oBAAiBC,OAAQ,EAAA,OAAA;AAAQ,oBAAA,QAAA,EAAA;;;;;MAWhDC,eAAkB,GAAA,CAAC,EAAEC,IAAAA,GAAO,MAAM,EAAwB,GAAA;IACrE,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;IAE1B,MAAM,EAAEC,kBAAkB,EAAE,GAAGC,6CAAAA,EAAAA;AAE/B,IAAA,MAAMC,WAAc,GAAA,IAAA;QAClB,MAAMC,IAAAA,GAAON,IAAS,KAAA,WAAA,GAAc,GAAM,GAAA,IAAA;QAE1CG,kBAAmB,CAAA;YACjBI,aAAeP,EAAAA,IAAAA;AACfM,YAAAA;AACF,SAAA,CAAA;AACF,KAAA;AAEA,IAAA,qBACEvB,cAACyB,CAAAA,iCAAAA,EAAAA;QAAiBjB,OAAS,EAAA,CAAA;QAAGkB,GAAI,EAAA,QAAA;QAASpB,SAAS,EAAA,IAAA;QAACW,IAAK,EAAA,QAAA;QAASU,OAASL,EAAAA,WAAAA;AAC1E,QAAA,QAAA,gBAAAlB,eAACH,CAAAA,iBAAAA,EAAAA;;8BACCD,cAAC4B,CAAAA,2BAAAA,EAAAA;oBAAcX,IAAMA,EAAAA;;8BACrBb,eAACyB,CAAAA,gBAAAA,EAAAA;oBAAIC,WAAa,EAAA,CAAA;oBAAGpB,KAAM,EAAA,MAAA;;sCACzBN,eAACH,CAAAA,iBAAAA,EAAAA;4BAAKE,cAAe,EAAA,eAAA;;8CACnBH,cAACa,CAAAA,uBAAAA,EAAAA;oCAAWkB,UAAW,EAAA,MAAA;oCAAOjB,SAAU,EAAA,YAAA;8CACrCI,aAAc,CAAA;AAAEc,wCAAAA,EAAAA,EAAIC,eAAQ,CAAA,CAAC,UAAU,EAAEhB,
|
|
1
|
+
{"version":3,"file":"AttributeOption.js","sources":["../../../../admin/src/components/AttributeOptions/AttributeOption.tsx"],"sourcesContent":["/**\n *\n * AttributeOption\n *\n */\n\nimport { Box, Flex, Typography } from '@strapi/design-system';\nimport { Sparkle } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { getTrad } from '../../utils/getTrad';\nimport { AttributeIcon, IconByType } from '../AttributeIcon';\nimport { useFormModalNavigation } from '../FormModalNavigation/useFormModalNavigation';\n\nimport { OptionBoxWrapper } from './OptionBoxWrapper';\n\nconst newAttributes: string[] = [];\n\nconst NewBadge = () => (\n <Flex grow={1} justifyContent=\"flex-end\">\n <Flex gap={1} hasRadius background=\"alternative100\" padding={`0.2rem 0.4rem`}>\n <Sparkle width={`1rem`} height={`1rem`} fill=\"alternative600\" />\n <Typography textColor=\"alternative600\" variant=\"sigma\">\n New\n </Typography>\n </Flex>\n </Flex>\n);\n\ntype AttributeOptionProps = {\n type: IconByType;\n};\n\nexport const AttributeOption = ({ type = 'text' }: AttributeOptionProps) => {\n const { formatMessage } = useIntl();\n\n const { onClickSelectField } = useFormModalNavigation();\n\n const handleClick = () => {\n const step = type === 'component' ? '1' : null;\n\n onClickSelectField({\n attributeType: type,\n step,\n });\n };\n\n return (\n <OptionBoxWrapper padding={4} tag=\"button\" hasRadius type=\"button\" onClick={handleClick}>\n <Flex>\n <AttributeIcon type={type} />\n <Box paddingLeft={4} width=\"100%\">\n <Flex justifyContent=\"space-between\">\n <Typography fontWeight=\"bold\" textColor=\"neutral800\">\n {formatMessage({ id: getTrad(`attribute.${type}`), defaultMessage: type })}\n </Typography>\n {newAttributes.includes(type) && <NewBadge />}\n </Flex>\n <Flex>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {formatMessage({\n id: getTrad(`attribute.${type}.description`),\n defaultMessage: 'A type for modeling data',\n })}\n </Typography>\n </Flex>\n </Box>\n </Flex>\n </OptionBoxWrapper>\n );\n};\n"],"names":["newAttributes","NewBadge","_jsx","Flex","grow","justifyContent","_jsxs","gap","hasRadius","background","padding","Sparkle","width","height","fill","Typography","textColor","variant","AttributeOption","type","formatMessage","useIntl","onClickSelectField","useFormModalNavigation","handleClick","step","attributeType","OptionBoxWrapper","tag","onClick","AttributeIcon","Box","paddingLeft","fontWeight","id","getTrad","defaultMessage","includes"],"mappings":";;;;;;;;;;;AAgBA,MAAMA,gBAA0B,EAAE;AAElC,MAAMC,QAAAA,GAAW,kBACfC,cAACC,CAAAA,iBAAAA,EAAAA;QAAKC,IAAM,EAAA,CAAA;QAAGC,cAAe,EAAA,UAAA;AAC5B,QAAA,QAAA,gBAAAC,eAACH,CAAAA,iBAAAA,EAAAA;YAAKI,GAAK,EAAA,CAAA;YAAGC,SAAS,EAAA,IAAA;YAACC,UAAW,EAAA,gBAAA;YAAiBC,OAAS,EAAA,CAAC,aAAa,CAAC;;8BAC1ER,cAACS,CAAAA,aAAAA,EAAAA;oBAAQC,KAAO,EAAA,CAAC,IAAI,CAAC;oBAAEC,MAAQ,EAAA,CAAC,IAAI,CAAC;oBAAEC,IAAK,EAAA;;8BAC7CZ,cAACa,CAAAA,uBAAAA,EAAAA;oBAAWC,SAAU,EAAA,gBAAA;oBAAiBC,OAAQ,EAAA,OAAA;AAAQ,oBAAA,QAAA,EAAA;;;;;MAWhDC,eAAkB,GAAA,CAAC,EAAEC,IAAAA,GAAO,MAAM,EAAwB,GAAA;IACrE,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;IAE1B,MAAM,EAAEC,kBAAkB,EAAE,GAAGC,6CAAAA,EAAAA;AAE/B,IAAA,MAAMC,WAAc,GAAA,IAAA;QAClB,MAAMC,IAAAA,GAAON,IAAS,KAAA,WAAA,GAAc,GAAM,GAAA,IAAA;QAE1CG,kBAAmB,CAAA;YACjBI,aAAeP,EAAAA,IAAAA;AACfM,YAAAA;AACF,SAAA,CAAA;AACF,KAAA;AAEA,IAAA,qBACEvB,cAACyB,CAAAA,iCAAAA,EAAAA;QAAiBjB,OAAS,EAAA,CAAA;QAAGkB,GAAI,EAAA,QAAA;QAASpB,SAAS,EAAA,IAAA;QAACW,IAAK,EAAA,QAAA;QAASU,OAASL,EAAAA,WAAAA;AAC1E,QAAA,QAAA,gBAAAlB,eAACH,CAAAA,iBAAAA,EAAAA;;8BACCD,cAAC4B,CAAAA,2BAAAA,EAAAA;oBAAcX,IAAMA,EAAAA;;8BACrBb,eAACyB,CAAAA,gBAAAA,EAAAA;oBAAIC,WAAa,EAAA,CAAA;oBAAGpB,KAAM,EAAA,MAAA;;sCACzBN,eAACH,CAAAA,iBAAAA,EAAAA;4BAAKE,cAAe,EAAA,eAAA;;8CACnBH,cAACa,CAAAA,uBAAAA,EAAAA;oCAAWkB,UAAW,EAAA,MAAA;oCAAOjB,SAAU,EAAA,YAAA;8CACrCI,aAAc,CAAA;AAAEc,wCAAAA,EAAAA,EAAIC,eAAQ,CAAA,CAAC,UAAU,EAAEhB,IAAM,CAAA,CAAA,CAAA;wCAAGiB,cAAgBjB,EAAAA;AAAK,qCAAA;;gCAEzEnB,aAAcqC,CAAAA,QAAQ,CAAClB,IAAAA,CAAAA,kBAASjB,cAACD,CAAAA,QAAAA,EAAAA,EAAAA;;;sCAEpCC,cAACC,CAAAA,iBAAAA,EAAAA;AACC,4BAAA,QAAA,gBAAAD,cAACa,CAAAA,uBAAAA,EAAAA;gCAAWE,OAAQ,EAAA,IAAA;gCAAKD,SAAU,EAAA,YAAA;0CAChCI,aAAc,CAAA;AACbc,oCAAAA,EAAAA,EAAIC,gBAAQ,CAAC,UAAU,EAAEhB,IAAAA,CAAK,YAAY,CAAC,CAAA;oCAC3CiB,cAAgB,EAAA;AAClB,iCAAA;;;;;;;;AAOd;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AttributeOption.mjs","sources":["../../../../admin/src/components/AttributeOptions/AttributeOption.tsx"],"sourcesContent":["/**\n *\n * AttributeOption\n *\n */\n\nimport { Box, Flex, Typography } from '@strapi/design-system';\nimport { Sparkle } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { getTrad } from '../../utils/getTrad';\nimport { AttributeIcon, IconByType } from '../AttributeIcon';\nimport { useFormModalNavigation } from '../FormModalNavigation/useFormModalNavigation';\n\nimport { OptionBoxWrapper } from './OptionBoxWrapper';\n\nconst newAttributes: string[] = [];\n\nconst NewBadge = () => (\n <Flex grow={1} justifyContent=\"flex-end\">\n <Flex gap={1} hasRadius background=\"alternative100\" padding={`0.2rem 0.4rem`}>\n <Sparkle width={`1rem`} height={`1rem`} fill=\"alternative600\" />\n <Typography textColor=\"alternative600\" variant=\"sigma\">\n New\n </Typography>\n </Flex>\n </Flex>\n);\n\ntype AttributeOptionProps = {\n type: IconByType;\n};\n\nexport const AttributeOption = ({ type = 'text' }: AttributeOptionProps) => {\n const { formatMessage } = useIntl();\n\n const { onClickSelectField } = useFormModalNavigation();\n\n const handleClick = () => {\n const step = type === 'component' ? '1' : null;\n\n onClickSelectField({\n attributeType: type,\n step,\n });\n };\n\n return (\n <OptionBoxWrapper padding={4} tag=\"button\" hasRadius type=\"button\" onClick={handleClick}>\n <Flex>\n <AttributeIcon type={type} />\n <Box paddingLeft={4} width=\"100%\">\n <Flex justifyContent=\"space-between\">\n <Typography fontWeight=\"bold\" textColor=\"neutral800\">\n {formatMessage({ id: getTrad(`attribute.${type}`), defaultMessage: type })}\n </Typography>\n {newAttributes.includes(type) && <NewBadge />}\n </Flex>\n <Flex>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {formatMessage({\n id: getTrad(`attribute.${type}.description`),\n defaultMessage: 'A type for modeling data',\n })}\n </Typography>\n </Flex>\n </Box>\n </Flex>\n </OptionBoxWrapper>\n );\n};\n"],"names":["newAttributes","NewBadge","_jsx","Flex","grow","justifyContent","_jsxs","gap","hasRadius","background","padding","Sparkle","width","height","fill","Typography","textColor","variant","AttributeOption","type","formatMessage","useIntl","onClickSelectField","useFormModalNavigation","handleClick","step","attributeType","OptionBoxWrapper","tag","onClick","AttributeIcon","Box","paddingLeft","fontWeight","id","getTrad","defaultMessage","includes"],"mappings":";;;;;;;;;AAgBA,MAAMA,gBAA0B,EAAE;AAElC,MAAMC,QAAAA,GAAW,kBACfC,GAACC,CAAAA,IAAAA,EAAAA;QAAKC,IAAM,EAAA,CAAA;QAAGC,cAAe,EAAA,UAAA;AAC5B,QAAA,QAAA,gBAAAC,IAACH,CAAAA,IAAAA,EAAAA;YAAKI,GAAK,EAAA,CAAA;YAAGC,SAAS,EAAA,IAAA;YAACC,UAAW,EAAA,gBAAA;YAAiBC,OAAS,EAAA,CAAC,aAAa,CAAC;;8BAC1ER,GAACS,CAAAA,OAAAA,EAAAA;oBAAQC,KAAO,EAAA,CAAC,IAAI,CAAC;oBAAEC,MAAQ,EAAA,CAAC,IAAI,CAAC;oBAAEC,IAAK,EAAA;;8BAC7CZ,GAACa,CAAAA,UAAAA,EAAAA;oBAAWC,SAAU,EAAA,gBAAA;oBAAiBC,OAAQ,EAAA,OAAA;AAAQ,oBAAA,QAAA,EAAA;;;;;MAWhDC,eAAkB,GAAA,CAAC,EAAEC,IAAAA,GAAO,MAAM,EAAwB,GAAA;IACrE,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;IAE1B,MAAM,EAAEC,kBAAkB,EAAE,GAAGC,sBAAAA,EAAAA;AAE/B,IAAA,MAAMC,WAAc,GAAA,IAAA;QAClB,MAAMC,IAAAA,GAAON,IAAS,KAAA,WAAA,GAAc,GAAM,GAAA,IAAA;QAE1CG,kBAAmB,CAAA;YACjBI,aAAeP,EAAAA,IAAAA;AACfM,YAAAA;AACF,SAAA,CAAA;AACF,KAAA;AAEA,IAAA,qBACEvB,GAACyB,CAAAA,gBAAAA,EAAAA;QAAiBjB,OAAS,EAAA,CAAA;QAAGkB,GAAI,EAAA,QAAA;QAASpB,SAAS,EAAA,IAAA;QAACW,IAAK,EAAA,QAAA;QAASU,OAASL,EAAAA,WAAAA;AAC1E,QAAA,QAAA,gBAAAlB,IAACH,CAAAA,IAAAA,EAAAA;;8BACCD,GAAC4B,CAAAA,aAAAA,EAAAA;oBAAcX,IAAMA,EAAAA;;8BACrBb,IAACyB,CAAAA,GAAAA,EAAAA;oBAAIC,WAAa,EAAA,CAAA;oBAAGpB,KAAM,EAAA,MAAA;;sCACzBN,IAACH,CAAAA,IAAAA,EAAAA;4BAAKE,cAAe,EAAA,eAAA;;8CACnBH,GAACa,CAAAA,UAAAA,EAAAA;oCAAWkB,UAAW,EAAA,MAAA;oCAAOjB,SAAU,EAAA,YAAA;8CACrCI,aAAc,CAAA;AAAEc,wCAAAA,EAAAA,EAAIC,OAAQ,CAAA,CAAC,UAAU,EAAEhB,
|
|
1
|
+
{"version":3,"file":"AttributeOption.mjs","sources":["../../../../admin/src/components/AttributeOptions/AttributeOption.tsx"],"sourcesContent":["/**\n *\n * AttributeOption\n *\n */\n\nimport { Box, Flex, Typography } from '@strapi/design-system';\nimport { Sparkle } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\n\nimport { getTrad } from '../../utils/getTrad';\nimport { AttributeIcon, IconByType } from '../AttributeIcon';\nimport { useFormModalNavigation } from '../FormModalNavigation/useFormModalNavigation';\n\nimport { OptionBoxWrapper } from './OptionBoxWrapper';\n\nconst newAttributes: string[] = [];\n\nconst NewBadge = () => (\n <Flex grow={1} justifyContent=\"flex-end\">\n <Flex gap={1} hasRadius background=\"alternative100\" padding={`0.2rem 0.4rem`}>\n <Sparkle width={`1rem`} height={`1rem`} fill=\"alternative600\" />\n <Typography textColor=\"alternative600\" variant=\"sigma\">\n New\n </Typography>\n </Flex>\n </Flex>\n);\n\ntype AttributeOptionProps = {\n type: IconByType;\n};\n\nexport const AttributeOption = ({ type = 'text' }: AttributeOptionProps) => {\n const { formatMessage } = useIntl();\n\n const { onClickSelectField } = useFormModalNavigation();\n\n const handleClick = () => {\n const step = type === 'component' ? '1' : null;\n\n onClickSelectField({\n attributeType: type,\n step,\n });\n };\n\n return (\n <OptionBoxWrapper padding={4} tag=\"button\" hasRadius type=\"button\" onClick={handleClick}>\n <Flex>\n <AttributeIcon type={type} />\n <Box paddingLeft={4} width=\"100%\">\n <Flex justifyContent=\"space-between\">\n <Typography fontWeight=\"bold\" textColor=\"neutral800\">\n {formatMessage({ id: getTrad(`attribute.${type}`), defaultMessage: type })}\n </Typography>\n {newAttributes.includes(type) && <NewBadge />}\n </Flex>\n <Flex>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {formatMessage({\n id: getTrad(`attribute.${type}.description`),\n defaultMessage: 'A type for modeling data',\n })}\n </Typography>\n </Flex>\n </Box>\n </Flex>\n </OptionBoxWrapper>\n );\n};\n"],"names":["newAttributes","NewBadge","_jsx","Flex","grow","justifyContent","_jsxs","gap","hasRadius","background","padding","Sparkle","width","height","fill","Typography","textColor","variant","AttributeOption","type","formatMessage","useIntl","onClickSelectField","useFormModalNavigation","handleClick","step","attributeType","OptionBoxWrapper","tag","onClick","AttributeIcon","Box","paddingLeft","fontWeight","id","getTrad","defaultMessage","includes"],"mappings":";;;;;;;;;AAgBA,MAAMA,gBAA0B,EAAE;AAElC,MAAMC,QAAAA,GAAW,kBACfC,GAACC,CAAAA,IAAAA,EAAAA;QAAKC,IAAM,EAAA,CAAA;QAAGC,cAAe,EAAA,UAAA;AAC5B,QAAA,QAAA,gBAAAC,IAACH,CAAAA,IAAAA,EAAAA;YAAKI,GAAK,EAAA,CAAA;YAAGC,SAAS,EAAA,IAAA;YAACC,UAAW,EAAA,gBAAA;YAAiBC,OAAS,EAAA,CAAC,aAAa,CAAC;;8BAC1ER,GAACS,CAAAA,OAAAA,EAAAA;oBAAQC,KAAO,EAAA,CAAC,IAAI,CAAC;oBAAEC,MAAQ,EAAA,CAAC,IAAI,CAAC;oBAAEC,IAAK,EAAA;;8BAC7CZ,GAACa,CAAAA,UAAAA,EAAAA;oBAAWC,SAAU,EAAA,gBAAA;oBAAiBC,OAAQ,EAAA,OAAA;AAAQ,oBAAA,QAAA,EAAA;;;;;MAWhDC,eAAkB,GAAA,CAAC,EAAEC,IAAAA,GAAO,MAAM,EAAwB,GAAA;IACrE,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;IAE1B,MAAM,EAAEC,kBAAkB,EAAE,GAAGC,sBAAAA,EAAAA;AAE/B,IAAA,MAAMC,WAAc,GAAA,IAAA;QAClB,MAAMC,IAAAA,GAAON,IAAS,KAAA,WAAA,GAAc,GAAM,GAAA,IAAA;QAE1CG,kBAAmB,CAAA;YACjBI,aAAeP,EAAAA,IAAAA;AACfM,YAAAA;AACF,SAAA,CAAA;AACF,KAAA;AAEA,IAAA,qBACEvB,GAACyB,CAAAA,gBAAAA,EAAAA;QAAiBjB,OAAS,EAAA,CAAA;QAAGkB,GAAI,EAAA,QAAA;QAASpB,SAAS,EAAA,IAAA;QAACW,IAAK,EAAA,QAAA;QAASU,OAASL,EAAAA,WAAAA;AAC1E,QAAA,QAAA,gBAAAlB,IAACH,CAAAA,IAAAA,EAAAA;;8BACCD,GAAC4B,CAAAA,aAAAA,EAAAA;oBAAcX,IAAMA,EAAAA;;8BACrBb,IAACyB,CAAAA,GAAAA,EAAAA;oBAAIC,WAAa,EAAA,CAAA;oBAAGpB,KAAM,EAAA,MAAA;;sCACzBN,IAACH,CAAAA,IAAAA,EAAAA;4BAAKE,cAAe,EAAA,eAAA;;8CACnBH,GAACa,CAAAA,UAAAA,EAAAA;oCAAWkB,UAAW,EAAA,MAAA;oCAAOjB,SAAU,EAAA,YAAA;8CACrCI,aAAc,CAAA;AAAEc,wCAAAA,EAAAA,EAAIC,OAAQ,CAAA,CAAC,UAAU,EAAEhB,IAAM,CAAA,CAAA,CAAA;wCAAGiB,cAAgBjB,EAAAA;AAAK,qCAAA;;gCAEzEnB,aAAcqC,CAAAA,QAAQ,CAAClB,IAAAA,CAAAA,kBAASjB,GAACD,CAAAA,QAAAA,EAAAA,EAAAA;;;sCAEpCC,GAACC,CAAAA,IAAAA,EAAAA;AACC,4BAAA,QAAA,gBAAAD,GAACa,CAAAA,UAAAA,EAAAA;gCAAWE,OAAQ,EAAA,IAAA;gCAAKD,SAAU,EAAA,YAAA;0CAChCI,aAAc,CAAA;AACbc,oCAAAA,EAAAA,EAAIC,QAAQ,CAAC,UAAU,EAAEhB,IAAAA,CAAK,YAAY,CAAC,CAAA;oCAC3CiB,cAAgB,EAAA;AAClB,iCAAA;;;;;;;;AAOd;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AttributeOptions.js","sources":["../../../../admin/src/components/AttributeOptions/AttributeOptions.tsx"],"sourcesContent":["/**\n *\n * AttributeOptions\n *\n */\n\nimport { Divider, Flex, Modal, Tabs, Typography } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { getTrad } from '../../utils';\nimport { IconByType } from '../AttributeIcon';\n\nimport { AttributeList } from './AttributeList';\nimport { CustomFieldsList } from './CustomFieldsList';\n\ntype AttributeOptionsProps = {\n attributes: IconByType[][];\n forTarget: string;\n kind: string;\n};\n\nexport const AttributeOptions = ({ attributes, forTarget, kind }: AttributeOptionsProps) => {\n const { formatMessage } = useIntl();\n\n const defaultTabId = getTrad('modalForm.tabs.default');\n const customTabId = getTrad('modalForm.tabs.custom');\n\n const titleIdSuffix = forTarget.includes('component') ? 'component' : kind;\n const titleId = getTrad(`modalForm.sub-header.chooseAttribute.${titleIdSuffix}`);\n\n return (\n <Modal.Body>\n <Tabs.Root variant=\"simple\" defaultValue=\"default\">\n <Flex justifyContent=\"space-between\">\n <Typography variant=\"beta\" tag=\"h2\">\n {formatMessage({ id: titleId, defaultMessage: 'Select a field' })}\n </Typography>\n <Tabs.List>\n <Tabs.Trigger value=\"default\">\n {formatMessage({ id: defaultTabId, defaultMessage: 'Default' })}\n </Tabs.Trigger>\n <Tabs.Trigger value=\"custom\">\n {formatMessage({ id: customTabId, defaultMessage: 'Custom' })}\n </Tabs.Trigger>\n </Tabs.List>\n </Flex>\n <Divider marginBottom={6} />\n <Tabs.Content value=\"default\">\n <AttributeList attributes={attributes} />\n </Tabs.Content>\n <Tabs.Content value=\"custom\">\n <CustomFieldsList />\n </Tabs.Content>\n </Tabs.Root>\n </Modal.Body>\n );\n};\n"],"names":["AttributeOptions","attributes","forTarget","kind","formatMessage","useIntl","defaultTabId","getTrad","customTabId","titleIdSuffix","includes","titleId","_jsx","Modal","Body","_jsxs","Tabs","Root","variant","defaultValue","Flex","justifyContent","Typography","tag","id","defaultMessage","List","Trigger","value","Divider","marginBottom","Content","AttributeList","CustomFieldsList"],"mappings":";;;;;;;;;AAqBO,MAAMA,mBAAmB,CAAC,EAAEC,UAAU,EAAEC,SAAS,EAAEC,IAAI,EAAyB,GAAA;IACrF,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAE1B,IAAA,MAAMC,eAAeC,eAAQ,CAAA,wBAAA,CAAA;AAC7B,IAAA,MAAMC,cAAcD,eAAQ,CAAA,uBAAA,CAAA;AAE5B,IAAA,MAAME,aAAgBP,GAAAA,SAAAA,CAAUQ,QAAQ,CAAC,eAAe,WAAcP,GAAAA,IAAAA;AACtE,IAAA,MAAMQ,
|
|
1
|
+
{"version":3,"file":"AttributeOptions.js","sources":["../../../../admin/src/components/AttributeOptions/AttributeOptions.tsx"],"sourcesContent":["/**\n *\n * AttributeOptions\n *\n */\n\nimport { Divider, Flex, Modal, Tabs, Typography } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { getTrad } from '../../utils';\nimport { IconByType } from '../AttributeIcon';\n\nimport { AttributeList } from './AttributeList';\nimport { CustomFieldsList } from './CustomFieldsList';\n\ntype AttributeOptionsProps = {\n attributes: IconByType[][];\n forTarget: string;\n kind: string;\n};\n\nexport const AttributeOptions = ({ attributes, forTarget, kind }: AttributeOptionsProps) => {\n const { formatMessage } = useIntl();\n\n const defaultTabId = getTrad('modalForm.tabs.default');\n const customTabId = getTrad('modalForm.tabs.custom');\n\n const titleIdSuffix = forTarget.includes('component') ? 'component' : kind;\n const titleId = getTrad(`modalForm.sub-header.chooseAttribute.${titleIdSuffix}`);\n\n return (\n <Modal.Body>\n <Tabs.Root variant=\"simple\" defaultValue=\"default\">\n <Flex justifyContent=\"space-between\">\n <Typography variant=\"beta\" tag=\"h2\">\n {formatMessage({ id: titleId, defaultMessage: 'Select a field' })}\n </Typography>\n <Tabs.List>\n <Tabs.Trigger value=\"default\">\n {formatMessage({ id: defaultTabId, defaultMessage: 'Default' })}\n </Tabs.Trigger>\n <Tabs.Trigger value=\"custom\">\n {formatMessage({ id: customTabId, defaultMessage: 'Custom' })}\n </Tabs.Trigger>\n </Tabs.List>\n </Flex>\n <Divider marginBottom={6} />\n <Tabs.Content value=\"default\">\n <AttributeList attributes={attributes} />\n </Tabs.Content>\n <Tabs.Content value=\"custom\">\n <CustomFieldsList />\n </Tabs.Content>\n </Tabs.Root>\n </Modal.Body>\n );\n};\n"],"names":["AttributeOptions","attributes","forTarget","kind","formatMessage","useIntl","defaultTabId","getTrad","customTabId","titleIdSuffix","includes","titleId","_jsx","Modal","Body","_jsxs","Tabs","Root","variant","defaultValue","Flex","justifyContent","Typography","tag","id","defaultMessage","List","Trigger","value","Divider","marginBottom","Content","AttributeList","CustomFieldsList"],"mappings":";;;;;;;;;AAqBO,MAAMA,mBAAmB,CAAC,EAAEC,UAAU,EAAEC,SAAS,EAAEC,IAAI,EAAyB,GAAA;IACrF,MAAM,EAAEC,aAAa,EAAE,GAAGC,iBAAAA,EAAAA;AAE1B,IAAA,MAAMC,eAAeC,eAAQ,CAAA,wBAAA,CAAA;AAC7B,IAAA,MAAMC,cAAcD,eAAQ,CAAA,uBAAA,CAAA;AAE5B,IAAA,MAAME,aAAgBP,GAAAA,SAAAA,CAAUQ,QAAQ,CAAC,eAAe,WAAcP,GAAAA,IAAAA;AACtE,IAAA,MAAMQ,OAAUJ,GAAAA,eAAAA,CAAQ,CAAC,qCAAqC,EAAEE,aAAe,CAAA,CAAA,CAAA;IAE/E,qBACEG,cAAA,CAACC,mBAAMC,IAAI,EAAA;gCACTC,eAAA,CAACC,kBAAKC,IAAI,EAAA;YAACC,OAAQ,EAAA,QAAA;YAASC,YAAa,EAAA,SAAA;;8BACvCJ,eAACK,CAAAA,iBAAAA,EAAAA;oBAAKC,cAAe,EAAA,eAAA;;sCACnBT,cAACU,CAAAA,uBAAAA,EAAAA;4BAAWJ,OAAQ,EAAA,MAAA;4BAAOK,GAAI,EAAA,IAAA;sCAC5BnB,aAAc,CAAA;gCAAEoB,EAAIb,EAAAA,OAAAA;gCAASc,cAAgB,EAAA;AAAiB,6BAAA;;AAEjE,sCAAAV,eAAA,CAACC,kBAAKU,IAAI,EAAA;;AACR,8CAAAd,cAAA,CAACI,kBAAKW,OAAO,EAAA;oCAACC,KAAM,EAAA,SAAA;8CACjBxB,aAAc,CAAA;wCAAEoB,EAAIlB,EAAAA,YAAAA;wCAAcmB,cAAgB,EAAA;AAAU,qCAAA;;AAE/D,8CAAAb,cAAA,CAACI,kBAAKW,OAAO,EAAA;oCAACC,KAAM,EAAA,QAAA;8CACjBxB,aAAc,CAAA;wCAAEoB,EAAIhB,EAAAA,WAAAA;wCAAaiB,cAAgB,EAAA;AAAS,qCAAA;;;;;;8BAIjEb,cAACiB,CAAAA,oBAAAA,EAAAA;oBAAQC,YAAc,EAAA;;AACvB,8BAAAlB,cAAA,CAACI,kBAAKe,OAAO,EAAA;oBAACH,KAAM,EAAA,SAAA;AAClB,oBAAA,QAAA,gBAAAhB,cAACoB,CAAAA,2BAAAA,EAAAA;wBAAc/B,UAAYA,EAAAA;;;AAE7B,8BAAAW,cAAA,CAACI,kBAAKe,OAAO,EAAA;oBAACH,KAAM,EAAA,QAAA;AAClB,oBAAA,QAAA,gBAAAhB,cAACqB,CAAAA,iCAAAA,EAAAA,EAAAA;;;;;AAKX;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AttributeOptions.mjs","sources":["../../../../admin/src/components/AttributeOptions/AttributeOptions.tsx"],"sourcesContent":["/**\n *\n * AttributeOptions\n *\n */\n\nimport { Divider, Flex, Modal, Tabs, Typography } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { getTrad } from '../../utils';\nimport { IconByType } from '../AttributeIcon';\n\nimport { AttributeList } from './AttributeList';\nimport { CustomFieldsList } from './CustomFieldsList';\n\ntype AttributeOptionsProps = {\n attributes: IconByType[][];\n forTarget: string;\n kind: string;\n};\n\nexport const AttributeOptions = ({ attributes, forTarget, kind }: AttributeOptionsProps) => {\n const { formatMessage } = useIntl();\n\n const defaultTabId = getTrad('modalForm.tabs.default');\n const customTabId = getTrad('modalForm.tabs.custom');\n\n const titleIdSuffix = forTarget.includes('component') ? 'component' : kind;\n const titleId = getTrad(`modalForm.sub-header.chooseAttribute.${titleIdSuffix}`);\n\n return (\n <Modal.Body>\n <Tabs.Root variant=\"simple\" defaultValue=\"default\">\n <Flex justifyContent=\"space-between\">\n <Typography variant=\"beta\" tag=\"h2\">\n {formatMessage({ id: titleId, defaultMessage: 'Select a field' })}\n </Typography>\n <Tabs.List>\n <Tabs.Trigger value=\"default\">\n {formatMessage({ id: defaultTabId, defaultMessage: 'Default' })}\n </Tabs.Trigger>\n <Tabs.Trigger value=\"custom\">\n {formatMessage({ id: customTabId, defaultMessage: 'Custom' })}\n </Tabs.Trigger>\n </Tabs.List>\n </Flex>\n <Divider marginBottom={6} />\n <Tabs.Content value=\"default\">\n <AttributeList attributes={attributes} />\n </Tabs.Content>\n <Tabs.Content value=\"custom\">\n <CustomFieldsList />\n </Tabs.Content>\n </Tabs.Root>\n </Modal.Body>\n );\n};\n"],"names":["AttributeOptions","attributes","forTarget","kind","formatMessage","useIntl","defaultTabId","getTrad","customTabId","titleIdSuffix","includes","titleId","_jsx","Modal","Body","_jsxs","Tabs","Root","variant","defaultValue","Flex","justifyContent","Typography","tag","id","defaultMessage","List","Trigger","value","Divider","marginBottom","Content","AttributeList","CustomFieldsList"],"mappings":";;;;;;;AAqBO,MAAMA,mBAAmB,CAAC,EAAEC,UAAU,EAAEC,SAAS,EAAEC,IAAI,EAAyB,GAAA;IACrF,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAE1B,IAAA,MAAMC,eAAeC,OAAQ,CAAA,wBAAA,CAAA;AAC7B,IAAA,MAAMC,cAAcD,OAAQ,CAAA,uBAAA,CAAA;AAE5B,IAAA,MAAME,aAAgBP,GAAAA,SAAAA,CAAUQ,QAAQ,CAAC,eAAe,WAAcP,GAAAA,IAAAA;AACtE,IAAA,MAAMQ,
|
|
1
|
+
{"version":3,"file":"AttributeOptions.mjs","sources":["../../../../admin/src/components/AttributeOptions/AttributeOptions.tsx"],"sourcesContent":["/**\n *\n * AttributeOptions\n *\n */\n\nimport { Divider, Flex, Modal, Tabs, Typography } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { getTrad } from '../../utils';\nimport { IconByType } from '../AttributeIcon';\n\nimport { AttributeList } from './AttributeList';\nimport { CustomFieldsList } from './CustomFieldsList';\n\ntype AttributeOptionsProps = {\n attributes: IconByType[][];\n forTarget: string;\n kind: string;\n};\n\nexport const AttributeOptions = ({ attributes, forTarget, kind }: AttributeOptionsProps) => {\n const { formatMessage } = useIntl();\n\n const defaultTabId = getTrad('modalForm.tabs.default');\n const customTabId = getTrad('modalForm.tabs.custom');\n\n const titleIdSuffix = forTarget.includes('component') ? 'component' : kind;\n const titleId = getTrad(`modalForm.sub-header.chooseAttribute.${titleIdSuffix}`);\n\n return (\n <Modal.Body>\n <Tabs.Root variant=\"simple\" defaultValue=\"default\">\n <Flex justifyContent=\"space-between\">\n <Typography variant=\"beta\" tag=\"h2\">\n {formatMessage({ id: titleId, defaultMessage: 'Select a field' })}\n </Typography>\n <Tabs.List>\n <Tabs.Trigger value=\"default\">\n {formatMessage({ id: defaultTabId, defaultMessage: 'Default' })}\n </Tabs.Trigger>\n <Tabs.Trigger value=\"custom\">\n {formatMessage({ id: customTabId, defaultMessage: 'Custom' })}\n </Tabs.Trigger>\n </Tabs.List>\n </Flex>\n <Divider marginBottom={6} />\n <Tabs.Content value=\"default\">\n <AttributeList attributes={attributes} />\n </Tabs.Content>\n <Tabs.Content value=\"custom\">\n <CustomFieldsList />\n </Tabs.Content>\n </Tabs.Root>\n </Modal.Body>\n );\n};\n"],"names":["AttributeOptions","attributes","forTarget","kind","formatMessage","useIntl","defaultTabId","getTrad","customTabId","titleIdSuffix","includes","titleId","_jsx","Modal","Body","_jsxs","Tabs","Root","variant","defaultValue","Flex","justifyContent","Typography","tag","id","defaultMessage","List","Trigger","value","Divider","marginBottom","Content","AttributeList","CustomFieldsList"],"mappings":";;;;;;;AAqBO,MAAMA,mBAAmB,CAAC,EAAEC,UAAU,EAAEC,SAAS,EAAEC,IAAI,EAAyB,GAAA;IACrF,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAE1B,IAAA,MAAMC,eAAeC,OAAQ,CAAA,wBAAA,CAAA;AAC7B,IAAA,MAAMC,cAAcD,OAAQ,CAAA,uBAAA,CAAA;AAE5B,IAAA,MAAME,aAAgBP,GAAAA,SAAAA,CAAUQ,QAAQ,CAAC,eAAe,WAAcP,GAAAA,IAAAA;AACtE,IAAA,MAAMQ,OAAUJ,GAAAA,OAAAA,CAAQ,CAAC,qCAAqC,EAAEE,aAAe,CAAA,CAAA,CAAA;IAE/E,qBACEG,GAAA,CAACC,MAAMC,IAAI,EAAA;gCACTC,IAAA,CAACC,KAAKC,IAAI,EAAA;YAACC,OAAQ,EAAA,QAAA;YAASC,YAAa,EAAA,SAAA;;8BACvCJ,IAACK,CAAAA,IAAAA,EAAAA;oBAAKC,cAAe,EAAA,eAAA;;sCACnBT,GAACU,CAAAA,UAAAA,EAAAA;4BAAWJ,OAAQ,EAAA,MAAA;4BAAOK,GAAI,EAAA,IAAA;sCAC5BnB,aAAc,CAAA;gCAAEoB,EAAIb,EAAAA,OAAAA;gCAASc,cAAgB,EAAA;AAAiB,6BAAA;;AAEjE,sCAAAV,IAAA,CAACC,KAAKU,IAAI,EAAA;;AACR,8CAAAd,GAAA,CAACI,KAAKW,OAAO,EAAA;oCAACC,KAAM,EAAA,SAAA;8CACjBxB,aAAc,CAAA;wCAAEoB,EAAIlB,EAAAA,YAAAA;wCAAcmB,cAAgB,EAAA;AAAU,qCAAA;;AAE/D,8CAAAb,GAAA,CAACI,KAAKW,OAAO,EAAA;oCAACC,KAAM,EAAA,QAAA;8CACjBxB,aAAc,CAAA;wCAAEoB,EAAIhB,EAAAA,WAAAA;wCAAaiB,cAAgB,EAAA;AAAS,qCAAA;;;;;;8BAIjEb,GAACiB,CAAAA,OAAAA,EAAAA;oBAAQC,YAAc,EAAA;;AACvB,8BAAAlB,GAAA,CAACI,KAAKe,OAAO,EAAA;oBAACH,KAAM,EAAA,SAAA;AAClB,oBAAA,QAAA,gBAAAhB,GAACoB,CAAAA,aAAAA,EAAAA;wBAAc/B,UAAYA,EAAAA;;;AAE7B,8BAAAW,GAAA,CAACI,KAAKe,OAAO,EAAA;oBAACH,KAAM,EAAA,QAAA;AAClB,oBAAA,QAAA,gBAAAhB,GAACqB,CAAAA,gBAAAA,EAAAA,EAAAA;;;;;AAKX;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmptyAttributes.js","sources":["../../../../admin/src/components/AttributeOptions/EmptyAttributes.tsx"],"sourcesContent":["import { Box, Flex, Typography, LinkButton } from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { EmptyDocuments } from '@strapi/icons/symbols';\nimport * as qs from 'qs';\nimport { useIntl } from 'react-intl';\nimport { Link } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { getTrad } from '../../utils';\n\nconst EmptyCard = styled(Box)`\n background: ${({ theme }) =>\n `linear-gradient(180deg, rgba(234, 234, 239, 0) 0%, ${theme.colors.neutral150} 100%)`};\n opacity: 0.33;\n`;\n\nexport const EmptyCardGrid = () => {\n return (\n <Flex wrap=\"wrap\" gap={4}>\n {[...Array(4)].map((_, idx) => {\n return (\n <EmptyCard\n // eslint-disable-next-line react/no-array-index-key\n key={`empty-card-${idx}`}\n height=\"138px\"\n width=\"375px\"\n hasRadius\n />\n );\n })}\n </Flex>\n );\n};\n\nexport const EmptyAttributes = () => {\n const { formatMessage } = useIntl();\n\n return (\n <Box position=\"relative\">\n <EmptyCardGrid />\n <Box position=\"absolute\" top={6} width=\"100%\">\n <Flex alignItems=\"center\" justifyContent=\"center\" direction=\"column\">\n <EmptyDocuments width=\"160px\" height=\"88px\" />\n <Box paddingTop={6} paddingBottom={4}>\n <Box textAlign=\"center\">\n <Typography variant=\"delta\" tag=\"p\" textColor=\"neutral600\">\n {formatMessage({\n id: getTrad('modalForm.empty.heading'),\n defaultMessage: 'Nothing in here yet.',\n })}\n </Typography>\n <Box paddingTop={4}>\n <Typography variant=\"delta\" tag=\"p\" textColor=\"neutral600\">\n {formatMessage({\n id: getTrad('modalForm.empty.sub-heading'),\n defaultMessage:\n 'Find what you are looking for through a wide range of extensions.',\n })}\n </Typography>\n </Box>\n </Box>\n </Box>\n <LinkButton\n tag={Link}\n to={`/marketplace?${qs.stringify({ categories: ['Custom fields'] })}`}\n variant=\"secondary\"\n startIcon={<Plus />}\n >\n {formatMessage({\n id: getTrad('modalForm.empty.button'),\n defaultMessage: 'Add custom fields',\n })}\n </LinkButton>\n </Flex>\n </Box>\n </Box>\n );\n};\n"],"names":["EmptyCard","styled","Box","theme","colors","neutral150","EmptyCardGrid","_jsx","Flex","wrap","gap","Array","map","_","idx","height","width","hasRadius","EmptyAttributes","formatMessage","useIntl","_jsxs","position","top","alignItems","justifyContent","direction","EmptyDocuments","paddingTop","paddingBottom","textAlign","Typography","variant","tag","textColor","id","getTrad","defaultMessage","LinkButton","Link","to","qs","stringify","categories","startIcon","Plus"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,MAAMA,SAAAA,GAAYC,uBAAOC,CAAAA,gBAAAA,CAAI;AACf,cAAA,EAAE,CAAC,EAAEC,KAAK,EAAE,GACtB,CAAC,mDAAmD,EAAEA,KAAAA,CAAMC,MAAM,CAACC,UAAU,CAAC,MAAM,CAAC,CAAC;;AAE1F,CAAC;MAEYC,aAAgB,GAAA,IAAA;AAC3B,IAAA,qBACEC,cAACC,CAAAA,iBAAAA,EAAAA;QAAKC,IAAK,EAAA,MAAA;QAAOC,GAAK,EAAA,CAAA;AACpB,QAAA,QAAA,EAAA;eAAIC,KAAM,CAAA,CAAA;SAAG,CAACC,GAAG,CAAC,CAACC,CAAGC,EAAAA,GAAAA,GAAAA;AACrB,YAAA,qBACEP,cAACP,CAAAA,SAAAA,EAAAA;gBAGCe,MAAO,EAAA,OAAA;gBACPC,KAAM,EAAA,OAAA;gBACNC,SAAS,EAAA;eAHJ,CAAC,WAAW,EAAEH,
|
|
1
|
+
{"version":3,"file":"EmptyAttributes.js","sources":["../../../../admin/src/components/AttributeOptions/EmptyAttributes.tsx"],"sourcesContent":["import { Box, Flex, Typography, LinkButton } from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { EmptyDocuments } from '@strapi/icons/symbols';\nimport * as qs from 'qs';\nimport { useIntl } from 'react-intl';\nimport { Link } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { getTrad } from '../../utils';\n\nconst EmptyCard = styled(Box)`\n background: ${({ theme }) =>\n `linear-gradient(180deg, rgba(234, 234, 239, 0) 0%, ${theme.colors.neutral150} 100%)`};\n opacity: 0.33;\n`;\n\nexport const EmptyCardGrid = () => {\n return (\n <Flex wrap=\"wrap\" gap={4}>\n {[...Array(4)].map((_, idx) => {\n return (\n <EmptyCard\n // eslint-disable-next-line react/no-array-index-key\n key={`empty-card-${idx}`}\n height=\"138px\"\n width=\"375px\"\n hasRadius\n />\n );\n })}\n </Flex>\n );\n};\n\nexport const EmptyAttributes = () => {\n const { formatMessage } = useIntl();\n\n return (\n <Box position=\"relative\">\n <EmptyCardGrid />\n <Box position=\"absolute\" top={6} width=\"100%\">\n <Flex alignItems=\"center\" justifyContent=\"center\" direction=\"column\">\n <EmptyDocuments width=\"160px\" height=\"88px\" />\n <Box paddingTop={6} paddingBottom={4}>\n <Box textAlign=\"center\">\n <Typography variant=\"delta\" tag=\"p\" textColor=\"neutral600\">\n {formatMessage({\n id: getTrad('modalForm.empty.heading'),\n defaultMessage: 'Nothing in here yet.',\n })}\n </Typography>\n <Box paddingTop={4}>\n <Typography variant=\"delta\" tag=\"p\" textColor=\"neutral600\">\n {formatMessage({\n id: getTrad('modalForm.empty.sub-heading'),\n defaultMessage:\n 'Find what you are looking for through a wide range of extensions.',\n })}\n </Typography>\n </Box>\n </Box>\n </Box>\n <LinkButton\n tag={Link}\n to={`/marketplace?${qs.stringify({ categories: ['Custom fields'] })}`}\n variant=\"secondary\"\n startIcon={<Plus />}\n >\n {formatMessage({\n id: getTrad('modalForm.empty.button'),\n defaultMessage: 'Add custom fields',\n })}\n </LinkButton>\n </Flex>\n </Box>\n </Box>\n );\n};\n"],"names":["EmptyCard","styled","Box","theme","colors","neutral150","EmptyCardGrid","_jsx","Flex","wrap","gap","Array","map","_","idx","height","width","hasRadius","EmptyAttributes","formatMessage","useIntl","_jsxs","position","top","alignItems","justifyContent","direction","EmptyDocuments","paddingTop","paddingBottom","textAlign","Typography","variant","tag","textColor","id","getTrad","defaultMessage","LinkButton","Link","to","qs","stringify","categories","startIcon","Plus"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmptyAttributes.mjs","sources":["../../../../admin/src/components/AttributeOptions/EmptyAttributes.tsx"],"sourcesContent":["import { Box, Flex, Typography, LinkButton } from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { EmptyDocuments } from '@strapi/icons/symbols';\nimport * as qs from 'qs';\nimport { useIntl } from 'react-intl';\nimport { Link } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { getTrad } from '../../utils';\n\nconst EmptyCard = styled(Box)`\n background: ${({ theme }) =>\n `linear-gradient(180deg, rgba(234, 234, 239, 0) 0%, ${theme.colors.neutral150} 100%)`};\n opacity: 0.33;\n`;\n\nexport const EmptyCardGrid = () => {\n return (\n <Flex wrap=\"wrap\" gap={4}>\n {[...Array(4)].map((_, idx) => {\n return (\n <EmptyCard\n // eslint-disable-next-line react/no-array-index-key\n key={`empty-card-${idx}`}\n height=\"138px\"\n width=\"375px\"\n hasRadius\n />\n );\n })}\n </Flex>\n );\n};\n\nexport const EmptyAttributes = () => {\n const { formatMessage } = useIntl();\n\n return (\n <Box position=\"relative\">\n <EmptyCardGrid />\n <Box position=\"absolute\" top={6} width=\"100%\">\n <Flex alignItems=\"center\" justifyContent=\"center\" direction=\"column\">\n <EmptyDocuments width=\"160px\" height=\"88px\" />\n <Box paddingTop={6} paddingBottom={4}>\n <Box textAlign=\"center\">\n <Typography variant=\"delta\" tag=\"p\" textColor=\"neutral600\">\n {formatMessage({\n id: getTrad('modalForm.empty.heading'),\n defaultMessage: 'Nothing in here yet.',\n })}\n </Typography>\n <Box paddingTop={4}>\n <Typography variant=\"delta\" tag=\"p\" textColor=\"neutral600\">\n {formatMessage({\n id: getTrad('modalForm.empty.sub-heading'),\n defaultMessage:\n 'Find what you are looking for through a wide range of extensions.',\n })}\n </Typography>\n </Box>\n </Box>\n </Box>\n <LinkButton\n tag={Link}\n to={`/marketplace?${qs.stringify({ categories: ['Custom fields'] })}`}\n variant=\"secondary\"\n startIcon={<Plus />}\n >\n {formatMessage({\n id: getTrad('modalForm.empty.button'),\n defaultMessage: 'Add custom fields',\n })}\n </LinkButton>\n </Flex>\n </Box>\n </Box>\n );\n};\n"],"names":["EmptyCard","styled","Box","theme","colors","neutral150","EmptyCardGrid","_jsx","Flex","wrap","gap","Array","map","_","idx","height","width","hasRadius","EmptyAttributes","formatMessage","useIntl","_jsxs","position","top","alignItems","justifyContent","direction","EmptyDocuments","paddingTop","paddingBottom","textAlign","Typography","variant","tag","textColor","id","getTrad","defaultMessage","LinkButton","Link","to","qs","stringify","categories","startIcon","Plus"],"mappings":";;;;;;;;;;AAUA,MAAMA,SAAAA,GAAYC,MAAOC,CAAAA,GAAAA,CAAI;AACf,cAAA,EAAE,CAAC,EAAEC,KAAK,EAAE,GACtB,CAAC,mDAAmD,EAAEA,KAAAA,CAAMC,MAAM,CAACC,UAAU,CAAC,MAAM,CAAC,CAAC;;AAE1F,CAAC;MAEYC,aAAgB,GAAA,IAAA;AAC3B,IAAA,qBACEC,GAACC,CAAAA,IAAAA,EAAAA;QAAKC,IAAK,EAAA,MAAA;QAAOC,GAAK,EAAA,CAAA;AACpB,QAAA,QAAA,EAAA;eAAIC,KAAM,CAAA,CAAA;SAAG,CAACC,GAAG,CAAC,CAACC,CAAGC,EAAAA,GAAAA,GAAAA;AACrB,YAAA,qBACEP,GAACP,CAAAA,SAAAA,EAAAA;gBAGCe,MAAO,EAAA,OAAA;gBACPC,KAAM,EAAA,OAAA;gBACNC,SAAS,EAAA;eAHJ,CAAC,WAAW,EAAEH,
|
|
1
|
+
{"version":3,"file":"EmptyAttributes.mjs","sources":["../../../../admin/src/components/AttributeOptions/EmptyAttributes.tsx"],"sourcesContent":["import { Box, Flex, Typography, LinkButton } from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { EmptyDocuments } from '@strapi/icons/symbols';\nimport * as qs from 'qs';\nimport { useIntl } from 'react-intl';\nimport { Link } from 'react-router-dom';\nimport { styled } from 'styled-components';\n\nimport { getTrad } from '../../utils';\n\nconst EmptyCard = styled(Box)`\n background: ${({ theme }) =>\n `linear-gradient(180deg, rgba(234, 234, 239, 0) 0%, ${theme.colors.neutral150} 100%)`};\n opacity: 0.33;\n`;\n\nexport const EmptyCardGrid = () => {\n return (\n <Flex wrap=\"wrap\" gap={4}>\n {[...Array(4)].map((_, idx) => {\n return (\n <EmptyCard\n // eslint-disable-next-line react/no-array-index-key\n key={`empty-card-${idx}`}\n height=\"138px\"\n width=\"375px\"\n hasRadius\n />\n );\n })}\n </Flex>\n );\n};\n\nexport const EmptyAttributes = () => {\n const { formatMessage } = useIntl();\n\n return (\n <Box position=\"relative\">\n <EmptyCardGrid />\n <Box position=\"absolute\" top={6} width=\"100%\">\n <Flex alignItems=\"center\" justifyContent=\"center\" direction=\"column\">\n <EmptyDocuments width=\"160px\" height=\"88px\" />\n <Box paddingTop={6} paddingBottom={4}>\n <Box textAlign=\"center\">\n <Typography variant=\"delta\" tag=\"p\" textColor=\"neutral600\">\n {formatMessage({\n id: getTrad('modalForm.empty.heading'),\n defaultMessage: 'Nothing in here yet.',\n })}\n </Typography>\n <Box paddingTop={4}>\n <Typography variant=\"delta\" tag=\"p\" textColor=\"neutral600\">\n {formatMessage({\n id: getTrad('modalForm.empty.sub-heading'),\n defaultMessage:\n 'Find what you are looking for through a wide range of extensions.',\n })}\n </Typography>\n </Box>\n </Box>\n </Box>\n <LinkButton\n tag={Link}\n to={`/marketplace?${qs.stringify({ categories: ['Custom fields'] })}`}\n variant=\"secondary\"\n startIcon={<Plus />}\n >\n {formatMessage({\n id: getTrad('modalForm.empty.button'),\n defaultMessage: 'Add custom fields',\n })}\n </LinkButton>\n </Flex>\n </Box>\n </Box>\n );\n};\n"],"names":["EmptyCard","styled","Box","theme","colors","neutral150","EmptyCardGrid","_jsx","Flex","wrap","gap","Array","map","_","idx","height","width","hasRadius","EmptyAttributes","formatMessage","useIntl","_jsxs","position","top","alignItems","justifyContent","direction","EmptyDocuments","paddingTop","paddingBottom","textAlign","Typography","variant","tag","textColor","id","getTrad","defaultMessage","LinkButton","Link","to","qs","stringify","categories","startIcon","Plus"],"mappings":";;;;;;;;;;AAUA,MAAMA,SAAAA,GAAYC,MAAOC,CAAAA,GAAAA,CAAI;AACf,cAAA,EAAE,CAAC,EAAEC,KAAK,EAAE,GACtB,CAAC,mDAAmD,EAAEA,KAAAA,CAAMC,MAAM,CAACC,UAAU,CAAC,MAAM,CAAC,CAAC;;AAE1F,CAAC;MAEYC,aAAgB,GAAA,IAAA;AAC3B,IAAA,qBACEC,GAACC,CAAAA,IAAAA,EAAAA;QAAKC,IAAK,EAAA,MAAA;QAAOC,GAAK,EAAA,CAAA;AACpB,QAAA,QAAA,EAAA;eAAIC,KAAM,CAAA,CAAA;SAAG,CAACC,GAAG,CAAC,CAACC,CAAGC,EAAAA,GAAAA,GAAAA;AACrB,YAAA,qBACEP,GAACP,CAAAA,SAAAA,EAAAA;gBAGCe,MAAO,EAAA,OAAA;gBACPC,KAAM,EAAA,OAAA;gBACNC,SAAS,EAAA;eAHJ,CAAC,WAAW,EAAEH,GAAK,CAAA,CAAA,CAAA;AAM9B,SAAA;;AAGN;MAEaI,eAAkB,GAAA,IAAA;IAC7B,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAE1B,IAAA,qBACEC,IAACnB,CAAAA,GAAAA,EAAAA;QAAIoB,QAAS,EAAA,UAAA;;0BACZf,GAACD,CAAAA,aAAAA,EAAAA,EAAAA,CAAAA;0BACDC,GAACL,CAAAA,GAAAA,EAAAA;gBAAIoB,QAAS,EAAA,UAAA;gBAAWC,GAAK,EAAA,CAAA;gBAAGP,KAAM,EAAA,MAAA;AACrC,gBAAA,QAAA,gBAAAK,IAACb,CAAAA,IAAAA,EAAAA;oBAAKgB,UAAW,EAAA,QAAA;oBAASC,cAAe,EAAA,QAAA;oBAASC,SAAU,EAAA,QAAA;;sCAC1DnB,GAACoB,CAAAA,cAAAA,EAAAA;4BAAeX,KAAM,EAAA,OAAA;4BAAQD,MAAO,EAAA;;sCACrCR,GAACL,CAAAA,GAAAA,EAAAA;4BAAI0B,UAAY,EAAA,CAAA;4BAAGC,aAAe,EAAA,CAAA;AACjC,4BAAA,QAAA,gBAAAR,IAACnB,CAAAA,GAAAA,EAAAA;gCAAI4B,SAAU,EAAA,QAAA;;kDACbvB,GAACwB,CAAAA,UAAAA,EAAAA;wCAAWC,OAAQ,EAAA,OAAA;wCAAQC,GAAI,EAAA,GAAA;wCAAIC,SAAU,EAAA,YAAA;kDAC3Cf,aAAc,CAAA;AACbgB,4CAAAA,EAAAA,EAAIC,OAAQ,CAAA,yBAAA,CAAA;4CACZC,cAAgB,EAAA;AAClB,yCAAA;;kDAEF9B,GAACL,CAAAA,GAAAA,EAAAA;wCAAI0B,UAAY,EAAA,CAAA;AACf,wCAAA,QAAA,gBAAArB,GAACwB,CAAAA,UAAAA,EAAAA;4CAAWC,OAAQ,EAAA,OAAA;4CAAQC,GAAI,EAAA,GAAA;4CAAIC,SAAU,EAAA,YAAA;sDAC3Cf,aAAc,CAAA;AACbgB,gDAAAA,EAAAA,EAAIC,OAAQ,CAAA,6BAAA,CAAA;gDACZC,cACE,EAAA;AACJ,6CAAA;;;;;;sCAKR9B,GAAC+B,CAAAA,UAAAA,EAAAA;4BACCL,GAAKM,EAAAA,IAAAA;AACLC,4BAAAA,EAAAA,EAAI,CAAC,aAAa,EAAEC,EAAAA,CAAGC,SAAS,CAAC;gCAAEC,UAAY,EAAA;AAAC,oCAAA;AAAgB;6BAAK,CAAA,CAAA,CAAA;4BACrEX,OAAQ,EAAA,WAAA;AACRY,4BAAAA,SAAAA,gBAAWrC,GAACsC,CAAAA,IAAAA,EAAAA,EAAAA,CAAAA;sCAEX1B,aAAc,CAAA;AACbgB,gCAAAA,EAAAA,EAAIC,OAAQ,CAAA,wBAAA,CAAA;gCACZC,cAAgB,EAAA;AAClB,6BAAA;;;;;;;AAMZ;;;;"}
|