wp-optimize
/
vendor
/
team-updraft
/
lib-onboarding-wizard
/
Wizard
/
Onboarding
/
src
/
components
/
Fields
/
FieldWrapper.tsx
FieldWrapper.tsx in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance trunk, at vendor/team-updraft/lib-onboarding-wizard/Wizard/Onboarding/src/components/Fields/FieldWrapper.tsx
| 1 | "use client"; |
| 2 | |
| 3 | import * as React from "react"; |
| 4 | import { memo } from "react"; |
| 5 | import {__} from "@wordpress/i18n"; |
| 6 | import {clsx} from "clsx"; |
| 7 | import type { TooltipProps } from "../../utils/Tooltip/Tooltip"; |
| 8 | import { renderPossiblyHtml } from '../../utils/html'; |
| 9 | import Label from './Label'; |
| 10 | |
| 11 | interface FieldWrapperProps { |
| 12 | label: React.ReactNode; |
| 13 | // Allow context to be a ReactNode or an object with text and url. |
| 14 | context?: React.ReactNode | { text?: string; url?: string }; |
| 15 | help?: string; |
| 16 | error?: string; |
| 17 | reverseLabel?: boolean; |
| 18 | alignWithLabel?: boolean; |
| 19 | className?: string; |
| 20 | inputId: string; |
| 21 | required?: boolean; |
| 22 | children: React.ReactNode; |
| 23 | pro?: { url?: string }; |
| 24 | tooltip?: TooltipProps; |
| 25 | contextHtml?: string; |
| 26 | } |
| 27 | |
| 28 | const isContextObject = (value: any): value is { text?: string; url?: string } => { |
| 29 | return value && typeof value === "object" && !React.isValidElement(value); |
| 30 | }; |
| 31 | |
| 32 | const FieldWrapper = memo(({ |
| 33 | label, |
| 34 | context, |
| 35 | help, |
| 36 | error, |
| 37 | reverseLabel = false, |
| 38 | alignWithLabel = false, |
| 39 | className = "", |
| 40 | inputId, |
| 41 | required = false, |
| 42 | children, |
| 43 | pro, |
| 44 | tooltip, |
| 45 | contextHtml, |
| 46 | }: FieldWrapperProps) => { |
| 47 | |
| 48 | |
| 49 | // Outer wrapper with conditional error background |
| 50 | const wrapperClasses = clsx(className, "w-full box-border ", error && "bg-red-100"); |
| 51 | |
| 52 | // Use a flex container that is row when aligning side-by-side and column otherwise. |
| 53 | const containerClasses = alignWithLabel ? "flex flex-row items-center justify-between" : "flex flex-col"; |
| 54 | |
| 55 | // Compute order classes based on reverseLabel. |
| 56 | const labelOrderClass = reverseLabel ? "order-2" : "order-1"; |
| 57 | const fieldOrderClass = reverseLabel ? "order-1" : "order-2"; |
| 58 | |
| 59 | // Margins based on horizontal or vertical layout. |
| 60 | const labelMargin = alignWithLabel ? (reverseLabel ? "ml-4" : "") : (reverseLabel ? "mt-1" : ""); |
| 61 | const fieldMargin = alignWithLabel ? (!reverseLabel ? "ml-4" : "") : (!reverseLabel ? "mt-0" : ""); |
| 62 | |
| 63 | const labelBlock = ( |
| 64 | <div className={clsx("flex items-center gap-2", labelMargin)}> |
| 65 | <Label |
| 66 | htmlFor={inputId} |
| 67 | text={label} |
| 68 | {...(tooltip && { tooltip })} |
| 69 | className="cursor-pointer text-md font-medium text-black" |
| 70 | /> |
| 71 | {required && ( |
| 72 | <span className="text-gray ml-1 text-xs font-normal"> |
| 73 | ({__("Required", "ONBOARDING_WIZARD_TEXT_DOMAIN")}) |
| 74 | </span> |
| 75 | )} |
| 76 | {help && ( |
| 77 | <span className="text-gray ml-2 text-sm font-light"> |
| 78 | {help} |
| 79 | </span> |
| 80 | )} |
| 81 | </div> |
| 82 | ); |
| 83 | |
| 84 | const fieldBlock = ( |
| 85 | <div className={clsx("w-full", fieldMargin)}> |
| 86 | {children} |
| 87 | </div> |
| 88 | ); |
| 89 | |
| 90 | return ( |
| 91 | <div className={wrapperClasses}> |
| 92 | <div className={containerClasses}> |
| 93 | <div className={clsx(labelOrderClass)}> |
| 94 | {labelBlock} |
| 95 | </div> |
| 96 | <div className={clsx(fieldOrderClass)}> |
| 97 | {fieldBlock} |
| 98 | </div> |
| 99 | </div> |
| 100 | |
| 101 | {error && ( |
| 102 | <p className="text-red mt-2 text-sm font-semibold" role="alert"> |
| 103 | {error} |
| 104 | </p> |
| 105 | )} |
| 106 | |
| 107 | {context && ( |
| 108 | <p className="text-gray mt-2 text-sm font-normal"> |
| 109 | {isContextObject(context) ? context.text : context} |
| 110 | {isContextObject(context) && context.url && ' '} |
| 111 | {isContextObject(context) && context.url && ( |
| 112 | <a rel="noopener noreferrer nofollow" className="text-blue underline" href={context.url} target="_blank"> |
| 113 | {__("More info", "ONBOARDING_WIZARD_TEXT_DOMAIN")} |
| 114 | </a> |
| 115 | )} |
| 116 | </p> |
| 117 | )} |
| 118 | |
| 119 | {contextHtml && ( |
| 120 | <div className="w-full text-right mt-2 text-sm font-normal text-gray"> |
| 121 | {renderPossiblyHtml(contextHtml)} |
| 122 | </div> |
| 123 | )} |
| 124 | </div> |
| 125 | ); |
| 126 | }); |
| 127 | |
| 128 | FieldWrapper.displayName = "FieldWrapper"; |
| 129 | |
| 130 | export default FieldWrapper; |