mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-11 01:36:37 +08:00
[功能] 更新组件库hero3.0.1
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
@import '../styles/tokens.css';
|
@import '../styles/tokens.css';
|
||||||
@import 'tailwindcss';
|
@import 'tailwindcss';
|
||||||
|
@import '@heroui/styles';
|
||||||
@import "tw-animate-css";
|
@import "tw-animate-css";
|
||||||
@import "shadcn/tailwind.css";
|
@import "shadcn/tailwind.css";
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import { deleteOrigin, getOrigin } from '@/features/origins/api/origins';
|
|||||||
import { OriginEditorModal } from '@/features/origins/components/origin-editor-modal';
|
import { OriginEditorModal } from '@/features/origins/components/origin-editor-modal';
|
||||||
import {
|
import {
|
||||||
DangerButton,
|
DangerButton,
|
||||||
PrimaryButton,
|
|
||||||
SecondaryButton,
|
SecondaryButton,
|
||||||
} from '@/features/shared/components/resource-primitives';
|
} from '@/features/shared/components/resource-primitives';
|
||||||
import { formatDateTime } from '@/lib/utils/date';
|
import { formatDateTime } from '@/lib/utils/date';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Select, SelectItem, SelectSection } from '@heroui/select';
|
import { ListBox, Select } from '@heroui/react';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
@@ -58,6 +58,8 @@ import {
|
|||||||
import { cn } from '@/lib/utils/cn';
|
import { cn } from '@/lib/utils/cn';
|
||||||
import { formatDateTime } from '@/lib/utils/date';
|
import { formatDateTime } from '@/lib/utils/date';
|
||||||
|
|
||||||
|
const SelectItem = ListBox.Item;
|
||||||
|
|
||||||
const customHeaderSchema = z.object({
|
const customHeaderSchema = z.object({
|
||||||
key: z.string(),
|
key: z.string(),
|
||||||
value: z.string(),
|
value: z.string(),
|
||||||
@@ -278,17 +280,15 @@ type SectionIconProps = {
|
|||||||
const INPUT_CLASS_NAME = 'h-10 rounded-xl px-3 py-2 text-sm';
|
const INPUT_CLASS_NAME = 'h-10 rounded-xl px-3 py-2 text-sm';
|
||||||
const PANEL_CLASS_NAME =
|
const PANEL_CLASS_NAME =
|
||||||
'rounded-2xl border border-[var(--border-default)] bg-[color:color-mix(in_srgb,var(--surface-elevated)_82%,white_18%)] p-4 shadow-[var(--shadow-soft)]';
|
'rounded-2xl border border-[var(--border-default)] bg-[color:color-mix(in_srgb,var(--surface-elevated)_82%,white_18%)] p-4 shadow-[var(--shadow-soft)]';
|
||||||
const HERO_SELECT_CLASS_NAMES = {
|
const HERO_SELECT_TRIGGER_CLASS_NAME = cn(
|
||||||
base: 'w-full',
|
INPUT_CLASS_NAME,
|
||||||
trigger: cn(
|
'flex min-h-10 w-full items-center justify-between rounded-xl border border-[var(--border-default)] bg-[var(--surface-elevated)] px-3 shadow-none transition-colors data-[hovered=true]:bg-[var(--surface-elevated)] data-[focus-visible=true]:border-[var(--border-strong)] data-[open=true]:border-[var(--border-strong)]',
|
||||||
INPUT_CLASS_NAME,
|
);
|
||||||
'min-h-10 rounded-xl border border-[var(--border-default)] bg-[var(--surface-elevated)] px-3 shadow-none data-[hover=true]:bg-[var(--surface-elevated)] data-[open=true]:border-[var(--border-strong)]',
|
const HERO_SELECT_VALUE_CLASS_NAME =
|
||||||
),
|
'truncate text-left text-sm text-[var(--foreground-primary)]';
|
||||||
value: 'text-sm text-[var(--foreground-primary)]',
|
const HERO_SELECT_POPOVER_CLASS_NAME =
|
||||||
popoverContent:
|
'rounded-2xl border border-[var(--border-default)] bg-[var(--surface-panel)] shadow-[var(--shadow-soft)]';
|
||||||
'rounded-2xl border border-[var(--border-default)] bg-[var(--surface-panel)] shadow-[var(--shadow-soft)]',
|
const HERO_SELECT_LISTBOX_CLASS_NAME = 'p-1';
|
||||||
listboxWrapper: 'p-1',
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
const defaultValues: ProxyRouteFormValues = {
|
const defaultValues: ProxyRouteFormValues = {
|
||||||
managed_domain_id: '',
|
managed_domain_id: '',
|
||||||
@@ -1074,10 +1074,6 @@ function HeroTextArea(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSelectedKeys(value: string) {
|
|
||||||
return value ? new Set([value]) : new Set<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
function HeroSelectField({
|
function HeroSelectField({
|
||||||
ariaLabel,
|
ariaLabel,
|
||||||
value,
|
value,
|
||||||
@@ -1089,29 +1085,29 @@ function HeroSelectField({
|
|||||||
value: string;
|
value: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
children: React.ComponentProps<typeof Select>['children'];
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
aria-label={ariaLabel}
|
aria-label={ariaLabel}
|
||||||
variant="bordered"
|
variant="primary"
|
||||||
radius="lg"
|
selectedKey={value || null}
|
||||||
disallowEmptySelection
|
|
||||||
selectedKeys={getSelectedKeys(value)}
|
|
||||||
isDisabled={disabled}
|
isDisabled={disabled}
|
||||||
classNames={HERO_SELECT_CLASS_NAMES}
|
className="w-full"
|
||||||
onSelectionChange={(keys) => {
|
onSelectionChange={(key) => {
|
||||||
if (keys === 'all') {
|
if (typeof key !== 'string') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
onChange(key);
|
||||||
const [nextValue] = Array.from(keys);
|
|
||||||
if (typeof nextValue === 'string') {
|
|
||||||
onChange(nextValue);
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
<Select.Trigger className={HERO_SELECT_TRIGGER_CLASS_NAME}>
|
||||||
|
<Select.Value className={HERO_SELECT_VALUE_CLASS_NAME} />
|
||||||
|
<Select.Indicator />
|
||||||
|
</Select.Trigger>
|
||||||
|
<Select.Popover className={HERO_SELECT_POPOVER_CLASS_NAME}>
|
||||||
|
<ListBox className={HERO_SELECT_LISTBOX_CLASS_NAME}>{children}</ListBox>
|
||||||
|
</Select.Popover>
|
||||||
</Select>
|
</Select>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1199,10 +1195,6 @@ export function ProxyRoutesPage() {
|
|||||||
control: form.control,
|
control: form.control,
|
||||||
name: 'origin_rows',
|
name: 'origin_rows',
|
||||||
});
|
});
|
||||||
const watchedOriginURI = useWatch({
|
|
||||||
control: form.control,
|
|
||||||
name: 'origin_uri',
|
|
||||||
});
|
|
||||||
const watchedEnabled = useWatch({ control: form.control, name: 'enabled' });
|
const watchedEnabled = useWatch({ control: form.control, name: 'enabled' });
|
||||||
const watchedEnableHttps = useWatch({
|
const watchedEnableHttps = useWatch({
|
||||||
control: form.control,
|
control: form.control,
|
||||||
@@ -1885,28 +1877,35 @@ export function ProxyRoutesPage() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
{matchResult?.candidate ? (
|
{matchResult?.candidate ? (
|
||||||
<SelectSection title="自动匹配">
|
<>
|
||||||
<SelectItem key={String(matchResult.candidate.certificate_id)}>
|
<SelectItem key="__auto_match_label__" isDisabled textValue="自动匹配">
|
||||||
|
自动匹配
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem
|
||||||
|
key={String(matchResult.candidate.certificate_id)}
|
||||||
|
textValue={matchResult.candidate.certificate_name}
|
||||||
|
>
|
||||||
{matchResult.candidate.certificate_name}
|
{matchResult.candidate.certificate_name}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
</SelectSection>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
<SelectSection title="全部证书">
|
<SelectItem key="__all_certificates_label__" isDisabled textValue="全部证书">
|
||||||
{certificates
|
全部证书
|
||||||
.filter(
|
</SelectItem>
|
||||||
(certificate) =>
|
{certificates
|
||||||
String(certificate.id) !==
|
.filter(
|
||||||
String(matchResult?.candidate?.certificate_id ?? ''),
|
(certificate) =>
|
||||||
)
|
String(certificate.id) !==
|
||||||
.map((certificate) => (
|
String(matchResult?.candidate?.certificate_id ?? ''),
|
||||||
<SelectItem
|
)
|
||||||
key={String(certificate.id)}
|
.map((certificate) => (
|
||||||
textValue={buildCertificateLabel(certificate)}
|
<SelectItem
|
||||||
>
|
key={String(certificate.id)}
|
||||||
{buildCertificateLabel(certificate)}
|
textValue={buildCertificateLabel(certificate)}
|
||||||
</SelectItem>
|
>
|
||||||
))}
|
{buildCertificateLabel(certificate)}
|
||||||
</SelectSection>
|
</SelectItem>
|
||||||
|
))}
|
||||||
</HeroSelectField>
|
</HeroSelectField>
|
||||||
</ResourceField>
|
</ResourceField>
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,8 @@
|
|||||||
"format:check": "prettier --check ."
|
"format:check": "prettier --check ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroui/input": "^2.4.33",
|
"@heroui/react": "^3.0.1",
|
||||||
"@heroui/react": "^2.8.10",
|
"@heroui/styles": "^3.0.1",
|
||||||
"@heroui/select": "^2.4.33",
|
|
||||||
"@hookform/resolvers": "^4.1.3",
|
"@hookform/resolvers": "^4.1.3",
|
||||||
"@tanstack/react-query": "^5.66.8",
|
"@tanstack/react-query": "^5.66.8",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
|
|||||||
Generated
+665
-1692
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user