@strapi/admin 5.53.0 → 5.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/admin/src/App.js +1 -1
- package/dist/admin/admin/src/App.js.map +1 -1
- package/dist/admin/admin/src/App.mjs +1 -1
- package/dist/admin/admin/src/App.mjs.map +1 -1
- package/dist/admin/admin/src/components/DismissibleBanner.js +60 -0
- package/dist/admin/admin/src/components/DismissibleBanner.js.map +1 -0
- package/dist/admin/admin/src/components/DismissibleBanner.mjs +58 -0
- package/dist/admin/admin/src/components/DismissibleBanner.mjs.map +1 -0
- package/dist/admin/admin/src/components/Form.js +11 -2
- package/dist/admin/admin/src/components/Form.js.map +1 -1
- package/dist/admin/admin/src/components/Form.mjs +11 -2
- package/dist/admin/admin/src/components/Form.mjs.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/DateTime.js +1 -1
- package/dist/admin/admin/src/components/FormInputs/DateTime.js.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/DateTime.mjs +1 -1
- package/dist/admin/admin/src/components/FormInputs/DateTime.mjs.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Time.js +1 -1
- package/dist/admin/admin/src/components/FormInputs/Time.js.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Time.mjs +1 -1
- package/dist/admin/admin/src/components/FormInputs/Time.mjs.map +1 -1
- package/dist/admin/admin/src/components/LanguageProvider.js +35 -1
- package/dist/admin/admin/src/components/LanguageProvider.js.map +1 -1
- package/dist/admin/admin/src/components/LanguageProvider.mjs +17 -2
- package/dist/admin/admin/src/components/LanguageProvider.mjs.map +1 -1
- package/dist/admin/admin/src/components/MainNav/NavUser.js +1 -2
- package/dist/admin/admin/src/components/MainNav/NavUser.js.map +1 -1
- package/dist/admin/admin/src/components/MainNav/NavUser.mjs +1 -2
- package/dist/admin/admin/src/components/MainNav/NavUser.mjs.map +1 -1
- package/dist/admin/admin/src/components/MediaLibraryBanner.js +85 -0
- package/dist/admin/admin/src/components/MediaLibraryBanner.js.map +1 -0
- package/dist/admin/admin/src/components/MediaLibraryBanner.mjs +83 -0
- package/dist/admin/admin/src/components/MediaLibraryBanner.mjs.map +1 -0
- package/dist/admin/admin/src/components/Providers.js +6 -6
- package/dist/admin/admin/src/components/Providers.js.map +1 -1
- package/dist/admin/admin/src/components/Providers.mjs +6 -6
- package/dist/admin/admin/src/components/Providers.mjs.map +1 -1
- package/dist/admin/admin/src/components/SubNav.js +113 -35
- package/dist/admin/admin/src/components/SubNav.js.map +1 -1
- package/dist/admin/admin/src/components/SubNav.mjs +115 -37
- package/dist/admin/admin/src/components/SubNav.mjs.map +1 -1
- package/dist/admin/admin/src/components/SubNavFolder.js +188 -0
- package/dist/admin/admin/src/components/SubNavFolder.js.map +1 -0
- package/dist/admin/admin/src/components/SubNavFolder.mjs +186 -0
- package/dist/admin/admin/src/components/SubNavFolder.mjs.map +1 -0
- package/dist/admin/admin/src/components/UpsellBanner.js +56 -86
- package/dist/admin/admin/src/components/UpsellBanner.js.map +1 -1
- package/dist/admin/admin/src/components/UpsellBanner.mjs +58 -88
- package/dist/admin/admin/src/components/UpsellBanner.mjs.map +1 -1
- package/dist/admin/admin/src/core/store/configure.js +14 -2
- package/dist/admin/admin/src/core/store/configure.js.map +1 -1
- package/dist/admin/admin/src/core/store/configure.mjs +14 -2
- package/dist/admin/admin/src/core/store/configure.mjs.map +1 -1
- package/dist/admin/admin/src/core/store/hooks.mjs +1 -1
- package/dist/admin/admin/src/features/Auth.js +162 -46
- package/dist/admin/admin/src/features/Auth.js.map +1 -1
- package/dist/admin/admin/src/features/Auth.mjs +164 -48
- package/dist/admin/admin/src/features/Auth.mjs.map +1 -1
- package/dist/admin/admin/src/features/Tracking.js.map +1 -1
- package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
- package/dist/admin/admin/src/hooks/useRegisterUnsavedChanges.js +19 -0
- package/dist/admin/admin/src/hooks/useRegisterUnsavedChanges.js.map +1 -0
- package/dist/admin/admin/src/hooks/useRegisterUnsavedChanges.mjs +17 -0
- package/dist/admin/admin/src/hooks/useRegisterUnsavedChanges.mjs.map +1 -0
- package/dist/admin/admin/src/hooks/{useIdleSessionLogout.js → useSessionKeepalive.js} +34 -27
- package/dist/admin/admin/src/hooks/useSessionKeepalive.js.map +1 -0
- package/dist/admin/admin/src/hooks/{useIdleSessionLogout.mjs → useSessionKeepalive.mjs} +34 -27
- package/dist/admin/admin/src/hooks/useSessionKeepalive.mjs.map +1 -0
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.js +2 -0
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.js.map +1 -1
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.mjs +2 -0
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.mjs.map +1 -1
- package/dist/admin/admin/src/pages/SessionsPage.js +2 -5
- package/dist/admin/admin/src/pages/SessionsPage.js.map +1 -1
- package/dist/admin/admin/src/pages/SessionsPage.mjs +2 -5
- package/dist/admin/admin/src/pages/SessionsPage.mjs.map +1 -1
- package/dist/admin/admin/src/render.js +6 -1
- package/dist/admin/admin/src/render.js.map +1 -1
- package/dist/admin/admin/src/render.mjs +6 -1
- package/dist/admin/admin/src/render.mjs.map +1 -1
- package/dist/admin/admin/src/translations/en.json.js +16 -0
- package/dist/admin/admin/src/translations/en.json.js.map +1 -1
- package/dist/admin/admin/src/translations/en.json.mjs +16 -0
- package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
- package/dist/admin/admin/src/utils/baseQuery.js +3 -13
- package/dist/admin/admin/src/utils/baseQuery.js.map +1 -1
- package/dist/admin/admin/src/utils/baseQuery.mjs +3 -13
- package/dist/admin/admin/src/utils/baseQuery.mjs.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.js +34 -5
- package/dist/admin/admin/src/utils/getFetchClient.js.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.mjs +34 -6
- package/dist/admin/admin/src/utils/getFetchClient.mjs.map +1 -1
- package/dist/admin/admin/src/utils/unsavedChangesRegistry.js +25 -0
- package/dist/admin/admin/src/utils/unsavedChangesRegistry.js.map +1 -0
- package/dist/admin/admin/src/utils/unsavedChangesRegistry.mjs +22 -0
- package/dist/admin/admin/src/utils/unsavedChangesRegistry.mjs.map +1 -0
- package/dist/admin/admin/tests/utils.js +14 -14
- package/dist/admin/admin/tests/utils.js.map +1 -1
- package/dist/admin/admin/tests/utils.mjs +14 -14
- package/dist/admin/admin/tests/utils.mjs.map +1 -1
- package/dist/admin/ee/admin/src/hooks/useAIAvailability.js +1 -6
- package/dist/admin/ee/admin/src/hooks/useAIAvailability.js.map +1 -1
- package/dist/admin/ee/admin/src/hooks/useAIAvailability.mjs +1 -6
- package/dist/admin/ee/admin/src/hooks/useAIAvailability.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js +7 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs +7 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js +9 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs +9 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.js +0 -4
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.mjs +0 -4
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/SingleSignOnPage.mjs.map +1 -1
- package/dist/admin/index.js +1 -0
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/DismissibleBanner.d.ts +8 -0
- package/dist/admin/src/components/MediaLibraryBanner.d.ts +2 -0
- package/dist/admin/src/components/SubNav.d.ts +27 -8
- package/dist/admin/src/components/SubNavFolder.d.ts +15 -0
- package/dist/admin/src/features/Tracking.d.ts +2 -1
- package/dist/admin/src/hooks/useRegisterUnsavedChanges.d.ts +6 -0
- package/dist/admin/src/hooks/useSessionKeepalive.d.ts +88 -0
- package/dist/admin/src/services/admin.d.ts +1 -0
- package/dist/admin/src/utils/getFetchClient.d.ts +14 -6
- package/dist/admin/src/utils/unsavedChangesRegistry.d.ts +11 -0
- package/dist/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.d.ts +8 -0
- package/dist/ee/server/src/controllers/admin.d.ts.map +1 -1
- package/dist/ee/server/src/index.d.ts.map +1 -1
- package/dist/server/ee/server/src/controllers/admin.js +1 -5
- package/dist/server/ee/server/src/controllers/admin.js.map +1 -1
- package/dist/server/ee/server/src/controllers/admin.mjs +1 -5
- package/dist/server/ee/server/src/controllers/admin.mjs.map +1 -1
- package/dist/server/ee/server/src/index.js +2 -0
- package/dist/server/ee/server/src/index.js.map +1 -1
- package/dist/server/ee/server/src/index.mjs +2 -0
- package/dist/server/ee/server/src/index.mjs.map +1 -1
- package/dist/server/server/src/ai/controllers/ai.js +3 -3
- package/dist/server/server/src/ai/controllers/ai.js.map +1 -1
- package/dist/server/server/src/ai/controllers/ai.mjs +3 -3
- package/dist/server/server/src/ai/controllers/ai.mjs.map +1 -1
- package/dist/server/server/src/ai/services/ai.js +37 -12
- package/dist/server/server/src/ai/services/ai.js.map +1 -1
- package/dist/server/server/src/ai/services/ai.mjs +37 -12
- package/dist/server/server/src/ai/services/ai.mjs.map +1 -1
- package/dist/server/server/src/audit-logs/tokens.js +106 -0
- package/dist/server/server/src/audit-logs/tokens.js.map +1 -0
- package/dist/server/server/src/audit-logs/tokens.mjs +99 -0
- package/dist/server/server/src/audit-logs/tokens.mjs.map +1 -0
- package/dist/server/server/src/controllers/admin.js +10 -1
- package/dist/server/server/src/controllers/admin.js.map +1 -1
- package/dist/server/server/src/controllers/admin.mjs +10 -1
- package/dist/server/server/src/controllers/admin.mjs.map +1 -1
- package/dist/server/server/src/services/api-token.js +106 -4
- package/dist/server/server/src/services/api-token.js.map +1 -1
- package/dist/server/server/src/services/api-token.mjs +107 -5
- package/dist/server/server/src/services/api-token.mjs.map +1 -1
- package/dist/server/server/src/services/transfer/token.js +56 -4
- package/dist/server/server/src/services/transfer/token.js.map +1 -1
- package/dist/server/server/src/services/transfer/token.mjs +57 -5
- package/dist/server/server/src/services/transfer/token.mjs.map +1 -1
- package/dist/server/src/ai/services/ai.d.ts +3 -1
- package/dist/server/src/ai/services/ai.d.ts.map +1 -1
- package/dist/server/src/audit-logs/tokens.d.ts +86 -0
- package/dist/server/src/audit-logs/tokens.d.ts.map +1 -0
- package/dist/server/src/controllers/admin.d.ts +1 -0
- package/dist/server/src/controllers/admin.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +1 -0
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +1 -0
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/services/api-token.d.ts.map +1 -1
- package/dist/server/src/services/transfer/token.d.ts.map +1 -1
- package/dist/shared/contracts/admin.d.ts +1 -0
- package/dist/shared/contracts/admin.d.ts.map +1 -1
- package/dist/shared/contracts/shared.d.ts +1 -0
- package/dist/shared/contracts/shared.d.ts.map +1 -1
- package/package.json +7 -7
- package/dist/admin/admin/src/hooks/useIdleSessionLogout.js.map +0 -1
- package/dist/admin/admin/src/hooks/useIdleSessionLogout.mjs.map +0 -1
- package/dist/admin/src/hooks/useIdleSessionLogout.d.ts +0 -87
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubNavFolder.js","sources":["../../../../../admin/src/components/SubNavFolder.tsx"],"sourcesContent":["import { useCallback, useId, useRef, useState } from 'react';\n\nimport { Box, Flex, Tooltip, Typography } from '@strapi/design-system';\nimport { ChevronDown } from '@strapi/icons';\nimport { styled } from 'styled-components';\n\nconst ANIMATION_DURATION = '0.5s';\nconst COLLAPSE_EASING = 'cubic-bezier(0, 1, 0, 1)';\n\ninterface SubNavFolderProps {\n label: string;\n depth?: number;\n open?: boolean;\n defaultOpen?: boolean;\n onToggle?: (open: boolean) => void;\n endAction?: React.ReactNode;\n /** Ref attached to the row element used as a drag-and-drop drop target. */\n rowRef?: React.Ref<HTMLDivElement>;\n isDropTarget?: boolean;\n children?: React.ReactNode;\n}\n\nconst FolderRow = styled(Flex)<{ $depth: number; $isDropTarget?: boolean }>`\n border-radius: ${({ theme }) => theme.borderRadius};\n\n padding-right: ${({ theme }) => theme.spaces[3]};\n\n padding-left: ${({ theme, $depth }) =>\n `calc(${$depth} * ${theme.spaces[6]} + ${theme.spaces[3]})`};\n\n background-color: ${({ $isDropTarget, theme }) =>\n $isDropTarget ? theme.colors.primary100 : 'transparent'};\n outline: ${({ $isDropTarget, theme }) =>\n $isDropTarget ? `1px solid ${theme.colors.primary600}` : 'none'};\n outline-offset: -1px;\n\n &:hover {\n background-color: ${({ $isDropTarget, theme }) =>\n $isDropTarget ? theme.colors.primary100 : theme.colors.neutral100};\n }\n`;\n\nconst ToggleButton = styled.button`\n gap: ${({ theme }) => theme.spaces[2]};\n align-items: center;\n display: flex;\n flex: 1;\n\n padding-block: ${({ theme }) => theme.spaces[2]};\n padding-inline: 0;\n\n min-width: 0;\n\n background: transparent;\n border: none;\n\n text-align: left;\n cursor: pointer;\n\n &:focus-visible {\n outline-offset: -2px;\n }\n`;\n\nconst EndActionWrapper = styled(Flex)`\n flex-shrink: 0;\n opacity: 0;\n transition: opacity 0.1s ease-out;\n\n ${FolderRow}:hover &,\n ${FolderRow}:focus-within & {\n opacity: 1;\n }\n`;\n\nconst Collapsible = styled.div<{ $open: boolean }>`\n grid-template-rows: ${({ $open }) => ($open ? '1fr' : '0fr')};\n display: grid;\n\n transition: grid-template-rows ${ANIMATION_DURATION} ${COLLAPSE_EASING};\n`;\n\nconst CollapsibleInner = styled.div`\n overflow: hidden;\n min-height: 0;\n`;\n\ninterface FolderViewProps {\n rowRef?: React.Ref<HTMLDivElement>;\n endAction?: React.ReactNode;\n children?: React.ReactNode;\n onToggleClick: () => void;\n isDropTarget?: boolean;\n label: string;\n depth: number;\n open: boolean;\n}\n\nconst FolderView = ({\n onToggleClick,\n isDropTarget,\n endAction,\n children,\n rowRef,\n label,\n depth,\n open,\n}: FolderViewProps) => {\n const listId = useId();\n\n const [isLabelTruncated, setIsLabelTruncated] = useState(false);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n\n // A callback ref (rather than useRef + useEffect) so measurement survives the label\n // element remounting when it moves in and out of the Tooltip wrapper below.\n const measureLabelRef = useCallback((node: HTMLElement | null) => {\n if (resizeObserverRef.current) {\n resizeObserverRef.current.disconnect();\n resizeObserverRef.current = null;\n }\n\n if (!node) {\n return;\n }\n\n const measure = () => {\n setIsLabelTruncated(node.scrollWidth > node.clientWidth);\n };\n\n measure();\n\n if (typeof ResizeObserver === 'undefined') {\n return;\n }\n\n resizeObserverRef.current = new ResizeObserver(measure);\n resizeObserverRef.current.observe(node);\n }, []);\n\n const applyInertWhenClosed = useCallback(\n (node: HTMLDivElement | null) => {\n if (!node) {\n return;\n }\n\n if (open) {\n node.removeAttribute('inert');\n } else {\n node.setAttribute('inert', '');\n }\n },\n [open]\n );\n\n const labelTypography = (\n <Typography\n textColor=\"neutral800\"\n fontWeight=\"semiBold\"\n ref={measureLabelRef}\n overflow=\"hidden\"\n tag=\"span\"\n style={{ flex: 1, minWidth: 0, textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}\n >\n {label}\n </Typography>\n );\n\n return (\n <Box>\n <FolderRow ref={rowRef} $depth={depth} $isDropTarget={isDropTarget} alignItems=\"center\">\n <ToggleButton\n onClick={onToggleClick}\n aria-controls={listId}\n aria-expanded={open}\n type=\"button\"\n >\n <ChevronDown\n fill=\"neutral500\"\n aria-hidden\n style={{\n transform: `rotate(${open ? '0deg' : '-90deg'})`,\n transition: `transform ${ANIMATION_DURATION}`,\n flexShrink: 0,\n }}\n />\n {isLabelTruncated ? <Tooltip label={label}>{labelTypography}</Tooltip> : labelTypography}\n </ToggleButton>\n {endAction != null && (\n <EndActionWrapper gap={2} alignItems=\"center\">\n {endAction}\n </EndActionWrapper>\n )}\n </FolderRow>\n <Collapsible $open={open} id={listId}>\n <CollapsibleInner ref={applyInertWhenClosed}>{children}</CollapsibleInner>\n </Collapsible>\n </Box>\n );\n};\n\nconst SubNavFolder = ({\n defaultOpen = false,\n open: openProp,\n isDropTarget,\n endAction,\n children,\n onToggle,\n rowRef,\n label,\n depth = 0,\n}: SubNavFolderProps) => {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n\n const isControlled = openProp !== undefined;\n const open = isControlled ? openProp : uncontrolledOpen;\n\n const handleToggleClick = () => {\n const next = !open;\n\n if (!isControlled) {\n setUncontrolledOpen(next);\n }\n\n onToggle?.(next);\n };\n\n return (\n <FolderView\n onToggleClick={handleToggleClick}\n isDropTarget={isDropTarget}\n endAction={endAction}\n rowRef={rowRef}\n label={label}\n depth={depth}\n open={open}\n >\n {children}\n </FolderView>\n );\n};\n\nexport { SubNavFolder };\nexport type { SubNavFolderProps };\n"],"names":["ANIMATION_DURATION","COLLAPSE_EASING","FolderRow","styled","Flex","theme","borderRadius","spaces","$depth","$isDropTarget","colors","primary100","primary600","neutral100","ToggleButton","button","EndActionWrapper","Collapsible","div","$open","CollapsibleInner","FolderView","onToggleClick","isDropTarget","endAction","children","rowRef","label","depth","open","listId","useId","isLabelTruncated","setIsLabelTruncated","useState","resizeObserverRef","useRef","measureLabelRef","useCallback","node","current","disconnect","measure","scrollWidth","clientWidth","ResizeObserver","observe","applyInertWhenClosed","removeAttribute","setAttribute","labelTypography","_jsx","Typography","textColor","fontWeight","ref","overflow","tag","style","flex","minWidth","textOverflow","whiteSpace","_jsxs","Box","alignItems","onClick","aria-controls","aria-expanded","type","ChevronDown","fill","aria-hidden","transform","transition","flexShrink","Tooltip","gap","id","SubNavFolder","defaultOpen","openProp","onToggle","uncontrolledOpen","setUncontrolledOpen","isControlled","undefined","handleToggleClick","next"],"mappings":"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"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useId, useRef, useCallback } from 'react';
|
|
3
|
+
import { Flex, Box, Tooltip, Typography } from '@strapi/design-system';
|
|
4
|
+
import { ChevronDown } from '@strapi/icons';
|
|
5
|
+
import { styled } from 'styled-components';
|
|
6
|
+
|
|
7
|
+
const ANIMATION_DURATION = '0.5s';
|
|
8
|
+
const COLLAPSE_EASING = 'cubic-bezier(0, 1, 0, 1)';
|
|
9
|
+
const FolderRow = styled(Flex)`
|
|
10
|
+
border-radius: ${({ theme })=>theme.borderRadius};
|
|
11
|
+
|
|
12
|
+
padding-right: ${({ theme })=>theme.spaces[3]};
|
|
13
|
+
|
|
14
|
+
padding-left: ${({ theme, $depth })=>`calc(${$depth} * ${theme.spaces[6]} + ${theme.spaces[3]})`};
|
|
15
|
+
|
|
16
|
+
background-color: ${({ $isDropTarget, theme })=>$isDropTarget ? theme.colors.primary100 : 'transparent'};
|
|
17
|
+
outline: ${({ $isDropTarget, theme })=>$isDropTarget ? `1px solid ${theme.colors.primary600}` : 'none'};
|
|
18
|
+
outline-offset: -1px;
|
|
19
|
+
|
|
20
|
+
&:hover {
|
|
21
|
+
background-color: ${({ $isDropTarget, theme })=>$isDropTarget ? theme.colors.primary100 : theme.colors.neutral100};
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
24
|
+
const ToggleButton = styled.button`
|
|
25
|
+
gap: ${({ theme })=>theme.spaces[2]};
|
|
26
|
+
align-items: center;
|
|
27
|
+
display: flex;
|
|
28
|
+
flex: 1;
|
|
29
|
+
|
|
30
|
+
padding-block: ${({ theme })=>theme.spaces[2]};
|
|
31
|
+
padding-inline: 0;
|
|
32
|
+
|
|
33
|
+
min-width: 0;
|
|
34
|
+
|
|
35
|
+
background: transparent;
|
|
36
|
+
border: none;
|
|
37
|
+
|
|
38
|
+
text-align: left;
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
|
|
41
|
+
&:focus-visible {
|
|
42
|
+
outline-offset: -2px;
|
|
43
|
+
}
|
|
44
|
+
`;
|
|
45
|
+
const EndActionWrapper = styled(Flex)`
|
|
46
|
+
flex-shrink: 0;
|
|
47
|
+
opacity: 0;
|
|
48
|
+
transition: opacity 0.1s ease-out;
|
|
49
|
+
|
|
50
|
+
${FolderRow}:hover &,
|
|
51
|
+
${FolderRow}:focus-within & {
|
|
52
|
+
opacity: 1;
|
|
53
|
+
}
|
|
54
|
+
`;
|
|
55
|
+
const Collapsible = styled.div`
|
|
56
|
+
grid-template-rows: ${({ $open })=>$open ? '1fr' : '0fr'};
|
|
57
|
+
display: grid;
|
|
58
|
+
|
|
59
|
+
transition: grid-template-rows ${ANIMATION_DURATION} ${COLLAPSE_EASING};
|
|
60
|
+
`;
|
|
61
|
+
const CollapsibleInner = styled.div`
|
|
62
|
+
overflow: hidden;
|
|
63
|
+
min-height: 0;
|
|
64
|
+
`;
|
|
65
|
+
const FolderView = ({ onToggleClick, isDropTarget, endAction, children, rowRef, label, depth, open })=>{
|
|
66
|
+
const listId = useId();
|
|
67
|
+
const [isLabelTruncated, setIsLabelTruncated] = useState(false);
|
|
68
|
+
const resizeObserverRef = useRef(null);
|
|
69
|
+
// A callback ref (rather than useRef + useEffect) so measurement survives the label
|
|
70
|
+
// element remounting when it moves in and out of the Tooltip wrapper below.
|
|
71
|
+
const measureLabelRef = useCallback((node)=>{
|
|
72
|
+
if (resizeObserverRef.current) {
|
|
73
|
+
resizeObserverRef.current.disconnect();
|
|
74
|
+
resizeObserverRef.current = null;
|
|
75
|
+
}
|
|
76
|
+
if (!node) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const measure = ()=>{
|
|
80
|
+
setIsLabelTruncated(node.scrollWidth > node.clientWidth);
|
|
81
|
+
};
|
|
82
|
+
measure();
|
|
83
|
+
if (typeof ResizeObserver === 'undefined') {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
resizeObserverRef.current = new ResizeObserver(measure);
|
|
87
|
+
resizeObserverRef.current.observe(node);
|
|
88
|
+
}, []);
|
|
89
|
+
const applyInertWhenClosed = useCallback((node)=>{
|
|
90
|
+
if (!node) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (open) {
|
|
94
|
+
node.removeAttribute('inert');
|
|
95
|
+
} else {
|
|
96
|
+
node.setAttribute('inert', '');
|
|
97
|
+
}
|
|
98
|
+
}, [
|
|
99
|
+
open
|
|
100
|
+
]);
|
|
101
|
+
const labelTypography = /*#__PURE__*/ jsx(Typography, {
|
|
102
|
+
textColor: "neutral800",
|
|
103
|
+
fontWeight: "semiBold",
|
|
104
|
+
ref: measureLabelRef,
|
|
105
|
+
overflow: "hidden",
|
|
106
|
+
tag: "span",
|
|
107
|
+
style: {
|
|
108
|
+
flex: 1,
|
|
109
|
+
minWidth: 0,
|
|
110
|
+
textOverflow: 'ellipsis',
|
|
111
|
+
whiteSpace: 'nowrap'
|
|
112
|
+
},
|
|
113
|
+
children: label
|
|
114
|
+
});
|
|
115
|
+
return /*#__PURE__*/ jsxs(Box, {
|
|
116
|
+
children: [
|
|
117
|
+
/*#__PURE__*/ jsxs(FolderRow, {
|
|
118
|
+
ref: rowRef,
|
|
119
|
+
$depth: depth,
|
|
120
|
+
$isDropTarget: isDropTarget,
|
|
121
|
+
alignItems: "center",
|
|
122
|
+
children: [
|
|
123
|
+
/*#__PURE__*/ jsxs(ToggleButton, {
|
|
124
|
+
onClick: onToggleClick,
|
|
125
|
+
"aria-controls": listId,
|
|
126
|
+
"aria-expanded": open,
|
|
127
|
+
type: "button",
|
|
128
|
+
children: [
|
|
129
|
+
/*#__PURE__*/ jsx(ChevronDown, {
|
|
130
|
+
fill: "neutral500",
|
|
131
|
+
"aria-hidden": true,
|
|
132
|
+
style: {
|
|
133
|
+
transform: `rotate(${open ? '0deg' : '-90deg'})`,
|
|
134
|
+
transition: `transform ${ANIMATION_DURATION}`,
|
|
135
|
+
flexShrink: 0
|
|
136
|
+
}
|
|
137
|
+
}),
|
|
138
|
+
isLabelTruncated ? /*#__PURE__*/ jsx(Tooltip, {
|
|
139
|
+
label: label,
|
|
140
|
+
children: labelTypography
|
|
141
|
+
}) : labelTypography
|
|
142
|
+
]
|
|
143
|
+
}),
|
|
144
|
+
endAction != null && /*#__PURE__*/ jsx(EndActionWrapper, {
|
|
145
|
+
gap: 2,
|
|
146
|
+
alignItems: "center",
|
|
147
|
+
children: endAction
|
|
148
|
+
})
|
|
149
|
+
]
|
|
150
|
+
}),
|
|
151
|
+
/*#__PURE__*/ jsx(Collapsible, {
|
|
152
|
+
$open: open,
|
|
153
|
+
id: listId,
|
|
154
|
+
children: /*#__PURE__*/ jsx(CollapsibleInner, {
|
|
155
|
+
ref: applyInertWhenClosed,
|
|
156
|
+
children: children
|
|
157
|
+
})
|
|
158
|
+
})
|
|
159
|
+
]
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
const SubNavFolder = ({ defaultOpen = false, open: openProp, isDropTarget, endAction, children, onToggle, rowRef, label, depth = 0 })=>{
|
|
163
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
|
|
164
|
+
const isControlled = openProp !== undefined;
|
|
165
|
+
const open = isControlled ? openProp : uncontrolledOpen;
|
|
166
|
+
const handleToggleClick = ()=>{
|
|
167
|
+
const next = !open;
|
|
168
|
+
if (!isControlled) {
|
|
169
|
+
setUncontrolledOpen(next);
|
|
170
|
+
}
|
|
171
|
+
onToggle?.(next);
|
|
172
|
+
};
|
|
173
|
+
return /*#__PURE__*/ jsx(FolderView, {
|
|
174
|
+
onToggleClick: handleToggleClick,
|
|
175
|
+
isDropTarget: isDropTarget,
|
|
176
|
+
endAction: endAction,
|
|
177
|
+
rowRef: rowRef,
|
|
178
|
+
label: label,
|
|
179
|
+
depth: depth,
|
|
180
|
+
open: open,
|
|
181
|
+
children: children
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export { SubNavFolder };
|
|
186
|
+
//# sourceMappingURL=SubNavFolder.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubNavFolder.mjs","sources":["../../../../../admin/src/components/SubNavFolder.tsx"],"sourcesContent":["import { useCallback, useId, useRef, useState } from 'react';\n\nimport { Box, Flex, Tooltip, Typography } from '@strapi/design-system';\nimport { ChevronDown } from '@strapi/icons';\nimport { styled } from 'styled-components';\n\nconst ANIMATION_DURATION = '0.5s';\nconst COLLAPSE_EASING = 'cubic-bezier(0, 1, 0, 1)';\n\ninterface SubNavFolderProps {\n label: string;\n depth?: number;\n open?: boolean;\n defaultOpen?: boolean;\n onToggle?: (open: boolean) => void;\n endAction?: React.ReactNode;\n /** Ref attached to the row element used as a drag-and-drop drop target. */\n rowRef?: React.Ref<HTMLDivElement>;\n isDropTarget?: boolean;\n children?: React.ReactNode;\n}\n\nconst FolderRow = styled(Flex)<{ $depth: number; $isDropTarget?: boolean }>`\n border-radius: ${({ theme }) => theme.borderRadius};\n\n padding-right: ${({ theme }) => theme.spaces[3]};\n\n padding-left: ${({ theme, $depth }) =>\n `calc(${$depth} * ${theme.spaces[6]} + ${theme.spaces[3]})`};\n\n background-color: ${({ $isDropTarget, theme }) =>\n $isDropTarget ? theme.colors.primary100 : 'transparent'};\n outline: ${({ $isDropTarget, theme }) =>\n $isDropTarget ? `1px solid ${theme.colors.primary600}` : 'none'};\n outline-offset: -1px;\n\n &:hover {\n background-color: ${({ $isDropTarget, theme }) =>\n $isDropTarget ? theme.colors.primary100 : theme.colors.neutral100};\n }\n`;\n\nconst ToggleButton = styled.button`\n gap: ${({ theme }) => theme.spaces[2]};\n align-items: center;\n display: flex;\n flex: 1;\n\n padding-block: ${({ theme }) => theme.spaces[2]};\n padding-inline: 0;\n\n min-width: 0;\n\n background: transparent;\n border: none;\n\n text-align: left;\n cursor: pointer;\n\n &:focus-visible {\n outline-offset: -2px;\n }\n`;\n\nconst EndActionWrapper = styled(Flex)`\n flex-shrink: 0;\n opacity: 0;\n transition: opacity 0.1s ease-out;\n\n ${FolderRow}:hover &,\n ${FolderRow}:focus-within & {\n opacity: 1;\n }\n`;\n\nconst Collapsible = styled.div<{ $open: boolean }>`\n grid-template-rows: ${({ $open }) => ($open ? '1fr' : '0fr')};\n display: grid;\n\n transition: grid-template-rows ${ANIMATION_DURATION} ${COLLAPSE_EASING};\n`;\n\nconst CollapsibleInner = styled.div`\n overflow: hidden;\n min-height: 0;\n`;\n\ninterface FolderViewProps {\n rowRef?: React.Ref<HTMLDivElement>;\n endAction?: React.ReactNode;\n children?: React.ReactNode;\n onToggleClick: () => void;\n isDropTarget?: boolean;\n label: string;\n depth: number;\n open: boolean;\n}\n\nconst FolderView = ({\n onToggleClick,\n isDropTarget,\n endAction,\n children,\n rowRef,\n label,\n depth,\n open,\n}: FolderViewProps) => {\n const listId = useId();\n\n const [isLabelTruncated, setIsLabelTruncated] = useState(false);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n\n // A callback ref (rather than useRef + useEffect) so measurement survives the label\n // element remounting when it moves in and out of the Tooltip wrapper below.\n const measureLabelRef = useCallback((node: HTMLElement | null) => {\n if (resizeObserverRef.current) {\n resizeObserverRef.current.disconnect();\n resizeObserverRef.current = null;\n }\n\n if (!node) {\n return;\n }\n\n const measure = () => {\n setIsLabelTruncated(node.scrollWidth > node.clientWidth);\n };\n\n measure();\n\n if (typeof ResizeObserver === 'undefined') {\n return;\n }\n\n resizeObserverRef.current = new ResizeObserver(measure);\n resizeObserverRef.current.observe(node);\n }, []);\n\n const applyInertWhenClosed = useCallback(\n (node: HTMLDivElement | null) => {\n if (!node) {\n return;\n }\n\n if (open) {\n node.removeAttribute('inert');\n } else {\n node.setAttribute('inert', '');\n }\n },\n [open]\n );\n\n const labelTypography = (\n <Typography\n textColor=\"neutral800\"\n fontWeight=\"semiBold\"\n ref={measureLabelRef}\n overflow=\"hidden\"\n tag=\"span\"\n style={{ flex: 1, minWidth: 0, textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}\n >\n {label}\n </Typography>\n );\n\n return (\n <Box>\n <FolderRow ref={rowRef} $depth={depth} $isDropTarget={isDropTarget} alignItems=\"center\">\n <ToggleButton\n onClick={onToggleClick}\n aria-controls={listId}\n aria-expanded={open}\n type=\"button\"\n >\n <ChevronDown\n fill=\"neutral500\"\n aria-hidden\n style={{\n transform: `rotate(${open ? '0deg' : '-90deg'})`,\n transition: `transform ${ANIMATION_DURATION}`,\n flexShrink: 0,\n }}\n />\n {isLabelTruncated ? <Tooltip label={label}>{labelTypography}</Tooltip> : labelTypography}\n </ToggleButton>\n {endAction != null && (\n <EndActionWrapper gap={2} alignItems=\"center\">\n {endAction}\n </EndActionWrapper>\n )}\n </FolderRow>\n <Collapsible $open={open} id={listId}>\n <CollapsibleInner ref={applyInertWhenClosed}>{children}</CollapsibleInner>\n </Collapsible>\n </Box>\n );\n};\n\nconst SubNavFolder = ({\n defaultOpen = false,\n open: openProp,\n isDropTarget,\n endAction,\n children,\n onToggle,\n rowRef,\n label,\n depth = 0,\n}: SubNavFolderProps) => {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n\n const isControlled = openProp !== undefined;\n const open = isControlled ? openProp : uncontrolledOpen;\n\n const handleToggleClick = () => {\n const next = !open;\n\n if (!isControlled) {\n setUncontrolledOpen(next);\n }\n\n onToggle?.(next);\n };\n\n return (\n <FolderView\n onToggleClick={handleToggleClick}\n isDropTarget={isDropTarget}\n endAction={endAction}\n rowRef={rowRef}\n label={label}\n depth={depth}\n open={open}\n >\n {children}\n </FolderView>\n );\n};\n\nexport { SubNavFolder };\nexport type { SubNavFolderProps };\n"],"names":["ANIMATION_DURATION","COLLAPSE_EASING","FolderRow","styled","Flex","theme","borderRadius","spaces","$depth","$isDropTarget","colors","primary100","primary600","neutral100","ToggleButton","button","EndActionWrapper","Collapsible","div","$open","CollapsibleInner","FolderView","onToggleClick","isDropTarget","endAction","children","rowRef","label","depth","open","listId","useId","isLabelTruncated","setIsLabelTruncated","useState","resizeObserverRef","useRef","measureLabelRef","useCallback","node","current","disconnect","measure","scrollWidth","clientWidth","ResizeObserver","observe","applyInertWhenClosed","removeAttribute","setAttribute","labelTypography","_jsx","Typography","textColor","fontWeight","ref","overflow","tag","style","flex","minWidth","textOverflow","whiteSpace","_jsxs","Box","alignItems","onClick","aria-controls","aria-expanded","type","ChevronDown","fill","aria-hidden","transform","transition","flexShrink","Tooltip","gap","id","SubNavFolder","defaultOpen","openProp","onToggle","uncontrolledOpen","setUncontrolledOpen","isControlled","undefined","handleToggleClick","next"],"mappings":";;;;;;AAMA,MAAMA,kBAAAA,GAAqB,MAAA;AAC3B,MAAMC,eAAAA,GAAkB,0BAAA;AAexB,MAAMC,SAAAA,GAAYC,MAAAA,CAAOC,IAAAA,CAAkD;AAC1D,iBAAA,EAAE,CAAC,EAAEC,KAAK,EAAE,GAAKA,KAAAA,CAAMC,YAAY,CAAC;;iBAEpC,EAAE,CAAC,EAAED,KAAK,EAAE,GAAKA,KAAAA,CAAME,MAAM,CAAC,CAAA,CAAE,CAAC;;gBAElC,EAAE,CAAC,EAAEF,KAAK,EAAEG,MAAM,EAAE,GAChC,CAAC,KAAK,EAAEA,MAAAA,CAAO,GAAG,EAAEH,KAAAA,CAAME,MAAM,CAAC,CAAA,CAAE,CAAC,GAAG,EAAEF,KAAAA,CAAME,MAAM,CAAC,CAAA,CAAE,CAAC,CAAC,CAAC,CAAC;;AAE5C,oBAAA,EAAE,CAAC,EAAEE,aAAa,EAAEJ,KAAK,EAAE,GAC3CI,aAAAA,GAAgBJ,KAAAA,CAAMK,MAAM,CAACC,UAAU,GAAG,aAAA,CAAc;AACjD,WAAA,EAAE,CAAC,EAAEF,aAAa,EAAEJ,KAAK,EAAE,GAClCI,aAAAA,GAAgB,CAAC,UAAU,EAAEJ,KAAAA,CAAMK,MAAM,CAACE,UAAU,CAAA,CAAE,GAAG,MAAA,CAAO;;;;AAI9C,sBAAA,EAAE,CAAC,EAAEH,aAAa,EAAEJ,KAAK,EAAE,GAC3CI,aAAAA,GAAgBJ,KAAAA,CAAMK,MAAM,CAACC,UAAU,GAAGN,MAAMK,MAAM,CAACG,UAAU,CAAC;;AAExE,CAAC;AAED,MAAMC,YAAAA,GAAeX,MAAAA,CAAOY,MAAM;OAC3B,EAAE,CAAC,EAAEV,KAAK,EAAE,GAAKA,KAAAA,CAAME,MAAM,CAAC,CAAA,CAAE,CAAC;;;;;iBAKvB,EAAE,CAAC,EAAEF,KAAK,EAAE,GAAKA,KAAAA,CAAME,MAAM,CAAC,CAAA,CAAE,CAAC;;;;;;;;;;;;;;AAclD,CAAC;AAED,MAAMS,gBAAAA,GAAmBb,MAAAA,CAAOC,IAAAA,CAAK;;;;;AAKnC,EAAA,EAAEF,SAAAA,CAAU;AACZ,EAAA,EAAEA,SAAAA,CAAU;;;AAGd,CAAC;AAED,MAAMe,WAAAA,GAAcd,MAAAA,CAAOe,GAAuB;AAC5B,sBAAA,EAAE,CAAC,EAAEC,KAAK,EAAE,GAAMA,KAAAA,GAAQ,QAAQ,KAAA,CAAO;;;iCAG9B,EAAEnB,kBAAAA,CAAmB,CAAC,EAAEC,eAAAA,CAAgB;AACzE,CAAC;AAED,MAAMmB,gBAAAA,GAAmBjB,MAAAA,CAAOe,GAAG;;;AAGnC,CAAC;AAaD,MAAMG,aAAa,CAAC,EAClBC,aAAa,EACbC,YAAY,EACZC,SAAS,EACTC,QAAQ,EACRC,MAAM,EACNC,KAAK,EACLC,KAAK,EACLC,IAAI,EACY,GAAA;AAChB,IAAA,MAAMC,MAAAA,GAASC,KAAAA,EAAAA;AAEf,IAAA,MAAM,CAACC,gBAAAA,EAAkBC,mBAAAA,CAAoB,GAAGC,QAAAA,CAAS,KAAA,CAAA;AACzD,IAAA,MAAMC,oBAAoBC,MAAAA,CAA8B,IAAA,CAAA;;;IAIxD,MAAMC,eAAAA,GAAkBC,YAAY,CAACC,IAAAA,GAAAA;QACnC,IAAIJ,iBAAAA,CAAkBK,OAAO,EAAE;YAC7BL,iBAAAA,CAAkBK,OAAO,CAACC,UAAU,EAAA;AACpCN,YAAAA,iBAAAA,CAAkBK,OAAO,GAAG,IAAA;AAC9B,QAAA;AAEA,QAAA,IAAI,CAACD,IAAAA,EAAM;AACT,YAAA;AACF,QAAA;AAEA,QAAA,MAAMG,OAAAA,GAAU,IAAA;AACdT,YAAAA,mBAAAA,CAAoBM,IAAAA,CAAKI,WAAW,GAAGJ,IAAAA,CAAKK,WAAW,CAAA;AACzD,QAAA,CAAA;AAEAF,QAAAA,OAAAA,EAAAA;QAEA,IAAI,OAAOG,mBAAmB,WAAA,EAAa;AACzC,YAAA;AACF,QAAA;QAEAV,iBAAAA,CAAkBK,OAAO,GAAG,IAAIK,cAAAA,CAAeH,OAAAA,CAAAA;QAC/CP,iBAAAA,CAAkBK,OAAO,CAACM,OAAO,CAACP,IAAAA,CAAAA;AACpC,IAAA,CAAA,EAAG,EAAE,CAAA;IAEL,MAAMQ,oBAAAA,GAAuBT,YAC3B,CAACC,IAAAA,GAAAA;AACC,QAAA,IAAI,CAACA,IAAAA,EAAM;AACT,YAAA;AACF,QAAA;AAEA,QAAA,IAAIV,IAAAA,EAAM;AACRU,YAAAA,IAAAA,CAAKS,eAAe,CAAC,OAAA,CAAA;QACvB,CAAA,MAAO;YACLT,IAAAA,CAAKU,YAAY,CAAC,OAAA,EAAS,EAAA,CAAA;AAC7B,QAAA;IACF,CAAA,EACA;AAACpB,QAAAA;AAAK,KAAA,CAAA;AAGR,IAAA,MAAMqB,gCACJC,GAAA,CAACC,UAAAA,EAAAA;QACCC,SAAAA,EAAU,YAAA;QACVC,UAAAA,EAAW,UAAA;QACXC,GAAAA,EAAKlB,eAAAA;QACLmB,QAAAA,EAAS,QAAA;QACTC,GAAAA,EAAI,MAAA;QACJC,KAAAA,EAAO;YAAEC,IAAAA,EAAM,CAAA;YAAGC,QAAAA,EAAU,CAAA;YAAGC,YAAAA,EAAc,UAAA;YAAYC,UAAAA,EAAY;AAAS,SAAA;AAE7EnC,QAAAA,QAAAA,EAAAA;;AAIL,IAAA,qBACEoC,IAAA,CAACC,GAAAA,EAAAA;;0BACCD,IAAA,CAAC7D,SAAAA,EAAAA;gBAAUqD,GAAAA,EAAK7B,MAAAA;gBAAQlB,MAAAA,EAAQoB,KAAAA;gBAAOnB,aAAAA,EAAec,YAAAA;gBAAc0C,UAAAA,EAAW,QAAA;;kCAC7EF,IAAA,CAACjD,YAAAA,EAAAA;wBACCoD,OAAAA,EAAS5C,aAAAA;wBACT6C,eAAAA,EAAerC,MAAAA;wBACfsC,eAAAA,EAAevC,IAAAA;wBACfwC,IAAAA,EAAK,QAAA;;0CAELlB,GAAA,CAACmB,WAAAA,EAAAA;gCACCC,IAAAA,EAAK,YAAA;gCACLC,aAAW,EAAA,IAAA;gCACXd,KAAAA,EAAO;AACLe,oCAAAA,SAAAA,EAAW,CAAC,OAAO,EAAE5C,OAAO,MAAA,GAAS,QAAA,CAAS,CAAC,CAAC;oCAChD6C,UAAAA,EAAY,CAAC,UAAU,EAAE1E,kBAAAA,CAAAA,CAAoB;oCAC7C2E,UAAAA,EAAY;AACd;;AAED3C,4BAAAA,gBAAAA,iBAAmBmB,GAAA,CAACyB,OAAAA,EAAAA;gCAAQjD,KAAAA,EAAOA,KAAAA;AAAQuB,gCAAAA,QAAAA,EAAAA;AAA6BA,6BAAAA,CAAAA,GAAAA;;;AAE1E1B,oBAAAA,SAAAA,IAAa,sBACZ2B,GAAA,CAACnC,gBAAAA,EAAAA;wBAAiB6D,GAAAA,EAAK,CAAA;wBAAGZ,UAAAA,EAAW,QAAA;AAClCzC,wBAAAA,QAAAA,EAAAA;;;;0BAIP2B,GAAA,CAAClC,WAAAA,EAAAA;gBAAYE,KAAAA,EAAOU,IAAAA;gBAAMiD,EAAAA,EAAIhD,MAAAA;AAC5B,gBAAA,QAAA,gBAAAqB,GAAA,CAAC/B,gBAAAA,EAAAA;oBAAiBmC,GAAAA,EAAKR,oBAAAA;AAAuBtB,oBAAAA,QAAAA,EAAAA;;;;;AAItD,CAAA;AAEA,MAAMsD,YAAAA,GAAe,CAAC,EACpBC,WAAAA,GAAc,KAAK,EACnBnD,IAAAA,EAAMoD,QAAQ,EACd1D,YAAY,EACZC,SAAS,EACTC,QAAQ,EACRyD,QAAQ,EACRxD,MAAM,EACNC,KAAK,EACLC,KAAAA,GAAQ,CAAC,EACS,GAAA;AAClB,IAAA,MAAM,CAACuD,gBAAAA,EAAkBC,mBAAAA,CAAoB,GAAGlD,QAAAA,CAAS8C,WAAAA,CAAAA;AAEzD,IAAA,MAAMK,eAAeJ,QAAAA,KAAaK,SAAAA;IAClC,MAAMzD,IAAAA,GAAOwD,eAAeJ,QAAAA,GAAWE,gBAAAA;AAEvC,IAAA,MAAMI,iBAAAA,GAAoB,IAAA;AACxB,QAAA,MAAMC,OAAO,CAAC3D,IAAAA;AAEd,QAAA,IAAI,CAACwD,YAAAA,EAAc;YACjBD,mBAAAA,CAAoBI,IAAAA,CAAAA;AACtB,QAAA;QAEAN,QAAAA,GAAWM,IAAAA,CAAAA;AACb,IAAA,CAAA;AAEA,IAAA,qBACErC,GAAA,CAAC9B,UAAAA,EAAAA;QACCC,aAAAA,EAAeiE,iBAAAA;QACfhE,YAAAA,EAAcA,YAAAA;QACdC,SAAAA,EAAWA,SAAAA;QACXE,MAAAA,EAAQA,MAAAA;QACRC,KAAAA,EAAOA,KAAAA;QACPC,KAAAA,EAAOA,KAAAA;QACPC,IAAAA,EAAMA,IAAAA;AAELJ,QAAAA,QAAAA,EAAAA;;AAGP;;;;"}
|
|
@@ -9,105 +9,75 @@ var dateFns = require('date-fns');
|
|
|
9
9
|
var reactIntl = require('react-intl');
|
|
10
10
|
var styledComponents = require('styled-components');
|
|
11
11
|
var admin = require('../services/admin.js');
|
|
12
|
-
var theme = require('../constants/theme.js');
|
|
13
12
|
var usePersistentState = require('../hooks/usePersistentState.js');
|
|
13
|
+
var DismissibleBanner = require('./DismissibleBanner.js');
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
);
|
|
21
|
-
position: relative;
|
|
22
|
-
`;
|
|
23
|
-
const FixedButtonWrapper = styledComponents.styled(designSystem.Box)`
|
|
15
|
+
/**
|
|
16
|
+
* Unlike `DismissibleBanner`'s own close button, this has no banner box left to
|
|
17
|
+
* anchor to once dismissed (the banner unmounts entirely), so it stays pinned
|
|
18
|
+
* to the viewport instead.
|
|
19
|
+
*/ const FixedButtonWrapper = styledComponents.styled(designSystem.Box)`
|
|
24
20
|
position: fixed;
|
|
25
21
|
display: flex;
|
|
26
22
|
flex-direction: column;
|
|
27
|
-
z-index:
|
|
23
|
+
z-index: 1;
|
|
28
24
|
align-items: flex-end;
|
|
29
25
|
top: 9px;
|
|
30
26
|
right: 16px;
|
|
31
27
|
`;
|
|
32
28
|
const Banner = ({ isTrialEndedRecently, onDismiss })=>{
|
|
33
29
|
const { formatMessage } = reactIntl.useIntl();
|
|
34
|
-
return /*#__PURE__*/ jsxRuntime.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
children:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
paddingRight: 4,
|
|
70
|
-
fontSize: 2,
|
|
71
|
-
children: formatMessage(isTrialEndedRecently ? {
|
|
72
|
-
id: 'app.components.UpsellBanner.text.ended',
|
|
73
|
-
defaultMessage: 'Keep access to Growth features by upgrading now.'
|
|
74
|
-
} : {
|
|
75
|
-
id: 'app.components.UpsellBanner.text',
|
|
76
|
-
defaultMessage: 'As part of your trial, you can explore premium tools such as Content History, Releases, and Single Sign-On (SSO).'
|
|
77
|
-
})
|
|
78
|
-
})
|
|
79
|
-
]
|
|
80
|
-
}),
|
|
81
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
|
|
82
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.LinkButton, {
|
|
83
|
-
width: "max-content",
|
|
84
|
-
variant: "tertiary",
|
|
85
|
-
href: "https://billing.strapi.io",
|
|
86
|
-
target: "_blank",
|
|
87
|
-
children: formatMessage(isTrialEndedRecently ? {
|
|
88
|
-
id: 'app.components.UpsellBanner.button.ended',
|
|
89
|
-
defaultMessage: 'Keep Growth plan'
|
|
90
|
-
} : {
|
|
91
|
-
id: 'app.components.UpsellBanner.button',
|
|
92
|
-
defaultMessage: 'Upgrade now'
|
|
93
|
-
})
|
|
94
|
-
})
|
|
95
|
-
})
|
|
96
|
-
]
|
|
97
|
-
})
|
|
98
|
-
}),
|
|
99
|
-
/*#__PURE__*/ jsxRuntime.jsx(FixedButtonWrapper, {
|
|
100
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
|
|
101
|
-
withTooltip: false,
|
|
102
|
-
label: formatMessage({
|
|
103
|
-
id: 'app.components.UpsellBanner.close',
|
|
104
|
-
defaultMessage: 'Close'
|
|
105
|
-
}),
|
|
106
|
-
onClick: onDismiss,
|
|
107
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(icons.Cross, {})
|
|
30
|
+
return /*#__PURE__*/ jsxRuntime.jsx(DismissibleBanner.DismissibleBanner, {
|
|
31
|
+
onDismiss: onDismiss,
|
|
32
|
+
closeLabel: formatMessage({
|
|
33
|
+
id: 'app.components.UpsellBanner.close',
|
|
34
|
+
defaultMessage: 'Close'
|
|
35
|
+
}),
|
|
36
|
+
message: /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
37
|
+
children: [
|
|
38
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
|
39
|
+
variant: "delta",
|
|
40
|
+
fontWeight: "bold",
|
|
41
|
+
textColor: "neutral0",
|
|
42
|
+
textAlign: "center",
|
|
43
|
+
fontSize: 2,
|
|
44
|
+
children: formatMessage(isTrialEndedRecently ? {
|
|
45
|
+
id: 'app.components.UpsellBanner.intro.ended',
|
|
46
|
+
defaultMessage: 'Your trial has ended: '
|
|
47
|
+
} : {
|
|
48
|
+
id: 'app.components.UpsellBanner.intro',
|
|
49
|
+
defaultMessage: 'Access to Growth plan features: '
|
|
50
|
+
})
|
|
51
|
+
}),
|
|
52
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
|
53
|
+
variant: "delta",
|
|
54
|
+
textColor: "neutral0",
|
|
55
|
+
textAlign: "center",
|
|
56
|
+
paddingRight: 4,
|
|
57
|
+
fontSize: 2,
|
|
58
|
+
children: formatMessage(isTrialEndedRecently ? {
|
|
59
|
+
id: 'app.components.UpsellBanner.text.ended',
|
|
60
|
+
defaultMessage: 'Keep access to Growth features by upgrading now.'
|
|
61
|
+
} : {
|
|
62
|
+
id: 'app.components.UpsellBanner.text',
|
|
63
|
+
defaultMessage: 'As part of your trial, you can explore premium tools such as Content History, Releases, and Single Sign-On (SSO).'
|
|
64
|
+
})
|
|
108
65
|
})
|
|
66
|
+
]
|
|
67
|
+
}),
|
|
68
|
+
action: /*#__PURE__*/ jsxRuntime.jsx(designSystem.LinkButton, {
|
|
69
|
+
width: "max-content",
|
|
70
|
+
variant: "tertiary",
|
|
71
|
+
href: "https://billing.strapi.io",
|
|
72
|
+
target: "_blank",
|
|
73
|
+
children: formatMessage(isTrialEndedRecently ? {
|
|
74
|
+
id: 'app.components.UpsellBanner.button.ended',
|
|
75
|
+
defaultMessage: 'Keep Growth plan'
|
|
76
|
+
} : {
|
|
77
|
+
id: 'app.components.UpsellBanner.button',
|
|
78
|
+
defaultMessage: 'Upgrade now'
|
|
109
79
|
})
|
|
110
|
-
|
|
80
|
+
})
|
|
111
81
|
});
|
|
112
82
|
};
|
|
113
83
|
const UpsellBanner = ()=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UpsellBanner.js","sources":["../../../../../admin/src/components/UpsellBanner.tsx"],"sourcesContent":["import { useEffect } from 'react';\n\nimport { useLicenseLimits } from '@strapi/admin/strapi-admin/ee';\nimport { Box, Flex, IconButton, LinkButton, Typography } from '@strapi/design-system';\nimport { ArrowsOut, Cross } from '@strapi/icons';\nimport { isAfter, isValid, subDays } from 'date-fns';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useGetLicenseTrialTimeLeftQuery } from '../../src/services/admin';\nimport { RESPONSIVE_DEFAULT_SPACING } from '../constants/theme';\nimport { useScopedPersistentState } from '../hooks/usePersistentState';\n\nconst BannerBackground = styled(Flex)`\n background: linear-gradient(\n 90deg,\n ${({ theme }) => theme.colors.primary600} 0%,\n ${({ theme }) => theme.colors.alternative600} 121.48%\n );\n position: relative;\n`;\n\nconst FixedButtonWrapper = styled(Box)`\n position: fixed;\n display: flex;\n flex-direction: column;\n z-index: 11;\n align-items: flex-end;\n top: 9px;\n right: 16px;\n`;\n\nconst Banner = ({\n isTrialEndedRecently,\n onDismiss,\n}: {\n isTrialEndedRecently: boolean;\n onDismiss: () => void;\n}) => {\n const { formatMessage } = useIntl();\n\n return (\n <>\n <BannerBackground width=\"100%\" justifyContent=\"center\">\n <Flex\n justifyContent=\"center\"\n alignItems=\"center\"\n width=\"100%\"\n paddingTop={2}\n paddingBottom={2}\n paddingLeft={RESPONSIVE_DEFAULT_SPACING}\n paddingRight={RESPONSIVE_DEFAULT_SPACING}\n gap={2}\n >\n <Box>\n <Typography\n variant=\"delta\"\n fontWeight=\"bold\"\n textColor=\"neutral0\"\n textAlign=\"center\"\n fontSize={2}\n >\n {formatMessage(\n isTrialEndedRecently\n ? {\n id: 'app.components.UpsellBanner.intro.ended',\n defaultMessage: 'Your trial has ended: ',\n }\n : {\n id: 'app.components.UpsellBanner.intro',\n defaultMessage: 'Access to Growth plan features: ',\n }\n )}\n </Typography>\n <Typography\n variant=\"delta\"\n textColor=\"neutral0\"\n textAlign=\"center\"\n paddingRight={4}\n fontSize={2}\n >\n {formatMessage(\n isTrialEndedRecently\n ? {\n id: 'app.components.UpsellBanner.text.ended',\n defaultMessage: 'Keep access to Growth features by upgrading now.',\n }\n : {\n id: 'app.components.UpsellBanner.text',\n defaultMessage:\n 'As part of your trial, you can explore premium tools such as Content History, Releases, and Single Sign-On (SSO).',\n }\n )}\n </Typography>\n </Box>\n <Box>\n <LinkButton\n width=\"max-content\"\n variant=\"tertiary\"\n href=\"https://billing.strapi.io\"\n target=\"_blank\"\n >\n {formatMessage(\n isTrialEndedRecently\n ? {\n id: 'app.components.UpsellBanner.button.ended',\n defaultMessage: 'Keep Growth plan',\n }\n : {\n id: 'app.components.UpsellBanner.button',\n defaultMessage: 'Upgrade now',\n }\n )}\n </LinkButton>\n </Box>\n </Flex>\n </BannerBackground>\n <FixedButtonWrapper>\n <IconButton\n withTooltip={false}\n label={formatMessage({\n id: 'app.components.UpsellBanner.close',\n defaultMessage: 'Close',\n })}\n onClick={onDismiss}\n >\n <Cross />\n </IconButton>\n </FixedButtonWrapper>\n </>\n );\n};\n\nconst UpsellBanner = () => {\n const { license } = useLicenseLimits();\n const { formatMessage } = useIntl();\n\n const [cachedTrialEndsAt, setCachedTrialEndsAt] = useScopedPersistentState<string | undefined>(\n 'STRAPI_FREE_TRIAL_ENDS_AT',\n undefined\n );\n\n const [dismissedFor, setDismissedFor] = useScopedPersistentState<string | undefined>(\n 'STRAPI_UPSELL_BANNER_DISMISSED_FOR',\n undefined\n );\n\n const sevenDaysAgo = subDays(new Date(), 7);\n\n const timeLeftData = useGetLicenseTrialTimeLeftQuery(undefined, {\n skip: !license?.isTrial,\n });\n\n useEffect(() => {\n if (timeLeftData.data?.trialEndsAt) {\n setCachedTrialEndsAt(timeLeftData.data.trialEndsAt);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [timeLeftData.data?.trialEndsAt]);\n\n // When the license is not a trial + not EE, and the cached trial end date is found in the localstorage, that means the trial has ended\n // We show the banner to encourage the user to upgrade (for 7 days after the trial ends)\n const isTrialEndedRecently = Boolean(\n !license?.isTrial &&\n !window.strapi.isEE &&\n cachedTrialEndsAt &&\n isAfter(new Date(cachedTrialEndsAt), sevenDaysAgo)\n );\n\n const trialEndsAt = timeLeftData.data?.trialEndsAt ?? cachedTrialEndsAt;\n\n const toCanonicalISO = (v: string | undefined): string | undefined => {\n if (!v) return undefined;\n const date = new Date(v);\n return isValid(date) ? date.toISOString() : undefined;\n };\n\n const isDismissed = Boolean(\n trialEndsAt && toCanonicalISO(dismissedFor) === toCanonicalISO(trialEndsAt)\n );\n\n const handleDismiss = () => setDismissedFor(toCanonicalISO(trialEndsAt));\n const handleReopen = () => setDismissedFor(undefined);\n\n if (!(timeLeftData.data?.trialEndsAt || isTrialEndedRecently)) {\n return null;\n }\n\n if (isDismissed) {\n return (\n <FixedButtonWrapper>\n <IconButton\n withTooltip={false}\n label={formatMessage({\n id: 'app.components.UpsellBanner.reopen',\n defaultMessage: 'Reopen banner',\n })}\n onClick={handleReopen}\n >\n <ArrowsOut />\n </IconButton>\n </FixedButtonWrapper>\n );\n }\n\n return <Banner isTrialEndedRecently={isTrialEndedRecently} onDismiss={handleDismiss} />;\n};\n\nexport { UpsellBanner };\n"],"names":["BannerBackground","styled","Flex","theme","colors","primary600","alternative600","FixedButtonWrapper","Box","Banner","isTrialEndedRecently","onDismiss","formatMessage","useIntl","_jsxs","_Fragment","_jsx","width","justifyContent","alignItems","paddingTop","paddingBottom","paddingLeft","RESPONSIVE_DEFAULT_SPACING","paddingRight","gap","Typography","variant","fontWeight","textColor","textAlign","fontSize","id","defaultMessage","LinkButton","href","target","IconButton","withTooltip","label","onClick","Cross","UpsellBanner","license","useLicenseLimits","cachedTrialEndsAt","setCachedTrialEndsAt","useScopedPersistentState","undefined","dismissedFor","setDismissedFor","sevenDaysAgo","subDays","Date","timeLeftData","useGetLicenseTrialTimeLeftQuery","skip","isTrial","useEffect","data","trialEndsAt","Boolean","window","strapi","isEE","isAfter","toCanonicalISO","v","date","isValid","toISOString","isDismissed","handleDismiss","handleReopen","ArrowsOut"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UpsellBanner.js","sources":["../../../../../admin/src/components/UpsellBanner.tsx"],"sourcesContent":["import { useEffect } from 'react';\n\nimport { useLicenseLimits } from '@strapi/admin/strapi-admin/ee';\nimport { Box, IconButton, LinkButton, Typography } from '@strapi/design-system';\nimport { ArrowsOut } from '@strapi/icons';\nimport { isAfter, isValid, subDays } from 'date-fns';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { useGetLicenseTrialTimeLeftQuery } from '../../src/services/admin';\nimport { useScopedPersistentState } from '../hooks/usePersistentState';\n\nimport { DismissibleBanner } from './DismissibleBanner';\n\n/**\n * Unlike `DismissibleBanner`'s own close button, this has no banner box left to\n * anchor to once dismissed (the banner unmounts entirely), so it stays pinned\n * to the viewport instead.\n */\nconst FixedButtonWrapper = styled(Box)`\n position: fixed;\n display: flex;\n flex-direction: column;\n z-index: 1;\n align-items: flex-end;\n top: 9px;\n right: 16px;\n`;\n\nconst Banner = ({\n isTrialEndedRecently,\n onDismiss,\n}: {\n isTrialEndedRecently: boolean;\n onDismiss: () => void;\n}) => {\n const { formatMessage } = useIntl();\n\n return (\n <DismissibleBanner\n onDismiss={onDismiss}\n closeLabel={formatMessage({\n id: 'app.components.UpsellBanner.close',\n defaultMessage: 'Close',\n })}\n message={\n <>\n <Typography\n variant=\"delta\"\n fontWeight=\"bold\"\n textColor=\"neutral0\"\n textAlign=\"center\"\n fontSize={2}\n >\n {formatMessage(\n isTrialEndedRecently\n ? {\n id: 'app.components.UpsellBanner.intro.ended',\n defaultMessage: 'Your trial has ended: ',\n }\n : {\n id: 'app.components.UpsellBanner.intro',\n defaultMessage: 'Access to Growth plan features: ',\n }\n )}\n </Typography>\n <Typography\n variant=\"delta\"\n textColor=\"neutral0\"\n textAlign=\"center\"\n paddingRight={4}\n fontSize={2}\n >\n {formatMessage(\n isTrialEndedRecently\n ? {\n id: 'app.components.UpsellBanner.text.ended',\n defaultMessage: 'Keep access to Growth features by upgrading now.',\n }\n : {\n id: 'app.components.UpsellBanner.text',\n defaultMessage:\n 'As part of your trial, you can explore premium tools such as Content History, Releases, and Single Sign-On (SSO).',\n }\n )}\n </Typography>\n </>\n }\n action={\n <LinkButton\n width=\"max-content\"\n variant=\"tertiary\"\n href=\"https://billing.strapi.io\"\n target=\"_blank\"\n >\n {formatMessage(\n isTrialEndedRecently\n ? {\n id: 'app.components.UpsellBanner.button.ended',\n defaultMessage: 'Keep Growth plan',\n }\n : {\n id: 'app.components.UpsellBanner.button',\n defaultMessage: 'Upgrade now',\n }\n )}\n </LinkButton>\n }\n />\n );\n};\n\nconst UpsellBanner = () => {\n const { license } = useLicenseLimits();\n const { formatMessage } = useIntl();\n\n const [cachedTrialEndsAt, setCachedTrialEndsAt] = useScopedPersistentState<string | undefined>(\n 'STRAPI_FREE_TRIAL_ENDS_AT',\n undefined\n );\n\n const [dismissedFor, setDismissedFor] = useScopedPersistentState<string | undefined>(\n 'STRAPI_UPSELL_BANNER_DISMISSED_FOR',\n undefined\n );\n\n const sevenDaysAgo = subDays(new Date(), 7);\n\n const timeLeftData = useGetLicenseTrialTimeLeftQuery(undefined, {\n skip: !license?.isTrial,\n });\n\n useEffect(() => {\n if (timeLeftData.data?.trialEndsAt) {\n setCachedTrialEndsAt(timeLeftData.data.trialEndsAt);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [timeLeftData.data?.trialEndsAt]);\n\n // When the license is not a trial + not EE, and the cached trial end date is found in the localstorage, that means the trial has ended\n // We show the banner to encourage the user to upgrade (for 7 days after the trial ends)\n const isTrialEndedRecently = Boolean(\n !license?.isTrial &&\n !window.strapi.isEE &&\n cachedTrialEndsAt &&\n isAfter(new Date(cachedTrialEndsAt), sevenDaysAgo)\n );\n\n const trialEndsAt = timeLeftData.data?.trialEndsAt ?? cachedTrialEndsAt;\n\n const toCanonicalISO = (v: string | undefined): string | undefined => {\n if (!v) return undefined;\n const date = new Date(v);\n return isValid(date) ? date.toISOString() : undefined;\n };\n\n const isDismissed = Boolean(\n trialEndsAt && toCanonicalISO(dismissedFor) === toCanonicalISO(trialEndsAt)\n );\n\n const handleDismiss = () => setDismissedFor(toCanonicalISO(trialEndsAt));\n const handleReopen = () => setDismissedFor(undefined);\n\n if (!(timeLeftData.data?.trialEndsAt || isTrialEndedRecently)) {\n return null;\n }\n\n if (isDismissed) {\n return (\n <FixedButtonWrapper>\n <IconButton\n withTooltip={false}\n label={formatMessage({\n id: 'app.components.UpsellBanner.reopen',\n defaultMessage: 'Reopen banner',\n })}\n onClick={handleReopen}\n >\n <ArrowsOut />\n </IconButton>\n </FixedButtonWrapper>\n );\n }\n\n return <Banner isTrialEndedRecently={isTrialEndedRecently} onDismiss={handleDismiss} />;\n};\n\nexport { UpsellBanner };\n"],"names":["FixedButtonWrapper","styled","Box","Banner","isTrialEndedRecently","onDismiss","formatMessage","useIntl","_jsx","DismissibleBanner","closeLabel","id","defaultMessage","message","_jsxs","_Fragment","Typography","variant","fontWeight","textColor","textAlign","fontSize","paddingRight","action","LinkButton","width","href","target","UpsellBanner","license","useLicenseLimits","cachedTrialEndsAt","setCachedTrialEndsAt","useScopedPersistentState","undefined","dismissedFor","setDismissedFor","sevenDaysAgo","subDays","Date","timeLeftData","useGetLicenseTrialTimeLeftQuery","skip","isTrial","useEffect","data","trialEndsAt","Boolean","window","strapi","isEE","isAfter","toCanonicalISO","v","date","isValid","toISOString","isDismissed","handleDismiss","handleReopen","IconButton","withTooltip","label","onClick","ArrowsOut"],"mappings":"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"}
|
|
@@ -1,111 +1,81 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { useEffect } from 'react';
|
|
3
3
|
import { useLicenseLimits } from '@strapi/admin/strapi-admin/ee';
|
|
4
|
-
import { IconButton, Box,
|
|
5
|
-
import { ArrowsOut
|
|
4
|
+
import { IconButton, Box, LinkButton, Typography } from '@strapi/design-system';
|
|
5
|
+
import { ArrowsOut } from '@strapi/icons';
|
|
6
6
|
import { subDays, isAfter, isValid } from 'date-fns';
|
|
7
7
|
import { useIntl } from 'react-intl';
|
|
8
8
|
import { styled } from 'styled-components';
|
|
9
9
|
import { useGetLicenseTrialTimeLeftQuery } from '../services/admin.mjs';
|
|
10
|
-
import { RESPONSIVE_DEFAULT_SPACING } from '../constants/theme.mjs';
|
|
11
10
|
import { useScopedPersistentState } from '../hooks/usePersistentState.mjs';
|
|
11
|
+
import { DismissibleBanner } from './DismissibleBanner.mjs';
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
);
|
|
19
|
-
position: relative;
|
|
20
|
-
`;
|
|
21
|
-
const FixedButtonWrapper = styled(Box)`
|
|
13
|
+
/**
|
|
14
|
+
* Unlike `DismissibleBanner`'s own close button, this has no banner box left to
|
|
15
|
+
* anchor to once dismissed (the banner unmounts entirely), so it stays pinned
|
|
16
|
+
* to the viewport instead.
|
|
17
|
+
*/ const FixedButtonWrapper = styled(Box)`
|
|
22
18
|
position: fixed;
|
|
23
19
|
display: flex;
|
|
24
20
|
flex-direction: column;
|
|
25
|
-
z-index:
|
|
21
|
+
z-index: 1;
|
|
26
22
|
align-items: flex-end;
|
|
27
23
|
top: 9px;
|
|
28
24
|
right: 16px;
|
|
29
25
|
`;
|
|
30
26
|
const Banner = ({ isTrialEndedRecently, onDismiss })=>{
|
|
31
27
|
const { formatMessage } = useIntl();
|
|
32
|
-
return /*#__PURE__*/
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
children:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
paddingRight: 4,
|
|
68
|
-
fontSize: 2,
|
|
69
|
-
children: formatMessage(isTrialEndedRecently ? {
|
|
70
|
-
id: 'app.components.UpsellBanner.text.ended',
|
|
71
|
-
defaultMessage: 'Keep access to Growth features by upgrading now.'
|
|
72
|
-
} : {
|
|
73
|
-
id: 'app.components.UpsellBanner.text',
|
|
74
|
-
defaultMessage: 'As part of your trial, you can explore premium tools such as Content History, Releases, and Single Sign-On (SSO).'
|
|
75
|
-
})
|
|
76
|
-
})
|
|
77
|
-
]
|
|
78
|
-
}),
|
|
79
|
-
/*#__PURE__*/ jsx(Box, {
|
|
80
|
-
children: /*#__PURE__*/ jsx(LinkButton, {
|
|
81
|
-
width: "max-content",
|
|
82
|
-
variant: "tertiary",
|
|
83
|
-
href: "https://billing.strapi.io",
|
|
84
|
-
target: "_blank",
|
|
85
|
-
children: formatMessage(isTrialEndedRecently ? {
|
|
86
|
-
id: 'app.components.UpsellBanner.button.ended',
|
|
87
|
-
defaultMessage: 'Keep Growth plan'
|
|
88
|
-
} : {
|
|
89
|
-
id: 'app.components.UpsellBanner.button',
|
|
90
|
-
defaultMessage: 'Upgrade now'
|
|
91
|
-
})
|
|
92
|
-
})
|
|
93
|
-
})
|
|
94
|
-
]
|
|
95
|
-
})
|
|
96
|
-
}),
|
|
97
|
-
/*#__PURE__*/ jsx(FixedButtonWrapper, {
|
|
98
|
-
children: /*#__PURE__*/ jsx(IconButton, {
|
|
99
|
-
withTooltip: false,
|
|
100
|
-
label: formatMessage({
|
|
101
|
-
id: 'app.components.UpsellBanner.close',
|
|
102
|
-
defaultMessage: 'Close'
|
|
103
|
-
}),
|
|
104
|
-
onClick: onDismiss,
|
|
105
|
-
children: /*#__PURE__*/ jsx(Cross, {})
|
|
28
|
+
return /*#__PURE__*/ jsx(DismissibleBanner, {
|
|
29
|
+
onDismiss: onDismiss,
|
|
30
|
+
closeLabel: formatMessage({
|
|
31
|
+
id: 'app.components.UpsellBanner.close',
|
|
32
|
+
defaultMessage: 'Close'
|
|
33
|
+
}),
|
|
34
|
+
message: /*#__PURE__*/ jsxs(Fragment, {
|
|
35
|
+
children: [
|
|
36
|
+
/*#__PURE__*/ jsx(Typography, {
|
|
37
|
+
variant: "delta",
|
|
38
|
+
fontWeight: "bold",
|
|
39
|
+
textColor: "neutral0",
|
|
40
|
+
textAlign: "center",
|
|
41
|
+
fontSize: 2,
|
|
42
|
+
children: formatMessage(isTrialEndedRecently ? {
|
|
43
|
+
id: 'app.components.UpsellBanner.intro.ended',
|
|
44
|
+
defaultMessage: 'Your trial has ended: '
|
|
45
|
+
} : {
|
|
46
|
+
id: 'app.components.UpsellBanner.intro',
|
|
47
|
+
defaultMessage: 'Access to Growth plan features: '
|
|
48
|
+
})
|
|
49
|
+
}),
|
|
50
|
+
/*#__PURE__*/ jsx(Typography, {
|
|
51
|
+
variant: "delta",
|
|
52
|
+
textColor: "neutral0",
|
|
53
|
+
textAlign: "center",
|
|
54
|
+
paddingRight: 4,
|
|
55
|
+
fontSize: 2,
|
|
56
|
+
children: formatMessage(isTrialEndedRecently ? {
|
|
57
|
+
id: 'app.components.UpsellBanner.text.ended',
|
|
58
|
+
defaultMessage: 'Keep access to Growth features by upgrading now.'
|
|
59
|
+
} : {
|
|
60
|
+
id: 'app.components.UpsellBanner.text',
|
|
61
|
+
defaultMessage: 'As part of your trial, you can explore premium tools such as Content History, Releases, and Single Sign-On (SSO).'
|
|
62
|
+
})
|
|
106
63
|
})
|
|
64
|
+
]
|
|
65
|
+
}),
|
|
66
|
+
action: /*#__PURE__*/ jsx(LinkButton, {
|
|
67
|
+
width: "max-content",
|
|
68
|
+
variant: "tertiary",
|
|
69
|
+
href: "https://billing.strapi.io",
|
|
70
|
+
target: "_blank",
|
|
71
|
+
children: formatMessage(isTrialEndedRecently ? {
|
|
72
|
+
id: 'app.components.UpsellBanner.button.ended',
|
|
73
|
+
defaultMessage: 'Keep Growth plan'
|
|
74
|
+
} : {
|
|
75
|
+
id: 'app.components.UpsellBanner.button',
|
|
76
|
+
defaultMessage: 'Upgrade now'
|
|
107
77
|
})
|
|
108
|
-
|
|
78
|
+
})
|
|
109
79
|
});
|
|
110
80
|
};
|
|
111
81
|
const UpsellBanner = ()=>{
|