@flipdish/portal-library 8.6.4 → 8.6.6

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.
Files changed (67) hide show
  1. package/dist/components/atoms/Badge/index.cjs.js +1 -1
  2. package/dist/components/atoms/Badge/index.cjs.js.map +1 -1
  3. package/dist/components/atoms/Badge/index.d.ts +1 -1
  4. package/dist/components/atoms/Badge/index.js +1 -1
  5. package/dist/components/atoms/Badge/index.js.map +1 -1
  6. package/dist/components/atoms/IconContainer/index.cjs.js +1 -1
  7. package/dist/components/atoms/IconContainer/index.cjs.js.map +1 -1
  8. package/dist/components/atoms/IconContainer/index.d.ts +1 -1
  9. package/dist/components/atoms/IconContainer/index.js +1 -1
  10. package/dist/components/atoms/IconContainer/index.js.map +1 -1
  11. package/dist/components/organisms/AssetManager/hooks/useAssetUploadManager.cjs.js +1 -1
  12. package/dist/components/organisms/AssetManager/hooks/useAssetUploadManager.cjs.js.map +1 -1
  13. package/dist/components/organisms/AssetManager/hooks/useAssetUploadManager.d.ts +2 -1
  14. package/dist/components/organisms/AssetManager/hooks/useAssetUploadManager.js +1 -1
  15. package/dist/components/organisms/AssetManager/hooks/useAssetUploadManager.js.map +1 -1
  16. package/dist/components/organisms/AssetManager/hooks/usePresignedUploadAsset.cjs.js +2 -0
  17. package/dist/components/organisms/AssetManager/hooks/usePresignedUploadAsset.cjs.js.map +1 -0
  18. package/dist/components/organisms/AssetManager/hooks/usePresignedUploadAsset.d.ts +12 -0
  19. package/dist/components/organisms/AssetManager/hooks/usePresignedUploadAsset.js +2 -0
  20. package/dist/components/organisms/AssetManager/hooks/usePresignedUploadAsset.js.map +1 -0
  21. package/dist/components/organisms/AssetManager/index.cjs.js +1 -1
  22. package/dist/components/organisms/AssetManager/index.cjs.js.map +1 -1
  23. package/dist/components/organisms/AssetManager/index.d.ts +2 -0
  24. package/dist/components/organisms/AssetManager/index.js +1 -1
  25. package/dist/components/organisms/AssetManager/index.js.map +1 -1
  26. package/dist/components/organisms/AssetManager/services/asset.service.cjs.js +1 -1
  27. package/dist/components/organisms/AssetManager/services/asset.service.cjs.js.map +1 -1
  28. package/dist/components/organisms/AssetManager/services/asset.service.d.ts +45 -2
  29. package/dist/components/organisms/AssetManager/services/asset.service.js +1 -1
  30. package/dist/components/organisms/AssetManager/services/asset.service.js.map +1 -1
  31. package/dist/mocks/msw/handlers.cjs.js +1 -1
  32. package/dist/mocks/msw/handlers.cjs.js.map +1 -1
  33. package/dist/mocks/msw/handlers.d.ts +6 -1
  34. package/dist/mocks/msw/handlers.js +1 -1
  35. package/dist/mocks/msw/handlers.js.map +1 -1
  36. package/dist/themes/theme.d.ts +6 -12
  37. package/dist/themes/tokens/breakpoints/BreakpointsVisualizer.cjs.js +2 -0
  38. package/dist/themes/tokens/breakpoints/BreakpointsVisualizer.cjs.js.map +1 -0
  39. package/dist/themes/tokens/breakpoints/BreakpointsVisualizer.d.ts +5 -0
  40. package/dist/themes/tokens/breakpoints/BreakpointsVisualizer.js +2 -0
  41. package/dist/themes/tokens/breakpoints/BreakpointsVisualizer.js.map +1 -0
  42. package/dist/themes/tokens/colours/colours-stories-utils.cjs.js +1 -1
  43. package/dist/themes/tokens/colours/colours-stories-utils.cjs.js.map +1 -1
  44. package/dist/themes/tokens/colours/colours-stories-utils.d.ts +19 -1
  45. package/dist/themes/tokens/colours/colours-stories-utils.js +1 -1
  46. package/dist/themes/tokens/colours/colours-stories-utils.js.map +1 -1
  47. package/dist/themes/tokens/colours/semantic.cjs.js +1 -1
  48. package/dist/themes/tokens/colours/semantic.cjs.js.map +1 -1
  49. package/dist/themes/tokens/colours/semantic.d.ts +6 -12
  50. package/dist/themes/tokens/colours/semantic.js +1 -1
  51. package/dist/themes/tokens/colours/semantic.js.map +1 -1
  52. package/dist/themes/tokens/radius/RadiusVisualizer.cjs.js +2 -0
  53. package/dist/themes/tokens/radius/RadiusVisualizer.cjs.js.map +1 -0
  54. package/dist/themes/tokens/radius/RadiusVisualizer.d.ts +5 -0
  55. package/dist/themes/tokens/radius/RadiusVisualizer.js +2 -0
  56. package/dist/themes/tokens/radius/RadiusVisualizer.js.map +1 -0
  57. package/dist/themes/tokens/shadows/ShadowsVisualizer.cjs.js +2 -0
  58. package/dist/themes/tokens/shadows/ShadowsVisualizer.cjs.js.map +1 -0
  59. package/dist/themes/tokens/shadows/ShadowsVisualizer.d.ts +5 -0
  60. package/dist/themes/tokens/shadows/ShadowsVisualizer.js +2 -0
  61. package/dist/themes/tokens/shadows/ShadowsVisualizer.js.map +1 -0
  62. package/dist/themes/tokens/spacing/SpacingVisualizer.cjs.js +2 -0
  63. package/dist/themes/tokens/spacing/SpacingVisualizer.cjs.js.map +1 -0
  64. package/dist/themes/tokens/spacing/SpacingVisualizer.d.ts +6 -0
  65. package/dist/themes/tokens/spacing/SpacingVisualizer.js +2 -0
  66. package/dist/themes/tokens/spacing/SpacingVisualizer.js.map +1 -0
  67. package/package.json +12 -12
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/components/organisms/AssetManager/index.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { styled } from '@mui/material/styles';\n\nimport Box from '@fd/components/atoms/Box';\nimport Tab from '@fd/components/atoms/Tab';\nimport Modal, { type ModalAction } from '@fd/components/molecules/Modal';\nimport Tabs from '@fd/components/molecules/Tabs';\nimport { useTranslation } from '@fd/providers/TranslationProvider';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\n\nimport { useAssetSelection } from './hooks/useAssetSelection';\nimport { useAssetUploadManager } from './hooks/useAssetUploadManager';\nimport { useGetAssets } from './hooks/useGetAssets';\nimport LibraryTabContent from './LibraryTabContent';\nimport type { Asset } from './types/assets.type';\nimport UploadAssetContent from './UploadTabContent';\n/**\n * Scrollable container for the tab content.\n * Allows the asset list to scroll while keeping the modal title, tabs, and actions visible.\n * Uses fixed height to prevent modal resizing when switching tabs.\n */\nconst StyledScrollableContent = styled(Box)(({ theme }) => ({\n height: 'calc(70vh - 200px)', // Fixed height for consistent modal size across tabs\n overflowY: 'auto',\n marginTop: theme.spacing(2),\n marginRight: theme.spacing(-2), // Extend to edge for scrollbar\n marginLeft: theme.spacing(-1), // Allow space for shadows on left\n marginBottom: theme.spacing(-1), // Allow space for shadows on bottom\n paddingRight: theme.spacing(2), // Compensate for negative margin\n paddingLeft: theme.spacing(1), // Compensate for negative margin\n paddingBottom: theme.spacing(1), // Compensate for negative margin\n}));\n\n/**\n * Props for the AssetManager component.\n * Provides a modal interface for selecting images from a grid display.\n * It supports both single and multiple image selection modes with configurable limits.\n *\n * import AssetManager from '@flipdish/portal-library/components/organisms/AssetManager';\n *\n * ```tsx\n * import AssetManager from '@flipdish/portal-library/components/organisms/AssetManager';\n */\nexport interface AssetManagerProps {\n /** Whether the asset manager modal is open */\n open: boolean;\n /** Callback function when the modal is closed or cancelled */\n onClose: () => void;\n /** Callback function when assets are selected */\n onSelect?: (selectedAssets: Asset[]) => void;\n /**\n * Organization ID for fetching assets\n */\n orgId: string;\n /** Brand ID for fetching assets */\n brandId?: string;\n /** Maximum number of assets that can be selected. Defaults to 1 */\n maxSelect?: number;\n}\n\n// Create a QueryClient instance for the AssetManager component\n// This allows the component to be used without requiring clients to wrap it in QueryClientProvider\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n refetchOnWindowFocus: false,\n retry: 2,\n },\n },\n});\n\n/**\n * Inner component that contains the AssetManager logic.\n * Must be rendered inside QueryClientProvider to use React Query hooks.\n */\nconst AssetManagerContent: React.FC<AssetManagerProps> = ({\n open,\n onClose,\n onSelect,\n orgId,\n brandId,\n maxSelect = 1,\n}) => {\n const [selectedTab, setSelectedTab] = useState<string>('library');\n const { translate } = useTranslation();\n\n // Fetch assets at the parent level to enable future reuse across tabs\n const {\n data: assetResponse,\n isLoading: isLoadingAssets,\n error: assetsError,\n } = useGetAssets(orgId, open, brandId);\n\n // Asset selection hook - manages selected assets from library\n const { selectedAssetsMap, handleAssetClick, clearSelection, addAssetsToSelection } = useAssetSelection({\n maxSelect,\n });\n\n // Asset upload hook - manages file uploads and upload state\n const {\n uploadedFiles,\n uploadError,\n isUploading,\n handleUpload,\n handleRemove,\n handleSave,\n clearUploadedFiles,\n clearSaveUploadError,\n } = useAssetUploadManager({\n orgId,\n brandId,\n onUploadSuccess: (uploadedAssets) => {\n // Add uploaded assets to selection and switch to library tab\n addAssetsToSelection(uploadedAssets);\n setSelectedTab('library');\n },\n getErrorMessage: () => translate('Failed_to_upload_assets_try_again'),\n });\n\n // Reset state when modal opens/closes\n useEffect(() => {\n if (!open) {\n clearSelection();\n clearUploadedFiles();\n clearSaveUploadError();\n }\n }, [open, clearSelection, clearUploadedFiles, clearSaveUploadError]);\n\n const handleCancel = useCallback((): void => {\n clearSelection();\n onClose();\n }, [onClose, clearSelection]);\n\n const handleSelectAssets = useCallback((): void => {\n if (selectedAssetsMap.size === 0) {\n onClose();\n return;\n }\n const selectedAssets = Array.from(selectedAssetsMap.values());\n if (onSelect && selectedAssets.length > 0) {\n onSelect(selectedAssets);\n }\n clearSelection();\n onClose();\n }, [onSelect, selectedAssetsMap, onClose, clearSelection]);\n\n const getTitle = (): string => {\n switch (selectedTab) {\n case 'library':\n return translate('Select_Images');\n default:\n return translate('Upload_Images');\n }\n };\n\n // Tab-specific action button configurations\n const actionButtons = useMemo<ModalAction[]>(() => {\n // Common cancel button configuration\n const cancelButton: ModalAction = {\n label: translate('Cancel'),\n onClick: handleCancel,\n variant: 'secondary',\n tone: 'neutral',\n id: 'asset-manager-cancel',\n };\n\n const tabActions: Record<string, ModalAction[]> = {\n library: [\n cancelButton,\n {\n label: translate('Select'),\n onClick: handleSelectAssets,\n variant: 'primary',\n id: 'asset-manager-select',\n },\n ],\n upload: [\n cancelButton,\n {\n label: translate('Save'),\n onClick: handleSave,\n loading: isUploading,\n variant: 'primary',\n id: 'asset-manager-upload',\n },\n ],\n };\n\n return tabActions[selectedTab] ?? (tabActions['library'] as ModalAction[]);\n }, [selectedTab, isUploading, handleCancel, handleSelectAssets, handleSave, translate]);\n\n return (\n <Modal actions={actionButtons} onClose={handleCancel} open={open} size=\"large\" title={getTitle()}>\n <Tabs\n fdKey=\"asset-manager-tabs\"\n onChange={(_, value: string) => {\n setSelectedTab(value);\n clearUploadedFiles();\n }}\n value={selectedTab}\n >\n <Tab label={translate('Upload')} value=\"upload\" />\n <Tab label={translate('Library')} value=\"library\" />\n </Tabs>\n <StyledScrollableContent>\n {selectedTab === 'library' ? (\n <LibraryTabContent\n assets={assetResponse?.data}\n error={assetsError}\n isLoading={isLoadingAssets}\n onAssetClick={handleAssetClick}\n selectedAssets={selectedAssetsMap}\n />\n ) : (\n <UploadAssetContent\n error={uploadError}\n files={uploadedFiles}\n onRemove={handleRemove}\n onUpload={handleUpload}\n />\n )}\n </StyledScrollableContent>\n </Modal>\n );\n};\n\n/**\n * AssetManager component used to select assets from the library or upload new assets.\n * Can manage assets at a organization or brand level.\n *\n * @example\n * ```tsx\n * <AssetManager\n * open={isOpen}\n * onClose={() => setIsOpen(false)}\n * onSelect={(assets) => console.log(assets)}\n * orgId=\"org123\"\n * brandId=\"brand456\"\n * maxSelect={3}\n * />\n * ```\n */\nconst AssetManager: React.FC<AssetManagerProps> = (props) => {\n return (\n <QueryClientProvider client={queryClient}>\n <AssetManagerContent {...props} />\n </QueryClientProvider>\n );\n};\n\nexport type { Asset, AssetMetadata, AssetMetadataDimensions, AssetType } from './types/assets.type';\nexport default AssetManager;\n"],"names":["StyledScrollableContent","styled","Box","theme","height","overflowY","marginTop","spacing","marginRight","marginLeft","marginBottom","paddingRight","paddingLeft","paddingBottom","queryClient","QueryClient","defaultOptions","queries","refetchOnWindowFocus","retry","AssetManagerContent","open","onClose","onSelect","orgId","brandId","maxSelect","selectedTab","setSelectedTab","useState","translate","useTranslation","data","assetResponse","isLoading","isLoadingAssets","error","assetsError","useGetAssets","selectedAssetsMap","handleAssetClick","clearSelection","addAssetsToSelection","useAssetSelection","uploadedFiles","uploadError","isUploading","handleUpload","handleRemove","handleSave","clearUploadedFiles","clearSaveUploadError","useAssetUploadManager","onUploadSuccess","uploadedAssets","getErrorMessage","useEffect","handleCancel","useCallback","handleSelectAssets","size","selectedAssets","Array","from","values","length","actionButtons","useMemo","cancelButton","label","onClick","variant","tone","id","tabActions","library","upload","loading","_jsxs","Modal","actions","title","Tabs","fdKey","onChange","_","value","_jsx","Tab","children","LibraryTabContent","assets","onAssetClick","UploadAssetContent","files","onRemove","onUpload","AssetManager","props","QueryClientProvider","client"],"mappings":"kwBAsBA,MAAMA,EAA0BC,EAAOC,EAAPD,CAAY,EAAGE,YAAO,CACpDC,OAAQ,qBACRC,UAAW,OACXC,UAAWH,EAAMI,QAAQ,GACzBC,YAAaL,EAAMI,YACnBE,WAAYN,EAAMI,YAClBG,aAAcP,EAAMI,YACpBI,aAAcR,EAAMI,QAAQ,GAC5BK,YAAaT,EAAMI,QAAQ,GAC3BM,cAAeV,EAAMI,QAAQ,MAgCzBO,EAAc,IAAIC,EAAY,CAClCC,eAAgB,CACdC,QAAS,CACPC,sBAAsB,EACtBC,MAAO,MASPC,EAAmD,EACvDC,OACAC,UACAC,WACAC,QACAC,UACAC,YAAY,MAEZ,MAAOC,EAAaC,GAAkBC,EAAiB,YACjDC,UAAEA,GAAcC,KAIpBC,KAAMC,EACNC,UAAWC,EACXC,MAAOC,GACLC,EAAad,EAAOH,EAAMI,IAGxBc,kBAAEA,EAAiBC,iBAAEA,EAAgBC,eAAEA,EAAcC,qBAAEA,GAAyBC,EAAkB,CACtGjB,eAIIkB,cACJA,EAAaC,YACbA,EAAWC,YACXA,EAAWC,aACXA,EAAYC,aACZA,EAAYC,WACZA,EAAUC,mBACVA,EAAkBC,qBAClBA,GACEC,EAAsB,CACxB5B,QACAC,UACA4B,gBAAkBC,IAEhBZ,EAAqBY,GACrB1B,EAAe,YAEjB2B,gBAAiB,IAAMzB,EAAU,uCAInC0B,EAAU,KACHnC,IACHoB,IACAS,IACAC,MAED,CAAC9B,EAAMoB,EAAgBS,EAAoBC,IAE9C,MAAMM,EAAeC,EAAY,KAC/BjB,IACAnB,KACC,CAACA,EAASmB,IAEPkB,EAAqBD,EAAY,KACrC,GAA+B,IAA3BnB,EAAkBqB,KAEpB,YADAtC,IAGF,MAAMuC,EAAiBC,MAAMC,KAAKxB,EAAkByB,UAChDzC,GAAYsC,EAAeI,OAAS,GACtC1C,EAASsC,GAEXpB,IACAnB,KACC,CAACC,EAAUgB,EAAmBjB,EAASmB,IAYpCyB,EAAgBC,EAAuB,KAE3C,MAAMC,EAA4B,CAChCC,MAAOvC,EAAU,UACjBwC,QAASb,EACTc,QAAS,YACTC,KAAM,UACNC,GAAI,wBAGAC,EAA4C,CAChDC,QAAS,CACPP,EACA,CACEC,MAAOvC,EAAU,UACjBwC,QAASX,EACTY,QAAS,UACTE,GAAI,yBAGRG,OAAQ,CACNR,EACA,CACEC,MAAOvC,EAAU,QACjBwC,QAASrB,EACT4B,QAAS/B,EACTyB,QAAS,UACTE,GAAI,0BAKV,OAAOC,EAAW/C,IAAiB+C,EAAoB,SACtD,CAAC/C,EAAamB,EAAaW,EAAcE,EAAoBV,EAAYnB,IAE5E,OACEgD,EAACC,EAAK,CAACC,QAASd,EAAe5C,QAASmC,EAAcpC,KAAMA,EAAMuC,KAAK,QAAQqB,MA3CpEnD,EADJ,YADCH,EAEa,gBAEA,2BA0CnBmD,EAACI,GACCC,MAAM,qBACNC,SAAU,CAACC,EAAGC,KACZ1D,EAAe0D,GACfpC,KAEFoC,MAAO3D,YAEP4D,EAACC,GAAInB,MAAOvC,EAAU,UAAWwD,MAAM,WACvCC,EAACC,EAAG,CAACnB,MAAOvC,EAAU,WAAYwD,MAAM,eAE1CC,EAACvF,EAAuB,CAAAyF,SACL,YAAhB9D,EACC4D,EAACG,EAAiB,CAChBC,OAAQ1D,GAAeD,KACvBI,MAAOC,EACPH,UAAWC,EACXyD,aAAcpD,EACdqB,eAAgBtB,IAGlBgD,EAACM,GACCzD,MAAOS,EACPiD,MAAOlD,EACPmD,SAAU/C,EACVgD,SAAUjD,UAwBhBkD,EAA6CC,GAE/CX,EAACY,EAAmB,CAACC,OAAQtF,EAAW2E,SACtCF,EAACnE,EAAmB,IAAK8E"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/components/organisms/AssetManager/index.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { styled } from '@mui/material/styles';\n\nimport Box from '@fd/components/atoms/Box';\nimport Tab from '@fd/components/atoms/Tab';\nimport Modal, { type ModalAction } from '@fd/components/molecules/Modal';\nimport Tabs from '@fd/components/molecules/Tabs';\nimport { useTranslation } from '@fd/providers/TranslationProvider';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\n\nimport { useAssetSelection } from './hooks/useAssetSelection';\nimport { useAssetUploadManager } from './hooks/useAssetUploadManager';\nimport { useGetAssets } from './hooks/useGetAssets';\nimport LibraryTabContent from './LibraryTabContent';\nimport type { Asset } from './types/assets.type';\nimport UploadAssetContent from './UploadTabContent';\n/**\n * Scrollable container for the tab content.\n * Allows the asset list to scroll while keeping the modal title, tabs, and actions visible.\n * Uses fixed height to prevent modal resizing when switching tabs.\n */\nconst StyledScrollableContent = styled(Box)(({ theme }) => ({\n height: 'calc(70vh - 200px)', // Fixed height for consistent modal size across tabs\n overflowY: 'auto',\n marginTop: theme.spacing(2),\n marginRight: theme.spacing(-2), // Extend to edge for scrollbar\n marginLeft: theme.spacing(-1), // Allow space for shadows on left\n marginBottom: theme.spacing(-1), // Allow space for shadows on bottom\n paddingRight: theme.spacing(2), // Compensate for negative margin\n paddingLeft: theme.spacing(1), // Compensate for negative margin\n paddingBottom: theme.spacing(1), // Compensate for negative margin\n}));\n\n/**\n * Props for the AssetManager component.\n * Provides a modal interface for selecting images from a grid display.\n * It supports both single and multiple image selection modes with configurable limits.\n *\n * import AssetManager from '@flipdish/portal-library/components/organisms/AssetManager';\n *\n * ```tsx\n * import AssetManager from '@flipdish/portal-library/components/organisms/AssetManager';\n */\nexport interface AssetManagerProps {\n /** Whether the asset manager modal is open */\n open: boolean;\n /** Callback function when the modal is closed or cancelled */\n onClose: () => void;\n /** Callback function when assets are selected */\n onSelect?: (selectedAssets: Asset[]) => void;\n /**\n * Organization ID for fetching assets\n */\n orgId: string;\n /** Brand ID for fetching assets */\n brandId?: string;\n /** Maximum number of assets that can be selected. Defaults to 1 */\n maxSelect?: number;\n /** When true, uploads via presigned S3 URLs (supports files up to 20 MB). Defaults to false */\n useNewUploadFlow?: boolean;\n}\n\n// Create a QueryClient instance for the AssetManager component\n// This allows the component to be used without requiring clients to wrap it in QueryClientProvider\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n refetchOnWindowFocus: false,\n retry: 2,\n },\n },\n});\n\n/**\n * Inner component that contains the AssetManager logic.\n * Must be rendered inside QueryClientProvider to use React Query hooks.\n */\nconst AssetManagerContent: React.FC<AssetManagerProps> = ({\n open,\n onClose,\n onSelect,\n orgId,\n brandId,\n maxSelect = 1,\n useNewUploadFlow = false,\n}) => {\n const [selectedTab, setSelectedTab] = useState<string>('library');\n const { translate } = useTranslation();\n\n // Fetch assets at the parent level to enable future reuse across tabs\n const {\n data: assetResponse,\n isLoading: isLoadingAssets,\n error: assetsError,\n } = useGetAssets(orgId, open, brandId);\n\n // Asset selection hook - manages selected assets from library\n const { selectedAssetsMap, handleAssetClick, clearSelection, addAssetsToSelection } = useAssetSelection({\n maxSelect,\n });\n\n // Asset upload hook - manages file uploads and upload state\n const {\n uploadedFiles,\n uploadError,\n isUploading,\n handleUpload,\n handleRemove,\n handleSave,\n clearUploadedFiles,\n clearSaveUploadError,\n } = useAssetUploadManager({\n orgId,\n brandId,\n useNewUploadFlow,\n onUploadSuccess: (uploadedAssets) => {\n // Add uploaded assets to selection and switch to library tab\n addAssetsToSelection(uploadedAssets);\n setSelectedTab('library');\n },\n getErrorMessage: (error: Error) => error.message || translate('Failed_to_upload_assets_try_again'),\n });\n\n // Reset state when modal opens/closes\n useEffect(() => {\n if (!open) {\n clearSelection();\n clearUploadedFiles();\n clearSaveUploadError();\n }\n }, [open, clearSelection, clearUploadedFiles, clearSaveUploadError]);\n\n const handleCancel = useCallback((): void => {\n clearSelection();\n onClose();\n }, [onClose, clearSelection]);\n\n const handleSelectAssets = useCallback((): void => {\n if (selectedAssetsMap.size === 0) {\n onClose();\n return;\n }\n const selectedAssets = Array.from(selectedAssetsMap.values());\n if (onSelect && selectedAssets.length > 0) {\n onSelect(selectedAssets);\n }\n clearSelection();\n onClose();\n }, [onSelect, selectedAssetsMap, onClose, clearSelection]);\n\n const getTitle = (): string => {\n switch (selectedTab) {\n case 'library':\n return translate('Select_Images');\n default:\n return translate('Upload_Images');\n }\n };\n\n // Tab-specific action button configurations\n const actionButtons = useMemo<ModalAction[]>(() => {\n // Common cancel button configuration\n const cancelButton: ModalAction = {\n label: translate('Cancel'),\n onClick: handleCancel,\n variant: 'secondary',\n tone: 'neutral',\n id: 'asset-manager-cancel',\n };\n\n const tabActions: Record<string, ModalAction[]> = {\n library: [\n cancelButton,\n {\n label: translate('Select'),\n onClick: handleSelectAssets,\n variant: 'primary',\n id: 'asset-manager-select',\n },\n ],\n upload: [\n cancelButton,\n {\n label: translate('Save'),\n onClick: handleSave,\n loading: isUploading,\n variant: 'primary',\n id: 'asset-manager-upload',\n },\n ],\n };\n\n return tabActions[selectedTab] ?? (tabActions['library'] as ModalAction[]);\n }, [selectedTab, isUploading, handleCancel, handleSelectAssets, handleSave, translate]);\n\n return (\n <Modal actions={actionButtons} onClose={handleCancel} open={open} size=\"large\" title={getTitle()}>\n <Tabs\n fdKey=\"asset-manager-tabs\"\n onChange={(_, value: string) => {\n setSelectedTab(value);\n clearUploadedFiles();\n }}\n value={selectedTab}\n >\n <Tab label={translate('Upload')} value=\"upload\" />\n <Tab label={translate('Library')} value=\"library\" />\n </Tabs>\n <StyledScrollableContent>\n {selectedTab === 'library' ? (\n <LibraryTabContent\n assets={assetResponse?.data}\n error={assetsError}\n isLoading={isLoadingAssets}\n onAssetClick={handleAssetClick}\n selectedAssets={selectedAssetsMap}\n />\n ) : (\n <UploadAssetContent\n error={uploadError}\n files={uploadedFiles}\n onRemove={handleRemove}\n onUpload={handleUpload}\n />\n )}\n </StyledScrollableContent>\n </Modal>\n );\n};\n\n/**\n * AssetManager component used to select assets from the library or upload new assets.\n * Can manage assets at a organization or brand level.\n *\n * @example\n * ```tsx\n * <AssetManager\n * open={isOpen}\n * onClose={() => setIsOpen(false)}\n * onSelect={(assets) => console.log(assets)}\n * orgId=\"org123\"\n * brandId=\"brand456\"\n * maxSelect={3}\n * />\n * ```\n */\nconst AssetManager: React.FC<AssetManagerProps> = (props) => {\n return (\n <QueryClientProvider client={queryClient}>\n <AssetManagerContent {...props} />\n </QueryClientProvider>\n );\n};\n\nexport type { Asset, AssetMetadata, AssetMetadataDimensions, AssetType } from './types/assets.type';\nexport default AssetManager;\n"],"names":["StyledScrollableContent","styled","Box","theme","height","overflowY","marginTop","spacing","marginRight","marginLeft","marginBottom","paddingRight","paddingLeft","paddingBottom","queryClient","QueryClient","defaultOptions","queries","refetchOnWindowFocus","retry","AssetManagerContent","open","onClose","onSelect","orgId","brandId","maxSelect","useNewUploadFlow","selectedTab","setSelectedTab","useState","translate","useTranslation","data","assetResponse","isLoading","isLoadingAssets","error","assetsError","useGetAssets","selectedAssetsMap","handleAssetClick","clearSelection","addAssetsToSelection","useAssetSelection","uploadedFiles","uploadError","isUploading","handleUpload","handleRemove","handleSave","clearUploadedFiles","clearSaveUploadError","useAssetUploadManager","onUploadSuccess","uploadedAssets","getErrorMessage","message","useEffect","handleCancel","useCallback","handleSelectAssets","size","selectedAssets","Array","from","values","length","actionButtons","useMemo","cancelButton","label","onClick","variant","tone","id","tabActions","library","upload","loading","_jsxs","Modal","actions","title","Tabs","fdKey","onChange","_","value","_jsx","Tab","children","LibraryTabContent","assets","onAssetClick","UploadAssetContent","files","onRemove","onUpload","AssetManager","props","QueryClientProvider","client"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";var t=require("../../../../utilities/apiUtils.cjs.js"),s=require("../../../../utilities/fileUtils.cjs.js");const e=()=>{const t=window.location?.host?.includes("portal.flipdish.com");return t?"https://api.portal.flipdish.com/assets":"https://api-prod-staging.portal.flipdishdev.com/assets"};exports.getAssets=async(t,s)=>{const r=((t,s)=>{if(!t)return;const r=s?`?brandId=${s}`:"";return`${e()}/orgs/${t}/assets${r}`})(t,s);if(!r)throw new Error("Organization ID is required to fetch assets");const o=await fetch(r,{method:"GET",credentials:"include"});if(!o.ok)throw new Error(`Failed to fetch assets: ${o.statusText}`);return await o.json()},exports.uploadAsset=async r=>{const{orgId:o,brandId:a,files:i}=r;if(!o)throw new Error("Organization ID is required to upload assets");if(!i||0===i.length)throw new Error("At least one file is required to upload");const n=i.map(s.sanitizeFile),d=`${e()}/orgs/${encodeURIComponent(o)}/assets/upload`,c=new FormData;for(const t of n)c.append("files",t);void 0!==a&&c.append("brandId",a);try{const t=await fetch(d,{method:"POST",credentials:"include",body:c});if(!t.ok){let s=t.statusText;try{const e=await t.json();s=e?.error?.message??e?.Message??s}catch{}throw new Error(s||"Failed to upload assets")}return await t.json()}catch(s){const e=t.getErrorMessage(s,"Failed to upload assets");throw new Error(e)}};
1
+ "use strict";var e=require("../../../../utilities/apiUtils.cjs.js"),t=require("../../../../utilities/fileUtils.cjs.js");const r=()=>{const e=window.location?.host?.includes("portal.flipdish.com");return e?"https://api.portal.flipdish.com/assets":"https://api-prod-staging.portal.flipdishdev.com/assets"},o=async t=>{const{orgId:o,brandId:s,files:a}=t;if(!o)throw new Error("Organization ID is required to request upload");const n=`${r()}/orgs/${encodeURIComponent(o)}/assets/request-upload`,i={files:a.map(e=>({fileName:e.name,contentType:e.type}))};void 0!==s&&(i.brandId=s);try{const e=await fetch(n,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)});if(!e.ok){let t=e.statusText;try{const r=await e.json();t=r?.error?.message??r?.Message??t}catch{}throw new Error(t||"Failed to request upload")}return await e.json()}catch(t){const r=e.getErrorMessage(t,"Failed to request upload");throw new Error(r)}},s=async(e,t)=>{const r=await fetch(e,{method:"PUT",headers:{"Content-Type":t.type},body:t});if(!r.ok)throw new Error(`Failed to upload file to storage: ${r.statusText}`)},a=async t=>{const{orgId:o,brandId:s,assetKeys:a}=t;if(!o)throw new Error("Organization ID is required to confirm upload");const n=`${r()}/orgs/${encodeURIComponent(o)}/assets/confirm-upload`,i={assetKeys:a};void 0!==s&&(i.brandId=s);try{const e=await fetch(n,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)});if(!e.ok){let t=e.statusText;try{const r=await e.json();t=r?.error?.message??r?.Message??t}catch{}throw new Error(t||"Failed to confirm upload")}return await e.json()}catch(t){const r=e.getErrorMessage(t,"Failed to confirm upload");throw new Error(r)}};exports.confirmUpload=a,exports.getAssets=async(e,t)=>{const o=((e,t)=>{if(!e)return;const o=t?`?brandId=${t}`:"";return`${r()}/orgs/${e}/assets${o}`})(e,t);if(!o)throw new Error("Organization ID is required to fetch assets");const s=await fetch(o,{method:"GET",credentials:"include"});if(!s.ok)throw new Error(`Failed to fetch assets: ${s.statusText}`);return await s.json()},exports.requestUpload=o,exports.uploadAsset=async o=>{const{orgId:s,brandId:a,files:n}=o;if(!s)throw new Error("Organization ID is required to upload assets");if(!n||0===n.length)throw new Error("At least one file is required to upload");const i=n.map(t.sanitizeFile),d=`${r()}/orgs/${encodeURIComponent(s)}/assets/upload`,c=new FormData;for(const e of i)c.append("files",e);void 0!==a&&c.append("brandId",a);try{const e=await fetch(d,{method:"POST",credentials:"include",body:c});if(!e.ok){let t=e.statusText;try{const r=await e.json();t=r?.error?.message??r?.Message??t}catch{}throw new Error(t||"Failed to upload assets")}return await e.json()}catch(t){const r=e.getErrorMessage(t,"Failed to upload assets");throw new Error(r)}},exports.uploadAssetViaPresignedUrl=async r=>{const{orgId:n,brandId:i,files:d}=r;if(!n)throw new Error("Organization ID is required to upload assets");if(!d||0===d.length)throw new Error("At least one file is required to upload");const c=d.map(t.sanitizeFile);try{const{data:e}=await o({orgId:n,brandId:i,files:c}),t=c.map((t,r)=>{const o=e[r];if(!o)throw new Error(`No presigned URL returned for file: ${t.name}`);const s=o.assetKey.split("/").pop()??t.name;return s===t.name?t:new File([t],s,{type:t.type})});await Promise.all(t.map((t,r)=>s(e[r].uploadUrl,t)));const r=e.map(e=>e.assetKey);return await a({orgId:n,brandId:i,assetKeys:r})}catch(t){const r=e.getErrorMessage(t,"Failed to upload assets");throw new Error(r)}},exports.uploadFileToPresignedUrl=s;
2
2
  //# sourceMappingURL=asset.service.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"asset.service.cjs.js","sources":["../../../../../src/components/organisms/AssetManager/services/asset.service.ts"],"sourcesContent":["import { getErrorMessage } from '@fd/utilities/apiUtils';\n\nimport { sanitizeFile } from '../../../../utilities/fileUtils';\nimport type { ListAssetsResponse, UploadAssetResponse } from '../types/assets.type';\n\nconst PROD_API_URL = 'https://api.portal.flipdish.com/assets';\nconst DEV_STAGING_API_URL = 'https://api-prod-staging.portal.flipdishdev.com/assets';\n\n/**\n * Gets the asset management API base URL based on the current environment\n * @returns The appropriate API URL for the current environment\n */\nconst getAssetManagementApiUrl = (): string => {\n const isProd = window.location?.host?.includes('portal.flipdish.com');\n\n if (isProd) {\n return PROD_API_URL;\n }\n\n return DEV_STAGING_API_URL;\n};\n\nconst buildApiUrl = (orgId: string, brandId?: string): string | undefined => {\n if (!orgId) return undefined;\n const brandIdQueryParam = brandId ? `?brandId=${brandId}` : '';\n const baseUrl = getAssetManagementApiUrl();\n return `${baseUrl}/orgs/${orgId}/assets${brandIdQueryParam}`;\n};\n\n/**\n * Fetches assets from the asset management service API\n * @param orgId - organization ID.\n * @param brandId - brand ID.\n * @returns Promise resolving to an array of assets\n */\nexport const getAssets = async (orgId: string, brandId?: string): Promise<ListAssetsResponse> => {\n const apiUrl = buildApiUrl(orgId, brandId);\n\n if (!apiUrl) {\n throw new Error('Organization ID is required to fetch assets');\n }\n\n const response = await fetch(apiUrl, {\n method: 'GET',\n credentials: 'include',\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch assets: ${response.statusText}`);\n }\n\n return (await response.json()) as ListAssetsResponse;\n};\n\n/**\n * Upload parameters for asset upload\n */\nexport interface UploadAssetParams {\n /** Organization ID */\n orgId: string;\n /** Optional brand ID */\n brandId?: string;\n /** The files to upload */\n files: File[];\n}\n\n/**\n * Uploads multiple assets to the asset management service API\n * Sanitizes filenames by replacing spaces with dashes before uploading\n * @param params - Upload parameters containing orgId, brandId, and files\n * @returns Promise resolving to an array of uploaded assets\n */\nexport const uploadAsset = async (params: UploadAssetParams): Promise<UploadAssetResponse> => {\n const { orgId, brandId, files } = params;\n\n if (!orgId) {\n throw new Error('Organization ID is required to upload assets');\n }\n\n if (!files || files.length === 0) {\n throw new Error('At least one file is required to upload');\n }\n\n // Sanitize filenames by replacing spaces with dashes\n const sanitizedFiles = files.map(sanitizeFile);\n\n const baseUrl = getAssetManagementApiUrl();\n const uploadUrl = `${baseUrl}/orgs/${encodeURIComponent(orgId)}/assets/upload`;\n\n const formData = new FormData();\n for (const file of sanitizedFiles) {\n formData.append('files', file);\n }\n if (brandId !== undefined) {\n formData.append('brandId', brandId);\n }\n\n try {\n const response = await fetch(uploadUrl, {\n method: 'POST',\n credentials: 'include',\n body: formData,\n });\n\n if (!response.ok) {\n let message = response.statusText;\n try {\n const body = (await response.json()) as { error?: { message?: string }; Message?: string };\n message = body?.error?.message ?? body?.Message ?? message;\n } catch {\n // ignore JSON parse failure\n }\n throw new Error(message || 'Failed to upload assets');\n }\n\n return (await response.json()) as UploadAssetResponse;\n } catch (error: unknown) {\n const errorMessage = getErrorMessage(error, 'Failed to upload assets');\n throw new Error(errorMessage);\n }\n};\n"],"names":["getAssetManagementApiUrl","isProd","window","location","host","includes","async","orgId","brandId","apiUrl","brandIdQueryParam","buildApiUrl","Error","response","fetch","method","credentials","ok","statusText","json","params","files","length","sanitizedFiles","map","sanitizeFile","uploadUrl","encodeURIComponent","formData","FormData","file","append","undefined","body","message","error","Message","errorMessage","getErrorMessage"],"mappings":"wHAKA,MAOMA,EAA2B,KAC/B,MAAMC,EAASC,OAAOC,UAAUC,MAAMC,SAAS,uBAE/C,OAAIJ,EAVe,yCACO,4EA6BHK,MAAOC,EAAeC,KAC7C,MAAMC,EAdY,EAACF,EAAeC,KAClC,IAAKD,EAAO,OACZ,MAAMG,EAAoBF,EAAU,YAAYA,IAAY,GAE5D,MAAO,GADSR,YACUO,WAAeG,KAU1BC,CAAYJ,EAAOC,GAElC,IAAKC,EACH,MAAM,IAAIG,MAAM,+CAGlB,MAAMC,QAAiBC,MAAML,EAAQ,CACnCM,OAAQ,MACRC,YAAa,YAGf,IAAKH,EAASI,GACZ,MAAM,IAAIL,MAAM,2BAA2BC,EAASK,cAGtD,aAAcL,EAASM,4BAqBEb,MAAOc,IAChC,MAAMb,MAAEA,EAAKC,QAAEA,EAAOa,MAAEA,GAAUD,EAElC,IAAKb,EACH,MAAM,IAAIK,MAAM,gDAGlB,IAAKS,GAA0B,IAAjBA,EAAMC,OAClB,MAAM,IAAIV,MAAM,2CAIlB,MAAMW,EAAiBF,EAAMG,IAAIC,gBAG3BC,EAAY,GADF1B,YACqB2B,mBAAmBpB,mBAElDqB,EAAW,IAAIC,SACrB,IAAK,MAAMC,KAAQP,EACjBK,EAASG,OAAO,QAASD,QAEXE,IAAZxB,GACFoB,EAASG,OAAO,UAAWvB,GAG7B,IACE,MAAMK,QAAiBC,MAAMY,EAAW,CACtCX,OAAQ,OACRC,YAAa,UACbiB,KAAML,IAGR,IAAKf,EAASI,GAAI,CAChB,IAAIiB,EAAUrB,EAASK,WACvB,IACE,MAAMe,QAAcpB,EAASM,OAC7Be,EAAUD,GAAME,OAAOD,SAAWD,GAAMG,SAAWF,CACrD,CAAE,MAEF,CACA,MAAM,IAAItB,MAAMsB,GAAW,0BAC7B,CAEA,aAAcrB,EAASM,MACzB,CAAE,MAAOgB,GACP,MAAME,EAAeC,EAAAA,gBAAgBH,EAAO,2BAC5C,MAAM,IAAIvB,MAAMyB,EAClB"}
1
+ {"version":3,"file":"asset.service.cjs.js","sources":["../../../../../src/components/organisms/AssetManager/services/asset.service.ts"],"sourcesContent":["import { getErrorMessage } from '@fd/utilities/apiUtils';\n\nimport { sanitizeFile } from '../../../../utilities/fileUtils';\nimport type { ListAssetsResponse, UploadAssetResponse } from '../types/assets.type';\n\ninterface PresignedUploadItem {\n uploadUrl: string;\n assetKey: string;\n expiresIn: number;\n}\n\ninterface RequestUploadResponse {\n data: PresignedUploadItem[];\n}\n\ninterface ConfirmUploadParams {\n orgId: string;\n brandId?: string;\n assetKeys: string[];\n}\n\nconst PROD_API_URL = 'https://api.portal.flipdish.com/assets';\nconst DEV_STAGING_API_URL = 'https://api-prod-staging.portal.flipdishdev.com/assets';\n\n/**\n * Gets the asset management API base URL based on the current environment\n * @returns The appropriate API URL for the current environment\n */\nconst getAssetManagementApiUrl = (): string => {\n const isProd = window.location?.host?.includes('portal.flipdish.com');\n\n if (isProd) {\n return PROD_API_URL;\n }\n\n return DEV_STAGING_API_URL;\n};\n\nconst buildApiUrl = (orgId: string, brandId?: string): string | undefined => {\n if (!orgId) return undefined;\n const brandIdQueryParam = brandId ? `?brandId=${brandId}` : '';\n const baseUrl = getAssetManagementApiUrl();\n return `${baseUrl}/orgs/${orgId}/assets${brandIdQueryParam}`;\n};\n\n/**\n * Fetches assets from the asset management service API\n * @param orgId - organization ID.\n * @param brandId - brand ID.\n * @returns Promise resolving to an array of assets\n */\nexport const getAssets = async (orgId: string, brandId?: string): Promise<ListAssetsResponse> => {\n const apiUrl = buildApiUrl(orgId, brandId);\n\n if (!apiUrl) {\n throw new Error('Organization ID is required to fetch assets');\n }\n\n const response = await fetch(apiUrl, {\n method: 'GET',\n credentials: 'include',\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch assets: ${response.statusText}`);\n }\n\n return (await response.json()) as ListAssetsResponse;\n};\n\n/**\n * Upload parameters for asset upload\n */\nexport interface UploadAssetParams {\n /** Organization ID */\n orgId: string;\n /** Optional brand ID */\n brandId?: string;\n /** The files to upload */\n files: File[];\n}\n\n/**\n * Uploads multiple assets to the asset management service API\n * Sanitizes filenames by replacing spaces with dashes before uploading\n * @param params - Upload parameters containing orgId, brandId, and files\n * @returns Promise resolving to an array of uploaded assets\n */\nexport const uploadAsset = async (params: UploadAssetParams): Promise<UploadAssetResponse> => {\n const { orgId, brandId, files } = params;\n\n if (!orgId) {\n throw new Error('Organization ID is required to upload assets');\n }\n\n if (!files || files.length === 0) {\n throw new Error('At least one file is required to upload');\n }\n\n // Sanitize filenames by replacing spaces with dashes\n const sanitizedFiles = files.map(sanitizeFile);\n\n const baseUrl = getAssetManagementApiUrl();\n const uploadUrl = `${baseUrl}/orgs/${encodeURIComponent(orgId)}/assets/upload`;\n\n const formData = new FormData();\n for (const file of sanitizedFiles) {\n formData.append('files', file);\n }\n if (brandId !== undefined) {\n formData.append('brandId', brandId);\n }\n\n try {\n const response = await fetch(uploadUrl, {\n method: 'POST',\n credentials: 'include',\n body: formData,\n });\n\n if (!response.ok) {\n let message = response.statusText;\n try {\n const body = (await response.json()) as { error?: { message?: string }; Message?: string };\n message = body?.error?.message ?? body?.Message ?? message;\n } catch {\n // ignore JSON parse failure\n }\n throw new Error(message || 'Failed to upload assets');\n }\n\n return (await response.json()) as UploadAssetResponse;\n } catch (error: unknown) {\n const errorMessage = getErrorMessage(error, 'Failed to upload assets');\n throw new Error(errorMessage);\n }\n};\n\n/**\n * Requests presigned S3 PUT URLs for direct client-to-S3 uploads.\n * @param params - orgId, optional brandId, and files to upload\n * @returns Presigned upload items containing uploadUrl and assetKey per file\n */\nexport const requestUpload = async (params: UploadAssetParams): Promise<RequestUploadResponse> => {\n const { orgId, brandId, files } = params;\n\n if (!orgId) {\n throw new Error('Organization ID is required to request upload');\n }\n\n const baseUrl = getAssetManagementApiUrl();\n const url = `${baseUrl}/orgs/${encodeURIComponent(orgId)}/assets/request-upload`;\n\n const body: { files: Array<{ fileName: string; contentType: string }>; brandId?: string } = {\n files: files.map((file) => ({ fileName: file.name, contentType: file.type })),\n };\n if (brandId !== undefined) {\n body.brandId = brandId;\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n credentials: 'include',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n let message = response.statusText;\n try {\n const responseBody = (await response.json()) as { error?: { message?: string }; Message?: string };\n message = responseBody?.error?.message ?? responseBody?.Message ?? message;\n } catch {\n // ignore JSON parse failure\n }\n throw new Error(message || 'Failed to request upload');\n }\n\n return (await response.json()) as RequestUploadResponse;\n } catch (error: unknown) {\n const errorMessage = getErrorMessage(error, 'Failed to request upload');\n throw new Error(errorMessage);\n }\n};\n\n/**\n * Uploads a single file directly to S3 using a presigned PUT URL.\n * Does not use credentials — the presigned URL is self-authenticating.\n * @param uploadUrl - The presigned S3 PUT URL\n * @param file - The file to upload\n */\nexport const uploadFileToPresignedUrl = async (uploadUrl: string, file: File): Promise<void> => {\n const response = await fetch(uploadUrl, {\n method: 'PUT',\n headers: { 'Content-Type': file.type },\n body: file,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to upload file to storage: ${response.statusText}`);\n }\n};\n\n/**\n * Confirms that files have been uploaded to S3 and creates asset metadata records.\n * @param params - orgId, optional brandId, and S3 asset keys from request-upload\n * @returns The created asset records\n */\nexport const confirmUpload = async (params: ConfirmUploadParams): Promise<UploadAssetResponse> => {\n const { orgId, brandId, assetKeys } = params;\n\n if (!orgId) {\n throw new Error('Organization ID is required to confirm upload');\n }\n\n const baseUrl = getAssetManagementApiUrl();\n const url = `${baseUrl}/orgs/${encodeURIComponent(orgId)}/assets/confirm-upload`;\n\n const body: { assetKeys: string[]; brandId?: string } = { assetKeys };\n if (brandId !== undefined) {\n body.brandId = brandId;\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n credentials: 'include',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n let message = response.statusText;\n try {\n const responseBody = (await response.json()) as { error?: { message?: string }; Message?: string };\n message = responseBody?.error?.message ?? responseBody?.Message ?? message;\n } catch {\n // ignore JSON parse failure\n }\n throw new Error(message || 'Failed to confirm upload');\n }\n\n return (await response.json()) as UploadAssetResponse;\n } catch (error: unknown) {\n const errorMessage = getErrorMessage(error, 'Failed to confirm upload');\n throw new Error(errorMessage);\n }\n};\n\n/**\n * Uploads assets via the presigned S3 URL flow:\n * 1. Request presigned URLs from the service\n * 2. PUT each file directly to its S3 presigned URL (in parallel)\n * 3. Confirm uploads to persist asset metadata\n *\n * Supports files up to 20 MB\n * @param params - Upload parameters containing orgId, brandId, and files\n * @returns Promise resolving to the created asset records\n */\nexport const uploadAssetViaPresignedUrl = async (params: UploadAssetParams): Promise<UploadAssetResponse> => {\n const { orgId, brandId, files } = params;\n\n if (!orgId) {\n throw new Error('Organization ID is required to upload assets');\n }\n\n if (!files || files.length === 0) {\n throw new Error('At least one file is required to upload');\n }\n\n // Sanitize filenames (spaces → dashes) before requesting presigned URLs\n const sanitizedFiles = files.map(sanitizeFile);\n\n try {\n // Step 1: Get presigned S3 PUT URLs\n const { data: presignedItems } = await requestUpload({ orgId, brandId, files: sanitizedFiles });\n\n // Step 2: Align file names with the asset keys returned by the server.\n // The server may have deduplicated filenames (e.g. my-file.jpg → my-file-1.jpg),\n // so rename any file whose name doesn't match the end of its asset key.\n const alignedFiles = sanitizedFiles.map((file, index) => {\n const item = presignedItems[index];\n if (!item) {\n throw new Error(`No presigned URL returned for file: ${file.name}`);\n }\n const keyFileName = item.assetKey.split('/').pop() ?? file.name;\n if (keyFileName === file.name) {\n return file;\n }\n return new File([file], keyFileName, { type: file.type });\n });\n\n // Step 3: Upload all files in parallel to their respective presigned URLs\n await Promise.all(\n alignedFiles.map((file, index) => {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return uploadFileToPresignedUrl(presignedItems[index]!.uploadUrl, file);\n }),\n );\n\n // Step 4: Confirm uploads and get asset metadata\n const assetKeys = presignedItems.map((item) => item.assetKey);\n return await confirmUpload({ orgId, brandId, assetKeys });\n } catch (error: unknown) {\n const errorMessage = getErrorMessage(error, 'Failed to upload assets');\n throw new Error(errorMessage);\n }\n};\n"],"names":["getAssetManagementApiUrl","isProd","window","location","host","includes","requestUpload","async","params","orgId","brandId","files","Error","url","encodeURIComponent","body","map","file","fileName","name","contentType","type","undefined","response","fetch","method","credentials","headers","JSON","stringify","ok","message","statusText","responseBody","json","error","Message","errorMessage","getErrorMessage","uploadFileToPresignedUrl","uploadUrl","confirmUpload","assetKeys","apiUrl","brandIdQueryParam","buildApiUrl","length","sanitizedFiles","sanitizeFile","formData","FormData","append","data","presignedItems","alignedFiles","index","item","keyFileName","assetKey","split","pop","File","Promise","all"],"mappings":"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"}
@@ -1,5 +1,18 @@
1
- import { ListAssetsResponse, UploadAssetResponse } from '@flipdish/asset-management';
1
+ import { UploadAssetResponse, ListAssetsResponse } from '@flipdish/asset-management';
2
2
 
3
+ interface PresignedUploadItem {
4
+ uploadUrl: string;
5
+ assetKey: string;
6
+ expiresIn: number;
7
+ }
8
+ interface RequestUploadResponse {
9
+ data: PresignedUploadItem[];
10
+ }
11
+ interface ConfirmUploadParams {
12
+ orgId: string;
13
+ brandId?: string;
14
+ assetKeys: string[];
15
+ }
3
16
  /**
4
17
  * Fetches assets from the asset management service API
5
18
  * @param orgId - organization ID.
@@ -25,6 +38,36 @@ interface UploadAssetParams {
25
38
  * @returns Promise resolving to an array of uploaded assets
26
39
  */
27
40
  declare const uploadAsset: (params: UploadAssetParams) => Promise<UploadAssetResponse>;
41
+ /**
42
+ * Requests presigned S3 PUT URLs for direct client-to-S3 uploads.
43
+ * @param params - orgId, optional brandId, and files to upload
44
+ * @returns Presigned upload items containing uploadUrl and assetKey per file
45
+ */
46
+ declare const requestUpload: (params: UploadAssetParams) => Promise<RequestUploadResponse>;
47
+ /**
48
+ * Uploads a single file directly to S3 using a presigned PUT URL.
49
+ * Does not use credentials — the presigned URL is self-authenticating.
50
+ * @param uploadUrl - The presigned S3 PUT URL
51
+ * @param file - The file to upload
52
+ */
53
+ declare const uploadFileToPresignedUrl: (uploadUrl: string, file: File) => Promise<void>;
54
+ /**
55
+ * Confirms that files have been uploaded to S3 and creates asset metadata records.
56
+ * @param params - orgId, optional brandId, and S3 asset keys from request-upload
57
+ * @returns The created asset records
58
+ */
59
+ declare const confirmUpload: (params: ConfirmUploadParams) => Promise<UploadAssetResponse>;
60
+ /**
61
+ * Uploads assets via the presigned S3 URL flow:
62
+ * 1. Request presigned URLs from the service
63
+ * 2. PUT each file directly to its S3 presigned URL (in parallel)
64
+ * 3. Confirm uploads to persist asset metadata
65
+ *
66
+ * Supports files up to 20 MB
67
+ * @param params - Upload parameters containing orgId, brandId, and files
68
+ * @returns Promise resolving to the created asset records
69
+ */
70
+ declare const uploadAssetViaPresignedUrl: (params: UploadAssetParams) => Promise<UploadAssetResponse>;
28
71
 
29
- export { getAssets, uploadAsset };
72
+ export { confirmUpload, getAssets, requestUpload, uploadAsset, uploadAssetViaPresignedUrl, uploadFileToPresignedUrl };
30
73
  export type { UploadAssetParams };
@@ -1,2 +1,2 @@
1
- import{getErrorMessage as t}from"../../../../utilities/apiUtils.js";import{sanitizeFile as s}from"../../../../utilities/fileUtils.js";const o=()=>{const t=window.location?.host?.includes("portal.flipdish.com");return t?"https://api.portal.flipdish.com/assets":"https://api-prod-staging.portal.flipdishdev.com/assets"},e=async(t,s)=>{const e=((t,s)=>{if(!t)return;const e=s?`?brandId=${s}`:"";return`${o()}/orgs/${t}/assets${e}`})(t,s);if(!e)throw new Error("Organization ID is required to fetch assets");const r=await fetch(e,{method:"GET",credentials:"include"});if(!r.ok)throw new Error(`Failed to fetch assets: ${r.statusText}`);return await r.json()},r=async e=>{const{orgId:r,brandId:a,files:i}=e;if(!r)throw new Error("Organization ID is required to upload assets");if(!i||0===i.length)throw new Error("At least one file is required to upload");const n=i.map(s),d=`${o()}/orgs/${encodeURIComponent(r)}/assets/upload`,c=new FormData;for(const t of n)c.append("files",t);void 0!==a&&c.append("brandId",a);try{const t=await fetch(d,{method:"POST",credentials:"include",body:c});if(!t.ok){let s=t.statusText;try{const o=await t.json();s=o?.error?.message??o?.Message??s}catch{}throw new Error(s||"Failed to upload assets")}return await t.json()}catch(s){const o=t(s,"Failed to upload assets");throw new Error(o)}};export{e as getAssets,r as uploadAsset};
1
+ import{getErrorMessage as t}from"../../../../utilities/apiUtils.js";import{sanitizeFile as e}from"../../../../utilities/fileUtils.js";const o=()=>{const t=window.location?.host?.includes("portal.flipdish.com");return t?"https://api.portal.flipdish.com/assets":"https://api-prod-staging.portal.flipdishdev.com/assets"},r=async(t,e)=>{const r=((t,e)=>{if(!t)return;const r=e?`?brandId=${e}`:"";return`${o()}/orgs/${t}/assets${r}`})(t,e);if(!r)throw new Error("Organization ID is required to fetch assets");const s=await fetch(r,{method:"GET",credentials:"include"});if(!s.ok)throw new Error(`Failed to fetch assets: ${s.statusText}`);return await s.json()},s=async r=>{const{orgId:s,brandId:a,files:n}=r;if(!s)throw new Error("Organization ID is required to upload assets");if(!n||0===n.length)throw new Error("At least one file is required to upload");const i=n.map(e),d=`${o()}/orgs/${encodeURIComponent(s)}/assets/upload`,c=new FormData;for(const t of i)c.append("files",t);void 0!==a&&c.append("brandId",a);try{const t=await fetch(d,{method:"POST",credentials:"include",body:c});if(!t.ok){let e=t.statusText;try{const o=await t.json();e=o?.error?.message??o?.Message??e}catch{}throw new Error(e||"Failed to upload assets")}return await t.json()}catch(e){const o=t(e,"Failed to upload assets");throw new Error(o)}},a=async e=>{const{orgId:r,brandId:s,files:a}=e;if(!r)throw new Error("Organization ID is required to request upload");const n=`${o()}/orgs/${encodeURIComponent(r)}/assets/request-upload`,i={files:a.map(t=>({fileName:t.name,contentType:t.type}))};void 0!==s&&(i.brandId=s);try{const t=await fetch(n,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)});if(!t.ok){let e=t.statusText;try{const o=await t.json();e=o?.error?.message??o?.Message??e}catch{}throw new Error(e||"Failed to request upload")}return await t.json()}catch(e){const o=t(e,"Failed to request upload");throw new Error(o)}},n=async(t,e)=>{const o=await fetch(t,{method:"PUT",headers:{"Content-Type":e.type},body:e});if(!o.ok)throw new Error(`Failed to upload file to storage: ${o.statusText}`)},i=async e=>{const{orgId:r,brandId:s,assetKeys:a}=e;if(!r)throw new Error("Organization ID is required to confirm upload");const n=`${o()}/orgs/${encodeURIComponent(r)}/assets/confirm-upload`,i={assetKeys:a};void 0!==s&&(i.brandId=s);try{const t=await fetch(n,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)});if(!t.ok){let e=t.statusText;try{const o=await t.json();e=o?.error?.message??o?.Message??e}catch{}throw new Error(e||"Failed to confirm upload")}return await t.json()}catch(e){const o=t(e,"Failed to confirm upload");throw new Error(o)}},d=async o=>{const{orgId:r,brandId:s,files:d}=o;if(!r)throw new Error("Organization ID is required to upload assets");if(!d||0===d.length)throw new Error("At least one file is required to upload");const c=d.map(e);try{const{data:t}=await a({orgId:r,brandId:s,files:c}),e=c.map((e,o)=>{const r=t[o];if(!r)throw new Error(`No presigned URL returned for file: ${e.name}`);const s=r.assetKey.split("/").pop()??e.name;return s===e.name?e:new File([e],s,{type:e.type})});await Promise.all(e.map((e,o)=>n(t[o].uploadUrl,e)));const o=t.map(t=>t.assetKey);return await i({orgId:r,brandId:s,assetKeys:o})}catch(e){const o=t(e,"Failed to upload assets");throw new Error(o)}};export{i as confirmUpload,r as getAssets,a as requestUpload,s as uploadAsset,d as uploadAssetViaPresignedUrl,n as uploadFileToPresignedUrl};
2
2
  //# sourceMappingURL=asset.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"asset.service.js","sources":["../../../../../src/components/organisms/AssetManager/services/asset.service.ts"],"sourcesContent":["import { getErrorMessage } from '@fd/utilities/apiUtils';\n\nimport { sanitizeFile } from '../../../../utilities/fileUtils';\nimport type { ListAssetsResponse, UploadAssetResponse } from '../types/assets.type';\n\nconst PROD_API_URL = 'https://api.portal.flipdish.com/assets';\nconst DEV_STAGING_API_URL = 'https://api-prod-staging.portal.flipdishdev.com/assets';\n\n/**\n * Gets the asset management API base URL based on the current environment\n * @returns The appropriate API URL for the current environment\n */\nconst getAssetManagementApiUrl = (): string => {\n const isProd = window.location?.host?.includes('portal.flipdish.com');\n\n if (isProd) {\n return PROD_API_URL;\n }\n\n return DEV_STAGING_API_URL;\n};\n\nconst buildApiUrl = (orgId: string, brandId?: string): string | undefined => {\n if (!orgId) return undefined;\n const brandIdQueryParam = brandId ? `?brandId=${brandId}` : '';\n const baseUrl = getAssetManagementApiUrl();\n return `${baseUrl}/orgs/${orgId}/assets${brandIdQueryParam}`;\n};\n\n/**\n * Fetches assets from the asset management service API\n * @param orgId - organization ID.\n * @param brandId - brand ID.\n * @returns Promise resolving to an array of assets\n */\nexport const getAssets = async (orgId: string, brandId?: string): Promise<ListAssetsResponse> => {\n const apiUrl = buildApiUrl(orgId, brandId);\n\n if (!apiUrl) {\n throw new Error('Organization ID is required to fetch assets');\n }\n\n const response = await fetch(apiUrl, {\n method: 'GET',\n credentials: 'include',\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch assets: ${response.statusText}`);\n }\n\n return (await response.json()) as ListAssetsResponse;\n};\n\n/**\n * Upload parameters for asset upload\n */\nexport interface UploadAssetParams {\n /** Organization ID */\n orgId: string;\n /** Optional brand ID */\n brandId?: string;\n /** The files to upload */\n files: File[];\n}\n\n/**\n * Uploads multiple assets to the asset management service API\n * Sanitizes filenames by replacing spaces with dashes before uploading\n * @param params - Upload parameters containing orgId, brandId, and files\n * @returns Promise resolving to an array of uploaded assets\n */\nexport const uploadAsset = async (params: UploadAssetParams): Promise<UploadAssetResponse> => {\n const { orgId, brandId, files } = params;\n\n if (!orgId) {\n throw new Error('Organization ID is required to upload assets');\n }\n\n if (!files || files.length === 0) {\n throw new Error('At least one file is required to upload');\n }\n\n // Sanitize filenames by replacing spaces with dashes\n const sanitizedFiles = files.map(sanitizeFile);\n\n const baseUrl = getAssetManagementApiUrl();\n const uploadUrl = `${baseUrl}/orgs/${encodeURIComponent(orgId)}/assets/upload`;\n\n const formData = new FormData();\n for (const file of sanitizedFiles) {\n formData.append('files', file);\n }\n if (brandId !== undefined) {\n formData.append('brandId', brandId);\n }\n\n try {\n const response = await fetch(uploadUrl, {\n method: 'POST',\n credentials: 'include',\n body: formData,\n });\n\n if (!response.ok) {\n let message = response.statusText;\n try {\n const body = (await response.json()) as { error?: { message?: string }; Message?: string };\n message = body?.error?.message ?? body?.Message ?? message;\n } catch {\n // ignore JSON parse failure\n }\n throw new Error(message || 'Failed to upload assets');\n }\n\n return (await response.json()) as UploadAssetResponse;\n } catch (error: unknown) {\n const errorMessage = getErrorMessage(error, 'Failed to upload assets');\n throw new Error(errorMessage);\n }\n};\n"],"names":["getAssetManagementApiUrl","isProd","window","location","host","includes","getAssets","async","orgId","brandId","apiUrl","brandIdQueryParam","buildApiUrl","Error","response","fetch","method","credentials","ok","statusText","json","uploadAsset","params","files","length","sanitizedFiles","map","sanitizeFile","uploadUrl","encodeURIComponent","formData","FormData","file","append","undefined","body","message","error","Message","errorMessage","getErrorMessage"],"mappings":"sIAKA,MAOMA,EAA2B,KAC/B,MAAMC,EAASC,OAAOC,UAAUC,MAAMC,SAAS,uBAE/C,OAAIJ,EAVe,yCACO,0DA6BfK,EAAYC,MAAOC,EAAeC,KAC7C,MAAMC,EAdY,EAACF,EAAeC,KAClC,IAAKD,EAAO,OACZ,MAAMG,EAAoBF,EAAU,YAAYA,IAAY,GAE5D,MAAO,GADST,YACUQ,WAAeG,KAU1BC,CAAYJ,EAAOC,GAElC,IAAKC,EACH,MAAM,IAAIG,MAAM,+CAGlB,MAAMC,QAAiBC,MAAML,EAAQ,CACnCM,OAAQ,MACRC,YAAa,YAGf,IAAKH,EAASI,GACZ,MAAM,IAAIL,MAAM,2BAA2BC,EAASK,cAGtD,aAAcL,EAASM,QAqBZC,EAAcd,MAAOe,IAChC,MAAMd,MAAEA,EAAKC,QAAEA,EAAOc,MAAEA,GAAUD,EAElC,IAAKd,EACH,MAAM,IAAIK,MAAM,gDAGlB,IAAKU,GAA0B,IAAjBA,EAAMC,OAClB,MAAM,IAAIX,MAAM,2CAIlB,MAAMY,EAAiBF,EAAMG,IAAIC,GAG3BC,EAAY,GADF5B,YACqB6B,mBAAmBrB,mBAElDsB,EAAW,IAAIC,SACrB,IAAK,MAAMC,KAAQP,EACjBK,EAASG,OAAO,QAASD,QAEXE,IAAZzB,GACFqB,EAASG,OAAO,UAAWxB,GAG7B,IACE,MAAMK,QAAiBC,MAAMa,EAAW,CACtCZ,OAAQ,OACRC,YAAa,UACbkB,KAAML,IAGR,IAAKhB,EAASI,GAAI,CAChB,IAAIkB,EAAUtB,EAASK,WACvB,IACE,MAAMgB,QAAcrB,EAASM,OAC7BgB,EAAUD,GAAME,OAAOD,SAAWD,GAAMG,SAAWF,CACrD,CAAE,MAEF,CACA,MAAM,IAAIvB,MAAMuB,GAAW,0BAC7B,CAEA,aAActB,EAASM,MACzB,CAAE,MAAOiB,GACP,MAAME,EAAeC,EAAgBH,EAAO,2BAC5C,MAAM,IAAIxB,MAAM0B,EAClB"}
1
+ {"version":3,"file":"asset.service.js","sources":["../../../../../src/components/organisms/AssetManager/services/asset.service.ts"],"sourcesContent":["import { getErrorMessage } from '@fd/utilities/apiUtils';\n\nimport { sanitizeFile } from '../../../../utilities/fileUtils';\nimport type { ListAssetsResponse, UploadAssetResponse } from '../types/assets.type';\n\ninterface PresignedUploadItem {\n uploadUrl: string;\n assetKey: string;\n expiresIn: number;\n}\n\ninterface RequestUploadResponse {\n data: PresignedUploadItem[];\n}\n\ninterface ConfirmUploadParams {\n orgId: string;\n brandId?: string;\n assetKeys: string[];\n}\n\nconst PROD_API_URL = 'https://api.portal.flipdish.com/assets';\nconst DEV_STAGING_API_URL = 'https://api-prod-staging.portal.flipdishdev.com/assets';\n\n/**\n * Gets the asset management API base URL based on the current environment\n * @returns The appropriate API URL for the current environment\n */\nconst getAssetManagementApiUrl = (): string => {\n const isProd = window.location?.host?.includes('portal.flipdish.com');\n\n if (isProd) {\n return PROD_API_URL;\n }\n\n return DEV_STAGING_API_URL;\n};\n\nconst buildApiUrl = (orgId: string, brandId?: string): string | undefined => {\n if (!orgId) return undefined;\n const brandIdQueryParam = brandId ? `?brandId=${brandId}` : '';\n const baseUrl = getAssetManagementApiUrl();\n return `${baseUrl}/orgs/${orgId}/assets${brandIdQueryParam}`;\n};\n\n/**\n * Fetches assets from the asset management service API\n * @param orgId - organization ID.\n * @param brandId - brand ID.\n * @returns Promise resolving to an array of assets\n */\nexport const getAssets = async (orgId: string, brandId?: string): Promise<ListAssetsResponse> => {\n const apiUrl = buildApiUrl(orgId, brandId);\n\n if (!apiUrl) {\n throw new Error('Organization ID is required to fetch assets');\n }\n\n const response = await fetch(apiUrl, {\n method: 'GET',\n credentials: 'include',\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch assets: ${response.statusText}`);\n }\n\n return (await response.json()) as ListAssetsResponse;\n};\n\n/**\n * Upload parameters for asset upload\n */\nexport interface UploadAssetParams {\n /** Organization ID */\n orgId: string;\n /** Optional brand ID */\n brandId?: string;\n /** The files to upload */\n files: File[];\n}\n\n/**\n * Uploads multiple assets to the asset management service API\n * Sanitizes filenames by replacing spaces with dashes before uploading\n * @param params - Upload parameters containing orgId, brandId, and files\n * @returns Promise resolving to an array of uploaded assets\n */\nexport const uploadAsset = async (params: UploadAssetParams): Promise<UploadAssetResponse> => {\n const { orgId, brandId, files } = params;\n\n if (!orgId) {\n throw new Error('Organization ID is required to upload assets');\n }\n\n if (!files || files.length === 0) {\n throw new Error('At least one file is required to upload');\n }\n\n // Sanitize filenames by replacing spaces with dashes\n const sanitizedFiles = files.map(sanitizeFile);\n\n const baseUrl = getAssetManagementApiUrl();\n const uploadUrl = `${baseUrl}/orgs/${encodeURIComponent(orgId)}/assets/upload`;\n\n const formData = new FormData();\n for (const file of sanitizedFiles) {\n formData.append('files', file);\n }\n if (brandId !== undefined) {\n formData.append('brandId', brandId);\n }\n\n try {\n const response = await fetch(uploadUrl, {\n method: 'POST',\n credentials: 'include',\n body: formData,\n });\n\n if (!response.ok) {\n let message = response.statusText;\n try {\n const body = (await response.json()) as { error?: { message?: string }; Message?: string };\n message = body?.error?.message ?? body?.Message ?? message;\n } catch {\n // ignore JSON parse failure\n }\n throw new Error(message || 'Failed to upload assets');\n }\n\n return (await response.json()) as UploadAssetResponse;\n } catch (error: unknown) {\n const errorMessage = getErrorMessage(error, 'Failed to upload assets');\n throw new Error(errorMessage);\n }\n};\n\n/**\n * Requests presigned S3 PUT URLs for direct client-to-S3 uploads.\n * @param params - orgId, optional brandId, and files to upload\n * @returns Presigned upload items containing uploadUrl and assetKey per file\n */\nexport const requestUpload = async (params: UploadAssetParams): Promise<RequestUploadResponse> => {\n const { orgId, brandId, files } = params;\n\n if (!orgId) {\n throw new Error('Organization ID is required to request upload');\n }\n\n const baseUrl = getAssetManagementApiUrl();\n const url = `${baseUrl}/orgs/${encodeURIComponent(orgId)}/assets/request-upload`;\n\n const body: { files: Array<{ fileName: string; contentType: string }>; brandId?: string } = {\n files: files.map((file) => ({ fileName: file.name, contentType: file.type })),\n };\n if (brandId !== undefined) {\n body.brandId = brandId;\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n credentials: 'include',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n let message = response.statusText;\n try {\n const responseBody = (await response.json()) as { error?: { message?: string }; Message?: string };\n message = responseBody?.error?.message ?? responseBody?.Message ?? message;\n } catch {\n // ignore JSON parse failure\n }\n throw new Error(message || 'Failed to request upload');\n }\n\n return (await response.json()) as RequestUploadResponse;\n } catch (error: unknown) {\n const errorMessage = getErrorMessage(error, 'Failed to request upload');\n throw new Error(errorMessage);\n }\n};\n\n/**\n * Uploads a single file directly to S3 using a presigned PUT URL.\n * Does not use credentials — the presigned URL is self-authenticating.\n * @param uploadUrl - The presigned S3 PUT URL\n * @param file - The file to upload\n */\nexport const uploadFileToPresignedUrl = async (uploadUrl: string, file: File): Promise<void> => {\n const response = await fetch(uploadUrl, {\n method: 'PUT',\n headers: { 'Content-Type': file.type },\n body: file,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to upload file to storage: ${response.statusText}`);\n }\n};\n\n/**\n * Confirms that files have been uploaded to S3 and creates asset metadata records.\n * @param params - orgId, optional brandId, and S3 asset keys from request-upload\n * @returns The created asset records\n */\nexport const confirmUpload = async (params: ConfirmUploadParams): Promise<UploadAssetResponse> => {\n const { orgId, brandId, assetKeys } = params;\n\n if (!orgId) {\n throw new Error('Organization ID is required to confirm upload');\n }\n\n const baseUrl = getAssetManagementApiUrl();\n const url = `${baseUrl}/orgs/${encodeURIComponent(orgId)}/assets/confirm-upload`;\n\n const body: { assetKeys: string[]; brandId?: string } = { assetKeys };\n if (brandId !== undefined) {\n body.brandId = brandId;\n }\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n credentials: 'include',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n let message = response.statusText;\n try {\n const responseBody = (await response.json()) as { error?: { message?: string }; Message?: string };\n message = responseBody?.error?.message ?? responseBody?.Message ?? message;\n } catch {\n // ignore JSON parse failure\n }\n throw new Error(message || 'Failed to confirm upload');\n }\n\n return (await response.json()) as UploadAssetResponse;\n } catch (error: unknown) {\n const errorMessage = getErrorMessage(error, 'Failed to confirm upload');\n throw new Error(errorMessage);\n }\n};\n\n/**\n * Uploads assets via the presigned S3 URL flow:\n * 1. Request presigned URLs from the service\n * 2. PUT each file directly to its S3 presigned URL (in parallel)\n * 3. Confirm uploads to persist asset metadata\n *\n * Supports files up to 20 MB\n * @param params - Upload parameters containing orgId, brandId, and files\n * @returns Promise resolving to the created asset records\n */\nexport const uploadAssetViaPresignedUrl = async (params: UploadAssetParams): Promise<UploadAssetResponse> => {\n const { orgId, brandId, files } = params;\n\n if (!orgId) {\n throw new Error('Organization ID is required to upload assets');\n }\n\n if (!files || files.length === 0) {\n throw new Error('At least one file is required to upload');\n }\n\n // Sanitize filenames (spaces → dashes) before requesting presigned URLs\n const sanitizedFiles = files.map(sanitizeFile);\n\n try {\n // Step 1: Get presigned S3 PUT URLs\n const { data: presignedItems } = await requestUpload({ orgId, brandId, files: sanitizedFiles });\n\n // Step 2: Align file names with the asset keys returned by the server.\n // The server may have deduplicated filenames (e.g. my-file.jpg → my-file-1.jpg),\n // so rename any file whose name doesn't match the end of its asset key.\n const alignedFiles = sanitizedFiles.map((file, index) => {\n const item = presignedItems[index];\n if (!item) {\n throw new Error(`No presigned URL returned for file: ${file.name}`);\n }\n const keyFileName = item.assetKey.split('/').pop() ?? file.name;\n if (keyFileName === file.name) {\n return file;\n }\n return new File([file], keyFileName, { type: file.type });\n });\n\n // Step 3: Upload all files in parallel to their respective presigned URLs\n await Promise.all(\n alignedFiles.map((file, index) => {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return uploadFileToPresignedUrl(presignedItems[index]!.uploadUrl, file);\n }),\n );\n\n // Step 4: Confirm uploads and get asset metadata\n const assetKeys = presignedItems.map((item) => item.assetKey);\n return await confirmUpload({ orgId, brandId, assetKeys });\n } catch (error: unknown) {\n const errorMessage = getErrorMessage(error, 'Failed to upload assets');\n throw new Error(errorMessage);\n }\n};\n"],"names":["getAssetManagementApiUrl","isProd","window","location","host","includes","getAssets","async","orgId","brandId","apiUrl","brandIdQueryParam","buildApiUrl","Error","response","fetch","method","credentials","ok","statusText","json","uploadAsset","params","files","length","sanitizedFiles","map","sanitizeFile","uploadUrl","encodeURIComponent","formData","FormData","file","append","undefined","body","message","error","Message","errorMessage","getErrorMessage","requestUpload","url","fileName","name","contentType","type","headers","JSON","stringify","responseBody","uploadFileToPresignedUrl","confirmUpload","assetKeys","uploadAssetViaPresignedUrl","data","presignedItems","alignedFiles","index","item","keyFileName","assetKey","split","pop","File","Promise","all"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";require("../../node_modules/.pnpm/msw@2.14.6_@types_node@20.19.41_typescript@5.4.5/node_modules/msw/lib/core/index.cjs.js");var e=require("../../components/organisms/AssetManager/__mocks__/mockAssets.cjs.js"),s=require("../../node_modules/.pnpm/msw@2.14.6_@types_node@20.19.41_typescript@5.4.5/node_modules/msw/lib/core/http.cjs.js"),t=require("../../node_modules/.pnpm/msw@2.14.6_@types_node@20.19.41_typescript@5.4.5/node_modules/msw/lib/core/HttpResponse.cjs.js");const o=[...[s.http.get("*/assets/orgs/:orgId/assets",({request:s,params:o})=>(console.log("[MSW] Intercepted GET assets request:",s.url,"orgId:",o.orgId),t.HttpResponse.json(e.mockAssets))),s.http.post("*/assets/orgs/:orgId/assets/upload",async({request:s,params:o})=>{console.log("[MSW] Intercepted POST upload request:",s.url,"orgId:",o.orgId),await new Promise(e=>setTimeout(e,2e3));const r=(await s.formData()).getAll("files").map(s=>e.createMockAsset({id:"asset_e3454351fw5",fileName:s.name,contentType:s.type||"image/jpeg",createdBy:"Test User",updatedBy:"Test User"}));return t.HttpResponse.json(r)})]];exports.handlers=o;
1
+ "use strict";require("../../node_modules/.pnpm/msw@2.14.6_@types_node@20.19.41_typescript@5.4.5/node_modules/msw/lib/core/index.cjs.js");var e=require("../../components/organisms/AssetManager/__mocks__/mockAssets.cjs.js"),s=require("../../node_modules/.pnpm/msw@2.14.6_@types_node@20.19.41_typescript@5.4.5/node_modules/msw/lib/core/http.cjs.js"),t=require("../../node_modules/.pnpm/msw@2.14.6_@types_node@20.19.41_typescript@5.4.5/node_modules/msw/lib/core/HttpResponse.cjs.js");const o="https://s3.mock.amazonaws.com/mock-flipdish-assets",r=[...[s.http.get("*/assets/orgs/:orgId/assets",({request:s,params:o})=>(console.log("[MSW] Intercepted GET assets request:",s.url,"orgId:",o.orgId),t.HttpResponse.json(e.mockAssets))),s.http.post("*/assets/orgs/:orgId/assets/upload",async({request:s,params:o})=>{console.log("[MSW] Intercepted POST upload request:",s.url,"orgId:",o.orgId),await new Promise(e=>setTimeout(e,2e3));const r=(await s.formData()).getAll("files").map(s=>e.createMockAsset({id:"asset_e3454351fw5",fileName:s.name,contentType:s.type||"image/jpeg",createdBy:"Test User",updatedBy:"Test User"}));return t.HttpResponse.json(r)}),s.http.post("*/assets/orgs/:orgId/assets/request-upload",async({request:e,params:s})=>{console.log("[MSW] Intercepted POST request-upload:",e.url,"orgId:",s.orgId);const r=await e.json(),a=String(s.orgId),n=r.files.map(e=>({uploadUrl:`${o}/${a}/${e.fileName}`,assetKey:`assets/${a}/${e.fileName}`,expiresIn:300}));return t.HttpResponse.json({data:n})}),s.http.put(`${o}/*`,async()=>(await new Promise(e=>setTimeout(e,2e3)),new t.HttpResponse(null,{status:200}))),s.http.post("*/assets/orgs/:orgId/assets/confirm-upload",async({request:s,params:o})=>{console.log("[MSW] Intercepted POST confirm-upload:",s.url,"orgId:",o.orgId);const r=(await s.json()).assetKeys.map(s=>{const t=s.split("/").pop()??"unknown";return e.createMockAsset({id:`asset_${Date.now()}_${t}`,fileName:t,contentType:"image/jpeg",createdBy:"Current User",updatedBy:"Current User"})});return t.HttpResponse.json({data:r})})]];exports.MOCK_S3_BASE_URL=o,exports.handlers=r;
2
2
  //# sourceMappingURL=handlers.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handlers.cjs.js","sources":["../../../src/mocks/msw/handlers.ts"],"sourcesContent":["import { http, HttpResponse } from 'msw';\n\nimport { createMockAsset, mockAssets } from '../../components/organisms/AssetManager/__mocks__/mockAssets';\n\n/** Mock delay (ms) for upload so loading indicator is visible in Storybook */\nconst UPLOAD_MOCK_DELAY_MS = 2000;\n\nconst assetManagementHandlers = [\n // GET assets handler\n http.get('*/assets/orgs/:orgId/assets', ({ request, params }) => {\n // eslint-disable-next-line no-console\n console.log('[MSW] Intercepted GET assets request:', request.url, 'orgId:', params['orgId']);\n return HttpResponse.json(mockAssets);\n }),\n\n // POST upload handler\n http.post('*/assets/orgs/:orgId/assets/upload', async ({ request, params }) => {\n // eslint-disable-next-line no-console\n console.log('[MSW] Intercepted POST upload request:', request.url, 'orgId:', params['orgId']);\n await new Promise((resolve) => setTimeout(resolve, UPLOAD_MOCK_DELAY_MS));\n const formData = await request.formData();\n const files = formData.getAll('files') as File[];\n\n const uploadedAssets = files.map((file) =>\n createMockAsset({\n id: `asset_e3454351fw5`,\n fileName: file.name,\n contentType: file.type || 'image/jpeg',\n createdBy: 'Test User',\n updatedBy: 'Test User',\n }),\n );\n\n return HttpResponse.json(uploadedAssets);\n }),\n];\n\nexport const handlers = [...assetManagementHandlers];\n"],"names":["handlers","http","get","request","params","console","log","url","HttpResponse","json","mockAssets","post","async","Promise","resolve","setTimeout","uploadedAssets","formData","getAll","map","file","createMockAsset","id","fileName","name","contentType","type","createdBy","updatedBy"],"mappings":"geAKA,MAgCaA,EAAW,IA9BQ,CAE9BC,EAAAA,KAAKC,IAAI,8BAA+B,EAAGC,UAASC,aAElDC,QAAQC,IAAI,wCAAyCH,EAAQI,IAAK,SAAUH,EAAc,OACnFI,EAAAA,aAAaC,KAAKC,gBAI3BT,EAAAA,KAAKU,KAAK,qCAAsCC,OAAST,UAASC,aAEhEC,QAAQC,IAAI,yCAA0CH,EAAQI,IAAK,SAAUH,EAAc,aACrF,IAAIS,QAASC,GAAYC,WAAWD,EAdjB,MAezB,MAGME,SAHiBb,EAAQc,YACRC,OAAO,SAEDC,IAAKC,GAChCC,EAAAA,gBAAgB,CACdC,GAAI,oBACJC,SAAUH,EAAKI,KACfC,YAAaL,EAAKM,MAAQ,aAC1BC,UAAW,YACXC,UAAW,eAIf,OAAOpB,EAAAA,aAAaC,KAAKO"}
1
+ {"version":3,"file":"handlers.cjs.js","sources":["../../../src/mocks/msw/handlers.ts"],"sourcesContent":["import { http, HttpResponse } from 'msw';\n\nimport { createMockAsset, mockAssets } from '../../components/organisms/AssetManager/__mocks__/mockAssets';\n\n/** Mock delay (ms) for upload so loading indicator is visible in Storybook */\nconst UPLOAD_MOCK_DELAY_MS = 2000;\n\n/**\n * Base URL used in mock presigned S3 URLs so MSW can intercept the PUT requests.\n * The request-upload handler returns URLs under this base.\n */\nexport const MOCK_S3_BASE_URL = 'https://s3.mock.amazonaws.com/mock-flipdish-assets';\n\nconst assetManagementHandlers = [\n // GET assets handler\n http.get('*/assets/orgs/:orgId/assets', ({ request, params }) => {\n // eslint-disable-next-line no-console\n console.log('[MSW] Intercepted GET assets request:', request.url, 'orgId:', params['orgId']);\n return HttpResponse.json(mockAssets);\n }),\n\n // POST upload handler (legacy multipart form flow)\n http.post('*/assets/orgs/:orgId/assets/upload', async ({ request, params }) => {\n // eslint-disable-next-line no-console\n console.log('[MSW] Intercepted POST upload request:', request.url, 'orgId:', params['orgId']);\n await new Promise((resolve) => setTimeout(resolve, UPLOAD_MOCK_DELAY_MS));\n const formData = await request.formData();\n const files = formData.getAll('files') as File[];\n\n const uploadedAssets = files.map((file) =>\n createMockAsset({\n id: `asset_e3454351fw5`,\n fileName: file.name,\n contentType: file.type || 'image/jpeg',\n createdBy: 'Test User',\n updatedBy: 'Test User',\n }),\n );\n\n return HttpResponse.json(uploadedAssets);\n }),\n\n // POST request-upload handler (presigned URL flow — step 1)\n http.post('*/assets/orgs/:orgId/assets/request-upload', async ({ request, params }) => {\n // eslint-disable-next-line no-console\n console.log('[MSW] Intercepted POST request-upload:', request.url, 'orgId:', params['orgId']);\n const body = (await request.json()) as {\n files: Array<{ fileName: string; contentType: string }>;\n brandId?: string;\n };\n const orgId = String(params['orgId']);\n\n const data = body.files.map((file) => ({\n uploadUrl: `${MOCK_S3_BASE_URL}/${orgId}/${file.fileName}`,\n assetKey: `assets/${orgId}/${file.fileName}`,\n expiresIn: 300,\n }));\n\n return HttpResponse.json({ data });\n }),\n\n // PUT presigned S3 URL handler (presigned URL flow — step 2)\n http.put(`${MOCK_S3_BASE_URL}/*`, async () => {\n await new Promise((resolve) => setTimeout(resolve, UPLOAD_MOCK_DELAY_MS));\n return new HttpResponse(null, { status: 200 });\n }),\n\n // POST confirm-upload handler (presigned URL flow — step 3)\n http.post('*/assets/orgs/:orgId/assets/confirm-upload', async ({ request, params }) => {\n // eslint-disable-next-line no-console\n console.log('[MSW] Intercepted POST confirm-upload:', request.url, 'orgId:', params['orgId']);\n const body = (await request.json()) as { assetKeys: string[]; brandId?: string };\n\n const uploadedAssets = body.assetKeys.map((key) => {\n const fileName = key.split('/').pop() ?? 'unknown';\n return createMockAsset({\n id: `asset_${Date.now()}_${fileName}`,\n fileName,\n contentType: 'image/jpeg',\n createdBy: 'Current User',\n updatedBy: 'Current User',\n });\n });\n\n return HttpResponse.json({ data: uploadedAssets });\n }),\n];\n\nexport const handlers = [...assetManagementHandlers];\n"],"names":["MOCK_S3_BASE_URL","handlers","http","get","request","params","console","log","url","HttpResponse","json","mockAssets","post","async","Promise","resolve","setTimeout","uploadedAssets","formData","getAll","map","file","createMockAsset","id","fileName","name","contentType","type","createdBy","updatedBy","body","orgId","String","data","files","uploadUrl","assetKey","expiresIn","put","status","assetKeys","key","split","pop","Date","now"],"mappings":"geAKA,MAMaA,EAAmB,qDA6EnBC,EAAW,IA3EQ,CAE9BC,EAAAA,KAAKC,IAAI,8BAA+B,EAAGC,UAASC,aAElDC,QAAQC,IAAI,wCAAyCH,EAAQI,IAAK,SAAUH,EAAc,OACnFI,EAAAA,aAAaC,KAAKC,gBAI3BT,EAAAA,KAAKU,KAAK,qCAAsCC,OAAST,UAASC,aAEhEC,QAAQC,IAAI,yCAA0CH,EAAQI,IAAK,SAAUH,EAAc,aACrF,IAAIS,QAASC,GAAYC,WAAWD,EApBjB,MAqBzB,MAGME,SAHiBb,EAAQc,YACRC,OAAO,SAEDC,IAAKC,GAChCC,EAAAA,gBAAgB,CACdC,GAAI,oBACJC,SAAUH,EAAKI,KACfC,YAAaL,EAAKM,MAAQ,aAC1BC,UAAW,YACXC,UAAW,eAIf,OAAOpB,EAAAA,aAAaC,KAAKO,KAI3Bf,EAAAA,KAAKU,KAAK,6CAA8CC,OAAST,UAASC,aAExEC,QAAQC,IAAI,yCAA0CH,EAAQI,IAAK,SAAUH,EAAc,OAC3F,MAAMyB,QAAc1B,EAAQM,OAItBqB,EAAQC,OAAO3B,EAAc,OAE7B4B,EAAOH,EAAKI,MAAMd,IAAKC,IAAI,CAC/Bc,UAAW,GAAGnC,KAAoB+B,KAASV,EAAKG,WAChDY,SAAU,UAAUL,KAASV,EAAKG,WAClCa,UAAW,OAGb,OAAO5B,eAAaC,KAAK,CAAEuB,WAI7B/B,EAAAA,KAAKoC,IAAI,GAAGtC,MAAsBa,gBAC1B,IAAIC,QAASC,GAAYC,WAAWD,EA1DjB,MA2DlB,IAAIN,EAAAA,aAAa,KAAM,CAAE8B,OAAQ,QAI1CrC,EAAAA,KAAKU,KAAK,6CAA8CC,OAAST,UAASC,aAExEC,QAAQC,IAAI,yCAA0CH,EAAQI,IAAK,SAAUH,EAAc,OAC3F,MAEMY,SAFcb,EAAQM,QAEA8B,UAAUpB,IAAKqB,IACzC,MAAMjB,EAAWiB,EAAIC,MAAM,KAAKC,OAAS,UACzC,OAAOrB,kBAAgB,CACrBC,GAAI,SAASqB,KAAKC,SAASrB,IAC3BA,WACAE,YAAa,aACbE,UAAW,eACXC,UAAW,mBAIf,OAAOpB,EAAAA,aAAaC,KAAK,CAAEuB,KAAMhB"}
@@ -1,5 +1,10 @@
1
1
  import { HttpHandler } from '../../node_modules/.pnpm/msw@2.14.6_@types_node@20.19.41_typescript@5.4.5/node_modules/msw/lib/core/handlers/HttpHandler.d.js';
2
2
 
3
+ /**
4
+ * Base URL used in mock presigned S3 URLs so MSW can intercept the PUT requests.
5
+ * The request-upload handler returns URLs under this base.
6
+ */
7
+ declare const MOCK_S3_BASE_URL = "https://s3.mock.amazonaws.com/mock-flipdish-assets";
3
8
  declare const handlers: HttpHandler[];
4
9
 
5
- export { handlers };
10
+ export { MOCK_S3_BASE_URL, handlers };
@@ -1,2 +1,2 @@
1
- import"../../node_modules/.pnpm/msw@2.14.6_@types_node@20.19.41_typescript@5.4.5/node_modules/msw/lib/core/index.js";import{mockAssets as e,createMockAsset as s}from"../../components/organisms/AssetManager/__mocks__/mockAssets.js";import{http as o}from"../../node_modules/.pnpm/msw@2.14.6_@types_node@20.19.41_typescript@5.4.5/node_modules/msw/lib/core/http.js";import{HttpResponse as t}from"../../node_modules/.pnpm/msw@2.14.6_@types_node@20.19.41_typescript@5.4.5/node_modules/msw/lib/core/HttpResponse.js";const r=[...[o.get("*/assets/orgs/:orgId/assets",({request:s,params:o})=>(console.log("[MSW] Intercepted GET assets request:",s.url,"orgId:",o.orgId),t.json(e))),o.post("*/assets/orgs/:orgId/assets/upload",async({request:e,params:o})=>{console.log("[MSW] Intercepted POST upload request:",e.url,"orgId:",o.orgId),await new Promise(e=>setTimeout(e,2e3));const r=(await e.formData()).getAll("files").map(e=>s({id:"asset_e3454351fw5",fileName:e.name,contentType:e.type||"image/jpeg",createdBy:"Test User",updatedBy:"Test User"}));return t.json(r)})]];export{r as handlers};
1
+ import"../../node_modules/.pnpm/msw@2.14.6_@types_node@20.19.41_typescript@5.4.5/node_modules/msw/lib/core/index.js";import{mockAssets as e,createMockAsset as s}from"../../components/organisms/AssetManager/__mocks__/mockAssets.js";import{http as t}from"../../node_modules/.pnpm/msw@2.14.6_@types_node@20.19.41_typescript@5.4.5/node_modules/msw/lib/core/http.js";import{HttpResponse as o}from"../../node_modules/.pnpm/msw@2.14.6_@types_node@20.19.41_typescript@5.4.5/node_modules/msw/lib/core/HttpResponse.js";const r="https://s3.mock.amazonaws.com/mock-flipdish-assets",a=[...[t.get("*/assets/orgs/:orgId/assets",({request:s,params:t})=>(console.log("[MSW] Intercepted GET assets request:",s.url,"orgId:",t.orgId),o.json(e))),t.post("*/assets/orgs/:orgId/assets/upload",async({request:e,params:t})=>{console.log("[MSW] Intercepted POST upload request:",e.url,"orgId:",t.orgId),await new Promise(e=>setTimeout(e,2e3));const r=(await e.formData()).getAll("files").map(e=>s({id:"asset_e3454351fw5",fileName:e.name,contentType:e.type||"image/jpeg",createdBy:"Test User",updatedBy:"Test User"}));return o.json(r)}),t.post("*/assets/orgs/:orgId/assets/request-upload",async({request:e,params:s})=>{console.log("[MSW] Intercepted POST request-upload:",e.url,"orgId:",s.orgId);const t=await e.json(),a=String(s.orgId),n=t.files.map(e=>({uploadUrl:`${r}/${a}/${e.fileName}`,assetKey:`assets/${a}/${e.fileName}`,expiresIn:300}));return o.json({data:n})}),t.put(`${r}/*`,async()=>(await new Promise(e=>setTimeout(e,2e3)),new o(null,{status:200}))),t.post("*/assets/orgs/:orgId/assets/confirm-upload",async({request:e,params:t})=>{console.log("[MSW] Intercepted POST confirm-upload:",e.url,"orgId:",t.orgId);const r=(await e.json()).assetKeys.map(e=>{const t=e.split("/").pop()??"unknown";return s({id:`asset_${Date.now()}_${t}`,fileName:t,contentType:"image/jpeg",createdBy:"Current User",updatedBy:"Current User"})});return o.json({data:r})})]];export{r as MOCK_S3_BASE_URL,a as handlers};
2
2
  //# sourceMappingURL=handlers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handlers.js","sources":["../../../src/mocks/msw/handlers.ts"],"sourcesContent":["import { http, HttpResponse } from 'msw';\n\nimport { createMockAsset, mockAssets } from '../../components/organisms/AssetManager/__mocks__/mockAssets';\n\n/** Mock delay (ms) for upload so loading indicator is visible in Storybook */\nconst UPLOAD_MOCK_DELAY_MS = 2000;\n\nconst assetManagementHandlers = [\n // GET assets handler\n http.get('*/assets/orgs/:orgId/assets', ({ request, params }) => {\n // eslint-disable-next-line no-console\n console.log('[MSW] Intercepted GET assets request:', request.url, 'orgId:', params['orgId']);\n return HttpResponse.json(mockAssets);\n }),\n\n // POST upload handler\n http.post('*/assets/orgs/:orgId/assets/upload', async ({ request, params }) => {\n // eslint-disable-next-line no-console\n console.log('[MSW] Intercepted POST upload request:', request.url, 'orgId:', params['orgId']);\n await new Promise((resolve) => setTimeout(resolve, UPLOAD_MOCK_DELAY_MS));\n const formData = await request.formData();\n const files = formData.getAll('files') as File[];\n\n const uploadedAssets = files.map((file) =>\n createMockAsset({\n id: `asset_e3454351fw5`,\n fileName: file.name,\n contentType: file.type || 'image/jpeg',\n createdBy: 'Test User',\n updatedBy: 'Test User',\n }),\n );\n\n return HttpResponse.json(uploadedAssets);\n }),\n];\n\nexport const handlers = [...assetManagementHandlers];\n"],"names":["handlers","http","get","request","params","console","log","url","HttpResponse","json","mockAssets","post","async","Promise","resolve","setTimeout","uploadedAssets","formData","getAll","map","file","createMockAsset","id","fileName","name","contentType","type","createdBy","updatedBy"],"mappings":"6fAKA,MAgCaA,EAAW,IA9BQ,CAE9BC,EAAKC,IAAI,8BAA+B,EAAGC,UAASC,aAElDC,QAAQC,IAAI,wCAAyCH,EAAQI,IAAK,SAAUH,EAAc,OACnFI,EAAaC,KAAKC,KAI3BT,EAAKU,KAAK,qCAAsCC,OAAST,UAASC,aAEhEC,QAAQC,IAAI,yCAA0CH,EAAQI,IAAK,SAAUH,EAAc,aACrF,IAAIS,QAASC,GAAYC,WAAWD,EAdjB,MAezB,MAGME,SAHiBb,EAAQc,YACRC,OAAO,SAEDC,IAAKC,GAChCC,EAAgB,CACdC,GAAI,oBACJC,SAAUH,EAAKI,KACfC,YAAaL,EAAKM,MAAQ,aAC1BC,UAAW,YACXC,UAAW,eAIf,OAAOpB,EAAaC,KAAKO"}
1
+ {"version":3,"file":"handlers.js","sources":["../../../src/mocks/msw/handlers.ts"],"sourcesContent":["import { http, HttpResponse } from 'msw';\n\nimport { createMockAsset, mockAssets } from '../../components/organisms/AssetManager/__mocks__/mockAssets';\n\n/** Mock delay (ms) for upload so loading indicator is visible in Storybook */\nconst UPLOAD_MOCK_DELAY_MS = 2000;\n\n/**\n * Base URL used in mock presigned S3 URLs so MSW can intercept the PUT requests.\n * The request-upload handler returns URLs under this base.\n */\nexport const MOCK_S3_BASE_URL = 'https://s3.mock.amazonaws.com/mock-flipdish-assets';\n\nconst assetManagementHandlers = [\n // GET assets handler\n http.get('*/assets/orgs/:orgId/assets', ({ request, params }) => {\n // eslint-disable-next-line no-console\n console.log('[MSW] Intercepted GET assets request:', request.url, 'orgId:', params['orgId']);\n return HttpResponse.json(mockAssets);\n }),\n\n // POST upload handler (legacy multipart form flow)\n http.post('*/assets/orgs/:orgId/assets/upload', async ({ request, params }) => {\n // eslint-disable-next-line no-console\n console.log('[MSW] Intercepted POST upload request:', request.url, 'orgId:', params['orgId']);\n await new Promise((resolve) => setTimeout(resolve, UPLOAD_MOCK_DELAY_MS));\n const formData = await request.formData();\n const files = formData.getAll('files') as File[];\n\n const uploadedAssets = files.map((file) =>\n createMockAsset({\n id: `asset_e3454351fw5`,\n fileName: file.name,\n contentType: file.type || 'image/jpeg',\n createdBy: 'Test User',\n updatedBy: 'Test User',\n }),\n );\n\n return HttpResponse.json(uploadedAssets);\n }),\n\n // POST request-upload handler (presigned URL flow — step 1)\n http.post('*/assets/orgs/:orgId/assets/request-upload', async ({ request, params }) => {\n // eslint-disable-next-line no-console\n console.log('[MSW] Intercepted POST request-upload:', request.url, 'orgId:', params['orgId']);\n const body = (await request.json()) as {\n files: Array<{ fileName: string; contentType: string }>;\n brandId?: string;\n };\n const orgId = String(params['orgId']);\n\n const data = body.files.map((file) => ({\n uploadUrl: `${MOCK_S3_BASE_URL}/${orgId}/${file.fileName}`,\n assetKey: `assets/${orgId}/${file.fileName}`,\n expiresIn: 300,\n }));\n\n return HttpResponse.json({ data });\n }),\n\n // PUT presigned S3 URL handler (presigned URL flow — step 2)\n http.put(`${MOCK_S3_BASE_URL}/*`, async () => {\n await new Promise((resolve) => setTimeout(resolve, UPLOAD_MOCK_DELAY_MS));\n return new HttpResponse(null, { status: 200 });\n }),\n\n // POST confirm-upload handler (presigned URL flow — step 3)\n http.post('*/assets/orgs/:orgId/assets/confirm-upload', async ({ request, params }) => {\n // eslint-disable-next-line no-console\n console.log('[MSW] Intercepted POST confirm-upload:', request.url, 'orgId:', params['orgId']);\n const body = (await request.json()) as { assetKeys: string[]; brandId?: string };\n\n const uploadedAssets = body.assetKeys.map((key) => {\n const fileName = key.split('/').pop() ?? 'unknown';\n return createMockAsset({\n id: `asset_${Date.now()}_${fileName}`,\n fileName,\n contentType: 'image/jpeg',\n createdBy: 'Current User',\n updatedBy: 'Current User',\n });\n });\n\n return HttpResponse.json({ data: uploadedAssets });\n }),\n];\n\nexport const handlers = [...assetManagementHandlers];\n"],"names":["MOCK_S3_BASE_URL","handlers","http","get","request","params","console","log","url","HttpResponse","json","mockAssets","post","async","Promise","resolve","setTimeout","uploadedAssets","formData","getAll","map","file","createMockAsset","id","fileName","name","contentType","type","createdBy","updatedBy","body","orgId","String","data","files","uploadUrl","assetKey","expiresIn","put","status","assetKeys","key","split","pop","Date","now"],"mappings":"6fAKA,MAMaA,EAAmB,qDA6EnBC,EAAW,IA3EQ,CAE9BC,EAAKC,IAAI,8BAA+B,EAAGC,UAASC,aAElDC,QAAQC,IAAI,wCAAyCH,EAAQI,IAAK,SAAUH,EAAc,OACnFI,EAAaC,KAAKC,KAI3BT,EAAKU,KAAK,qCAAsCC,OAAST,UAASC,aAEhEC,QAAQC,IAAI,yCAA0CH,EAAQI,IAAK,SAAUH,EAAc,aACrF,IAAIS,QAASC,GAAYC,WAAWD,EApBjB,MAqBzB,MAGME,SAHiBb,EAAQc,YACRC,OAAO,SAEDC,IAAKC,GAChCC,EAAgB,CACdC,GAAI,oBACJC,SAAUH,EAAKI,KACfC,YAAaL,EAAKM,MAAQ,aAC1BC,UAAW,YACXC,UAAW,eAIf,OAAOpB,EAAaC,KAAKO,KAI3Bf,EAAKU,KAAK,6CAA8CC,OAAST,UAASC,aAExEC,QAAQC,IAAI,yCAA0CH,EAAQI,IAAK,SAAUH,EAAc,OAC3F,MAAMyB,QAAc1B,EAAQM,OAItBqB,EAAQC,OAAO3B,EAAc,OAE7B4B,EAAOH,EAAKI,MAAMd,IAAKC,IAAI,CAC/Bc,UAAW,GAAGnC,KAAoB+B,KAASV,EAAKG,WAChDY,SAAU,UAAUL,KAASV,EAAKG,WAClCa,UAAW,OAGb,OAAO5B,EAAaC,KAAK,CAAEuB,WAI7B/B,EAAKoC,IAAI,GAAGtC,MAAsBa,gBAC1B,IAAIC,QAASC,GAAYC,WAAWD,EA1DjB,MA2DlB,IAAIN,EAAa,KAAM,CAAE8B,OAAQ,QAI1CrC,EAAKU,KAAK,6CAA8CC,OAAST,UAASC,aAExEC,QAAQC,IAAI,yCAA0CH,EAAQI,IAAK,SAAUH,EAAc,OAC3F,MAEMY,SAFcb,EAAQM,QAEA8B,UAAUpB,IAAKqB,IACzC,MAAMjB,EAAWiB,EAAIC,MAAM,KAAKC,OAAS,UACzC,OAAOrB,EAAgB,CACrBC,GAAI,SAASqB,KAAKC,SAASrB,IAC3BA,WACAE,YAAa,aACbE,UAAW,eACXC,UAAW,mBAIf,OAAOpB,EAAaC,KAAK,CAAEuB,KAAMhB"}
@@ -12,7 +12,7 @@ declare module '@mui/material/styles' {
12
12
  'text-error': string;
13
13
  'text-warning': string;
14
14
  'text-success': string;
15
- 'text-information': string;
15
+ 'text-ai': string;
16
16
  'text-inverse-strong': string;
17
17
  'text-inverse-weak': string;
18
18
  'text-inverse-disabled': string;
@@ -33,8 +33,7 @@ declare module '@mui/material/styles' {
33
33
  'stroke-warning-weak': string;
34
34
  'stroke-success-strong': string;
35
35
  'stroke-success-weak': string;
36
- 'stroke-information-strong': string;
37
- 'stroke-information-weak': string;
36
+ 'stroke-ai-strong': string;
38
37
  'stroke-ai-weak': string;
39
38
  'stroke-inverse-strong': string;
40
39
  'stroke-inverse-weak': string;
@@ -47,7 +46,6 @@ declare module '@mui/material/styles' {
47
46
  'icon-error': string;
48
47
  'icon-warning': string;
49
48
  'icon-success': string;
50
- 'icon-information': string;
51
49
  'icon-inverse': string;
52
50
  'icon-inverse-strong': string;
53
51
  'icon-inverse-disabled': string;
@@ -72,8 +70,7 @@ declare module '@mui/material/styles' {
72
70
  'fill-warning-weak': string;
73
71
  'fill-success-strong': string;
74
72
  'fill-success-weak': string;
75
- 'fill-information-strong': string;
76
- 'fill-information-weak': string;
73
+ 'fill-ai-strong': string;
77
74
  'fill-ai-weak': string;
78
75
  'fill-inverse-strong': string;
79
76
  'fill-inverse-weak': string;
@@ -115,7 +112,7 @@ declare module '@mui/material/styles' {
115
112
  'text-error'?: string;
116
113
  'text-warning'?: string;
117
114
  'text-success'?: string;
118
- 'text-information'?: string;
115
+ 'text-ai'?: string;
119
116
  'text-inverse-strong'?: string;
120
117
  'text-inverse-weak'?: string;
121
118
  'text-inverse-disabled'?: string;
@@ -136,8 +133,7 @@ declare module '@mui/material/styles' {
136
133
  'stroke-warning-weak'?: string;
137
134
  'stroke-success-strong'?: string;
138
135
  'stroke-success-weak'?: string;
139
- 'stroke-information-strong'?: string;
140
- 'stroke-information-weak'?: string;
136
+ 'stroke-ai-strong'?: string;
141
137
  'stroke-ai-weak'?: string;
142
138
  'stroke-inverse-strong'?: string;
143
139
  'stroke-inverse-weak'?: string;
@@ -150,7 +146,6 @@ declare module '@mui/material/styles' {
150
146
  'icon-error'?: string;
151
147
  'icon-warning'?: string;
152
148
  'icon-success'?: string;
153
- 'icon-information'?: string;
154
149
  'icon-inverse': string;
155
150
  'icon-inverse-strong'?: string;
156
151
  'icon-inverse-disabled'?: string;
@@ -175,8 +170,7 @@ declare module '@mui/material/styles' {
175
170
  'fill-warning-weak'?: string;
176
171
  'fill-success-strong'?: string;
177
172
  'fill-success-weak'?: string;
178
- 'fill-information-strong'?: string;
179
- 'fill-information-weak'?: string;
173
+ 'fill-ai-strong'?: string;
180
174
  'fill-ai-weak'?: string;
181
175
  'fill-inverse-strong'?: string;
182
176
  'fill-inverse-weak'?: string;
@@ -0,0 +1,2 @@
1
+ "use strict";var e=require("react/jsx-runtime");require("react");var i=require("@mui/material/Box"),t=require("@mui/material/Stack"),r=require("@mui/material/styles"),s=require("@mui/material/Typography"),a=require("./breakpoints.cjs.js");const n=r.styled(i)(({theme:e})=>({backgroundColor:e.palette.primary.main,borderRadius:"4px",height:"80px"})),l=r.styled(s)(({theme:e})=>({fontFamily:"monospace",overflow:"hidden",padding:e.spacing(1,2),textOverflow:"ellipsis",whiteSpace:"nowrap"})),o=r.styled(i)(({theme:e})=>({alignItems:"center",display:"grid",gap:e.spacing(.5),gridTemplateColumns:"280px 180px 100px 1fr",maxWidth:"1200px",width:"100%"})),p=r.styled(s)(({theme:e})=>({fontSize:"0.875rem",fontWeight:600,padding:e.spacing(1,2)})),d=({token:i,value:t,muiValue:r})=>{const s=parseInt(t);return e.jsxs(o,{children:[e.jsx(l,{title:r,children:r}),e.jsx(l,{title:i,children:i}),e.jsx(l,{title:t,children:t}),e.jsx(n,{sx:{width:.3*s}})]})};exports.BreakpointsVisualizer=()=>{const r=Object.entries(a.breakpoints).map(([e,i])=>{const t=Object.entries(a.breakpointValues).find(([e,t])=>t===parseInt(i))?.[0];return{muiValue:`theme.breakpoints.${t}`,token:e,value:i}});return e.jsxs(t,{spacing:4,sx:{maxWidth:"1200px",width:"100%"},children:[e.jsx(t,{spacing:1,children:e.jsx(s,{color:"text.secondary",variant:"body2",children:"Breakpoints define the responsive layout grid points. Use these values with theme.breakpoints.up() or theme.breakpoints.down() in your styles."})}),e.jsxs(i,{children:[e.jsxs(o,{sx:{mb:2},children:[e.jsx(p,{children:"Design token"}),e.jsx(p,{children:"Figma token"}),e.jsx(p,{children:"Size"}),e.jsx(p,{children:"Visual Scale"})]}),r.map(({token:i,value:t,muiValue:r})=>e.jsx(d,{muiValue:r,token:i,value:t},i))]})]})};
2
+ //# sourceMappingURL=BreakpointsVisualizer.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BreakpointsVisualizer.cjs.js","sources":["../../../../src/themes/tokens/breakpoints/BreakpointsVisualizer.tsx"],"sourcesContent":["import React from 'react';\n\nimport Box from '@mui/material/Box';\nimport Stack from '@mui/material/Stack';\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\n\nimport { breakpoints, breakpointValues } from './breakpoints';\n\nconst BreakpointBar = styled(Box)(({ theme }) => ({\n backgroundColor: theme.palette.primary.main,\n borderRadius: '4px',\n height: '80px',\n}));\n\nconst Cell = styled(Typography)(({ theme }) => ({\n fontFamily: 'monospace',\n overflow: 'hidden',\n padding: theme.spacing(1, 2),\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n}));\n\nconst GridContainer = styled(Box)(({ theme }) => ({\n alignItems: 'center',\n display: 'grid',\n gap: theme.spacing(0.5),\n gridTemplateColumns: '280px 180px 100px 1fr',\n maxWidth: '1200px',\n width: '100%',\n}));\n\nconst ColumnHeader = styled(Typography)(({ theme }) => ({\n fontSize: '0.875rem',\n fontWeight: 600,\n padding: theme.spacing(1, 2),\n}));\n\ninterface BreakpointRowProps {\n muiValue: string;\n token: string;\n value: string;\n}\n\nconst BreakpointRow = ({ token, value, muiValue }: BreakpointRowProps): React.ReactElement => {\n const numericValue = parseInt(value);\n const scale = 0.3;\n\n return (\n <GridContainer>\n <Cell title={muiValue}>{muiValue}</Cell>\n <Cell title={token}>{token}</Cell>\n <Cell title={value}>{value}</Cell>\n <BreakpointBar sx={{ width: numericValue * scale }} />\n </GridContainer>\n );\n};\n\nexport const BreakpointsVisualizer = (): React.ReactElement => {\n const breakpointData = Object.entries(breakpoints).map(([token, value]) => {\n const muiKey = Object.entries(breakpointValues).find(([_, size]) => size === parseInt(value))?.[0];\n return { muiValue: `theme.breakpoints.${muiKey}`, token, value };\n });\n\n return (\n <Stack spacing={4} sx={{ maxWidth: '1200px', width: '100%' }}>\n <Stack spacing={1}>\n <Typography color=\"text.secondary\" variant=\"body2\">\n Breakpoints define the responsive layout grid points. Use these values with theme.breakpoints.up()\n or theme.breakpoints.down() in your styles.\n </Typography>\n </Stack>\n <Box>\n <GridContainer sx={{ mb: 2 }}>\n <ColumnHeader>Design token</ColumnHeader>\n <ColumnHeader>Figma token</ColumnHeader>\n <ColumnHeader>Size</ColumnHeader>\n <ColumnHeader>Visual Scale</ColumnHeader>\n </GridContainer>\n {breakpointData.map(({ token, value, muiValue }) => (\n <BreakpointRow key={token} muiValue={muiValue} token={token} value={value} />\n ))}\n </Box>\n </Stack>\n );\n};\n"],"names":["BreakpointBar","styled","Box","theme","backgroundColor","palette","primary","main","borderRadius","height","Cell","Typography","fontFamily","overflow","padding","spacing","textOverflow","whiteSpace","GridContainer","alignItems","display","gap","gridTemplateColumns","maxWidth","width","ColumnHeader","fontSize","fontWeight","BreakpointRow","token","value","muiValue","numericValue","parseInt","_jsxs","children","_jsx","title","sx","breakpointData","Object","entries","breakpoints","map","muiKey","breakpointValues","find","_","size","Stack","color","variant","mb"],"mappings":"+OASA,MAAMA,EAAgBC,EAAAA,OAAOC,EAAPD,CAAY,EAAGE,YAAO,CAC1CC,gBAAiBD,EAAME,QAAQC,QAAQC,KACvCC,aAAc,MACdC,OAAQ,UAGJC,EAAOT,EAAAA,OAAOU,EAAPV,CAAmB,EAAGE,YAAO,CACxCS,WAAY,YACZC,SAAU,SACVC,QAASX,EAAMY,QAAQ,EAAG,GAC1BC,aAAc,WACdC,WAAY,YAGRC,EAAgBjB,EAAAA,OAAOC,EAAPD,CAAY,EAAGE,YAAO,CAC1CgB,WAAY,SACZC,QAAS,OACTC,IAAKlB,EAAMY,QAAQ,IACnBO,oBAAqB,wBACrBC,SAAU,SACVC,MAAO,UAGHC,EAAexB,EAAAA,OAAOU,EAAPV,CAAmB,EAAGE,YAAO,CAChDuB,SAAU,WACVC,WAAY,IACZb,QAASX,EAAMY,QAAQ,EAAG,MAStBa,EAAgB,EAAGC,QAAOC,QAAOC,eACrC,MAAMC,EAAeC,SAASH,GAG9B,OACEI,EAAAA,KAAChB,EAAa,CAAAiB,SAAA,CACZC,MAAC1B,EAAI,CAAC2B,MAAON,EAAQI,SAAGJ,IACxBK,EAAAA,IAAC1B,EAAI,CAAC2B,MAAOR,EAAKM,SAAGN,IACrBO,EAAAA,IAAC1B,EAAI,CAAC2B,MAAOP,WAAQA,IACrBM,EAAAA,IAACpC,EAAa,CAACsC,GAAI,CAAEd,MAPX,GAOkBQ,uCAKG,KACnC,MAAMO,EAAiBC,OAAOC,QAAQC,EAAAA,aAAaC,IAAI,EAAEd,EAAOC,MAC9D,MAAMc,EAASJ,OAAOC,QAAQI,EAAAA,kBAAkBC,KAAK,EAAEC,EAAGC,KAAUA,IAASf,SAASH,MAAU,GAChG,MAAO,CAAEC,SAAU,qBAAqBa,IAAUf,QAAOC,WAG3D,OACEI,EAAAA,KAACe,EAAK,CAAClC,QAAS,EAAGuB,GAAI,CAAEf,SAAU,SAAUC,MAAO,kBAClDY,EAAAA,IAACa,EAAK,CAAClC,QAAS,WACdqB,EAAAA,IAACzB,EAAU,CAACuC,MAAM,iBAAiBC,QAAQ,QAAOhB,SAAA,qJAKpDD,EAAAA,KAAChC,EAAG,CAAAiC,SAAA,CACFD,EAAAA,KAAChB,EAAa,CAACoB,GAAI,CAAEc,GAAI,GAAGjB,SAAA,CAC1BC,MAACX,EAAY,CAAAU,SAAA,iBACbC,EAAAA,IAACX,EAAY,CAAAU,SAAA,gBACbC,EAAAA,IAACX,EAAY,CAAAU,SAAA,SACbC,EAAAA,IAACX,gCAEFc,EAAeI,IAAI,EAAGd,QAAOC,QAAOC,cACnCK,EAAAA,IAACR,GAA0BG,SAAUA,EAAUF,MAAOA,EAAOC,MAAOA,GAAhDD"}
@@ -0,0 +1,5 @@
1
+ import react__default from 'react';
2
+
3
+ declare const BreakpointsVisualizer: () => react__default.ReactElement;
4
+
5
+ export { BreakpointsVisualizer };
@@ -0,0 +1,2 @@
1
+ import{jsxs as e,jsx as i}from"react/jsx-runtime";import"react";import t from"@mui/material/Box";import r from"@mui/material/Stack";import{styled as n}from"@mui/material/styles";import a from"@mui/material/Typography";import{breakpoints as o,breakpointValues as m}from"./breakpoints.js";const l=n(t)(({theme:e})=>({backgroundColor:e.palette.primary.main,borderRadius:"4px",height:"80px"})),p=n(a)(({theme:e})=>({fontFamily:"monospace",overflow:"hidden",padding:e.spacing(1,2),textOverflow:"ellipsis",whiteSpace:"nowrap"})),s=n(t)(({theme:e})=>({alignItems:"center",display:"grid",gap:e.spacing(.5),gridTemplateColumns:"280px 180px 100px 1fr",maxWidth:"1200px",width:"100%"})),d=n(a)(({theme:e})=>({fontSize:"0.875rem",fontWeight:600,padding:e.spacing(1,2)})),c=({token:t,value:r,muiValue:n})=>{const a=parseInt(r);return e(s,{children:[i(p,{title:n,children:n}),i(p,{title:t,children:t}),i(p,{title:r,children:r}),i(l,{sx:{width:.3*a}})]})},h=()=>{const n=Object.entries(o).map(([e,i])=>{const t=Object.entries(m).find(([e,t])=>t===parseInt(i))?.[0];return{muiValue:`theme.breakpoints.${t}`,token:e,value:i}});return e(r,{spacing:4,sx:{maxWidth:"1200px",width:"100%"},children:[i(r,{spacing:1,children:i(a,{color:"text.secondary",variant:"body2",children:"Breakpoints define the responsive layout grid points. Use these values with theme.breakpoints.up() or theme.breakpoints.down() in your styles."})}),e(t,{children:[e(s,{sx:{mb:2},children:[i(d,{children:"Design token"}),i(d,{children:"Figma token"}),i(d,{children:"Size"}),i(d,{children:"Visual Scale"})]}),n.map(({token:e,value:t,muiValue:r})=>i(c,{muiValue:r,token:e,value:t},e))]})]})};export{h as BreakpointsVisualizer};
2
+ //# sourceMappingURL=BreakpointsVisualizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BreakpointsVisualizer.js","sources":["../../../../src/themes/tokens/breakpoints/BreakpointsVisualizer.tsx"],"sourcesContent":["import React from 'react';\n\nimport Box from '@mui/material/Box';\nimport Stack from '@mui/material/Stack';\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\n\nimport { breakpoints, breakpointValues } from './breakpoints';\n\nconst BreakpointBar = styled(Box)(({ theme }) => ({\n backgroundColor: theme.palette.primary.main,\n borderRadius: '4px',\n height: '80px',\n}));\n\nconst Cell = styled(Typography)(({ theme }) => ({\n fontFamily: 'monospace',\n overflow: 'hidden',\n padding: theme.spacing(1, 2),\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n}));\n\nconst GridContainer = styled(Box)(({ theme }) => ({\n alignItems: 'center',\n display: 'grid',\n gap: theme.spacing(0.5),\n gridTemplateColumns: '280px 180px 100px 1fr',\n maxWidth: '1200px',\n width: '100%',\n}));\n\nconst ColumnHeader = styled(Typography)(({ theme }) => ({\n fontSize: '0.875rem',\n fontWeight: 600,\n padding: theme.spacing(1, 2),\n}));\n\ninterface BreakpointRowProps {\n muiValue: string;\n token: string;\n value: string;\n}\n\nconst BreakpointRow = ({ token, value, muiValue }: BreakpointRowProps): React.ReactElement => {\n const numericValue = parseInt(value);\n const scale = 0.3;\n\n return (\n <GridContainer>\n <Cell title={muiValue}>{muiValue}</Cell>\n <Cell title={token}>{token}</Cell>\n <Cell title={value}>{value}</Cell>\n <BreakpointBar sx={{ width: numericValue * scale }} />\n </GridContainer>\n );\n};\n\nexport const BreakpointsVisualizer = (): React.ReactElement => {\n const breakpointData = Object.entries(breakpoints).map(([token, value]) => {\n const muiKey = Object.entries(breakpointValues).find(([_, size]) => size === parseInt(value))?.[0];\n return { muiValue: `theme.breakpoints.${muiKey}`, token, value };\n });\n\n return (\n <Stack spacing={4} sx={{ maxWidth: '1200px', width: '100%' }}>\n <Stack spacing={1}>\n <Typography color=\"text.secondary\" variant=\"body2\">\n Breakpoints define the responsive layout grid points. Use these values with theme.breakpoints.up()\n or theme.breakpoints.down() in your styles.\n </Typography>\n </Stack>\n <Box>\n <GridContainer sx={{ mb: 2 }}>\n <ColumnHeader>Design token</ColumnHeader>\n <ColumnHeader>Figma token</ColumnHeader>\n <ColumnHeader>Size</ColumnHeader>\n <ColumnHeader>Visual Scale</ColumnHeader>\n </GridContainer>\n {breakpointData.map(({ token, value, muiValue }) => (\n <BreakpointRow key={token} muiValue={muiValue} token={token} value={value} />\n ))}\n </Box>\n </Stack>\n );\n};\n"],"names":["BreakpointBar","styled","Box","theme","backgroundColor","palette","primary","main","borderRadius","height","Cell","Typography","fontFamily","overflow","padding","spacing","textOverflow","whiteSpace","GridContainer","alignItems","display","gap","gridTemplateColumns","maxWidth","width","ColumnHeader","fontSize","fontWeight","BreakpointRow","token","value","muiValue","numericValue","parseInt","_jsxs","children","_jsx","title","sx","BreakpointsVisualizer","breakpointData","Object","entries","breakpoints","map","muiKey","breakpointValues","find","_","size","Stack","color","variant","mb"],"mappings":"+RASA,MAAMA,EAAgBC,EAAOC,EAAPD,CAAY,EAAGE,YAAO,CAC1CC,gBAAiBD,EAAME,QAAQC,QAAQC,KACvCC,aAAc,MACdC,OAAQ,UAGJC,EAAOT,EAAOU,EAAPV,CAAmB,EAAGE,YAAO,CACxCS,WAAY,YACZC,SAAU,SACVC,QAASX,EAAMY,QAAQ,EAAG,GAC1BC,aAAc,WACdC,WAAY,YAGRC,EAAgBjB,EAAOC,EAAPD,CAAY,EAAGE,YAAO,CAC1CgB,WAAY,SACZC,QAAS,OACTC,IAAKlB,EAAMY,QAAQ,IACnBO,oBAAqB,wBACrBC,SAAU,SACVC,MAAO,UAGHC,EAAexB,EAAOU,EAAPV,CAAmB,EAAGE,YAAO,CAChDuB,SAAU,WACVC,WAAY,IACZb,QAASX,EAAMY,QAAQ,EAAG,MAStBa,EAAgB,EAAGC,QAAOC,QAAOC,eACrC,MAAMC,EAAeC,SAASH,GAG9B,OACEI,EAAChB,EAAa,CAAAiB,SAAA,CACZC,EAAC1B,EAAI,CAAC2B,MAAON,EAAQI,SAAGJ,IACxBK,EAAC1B,EAAI,CAAC2B,MAAOR,EAAKM,SAAGN,IACrBO,EAAC1B,EAAI,CAAC2B,MAAOP,WAAQA,IACrBM,EAACpC,EAAa,CAACsC,GAAI,CAAEd,MAPX,GAOkBQ,SAKrBO,EAAwB,KACnC,MAAMC,EAAiBC,OAAOC,QAAQC,GAAaC,IAAI,EAAEf,EAAOC,MAC9D,MAAMe,EAASJ,OAAOC,QAAQI,GAAkBC,KAAK,EAAEC,EAAGC,KAAUA,IAAShB,SAASH,MAAU,GAChG,MAAO,CAAEC,SAAU,qBAAqBc,IAAUhB,QAAOC,WAG3D,OACEI,EAACgB,EAAK,CAACnC,QAAS,EAAGuB,GAAI,CAAEf,SAAU,SAAUC,MAAO,kBAClDY,EAACc,EAAK,CAACnC,QAAS,WACdqB,EAACzB,EAAU,CAACwC,MAAM,iBAAiBC,QAAQ,QAAOjB,SAAA,qJAKpDD,EAAChC,EAAG,CAAAiC,SAAA,CACFD,EAAChB,EAAa,CAACoB,GAAI,CAAEe,GAAI,GAAGlB,SAAA,CAC1BC,EAACX,EAAY,CAAAU,SAAA,iBACbC,EAACX,EAAY,CAAAU,SAAA,gBACbC,EAACX,EAAY,CAAAU,SAAA,SACbC,EAACX,gCAEFe,EAAeI,IAAI,EAAGf,QAAOC,QAAOC,cACnCK,EAACR,GAA0BG,SAAUA,EAAUF,MAAOA,EAAOC,MAAOA,GAAhDD"}
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("react/jsx-runtime"),r=require("@mui/material/Box"),o=require("@mui/material/Grid2"),t=require("@mui/material/Stack"),i=require("@mui/material/styles"),a=require("@mui/material/Typography");const s=i.styled(r)(({theme:e,colour:r})=>({width:"100%",height:100,backgroundColor:r,borderRadius:e.shape.borderRadius,border:"1px solid",borderColor:e.palette.semantic.stroke["stroke-weak"],marginBottom:e.spacing(2)})),l=({name:o,colour:t})=>e.jsxs(r,{sx:{textAlign:"center"},children:[e.jsx(s,{colour:t}),e.jsx(a,{display:"block",variant:"caption",children:o}),e.jsx(a,{color:"text.secondary",display:"block",variant:"caption",children:t})]}),n=i.styled(o)(()=>({width:800})),d=i.styled(t,{shouldForwardProp:e=>"inverse"!==e})(({theme:e,inverse:r})=>({alignItems:"center",border:"1px solid",borderColor:e.palette.semantic.stroke["stroke-weak"],borderRadius:"100px",padding:"6px",marginBottom:"10px",...r&&{backgroundColor:e.palette.semantic.background["background-inverse"],color:e.palette.semantic.text["text-inverse-strong"]}})),c=i.styled(r)(({theme:e,colour:r})=>({width:24,height:24,backgroundColor:r,borderRadius:"50%",marginRight:e.spacing(2),border:"1px solid",borderColor:e.palette.semantic.stroke["stroke-weak"]})),m=i.styled(a)(({theme:e})=>({marginBottom:e.spacing(2),paddingBottom:e.spacing(1),borderBottom:"1px solid",borderColor:e.palette.semantic.stroke["stroke-weak"]})),p=i.styled(r)({display:"flex",flexDirection:"column"}),u=({name:r,colour:o})=>e.jsxs(d,{direction:"row",inverse:r.includes("inverse"),spacing:2,children:[e.jsx(c,{colour:o}),e.jsx(a,{variant:"body2",children:r})]});exports.PrimitiveColourSwatch=l,exports.StyledColourSwatch=s,exports.StyledGrid=n,exports.createColourPrimitiveStory=(t,i)=>({render:()=>i?e.jsx(n,{container:!0,spacing:3,children:Object.entries(i).sort(([e],[r])=>parseInt(r)-parseInt(e)).map(([r,i])=>e.jsx(o,{size:2,children:e.jsx(l,{colour:i,name:`${t}-${r}`.toLowerCase()})},r))}):e.jsx(r,{children:"No colors available"})}),exports.createSemanticColourStory=(o,t)=>({render:()=>t?e.jsxs(e.Fragment,{children:[e.jsx(m,{variant:"h6",children:o.toUpperCase()}),e.jsx(p,{children:Object.entries(t).map(([r,o])=>e.jsx(u,{colour:o,name:r},r))})]}):e.jsx(r,{children:"No colors available"})});
1
+ "use strict";var e=require("react/jsx-runtime"),r=require("@mui/material/Box"),o=require("@mui/material/Grid2"),t=require("@mui/material/Stack"),i=require("@mui/material/styles"),s=require("@mui/material/Typography");const a=i.styled(r)(({theme:e,colour:r})=>({width:"100%",height:100,backgroundColor:r,borderRadius:e.shape.borderRadius,border:"1px solid",borderColor:e.palette.semantic.stroke["stroke-weak"],marginBottom:e.spacing(2)})),n=({name:o,colour:t})=>e.jsxs(r,{sx:{textAlign:"center"},children:[e.jsx(a,{colour:t}),e.jsx(s,{display:"block",variant:"caption",children:o}),e.jsx(s,{color:"text.secondary",display:"block",variant:"caption",children:t})]}),l=i.styled(o)(()=>({width:800,overflowX:"auto"})),d=i.styled(t,{shouldForwardProp:e=>"inverse"!==e})(({theme:e,inverse:r})=>({alignItems:"center",border:"1px solid",borderColor:e.palette.semantic.stroke["stroke-weak"],borderRadius:"100px",padding:"6px",marginBottom:"10px",...r&&{backgroundColor:e.palette.semantic.background["background-inverse"],color:e.palette.semantic.text["text-inverse-strong"]}})),c=i.styled(r)(({theme:e,colour:r})=>({width:24,height:24,backgroundColor:r,borderRadius:"50%",marginRight:e.spacing(2),border:"1px solid",borderColor:e.palette.semantic.stroke["stroke-weak"]})),x=i.styled(s)(({theme:e})=>({marginBottom:e.spacing(2),paddingBottom:e.spacing(1),borderBottom:"1px solid",borderColor:e.palette.semantic.stroke["stroke-weak"]})),p=i.styled(r)({display:"flex",flexDirection:"column"}),m=({name:r,colour:o})=>e.jsxs(d,{direction:"row",inverse:r.includes("inverse"),spacing:2,children:[e.jsx(c,{colour:o}),e.jsx(s,{variant:"body2",children:r})]});exports.PrimitiveColourSection=({title:o,description:t,codePattern:i,colours:a})=>e.jsxs(r,{sx:{mb:5},children:[e.jsx(s,{color:"text.secondary",sx:{mb:.5,fontWeight:600},variant:"h6",children:o}),t&&e.jsx(s,{color:"text.secondary",sx:{mb:1,maxWidth:600},variant:"body2",children:t}),i&&e.jsx(s,{component:"code",sx:{display:"inline-block",mb:2,px:.75,py:.25,borderRadius:.5,bgcolor:"semantic.fill.fill-weak",fontFamily:"monospace"},variant:"caption",children:i}),e.jsx(r,{sx:{display:"flex",flexWrap:"wrap",gap:2},children:Object.entries(a).map(([o,t])=>e.jsxs(r,{sx:{width:120},children:[e.jsx(r,{sx:{height:80,backgroundColor:t,borderRadius:1,border:"1px solid",borderColor:"semantic.stroke.stroke-weak",mb:1}}),e.jsx(s,{display:"block",fontWeight:600,variant:"caption",children:o}),e.jsx(s,{color:"text.secondary",display:"block",variant:"caption",children:t})]},o))})]}),exports.PrimitiveColourSwatch=n,exports.SemanticColourTable=({title:o,description:t,tokens:i})=>e.jsxs(r,{sx:{mb:6},children:[e.jsx(s,{color:"text.secondary",sx:{mb:.5,fontWeight:600},variant:"h5",children:o}),e.jsx(s,{color:"text.secondary",sx:{mb:3},variant:"body2",children:t}),e.jsxs(r,{sx:{display:"flex",pb:1.5,borderBottom:"1px solid",borderColor:"semantic.stroke.stroke-weak"},children:[e.jsx(s,{fontWeight:600,sx:{width:220,flexShrink:0},variant:"caption",children:"Design token"}),e.jsx(s,{fontWeight:600,sx:{flex:1},variant:"caption",children:"Usage"}),e.jsx(s,{fontWeight:600,sx:{width:220,flexShrink:0},variant:"caption",children:"Colour token"})]}),i.map(({token:o,usage:t,colour:i,primitive:a})=>e.jsxs(r,{sx:{display:"flex",alignItems:"center",py:2,borderBottom:"1px solid",borderColor:"semantic.stroke.stroke-weak"},children:[e.jsx(r,{sx:{width:220,flexShrink:0},children:e.jsx(s,{component:"code",sx:{px:1.5,py:.5,borderRadius:"100px",border:"1px solid",borderColor:"semantic.stroke.stroke-weak",fontFamily:"monospace"},variant:"caption",children:o})}),e.jsx(s,{color:"text.secondary",sx:{flex:1,pr:3},variant:"body2",children:t}),e.jsxs(r,{sx:{width:220,flexShrink:0,display:"flex",alignItems:"center",gap:1,...o.includes("inverse")&&{bgcolor:"semantic.background.background-inverse",px:1,py:.5,borderRadius:"100px"}},children:[e.jsx(r,{sx:{width:24,height:24,borderRadius:"50%",backgroundColor:i,border:"1px solid",borderColor:"semantic.stroke.stroke-weak",flexShrink:0}}),e.jsx(s,{component:"code",sx:{fontFamily:"monospace",...o.includes("inverse")&&{color:"semantic.text.text-inverse-strong"}},variant:"caption",children:a})]})]},o))]}),exports.StyledColourSwatch=a,exports.StyledGrid=l,exports.createColourPrimitiveStory=(t,i)=>({render:()=>i?e.jsx(l,{container:!0,spacing:3,children:Object.entries(i).sort(([e],[r])=>parseInt(r)-parseInt(e)).map(([r,i])=>e.jsx(o,{size:2,children:e.jsx(n,{colour:i,name:`${t}-${r}`.toLowerCase()})},r))}):e.jsx(r,{children:"No colors available"})}),exports.createSemanticColourStory=(o,t)=>({render:()=>t?e.jsxs(e.Fragment,{children:[e.jsx(x,{variant:"h6",children:o.toUpperCase()}),e.jsx(p,{children:Object.entries(t).map(([r,o])=>e.jsx(m,{colour:o,name:r},r))})]}):e.jsx(r,{children:"No colors available"})});
2
2
  //# sourceMappingURL=colours-stories-utils.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"colours-stories-utils.cjs.js","sources":["../../../../src/themes/tokens/colours/colours-stories-utils.tsx"],"sourcesContent":["import Box from '@mui/material/Box';\nimport Grid from '@mui/material/Grid2';\nimport Stack from '@mui/material/Stack';\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\n\nexport const StyledColourSwatch = styled(Box)<{ colour: string }>(({ theme, colour }) => ({\n width: '100%',\n height: 100,\n backgroundColor: colour,\n borderRadius: theme.shape.borderRadius,\n border: '1px solid',\n borderColor: theme.palette.semantic.stroke['stroke-weak'],\n marginBottom: theme.spacing(2),\n}));\n\nexport const PrimitiveColourSwatch = ({ name, colour }: { name: string; colour: string }) => (\n <Box sx={{ textAlign: 'center' }}>\n <StyledColourSwatch colour={colour} />\n <Typography display=\"block\" variant=\"caption\">\n {name}\n </Typography>\n <Typography color=\"text.secondary\" display=\"block\" variant=\"caption\">\n {colour}\n </Typography>\n </Box>\n);\n\nexport const StyledGrid = styled(Grid)(() => ({\n width: 800,\n}));\n\n// Helper function to create colour primitive stories\nexport const createColourPrimitiveStory = (colourGroup: string, colourObject: Record<string, string>) => {\n return {\n render: () => {\n if (!colourObject) return <Box>No colors available</Box>;\n\n return (\n <StyledGrid container spacing={3}>\n {Object.entries(colourObject)\n .sort(([a], [b]) => parseInt(b) - parseInt(a))\n .map(([shade, colour]) => (\n <Grid key={shade} size={2}>\n <PrimitiveColourSwatch colour={colour} name={`${colourGroup}-${shade}`.toLowerCase()} />\n </Grid>\n ))}\n </StyledGrid>\n );\n },\n };\n};\n\nconst StyledStack = styled(Stack, {\n shouldForwardProp: (prop) => prop !== 'inverse',\n})<{ inverse: boolean }>(({ theme, inverse }) => ({\n alignItems: 'center',\n border: '1px solid',\n borderColor: theme.palette.semantic.stroke['stroke-weak'],\n borderRadius: '100px',\n padding: '6px',\n marginBottom: '10px',\n ...(inverse && {\n backgroundColor: theme.palette.semantic.background['background-inverse'],\n color: theme.palette.semantic.text['text-inverse-strong'],\n }),\n}));\n\nconst StyledColourBox = styled(Box)<{ colour: string }>(({ theme, colour }) => ({\n width: 24,\n height: 24,\n backgroundColor: colour,\n borderRadius: '50%',\n marginRight: theme.spacing(2),\n border: '1px solid',\n borderColor: theme.palette.semantic.stroke['stroke-weak'],\n}));\n\nconst StyledCategoryTitle = styled(Typography)(({ theme }) => ({\n marginBottom: theme.spacing(2),\n paddingBottom: theme.spacing(1),\n borderBottom: '1px solid',\n borderColor: theme.palette.semantic.stroke['stroke-weak'],\n}));\n\nconst StyledColourContainer = styled(Box)({\n display: 'flex',\n flexDirection: 'column',\n});\n\nconst SemanticColourSwatch = ({ name, colour }: { name: string; colour: string }) => (\n <StyledStack direction=\"row\" inverse={name.includes('inverse')} spacing={2}>\n <StyledColourBox colour={colour} />\n <Typography variant=\"body2\">{name}</Typography>\n </StyledStack>\n);\n\n// Helper function to create semantic colour stories\nexport const createSemanticColourStory = (category: string, colourObject: Record<string, string>) => {\n return {\n render: () => {\n if (!colourObject) return <Box>No colors available</Box>;\n\n return (\n <>\n <StyledCategoryTitle variant=\"h6\">{category.toUpperCase()}</StyledCategoryTitle>\n <StyledColourContainer>\n {Object.entries(colourObject).map(([name, colour]) => (\n <SemanticColourSwatch key={name} colour={colour} name={name} />\n ))}\n </StyledColourContainer>\n </>\n );\n },\n };\n};\n"],"names":["StyledColourSwatch","styled","Box","theme","colour","width","height","backgroundColor","borderRadius","shape","border","borderColor","palette","semantic","stroke","marginBottom","spacing","PrimitiveColourSwatch","name","_jsxs","sx","textAlign","children","_jsx","Typography","display","variant","color","StyledGrid","Grid","StyledStack","Stack","shouldForwardProp","prop","inverse","alignItems","padding","background","text","StyledColourBox","marginRight","StyledCategoryTitle","paddingBottom","borderBottom","StyledColourContainer","flexDirection","SemanticColourSwatch","direction","includes","colourGroup","colourObject","render","container","Object","entries","sort","a","b","parseInt","map","shade","size","toLowerCase","category","_Fragment","toUpperCase"],"mappings":"yNAMO,MAAMA,EAAqBC,EAAAA,OAAOC,EAAPD,CAAgC,EAAGE,QAAOC,aAAQ,CAClFC,MAAO,OACPC,OAAQ,IACRC,gBAAiBH,EACjBI,aAAcL,EAAMM,MAAMD,aAC1BE,OAAQ,YACRC,YAAaR,EAAMS,QAAQC,SAASC,OAAO,eAC3CC,aAAcZ,EAAMa,QAAQ,MAGjBC,EAAwB,EAAGC,OAAMd,YAC5Ce,EAAAA,KAACjB,EAAG,CAACkB,GAAI,CAAEC,UAAW,UAAUC,SAAA,CAC9BC,MAACvB,EAAkB,CAACI,OAAQA,IAC5BmB,MAACC,EAAU,CAACC,QAAQ,QAAQC,QAAQ,UAASJ,SAC1CJ,IAEHK,EAAAA,IAACC,EAAU,CAACG,MAAM,iBAAiBF,QAAQ,QAAQC,QAAQ,UAASJ,SACjElB,OAKMwB,EAAa3B,EAAAA,OAAO4B,EAAP5B,CAAa,KAAA,CACrCI,MAAO,OAwBHyB,EAAc7B,EAAAA,OAAO8B,EAAO,CAChCC,kBAAoBC,GAAkB,YAATA,GADXhC,CAEK,EAAGE,QAAO+B,cAAS,CAC1CC,WAAY,SACZzB,OAAQ,YACRC,YAAaR,EAAMS,QAAQC,SAASC,OAAO,eAC3CN,aAAc,QACd4B,QAAS,MACTrB,aAAc,UACVmB,GAAW,CACb3B,gBAAiBJ,EAAMS,QAAQC,SAASwB,WAAW,sBACnDV,MAAOxB,EAAMS,QAAQC,SAASyB,KAAK,2BAIjCC,EAAkBtC,EAAAA,OAAOC,EAAPD,CAAgC,EAAGE,QAAOC,aAAQ,CACxEC,MAAO,GACPC,OAAQ,GACRC,gBAAiBH,EACjBI,aAAc,MACdgC,YAAarC,EAAMa,QAAQ,GAC3BN,OAAQ,YACRC,YAAaR,EAAMS,QAAQC,SAASC,OAAO,kBAGvC2B,EAAsBxC,EAAAA,OAAOuB,EAAPvB,CAAmB,EAAGE,YAAO,CACvDY,aAAcZ,EAAMa,QAAQ,GAC5B0B,cAAevC,EAAMa,QAAQ,GAC7B2B,aAAc,YACdhC,YAAaR,EAAMS,QAAQC,SAASC,OAAO,kBAGvC8B,EAAwB3C,EAAAA,OAAOC,EAAPD,CAAY,CACxCwB,QAAS,OACToB,cAAe,WAGXC,EAAuB,EAAG5B,OAAMd,YACpCe,EAAAA,KAACW,EAAW,CAACiB,UAAU,MAAMb,QAAShB,EAAK8B,SAAS,WAAYhC,QAAS,EAACM,SAAA,CACxEC,EAAAA,IAACgB,EAAe,CAACnC,OAAQA,IACzBmB,EAAAA,IAACC,EAAU,CAACE,QAAQ,iBAASR,4HA5DS,CAAC+B,EAAqBC,KACvD,CACLC,OAAQ,IACDD,EAGH3B,MAACK,EAAU,CAACwB,WAAS,EAACpC,QAAS,WAC5BqC,OAAOC,QAAQJ,GACbK,KAAK,EAAEC,IAAKC,KAAOC,SAASD,GAAKC,SAASF,IAC1CG,IAAI,EAAEC,EAAOxD,KACZmB,EAAAA,IAACM,EAAI,CAAagC,KAAM,EAACvC,SACvBC,EAAAA,IAACN,EAAqB,CAACb,OAAQA,EAAQc,KAAM,GAAG+B,KAAeW,IAAQE,iBAD9DF,MAPOrC,EAAAA,IAACrB,EAAG,CAAAoB,SAAA,4DA8DK,CAACyC,EAAkBb,KACnD,CACLC,OAAQ,IACDD,EAGH/B,EAAAA,KAAA6C,EAAAA,SAAA,CAAA1C,SAAA,CACEC,MAACkB,EAAmB,CAACf,QAAQ,KAAIJ,SAAEyC,EAASE,gBAC5C1C,EAAAA,IAACqB,EAAqB,CAAAtB,SACnB+B,OAAOC,QAAQJ,GAAcS,IAAI,EAAEzC,EAAMd,KACxCmB,EAAAA,IAACuB,EAAoB,CAAY1C,OAAQA,EAAQc,KAAMA,GAA5BA,SAPTK,EAAAA,IAACrB,EAAG,CAAAoB,SAAA"}
1
+ {"version":3,"file":"colours-stories-utils.cjs.js","sources":["../../../../src/themes/tokens/colours/colours-stories-utils.tsx"],"sourcesContent":["import Box from '@mui/material/Box';\nimport Grid from '@mui/material/Grid2';\nimport Stack from '@mui/material/Stack';\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\n\nexport const StyledColourSwatch = styled(Box)<{ colour: string }>(({ theme, colour }) => ({\n width: '100%',\n height: 100,\n backgroundColor: colour,\n borderRadius: theme.shape.borderRadius,\n border: '1px solid',\n borderColor: theme.palette.semantic.stroke['stroke-weak'],\n marginBottom: theme.spacing(2),\n}));\n\nexport const PrimitiveColourSwatch = ({ name, colour }: { name: string; colour: string }) => (\n <Box sx={{ textAlign: 'center' }}>\n <StyledColourSwatch colour={colour} />\n <Typography display=\"block\" variant=\"caption\">\n {name}\n </Typography>\n <Typography color=\"text.secondary\" display=\"block\" variant=\"caption\">\n {colour}\n </Typography>\n </Box>\n);\n\nexport interface SemanticTokenEntry {\n token: string;\n usage: string;\n colour: string;\n primitive: string;\n}\n\nexport const SemanticColourTable = ({\n title,\n description,\n tokens,\n}: {\n title: string;\n description: string;\n tokens: SemanticTokenEntry[];\n}) => (\n <Box sx={{ mb: 6 }}>\n <Typography color=\"text.secondary\" sx={{ mb: 0.5, fontWeight: 600 }} variant=\"h5\">\n {title}\n </Typography>\n <Typography color=\"text.secondary\" sx={{ mb: 3 }} variant=\"body2\">\n {description}\n </Typography>\n <Box\n sx={{\n display: 'flex',\n pb: 1.5,\n borderBottom: '1px solid',\n borderColor: 'semantic.stroke.stroke-weak',\n }}\n >\n <Typography fontWeight={600} sx={{ width: 220, flexShrink: 0 }} variant=\"caption\">\n Design token\n </Typography>\n <Typography fontWeight={600} sx={{ flex: 1 }} variant=\"caption\">\n Usage\n </Typography>\n <Typography fontWeight={600} sx={{ width: 220, flexShrink: 0 }} variant=\"caption\">\n Colour token\n </Typography>\n </Box>\n {tokens.map(({ token, usage, colour, primitive }) => (\n <Box\n key={token}\n sx={{\n display: 'flex',\n alignItems: 'center',\n py: 2,\n borderBottom: '1px solid',\n borderColor: 'semantic.stroke.stroke-weak',\n }}\n >\n <Box sx={{ width: 220, flexShrink: 0 }}>\n <Typography\n component=\"code\"\n sx={{\n px: 1.5,\n py: 0.5,\n borderRadius: '100px',\n border: '1px solid',\n borderColor: 'semantic.stroke.stroke-weak',\n fontFamily: 'monospace',\n }}\n variant=\"caption\"\n >\n {token}\n </Typography>\n </Box>\n <Typography color=\"text.secondary\" sx={{ flex: 1, pr: 3 }} variant=\"body2\">\n {usage}\n </Typography>\n <Box\n sx={{\n width: 220,\n flexShrink: 0,\n display: 'flex',\n alignItems: 'center',\n gap: 1,\n ...(token.includes('inverse') && {\n bgcolor: 'semantic.background.background-inverse',\n px: 1,\n py: 0.5,\n borderRadius: '100px',\n }),\n }}\n >\n <Box\n sx={{\n width: 24,\n height: 24,\n borderRadius: '50%',\n backgroundColor: colour,\n border: '1px solid',\n borderColor: 'semantic.stroke.stroke-weak',\n flexShrink: 0,\n }}\n />\n <Typography\n component=\"code\"\n sx={{\n fontFamily: 'monospace',\n ...(token.includes('inverse') && { color: 'semantic.text.text-inverse-strong' }),\n }}\n variant=\"caption\"\n >\n {primitive}\n </Typography>\n </Box>\n </Box>\n ))}\n </Box>\n);\n\nexport const PrimitiveColourSection = ({\n title,\n description,\n codePattern,\n colours,\n}: {\n title: string;\n description?: string;\n codePattern?: string;\n colours: Record<string, string>;\n}) => (\n <Box sx={{ mb: 5 }}>\n <Typography color=\"text.secondary\" sx={{ mb: 0.5, fontWeight: 600 }} variant=\"h6\">\n {title}\n </Typography>\n {description && (\n <Typography color=\"text.secondary\" sx={{ mb: 1, maxWidth: 600 }} variant=\"body2\">\n {description}\n </Typography>\n )}\n {codePattern && (\n <Typography\n component=\"code\"\n sx={{\n display: 'inline-block',\n mb: 2,\n px: 0.75,\n py: 0.25,\n borderRadius: 0.5,\n bgcolor: 'semantic.fill.fill-weak',\n fontFamily: 'monospace',\n }}\n variant=\"caption\"\n >\n {codePattern}\n </Typography>\n )}\n <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 2 }}>\n {Object.entries(colours).map(([shade, colour]) => (\n <Box key={shade} sx={{ width: 120 }}>\n <Box\n sx={{\n height: 80,\n backgroundColor: colour,\n borderRadius: 1,\n border: '1px solid',\n borderColor: 'semantic.stroke.stroke-weak',\n mb: 1,\n }}\n />\n <Typography display=\"block\" fontWeight={600} variant=\"caption\">\n {shade}\n </Typography>\n <Typography color=\"text.secondary\" display=\"block\" variant=\"caption\">\n {colour}\n </Typography>\n </Box>\n ))}\n </Box>\n </Box>\n);\n\nexport const StyledGrid = styled(Grid)(() => ({\n width: 800,\n overflowX: 'auto',\n}));\n\n// Helper function to create colour primitive stories\nexport const createColourPrimitiveStory = (colourGroup: string, colourObject: Record<string, string>) => {\n return {\n render: () => {\n if (!colourObject) return <Box>No colors available</Box>;\n\n return (\n <StyledGrid container spacing={3}>\n {Object.entries(colourObject)\n .sort(([a], [b]) => parseInt(b) - parseInt(a))\n .map(([shade, colour]) => (\n <Grid key={shade} size={2}>\n <PrimitiveColourSwatch colour={colour} name={`${colourGroup}-${shade}`.toLowerCase()} />\n </Grid>\n ))}\n </StyledGrid>\n );\n },\n };\n};\n\nconst StyledStack = styled(Stack, {\n shouldForwardProp: (prop) => prop !== 'inverse',\n})<{ inverse: boolean }>(({ theme, inverse }) => ({\n alignItems: 'center',\n border: '1px solid',\n borderColor: theme.palette.semantic.stroke['stroke-weak'],\n borderRadius: '100px',\n padding: '6px',\n marginBottom: '10px',\n ...(inverse && {\n backgroundColor: theme.palette.semantic.background['background-inverse'],\n color: theme.palette.semantic.text['text-inverse-strong'],\n }),\n}));\n\nconst StyledColourBox = styled(Box)<{ colour: string }>(({ theme, colour }) => ({\n width: 24,\n height: 24,\n backgroundColor: colour,\n borderRadius: '50%',\n marginRight: theme.spacing(2),\n border: '1px solid',\n borderColor: theme.palette.semantic.stroke['stroke-weak'],\n}));\n\nconst StyledCategoryTitle = styled(Typography)(({ theme }) => ({\n marginBottom: theme.spacing(2),\n paddingBottom: theme.spacing(1),\n borderBottom: '1px solid',\n borderColor: theme.palette.semantic.stroke['stroke-weak'],\n}));\n\nconst StyledColourContainer = styled(Box)({\n display: 'flex',\n flexDirection: 'column',\n});\n\nconst SemanticColourSwatch = ({ name, colour }: { name: string; colour: string }) => (\n <StyledStack direction=\"row\" inverse={name.includes('inverse')} spacing={2}>\n <StyledColourBox colour={colour} />\n <Typography variant=\"body2\">{name}</Typography>\n </StyledStack>\n);\n\n// Helper function to create semantic colour stories\nexport const createSemanticColourStory = (category: string, colourObject: Record<string, string>) => {\n return {\n render: () => {\n if (!colourObject) return <Box>No colors available</Box>;\n\n return (\n <>\n <StyledCategoryTitle variant=\"h6\">{category.toUpperCase()}</StyledCategoryTitle>\n <StyledColourContainer>\n {Object.entries(colourObject).map(([name, colour]) => (\n <SemanticColourSwatch key={name} colour={colour} name={name} />\n ))}\n </StyledColourContainer>\n </>\n );\n },\n };\n};\n"],"names":["StyledColourSwatch","styled","Box","theme","colour","width","height","backgroundColor","borderRadius","shape","border","borderColor","palette","semantic","stroke","marginBottom","spacing","PrimitiveColourSwatch","name","_jsxs","sx","textAlign","children","_jsx","Typography","display","variant","color","StyledGrid","Grid","overflowX","StyledStack","Stack","shouldForwardProp","prop","inverse","alignItems","padding","background","text","StyledColourBox","marginRight","StyledCategoryTitle","paddingBottom","borderBottom","StyledColourContainer","flexDirection","SemanticColourSwatch","direction","includes","title","description","codePattern","colours","mb","fontWeight","maxWidth","component","px","py","bgcolor","fontFamily","flexWrap","gap","Object","entries","map","shade","tokens","pb","flexShrink","flex","token","usage","primitive","pr","colourGroup","colourObject","render","container","sort","a","b","parseInt","size","toLowerCase","category","_Fragment","toUpperCase"],"mappings":"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"}