feat(dashboard,types,js-sdk,ui): Tax Regions UI (#7935)
This commit is contained in:
committed by
GitHub
parent
75e7047243
commit
046a34bdfc
@@ -8,7 +8,7 @@ import {
|
||||
import { TrianglesMini } from "@medusajs/icons"
|
||||
import { clx } from "@medusajs/ui"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { countries } from "../../../lib/countries"
|
||||
import { countries } from "../../../lib/data/countries"
|
||||
|
||||
export const CountrySelect = forwardRef<
|
||||
HTMLSelectElement,
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { Input, Text } from "@medusajs/ui"
|
||||
import { Input, Text, clx } from "@medusajs/ui"
|
||||
import { ComponentProps, ElementRef, forwardRef } from "react"
|
||||
import Primitive from "react-currency-input-field"
|
||||
|
||||
export const PercentageInput = forwardRef<
|
||||
/**
|
||||
* @deprecated Use `PercentageInput` instead
|
||||
*/
|
||||
export const DeprecatedPercentageInput = forwardRef<
|
||||
ElementRef<typeof Input>,
|
||||
Omit<ComponentProps<typeof Input>, "type">
|
||||
>(({ min = 0, max = 100, step = 0.0001, ...props }, ref) => {
|
||||
@@ -29,4 +33,43 @@ export const PercentageInput = forwardRef<
|
||||
</div>
|
||||
)
|
||||
})
|
||||
PercentageInput.displayName = "HandleInput"
|
||||
DeprecatedPercentageInput.displayName = "PercentageInput"
|
||||
|
||||
export const PercentageInput = forwardRef<
|
||||
ElementRef<"input">,
|
||||
ComponentProps<typeof Primitive>
|
||||
>(({ min = 0, decimalScale = 2, className, ...props }, ref) => {
|
||||
return (
|
||||
<div className="relative">
|
||||
<Primitive
|
||||
ref={ref as any} // dependency is typed incorrectly
|
||||
min={min}
|
||||
autoComplete="off"
|
||||
decimalScale={decimalScale}
|
||||
decimalsLimit={decimalScale}
|
||||
{...props}
|
||||
className={clx(
|
||||
"caret-ui-fg-base bg-ui-bg-field shadow-buttons-neutral transition-fg txt-compact-small flex w-full select-none appearance-none items-center justify-between rounded-md px-2 py-1.5 pr-10 text-right outline-none",
|
||||
"placeholder:text-ui-fg-muted text-ui-fg-base",
|
||||
"hover:bg-ui-bg-field-hover",
|
||||
"focus-visible:shadow-borders-interactive-with-active data-[state=open]:!shadow-borders-interactive-with-active",
|
||||
"aria-[invalid=true]:border-ui-border-error aria-[invalid=true]:shadow-borders-error",
|
||||
"invalid::border-ui-border-error invalid:shadow-borders-error",
|
||||
"disabled:!bg-ui-bg-disabled disabled:!text-ui-fg-disabled",
|
||||
className
|
||||
)}
|
||||
/>
|
||||
<div className="absolute inset-y-0 right-0 z-10 flex w-8 items-center justify-center border-l">
|
||||
<Text
|
||||
className="text-ui-fg-muted"
|
||||
size="small"
|
||||
leading="compact"
|
||||
weight="plus"
|
||||
>
|
||||
%
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
PercentageInput.displayName = "PercentageInput"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./province-select"
|
||||
@@ -0,0 +1,111 @@
|
||||
import {
|
||||
ComponentPropsWithoutRef,
|
||||
forwardRef,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
} from "react"
|
||||
|
||||
import { TrianglesMini } from "@medusajs/icons"
|
||||
import { clx } from "@medusajs/ui"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { getCountryProvinceObjectByIso2 } from "../../../lib/data/country-states"
|
||||
|
||||
interface ProvinceSelectProps extends ComponentPropsWithoutRef<"select"> {
|
||||
/**
|
||||
* ISO 3166-1 alpha-2 country code
|
||||
*/
|
||||
country_code: string
|
||||
/**
|
||||
* Whether to use the ISO 3166-1 alpha-2 code or the name of the province as the value
|
||||
*
|
||||
* @default "iso_2"
|
||||
*/
|
||||
valueAs?: "iso_2" | "name"
|
||||
placeholder?: string
|
||||
}
|
||||
|
||||
export const ProvinceSelect = forwardRef<
|
||||
HTMLSelectElement,
|
||||
ProvinceSelectProps
|
||||
>(
|
||||
(
|
||||
{
|
||||
className,
|
||||
disabled,
|
||||
placeholder,
|
||||
country_code,
|
||||
valueAs = "iso_2",
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const { t } = useTranslation()
|
||||
const innerRef = useRef<HTMLSelectElement>(null)
|
||||
|
||||
useImperativeHandle(ref, () => innerRef.current as HTMLSelectElement)
|
||||
|
||||
const isPlaceholder = innerRef.current?.value === ""
|
||||
|
||||
const provinceObject = getCountryProvinceObjectByIso2(country_code)
|
||||
|
||||
if (!provinceObject) {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
const options = Object.entries(provinceObject?.options ?? {}).map(
|
||||
([iso2, name]) => {
|
||||
return (
|
||||
<option key={iso2} value={valueAs === "iso_2" ? iso2 : name}>
|
||||
{name}
|
||||
</option>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
const placeholderText = provinceObject
|
||||
? t(`taxRegions.fields.sublevels.placeholders.${provinceObject.type}`)
|
||||
: ""
|
||||
|
||||
const placeholderOption = provinceObject ? (
|
||||
<option value="" disabled className="text-ui-fg-muted">
|
||||
{placeholder || placeholderText}
|
||||
</option>
|
||||
) : null
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<TrianglesMini
|
||||
className={clx(
|
||||
"text-ui-fg-muted transition-fg pointer-events-none absolute right-2 top-1/2 -translate-y-1/2",
|
||||
{
|
||||
"text-ui-fg-disabled": disabled,
|
||||
}
|
||||
)}
|
||||
/>
|
||||
<select
|
||||
disabled={disabled}
|
||||
className={clx(
|
||||
"bg-ui-bg-field shadow-buttons-neutral transition-fg txt-compact-small flex w-full select-none appearance-none items-center justify-between rounded-md px-2 py-1.5 outline-none",
|
||||
"placeholder:text-ui-fg-muted text-ui-fg-base",
|
||||
"hover:bg-ui-bg-field-hover",
|
||||
"focus-visible:shadow-borders-interactive-with-active data-[state=open]:!shadow-borders-interactive-with-active",
|
||||
"aria-[invalid=true]:border-ui-border-error aria-[invalid=true]:shadow-borders-error",
|
||||
"invalid::border-ui-border-error invalid:shadow-borders-error",
|
||||
"disabled:!bg-ui-bg-disabled disabled:!text-ui-fg-disabled",
|
||||
{
|
||||
"text-ui-fg-muted": isPlaceholder,
|
||||
},
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
ref={innerRef}
|
||||
>
|
||||
{/* Add an empty option so the first option is preselected */}
|
||||
{placeholderOption}
|
||||
{options}
|
||||
</select>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
ProvinceSelect.displayName = "CountrySelect"
|
||||
Reference in New Issue
Block a user