From 91b0ec5cfaa96fac7284b268ecdaea6b7da9f1af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joa=CC=83o=20Leite?= Date: Mon, 13 Mar 2023 16:01:27 +0000 Subject: [PATCH] added "File" Prop Type to core project --- theatre/core/src/projects/TheatreProject.ts | 4 +- theatre/core/src/propTypes/index.ts | 72 ++++++++++++++++++++- theatre/shared/src/utils/assets.ts | 1 + 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/theatre/core/src/projects/TheatreProject.ts b/theatre/core/src/projects/TheatreProject.ts index 537e5a9..bf86d60 100644 --- a/theatre/core/src/projects/TheatreProject.ts +++ b/theatre/core/src/projects/TheatreProject.ts @@ -3,7 +3,7 @@ import Project from '@theatre/core/projects/Project' import type {ISheet} from '@theatre/core/sheets/TheatreSheet' import type {ProjectAddress} from '@theatre/shared/utils/addresses' -import type {Asset} from '@theatre/shared/utils/assets' +import type {Asset, File} from '@theatre/shared/utils/assets' import type { ProjectId, SheetId, @@ -80,7 +80,7 @@ export interface IProject { * @param asset - The asset to get the URL for * @returns The URL for the asset, or `undefined` if the asset is not found */ - getAssetUrl(asset: Asset): string | undefined + getAssetUrl(asset: Asset | File): string | undefined } export default class TheatreProject implements IProject { diff --git a/theatre/core/src/propTypes/index.ts b/theatre/core/src/propTypes/index.ts index 2af27c8..9be1c93 100644 --- a/theatre/core/src/propTypes/index.ts +++ b/theatre/core/src/propTypes/index.ts @@ -17,7 +17,7 @@ import type { import {propTypeSymbol, sanitizeCompoundProps} from './internals' // eslint-disable-next-line unused-imports/no-unused-imports import type SheetObject from '@theatre/core/sheetObjects/SheetObject' -import type {Asset} from '@theatre/shared/utils/assets' +import type {Asset, File} from '@theatre/shared/utils/assets' // Notes on naming: // As of now, prop types are either `simple` or `composite`. @@ -138,6 +138,74 @@ export const compound = ( return config } +/** + * A file prop type + * + * @example + * Usage: + * ```ts + * + * // with a label: + * const obj = sheet.object('key', { + * url: t.file('My file.glb', { + * label: 'Model' + * }) + * }) + * ``` + * + * @param opts - Options (See usage examples) + */ +export const file = ( + // The defaultValue parameter is a string for convenience, but it will be converted to an Asset object + defaultValue: File['id'], + opts: { + label?: string + interpolate?: Interpolator + } = {}, +): PropTypeConfig_File => { + if (process.env.NODE_ENV !== 'production') { + validateCommonOpts('t.file(defaultValue, opts)', opts) + } + + const interpolate: Interpolator = (left, right, progression) => { + const stringInterpolate = opts.interpolate ?? leftInterpolate + + return { + type: 'file', + id: stringInterpolate(left.id, right.id, progression), + } + } + + return { + type: 'file', + default: {type: 'file', id: defaultValue}, + valueType: null as $IntentionalAny, + [propTypeSymbol]: 'TheatrePropType', + label: opts.label, + interpolate, + deserializeAndSanitize: _ensureFile, + } +} + +const _ensureFile = (val: unknown): File | undefined => { + if (!val) return undefined + + let valid = true + + if ( + typeof (val as $IntentionalAny).id !== 'string' && + ![null, undefined].includes((val as $IntentionalAny).id) + ) { + valid = false + } + + if ((val as $IntentionalAny).type !== 'file') valid = false + + if (!valid) return undefined + + return val as File +} + /** * An image prop type * @@ -778,6 +846,7 @@ export interface PropTypeConfig_StringLiteral export interface PropTypeConfig_Rgba extends ISimplePropType<'rgba', Rgba> {} export interface PropTypeConfig_Image extends ISimplePropType<'image', Asset> {} +export interface PropTypeConfig_File extends ISimplePropType<'file', File> {} type DeepPartialCompound = { [K in keyof Props]?: DeepPartial @@ -812,6 +881,7 @@ export type PropTypeConfig_AllSimples = | PropTypeConfig_StringLiteral<$IntentionalAny> | PropTypeConfig_Rgba | PropTypeConfig_Image + | PropTypeConfig_File export type PropTypeConfig = | PropTypeConfig_AllSimples diff --git a/theatre/shared/src/utils/assets.ts b/theatre/shared/src/utils/assets.ts index 1aa717b..445dd45 100644 --- a/theatre/shared/src/utils/assets.ts +++ b/theatre/shared/src/utils/assets.ts @@ -48,3 +48,4 @@ export function getAllPossibleAssetIDs(project: Project, type?: string) { } export type Asset = {type: 'image'; id: string | undefined} +export type File = {type: 'file'; id: string | undefined}