feat: integrate platform backend and application interfaces
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@miragenflow/contracts",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,462 @@
|
||||
export const CONTRACT_VERSION = "2026-08-20.v1" as const;
|
||||
export const API_PREFIX = "/api/v1" as const;
|
||||
export const WS_PATH = "/api/v1/ws/tasks" as const;
|
||||
|
||||
export const ErrorCodes = {
|
||||
Unauthorized: "UNAUTHORIZED",
|
||||
Forbidden: "FORBIDDEN",
|
||||
ValidationFailed: "VALIDATION_FAILED",
|
||||
RateLimited: "RATE_LIMITED",
|
||||
NotFound: "NOT_FOUND",
|
||||
Conflict: "CONFLICT",
|
||||
InsufficientBalance: "INSUFFICIENT_BALANCE",
|
||||
CapabilityNotEnabled: "CAPABILITY_NOT_ENABLED",
|
||||
ModelGroupUnavailable: "MODEL_GROUP_UNAVAILABLE",
|
||||
Internal: "INTERNAL_ERROR",
|
||||
VerificationRequired: "VERIFICATION_REQUIRED",
|
||||
VerificationExpired: "VERIFICATION_EXPIRED",
|
||||
SessionReused: "SESSION_REUSED",
|
||||
IdempotencyConflict: "IDEMPOTENCY_CONFLICT",
|
||||
ObjectNotFound: "OBJECT_NOT_FOUND",
|
||||
ObjectOwnershipDenied: "OBJECT_OWNERSHIP_DENIED",
|
||||
FileRejected: "FILE_REJECTED",
|
||||
StorageUnavailable: "STORAGE_UNAVAILABLE",
|
||||
ApprovalRequired: "APPROVAL_REQUIRED",
|
||||
VersionConflict: "VERSION_CONFLICT",
|
||||
AdminMfaRequired: "ADMIN_MFA_REQUIRED",
|
||||
} as const;
|
||||
|
||||
export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
|
||||
|
||||
export type ApiError = {
|
||||
code: ErrorCode;
|
||||
message: string;
|
||||
requestId: string;
|
||||
details?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type ApiEnvelope<T> =
|
||||
| { ok: true; data: T; requestId: string }
|
||||
| { ok: false; error: ApiError };
|
||||
|
||||
export type AuthUser = {
|
||||
id: string;
|
||||
username?: string;
|
||||
email?: string;
|
||||
phone?: string;
|
||||
displayName: string;
|
||||
status: "pending_verification" | "active" | "frozen" | "closing";
|
||||
mfaRequired: boolean;
|
||||
mfaEnabled: boolean;
|
||||
mfaSetupRequired: boolean;
|
||||
};
|
||||
|
||||
export type SessionResponse = {
|
||||
user: AuthUser;
|
||||
accessToken: string;
|
||||
accessTokenExpiresAt: string;
|
||||
};
|
||||
|
||||
export type MfaEnrollment = {
|
||||
secret: string;
|
||||
provisioningUri: string;
|
||||
recoveryCodes: string[];
|
||||
};
|
||||
|
||||
export type UserMfaChallengeResponse =
|
||||
| { mfaRequired: true; challengeId: string; challengeType: "verify" }
|
||||
| { mfaRequired: true; challengeId: string; challengeType: "setup"; mfaEnrollment: MfaEnrollment };
|
||||
|
||||
export type UserMfaSetupResponse = {
|
||||
enabled: boolean;
|
||||
challengeId: string;
|
||||
mfaEnrollment: MfaEnrollment;
|
||||
};
|
||||
|
||||
export type UserMfaVerifyResponse =
|
||||
| (SessionResponse & { mfaRequired: false })
|
||||
| { enabled: true; user: AuthUser };
|
||||
|
||||
export type CaptchaAction = "register" | "login" | "verify" | "reset" | "admin-login";
|
||||
export type CaptchaChallengeResponse = { challengeId: string; question: string; expiresAt: string };
|
||||
|
||||
export type ModelCapability = "image" | "text" | "audio" | "utility" | "3d" | "reverse-prompt" | "multi-angle" | "matting" | "split" | "upscale" | "expand";
|
||||
|
||||
export type CapabilitySchema = {
|
||||
capability: ModelCapability;
|
||||
inputTypes: Array<"prompt" | "image" | "mask" | "audio" | "text">;
|
||||
maxInputBytes?: number;
|
||||
parameters?: Record<string, { type: string; required?: boolean; enum?: string[]; min?: number; max?: number }>;
|
||||
resultTypes: Array<"image" | "text" | "audio" | "archive" | "3d">;
|
||||
async: boolean;
|
||||
};
|
||||
|
||||
export type PublicResolution = {
|
||||
id: string;
|
||||
label: string;
|
||||
width: number;
|
||||
height: number;
|
||||
priceMultiplier: number;
|
||||
/** Standard image ratios enabled for this billing preset; `auto` is implicit. */
|
||||
ratios?: string[];
|
||||
};
|
||||
|
||||
export type ReferenceImageInput = {
|
||||
objectId: string;
|
||||
seq: number;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type ReferenceImageGroup = {
|
||||
id?: string;
|
||||
images: ReferenceImageInput[];
|
||||
};
|
||||
|
||||
export type ImageOutputMetadata = {
|
||||
width?: number;
|
||||
height?: number;
|
||||
format?: "png" | "jpeg" | "webp" | string;
|
||||
size?: string;
|
||||
/** Public resolution tier selected for this task, when applicable. */
|
||||
resolution?: "1K" | "2K" | "4K" | string;
|
||||
revisedPrompt?: string;
|
||||
usage?: Record<string, number>;
|
||||
source?: "base64" | "url";
|
||||
};
|
||||
|
||||
export type PublicModelProduct = {
|
||||
id: string;
|
||||
publicModelId: string;
|
||||
name: string;
|
||||
tier: "basic" | "advanced" | "flagship";
|
||||
capabilities: ModelCapability[];
|
||||
resolutions: PublicResolution[];
|
||||
basePrice: number;
|
||||
currencyUnit: string;
|
||||
enabled: boolean;
|
||||
version?: number;
|
||||
capabilitiesSchema?: CapabilitySchema[];
|
||||
publicErrorMessages?: Partial<Record<ErrorCode, string>>;
|
||||
maxCount?: number;
|
||||
maxConcurrent?: number;
|
||||
};
|
||||
|
||||
export type InternalModelProduct = PublicModelProduct & {
|
||||
channelGroupId?: string;
|
||||
};
|
||||
|
||||
export type BalanceSummary = {
|
||||
available: number;
|
||||
reserved: number;
|
||||
unit: { name: string; shortCode: string; icon: string; precision: number; version: number };
|
||||
/** Reserved for future organization/team balances; V1 always omits it. */
|
||||
organizationId?: string;
|
||||
};
|
||||
|
||||
/** Organization/team scope is deliberately a nullable contract extension in
|
||||
* V1. No organization records or sharing endpoints are enabled yet. */
|
||||
export type OrganizationScope = {
|
||||
organizationId?: string;
|
||||
workspaceOwnerId?: string;
|
||||
objectScope?: "user" | "organization";
|
||||
};
|
||||
|
||||
export type BalanceLedgerEntry = {
|
||||
id: string;
|
||||
userId: string;
|
||||
type: "recharge" | "reserve" | "settle" | "release" | "refund" | "adjustment";
|
||||
amount: number;
|
||||
balanceUnitVersion: number;
|
||||
idempotencyKey: string;
|
||||
createdAt: string;
|
||||
referenceId?: string;
|
||||
bucketId?: string;
|
||||
taskId?: string;
|
||||
outputId?: string;
|
||||
expiresAt?: string;
|
||||
status?: "posted" | "voided";
|
||||
};
|
||||
|
||||
export type BalanceBucket = OrganizationScope & {
|
||||
id: string;
|
||||
userId: string;
|
||||
source: "recharge" | "plan" | "manual" | "bonus";
|
||||
remaining: number;
|
||||
expiresAt?: string;
|
||||
priority: number;
|
||||
};
|
||||
|
||||
export type BalanceUnitConfig = {
|
||||
name: string;
|
||||
shortCode: string;
|
||||
icon: string;
|
||||
precision: number;
|
||||
version: number;
|
||||
currencyCode: string;
|
||||
conversionRate: number;
|
||||
rounding: "floor" | "ceil" | "round";
|
||||
};
|
||||
|
||||
export type MembershipPlan = {
|
||||
id: string;
|
||||
code: string;
|
||||
name: string;
|
||||
icon?: string;
|
||||
description: string;
|
||||
durationDays: number;
|
||||
purchaseAmount: number;
|
||||
includedBalance: number;
|
||||
published: boolean;
|
||||
allowedModelProductIds: string[];
|
||||
allowedChannelGroupIds: string[];
|
||||
maxConcurrent: number;
|
||||
queuePriority: number;
|
||||
retentionDays: number;
|
||||
maxRetentionExtensionDays: number;
|
||||
version: number;
|
||||
};
|
||||
|
||||
export type TaskType = "image" | "text" | "audio" | "reverse-prompt" | "multi-angle" | "matting" | "split" | "upscale" | "expand" | "3d";
|
||||
export type TaskStatus = "queued" | "running" | "succeeded" | "partial" | "failed" | "unknown" | "canceled";
|
||||
|
||||
export type CreateTaskRequest = OrganizationScope & {
|
||||
modelProductId: string;
|
||||
resolutionPresetId?: string;
|
||||
prompt?: string;
|
||||
references?: string[];
|
||||
referenceGroup?: ReferenceImageGroup;
|
||||
maskObjectId?: string;
|
||||
count?: number;
|
||||
canvasProjectId?: string;
|
||||
params?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type GenerationTask = OrganizationScope & {
|
||||
id: string;
|
||||
ownerId: string;
|
||||
taskType: TaskType;
|
||||
modelProductId: string;
|
||||
status: TaskStatus;
|
||||
estimatedCost: number;
|
||||
reservedCost: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
eventSequence: number;
|
||||
channelGroupId: string;
|
||||
routeSnapshotVersion: number;
|
||||
attempts: GenerationAttempt[];
|
||||
outputs: Array<{ id: string; mimeType: string; url?: string; status: "succeeded" | "failed"; unitPriceSnapshot?: number; chargedAmount?: number; metadata?: ImageOutputMetadata }>;
|
||||
publicErrorCode?: ErrorCode;
|
||||
prompt?: string;
|
||||
resolutionPresetId?: string;
|
||||
count?: number;
|
||||
pricingSnapshot?: { basePrice: number; multiplier: number; unitVersion: number };
|
||||
modelSnapshot?: { publicModelId: string; version: number };
|
||||
routeSnapshot?: { groupId: string; version: number; channelIds: string[]; retryBudget?: number; channelRetryBudgets?: Record<string, number> };
|
||||
planSnapshot?: { planId?: string; version?: number; queuePriority: number; maxConcurrent: number };
|
||||
leaseExpiresAt?: string;
|
||||
/** Fences a late worker/provider response after a lease is recovered. */
|
||||
leaseToken?: string;
|
||||
providerSubmitted?: boolean;
|
||||
idempotencyKey?: string;
|
||||
requestFingerprint?: string;
|
||||
retentionExpiresAt?: string;
|
||||
retentionState?: "active" | "archiving" | "archive_failed" | "archived" | "deleted";
|
||||
retentionExtensionDays?: number;
|
||||
reserveExpiresAt?: string;
|
||||
inputSnapshot?: { references: string[]; referenceGroup?: ReferenceImageGroup; maskObjectId?: string; params: Record<string, unknown>; originalPrompt?: string };
|
||||
};
|
||||
|
||||
export type GenerationAttempt = {
|
||||
id: string;
|
||||
channelId: string;
|
||||
sequence: number;
|
||||
status: "started" | "succeeded" | "failed" | "unknown";
|
||||
errorCode?: string;
|
||||
providerRequestId?: string;
|
||||
platformIdempotencyKey?: string;
|
||||
startedAt: string;
|
||||
finishedAt?: string;
|
||||
leaseExpiresAt?: string;
|
||||
retryable?: boolean;
|
||||
reconciliationStatus?: "pending" | "confirmed_success" | "confirmed_failure" | "manual_review";
|
||||
};
|
||||
|
||||
export type PublicGenerationAttempt = {
|
||||
id: string;
|
||||
sequence: number;
|
||||
status: GenerationAttempt["status"];
|
||||
startedAt: string;
|
||||
finishedAt?: string;
|
||||
retryable?: boolean;
|
||||
reconciliationStatus?: GenerationAttempt["reconciliationStatus"];
|
||||
};
|
||||
|
||||
export type PublicGenerationTask = {
|
||||
id: string;
|
||||
taskType: TaskType;
|
||||
modelProductId: string;
|
||||
status: TaskStatus;
|
||||
estimatedCost: number;
|
||||
reservedCost: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
eventSequence: number;
|
||||
publicErrorCode?: ErrorCode;
|
||||
prompt?: string;
|
||||
resolutionPresetId?: string;
|
||||
count?: number;
|
||||
modelSnapshot?: GenerationTask["modelSnapshot"];
|
||||
retentionExpiresAt?: string;
|
||||
retentionState?: GenerationTask["retentionState"];
|
||||
retentionExtensionDays?: number;
|
||||
inputSnapshot?: GenerationTask["inputSnapshot"];
|
||||
attempts: PublicGenerationAttempt[];
|
||||
outputs: GenerationTask["outputs"];
|
||||
};
|
||||
|
||||
export type TaskEvent = {
|
||||
eventId: string;
|
||||
sequence: number;
|
||||
taskId: string;
|
||||
attemptId?: string;
|
||||
type: "task.queued" | "task.running" | "task.attempt" | "task.progress" | "task.succeeded" | "task.failed" | "task.canceled" | "task.unknown";
|
||||
occurredAt: string;
|
||||
payload: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type PaymentWebhookRequest = { orderId: string; eventId: string; status: "paid" | "failed" | "refunded"; amount?: number; currency?: string };
|
||||
|
||||
export type UploadObject = OrganizationScope & {
|
||||
id: string;
|
||||
idempotencyKey?: string;
|
||||
ownerId: string;
|
||||
mimeType: string;
|
||||
size: number;
|
||||
checksum: string;
|
||||
status: "pending" | "scanning" | "ready" | "rejected" | "deleted";
|
||||
stagingKey?: string;
|
||||
expiresAt: string;
|
||||
};
|
||||
|
||||
export type AssetRecord = OrganizationScope & {
|
||||
id: string;
|
||||
ownerId: string;
|
||||
type: "image" | "text" | "audio" | "archive" | "3d";
|
||||
objectId?: string;
|
||||
taskId?: string;
|
||||
sourceOutputId?: string;
|
||||
name: string;
|
||||
tags: string[];
|
||||
deletedAt?: string;
|
||||
retentionExpiresAt?: string;
|
||||
pinned?: boolean;
|
||||
objectUrl?: string;
|
||||
mimeType?: string;
|
||||
};
|
||||
|
||||
export type WebDavConfigStatus = {
|
||||
configured: boolean;
|
||||
url?: string;
|
||||
username?: string;
|
||||
directory?: string;
|
||||
lastSyncedAt?: string;
|
||||
state: "unconfigured" | "ready" | "syncing" | "error";
|
||||
};
|
||||
|
||||
export type WsClientMessage =
|
||||
| { type: "subscribe"; taskId: string; cursor?: number }
|
||||
| { type: "unsubscribe"; taskId: string }
|
||||
| { type: "ping" };
|
||||
|
||||
export type WsServerMessage =
|
||||
| { type: "ready"; contractVersion: string; heartbeatIntervalMs: number }
|
||||
| { type: "pong"; at: string }
|
||||
| { type: "event"; event: TaskEvent }
|
||||
| { type: "error"; error: ApiError };
|
||||
|
||||
export type HealthResponse = {
|
||||
status: "ok";
|
||||
service: "miragenflow-server";
|
||||
contractVersion: string;
|
||||
now: string;
|
||||
dependencies?: { persistence: { adapter: string; status: string; detail?: string }; queue: { adapter: string; status: string; detail?: string } };
|
||||
};
|
||||
|
||||
export type AdminRole = "super_admin" | "operator" | "finance" | "support" | "auditor";
|
||||
|
||||
export type AdminScope = "admin:read" | "admin:write" | "admin:finance" | "admin:security" | "admin:audit";
|
||||
|
||||
export type AdminUser = {
|
||||
id: string;
|
||||
email: string;
|
||||
roles: AdminRole[];
|
||||
scopes: AdminScope[];
|
||||
mfaRequired: boolean;
|
||||
};
|
||||
|
||||
export type AdminSessionResponse = {
|
||||
admin: AdminUser;
|
||||
accessToken?: string;
|
||||
accessTokenExpiresAt?: string;
|
||||
mfaRequired?: boolean;
|
||||
challengeId?: string;
|
||||
};
|
||||
|
||||
export type AdminPage<T> = {
|
||||
items: T[];
|
||||
total?: number;
|
||||
nextCursor?: string;
|
||||
};
|
||||
|
||||
export type AdminChannelSummary = {
|
||||
id: string;
|
||||
label: string;
|
||||
enabled: boolean;
|
||||
priority: number;
|
||||
health: "healthy" | "degraded" | "open";
|
||||
version: number;
|
||||
retryBudget: number;
|
||||
consecutiveFailures: number;
|
||||
providerType?: "generic" | "openai-images";
|
||||
providerName?: string;
|
||||
providerModelId?: string;
|
||||
enabledModelIds?: string[];
|
||||
modelMappings?: Array<{ displayModelId: string; requestModelId: string }>;
|
||||
resolutionModelMap?: Record<string, string>;
|
||||
baseUrl?: string;
|
||||
secretConfigured?: boolean;
|
||||
};
|
||||
|
||||
export type AdminTaskSummary = {
|
||||
id: string;
|
||||
ownerId: string;
|
||||
taskType: TaskType;
|
||||
modelProductId: string;
|
||||
status: TaskStatus;
|
||||
estimatedCost: number;
|
||||
reservedCost: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
attemptCount: number;
|
||||
outputCount: number;
|
||||
publicErrorCode?: ErrorCode;
|
||||
};
|
||||
|
||||
export type AdminAuditEntry = {
|
||||
id: string;
|
||||
actorId?: string;
|
||||
action: string;
|
||||
category?: string;
|
||||
actionLabel?: string;
|
||||
actorName?: string;
|
||||
actorType?: "admin" | "user" | "system" | "payment" | "unknown";
|
||||
objectType: string;
|
||||
objectId?: string;
|
||||
requestId: string;
|
||||
createdAt: string;
|
||||
statusCode?: number;
|
||||
level?: "normal" | "error";
|
||||
before?: unknown;
|
||||
after?: unknown;
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "@miragenflow/ui",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "./src/index.tsx",
|
||||
"types": "./src/index.tsx",
|
||||
"exports": {
|
||||
".": "./src/index.tsx",
|
||||
"./alert": "./src/alert.ts",
|
||||
"./breadcrumb": "./src/breadcrumb.ts",
|
||||
"./button": "./src/button.tsx",
|
||||
"./card": "./src/card.ts",
|
||||
"./checkbox": "./src/checkbox.ts",
|
||||
"./dialog": "./src/dialog.ts",
|
||||
"./drawer": "./src/drawer.ts",
|
||||
"./dropdown": "./src/dropdown.ts",
|
||||
"./form": "./src/form.ts",
|
||||
"./grid": "./src/grid.ts",
|
||||
"./layout": "./src/layout.ts",
|
||||
"./menu": "./src/menu.ts",
|
||||
"./color-picker": "./src/color-picker.ts",
|
||||
"./date-picker": "./src/date-picker.ts",
|
||||
"./input": "./src/input.ts",
|
||||
"./input-number": "./src/input-number.ts",
|
||||
"./loading": "./src/loading.ts",
|
||||
"./message": "./src/message.ts",
|
||||
"./pagination": "./src/pagination.ts",
|
||||
"./popup": "./src/popup.ts",
|
||||
"./select": "./src/select.ts",
|
||||
"./space": "./src/space.ts",
|
||||
"./slider": "./src/slider.ts",
|
||||
"./switch": "./src/switch.ts",
|
||||
"./statistic": "./src/statistic.ts",
|
||||
"./table": "./src/table.ts",
|
||||
"./tag": "./src/tag.ts",
|
||||
"./textarea": "./src/textarea.ts",
|
||||
"./tabs": "./src/tabs.ts",
|
||||
"./tooltip": "./src/tooltip.ts"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18.0.0",
|
||||
"react-dom": ">=18.0.0",
|
||||
"tdesign-react": "1.15.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "19.1.12",
|
||||
"@types/react-dom": "19.1.9",
|
||||
"react": "19.2.5",
|
||||
"react-dom": "19.2.5",
|
||||
"tdesign-react": "1.15.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Alert } from "tdesign-react/es/alert";
|
||||
export type { AlertProps } from "tdesign-react/es/alert";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Breadcrumb } from "tdesign-react/es/breadcrumb";
|
||||
export type { BreadcrumbProps, BreadcrumbItemProps } from "tdesign-react/es/breadcrumb";
|
||||
@@ -0,0 +1,7 @@
|
||||
.t-button.mf-button--rich {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.t-button.mf-button--rich > .t-button__text {
|
||||
display: contents;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Children, forwardRef, isValidElement, type ReactElement, type ReactNode } from "react";
|
||||
import { Button as TDesignButton } from "tdesign-react/es/button";
|
||||
import type { ButtonProps as TDesignButtonProps } from "tdesign-react/es/button";
|
||||
import "./button.css";
|
||||
|
||||
export type MiragenFlowButtonType = "default" | "primary" | "outline" | "dashed" | "link" | "text" | "danger" | "danger-outline";
|
||||
|
||||
export interface MiragenFlowButtonProps extends Omit<TDesignButtonProps, "children" | "content" | "icon" | "theme" | "type" | "variant"> {
|
||||
children?: ReactNode;
|
||||
htmlType?: "button" | "submit" | "reset";
|
||||
icon?: ReactElement;
|
||||
type?: MiragenFlowButtonType;
|
||||
}
|
||||
|
||||
const buttonTypeMap: Record<MiragenFlowButtonType, { theme: "default" | "primary" | "danger"; variant: "base" | "outline" | "dashed" | "text" }> = {
|
||||
default: { theme: "default", variant: "base" },
|
||||
primary: { theme: "primary", variant: "base" },
|
||||
outline: { theme: "default", variant: "outline" },
|
||||
dashed: { theme: "default", variant: "dashed" },
|
||||
link: { theme: "primary", variant: "text" },
|
||||
text: { theme: "default", variant: "text" },
|
||||
danger: { theme: "danger", variant: "base" },
|
||||
"danger-outline": { theme: "danger", variant: "outline" },
|
||||
};
|
||||
|
||||
export const MiragenFlowButton = forwardRef<HTMLElement, MiragenFlowButtonProps>(function MiragenFlowButton(
|
||||
{ children, className, htmlType = "button", icon, loading, onClick, tag, type = "default", ...rest },
|
||||
ref,
|
||||
) {
|
||||
const mapped = buttonTypeMap[type];
|
||||
const hasRichChildren = Children.count(children) > 1 || Children.toArray(children).some(isValidElement);
|
||||
const resolvedClassName = ["mf-button", hasRichChildren && "mf-button--rich", className].filter(Boolean).join(" ");
|
||||
|
||||
return (
|
||||
<TDesignButton
|
||||
{...rest}
|
||||
ref={ref}
|
||||
className={resolvedClassName}
|
||||
icon={icon}
|
||||
loading={loading}
|
||||
onClick={onClick}
|
||||
tag={tag ?? (rest.href ? undefined : "button")}
|
||||
theme={mapped.theme}
|
||||
type={htmlType}
|
||||
variant={mapped.variant}
|
||||
>
|
||||
{children}
|
||||
</TDesignButton>
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Card } from "tdesign-react/es/card";
|
||||
export type { CardProps } from "tdesign-react/es/card";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Checkbox } from "tdesign-react/es/checkbox";
|
||||
export type { CheckboxProps } from "tdesign-react/es/checkbox";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { ColorPicker, ColorPickerPanel } from "tdesign-react/es/color-picker";
|
||||
export type { ColorPickerProps } from "tdesign-react/es/color-picker";
|
||||
@@ -0,0 +1,8 @@
|
||||
export { DatePicker, DateRangePicker, DatePickerPanel, DateRangePickerPanel } from "tdesign-react/es/date-picker";
|
||||
export type {
|
||||
DatePickerProps,
|
||||
DateRangePickerProps,
|
||||
DatePickerPanelProps,
|
||||
DateRangePickerPanelProps,
|
||||
DateRangeValue,
|
||||
} from "tdesign-react/es/date-picker";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Dialog, DialogPlugin } from "tdesign-react/es/dialog";
|
||||
export type { DialogInstance, DialogProps } from "tdesign-react/es/dialog";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Drawer, DrawerPlugin } from "tdesign-react/es/drawer";
|
||||
export type { DrawerInstance, DrawerProps } from "tdesign-react/es/drawer";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Dropdown } from "tdesign-react/es/dropdown";
|
||||
export type { DropdownProps } from "tdesign-react/es/dropdown";
|
||||
@@ -0,0 +1,8 @@
|
||||
export { Form } from "tdesign-react/es/form";
|
||||
export type {
|
||||
FormInstanceFunctions,
|
||||
FormItemProps,
|
||||
FormProps,
|
||||
FormRule,
|
||||
SubmitContext,
|
||||
} from "tdesign-react/es/form";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Col, Row } from "tdesign-react/es/grid";
|
||||
export type { ColProps, RowProps } from "tdesign-react/es/grid";
|
||||
@@ -0,0 +1,92 @@
|
||||
import type { ReactNode } from "react";
|
||||
import { ConfigProvider } from "tdesign-react/es/config-provider";
|
||||
import enUS from "tdesign-react/es/locale/en_US";
|
||||
import zhCN from "tdesign-react/es/locale/zh_CN";
|
||||
|
||||
export { MiragenFlowButton } from "./button";
|
||||
export type { MiragenFlowButtonProps, MiragenFlowButtonType } from "./button";
|
||||
export { Alert } from "./alert";
|
||||
export type { AlertProps } from "./alert";
|
||||
export { Card } from "./card";
|
||||
export type { CardProps } from "./card";
|
||||
export { Breadcrumb } from "./breadcrumb";
|
||||
export type { BreadcrumbProps, BreadcrumbItemProps } from "./breadcrumb";
|
||||
export { Checkbox } from "./checkbox";
|
||||
export type { CheckboxProps } from "./checkbox";
|
||||
export { Dialog, DialogPlugin } from "./dialog";
|
||||
export type { DialogInstance, DialogProps } from "./dialog";
|
||||
export { Drawer, DrawerPlugin } from "./drawer";
|
||||
export type { DrawerInstance, DrawerProps } from "./drawer";
|
||||
export { Dropdown } from "./dropdown";
|
||||
export type { DropdownProps } from "./dropdown";
|
||||
export { Form } from "./form";
|
||||
export type { FormInstanceFunctions, FormItemProps, FormProps, FormRule, SubmitContext } from "./form";
|
||||
export { Col, Row } from "./grid";
|
||||
export type { ColProps, RowProps } from "./grid";
|
||||
export { Layout } from "./layout";
|
||||
export type { LayoutProps } from "./layout";
|
||||
export { Menu } from "./menu";
|
||||
export type { HeadMenuProps, MenuItemProps, MenuProps, MenuValue, SubMenuProps } from "./menu";
|
||||
export { ColorPicker, ColorPickerPanel } from "./color-picker";
|
||||
export type { ColorPickerProps } from "./color-picker";
|
||||
export { DatePicker, DateRangePicker, DatePickerPanel, DateRangePickerPanel } from "./date-picker";
|
||||
export type { DatePickerProps, DateRangePickerProps, DatePickerPanelProps, DateRangePickerPanelProps, DateRangeValue } from "./date-picker";
|
||||
export { Input, InputGroup } from "./input";
|
||||
export type { InputGroupProps, InputProps, InputRef } from "./input";
|
||||
export { InputNumber } from "./input-number";
|
||||
export type { InputNumberProps } from "./input-number";
|
||||
export { Loading } from "./loading";
|
||||
export type { LoadingProps } from "./loading";
|
||||
export { MessagePlugin } from "./message";
|
||||
export type { MessageOptions } from "./message";
|
||||
export { Popup, PopupPlugin } from "./popup";
|
||||
export type { PopupProps, PopupRef } from "./popup";
|
||||
export { Pagination } from "./pagination";
|
||||
export type { PaginationProps } from "./pagination";
|
||||
export { Select } from "./select";
|
||||
export type { SelectProps } from "./select";
|
||||
export { Space } from "./space";
|
||||
export type { SpaceProps } from "./space";
|
||||
export { Switch } from "./switch";
|
||||
export type { SwitchProps } from "./switch";
|
||||
export { Statistic } from "./statistic";
|
||||
export type { StatisticProps, StatisticRef } from "./statistic";
|
||||
export { Table, BaseTable, EnhancedTable, PrimaryTable, SimpleTable } from "./table";
|
||||
export type {
|
||||
BaseTableColumns,
|
||||
BaseTableProps,
|
||||
DragSortContext,
|
||||
EnhancedTableProps,
|
||||
PrimaryTableCol,
|
||||
PrimaryTableProps,
|
||||
TableProps,
|
||||
TableRowData,
|
||||
} from "./table";
|
||||
export { Tag } from "./tag";
|
||||
export type { TagProps } from "./tag";
|
||||
export { Textarea } from "./textarea";
|
||||
export type { TextareaProps } from "./textarea";
|
||||
export { Tabs } from "./tabs";
|
||||
export type { TabPanelProps, TabValue, TabsProps } from "./tabs";
|
||||
export { Slider } from "./slider";
|
||||
export type { SliderProps } from "./slider";
|
||||
export { Tooltip, TooltipLite } from "./tooltip";
|
||||
export type { TooltipLiteProps, TooltipProps } from "./tooltip";
|
||||
|
||||
export type MiragenFlowLocale = "zh-CN" | "en-US";
|
||||
|
||||
export type TDesignThemeVariables = Record<string, string>;
|
||||
|
||||
export function TDesignProvider({ locale, children }: { locale: MiragenFlowLocale; children: ReactNode }) {
|
||||
return <ConfigProvider globalConfig={locale === "zh-CN" ? zhCN : enUS}>{children}</ConfigProvider>;
|
||||
}
|
||||
|
||||
export function applyTDesignVariables(mode: "light" | "dark", variables: TDesignThemeVariables) {
|
||||
const root = document.documentElement;
|
||||
|
||||
root.setAttribute("theme-mode", mode);
|
||||
root.setAttribute("data-mf-tdesign", "true");
|
||||
Object.entries(variables).forEach(([name, value]) => {
|
||||
root.style.setProperty(name, value);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export { InputNumber } from "tdesign-react/es/input-number";
|
||||
export type { InputNumberProps } from "tdesign-react/es/input-number";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Input, InputGroup } from "tdesign-react/es/input";
|
||||
export type { InputGroupProps, InputProps, InputRef } from "tdesign-react/es/input";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Layout } from "tdesign-react/es/layout";
|
||||
export type { LayoutProps } from "tdesign-react/es/layout";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Loading } from "tdesign-react/es/loading";
|
||||
export type { LoadingProps } from "tdesign-react/es/loading";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Menu } from "tdesign-react/es/menu";
|
||||
export type { HeadMenuProps, MenuItemProps, MenuProps, MenuValue, SubMenuProps } from "tdesign-react/es/menu";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { MessagePlugin } from "tdesign-react/es/message";
|
||||
export type { MessageOptions } from "tdesign-react/es/message";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Pagination } from "tdesign-react/es/pagination";
|
||||
export type { PaginationProps } from "tdesign-react/es/pagination";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Popup, PopupPlugin } from "tdesign-react/es/popup";
|
||||
export type { PopupProps, PopupRef } from "tdesign-react/es/popup";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Select } from "tdesign-react/es/select";
|
||||
export type { SelectProps } from "tdesign-react/es/select";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Slider } from "tdesign-react/es/slider";
|
||||
export type { SliderProps } from "tdesign-react/es/slider";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Space } from "tdesign-react/es/space";
|
||||
export type { SpaceProps } from "tdesign-react/es/space";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Statistic } from "tdesign-react/es/statistic";
|
||||
export type { StatisticProps, StatisticRef } from "tdesign-react/es/statistic";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Switch } from "tdesign-react/es/switch";
|
||||
export type { SwitchProps } from "tdesign-react/es/switch";
|
||||
@@ -0,0 +1,11 @@
|
||||
export { Table, BaseTable, EnhancedTable, PrimaryTable, SimpleTable } from "tdesign-react/es/table";
|
||||
export type {
|
||||
BaseTableColumns,
|
||||
BaseTableProps,
|
||||
DragSortContext,
|
||||
EnhancedTableProps,
|
||||
PrimaryTableCol,
|
||||
PrimaryTableProps,
|
||||
TableProps,
|
||||
TableRowData,
|
||||
} from "tdesign-react/es/table";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Tabs } from "tdesign-react/es/tabs";
|
||||
export type { TabPanelProps, TabValue, TabsProps } from "tdesign-react/es/tabs";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Tag } from "tdesign-react/es/tag";
|
||||
export type { TagProps } from "tdesign-react/es/tag";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Textarea } from "tdesign-react/es/textarea";
|
||||
export type { TextareaProps } from "tdesign-react/es/textarea";
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Tooltip, TooltipLite } from "tdesign-react/es/tooltip";
|
||||
export type { TooltipLiteProps, TooltipProps } from "tdesign-react/es/tooltip";
|
||||
Reference in New Issue
Block a user