mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-22 09:39:31 -04:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56c80eb1a1 | ||
|
|
97bef45a4f | ||
|
|
7ed3d6ae08 | ||
|
|
aecb977481 | ||
|
|
7106e34bf1 |
@@ -1,4 +1,4 @@
|
||||
import React, { useContext, useEffect, useRef } from "react";
|
||||
import React, { useContext, useEffect } from "react";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { TopBar } from "~/components";
|
||||
import { Controls3D } from "./comps/Controls3D";
|
||||
@@ -31,7 +31,12 @@ import { PopoverItem } from "@storyteller/ui-popover";
|
||||
import { LoadingDots } from "@storyteller/ui-loading";
|
||||
import { OnboardingHelper } from "./comps/OnboardingHelper";
|
||||
import { FocalLengthDisplay } from "./comps/FocalLengthDisplay/FocalLengthDisplay";
|
||||
import { appTabId, is3DEditorInitialized, is3DPageMounted, set3DPageMounted, setAppTabId } from "~/signals/appTab";
|
||||
import {
|
||||
appTabId,
|
||||
is3DEditorInitialized,
|
||||
set3DPageMounted,
|
||||
setAppTabId,
|
||||
} from "~/signals/appTab";
|
||||
import { KonvaCanvasContainer } from "../Page2d/KonvaCanvasContainer";
|
||||
import { KonvaRootComponent } from "../Page2d/KonvaRootComponent";
|
||||
import {
|
||||
@@ -68,6 +73,14 @@ import {
|
||||
onImageDrop,
|
||||
removeImageDropListener,
|
||||
} from "@storyteller/ui-gallery-modal";
|
||||
import {
|
||||
imageGenerationModels,
|
||||
ModelCategory,
|
||||
// ModelCategory,
|
||||
ModelSelector,
|
||||
// videoGenerationModels,
|
||||
// useModelSelectorStore,
|
||||
} from "@storyteller/ui-model-selector";
|
||||
|
||||
export const PageEditor = () => {
|
||||
useSignals();
|
||||
@@ -76,6 +89,12 @@ export const PageEditor = () => {
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
// TODO: For 3d Promptbox to accept this later on
|
||||
// const { selectedModels } = useModelSelectorStore();
|
||||
// const selectedModel =
|
||||
// selectedModels[ModelCategory.Editor3D] ||
|
||||
// videoGenerationModels[0]?.label;
|
||||
|
||||
useEffect(() => {
|
||||
timelineHeight.value = 0; //timelineHeight.value = 208;
|
||||
sidePanelWidth.value = 340;
|
||||
@@ -343,7 +362,7 @@ export const PageEditor = () => {
|
||||
}
|
||||
|
||||
set3DPageMounted(true);
|
||||
}, [currentAppTabId, editorEngine, is3DInit])
|
||||
}, [currentAppTabId, editorEngine, is3DInit]);
|
||||
|
||||
return (
|
||||
<div className="w-screen">
|
||||
@@ -356,6 +375,7 @@ export const PageEditor = () => {
|
||||
{display3d && (
|
||||
<>
|
||||
<OnboardingHelper />
|
||||
|
||||
<div
|
||||
className="relative flex w-screen"
|
||||
style={{ height: "calc(100vh - 68px)" }}
|
||||
@@ -446,6 +466,18 @@ export const PageEditor = () => {
|
||||
type="bricks"
|
||||
message={editorLoader.value.message}
|
||||
/>
|
||||
|
||||
<div className="absolute bottom-6 left-6 z-20 flex items-center gap-2">
|
||||
<ModelSelector
|
||||
items={imageGenerationModels}
|
||||
category={ModelCategory.Editor3D}
|
||||
panelTitle="Select Model"
|
||||
panelClassName="min-w-[280px]"
|
||||
buttonClassName="bg-transparent p-0 text-lg hover:bg-transparent text-white/80 hover:text-white"
|
||||
showIconsInList
|
||||
triggerLabel="Model"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -477,7 +509,7 @@ export const PageEditor = () => {
|
||||
)}
|
||||
|
||||
<LoginModal
|
||||
onClose={() => { }}
|
||||
onClose={() => {}}
|
||||
videoSrc2D="/resources/videos/artcraft-canvas-demo.mp4"
|
||||
videoSrc3D="/resources/videos/artcraft-3d-demo.mp4"
|
||||
openAiLogo="/resources/images/openai-logo.png"
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { JobContextType } from "libs/common/src/lib/types";
|
||||
import { useRef } from "react";
|
||||
import { JobContextType } from "@storyteller/common";
|
||||
import { PromptBoxImage } from "@storyteller/ui-promptbox";
|
||||
import BackgroundGallery from "./BackgroundGallery";
|
||||
import { PopoverMenu, type PopoverItem } from "@storyteller/ui-popover";
|
||||
import { faClock, faImage } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import {
|
||||
imageGenerationModels,
|
||||
ModelCategory,
|
||||
ModelSelector,
|
||||
useModelSelectorStore,
|
||||
} from "@storyteller/ui-model-selector";
|
||||
|
||||
interface TextToImageProps {
|
||||
imageMediaId?: string;
|
||||
@@ -13,14 +16,10 @@ interface TextToImageProps {
|
||||
|
||||
const TextToImage = ({ imageMediaId, imageUrl }: TextToImageProps) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [selectedModel, setSelectedModel] = useState<string>(
|
||||
"GPT Image 1 (GPT-4o)",
|
||||
);
|
||||
const [useSystemPrompt, setUseSystemPrompt] = useState(false);
|
||||
const [isImageBeingProcessed, setIsImageBeingProcessed] = useState(false);
|
||||
const [selectedImage, setSelectedImage] = useState<File | null>(null);
|
||||
const [imagePreviewUrl, setImagePreviewUrl] = useState<string>("");
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||
const { selectedModels } = useModelSelectorStore();
|
||||
const selectedModel =
|
||||
selectedModels[ModelCategory.TextToImage] ||
|
||||
imageGenerationModels[0]?.label;
|
||||
|
||||
const jobContext: JobContextType = {
|
||||
jobTokens: [],
|
||||
@@ -29,34 +28,6 @@ const TextToImage = ({ imageMediaId, imageUrl }: TextToImageProps) => {
|
||||
clearJobTokens: () => {},
|
||||
};
|
||||
|
||||
const modelList: PopoverItem[] = [
|
||||
{
|
||||
label: "GPT Image 1 (GPT-4o)",
|
||||
icon: <FontAwesomeIcon icon={faImage} className="h-4 w-4" />,
|
||||
selected: selectedModel === "GPT Image 1 (GPT-4o)",
|
||||
description: "Slow, ultra instructive model",
|
||||
badges: [{ label: "45 sec.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
},
|
||||
{
|
||||
label: "Flux Pro Ultra",
|
||||
icon: <FontAwesomeIcon icon={faImage} className="h-4 w-4" />,
|
||||
selected: selectedModel === "Flux Pro Ultra",
|
||||
description: "High quality model",
|
||||
badges: [{ label: "15 sec.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
},
|
||||
{
|
||||
label: "Recraft 3",
|
||||
icon: <FontAwesomeIcon icon={faImage} className="h-4 w-4" />,
|
||||
selected: selectedModel === "Recraft 3",
|
||||
description: "Fast and high-quality model",
|
||||
badges: [{ label: "15 sec.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
},
|
||||
];
|
||||
|
||||
const handleModelSelect = (item: PopoverItem) => {
|
||||
setSelectedModel(item.label);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
@@ -73,13 +44,12 @@ const TextToImage = ({ imageMediaId, imageUrl }: TextToImageProps) => {
|
||||
|
||||
<PromptBoxImage
|
||||
useJobContext={() => {
|
||||
// TODO: Implement job context logic
|
||||
console.log("Using job context");
|
||||
return jobContext;
|
||||
}}
|
||||
model={selectedModel}
|
||||
imageMediaId={imageMediaId}
|
||||
url={imageUrl ?? imagePreviewUrl ?? undefined}
|
||||
url={imageUrl ?? undefined}
|
||||
onEnqueuePressed={async () => {
|
||||
console.log("Enqueue pressed");
|
||||
}}
|
||||
@@ -88,9 +58,9 @@ const TextToImage = ({ imageMediaId, imageUrl }: TextToImageProps) => {
|
||||
<BackgroundGallery />
|
||||
|
||||
<div className="absolute bottom-6 left-6 z-20 flex items-center gap-2">
|
||||
<PopoverMenu
|
||||
items={modelList}
|
||||
onSelect={handleModelSelect}
|
||||
<ModelSelector
|
||||
items={imageGenerationModels}
|
||||
category={ModelCategory.TextToImage}
|
||||
mode="hoverSelect"
|
||||
panelTitle="Select Model"
|
||||
panelClassName="min-w-[280px]"
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { JobContextType } from "libs/common/src/lib/types";
|
||||
import { useRef } from "react";
|
||||
import { JobContextType } from "@storyteller/common";
|
||||
import { PromptBoxVideo } from "@storyteller/ui-promptbox";
|
||||
import BackgroundGallery from "./BackgroundGallery";
|
||||
import { PopoverMenu, type PopoverItem } from "@storyteller/ui-popover";
|
||||
import { faFilm, faClock } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import {
|
||||
ModelCategory,
|
||||
ModelSelector,
|
||||
useModelSelectorStore,
|
||||
videoGenerationModels,
|
||||
} from "@storyteller/ui-model-selector";
|
||||
|
||||
interface ImageToVideoProps {
|
||||
imageMediaId?: string;
|
||||
@@ -14,14 +16,10 @@ interface ImageToVideoProps {
|
||||
|
||||
const ImageToVideo = ({ imageMediaId, imageUrl }: ImageToVideoProps) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [selectedModel, setSelectedModel] = useState<string>("Kling 2.0");
|
||||
|
||||
const [useSystemPrompt, setUseSystemPrompt] = useState(false);
|
||||
const [isImageBeingProcessed, setIsImageBeingProcessed] = useState(false);
|
||||
|
||||
const [selectedImage, setSelectedImage] = useState<File | null>(null);
|
||||
const [imagePreviewUrl, setImagePreviewUrl] = useState<string>("");
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||
const { selectedModels } = useModelSelectorStore();
|
||||
const selectedModel =
|
||||
selectedModels[ModelCategory.ImageToVideo] ||
|
||||
videoGenerationModels[0]?.label;
|
||||
|
||||
const jobContext: JobContextType = {
|
||||
jobTokens: [],
|
||||
@@ -30,27 +28,6 @@ const ImageToVideo = ({ imageMediaId, imageUrl }: ImageToVideoProps) => {
|
||||
clearJobTokens: () => {},
|
||||
};
|
||||
|
||||
const modelList: PopoverItem[] = [
|
||||
{
|
||||
label: "Kling 2.0",
|
||||
icon: <FontAwesomeIcon icon={faFilm} className="h-4 w-4" />,
|
||||
selected: selectedModel === "Kling 2.0",
|
||||
description: "High quality model",
|
||||
badges: [{ label: "2 min.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
},
|
||||
{
|
||||
label: "Runway",
|
||||
icon: <FontAwesomeIcon icon={faFilm} className="h-4 w-4" />,
|
||||
selected: selectedModel === "Runway",
|
||||
description: "Fast and high-quality model",
|
||||
badges: [{ label: "2 min.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
},
|
||||
];
|
||||
|
||||
const handleModelSelect = (item: PopoverItem) => {
|
||||
setSelectedModel(item.label);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
@@ -73,7 +50,7 @@ const ImageToVideo = ({ imageMediaId, imageUrl }: ImageToVideoProps) => {
|
||||
}}
|
||||
model={selectedModel}
|
||||
imageMediaId={imageMediaId}
|
||||
url={imageUrl ?? imagePreviewUrl ?? undefined}
|
||||
url={imageUrl ?? undefined}
|
||||
onEnqueuePressed={async () => {
|
||||
console.log("Enqueue pressed");
|
||||
}}
|
||||
@@ -82,10 +59,9 @@ const ImageToVideo = ({ imageMediaId, imageUrl }: ImageToVideoProps) => {
|
||||
<BackgroundGallery />
|
||||
|
||||
<div className="absolute bottom-6 left-6 z-20 flex items-center gap-2">
|
||||
<PopoverMenu
|
||||
items={modelList}
|
||||
onSelect={handleModelSelect}
|
||||
mode="hoverSelect"
|
||||
<ModelSelector
|
||||
items={videoGenerationModels}
|
||||
category={ModelCategory.ImageToVideo}
|
||||
panelTitle="Select Model"
|
||||
panelClassName="min-w-[280px]"
|
||||
buttonClassName="bg-transparent p-0 text-lg hover:bg-transparent text-white/80 hover:text-white"
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
"noEmit": true
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "../../libs/components/model-selector"
|
||||
},
|
||||
{
|
||||
"path": "../../libs/components/pagination"
|
||||
},
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './lib/enums';
|
||||
export * from './lib/interfaces';
|
||||
export * from './lib/types';
|
||||
export * from "./lib/enums";
|
||||
export * from "./lib/interfaces";
|
||||
export * from "./lib/types";
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@nx/react/babel",
|
||||
{
|
||||
"runtime": "automatic",
|
||||
"useBuiltIns": "usage"
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# @storyteller/ui-model-selector
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `nx test @storyteller/ui-model-selector` to execute the unit tests via [Vitest](https://vitest.dev/).
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "@storyteller/ui-model-selector",
|
||||
"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,4 @@
|
||||
export * from "./lib/model-selector";
|
||||
export * from "./lib/model-selector-store";
|
||||
export * from "./lib/model-lists";
|
||||
export * from "./lib/model-categories";
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Defines the unique categories for each product or context where a model
|
||||
* selection is required. Using an enum prevents typos and ensures type safety.
|
||||
*/
|
||||
export enum ModelCategory {
|
||||
TextToImage = "text-to-image",
|
||||
ImageToVideo = "image-to-video",
|
||||
Canvas2D = "2d-canvas",
|
||||
Editor3D = "3d-editor",
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import type { PopoverItem } from "@storyteller/ui-popover";
|
||||
import { faClock, faFilm, faImage } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
export type ModelList = Omit<PopoverItem, "selected">[];
|
||||
|
||||
export const allModels = {
|
||||
video: [
|
||||
{
|
||||
label: "Kling 2.0",
|
||||
icon: <FontAwesomeIcon icon={faFilm} className="h-4 w-4" />,
|
||||
description: "High quality model",
|
||||
badges: [{ label: "2 min.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
},
|
||||
{
|
||||
label: "Runway",
|
||||
icon: <FontAwesomeIcon icon={faFilm} className="h-4 w-4" />,
|
||||
description: "Fast and high-quality model",
|
||||
badges: [{ label: "2 min.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
},
|
||||
],
|
||||
image: [
|
||||
{
|
||||
label: "GPT Image 1 (GPT-4o)",
|
||||
icon: <FontAwesomeIcon icon={faImage} className="h-4 w-4" />,
|
||||
description: "Slow, ultra instructive model",
|
||||
badges: [{ label: "45 sec.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
},
|
||||
{
|
||||
label: "Flux Pro Ultra",
|
||||
icon: <FontAwesomeIcon icon={faImage} className="h-4 w-4" />,
|
||||
description: "High quality model",
|
||||
badges: [{ label: "15 sec.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
},
|
||||
{
|
||||
label: "Recraft 3",
|
||||
icon: <FontAwesomeIcon icon={faImage} className="h-4 w-4" />,
|
||||
description: "Fast and high-quality model",
|
||||
badges: [{ label: "15 sec.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
},
|
||||
{
|
||||
label: "Flux.1 Kontext",
|
||||
icon: <FontAwesomeIcon icon={faImage} className="h-4 w-4" />,
|
||||
description: "New model with advanced context",
|
||||
badges: [{ label: "25 sec.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const videoGenerationModels: ModelList = allModels.video;
|
||||
export const imageGenerationModels: ModelList = allModels.image;
|
||||
@@ -0,0 +1,18 @@
|
||||
import { create } from "zustand";
|
||||
import { ModelCategory } from "./model-categories";
|
||||
|
||||
interface ModelSelectorState {
|
||||
selectedModels: { [category in ModelCategory]?: string };
|
||||
setSelectedModel: (category: ModelCategory, modelLabel: string) => void;
|
||||
}
|
||||
|
||||
export const useModelSelectorStore = create<ModelSelectorState>((set) => ({
|
||||
selectedModels: {},
|
||||
setSelectedModel: (category, modelLabel) =>
|
||||
set((state) => ({
|
||||
selectedModels: {
|
||||
...state.selectedModels,
|
||||
[category]: modelLabel,
|
||||
},
|
||||
})),
|
||||
}));
|
||||
@@ -0,0 +1,12 @@
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
import ModelSelector from './model-selector';
|
||||
|
||||
describe('ModelSelector', () => {
|
||||
|
||||
it('should render successfully', () => {
|
||||
const { baseElement } = render(<ModelSelector />);
|
||||
expect(baseElement).toBeTruthy();
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
import { PopoverMenu, type PopoverItem } from "@storyteller/ui-popover";
|
||||
import { useModelSelectorStore } from "./model-selector-store";
|
||||
import { useMemo } from "react";
|
||||
import { ModelCategory } from "./model-categories";
|
||||
|
||||
interface ModelSelectorProps {
|
||||
items: Omit<PopoverItem, "selected">[];
|
||||
category: ModelCategory;
|
||||
mode?: "hoverSelect" | "default" | "toggle" | "button";
|
||||
panelTitle?: string;
|
||||
buttonClassName?: string;
|
||||
panelClassName?: string;
|
||||
showIconsInList?: boolean;
|
||||
triggerLabel?: string;
|
||||
}
|
||||
|
||||
export function ModelSelector({
|
||||
items,
|
||||
category,
|
||||
...popoverProps
|
||||
}: ModelSelectorProps) {
|
||||
const { selectedModels, setSelectedModel } = useModelSelectorStore();
|
||||
const selectedModel = selectedModels[category] || items[0]?.label;
|
||||
|
||||
const handleModelSelect = (item: PopoverItem) => {
|
||||
setSelectedModel(category, item.label);
|
||||
};
|
||||
|
||||
const modelList = useMemo(
|
||||
() =>
|
||||
items.map((item) => ({
|
||||
...item,
|
||||
selected: item.label === selectedModel,
|
||||
})),
|
||||
[items, selectedModel]
|
||||
);
|
||||
|
||||
return (
|
||||
<PopoverMenu
|
||||
items={modelList}
|
||||
onSelect={handleModelSelect}
|
||||
mode="hoverSelect"
|
||||
{...popoverProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default ModelSelector;
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "../popover"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
],
|
||||
"extends": "../../../tsconfig.base.json"
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"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"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../popover/tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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/model-selector',
|
||||
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-model-selector',
|
||||
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,
|
||||
}
|
||||
},
|
||||
}));
|
||||
@@ -2,18 +2,18 @@
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../tauri-api"
|
||||
},
|
||||
{
|
||||
"path": "../camera-settings-modal"
|
||||
},
|
||||
{
|
||||
"path": "../toaster"
|
||||
"path": "../action-reminder-modal"
|
||||
},
|
||||
{
|
||||
"path": "../../soundboard"
|
||||
},
|
||||
{
|
||||
"path": "../../tauri-api"
|
||||
},
|
||||
{
|
||||
"path": "../gallery-modal"
|
||||
},
|
||||
@@ -38,6 +38,9 @@
|
||||
{
|
||||
"path": "../../common"
|
||||
},
|
||||
{
|
||||
"path": "../toaster"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
|
||||
@@ -43,18 +43,18 @@
|
||||
"src/**/*.tsx"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../tauri-api/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../camera-settings-modal/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../toaster/tsconfig.lib.json"
|
||||
"path": "../action-reminder-modal/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../soundboard/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../../tauri-api/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../gallery-modal/tsconfig.lib.json"
|
||||
},
|
||||
@@ -78,6 +78,9 @@
|
||||
},
|
||||
{
|
||||
"path": "../../common/tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "../toaster/tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Generated
+38
-1
@@ -22,7 +22,8 @@
|
||||
"react-device-detect": "^2.2.3",
|
||||
"react-dom": "18.3.1",
|
||||
"react-hot-toast": "^2.5.2",
|
||||
"react-router-dom": "6.29.0"
|
||||
"react-router-dom": "6.29.0",
|
||||
"zustand": "^5.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.14.5",
|
||||
@@ -1385,6 +1386,10 @@
|
||||
"name": "@storyteller/ui-modal",
|
||||
"version": "0.0.1"
|
||||
},
|
||||
"libs/components/model-selector": {
|
||||
"name": "@storyteller/ui-model-selector",
|
||||
"version": "0.0.1"
|
||||
},
|
||||
"libs/components/pagination": {
|
||||
"name": "@storyteller/ui-pagination",
|
||||
"version": "0.0.1"
|
||||
@@ -9263,6 +9268,10 @@
|
||||
"resolved": "libs/components/modal",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@storyteller/ui-model-selector": {
|
||||
"resolved": "libs/components/model-selector",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@storyteller/ui-pagination": {
|
||||
"resolved": "libs/components/pagination",
|
||||
"link": true
|
||||
@@ -28141,6 +28150,34 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/zustand": {
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.5.tgz",
|
||||
"integrity": "sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==",
|
||||
"engines": {
|
||||
"node": ">=12.20.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": ">=18.0.0",
|
||||
"immer": ">=9.0.6",
|
||||
"react": ">=18.0.0",
|
||||
"use-sync-external-store": ">=1.2.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"immer": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"use-sync-external-store": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/zwitch": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
"react-device-detect": "^2.2.3",
|
||||
"react-dom": "18.3.1",
|
||||
"react-hot-toast": "^2.5.2",
|
||||
"react-router-dom": "6.29.0"
|
||||
"react-router-dom": "6.29.0",
|
||||
"zustand": "^5.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.14.5",
|
||||
|
||||
@@ -131,6 +131,9 @@
|
||||
},
|
||||
{
|
||||
"path": "./libs/components/action-reminder-modal"
|
||||
},
|
||||
{
|
||||
"path": "./libs/components/model-selector"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user