Port over more components as libs for PromptBox

This commit is contained in:
Tanish Manku committed 2025-05-07 16:15:08 -07:00
1 parent 6190416514
commit df7b45f62d
59 files changed
+1785 -927

No files matched your search

+1
View File
@@ -2,3 +2,4 @@ export * from "./lib/EditorState";
export * from "./lib/Queue";
export * from "./lib/UploaderStates";
export * from "./lib/Hotkeys";
export * from "./lib/Toaster";
@@ -0,0 +1,10 @@
export enum AssetType {
ANIMATION = "animation",
AUDIO = "audio",
CAMERA = "camera",
CHARACTER = "character",
EXPRESSION = "expression",
OBJECT = "object",
SKYBOX = "skybox",
SHAPE = "shape",
}
@@ -0,0 +1,7 @@
export enum ClipGroup {
CHARACTER = "character",
CAMERA = "camera",
GLOBAL_AUDIO = "global_audio",
OBJECT = "object",
PROMPT_TRAVEL = "prompt",
}
@@ -0,0 +1,8 @@
export enum ClipType {
TRANSFORM = "transform",
AUDIO = "audio",
ANIMATION = "animation",
EXPRESSION = "expression",
FAKE = "fake",
PROMPT_TRAVEL = "prompt",
}
@@ -0,0 +1,14 @@
export enum fromEngineActions {
ADD_OBJECT = "add_object",
CAMERA_ASPECT_RATIO_CHANGED = "camera_aspect_ratio_changed",
// data = CameraAspectRatio
DELETE_OBJECT = "delete_object",
DESELECT_OBJECT = "deselect_object",
RESET_TIMELINE = "reset_timeline",
SELECT_OBJECT = "select_object",
UPDATE_CHARACTER_ID = "update_character_id",
UPDATE_TIME = "update_time",
UPDATE_TIME_LINE = "update_timeline",
POP_A_TOAST = "pop_a_toast",
// data={currentTime: number}
}
@@ -0,0 +1,47 @@
export enum toEngineActions {
ADD_CLIP = "add_clip",
// data=QueueClip
ADD_KEYFRAME = "add_keyframe",
ADD_CHARACTER = "add_character",
ADD_OBJECT = "add_object",
ADD_SHAPE = "add_shape",
// data= QueueKeyframe
DELETE_CLIP = "delete_clip",
// data=QueueClip
DELETE_KEYFRAME = "delete_keyframe",
// data=QueueKeyframe
ENTER_EDIT_STATE = "enter_edit",
// data=null
ENTER_PREVIEW_STATE = "enter_preview",
// data=null
GENERATE_VIDEO = "generate_video",
// data=null
MUTE = "mute",
// data={version, type, group, object_uuid} if lipsync
// data={version, type, group} if global_audio
REFRESH_PREVIEW = "refresh_preview",
// data=QueueClip
TOGGLE_CAMERA_STATE = "toggle_camera",
// data=null
TOGGLE_REPEATING = "toggle_repeating",
// data=null
CHANGE_CAMERA_ASPECT_RATIO = "change_camera_aspect_ratio",
// data=CamperaAspectRatio
CAMERA_CHANGED = "camera_changed",
UNMUTE = "unmute",
// data={version, type, group, object_uuid} if lipsync
// data={version, type, group} if global_audio
UPDATE_CLIP = "update_clip",
// data=QueueClip
UPDATE_KEYFRAME = "update_keyframe",
// data=QueueKeyframe
UPDATE_TIME = "update_time",
// data={currentTime: number}
}
@@ -0,0 +1,4 @@
export enum toTimelineActions {
ADD_KEYFRAME = "add_keyframe",
GENERATE_PROGRESS = "generate_progress",
}
@@ -1 +1,7 @@
export * from "./AssetType";
export * from "./QueueNames";
export * from "./FromEngineActions";
export * from "./ToEngineActions";
export * from "./ToTimelineActions";
export * from "./ClipType";
export * from "./ClipGroup";
@@ -0,0 +1,5 @@
export enum ToastTypes {
SUCCESS,
WARNING,
ERROR,
}
@@ -0,0 +1 @@
export * from "./ToastTypes";
@@ -1,2 +1,8 @@
export * from "./lib/Camera";
export * from "./lib/UploadImage";
export * from "./lib/IGenerationOptions";
export * from "./lib/UpdateTime";
export * from "./lib/Queue";
export * from "./lib/MediaItem";
export * from "./lib/UploadImage";
export * from "./lib/UploadedState";
@@ -0,0 +1,9 @@
export interface IGenerationOptions {
upscale: boolean;
faceDetail: boolean;
styleStrength: number;
lipSync: boolean;
cinematic: boolean;
globalIpAdapterImageMediaToken: string | null;
enginePreProcessing: boolean;
}
@@ -0,0 +1,18 @@
import { AssetType } from "@storyteller/enums";
export interface MediaItem {
version: number;
type: AssetType;
maybe_animation_type?: string;
media_type?: string;
media_id: string;
object_uuid?: string;
name: string;
description?: string;
publicBucketPath?: string;
length?: number;
thumbnail?: string;
isMine?: boolean;
isBookmarked?: boolean;
imageIndex?: number;
}
@@ -0,0 +1,28 @@
import { ClipGroup, ClipType } from "@storyteller/enums";
import { XYZ } from "@storyteller/types";
export interface QueueClip {
version: number;
type: ClipType;
group: ClipGroup;
object_uuid?: string;
clip_uuid?: string;
media_id?: string;
name?: string;
offset?: number;
length?: number;
selected?: boolean;
}
export interface QueueKeyframe {
version: number;
keyframe_uuid?: string;
group: ClipGroup;
object_uuid: string;
object_name?: string;
offset?: number;
position: XYZ;
rotation: XYZ;
scale: XYZ;
selected?: boolean;
}
@@ -0,0 +1,3 @@
export interface UpdateTime {
currentTime: number;
}
+12
View File
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
+7
View File
@@ -0,0 +1,7 @@
# @storyteller/types
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test @storyteller/types` to execute the unit tests via [Vitest](https://vitest.dev/).
+17
View File
@@ -0,0 +1,17 @@
{
"name": "@storyteller/types",
"version": "0.0.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"development": "./src/index.ts",
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
}
}
+1
View File
@@ -0,0 +1 @@
export * from './lib';
@@ -0,0 +1,3 @@
export * from './queue';
export * from './toast';
export * from './xyz';
+114
View File
@@ -0,0 +1,114 @@
import { QueueNames, toTimelineActions, CameraAspectRatio, fromEngineActions, toEngineActions } from "@storyteller/enums";
import { IGenerationOptions, UpdateTime, QueueClip, QueueKeyframe, MediaItem } from "@storyteller/interfaces";
import { ToastDataType } from "@storyteller/types";
export type UnionedActionTypes =
| fromEngineActions
| toEngineActions
| toTimelineActions;
export type UnionedDataTypes =
| QueueClip
| UpdateTime
| QueueKeyframe
| MediaItem
| ToastDataType
| IGenerationOptions
| CameraAspectRatio
| null;
export type QueueSubscribeType = {
action: UnionedActionTypes;
data: UnionedDataTypes;
};
export type SubscribeHandler = (entry: {
action: UnionedActionTypes;
data: UnionedDataTypes;
}) => void;
class Queue {
private _queues: Record<
QueueNames,
Array<{
action: UnionedActionTypes;
data: UnionedDataTypes;
}>
> = {
[QueueNames.FROM_ENGINE]: [],
[QueueNames.TO_ENGINE]: [],
[QueueNames.TO_TIMELINE]: []
};
private _subscribers: Record<
QueueNames,
Map<
string,
SubscribeHandler
>
> = {
[QueueNames.FROM_ENGINE]: new Map<string, SubscribeHandler>(),
[QueueNames.TO_ENGINE]: new Map<string, SubscribeHandler>(),
[QueueNames.TO_TIMELINE]: new Map<string, SubscribeHandler>(),
};
// Enqueues actions to a specified queue
public publish({
queueName,
action,
data,
}: {
queueName: QueueNames;
action: UnionedActionTypes;
data: UnionedDataTypes;
}) {
// Queues for all QueueNames should be initialized above but this is a safeguard for future enum additions
// Make sure the queue exists
if (!this._queues[queueName]) {
this._queues[queueName] = [];
}
// Queue the task in the right queue
this._queues[queueName].push({ action, data });
// TODO: Ideally the publisher shouldn't deal at all with the subscribers
// It should only publish the events to the right queue
// It also doesn't make sense to fire an event on publish because the operations are then dispersed
// leading to potential race conditions
// FIXME: Add some sort of queue loop using internal event and add queue locks using promises to serialize queue publishes
if (this._subscribers[queueName]) {
this._subscribers[queueName].forEach((subcribeHandler) =>
subcribeHandler(this._queues[queueName][0]),
);
this._queues[queueName].shift();
}
}
public subscribe(
queueName: QueueNames,
id: string,
onMessage: (entry: QueueSubscribeType) => void,
) {
// Queues for all QueueNames should be initialized above but this is a safeguard for future enum additions
// Make sure the queue exists
if (!this._subscribers[queueName]) {
this._subscribers[queueName] = new Map<string, SubscribeHandler>();
}
// Set the handler mapped to the ID
this._subscribers[queueName].set(id, onMessage);
while (this._queues[queueName]?.length) {
this._subscribers[queueName].forEach((subscribeHandler) =>
subscribeHandler(this._queues[queueName][0]),
);
this._queues[queueName].shift();
}
}
}
const queue = new Queue();
export default queue;
@@ -0,0 +1,6 @@
import { ToastTypes } from "@storyteller/enums";
export type ToastDataType = {
type: ToastTypes;
message: string;
};
+11
View File
@@ -0,0 +1,11 @@
export type XYZ = {
x: number;
y: number;
z: number;
};
export type Simple3DVector = {
position: XYZ;
rotation: XYZ;
scale: XYZ;
};
+13
View File
@@ -0,0 +1,13 @@
{
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"extends": "../../../tsconfig.base.json"
}
@@ -0,0 +1,45 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"types": [
"node",
"@nx/react/typings/cssmodule.d.ts",
"@nx/react/typings/image.d.ts",
"vite/client"
],
"rootDir": "src",
"jsx": "react-jsx",
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
},
"exclude": [
"out-tsc",
"dist",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx"
],
"include": [
"src/**/*.js",
"src/**/*.jsx",
"src/**/*.ts",
"src/**/*.tsx"
]
}
@@ -0,0 +1,34 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/vitest",
"types": [
"vitest/globals",
"vitest/importMeta",
"vite/client",
"node",
"vitest"
],
"jsx": "react-jsx"
},
"include": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
+49
View File
@@ -0,0 +1,49 @@
/// <reference types='vitest' />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
import * as path from 'path';
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../../node_modules/.vite/libs/common/types',
plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
outDir: './dist',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: '@storyteller/types',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es' as const]
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react','react-dom','react/jsx-runtime']
},
},
test: {
watch: false,
globals: true,
environment: 'jsdom',
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],
coverage: {
reportsDirectory: './test-output/vitest/coverage',
provider: 'v8' as const,
}
},
}));
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
@@ -0,0 +1,7 @@
# @storyteller/ui-camera-settings-modal
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test @storyteller/ui-camera-settings-modal` to execute the unit tests via [Vitest](https://vitest.dev/).
@@ -0,0 +1,17 @@
{
"name": "@storyteller/ui-camera-settings-modal",
"version": "0.0.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"development": "./src/index.ts",
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
}
}
@@ -0,0 +1,2 @@
export * from './lib/camera-settings-modal';
@@ -0,0 +1,236 @@
import { TransitionDialogue } from "@storyteller/ui-transition-dialogue";
import { faPlus, faTrashAlt } from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { PopoverItem } from "@storyteller/ui-popover"
import { Button } from "@storyteller/ui-button";
import { Input } from "@storyteller/ui-input";
import { Label } from "@storyteller/ui-label";
import { Tooltip } from "@storyteller/ui-tooltip";
import { SliderV2 } from "@storyteller/ui-sliderv2";
import { useState, useEffect } from "react";
import { twMerge } from "tailwind-merge";
import { Signal } from "@preact/signals-react";
interface ExtendedPopoverItem extends PopoverItem {
id: string;
focalLength: number;
position: { x: number; y: number; z: number };
rotation: { x: number; y: number; z: number };
lookAt: { x: number; y: number; z: number };
}
interface CameraSettingsModalProps {
isOpen: boolean;
onClose: () => void;
cameras: ExtendedPopoverItem[];
onCameraNameChange: (id: string, newName: string) => void;
onCameraFocalLengthChange: (id: string, value: number) => void;
onAddCamera: () => void;
selectedCameraId: string;
handleCameraSelect: (selectedItem: PopoverItem) => void;
onDeleteCamera: (id: string) => void;
focalLengthDragging: Signal;
disableHotkeyInput: (level: number) => void;
enableHotkeyInput: (level: number) => void;
}
export const CameraSettingsModal = ({
isOpen,
onClose,
cameras,
onCameraNameChange,
onCameraFocalLengthChange,
onAddCamera,
selectedCameraId,
handleCameraSelect,
onDeleteCamera,
focalLengthDragging,
disableHotkeyInput,
enableHotkeyInput,
}: CameraSettingsModalProps) => {
const selectedCamera = cameras.find((cam) => cam.id === selectedCameraId);
const [isDragging, setIsDragging] = useState(false);
const [tempCameraName, setTempCameraName] = useState<string>("");
const [editingCameraId, setEditingCameraId] = useState<string | null>(null);
useEffect(() => {
if (selectedCamera) {
setTempCameraName(selectedCamera.label);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedCamera?.id]);
useEffect(() => {
const handlePointerUp = () => {
setIsDragging(false);
focalLengthDragging.value = {
isDragging: false,
focalLength: selectedCamera?.focalLength || 35,
};
};
document.addEventListener("pointerup", handlePointerUp);
return () => document.removeEventListener("pointerup", handlePointerUp);
}, [selectedCamera?.focalLength]);
const handlePointerDown = () => {
setIsDragging(true);
focalLengthDragging.value = {
isDragging: true,
focalLength: selectedCamera?.focalLength || 35,
};
};
const handleFocalLengthChange = (id: string, value: number) => {
focalLengthDragging.value = { isDragging: true, focalLength: value };
onCameraFocalLengthChange(id, value);
};
const handleNameBlur = () => {
if (selectedCamera && tempCameraName.trim() !== "") {
onCameraNameChange(selectedCamera.id, tempCameraName);
} else if (selectedCamera) {
setTempCameraName(selectedCamera.label);
}
setEditingCameraId(null);
};
const handleNameFocus = (id: string) => {
setEditingCameraId(id);
};
return (
<TransitionDialogue
isOpen={isOpen}
onClose={onClose}
className={twMerge(
"h-[500px] max-w-3xl duration-200",
isDragging ? "opacity-10" : "opacity-100",
)}
backdropClassName={twMerge(
"duration-200",
isDragging ? "opacity-0" : "opacity-100",
)}
childPadding={false}
disableHotkeyInput={disableHotkeyInput}
enableHotkeyInput={enableHotkeyInput}
>
<div className="grid h-full grid-cols-12 gap-3">
<div className="relative col-span-4 p-3 pt-2 after:absolute after:right-0 after:top-0 after:h-full after:w-px after:bg-gray-200 after:dark:bg-white/10">
<div className="flex items-center justify-between gap-2.5 py-0.5">
<h2 className="text-[18px] font-semibold opacity-80">Camera</h2>
<Tooltip content="Add camera" position="top" delay={200}>
<button
className="h-6 w-6 rounded-full text-white/70 transition-colors hover:text-white/100"
onClick={onAddCamera}
>
<FontAwesomeIcon icon={faPlus} className="text-xl" />
</button>
</Tooltip>
</div>
<hr className="my-2 w-full border-white/10" />
<div className="space-y-1">
{cameras.map((camera) => (
<button
key={camera.id}
className={`h-9 w-full rounded-lg p-2 text-left transition-colors duration-100 hover:bg-[#63636B]/40 ${camera.id === selectedCameraId ? "bg-[#63636B]/40" : ""
}`}
onClick={() => handleCameraSelect(camera)}
>
<div className="flex items-center gap-2.5 text-sm">
{camera.icon}
{editingCameraId === camera.id
? tempCameraName
: camera.label}
</div>
</button>
))}
</div>
</div>
<div className="col-span-8 p-3 ps-0 pt-2">
<div className="flex h-full flex-col">
<div>
<div className="flex items-center justify-between gap-2.5 py-0.5 opacity-100">
<h2 className="text-[18px] font-semibold">
{selectedCamera?.label || "Camera"}
</h2>
<Tooltip
content={
selectedCamera?.id === "main"
? "Cannot delete the main camera"
: "Delete camera"
}
position="top"
delay={200}
>
<button
className={`h-6 w-6 rounded-lg transition-colors ${selectedCamera?.id === "main"
? "cursor-not-allowed text-white/30"
: "text-white/60 hover:text-white/100"
}`}
onClick={() =>
selectedCamera &&
selectedCamera.id !== "main" &&
onDeleteCamera(selectedCamera.id)
}
disabled={selectedCamera?.id === "main"}
>
<FontAwesomeIcon icon={faTrashAlt} className="text-lg" />
</button>
</Tooltip>
</div>
<hr className="my-2 w-full border-white/10" />
<div className="space-y-4">
<div className="space-y-1">
<Label htmlFor="camera-name" className="text-sm opacity-70">
Name
</Label>
<Input
id="camera-name"
type="text"
value={tempCameraName}
onChange={(e) => setTempCameraName(e.target.value)}
onBlur={handleNameBlur}
onFocus={() =>
selectedCamera && handleNameFocus(selectedCamera.id)
}
className="text-sm"
/>
</div>
<div className="space-y-2">
<Label htmlFor="focal-length" className="text-sm opacity-70">
Focal Length
</Label>
<div
className="mt-1 flex items-center gap-4"
onPointerDown={handlePointerDown}
>
<SliderV2
min={10}
max={200}
value={selectedCamera?.focalLength || 35}
onChange={(value) =>
selectedCamera &&
handleFocalLengthChange(selectedCamera.id, value)
}
step={1}
suffix="mm"
showDecrement={true}
showIncrement={true}
className="w-full"
/>
<span className="min-w-[60px] text-sm">
{selectedCamera?.focalLength || 35}mm
</span>
</div>
</div>
</div>
</div>
<div className="mt-auto flex justify-end pt-4">
<Button onClick={onClose}>Done</Button>
</div>
</div>
</div>
</div>
</TransitionDialogue>
);
};
@@ -0,0 +1,13 @@
{
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"extends": "../../../tsconfig.base.json"
}
@@ -0,0 +1,45 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"types": [
"node",
"@nx/react/typings/cssmodule.d.ts",
"@nx/react/typings/image.d.ts",
"vite/client"
],
"rootDir": "src",
"jsx": "react-jsx",
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
},
"exclude": [
"out-tsc",
"dist",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx"
],
"include": [
"src/**/*.js",
"src/**/*.jsx",
"src/**/*.ts",
"src/**/*.tsx"
]
}
@@ -0,0 +1,34 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/vitest",
"types": [
"vitest/globals",
"vitest/importMeta",
"vite/client",
"node",
"vitest"
],
"jsx": "react-jsx"
},
"include": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
@@ -0,0 +1,49 @@
/// <reference types='vitest' />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
import * as path from 'path';
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../../node_modules/.vite/libs/components/camera-settings-modal',
plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
outDir: './dist',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: '@storyteller/ui-camera-settings-modal',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es' as const]
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react','react-dom','react/jsx-runtime']
},
},
test: {
watch: false,
globals: true,
environment: 'jsdom',
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],
coverage: {
reportsDirectory: './test-output/vitest/coverage',
provider: 'v8' as const,
}
},
}));
@@ -1 +1 @@
export * from "./lib/PromptBox";
export * from "./lib/PromptBox3D";
@@ -1,11 +0,0 @@
interface PromptBoxProps {
is3D: boolean;
}
export const PromptBox = ({
is3D
}: PromptBoxProps) => {
return (
{is3D ?? PromptBox3D : PromptBox2D}
);
};
@@ -52,7 +52,7 @@ import {
UploadImageArgs,
} from "@storyteller/interfaces";
import { EngineApi } from "@storyteller/api";
import { CameraSettingsModal } from "../CameraSettingsModal";
import { CameraSettingsModal } from "@storyteller/ui-camera-settings-modal";
import { twMerge } from "tailwind-merge";
import { GalleryModal, GalleryItem } from "@storyteller/ui-gallery-modal";
import { Modal } from "@storyteller/ui-modal";
@@ -66,22 +66,20 @@ interface PromptBox3DProps {
gridVisibility: Signal<boolean>;
setGridVisibility: (isVisible: boolean) => void;
selectedCameraId: Signal<string>;
addCamera: (cam: Camera) => void;
updateCamera: (id: string, updates: Partial<Camera>) => void;
deleteCamera: (id: string) => void;
focalLengthDragging: Signal<FocalLengthDragging>;
isPromptBoxFocused: Signal<boolean>;
uploadImage: (arg: UploadImageArgs) => Promise<void>;
handleCameraSelect: (item: PopoverItem) => void;
handleAddCamera: () => void;
handleCameraNameChange: (name: string) => void;
handleCameraNameChange: (id: string, newName: string) => void;
handleCameraFocalLengthChange: (id: string, value: number) => void;
handleAspectRatioSelect: (selectedItem: PopoverItem) => void;
onAspectRatioSelect: (newRatio: CameraAspectRatio) => void;
setEnginePrompt: (prompt: string) => void;
snapshotCurrentFrame: (shouldDownload?: boolean) => {
snapshotCurrentFrame: ((shouldDownload?: boolean) => {
base64Snapshot: string;
file: File;
} | null;
} | null) | undefined;
}
export const PromptBox3D = ({
@@ -92,8 +90,6 @@ export const PromptBox3D = ({
gridVisibility,
setGridVisibility,
selectedCameraId,
addCamera,
updateCamera,
deleteCamera,
focalLengthDragging,
isPromptBoxFocused,
@@ -102,7 +98,7 @@ export const PromptBox3D = ({
handleAddCamera,
handleCameraNameChange,
handleCameraFocalLengthChange,
handleAspectRatioSelect,
onAspectRatioSelect,
setEnginePrompt,
snapshotCurrentFrame,
}: PromptBox3DProps) => {
@@ -169,6 +165,37 @@ export const PromptBox3D = ({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [cameraAspectRatio.value]);
const handleAspectRatioSelect = (selectedItem: PopoverItem) => {
setAspectRatioList((prev) =>
prev.map((item) => ({
...item,
selected: item.label === selectedItem.label,
})),
);
// Map the selected label to the corresponding CameraAspectRatio enum value
let newRatio: CameraAspectRatio;
switch (selectedItem.label) {
case "16:9":
newRatio = CameraAspectRatio.HORIZONTAL_16_9;
break;
case "3:2":
newRatio = CameraAspectRatio.HORIZONTAL_3_2;
break;
case "2:3":
newRatio = CameraAspectRatio.VERTICAL_2_3;
break;
case "1:1":
newRatio = CameraAspectRatio.SQUARE_1_1;
break;
default:
newRatio = CameraAspectRatio.HORIZONTAL_16_9;
}
onAspectRatioSelect(newRatio);
};
const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
const files = event.target.files;
if (files) {
@@ -314,44 +341,46 @@ export const PromptBox3D = ({
//const engineApi = new EngineApi();
const promptsApi = new PromptsApi();
const snapshot = snapshotCurrentFrame(false);
if (snapshotCurrentFrame) {
const snapshot = snapshotCurrentFrame(false);
if (snapshot) {
const snapshotResult = await promptsApi.uploadSceneSnapshot({
screenshot: snapshot.file,
sceneMediaToken: "",
});
if (snapshot) {
const snapshotResult = await promptsApi.uploadSceneSnapshot({
screenshot: snapshot.file,
sceneMediaToken: "",
});
console.log("useSystemPrompt", useSystemPrompt);
console.log("useSystemPrompt", useSystemPrompt);
const response = await promptsApi.enqueueImageGeneration({
disableSystemPrompt: !useSystemPrompt,
prompt: prompt,
snapshotMediaToken: snapshotResult.data || "",
additionalImages: referenceImages.map((image) => image.mediaToken),
});
const response = await promptsApi.enqueueImageGeneration({
disableSystemPrompt: !useSystemPrompt,
prompt: prompt,
snapshotMediaToken: snapshotResult.data || "",
additionalImages: referenceImages.map((image) => image.mediaToken),
});
console.log("response", response);
console.log("response", response);
if (response.errorMessage) {
handleError(response.errorMessage);
setisEnqueueing(false);
return;
if (response.errorMessage) {
handleError(response.errorMessage);
setisEnqueueing(false);
return;
}
}
}
try {
// Here we would pass both the prompt and reference images to the generation
console.log(
"Enqueuing with prompt:",
prompt,
"and reference images:",
referenceImages
);
await new Promise((resolve) => setTimeout(resolve, 2000));
} finally {
setisEnqueueing(false);
toast.success("Image added to queue");
try {
// Here we would pass both the prompt and reference images to the generation
console.log(
"Enqueuing with prompt:",
prompt,
"and reference images:",
referenceImages
);
await new Promise((resolve) => setTimeout(resolve, 2000));
} finally {
setisEnqueueing(false);
toast.success("Image added to queue");
}
}
setisEnqueueing(false);
};
@@ -365,47 +394,49 @@ export const PromptBox3D = ({
const promptsApi = new PromptsApi();
const snapshot = snapshotCurrentFrame(false);
if (snapshotCurrentFrame) {
const snapshot = snapshotCurrentFrame(false);
if (snapshot) {
const snapshotResult = await promptsApi.uploadSceneSnapshot({
screenshot: snapshot.file,
//sceneMediaToken: "",
});
if (snapshot) {
const snapshotResult = await promptsApi.uploadSceneSnapshot({
screenshot: snapshot.file,
//sceneMediaToken: "",
});
const generateResponse = await invoke("sora_image_remix_command", {
request: {
snapshot_media_token: snapshotResult.data!,
disable_system_prompt: !useSystemPrompt,
prompt: prompt,
maybe_additional_images: referenceImages.map(
(image) => image.mediaToken
),
maybe_number_of_samples: 1,
},
});
const generateResponse = await invoke("sora_image_remix_command", {
request: {
snapshot_media_token: snapshotResult.data!,
disable_system_prompt: !useSystemPrompt,
prompt: prompt,
maybe_additional_images: referenceImages.map(
(image) => image.mediaToken
),
maybe_number_of_samples: 1,
},
});
console.log("response", generateResponse);
console.log("response", generateResponse);
//if (generateResponse.errorMessage) {
// handleError(response.errorMessage);
// setisEnqueueing(false);
// return;
//}
}
//if (generateResponse.errorMessage) {
// handleError(response.errorMessage);
// setisEnqueueing(false);
// return;
//}
}
try {
// Here we would pass both the prompt and reference images to the generation
console.log(
"Enqueuing with prompt:",
prompt,
"and reference images:",
referenceImages
);
await new Promise((resolve) => setTimeout(resolve, 2000));
} finally {
setisEnqueueing(false);
toast.success("Image added to queue");
try {
// Here we would pass both the prompt and reference images to the generation
console.log(
"Enqueuing with prompt:",
prompt,
"and reference images:",
referenceImages
);
await new Promise((resolve) => setTimeout(resolve, 2000));
} finally {
setisEnqueueing(false);
toast.success("Image added to queue");
}
}
setisEnqueueing(false);
@@ -435,6 +466,10 @@ export const PromptBox3D = ({
};
const handleSaveFrame = async () => {
if (!snapshotCurrentFrame) {
return;
}
const snapshot = snapshotCurrentFrame(false);
if (snapshot) {
const engineApi = new EngineApi();
@@ -446,6 +481,9 @@ export const PromptBox3D = ({
};
const handleDownloadFrame = () => {
if (!snapshotCurrentFrame) {
return;
}
snapshotCurrentFrame(true);
};
@@ -704,6 +742,7 @@ export const PromptBox3D = ({
selected: cam.id === selectedCameraId.value,
icon: <FontAwesomeIcon icon={faCamera} className="h-4 w-4" />,
focalLength: cam.focalLength,
focalLengthDragging: focalLengthDragging,
position: cam.position,
rotation: cam.rotation,
lookAt: cam.lookAt,
@@ -714,6 +753,9 @@ export const PromptBox3D = ({
selectedCameraId={selectedCameraId.value}
handleCameraSelect={handleCameraSelect}
onDeleteCamera={deleteCamera}
disableHotkeyInput={disableHotkeyInput}
enableHotkeyInput={enableHotkeyInput}
focalLengthDragging={focalLengthDragging}
/>
</div>
<GalleryModal
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
@@ -0,0 +1,7 @@
# @storyteller/ui-sliderv2
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test @storyteller/ui-sliderv2` to execute the unit tests via [Vitest](https://vitest.dev/).
@@ -0,0 +1,17 @@
{
"name": "@storyteller/ui-sliderv2",
"version": "0.0.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"development": "./src/index.ts",
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
}
}
@@ -0,0 +1,2 @@
export * from './lib/slider-v2';
@@ -0,0 +1,184 @@
import { Transition } from "@headlessui/react";
import React, { useState, useRef, useEffect, ReactNode } from "react";
import { twMerge } from "tailwind-merge";
import { Button } from "@storyteller/ui-button";
import { faMinus, faPlus } from "@fortawesome/pro-solid-svg-icons";
interface SliderProps {
min: number;
max: number;
value: number;
onChange: (value: number) => void;
step: number;
className?: string;
showTooltip?: boolean;
tooltipContent?: ReactNode;
suffix?: string;
innerLabel?: string;
showDecrement?: boolean;
showIncrement?: boolean;
}
export const SliderV2 = ({
min,
max,
value,
onChange,
step,
className,
showTooltip,
tooltipContent,
suffix,
innerLabel,
showDecrement,
showIncrement,
}: SliderProps) => {
const [localValue, setLocalValue] = useState(value);
const sliderRef = useRef<HTMLDivElement>(null);
const [isDragging, setIsDragging] = useState(false);
const [showHandleTooltip, setShowHandleTooltip] = useState(false);
useEffect(() => {
setLocalValue(value);
}, [value]);
const setClampedValue = (value: number) => {
const roundedValue = Math.round(value / step) * step;
const clampedValue = Math.min(Math.max(roundedValue, min), max);
setLocalValue(clampedValue);
onChange(clampedValue);
};
const updatePosition = (x: number) => {
if (!sliderRef.current) return;
const rect = sliderRef.current.getBoundingClientRect();
const fraction = (x - rect.left) / rect.width;
const newValue = fraction * (max - min) + min;
setClampedValue(newValue);
};
const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
e.preventDefault();
setIsDragging(true);
setShowHandleTooltip(true);
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
updatePosition(e.clientX);
};
const handleMouseMove = (e: MouseEvent) => {
e.preventDefault();
updatePosition(e.clientX);
};
const handleMouseUp = (e: MouseEvent) => {
e.preventDefault();
setIsDragging(false);
setShowHandleTooltip(false);
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
};
const handleMouseEnter = () => {
if (!isDragging) {
setShowHandleTooltip(true);
}
};
const handleMouseLeave = () => {
if (!isDragging) {
setShowHandleTooltip(false);
}
};
const handleDecrement = () => {
setClampedValue(localValue - step);
};
const handleIncrement = () => {
setClampedValue(localValue + step);
};
const percentage = ((localValue - min) / (max - min)) * 100;
const displayValue =
localValue.toFixed(step.toString().split(".")[1]?.length || 0) +
(suffix || "");
return (
<div className="flex w-full">
{showDecrement && (
<Button
icon={faMinus}
className="focus-visible:outline-primary my-auto mr-1 size-6 rounded-full bg-transparent text-white/80 hover:bg-white/10 active:bg-brand-primary/30"
onClick={handleDecrement}
/>
)}
<div
ref={sliderRef}
className={twMerge(
"glass border-ui-border group relative h-7 w-full cursor-pointer overflow-hidden rounded-lg border",
isDragging && "!bg-ui-controls/90",
className,
)}
onMouseDown={handleMouseDown}
>
<div
className={twMerge(
"absolute h-full bg-brand-primary/30 transition-colors duration-300 group-hover:bg-brand-primary/50",
isDragging && "!bg-brand-primary/50",
)}
style={{ width: `${percentage}%` }}
>
{innerLabel && (
<span
className={twMerge(
"absolute top-1/2 ml-2.5 -translate-y-1/2 text-nowrap text-sm font-medium text-white/60 transition-colors duration-300 group-hover:text-white",
isDragging && "!text-white",
)}
>
{innerLabel}
</span>
)}
<div
className={twMerge(
"absolute right-0 top-1/2 mr-1 h-4 w-0.5 -translate-y-1/2 rounded-full",
isDragging ? "bg-white" : "bg-white/50",
)}
onMouseDown={handleMouseDown}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
/>
</div>
</div>
{showIncrement && (
<Button
icon={faPlus}
className="focus-visible:outline-primary my-auto ml-1 size-6 rounded-full bg-transparent text-white/80 hover:bg-white/10 active:bg-brand-primary/30"
onClick={handleIncrement}
/>
)}
{showTooltip && (
<Transition
as={"div"}
show={showHandleTooltip}
enter="transition ease-out duration-200"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0"
>
<div
className="absolute -top-8 z-10 rounded-md bg-ui-panel px-2 py-1 text-xs text-black shadow-lg"
style={{ left: `${percentage}%`, transform: "translateX(-50%)" }}
>
{tooltipContent ? tooltipContent : displayValue}
</div>
</Transition>
)}
</div>
);
};
@@ -0,0 +1,13 @@
{
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"extends": "../../../tsconfig.base.json"
}
@@ -0,0 +1,45 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"types": [
"node",
"@nx/react/typings/cssmodule.d.ts",
"@nx/react/typings/image.d.ts",
"vite/client"
],
"rootDir": "src",
"jsx": "react-jsx",
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
},
"exclude": [
"out-tsc",
"dist",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx"
],
"include": [
"src/**/*.js",
"src/**/*.jsx",
"src/**/*.ts",
"src/**/*.tsx"
]
}
@@ -0,0 +1,34 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/vitest",
"types": [
"vitest/globals",
"vitest/importMeta",
"vite/client",
"node",
"vitest"
],
"jsx": "react-jsx"
},
"include": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
@@ -0,0 +1,49 @@
/// <reference types='vitest' />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
import * as path from 'path';
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../../node_modules/.vite/libs/components/slider-v2',
plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
outDir: './dist',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: '@storyteller/ui-sliderv2',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es' as const]
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react','react-dom','react/jsx-runtime']
},
},
test: {
watch: false,
globals: true,
environment: 'jsdom',
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],
coverage: {
reportsDirectory: './test-output/vitest/coverage',
provider: 'v8' as const,
}
},
}));
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
@@ -0,0 +1,7 @@
# @storyteller/ui-transition-dialogue
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test @storyteller/ui-transition-dialogue` to execute the unit tests via [Vitest](https://vitest.dev/).
@@ -0,0 +1,17 @@
{
"name": "@storyteller/ui-transition-dialogue",
"version": "0.0.1",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"development": "./src/index.ts",
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
}
}
@@ -0,0 +1,2 @@
export * from './lib/transition-dialogue';
@@ -0,0 +1,165 @@
import { useEffect, Fragment, ReactNode } from "react";
import { Dialog, Transition } from "@headlessui/react";
import { twMerge } from "tailwind-merge";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
IconDefinition,
faDownLeftAndUpRightToCenter,
} from "@fortawesome/pro-solid-svg-icons";
import { Tooltip } from "@storyteller/ui-tooltip";
import { DomLevels } from "@storyteller/enums";
const DialogBackdrop = ({
className,
disableHotkeyInput,
enableHotkeyInput,
}: {
className?: string;
disableHotkeyInput: (level: number) => void;
enableHotkeyInput: (level: number) => void;
}) => {
useEffect(() => {
disableHotkeyInput(DomLevels.DIALOGUE);
return () => {
enableHotkeyInput(DomLevels.DIALOGUE);
};
}, []);
return (
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div
className={twMerge("fixed inset-0 bg-black/60", className)}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
/>
</Transition.Child>
);
};
export const TransitionDialogue = ({
isOpen,
title,
titleIcon,
onTitleIconClick,
onClose,
className,
backdropClassName,
width,
children,
childPadding = true,
titleIconClassName,
showClose = true,
disableHotkeyInput = () => { },
enableHotkeyInput = () => { },
}: {
isOpen: boolean;
title?: ReactNode;
titleIcon?: IconDefinition;
onTitleIconClick?: () => void;
titleIconClassName?: string;
onClose: () => void;
className?: string;
backdropClassName?: string;
width?: number;
children: ReactNode;
childPadding?: boolean;
showClose?: boolean;
disableHotkeyInput: (level: number) => void;
enableHotkeyInput: (level: number) => void;
}) => {
return (
<Transition appear show={isOpen} as={Fragment}>
<Dialog as="div" className="relative z-[70]" onClose={onClose}>
<DialogBackdrop className={backdropClassName} disableHotkeyInput={disableHotkeyInput} enableHotkeyInput={enableHotkeyInput} />
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-200"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel
className={twMerge(
"w-full max-w-lg transform rounded-xl",
"border border-ui-panel-border bg-[#2C2C2C]",
"text-left align-middle shadow-xl transition-all",
className,
)}
style={{ minWidth: width }}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
{title && (
<Dialog.Title
as="div"
className="mb-5 flex justify-between p-5 pb-0 text-xl font-bold text-white"
>
<>
{onTitleIconClick ? (
<button
className="flex items-center gap-3"
onClick={onTitleIconClick}
>
{titleIcon && (
<FontAwesomeIcon
icon={titleIcon}
className={titleIconClassName}
/>
)}
{title}
</button>
) : (
<div className="flex items-center gap-3">
{titleIcon && (
<FontAwesomeIcon
icon={titleIcon}
className={titleIconClassName}
/>
)}
{title}
</div>
)}
</>
{showClose && (
<Tooltip position="top" content="Close">
<button
onClick={onClose}
className="opacity-50 transition-opacity duration-150 hover:opacity-80 focus:outline-none"
>
<FontAwesomeIcon
icon={faDownLeftAndUpRightToCenter}
/>
</button>
</Tooltip>
)}
</Dialog.Title>
)}
<div
className={`h-full ${childPadding ? "p-5 pt-0" : ""}`.trim()}
>
{children}
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition>
);
};
@@ -0,0 +1,13 @@
{
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"extends": "../../../tsconfig.base.json"
}
@@ -0,0 +1,45 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"types": [
"node",
"@nx/react/typings/cssmodule.d.ts",
"@nx/react/typings/image.d.ts",
"vite/client"
],
"rootDir": "src",
"jsx": "react-jsx",
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
},
"exclude": [
"out-tsc",
"dist",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx"
],
"include": [
"src/**/*.js",
"src/**/*.jsx",
"src/**/*.ts",
"src/**/*.tsx"
]
}
@@ -0,0 +1,34 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/vitest",
"types": [
"vitest/globals",
"vitest/importMeta",
"vite/client",
"node",
"vitest"
],
"jsx": "react-jsx"
},
"include": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
@@ -0,0 +1,49 @@
/// <reference types='vitest' />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import dts from 'vite-plugin-dts';
import * as path from 'path';
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../../node_modules/.vite/libs/components/transition-dialogue',
plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
outDir: './dist',
emptyOutDir: true,
reportCompressedSize: true,
commonjsOptions: {
transformMixedEsModules: true,
},
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: '@storyteller/ui-transition-dialogue',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es' as const]
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react','react-dom','react/jsx-runtime']
},
},
test: {
watch: false,
globals: true,
environment: 'jsdom',
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],
coverage: {
reportsDirectory: './test-output/vitest/coverage',
provider: 'v8' as const,
}
},
}));
+52 -838
View File
File diff suppressed because it is too large. Load diff
+12
View File
@@ -74,6 +74,18 @@
},
{
"path": "./libs/common/interfaces"
},
{
"path": "./libs/components/camera-settings-modal"
},
{
"path": "./libs/components/transition-dialogue"
},
{
"path": "./libs/components/slider-v2"
},
{
"path": "./libs/common/types"
}
]
}