mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-11-12 22:29:53 -06:00
Report exports only used in their own file
This commit is contained in:
@@ -38,7 +38,7 @@ const TOOLTIP_FLIP_RATIO = 0.55;
|
||||
const SIDES = [0, 1] as const;
|
||||
|
||||
/** One objective-counter read, values in `[alpha, bravo]` order. */
|
||||
export interface ObjectiveTimelineSample {
|
||||
interface ObjectiveTimelineSample {
|
||||
/** seconds shown on the match timer at the read ("3:35" = 215); null = unreadable */
|
||||
time: number | null;
|
||||
/** displayed count per team; null = unreadable */
|
||||
|
||||
@@ -2,7 +2,7 @@ import clsx from "clsx";
|
||||
import { ArrowDown, ArrowUp, ChevronsUpDown } from "lucide-react";
|
||||
import styles from "./SortableTableHeader.module.css";
|
||||
|
||||
export type SortDirection = "asc" | "desc";
|
||||
type SortDirection = "asc" | "desc";
|
||||
|
||||
export type SortState<Key extends string = string> = {
|
||||
key: Key;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Flipper } from "../Flipper";
|
||||
import { SendouButton } from "./Button";
|
||||
import styles from "./Toast.module.css";
|
||||
|
||||
export interface SendouToast {
|
||||
interface SendouToast {
|
||||
message: string;
|
||||
variant: "error" | "success" | "info";
|
||||
}
|
||||
|
||||
@@ -4,11 +4,9 @@ import { SEARCH_DEBOUNCE_MS } from "~/features/search/search-constants";
|
||||
import { useDebounce } from "~/hooks/useDebounce";
|
||||
|
||||
/** Sentinel items rendered in place of real results while loading or when empty. */
|
||||
export type EntitySearchPlaceholder =
|
||||
| { id: "PLACEHOLDER" }
|
||||
| { id: "NO_RESULTS" };
|
||||
type EntitySearchPlaceholder = { id: "PLACEHOLDER" } | { id: "NO_RESULTS" };
|
||||
|
||||
export type EntitySearchItem<TItem> = TItem | EntitySearchPlaceholder;
|
||||
type EntitySearchItem<TItem> = TItem | EntitySearchPlaceholder;
|
||||
|
||||
interface UseEntitySearchArgs<TItem extends { id: number }> {
|
||||
/** Builds the loader URL queried (debounced) as the user types. */
|
||||
|
||||
@@ -50,7 +50,7 @@ const WEAPON_DESTINATIONS = [
|
||||
"art",
|
||||
"lfg",
|
||||
] as const;
|
||||
export type WeaponDestination = (typeof WEAPON_DESTINATIONS)[number];
|
||||
type WeaponDestination = (typeof WEAPON_DESTINATIONS)[number];
|
||||
|
||||
export interface SelectedWeapon {
|
||||
id: MainWeaponId;
|
||||
|
||||
@@ -52,12 +52,12 @@ const ABILITY_NAMES: ReadonlySet<string> = new Set(
|
||||
|
||||
type MatchSide = "ALPHA" | "BRAVO";
|
||||
|
||||
export interface TimelineTeam {
|
||||
interface TimelineTeam {
|
||||
name: string;
|
||||
avatar?: string;
|
||||
}
|
||||
|
||||
export interface TimelineScoreboardPlayer {
|
||||
interface TimelineScoreboardPlayer {
|
||||
name: string;
|
||||
weaponSplId: MainWeaponId | null;
|
||||
ka: number | null;
|
||||
|
||||
278
app/db/tables.ts
278
app/db/tables.ts
File diff suppressed because it is too large
Load Diff
@@ -125,7 +125,7 @@ export interface BaseWeaponStats extends RangeParams {
|
||||
/** A way of shooting a main weapon with its own flight, e.g. a roller's vertical or horizontal swing */
|
||||
export type RangeVariantKey = (typeof RANGE_VARIANT_KEYS)[number];
|
||||
|
||||
export interface RangeVariantParams extends RangeParams {
|
||||
interface RangeVariantParams extends RangeParams {
|
||||
Range_VariantKey: RangeVariantKey;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ interface AttentionEnvironment {
|
||||
export type Tracker = ReturnType<typeof createTracker>;
|
||||
|
||||
// Whether the user is paying attention to this tab. It has to be visible, window focused, and be interacted with in the last 3 minutes
|
||||
/** @internal */
|
||||
export function createTracker(
|
||||
getEnvironment: () => AttentionEnvironment,
|
||||
{ idleAfterMs = IDLE_AFTER_MS }: { idleAfterMs?: number } = {},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/** @internal */
|
||||
export const CHAT_STICKERS = [
|
||||
{ id: "booyah", name: "Booyah" },
|
||||
{ id: "despair", name: "Despair" },
|
||||
|
||||
@@ -8,7 +8,7 @@ export type CapturedSource =
|
||||
| "uncaught error"
|
||||
| "unhandled rejection";
|
||||
|
||||
export interface CapturedEntry {
|
||||
interface CapturedEntry {
|
||||
id: number;
|
||||
level: CapturedLevel;
|
||||
source: CapturedSource;
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { ServerEvent } from "~/features/events/events-types";
|
||||
|
||||
const MAX_ENTRIES = 300;
|
||||
|
||||
export type RecordedEvent =
|
||||
type RecordedEvent =
|
||||
| { id: number; at: number; type: "event"; event: ServerEvent }
|
||||
| { id: number; at: number; type: "connection"; state: EventsReadyState };
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ const UNTRACKED_PATH_PREFIXES = ["/dev/", "/sse"];
|
||||
|
||||
export type RequestKind = "document" | "data" | "action" | "resource";
|
||||
|
||||
export interface LoggedQuery {
|
||||
interface LoggedQuery {
|
||||
sql: string;
|
||||
parameters: unknown[];
|
||||
durationMs: number;
|
||||
|
||||
@@ -84,7 +84,7 @@ export interface TeammateHistory {
|
||||
}
|
||||
|
||||
/** A candidate split of the players into two teams, scored by {@link splitCost}. */
|
||||
export interface Split {
|
||||
interface Split {
|
||||
alpha: ShufflePlayer[];
|
||||
bravo: ShufflePlayer[];
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ export const ROLLABLE_WEAPON_IDS = mainWeaponIds.filter(
|
||||
(weaponId) => weaponIdToType(weaponId) !== "ALT_SKIN",
|
||||
);
|
||||
|
||||
export interface WeaponRollCost {
|
||||
interface WeaponRollCost {
|
||||
strength: number;
|
||||
shape: number;
|
||||
shapeMismatch: number;
|
||||
|
||||
@@ -27,7 +27,7 @@ import { SendouMenu, SendouMenuItem } from "~/components/elements/Menu";
|
||||
import * as CoachPlayback from "../core/CoachPlayback";
|
||||
import styles from "./CoachControls.module.css";
|
||||
|
||||
export type CoachStep = "GAME" | "LIFE" | "EVENT" | "SECONDS";
|
||||
type CoachStep = "GAME" | "LIFE" | "EVENT" | "SECONDS";
|
||||
|
||||
interface StepControl {
|
||||
label: string;
|
||||
|
||||
@@ -103,11 +103,11 @@ const NO_SOURCE_ERROR =
|
||||
const MISSING_ATLASES_ERROR =
|
||||
"Some of the scanner's game data could not be downloaded — check the connection and start the capture again";
|
||||
|
||||
export type LiveStatus = "idle" | "starting" | "running" | "error";
|
||||
type LiveStatus = "idle" | "starting" | "running" | "error";
|
||||
/** `unsupported`: no WebCodecs/track processor; `failed`: the encoder refused this stream */
|
||||
export type ClipsState = "on" | "off" | "unsupported" | "failed";
|
||||
type ClipsState = "on" | "off" | "unsupported" | "failed";
|
||||
/** `muted`: the browser gets nothing from the device; `silent`: it gets samples, all of them silence; `ended`: the track stopped (a share ended, say); `failed`: the encoder gave up */
|
||||
export type AudioSignal = "ok" | "silent" | "muted" | "ended" | "failed";
|
||||
type AudioSignal = "ok" | "silent" | "muted" | "ended" | "failed";
|
||||
|
||||
export interface LiveSnapshot {
|
||||
status: LiveStatus;
|
||||
|
||||
@@ -60,7 +60,7 @@ import { describeError } from "./errors";
|
||||
import { scannedTeamComps } from "./montage-comps";
|
||||
import { cancelVodScan, startVodScan } from "./vod-scan";
|
||||
|
||||
export interface MontageFolder {
|
||||
interface MontageFolder {
|
||||
manifest: MontageManifest;
|
||||
/** the manifest's VoDs found in the folder */
|
||||
vods: MontageManifestVod[];
|
||||
@@ -69,7 +69,7 @@ export interface MontageFolder {
|
||||
directory: FileSystemDirectoryHandle | null;
|
||||
}
|
||||
|
||||
export type MontageScan =
|
||||
type MontageScan =
|
||||
| { state: "scanning"; file: string; index: number; total: number }
|
||||
| { state: "done"; failed: string[] };
|
||||
|
||||
@@ -93,7 +93,7 @@ type GraphicCapture = (graphic: MontageGraphic) => Promise<{
|
||||
revealRects: CardRevealRect[];
|
||||
}>;
|
||||
|
||||
export type MontageRender =
|
||||
type MontageRender =
|
||||
| ({ state: "rendering" } & MontageRenderProgress)
|
||||
| { state: "done"; error: string | null };
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ export interface ScannerSettings {
|
||||
}
|
||||
|
||||
export const CLIP_MIN_KILLS_OPTIONS = [3, 4, 5] as const;
|
||||
export type ClipMinKills = (typeof CLIP_MIN_KILLS_OPTIONS)[number];
|
||||
type ClipMinKills = (typeof CLIP_MIN_KILLS_OPTIONS)[number];
|
||||
|
||||
/**
|
||||
* `source`: the video input's own audio side; `desktop`: the system's sound
|
||||
|
||||
@@ -73,13 +73,13 @@ const UI_UPDATE_INTERVAL_MS = 250;
|
||||
*/
|
||||
const EVENTS_PUBLISH_INTERVAL_MS = 1000;
|
||||
|
||||
export type VodScanStatus = "idle" | "scanning" | "done" | "error";
|
||||
type VodScanStatus = "idle" | "scanning" | "done" | "error";
|
||||
|
||||
export type ClipsWork =
|
||||
type ClipsWork =
|
||||
| { state: "cutting"; done: number; total: number }
|
||||
| { state: "done"; saved: number; error: string | null };
|
||||
|
||||
export type VodScanMode = "active" | "skim";
|
||||
type VodScanMode = "active" | "skim";
|
||||
|
||||
/** One worker's slice of the file. */
|
||||
export interface VodScanLane {
|
||||
@@ -93,7 +93,7 @@ export interface VodScanLane {
|
||||
failed: boolean;
|
||||
}
|
||||
|
||||
export interface VodScanProgress {
|
||||
interface VodScanProgress {
|
||||
t: number;
|
||||
duration: number;
|
||||
/** scan speed as a multiple of realtime */
|
||||
|
||||
@@ -483,7 +483,7 @@ export interface CoachLife {
|
||||
summary: CoachLifeSummary | null;
|
||||
}
|
||||
|
||||
export interface CoachLifeSummary {
|
||||
interface CoachLifeSummary {
|
||||
/** seconds alive, the first life counted from the game clock's start when read */
|
||||
duration: number;
|
||||
/** the POV player's splats in the life (a trade on the death's second included); null without a kill feed read */
|
||||
|
||||
@@ -13,7 +13,7 @@ const INTERVAL_EPSILON_S = 1e-6;
|
||||
/** Stepped samples remembered, so a plan made behind the decoder can be replayed up to it. */
|
||||
const HISTORY_LIMIT = 512;
|
||||
|
||||
export interface DetectorCheckPlan {
|
||||
interface DetectorCheckPlan {
|
||||
lastCheckT: number;
|
||||
/** intervals the detector's next check may come after */
|
||||
next: readonly number[];
|
||||
|
||||
@@ -70,7 +70,7 @@ import { readTrackSteps, trackComb } from "./track";
|
||||
export type ObjectiveData = ZonesObjectiveData | TrackObjectiveData;
|
||||
|
||||
/** Splat Zones / Clam Blitz plates. */
|
||||
export interface ZonesObjectiveData {
|
||||
interface ZonesObjectiveData {
|
||||
/** names the plates overlay: CB draws it too, so the match's mode tells the two apart */
|
||||
mode: "SZ";
|
||||
/** match timer seconds ("3:35" = 215); null = unreadable. Overtime display unattested so far. */
|
||||
@@ -92,7 +92,10 @@ export interface ZonesObjectiveData {
|
||||
teamColor: [InkRgb | null, InkRgb | null];
|
||||
}
|
||||
|
||||
/** Tower Control / Rainmaker: one overlay, told apart only by its checkpoint markers. */
|
||||
/**
|
||||
* Tower Control / Rainmaker: one overlay, told apart only by its checkpoint markers.
|
||||
* @internal
|
||||
*/
|
||||
export interface TrackObjectiveData {
|
||||
/** off the checkpoint markers; null when none read (the match's mode decides) */
|
||||
mode: "TC" | "RM" | null;
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
|
||||
export const STRIP_WEAPONS_EVENT_TYPE = "StripWeapons";
|
||||
|
||||
export interface StripWeaponCandidate {
|
||||
interface StripWeaponCandidate {
|
||||
weaponId: MainWeaponId;
|
||||
score: number;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import {
|
||||
|
||||
export const X_RANK_POSITION_EVENT_TYPE = "XRankPosition";
|
||||
|
||||
export type XRankPositionDirection = "UP" | "DOWN" | "SAME";
|
||||
type XRankPositionDirection = "UP" | "DOWN" | "SAME";
|
||||
|
||||
export interface XRankPositionData {
|
||||
mode: RankedModeShort | null;
|
||||
|
||||
@@ -48,7 +48,7 @@ import {
|
||||
|
||||
export const X_SET_RESULT_EVENT_TYPE = "XSetResult";
|
||||
|
||||
export type XSetGameResult = "WIN" | "LOSE";
|
||||
type XSetGameResult = "WIN" | "LOSE";
|
||||
|
||||
export interface XSetResultData {
|
||||
mode: RankedModeShort | null;
|
||||
|
||||
@@ -57,7 +57,7 @@ export type MontageManifestTopTeam = MontageManifestTeam & {
|
||||
placement: number;
|
||||
};
|
||||
|
||||
export interface MontageManifestTeam {
|
||||
interface MontageManifestTeam {
|
||||
id: number;
|
||||
name: string;
|
||||
logo: string | null;
|
||||
|
||||
@@ -76,6 +76,7 @@ export interface ScannerMatchObjective {
|
||||
samples: ScannerMatchObjectiveSample[];
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export type ScannerMatchPlayerFlags = [boolean, boolean, boolean, boolean];
|
||||
|
||||
export interface ScannerMatchPlayerStatusSample {
|
||||
|
||||
@@ -80,7 +80,7 @@ const UNIX_FILE_TYPE_MASK = 0o170000;
|
||||
const UNIX_REGULAR_FILE = 0o100000;
|
||||
|
||||
/** One analyzed frame of the game, as unpacked. */
|
||||
export interface GameDataFrame {
|
||||
interface GameDataFrame {
|
||||
/** folder relative to the output directory, e.g. `frames/012-Death-1m42s` */
|
||||
folder: string;
|
||||
eventType: (typeof EVENT_TYPES)[number];
|
||||
|
||||
@@ -23,9 +23,9 @@ const STORAGE_RESERVE_BYTES = 250_000_000;
|
||||
/** clips saved before their size was kept were all encoded at 16 Mbps */
|
||||
const LEGACY_BYTES_PER_SECOND = 2_000_000;
|
||||
|
||||
export type ClipBucket = "session" | "history" | "vod";
|
||||
type ClipBucket = "session" | "history" | "vod";
|
||||
|
||||
export type ClipSource =
|
||||
type ClipSource =
|
||||
| { kind: "live"; sessionKey: number }
|
||||
/** `visit`: the page load that cut it (see visit.ts) */
|
||||
| { kind: "vod"; name: string; visit: string };
|
||||
|
||||
@@ -10,7 +10,7 @@ import { test as vitestTest } from "vitest";
|
||||
|
||||
type SubtestBody = () => void | Promise<void>;
|
||||
|
||||
export interface SubtestOptions {
|
||||
interface SubtestOptions {
|
||||
skip?: boolean | string;
|
||||
expectFailure?: string;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ export interface DoneInfo {
|
||||
telemetry: ScanTelemetry | null;
|
||||
}
|
||||
export type DoneHandler = (t: number, info: DoneInfo) => void;
|
||||
export type ChunkProgress = Extract<WorkerResponse, { kind: "chunkProgress" }>;
|
||||
type ChunkProgress = Extract<WorkerResponse, { kind: "chunkProgress" }>;
|
||||
export type ChunkProgressHandler = (progress: ChunkProgress) => void;
|
||||
|
||||
/** Each chunk worker decodes and analyzes on its own; leave a core for the main thread and one for the media stack. */
|
||||
|
||||
@@ -56,7 +56,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups)
|
||||
`;
|
||||
|
||||
/** The part of a source picture to upscale: `box` of an RGBA buffer `stride` pixels wide. */
|
||||
export interface UpscaleSource {
|
||||
interface UpscaleSource {
|
||||
buffer: GPUBuffer;
|
||||
stride: number;
|
||||
box: { x: number; y: number; w: number; h: number };
|
||||
|
||||
@@ -326,7 +326,7 @@ function resolveJob(job: Job, score: number) {
|
||||
job.cache?.set(job.cacheKey, score);
|
||||
}
|
||||
|
||||
export interface GpuMatcherStats {
|
||||
interface GpuMatcherStats {
|
||||
steps: number;
|
||||
dispatches: number;
|
||||
jobs: number;
|
||||
|
||||
@@ -43,7 +43,7 @@ export interface ScanChunkRequest {
|
||||
tEnd: number;
|
||||
}
|
||||
|
||||
export interface AbortChunkRequest {
|
||||
interface AbortChunkRequest {
|
||||
kind: "abortChunk";
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ interface ScrimPostTeam {
|
||||
avatarUrl: string | null;
|
||||
}
|
||||
|
||||
export interface TimeRange {
|
||||
interface TimeRange {
|
||||
start: string;
|
||||
end: string;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import * as RejoinVote from "../core/RejoinVote";
|
||||
import { matchSchema } from "../q-match-schemas";
|
||||
import styles from "./RematchVotePanel.module.css";
|
||||
|
||||
export type RematchVoteMember = {
|
||||
type RematchVoteMember = {
|
||||
id: number;
|
||||
username: string;
|
||||
avatar: string | null;
|
||||
|
||||
@@ -72,7 +72,7 @@ export type SidebarEvent = {
|
||||
scrimStatus?: "booked" | "looking" | "requestPending";
|
||||
};
|
||||
|
||||
export type SidebarFriend = {
|
||||
type SidebarFriend = {
|
||||
id: number;
|
||||
name: string;
|
||||
avatar: CommonUser["avatar"];
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export const SPLATOON_ROTATION_TYPES = ["SERIES", "OPEN", "X"] as const;
|
||||
const SPLATOON_ROTATION_TYPES = ["SERIES", "OPEN", "X"] as const;
|
||||
|
||||
export type SplatoonRotationType = (typeof SPLATOON_ROTATION_TYPES)[number];
|
||||
|
||||
@@ -516,6 +516,7 @@ export function isStageLegal({
|
||||
return pool.some((m) => m.stageId === stageId && m.isLegal);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface PickBanEvent {
|
||||
type: string;
|
||||
stageId: StageId | null;
|
||||
@@ -769,6 +770,7 @@ const MAP_PICK_ACTIONS: ReadonlySet<ActionType> = new Set([
|
||||
"PICK_NO_MODE_REPEAT",
|
||||
]);
|
||||
|
||||
/** @internal */
|
||||
export const CUSTOM_FLOW_VALIDATION_ERRORS = {
|
||||
STEP_MISSING_ACTION: "STEP_MISSING_ACTION",
|
||||
STEP_MISSING_WHO: "STEP_MISSING_WHO",
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface DBSource {
|
||||
rest?: boolean;
|
||||
}
|
||||
|
||||
export interface EditableSource {
|
||||
interface EditableSource {
|
||||
/** Frontend-only id while editing, replaced by an index once set. See DBSource.bracketIdx. */
|
||||
bracketId: string;
|
||||
/** User editable, "1-3" and "1,2,3" mean the same. See DBSource.placements for the validated version. */
|
||||
|
||||
@@ -22,6 +22,7 @@ const SIZE_BONUS = {
|
||||
MAX_BONUS_PER_10_TEAMS: 1.5,
|
||||
} as const;
|
||||
|
||||
/** @internal */
|
||||
export const TIER_TO_NUMBER = {
|
||||
X: 1,
|
||||
"S+": 2,
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface Vod {
|
||||
submitterUserId: Tables["Video"]["submitterUserId"];
|
||||
}
|
||||
|
||||
export type VodMatch = Pick<
|
||||
type VodMatch = Pick<
|
||||
Tables["VideoMatch"],
|
||||
"id" | "mode" | "stageId" | "startsAt"
|
||||
> & {
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
import type { VoiceClientErrorKind, VoiceInputMode } from "./voice-constants";
|
||||
import { useVoiceRooms, useVoiceSnapshot } from "./voice-hooks";
|
||||
|
||||
export type VoiceActivityStatus = "AVAILABLE" | VoiceCallStatus;
|
||||
type VoiceActivityStatus = "AVAILABLE" | VoiceCallStatus;
|
||||
|
||||
export interface VoiceActivityParticipant {
|
||||
key: string;
|
||||
@@ -49,7 +49,7 @@ export interface VoiceActivityState {
|
||||
latencyMs: number | null;
|
||||
}
|
||||
|
||||
export interface VoiceActivityActions {
|
||||
interface VoiceActivityActions {
|
||||
join: () => void;
|
||||
leave: () => void;
|
||||
setMicEnabled: (enabled: boolean) => void;
|
||||
|
||||
@@ -81,14 +81,14 @@ export interface VoiceSnapshot {
|
||||
inputMode: VoiceInputMode;
|
||||
}
|
||||
|
||||
export interface VoiceCallHandle {
|
||||
interface VoiceCallHandle {
|
||||
setLocalAudio: (enabled: boolean) => void;
|
||||
ensureMic: (options: { mayAsk: boolean }) => Promise<boolean>;
|
||||
leave: () => Promise<void>;
|
||||
resumeAudio: () => void;
|
||||
}
|
||||
|
||||
export interface VoiceTelemetrySummary {
|
||||
interface VoiceTelemetrySummary {
|
||||
lowQualitySeconds: number;
|
||||
talkSeconds: number;
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ export interface FormRenderProps<T extends v.ObjectEntries> {
|
||||
FormField: TypedFormFieldComponent<T>;
|
||||
}
|
||||
|
||||
export type FormMode = "submit" | "autoSubmit" | "client";
|
||||
type FormMode = "submit" | "autoSubmit" | "client";
|
||||
|
||||
type BaseFormProps<T extends v.ObjectEntries> = {
|
||||
children: React.ReactNode | ((props: FormRenderProps<T>) => React.ReactNode);
|
||||
@@ -159,7 +159,7 @@ type FormModeProps<T extends v.ObjectEntries> =
|
||||
saveAttempted?: boolean;
|
||||
};
|
||||
|
||||
export type FormDefaultValues<T extends v.ObjectEntries> = Partial<
|
||||
type FormDefaultValues<T extends v.ObjectEntries> = Partial<
|
||||
v.InferInput<v.ObjectSchema<T, undefined>>
|
||||
>;
|
||||
|
||||
|
||||
@@ -300,7 +300,7 @@ type FormFieldChildrenProps = {
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export type TypedFormFieldProps<
|
||||
type TypedFormFieldProps<
|
||||
TSchema extends v.ObjectEntries,
|
||||
TName extends keyof TSchema & string,
|
||||
> = {
|
||||
@@ -324,7 +324,7 @@ export type TypedFormFieldProps<
|
||||
type NestedPath = `${string}.${string}` | `${string}[${string}`;
|
||||
|
||||
/** FormField props with a free-form name, for nested paths like `${itemName}.field` */
|
||||
export type FlexibleFormFieldProps = {
|
||||
type FlexibleFormFieldProps = {
|
||||
name: NestedPath;
|
||||
label?: string;
|
||||
disabled?: boolean;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export type Permissions = Record<string, number[]>;
|
||||
type Permissions = Record<string, number[]>;
|
||||
|
||||
export type EntityWithPermissions = {
|
||||
permissions: Permissions;
|
||||
|
||||
Reference in New Issue
Block a user