myoperator-ui 0.0.200 → 0.0.201-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +574 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9135,25 +9135,25 @@ const SummaryRow = ({ item }: { item: PaymentSummaryItem }) => (
|
|
|
9135
9135
|
<div className="flex flex-col gap-0.5">
|
|
9136
9136
|
<span
|
|
9137
9137
|
className={cn(
|
|
9138
|
-
"
|
|
9138
|
+
"tracking-[0.035px]",
|
|
9139
9139
|
item.bold
|
|
9140
|
-
? "font-semibold text-semantic-text-primary"
|
|
9141
|
-
: "text-semantic-text-muted"
|
|
9140
|
+
? "text-base font-semibold text-semantic-text-primary"
|
|
9141
|
+
: "text-sm text-semantic-text-muted"
|
|
9142
9142
|
)}
|
|
9143
9143
|
>
|
|
9144
9144
|
{item.label}
|
|
9145
9145
|
</span>
|
|
9146
|
-
<span className="text-
|
|
9146
|
+
<span className="text-sm text-semantic-text-link tracking-[0.06px]">
|
|
9147
9147
|
{item.hint}
|
|
9148
9148
|
</span>
|
|
9149
9149
|
</div>
|
|
9150
9150
|
) : (
|
|
9151
9151
|
<span
|
|
9152
9152
|
className={cn(
|
|
9153
|
-
"
|
|
9153
|
+
"tracking-[0.035px]",
|
|
9154
9154
|
item.bold
|
|
9155
|
-
? "font-semibold text-semantic-text-primary"
|
|
9156
|
-
: "text-semantic-text-muted"
|
|
9155
|
+
? "text-base font-semibold text-semantic-text-primary"
|
|
9156
|
+
: "text-sm text-semantic-text-muted"
|
|
9157
9157
|
)}
|
|
9158
9158
|
>
|
|
9159
9159
|
{item.label}
|
|
@@ -9673,6 +9673,573 @@ export interface PaymentOptionCardProps {
|
|
|
9673
9673
|
content: prefixTailwindClasses(`export { PaymentOptionCard } from "./payment-option-card";
|
|
9674
9674
|
export { PaymentOptionCardModal } from "./payment-option-card-modal";
|
|
9675
9675
|
export type { PaymentOptionCardProps, PaymentOption } from "./types";
|
|
9676
|
+
`, prefix)
|
|
9677
|
+
}
|
|
9678
|
+
]
|
|
9679
|
+
},
|
|
9680
|
+
"plan-upgrade-modal": {
|
|
9681
|
+
name: "plan-upgrade-modal",
|
|
9682
|
+
description: "A modal for selecting whether a plan upgrade is applied in the current or upcoming billing cycle",
|
|
9683
|
+
category: "custom",
|
|
9684
|
+
dependencies: [
|
|
9685
|
+
"clsx",
|
|
9686
|
+
"tailwind-merge",
|
|
9687
|
+
"lucide-react",
|
|
9688
|
+
"@radix-ui/react-dialog"
|
|
9689
|
+
],
|
|
9690
|
+
internalDependencies: [
|
|
9691
|
+
"button",
|
|
9692
|
+
"dialog"
|
|
9693
|
+
],
|
|
9694
|
+
isMultiFile: true,
|
|
9695
|
+
directory: "plan-upgrade-modal",
|
|
9696
|
+
mainFile: "plan-upgrade-modal.tsx",
|
|
9697
|
+
files: [
|
|
9698
|
+
{
|
|
9699
|
+
name: "plan-upgrade-modal.tsx",
|
|
9700
|
+
content: prefixTailwindClasses(`import * as React from "react";
|
|
9701
|
+
import { cva } from "class-variance-authority";
|
|
9702
|
+
import { CalendarDays, Clock3, X } from "lucide-react";
|
|
9703
|
+
import { cn } from "../../../lib/utils";
|
|
9704
|
+
import { Button } from "../button";
|
|
9705
|
+
import { Dialog, DialogContent, DialogDescription, DialogTitle } from "../dialog";
|
|
9706
|
+
import type { BillingCycleOption, PlanUpgradeModalProps } from "./types";
|
|
9707
|
+
|
|
9708
|
+
const modalRootVariants = cva(
|
|
9709
|
+
"flex flex-col gap-6 rounded-lg border border-semantic-border-layout bg-semantic-bg-primary p-9"
|
|
9710
|
+
);
|
|
9711
|
+
|
|
9712
|
+
const billingCycleOptionVariants = cva(
|
|
9713
|
+
"flex w-full items-center gap-2.5 rounded-lg border bg-semantic-bg-primary p-3 text-left transition-colors",
|
|
9714
|
+
{
|
|
9715
|
+
variants: {
|
|
9716
|
+
selected: {
|
|
9717
|
+
true: "border-semantic-border-input-focus",
|
|
9718
|
+
false: "border-semantic-border-layout hover:border-semantic-border-input",
|
|
9719
|
+
},
|
|
9720
|
+
},
|
|
9721
|
+
defaultVariants: {
|
|
9722
|
+
selected: false,
|
|
9723
|
+
},
|
|
9724
|
+
}
|
|
9725
|
+
);
|
|
9726
|
+
|
|
9727
|
+
const iconContainerVariants = cva(
|
|
9728
|
+
"flex size-[34px] shrink-0 items-center justify-center rounded-lg bg-semantic-info-surface"
|
|
9729
|
+
);
|
|
9730
|
+
|
|
9731
|
+
const defaultOptions: BillingCycleOption[] = [
|
|
9732
|
+
{ id: "current-billing-cycle", label: "Current billing cycle", icon: "clock" },
|
|
9733
|
+
{ id: "upcoming-billing-cycle", label: "Upcoming billing cycle", icon: "calendar" },
|
|
9734
|
+
];
|
|
9735
|
+
|
|
9736
|
+
const renderOptionIcon = (icon: BillingCycleOption["icon"]) => {
|
|
9737
|
+
if (icon === "calendar") {
|
|
9738
|
+
return <CalendarDays className="size-5 text-semantic-text-secondary" aria-hidden="true" />;
|
|
9739
|
+
}
|
|
9740
|
+
if (icon === "clock" || icon === undefined) {
|
|
9741
|
+
return <Clock3 className="size-5 text-semantic-text-secondary" aria-hidden="true" />;
|
|
9742
|
+
}
|
|
9743
|
+
return icon;
|
|
9744
|
+
};
|
|
9745
|
+
|
|
9746
|
+
const PlanUpgradeModal = React.forwardRef<HTMLDivElement, PlanUpgradeModalProps>(
|
|
9747
|
+
(
|
|
9748
|
+
{
|
|
9749
|
+
open,
|
|
9750
|
+
onOpenChange,
|
|
9751
|
+
title = "Plan upgrade, SUV \u20B9 15,000.00/month",
|
|
9752
|
+
description = "Select how you want to apply your new plan.",
|
|
9753
|
+
options = defaultOptions,
|
|
9754
|
+
selectedOptionId,
|
|
9755
|
+
defaultSelectedOptionId,
|
|
9756
|
+
onOptionChange,
|
|
9757
|
+
nextLabel = "Next",
|
|
9758
|
+
onNext,
|
|
9759
|
+
onClose,
|
|
9760
|
+
className,
|
|
9761
|
+
...props
|
|
9762
|
+
},
|
|
9763
|
+
ref
|
|
9764
|
+
) => {
|
|
9765
|
+
const initialOptionId = defaultSelectedOptionId ?? options[0]?.id;
|
|
9766
|
+
const [internalSelectedOptionId, setInternalSelectedOptionId] = React.useState<
|
|
9767
|
+
string | undefined
|
|
9768
|
+
>(initialOptionId);
|
|
9769
|
+
const isControlled = selectedOptionId !== undefined;
|
|
9770
|
+
const activeOptionId = isControlled ? selectedOptionId : internalSelectedOptionId;
|
|
9771
|
+
|
|
9772
|
+
React.useEffect(() => {
|
|
9773
|
+
if (!isControlled) {
|
|
9774
|
+
setInternalSelectedOptionId(initialOptionId);
|
|
9775
|
+
}
|
|
9776
|
+
}, [initialOptionId, isControlled]);
|
|
9777
|
+
|
|
9778
|
+
const handleOptionSelect = (optionId: string) => {
|
|
9779
|
+
if (!isControlled) {
|
|
9780
|
+
setInternalSelectedOptionId(optionId);
|
|
9781
|
+
}
|
|
9782
|
+
onOptionChange?.(optionId);
|
|
9783
|
+
};
|
|
9784
|
+
|
|
9785
|
+
const handleNext = () => {
|
|
9786
|
+
if (!activeOptionId) {
|
|
9787
|
+
return;
|
|
9788
|
+
}
|
|
9789
|
+
onNext?.(activeOptionId);
|
|
9790
|
+
};
|
|
9791
|
+
|
|
9792
|
+
const handleClose = () => {
|
|
9793
|
+
onClose?.();
|
|
9794
|
+
onOpenChange(false);
|
|
9795
|
+
};
|
|
9796
|
+
|
|
9797
|
+
return (
|
|
9798
|
+
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
9799
|
+
<DialogContent
|
|
9800
|
+
size="default"
|
|
9801
|
+
hideCloseButton
|
|
9802
|
+
className="w-full max-w-[480px] border-none bg-transparent p-0 shadow-none"
|
|
9803
|
+
>
|
|
9804
|
+
<div ref={ref} className={cn(modalRootVariants(), className)} {...props}>
|
|
9805
|
+
<div className="flex items-start justify-between gap-4">
|
|
9806
|
+
<div className="flex flex-col gap-2">
|
|
9807
|
+
<DialogTitle className="m-0 text-lg font-semibold leading-normal text-semantic-text-primary">
|
|
9808
|
+
{title}
|
|
9809
|
+
</DialogTitle>
|
|
9810
|
+
<DialogDescription className="m-0 text-sm tracking-[0.035px] text-semantic-text-muted">
|
|
9811
|
+
{description}
|
|
9812
|
+
</DialogDescription>
|
|
9813
|
+
</div>
|
|
9814
|
+
<button
|
|
9815
|
+
type="button"
|
|
9816
|
+
onClick={handleClose}
|
|
9817
|
+
className="shrink-0 text-semantic-text-muted transition-colors hover:text-semantic-text-primary"
|
|
9818
|
+
aria-label="Close plan upgrade modal"
|
|
9819
|
+
>
|
|
9820
|
+
<X className="size-5" />
|
|
9821
|
+
</button>
|
|
9822
|
+
</div>
|
|
9823
|
+
|
|
9824
|
+
<div className="flex flex-col gap-2.5">
|
|
9825
|
+
{options.map((option) => {
|
|
9826
|
+
const isSelected = activeOptionId === option.id;
|
|
9827
|
+
return (
|
|
9828
|
+
<button
|
|
9829
|
+
key={option.id}
|
|
9830
|
+
type="button"
|
|
9831
|
+
onClick={() => handleOptionSelect(option.id)}
|
|
9832
|
+
className={cn(billingCycleOptionVariants({ selected: isSelected }))}
|
|
9833
|
+
aria-pressed={isSelected}
|
|
9834
|
+
>
|
|
9835
|
+
<span className={iconContainerVariants()}>{renderOptionIcon(option.icon)}</span>
|
|
9836
|
+
<span className="text-sm leading-normal tracking-[0.035px] text-semantic-text-primary">
|
|
9837
|
+
{option.label}
|
|
9838
|
+
</span>
|
|
9839
|
+
</button>
|
|
9840
|
+
);
|
|
9841
|
+
})}
|
|
9842
|
+
</div>
|
|
9843
|
+
|
|
9844
|
+
<div className="flex justify-end">
|
|
9845
|
+
<Button
|
|
9846
|
+
variant="default"
|
|
9847
|
+
onClick={handleNext}
|
|
9848
|
+
disabled={!activeOptionId}
|
|
9849
|
+
className="min-w-[95px]"
|
|
9850
|
+
>
|
|
9851
|
+
{nextLabel}
|
|
9852
|
+
</Button>
|
|
9853
|
+
</div>
|
|
9854
|
+
</div>
|
|
9855
|
+
</DialogContent>
|
|
9856
|
+
</Dialog>
|
|
9857
|
+
);
|
|
9858
|
+
}
|
|
9859
|
+
);
|
|
9860
|
+
|
|
9861
|
+
PlanUpgradeModal.displayName = "PlanUpgradeModal";
|
|
9862
|
+
|
|
9863
|
+
export { PlanUpgradeModal, billingCycleOptionVariants };
|
|
9864
|
+
`, prefix)
|
|
9865
|
+
},
|
|
9866
|
+
{
|
|
9867
|
+
name: "types.ts",
|
|
9868
|
+
content: prefixTailwindClasses(`import * as React from "react";
|
|
9869
|
+
|
|
9870
|
+
export type BillingCycleOptionIcon = "clock" | "calendar" | React.ReactNode;
|
|
9871
|
+
|
|
9872
|
+
/**
|
|
9873
|
+
* A selectable billing cycle option shown inside PlanUpgradeModal.
|
|
9874
|
+
*/
|
|
9875
|
+
export interface BillingCycleOption {
|
|
9876
|
+
/** Unique identifier for the option */
|
|
9877
|
+
id: string;
|
|
9878
|
+
/** Option label text */
|
|
9879
|
+
label: string;
|
|
9880
|
+
/** Optional icon key or custom icon node */
|
|
9881
|
+
icon?: BillingCycleOptionIcon;
|
|
9882
|
+
}
|
|
9883
|
+
|
|
9884
|
+
export interface PlanUpgradeModalProps
|
|
9885
|
+
extends React.HTMLAttributes<HTMLDivElement> {
|
|
9886
|
+
/** Whether the modal is open */
|
|
9887
|
+
open: boolean;
|
|
9888
|
+
/** Called when modal open state changes */
|
|
9889
|
+
onOpenChange: (open: boolean) => void;
|
|
9890
|
+
/** Title shown at the top of the modal */
|
|
9891
|
+
title?: string;
|
|
9892
|
+
/** Description shown below the title */
|
|
9893
|
+
description?: string;
|
|
9894
|
+
/** Options to select from */
|
|
9895
|
+
options?: BillingCycleOption[];
|
|
9896
|
+
/** Controlled selected option id */
|
|
9897
|
+
selectedOptionId?: string;
|
|
9898
|
+
/** Uncontrolled selected option id */
|
|
9899
|
+
defaultSelectedOptionId?: string;
|
|
9900
|
+
/** Called when an option is selected */
|
|
9901
|
+
onOptionChange?: (optionId: string) => void;
|
|
9902
|
+
/** Next button label */
|
|
9903
|
+
nextLabel?: string;
|
|
9904
|
+
/** Called when Next is clicked */
|
|
9905
|
+
onNext?: (selectedOptionId: string) => void;
|
|
9906
|
+
/** Called when close button is clicked */
|
|
9907
|
+
onClose?: () => void;
|
|
9908
|
+
}
|
|
9909
|
+
`, prefix)
|
|
9910
|
+
},
|
|
9911
|
+
{
|
|
9912
|
+
name: "index.ts",
|
|
9913
|
+
content: prefixTailwindClasses(`export { PlanUpgradeModal, billingCycleOptionVariants } from "./plan-upgrade-modal";
|
|
9914
|
+
export type { BillingCycleOption, BillingCycleOptionIcon, PlanUpgradeModalProps } from "./types";
|
|
9915
|
+
`, prefix)
|
|
9916
|
+
}
|
|
9917
|
+
]
|
|
9918
|
+
},
|
|
9919
|
+
"plan-upgrade-summary-modal": {
|
|
9920
|
+
name: "plan-upgrade-summary-modal",
|
|
9921
|
+
description: "A billing summary modal for confirming plan upgrades and downgrades",
|
|
9922
|
+
category: "custom",
|
|
9923
|
+
dependencies: [
|
|
9924
|
+
"clsx",
|
|
9925
|
+
"tailwind-merge",
|
|
9926
|
+
"lucide-react",
|
|
9927
|
+
"@radix-ui/react-dialog"
|
|
9928
|
+
],
|
|
9929
|
+
internalDependencies: [
|
|
9930
|
+
"button",
|
|
9931
|
+
"dialog"
|
|
9932
|
+
],
|
|
9933
|
+
isMultiFile: true,
|
|
9934
|
+
directory: "plan-upgrade-summary-modal",
|
|
9935
|
+
mainFile: "plan-upgrade-summary-modal.tsx",
|
|
9936
|
+
files: [
|
|
9937
|
+
{
|
|
9938
|
+
name: "plan-upgrade-summary-modal.tsx",
|
|
9939
|
+
content: prefixTailwindClasses(`import * as React from "react";
|
|
9940
|
+
import { cva } from "class-variance-authority";
|
|
9941
|
+
import { AlertCircle, CircleCheck, X } from "lucide-react";
|
|
9942
|
+
import { cn } from "../../../lib/utils";
|
|
9943
|
+
import { Button } from "../button";
|
|
9944
|
+
import { Dialog, DialogContent, DialogDescription, DialogTitle } from "../dialog";
|
|
9945
|
+
import type {
|
|
9946
|
+
PlanUpgradeSummaryModalProps,
|
|
9947
|
+
PlanUpgradeSummaryMode,
|
|
9948
|
+
PlanUpgradeSummaryRow,
|
|
9949
|
+
PlanUpgradeSummaryStatus,
|
|
9950
|
+
PlanUpgradeSummaryTone,
|
|
9951
|
+
} from "./types";
|
|
9952
|
+
|
|
9953
|
+
const modalRootVariants = cva(
|
|
9954
|
+
"flex flex-col gap-8 rounded-lg border border-semantic-border-layout bg-semantic-bg-primary p-9"
|
|
9955
|
+
);
|
|
9956
|
+
|
|
9957
|
+
const summaryPanelVariants = cva(
|
|
9958
|
+
"flex flex-col gap-5 rounded border border-semantic-border-layout bg-semantic-bg-ui p-4"
|
|
9959
|
+
);
|
|
9960
|
+
|
|
9961
|
+
const statusTitleVariants = cva("text-sm font-semibold leading-5 tracking-[0.014px]", {
|
|
9962
|
+
variants: {
|
|
9963
|
+
tone: {
|
|
9964
|
+
warning: "text-semantic-warning-text",
|
|
9965
|
+
success: "text-semantic-success-text",
|
|
9966
|
+
},
|
|
9967
|
+
},
|
|
9968
|
+
defaultVariants: {
|
|
9969
|
+
tone: "warning",
|
|
9970
|
+
},
|
|
9971
|
+
});
|
|
9972
|
+
|
|
9973
|
+
const statusMessageVariants = cva("text-xs leading-normal", {
|
|
9974
|
+
variants: {
|
|
9975
|
+
tone: {
|
|
9976
|
+
warning: "text-semantic-warning-text",
|
|
9977
|
+
success: "text-semantic-success-text",
|
|
9978
|
+
},
|
|
9979
|
+
},
|
|
9980
|
+
defaultVariants: {
|
|
9981
|
+
tone: "warning",
|
|
9982
|
+
},
|
|
9983
|
+
});
|
|
9984
|
+
|
|
9985
|
+
const defaultRowsByMode: Record<PlanUpgradeSummaryMode, PlanUpgradeSummaryRow[]> = {
|
|
9986
|
+
upgrade: [
|
|
9987
|
+
{ label: "Prepaid amount", value: "(\u20B9 47,229.20)" },
|
|
9988
|
+
{ label: "Difference in rental", value: "\u20B9 150,000.00" },
|
|
9989
|
+
{ label: "Total", value: "\u20B9 102,770.80" },
|
|
9990
|
+
{ label: "Taxes", value: "\u20B9 18,498.74" },
|
|
9991
|
+
],
|
|
9992
|
+
downgrade: [
|
|
9993
|
+
{ label: "Prepaid amount", value: "(\u20B9 581.48)" },
|
|
9994
|
+
{ label: "Difference in rental", value: "\u20B9 -120,000.00" },
|
|
9995
|
+
{ label: "Total", value: "\u20B9 -120,581.48" },
|
|
9996
|
+
{ label: "Taxes", value: "\u20B9 0.00" },
|
|
9997
|
+
],
|
|
9998
|
+
};
|
|
9999
|
+
|
|
10000
|
+
const defaultStatusByMode: Record<PlanUpgradeSummaryMode, PlanUpgradeSummaryStatus> = {
|
|
10001
|
+
upgrade: {
|
|
10002
|
+
title: "Payable Amount",
|
|
10003
|
+
message: "A payment of \u20B9 59,437.44 is required to upgrade.",
|
|
10004
|
+
tone: "warning",
|
|
10005
|
+
},
|
|
10006
|
+
downgrade: {
|
|
10007
|
+
title: "Adjustable Credit",
|
|
10008
|
+
tone: "success",
|
|
10009
|
+
},
|
|
10010
|
+
};
|
|
10011
|
+
|
|
10012
|
+
const defaultTitleByMode: Record<PlanUpgradeSummaryMode, string> = {
|
|
10013
|
+
upgrade: "Plan upgrade, SUV \u20B9 15,000.00/month",
|
|
10014
|
+
downgrade: "Plan downgrade, SUV \u20B9 15,000.00/month",
|
|
10015
|
+
};
|
|
10016
|
+
|
|
10017
|
+
const defaultPrimaryActionLabelByMode: Record<PlanUpgradeSummaryMode, string> = {
|
|
10018
|
+
upgrade: "Pay & Upgrade Plan",
|
|
10019
|
+
downgrade: "Downgrade Plan",
|
|
10020
|
+
};
|
|
10021
|
+
|
|
10022
|
+
const defaultTotalValueByMode: Record<PlanUpgradeSummaryMode, string> = {
|
|
10023
|
+
upgrade: "\u20B9 59,437.44",
|
|
10024
|
+
downgrade: "\u20B9 -120,581.48",
|
|
10025
|
+
};
|
|
10026
|
+
|
|
10027
|
+
const defaultDescription =
|
|
10028
|
+
"Your request will be processed from the current billing cycle.";
|
|
10029
|
+
|
|
10030
|
+
const getStatusIcon = (tone: PlanUpgradeSummaryTone) => {
|
|
10031
|
+
if (tone === "success") {
|
|
10032
|
+
return <CircleCheck className="size-6 text-semantic-success-text" aria-hidden="true" />;
|
|
10033
|
+
}
|
|
10034
|
+
|
|
10035
|
+
return <AlertCircle className="size-6 text-semantic-warning-text" aria-hidden="true" />;
|
|
10036
|
+
};
|
|
10037
|
+
|
|
10038
|
+
const PlanUpgradeSummaryModal = React.forwardRef<
|
|
10039
|
+
HTMLDivElement,
|
|
10040
|
+
PlanUpgradeSummaryModalProps
|
|
10041
|
+
>(
|
|
10042
|
+
(
|
|
10043
|
+
{
|
|
10044
|
+
open,
|
|
10045
|
+
onOpenChange,
|
|
10046
|
+
mode = "upgrade",
|
|
10047
|
+
title,
|
|
10048
|
+
description = defaultDescription,
|
|
10049
|
+
status,
|
|
10050
|
+
rows,
|
|
10051
|
+
totalLabel = "Total amount due",
|
|
10052
|
+
totalValue,
|
|
10053
|
+
cancelLabel = "Cancel",
|
|
10054
|
+
primaryActionLabel,
|
|
10055
|
+
onPrimaryAction,
|
|
10056
|
+
onCancel,
|
|
10057
|
+
onClose,
|
|
10058
|
+
closeAriaLabel = "Close plan summary modal",
|
|
10059
|
+
className,
|
|
10060
|
+
...props
|
|
10061
|
+
},
|
|
10062
|
+
ref
|
|
10063
|
+
) => {
|
|
10064
|
+
const resolvedStatus = status ?? defaultStatusByMode[mode];
|
|
10065
|
+
const resolvedTone = resolvedStatus.tone ?? defaultStatusByMode[mode].tone ?? "warning";
|
|
10066
|
+
const resolvedRows = rows ?? defaultRowsByMode[mode];
|
|
10067
|
+
const resolvedTitle = title ?? defaultTitleByMode[mode];
|
|
10068
|
+
const resolvedTotalValue = totalValue ?? defaultTotalValueByMode[mode];
|
|
10069
|
+
const resolvedPrimaryActionLabel =
|
|
10070
|
+
primaryActionLabel ?? defaultPrimaryActionLabelByMode[mode];
|
|
10071
|
+
|
|
10072
|
+
const handleClose = () => {
|
|
10073
|
+
onClose?.();
|
|
10074
|
+
onOpenChange(false);
|
|
10075
|
+
};
|
|
10076
|
+
|
|
10077
|
+
const handleCancel = () => {
|
|
10078
|
+
onCancel?.();
|
|
10079
|
+
onOpenChange(false);
|
|
10080
|
+
};
|
|
10081
|
+
|
|
10082
|
+
return (
|
|
10083
|
+
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
10084
|
+
<DialogContent
|
|
10085
|
+
size="default"
|
|
10086
|
+
hideCloseButton
|
|
10087
|
+
className="w-full max-w-[660px] border-none bg-transparent p-0 shadow-none"
|
|
10088
|
+
>
|
|
10089
|
+
<div ref={ref} className={cn(modalRootVariants(), className)} {...props}>
|
|
10090
|
+
<div className="flex items-start justify-between gap-4">
|
|
10091
|
+
<div className="flex flex-col gap-2">
|
|
10092
|
+
<DialogTitle className="m-0 text-lg font-semibold leading-normal text-semantic-text-primary">
|
|
10093
|
+
{resolvedTitle}
|
|
10094
|
+
</DialogTitle>
|
|
10095
|
+
<DialogDescription className="m-0 text-sm tracking-[0.035px] text-semantic-text-muted">
|
|
10096
|
+
{description}
|
|
10097
|
+
</DialogDescription>
|
|
10098
|
+
</div>
|
|
10099
|
+
<button
|
|
10100
|
+
type="button"
|
|
10101
|
+
onClick={handleClose}
|
|
10102
|
+
className="shrink-0 text-semantic-text-muted transition-colors hover:text-semantic-text-primary"
|
|
10103
|
+
aria-label={closeAriaLabel}
|
|
10104
|
+
>
|
|
10105
|
+
<X className="size-6" />
|
|
10106
|
+
</button>
|
|
10107
|
+
</div>
|
|
10108
|
+
|
|
10109
|
+
<div className={summaryPanelVariants()}>
|
|
10110
|
+
<div className="flex items-start gap-4">
|
|
10111
|
+
<span className="shrink-0">{getStatusIcon(resolvedTone)}</span>
|
|
10112
|
+
<div className="flex flex-col gap-1">
|
|
10113
|
+
<p className={statusTitleVariants({ tone: resolvedTone })}>
|
|
10114
|
+
{resolvedStatus.title}
|
|
10115
|
+
</p>
|
|
10116
|
+
{resolvedStatus.message ? (
|
|
10117
|
+
<p className={statusMessageVariants({ tone: resolvedTone })}>
|
|
10118
|
+
{resolvedStatus.message}
|
|
10119
|
+
</p>
|
|
10120
|
+
) : null}
|
|
10121
|
+
</div>
|
|
10122
|
+
</div>
|
|
10123
|
+
|
|
10124
|
+
<div className="flex flex-col gap-2.5">
|
|
10125
|
+
{resolvedRows.map((row) => (
|
|
10126
|
+
<div
|
|
10127
|
+
key={\`\${row.label}-\${row.value}\`}
|
|
10128
|
+
className="flex items-center justify-between gap-6"
|
|
10129
|
+
>
|
|
10130
|
+
<span className="text-sm tracking-[0.035px] text-semantic-text-secondary">
|
|
10131
|
+
{row.label}
|
|
10132
|
+
</span>
|
|
10133
|
+
<span className="text-sm tracking-[0.035px] text-semantic-text-primary">
|
|
10134
|
+
{row.value}
|
|
10135
|
+
</span>
|
|
10136
|
+
</div>
|
|
10137
|
+
))}
|
|
10138
|
+
</div>
|
|
10139
|
+
|
|
10140
|
+
<div className="flex items-center justify-between gap-6 border-t border-semantic-border-layout pt-3">
|
|
10141
|
+
<span className="text-sm font-semibold tracking-[0.014px] text-semantic-text-secondary">
|
|
10142
|
+
{totalLabel}
|
|
10143
|
+
</span>
|
|
10144
|
+
<span className="text-sm font-semibold tracking-[0.014px] text-semantic-text-primary">
|
|
10145
|
+
{resolvedTotalValue}
|
|
10146
|
+
</span>
|
|
10147
|
+
</div>
|
|
10148
|
+
</div>
|
|
10149
|
+
|
|
10150
|
+
<div className="flex justify-end gap-2.5">
|
|
10151
|
+
<Button variant="outline" onClick={handleCancel}>
|
|
10152
|
+
{cancelLabel}
|
|
10153
|
+
</Button>
|
|
10154
|
+
<Button variant="primary" onClick={onPrimaryAction}>
|
|
10155
|
+
{resolvedPrimaryActionLabel}
|
|
10156
|
+
</Button>
|
|
10157
|
+
</div>
|
|
10158
|
+
</div>
|
|
10159
|
+
</DialogContent>
|
|
10160
|
+
</Dialog>
|
|
10161
|
+
);
|
|
10162
|
+
}
|
|
10163
|
+
);
|
|
10164
|
+
|
|
10165
|
+
PlanUpgradeSummaryModal.displayName = "PlanUpgradeSummaryModal";
|
|
10166
|
+
|
|
10167
|
+
export { PlanUpgradeSummaryModal, modalRootVariants, summaryPanelVariants };
|
|
10168
|
+
`, prefix)
|
|
10169
|
+
},
|
|
10170
|
+
{
|
|
10171
|
+
name: "types.ts",
|
|
10172
|
+
content: prefixTailwindClasses(`import * as React from "react";
|
|
10173
|
+
|
|
10174
|
+
export type PlanUpgradeSummaryMode = "upgrade" | "downgrade";
|
|
10175
|
+
|
|
10176
|
+
export type PlanUpgradeSummaryTone = "warning" | "success";
|
|
10177
|
+
|
|
10178
|
+
export interface PlanUpgradeSummaryRow {
|
|
10179
|
+
/** Label shown on the left side of the summary row */
|
|
10180
|
+
label: string;
|
|
10181
|
+
/** Value shown on the right side of the summary row */
|
|
10182
|
+
value: string;
|
|
10183
|
+
}
|
|
10184
|
+
|
|
10185
|
+
export interface PlanUpgradeSummaryStatus {
|
|
10186
|
+
/** Highlighted title shown at the top of the summary panel */
|
|
10187
|
+
title: string;
|
|
10188
|
+
/** Optional supporting message shown below the status title */
|
|
10189
|
+
message?: string;
|
|
10190
|
+
/** Visual tone used for the status title and icon */
|
|
10191
|
+
tone?: PlanUpgradeSummaryTone;
|
|
10192
|
+
}
|
|
10193
|
+
|
|
10194
|
+
export interface PlanUpgradeSummaryModalProps
|
|
10195
|
+
extends React.HTMLAttributes<HTMLDivElement> {
|
|
10196
|
+
/** Whether the modal is open */
|
|
10197
|
+
open: boolean;
|
|
10198
|
+
/** Called when modal open state changes */
|
|
10199
|
+
onOpenChange: (open: boolean) => void;
|
|
10200
|
+
/** Preset content mode for upgrade or downgrade flows */
|
|
10201
|
+
mode?: PlanUpgradeSummaryMode;
|
|
10202
|
+
/** Title shown at the top of the modal */
|
|
10203
|
+
title?: string;
|
|
10204
|
+
/** Supporting description below the title */
|
|
10205
|
+
description?: string;
|
|
10206
|
+
/** Status content shown inside the summary panel */
|
|
10207
|
+
status?: PlanUpgradeSummaryStatus;
|
|
10208
|
+
/** Summary rows shown above the total row */
|
|
10209
|
+
rows?: PlanUpgradeSummaryRow[];
|
|
10210
|
+
/** Label for the total row */
|
|
10211
|
+
totalLabel?: string;
|
|
10212
|
+
/** Value for the total row */
|
|
10213
|
+
totalValue?: string;
|
|
10214
|
+
/** Text for the cancel button */
|
|
10215
|
+
cancelLabel?: string;
|
|
10216
|
+
/** Text for the primary CTA button */
|
|
10217
|
+
primaryActionLabel?: string;
|
|
10218
|
+
/** Called when the primary CTA is clicked */
|
|
10219
|
+
onPrimaryAction?: () => void;
|
|
10220
|
+
/** Called when the cancel button is clicked */
|
|
10221
|
+
onCancel?: () => void;
|
|
10222
|
+
/** Called when the close icon is clicked */
|
|
10223
|
+
onClose?: () => void;
|
|
10224
|
+
/** Accessible label for the close button */
|
|
10225
|
+
closeAriaLabel?: string;
|
|
10226
|
+
}
|
|
10227
|
+
`, prefix)
|
|
10228
|
+
},
|
|
10229
|
+
{
|
|
10230
|
+
name: "index.ts",
|
|
10231
|
+
content: prefixTailwindClasses(`export {
|
|
10232
|
+
PlanUpgradeSummaryModal,
|
|
10233
|
+
modalRootVariants,
|
|
10234
|
+
summaryPanelVariants,
|
|
10235
|
+
} from "./plan-upgrade-summary-modal";
|
|
10236
|
+
export type {
|
|
10237
|
+
PlanUpgradeSummaryModalProps,
|
|
10238
|
+
PlanUpgradeSummaryMode,
|
|
10239
|
+
PlanUpgradeSummaryRow,
|
|
10240
|
+
PlanUpgradeSummaryStatus,
|
|
10241
|
+
PlanUpgradeSummaryTone,
|
|
10242
|
+
} from "./types";
|
|
9676
10243
|
`, prefix)
|
|
9677
10244
|
}
|
|
9678
10245
|
]
|