diff --git a/package.json b/package.json index 34d60226..019aa775 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,6 @@ "rehype-raw": "7.0.0", "remark-gfm": "4.0.0", "resize-observer-polyfill": "1.5.1", - "styled-container-query": "1.3.5", "type-fest": "4.8.3", "use-immer": "0.9.0", "usehooks-ts": "2.9.1" diff --git a/src/components/pricingcalculator/PricingCalculator.tsx b/src/components/pricingcalculator/PricingCalculator.tsx deleted file mode 100644 index ac6a55bf..00000000 --- a/src/components/pricingcalculator/PricingCalculator.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { forwardRef, useMemo, useState } from 'react' - -import Callout from '../Callout' - -import { - PROVIDERS, - PricingCalculatorContainerQuery, - PricingCalculatorWrap, - estimateProviderCost, -} from './misc' -import AppsControl from './controls/AppsControl' -import ProviderControl from './controls/ProvidersControl' -import Cost from './costs/Cost' -import Costs from './costs/Costs' -import TotalCost from './costs/TotalCost' - -export type PricingCalculatorProps = { - appsDefault?: number - expandedDefault?: boolean -} - -const PricingCalculator = forwardRef( - ({ appsDefault = 5, expandedDefault = false }, ref) => { - const [expanded, setExpanded] = useState(expandedDefault) - const [providerId, setProviderId] = useState(PROVIDERS[0].id) - const [apps, setApps] = useState(appsDefault) - const provider = useMemo( - () => PROVIDERS.find(({ id }) => id === providerId), - [providerId] - ) - const providerCost = useMemo( - () => estimateProviderCost(provider, apps), - [provider, apps] - ) - - return ( - - - -

- Estimate your cloud cost to get started with Plural open-source. -

-
-
- - -
-
- - - - - - -
-
-
-
-
- ) - } -) - -export default PricingCalculator diff --git a/src/components/pricingcalculator/PricingCalculatorExtended.tsx b/src/components/pricingcalculator/PricingCalculatorExtended.tsx deleted file mode 100644 index 7280dd15..00000000 --- a/src/components/pricingcalculator/PricingCalculatorExtended.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import { forwardRef, useEffect, useMemo, useState } from 'react' -import { Switch } from 'honorable' - -import { useTheme } from 'styled-components' - -import Card, { type CardProps } from '../Card' - -import { - PROVIDERS, - PricingCalculatorContainerQuery, - PricingCalculatorWrap, - estimatePluralCost, - estimateProviderCost, -} from './misc' -import AppsControl from './controls/AppsControl' -import ProviderControl from './controls/ProvidersControl' -import Cost from './costs/Cost' -import UsersControl from './controls/UsersControl' -import ClustersControl from './controls/ClustersControl' -import Costs from './costs/Costs' -import TotalCost from './costs/TotalCost' - -export type PricingCalculatorProps = { - appsDefault?: number - clustersDefault?: number - usersDefault?: number - professionalDefault?: boolean -} & CardProps - -const PricingCalculatorExtended = forwardRef< - HTMLDivElement, - PricingCalculatorProps ->( - ( - { - appsDefault = 5, - clustersDefault = 1, - usersDefault = 0, - professionalDefault = false, - ...props - }, - ref - ) => { - const theme = useTheme() - const [providerId, setProviderId] = useState(PROVIDERS[0].id) - const [clusters, setClusters] = useState(clustersDefault) - const [apps, setApps] = useState(appsDefault) - const [users, setUsers] = useState(usersDefault) - const [enforcedPro, setEnforcedPro] = useState(users > 5) - const [professional, setProfessional] = useState( - professionalDefault || enforcedPro - ) - const provider = useMemo( - () => PROVIDERS.find(({ id }) => id === providerId), - [providerId] - ) - const providerCost = useMemo( - () => estimateProviderCost(provider, apps, clusters), - [provider, apps, clusters] - ) - const pluralCost = useMemo( - () => estimatePluralCost(professional, clusters, users), - [professional, clusters, users] - ) - - useEffect(() => { - if (users > 5 && !professional) { - setProfessional(true) - setEnforcedPro(true) - } - if (users <= 5 && enforcedPro) { - setProfessional(false) - setEnforcedPro(false) - } - }, [users, professional, setProfessional, enforcedPro, setEnforcedPro]) - - return ( - - - -
-
- - - - -
- *Accounts requiring {'>'}6 clusters or {'>'}60 users should - reach out to discuss our Enterprise option to optimize plan - costs to your specific needs. -
-
-
- 5} - checked={professional} - onChange={({ target: { checked } }) => - setProfessional(checked) - } - marginBottom="xlarge" - > - Professional plan - - - - - - - - - - - -
-
-
-
-
- ) - } -) - -export default PricingCalculatorExtended diff --git a/src/components/pricingcalculator/controls/AppsControl.tsx b/src/components/pricingcalculator/controls/AppsControl.tsx deleted file mode 100644 index eaaabc26..00000000 --- a/src/components/pricingcalculator/controls/AppsControl.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { type Dispatch } from 'react' - -import Slider from '../../Slider' - -import Control from './Control' - -type AppsControlProps = { - header: string - caption?: string - apps: number - setApps: Dispatch -} - -export default function AppsControl({ - header, - caption, - apps, - setApps, -}: AppsControlProps) { - return ( - - ({ value }))} - onChange={(v) => setApps(v)} - /> - - ) -} diff --git a/src/components/pricingcalculator/controls/ClustersControl.tsx b/src/components/pricingcalculator/controls/ClustersControl.tsx deleted file mode 100644 index bc69a2b1..00000000 --- a/src/components/pricingcalculator/controls/ClustersControl.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { type Dispatch } from 'react' - -import Slider from '../../Slider' - -import Control from './Control' - -type ClustersControlProps = { - clusters: number - setClusters: Dispatch -} - -export default function ClustersControl({ - clusters, - setClusters, -}: ClustersControlProps) { - return ( - - setClusters(v)} - /> - - ) -} diff --git a/src/components/pricingcalculator/controls/Control.tsx b/src/components/pricingcalculator/controls/Control.tsx deleted file mode 100644 index 2304ee56..00000000 --- a/src/components/pricingcalculator/controls/Control.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { type FocusableElement } from '@react-types/shared' -import { type DOMAttributes, type ReactElement } from 'react' -import styled from 'styled-components' - -const ControlWrap = styled.div(({ theme }) => ({ - marginBottom: theme.spacing.xlarge, - - '.header': { - ...theme.partials.text.body2Bold, - color: theme.colors.text, - - '&.without-caption': { - marginBottom: theme.spacing.medium, - }, - }, - - '.caption': { - ...theme.partials.text.caption, - color: theme.colors['text-xlight'], - marginBottom: theme.spacing.medium, - }, -})) - -type ControlProps = { - header: string - caption?: string - children: ReactElement | ReactElement[] | string - labelProps?: DOMAttributes -} - -export default function Control({ - header, - caption, - children, - labelProps, -}: ControlProps) { - return ( - -
-
- {header} -
- {caption &&
{caption}
} -
- {children} -
- ) -} diff --git a/src/components/pricingcalculator/controls/ProvidersControl.tsx b/src/components/pricingcalculator/controls/ProvidersControl.tsx deleted file mode 100644 index 2c1e6bae..00000000 --- a/src/components/pricingcalculator/controls/ProvidersControl.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { type Dispatch, createElement } from 'react' -import styled from 'styled-components' -import { useRadioGroupState } from 'react-stately' -import { useRadioGroup } from 'react-aria' - -import SelectItem from '../../SelectItem' -import { PROVIDERS } from '../misc' -import { RadioContext } from '../../RadioGroup' - -import Control from './Control' - -const ProvidersWrap = styled.div(({ theme }) => ({ - display: 'flex', - flexDirection: 'row', - gap: theme.spacing.small, -})) - -type ProviderControlProps = { - header: string - caption?: string - providerId: string - setProviderId: Dispatch -} - -export default function ProviderControl({ - header, - caption, - providerId, - setProviderId, -}: ProviderControlProps) { - const providerRadioGroupProps = { - label: header, - description: 'caption', - value: providerId, - onChange: (id: string) => { - setProviderId(id) - }, - } - const state = useRadioGroupState(providerRadioGroupProps) - const { radioGroupProps, labelProps } = useRadioGroup( - providerRadioGroupProps, - state - ) - - return ( - - - - {PROVIDERS.map(({ id, name, icon }) => ( - - ))} - - - - ) -} diff --git a/src/components/pricingcalculator/controls/UsersControl.tsx b/src/components/pricingcalculator/controls/UsersControl.tsx deleted file mode 100644 index f769e8e0..00000000 --- a/src/components/pricingcalculator/controls/UsersControl.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { type Dispatch } from 'react' - -import Radio from '../../Radio' -import RadioGroup from '../../RadioGroup' - -import Control from './Control' - -const OPTIONS = [ - { - value: '0', - label: '0-5', - }, - { - value: '10', - label: '10', - }, - { - value: '30', - label: '30', - }, - { - value: '60', - label: '60*', - }, -] - -type UsersControlProps = { - users: number - setUsers: Dispatch -} - -export default function UsersControl({ users, setUsers }: UsersControlProps) { - return ( - - setUsers(parseInt(s))} - display="flex" - gap="medium" - > - {OPTIONS.map(({ value, label }) => ( - - {label} - - ))} - - - ) -} diff --git a/src/components/pricingcalculator/costs/Cost.tsx b/src/components/pricingcalculator/costs/Cost.tsx deleted file mode 100644 index 6b1e3aea..00000000 --- a/src/components/pricingcalculator/costs/Cost.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import styled from 'styled-components' - -import InfoOutlineIcon from '../../icons/InfoOutlineIcon' -import Tooltip from '../../Tooltip' - -const CostWrap = styled.div(({ theme }) => ({ - display: 'flex', - flexDirection: 'row', - flexGrow: 1, - flexShrink: 1, - gap: theme.spacing.xsmall, - alignItems: 'center', - - '.value': { - ...theme.partials.text.subtitle2, - color: theme.colors.text, - minWidth: theme.spacing.xxlarge, - marginRight: theme.spacing.xxxsmall, - }, -})) - -export type CostProps = { - cost: number - label: string - tooltip?: string -} - -export default function Cost({ cost, label, tooltip }: CostProps) { - return ( - -
${cost}
-
{label}
- {tooltip && ( - - - - )} -
- ) -} diff --git a/src/components/pricingcalculator/costs/Costs.tsx b/src/components/pricingcalculator/costs/Costs.tsx deleted file mode 100644 index c06345cf..00000000 --- a/src/components/pricingcalculator/costs/Costs.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { type ReactElement } from 'react' -import styled from 'styled-components' - -type CostsWrapProps = { - marginTop?: number -} - -const CostsWrap = styled.div(({ theme, marginTop }) => ({ - display: 'flex', - flexDirection: 'column', - gap: 14, - marginTop, - - '.header': { - ...theme.partials.text.overline, - color: theme.colors.text, - }, -})) - -export type CostsProps = { - header?: string - marginTop?: number - children: ReactElement | ReactElement[] | string -} - -export default function Costs({ header, marginTop, children }: CostsProps) { - return ( - - {header &&
{header}
} - {children} -
- ) -} diff --git a/src/components/pricingcalculator/costs/TotalCost.tsx b/src/components/pricingcalculator/costs/TotalCost.tsx deleted file mode 100644 index e249dab5..00000000 --- a/src/components/pricingcalculator/costs/TotalCost.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import styled from 'styled-components' - -type TotalCostWrapProps = { - marginTop?: number -} - -const TotalCostWrap = styled.div( - ({ theme, marginTop }) => ({ - display: 'flex', - gap: theme.spacing.xxlarge, - marginTop: marginTop || theme.spacing.xxlarge, - - '.value': { - ...theme.partials.text.title1, - color: theme.colors['text-warning-light'], - marginRight: theme.spacing.xxsmall, - - '&.primary': { - color: theme.colors.purple[200], - }, - }, - - '.provider': { - ...theme.partials.text.body2Bold, - color: theme.colors.text, - }, - }) -) - -export type TotalCostProps = { - providerCost: number - provider: string - pluralCost?: number - proPlan?: boolean - marginTop?: number -} - -export default function TotalCost({ - providerCost, - provider, - pluralCost, - proPlan, - marginTop, -}: TotalCostProps) { - return ( - -
-
~${providerCost}
-
- per month to {provider} -
-
- {!!pluralCost && proPlan && ( -
-
${pluralCost}
-
- (Professional) Plural -
-
- )} -
- ) -} diff --git a/src/components/pricingcalculator/misc.tsx b/src/components/pricingcalculator/misc.tsx deleted file mode 100644 index df96b968..00000000 --- a/src/components/pricingcalculator/misc.tsx +++ /dev/null @@ -1,160 +0,0 @@ -import { type ComponentType } from 'react' -import styled from 'styled-components' - -// @ts-ignore -import styledContainerQuery from 'styled-container-query' - -import AwsLogoIcon from '../icons/AwsLogoIcon' -import AzureLogoIcon from '../icons/AzureLogoIcon' -import { type IconProps } from '../icons/createIcon' -import GoogleCloudLogoIcon from '../icons/GoogleCloudLogoIcon' - -export const CLUSTER_PRICE = 399 -export const USER_PRICE = 49 - -type Provider = { - name: string - id: string - icon: ComponentType - k8sPrice: number - infraPrice: number - appPrice: number // Additional instance cost. Each instance can handle 2 apps. -} - -export const PROVIDERS: Provider[] = [ - { - name: 'AWS', - id: 'aws', - icon: AwsLogoIcon, - k8sPrice: 73, - infraPrice: 165, - appPrice: 54.9, - }, - { - name: 'GCP', - id: 'gcp', - icon: GoogleCloudLogoIcon, - k8sPrice: 73, - infraPrice: 221, - appPrice: 48.92, - }, - { - name: 'Azure', - id: 'azure', - icon: AzureLogoIcon, - k8sPrice: 72, - infraPrice: 147, - appPrice: 73.73, - }, -] - -type ProviderCostEstimation = { - k8s: number - infra: number - app: number - total: number -} - -export function estimateProviderCost( - provider: Provider, - appCount: number, - clusterCount = 1 -): ProviderCostEstimation { - if (!provider) { - return { - total: 0, - k8s: 0, - infra: 0, - app: 0, - } - } - - const { k8sPrice = 0, infraPrice = 0, appPrice = 0 } = provider - const k8s = Math.round(k8sPrice * clusterCount) - const infra = Math.round(infraPrice) - - // First 5 apps do not raise the cost, then for every 2 apps we add one more instance. - const app = - appCount <= 5 ? 0 : Math.round(Math.floor((appCount - 4) / 2) * appPrice) - - return { - k8s, - infra, - app, - total: k8s + infra + app, - } -} - -type PluralCostEstimation = { - clusters: number - users: number - total: number -} - -export function estimatePluralCost( - isProPlan: boolean, - clusterCount: number, - userCount: number -): PluralCostEstimation { - const pro = isProPlan ? 1 : 0 - const clusters = clusterCount * CLUSTER_PRICE * pro - const users = userCount * USER_PRICE * pro - - return { - clusters, - users, - total: clusters + users, - } -} - -export const PricingCalculatorWrap = styled.div(({ theme }) => ({ - ...theme.partials.text.body2, - color: theme.colors['text-xlight'], - - p: { - color: theme.colors['text-light'], - marginBottom: theme.spacing.xlarge, - }, - - '.content': { - display: 'flex', - flexDirection: 'row', - flexGrow: 1, - flexShrink: 1, - gap: theme.spacing.xxxlarge, - - '&.with-padding': { - paddingBottom: theme.spacing.medium, - }, - - '.column': { - display: 'flex', - flexBasis: '100%', - flexDirection: 'column', - flexGrow: 1, - flexShrink: 1, - }, - }, - - '.hint': { - ...theme.partials.text.caption, - color: theme.colors['text-xlight'], - marginBottom: theme.spacing.medium, - fontStyle: 'italic', - }, -})) - -// If https://github.com/styled-components/styled-components/issues/416 -// will be fixed then we can remove it and use above wrapper. -export const PricingCalculatorContainerQuery = styledContainerQuery.div` - &:container(max-width: 620px) { - .content { - flex-direction: column; - gap: 32px; - } - - .hint { - margin-bottom: 0; - } -}, -` diff --git a/src/index.ts b/src/index.ts index afa7d72a..4ea3e4c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -123,8 +123,6 @@ export type { } from './components/AppList' export { AppList } from './components/AppList' export { default as Slider } from './components/Slider' -export { default as PricingCalculator } from './components/pricingcalculator/PricingCalculator' -export { default as PricingCalculatorExtended } from './components/pricingcalculator/PricingCalculatorExtended' export { default as Layer } from './components/Layer' export { Breadcrumbs } from './components/Breadcrumbs' export { DatePicker } from './components/DatePicker' diff --git a/src/markdoc/tags/calculator.markdoc.ts b/src/markdoc/tags/calculator.markdoc.ts deleted file mode 100644 index 85b4842d..00000000 --- a/src/markdoc/tags/calculator.markdoc.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Tag } from '@markdoc/markdoc' - -import PricingCalculatorExtended from '../../components/pricingcalculator/PricingCalculatorExtended' - -export const calculator = { - render: PricingCalculatorExtended, - description: 'Display extended version of pricing calculator', - transform() { - return new Tag(this.render as any) - }, -} diff --git a/src/markdoc/tags/index.ts b/src/markdoc/tags/index.ts index 24254e6e..d933b502 100644 --- a/src/markdoc/tags/index.ts +++ b/src/markdoc/tags/index.ts @@ -1,6 +1,5 @@ /* Use this file to export your markdoc tags */ export * from './callout.markdoc' -export * from './calculator.markdoc' export * from './embed.markdoc' export * from './tabs.markdoc' export * from './figure.markdoc' diff --git a/src/stories/PricingCalculator.stories.tsx b/src/stories/PricingCalculator.stories.tsx deleted file mode 100644 index 5c3dd082..00000000 --- a/src/stories/PricingCalculator.stories.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import PricingCalculator from '../components/pricingcalculator/PricingCalculator' - -export default { - title: 'Pricing Calculator', - component: PricingCalculator, -} - -function Template(args: any) { - return -} - -export const Default = Template.bind({}) - -Default.args = { - appsDefault: 15, - expandedDefault: true, -} diff --git a/src/stories/PricingCalculatorExtended.stories.tsx b/src/stories/PricingCalculatorExtended.stories.tsx deleted file mode 100644 index 60e1eb84..00000000 --- a/src/stories/PricingCalculatorExtended.stories.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import PricingCalculatorExtended from '../components/pricingcalculator/PricingCalculatorExtended' - -export default { - title: 'Pricing Calculator Extended', - component: PricingCalculatorExtended, -} - -function Template(args: any) { - return -} - -export const Default = Template.bind({}) - -Default.args = { - appsDefault: 5, - clustersDefault: 1, - usersDefault: 0, - professionalDefualt: false, - fillLevel: 2, -} diff --git a/yarn.lock b/yarn.lock index db95ef73..5fc17ae3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2657,7 +2657,6 @@ __metadata: rimraf: 5.0.5 storybook: 8.3.5 styled-components: 6.1.13 - styled-container-query: 1.3.5 type-fest: 4.8.3 typescript: 5.6.2 use-immer: 0.9.0 @@ -7443,13 +7442,6 @@ __metadata: languageName: node linkType: hard -"classnames@npm:^2.2.6": - version: 2.5.1 - resolution: "classnames@npm:2.5.1" - checksum: da424a8a6f3a96a2e87d01a432ba19315503294ac7e025f9fece656db6b6a0f7b5003bb1fbb51cbb0d9624d964f1b9bb35a51c73af9b2434c7b292c42231c1e5 - languageName: node - linkType: hard - "clean-stack@npm:^2.0.0": version: 2.2.0 resolution: "clean-stack@npm:2.2.0" @@ -10662,7 +10654,7 @@ __metadata: languageName: node linkType: hard -"hoist-non-react-statics@npm:^3.3.1, hoist-non-react-statics@npm:^3.3.2": +"hoist-non-react-statics@npm:^3.3.1": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" dependencies: @@ -15665,13 +15657,6 @@ __metadata: languageName: node linkType: hard -"resize-observer@npm:^1.0.0": - version: 1.0.4 - resolution: "resize-observer@npm:1.0.4" - checksum: 43e2f45e40507279cad474f6bd2fe62e92de1fd1d67cd5285ece1fec6c1b664c4d3795b094b2be292244bf542b1b5402578670400beadc2cfedac8fb483a0976 - languageName: node - linkType: hard - "resolve-from@npm:^4.0.0": version: 4.0.0 resolution: "resolve-from@npm:4.0.0" @@ -16187,13 +16172,6 @@ __metadata: languageName: node linkType: hard -"shorthash@npm:0.0.2": - version: 0.0.2 - resolution: "shorthash@npm:0.0.2" - checksum: 4048833f2a7f324350cc1a48a6b64bca268e5a2e9c59cb6cad3607c41fd800bf1739498fe4b8b6737709cdb540fb74125fb7254eba98bdd3dc41e8d9f7990b20 - languageName: node - linkType: hard - "side-channel@npm:^1.0.4, side-channel@npm:^1.0.6": version: 1.0.6 resolution: "side-channel@npm:1.0.6" @@ -16798,22 +16776,6 @@ __metadata: languageName: node linkType: hard -"styled-container-query@npm:1.3.5": - version: 1.3.5 - resolution: "styled-container-query@npm:1.3.5" - dependencies: - classnames: ^2.2.6 - hoist-non-react-statics: ^3.3.2 - resize-observer: ^1.0.0 - shorthash: 0.0.2 - peerDependencies: - react: ^16.9.0 - react-dom: ^16.9.0 - styled-components: ^4.3.2 - checksum: 4bc8e046234ce39b33df199603bf4a3887abb5239966d5b3904b45b79889385320bd0df7129a0805c945947aa692ca6b950296d041ee68b6b667f912926c3b77 - languageName: node - linkType: hard - "stylis@npm:4.2.0": version: 4.2.0 resolution: "stylis@npm:4.2.0"