1
0
forked from baron/baron-sso

Merge origin/dev into dev

This commit is contained in:
2026-06-15 20:05:47 +09:00
67 changed files with 6933 additions and 3919 deletions

View File

@@ -29,6 +29,7 @@ type DomainTagInputProps = {
confirmedConflicts?: string[];
onConfirmedConflictsChange?: (domains: string[]) => void;
placeholder?: string;
disabled?: boolean;
};
export function DomainTagInput({
@@ -40,6 +41,7 @@ export function DomainTagInput({
confirmedConflicts = [],
onConfirmedConflictsChange,
placeholder,
disabled = false,
}: DomainTagInputProps) {
const [input, setInput] = useState("");
const [pendingConflict, setPendingConflict] = useState<DomainConflict | null>(
@@ -107,14 +109,16 @@ export function DomainTagInput({
className="gap-1 rounded-md"
>
<span>{domain}</span>
<button
type="button"
className="inline-flex h-4 w-4 items-center justify-center rounded-sm hover:bg-background/60"
onClick={() => removeDomain(domain)}
aria-label={t("ui.common.remove", "삭제")}
>
<X size={12} />
</button>
{!disabled && (
<button
type="button"
className="inline-flex h-4 w-4 items-center justify-center rounded-sm hover:bg-background/60"
onClick={() => removeDomain(domain)}
aria-label={t("ui.common.remove", "삭제")}
>
<X size={12} />
</button>
)}
</Badge>
))}
<Input
@@ -133,6 +137,7 @@ export function DomainTagInput({
tokenizeInput();
}
}}
disabled={disabled}
className="h-7 min-w-[180px] flex-1 border-0 px-0 py-0 shadow-none focus-visible:ring-0"
placeholder={value.length === 0 ? placeholder : undefined}
/>

View File

@@ -36,6 +36,7 @@ type ParentTenantSelectorProps = {
localTenantFilter?: (tenant: TenantSummary) => boolean;
compact?: boolean;
controlTestId?: string;
disabled?: boolean;
};
export function ParentTenantSelector({
@@ -55,6 +56,7 @@ export function ParentTenantSelector({
localTenantFilter,
compact = false,
controlTestId,
disabled = false,
}: ParentTenantSelectorProps) {
const [pickerOpen, setPickerOpen] = useState(false);
const [localPickerOpen, setLocalPickerOpen] = useState(false);
@@ -117,6 +119,7 @@ export function ParentTenantSelector({
variant="outline"
size="sm"
className={compact ? "h-8 shrink-0 px-2" : undefined}
disabled={disabled}
>
<Building2 className="h-4 w-4" />
{orgChartPickerLabel ??
@@ -147,7 +150,12 @@ export function ParentTenantSelector({
{localPickerLabel && (
<Dialog open={localPickerOpen} onOpenChange={setLocalPickerOpen}>
<DialogTrigger asChild>
<Button type="button" variant="outline" size="sm">
<Button
type="button"
variant="outline"
size="sm"
disabled={disabled}
>
<Building2 className="h-4 w-4" />
{localPickerLabel}
</Button>
@@ -234,6 +242,7 @@ export function ParentTenantSelector({
className={compact ? "h-7 w-7 shrink-0" : "h-8 w-8"}
onClick={() => onChange("")}
aria-label={noneLabel}
disabled={disabled}
>
<X className="h-4 w-4" />
</Button>

View File

@@ -0,0 +1,29 @@
import type React from "react";
import {
type TenantPermissionKey,
useTenantPermission,
} from "../hooks/useTenantPermission";
interface TenantPermissionGuardProps {
tenantId: string;
relation: TenantPermissionKey;
fallback?: React.ReactNode;
children: React.ReactNode;
}
export function TenantPermissionGuard({
tenantId,
relation,
fallback = null,
children,
}: TenantPermissionGuardProps) {
const { hasPermission, isLoading } = useTenantPermission(tenantId);
if (isLoading) return null;
if (!hasPermission(relation)) {
return <>{fallback}</>;
}
return <>{children}</>;
}