Compare commits

...
Author SHA1 Message Date
bflatastic 22d7698618 reusable demo modal + 3d demo video 2025-04-22 19:21:45 +07:00
19 changed files with 333 additions and 76 deletions
@@ -2,10 +2,6 @@ import { useParams } from "react-router-dom";
import { withProtectionRoute } from "~/components/hoc";
import { useRenderCounter } from "~/hooks/useRenderCounter";
import { Resource, invoke } from "@tauri-apps/api/core";
// Components of the page
import { ToolbarUserProfile } from "~/components/features";
//Components of the Konva App are all in the KonvaComponent
import { KonvaRootComponent } from "~/KonvaRootComponent";
import { ToolbarTopLeft } from "~/components/features/ToolbarTopLeft";
@@ -15,17 +11,10 @@ import { appMode } from "~/signals";
import { useSignals } from "@preact/signals-react/runtime";
import { GenerationRootComponent } from "~/GenerationRootComponent/GenerationRootComponent";
import { EditModeRootComponent } from "~/EditModeRootComponent/EditModeRootComponent";
import { useRef, useState } from "react";
import { EngineType } from "~/KonvaApp";
import { useRef } from "react";
import { GenerationEngine } from "~/KonvaApp/GenerationEngine";
import { GalleryRootComponent } from "~/GalleryRootComponent";
import { BaseDialog } from "~/components/ui/BaseDialog";
import { Button } from "~/components/ui/Button";
import {
faArrowRight,
faMagicWandSparkles,
} from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { DemoModal } from "@storyteller/ui-demo-modal";
export const isTauri = (): boolean => {
console.log(window.__TAURI_INTERNALS__);
@@ -43,10 +32,7 @@ export const Main = withProtectionRoute(() => {
useSignals();
const realtimeEngineRef = useRef<EngineType | null>(null);
const generationEngineRef = useRef<GenerationEngine | null>(null);
const [firstTimeDialogOpen, setFirstTimeDialogOpen] = useState(true);
const [signinDialogOpen, setSigninDialogOpen] = useState(false);
const appModeValue = appMode.value;
let childView;
@@ -96,65 +82,21 @@ export const Main = withProtectionRoute(() => {
<GalleryRootComponent className="z-1 fixed h-full w-full bg-black" />
)}
</div>
<BaseDialog
isOpen={firstTimeDialogOpen}
onClose={() => {
setFirstTimeDialogOpen(false);
}}
className="max-w-5xl"
>
<div className="flex flex-col items-center justify-center gap-5">
<div className="flex flex-col items-center gap-3">
<h1 className="text-3xl font-bold">
<FontAwesomeIcon
icon={faMagicWandSparkles}
className="mr-3 text-[24px]"
/>
Welcome to ArtCraft
</h1>
<div className="text-center">
<p className="text-lg font-medium text-white/80">
Your creative canvas for digital art and design
</p>
<p className="text-white/60">
Draw freely, create collages, and design with our intuitive
tool. Bring your ideas to life in seconds!
</p>
</div>
</div>
<div className="aspect-video w-full overflow-hidden rounded-md">
<video autoPlay muted loop controls={false}>
<source src="/videos/artcraft-canvas-demo.mp4" type="video/mp4" />
</video>
</div>
<Button
className="font-semibold"
icon={faArrowRight}
iconFlip={true}
onClick={async () => {
if (isTauri()) {
await invoke("open_sora_login_command");
setFirstTimeDialogOpen(false);
} else {
console.error("Tauri is not available in this environment");
}
}}
>
Sign in to OpenAI to get Started
</Button>
{/* <Button
className="font-semibold"
icon={faArrowRight}
iconFlip={true}
onClick={() => {
setFirstTimeDialogOpen(false);
}}
>
Start creating now
</Button> */}
</div>
</BaseDialog>
<DemoModal
title="Welcome to ArtCraft Canvas"
subTitle="Your creative canvas for digital art and design"
description="Draw freely, create collages, and design with our intuitive tool."
videoSrc="/videos/artcraft-canvas-demo.mp4"
buttonText="Sign in to OpenAI to get started"
buttonOnClick={async () => {
if (isTauri()) {
await invoke("open_sora_login_command");
} else {
console.error("Tauri is not available in this environment");
}
}}
/>
</>
);
});
+3
View File
@@ -36,6 +36,9 @@
},
{
"path": "../../libs/tauri-utils/tsconfig.lib.json"
},
{
"path": "../../libs/components/demo-modal/tsconfig.lib.json"
}
]
}
+3
View File
@@ -10,6 +10,9 @@
{
"path": "../../libs/tauri-utils"
},
{
"path": "../../libs/components/demo-modal"
},
{
"path": "./tsconfig.app.json"
},
@@ -23,8 +23,7 @@ import { CameraAspectRatio } from "./enums";
import { PromptBox } from "./comps/PromptBox";
import { OnboardingHelper } from "./comps/OnboardingHelper";
import { FocalLengthDisplay } from "./comps/FocalLengthDisplay/FocalLengthDisplay";
// import { api } from "@storyteller/api";
// import { AnalyticsApi } from "@storyteller/api";
import { DemoModal } from "@storyteller/ui-demo-modal";
export const PageEditor = () => {
useSignals();
@@ -151,6 +150,15 @@ export const PageEditor = () => {
{/* <div onClick={handleOverlayClick}>
<Timeline />
</div> */}
<DemoModal
title="Welcome to ArtCraft 3D"
subTitle="Your 3D editor for digital art and design"
description="Set up your scene by adding objects and start bringing your ideas to life!"
videoSrc="/resources/videos/artcraft-3d-demo.mp4"
buttonText="Sign in to OpenAI to get started"
buttonOnClick={() => {}}
/>
</div>
);
};
+3
View File
@@ -36,6 +36,9 @@
{
"path": "../../libs/components/toaster"
},
{
"path": "../../libs/components/demo-modal"
},
{
"path": "../../libs/components/tooltip"
},
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
@@ -0,0 +1,7 @@
# @storyteller/ui-demo-modal
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test @storyteller/ui-demo-modal` to execute the unit tests via [Vitest](https://vitest.dev/).
@@ -0,0 +1,17 @@
{
"name": "@storyteller/ui-demo-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/demo-modal';
@@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/
@@ -0,0 +1,12 @@
import { render } from '@testing-library/react';
import DemoModal from './demo-modal';
describe('DemoModal', () => {
it('should render successfully', () => {
const { baseElement } = render(<DemoModal />);
expect(baseElement).toBeTruthy();
});
});
@@ -0,0 +1,75 @@
import { Modal } from "@storyteller/ui-modal";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faArrowRight,
faMagicWandSparkles,
} from "@fortawesome/pro-solid-svg-icons";
import { Button } from "@storyteller/ui-button";
import { useState } from "react";
interface DemoModalProps {
title: string;
subTitle: string;
description: string;
videoSrc: string;
buttonText: string;
buttonOnClick: () => void;
}
export function DemoModal({
title,
subTitle,
description,
videoSrc,
buttonText,
buttonOnClick,
}: DemoModalProps) {
const [firstTimeDialogOpen, setFirstTimeDialogOpen] = useState(true);
return (
<Modal
isOpen={firstTimeDialogOpen}
onClose={() => {
setFirstTimeDialogOpen(false);
}}
className="max-w-4xl p-6"
showClose={false}
>
<div className="flex flex-col items-center justify-center gap-6">
<div className="flex flex-col items-center gap-3">
<h1 className="text-3xl font-bold">
<FontAwesomeIcon
icon={faMagicWandSparkles}
className="mr-3 text-[24px]"
/>
{title}
</h1>
<div className="text-center">
<p className="text-lg font-medium text-white/80">{subTitle}</p>
<p className="text-white/60">{description}</p>
</div>
</div>
<div className="aspect-video w-full overflow-hidden rounded-md">
<video autoPlay muted loop controls={false}>
<source src={videoSrc} type="video/mp4" />
</video>
W
</div>
<Button
className="font-semibold"
icon={faArrowRight}
iconFlip={true}
onClick={() => {
buttonOnClick();
setFirstTimeDialogOpen(false);
}}
>
{buttonText}
</Button>
</div>
</Modal>
);
}
export default DemoModal;
@@ -0,0 +1,19 @@
{
"files": [],
"include": [],
"references": [
{
"path": "../button"
},
{
"path": "../modal"
},
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"extends": "../../../tsconfig.base.json"
}
@@ -0,0 +1,53 @@
{
"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": "../button/tsconfig.lib.json"
},
{
"path": "../modal/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/demo-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-demo-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,
}
},
}));
+8
View File
@@ -2009,6 +2009,10 @@
"name": "@storyteller/ui-close-button",
"version": "0.0.1"
},
"libs/components/demo-modal": {
"name": "@storyteller/ui-demo-modal",
"version": "0.0.1"
},
"libs/components/input": {
"name": "@storyteller/ui-input",
"version": "0.0.1"
@@ -10063,6 +10067,10 @@
"resolved": "libs/components/close-button",
"link": true
},
"node_modules/@storyteller/ui-demo-modal": {
"resolved": "libs/components/demo-modal",
"link": true
},
"node_modules/@storyteller/ui-input": {
"resolved": "libs/components/input",
"link": true
+3
View File
@@ -44,6 +44,9 @@
},
{
"path": "./libs/tauri-utils"
},
{
"path": "./libs/components/demo-modal"
}
]
}