mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-21 17:28:24 -04:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce60583675 | ||
|
|
496fc46300 |
@@ -15,6 +15,7 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storyteller/shared": "file:../../shared/*",
|
||||
"@devnomic/marquee": "^1.0.3",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
||||
|
||||
@@ -5,7 +5,7 @@ import { RouterProvider } from "react-router-dom";
|
||||
import { router } from "./router";
|
||||
import { posthog } from "posthog-js";
|
||||
import { PostHogProvider } from "posthog-js/react";
|
||||
import { Toaster } from "~/components/ui/Toast";
|
||||
import { Toaster } from "@storyteller/shared/components";
|
||||
import { JobProvider } from "~/components/JobContext";
|
||||
import "./global.css";
|
||||
import { useRenderCounter } from "~/hooks/useRenderCounter";
|
||||
@@ -33,7 +33,7 @@ const App = () => {
|
||||
<JobProvider>
|
||||
<PostHogProvider client={posthog}>
|
||||
<RouterProvider router={router} />
|
||||
<Toaster />
|
||||
<Toaster topOffset={70} rightOffset={12} />
|
||||
</PostHogProvider>
|
||||
</JobProvider>
|
||||
</StrictMode>
|
||||
@@ -43,7 +43,7 @@ const App = () => {
|
||||
<>
|
||||
<JobProvider>
|
||||
<RouterProvider router={router} />
|
||||
<Toaster />
|
||||
<Toaster topOffset={70} rightOffset={12} />
|
||||
</JobProvider>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -77,8 +77,9 @@ export const Main = withProtectionRoute(() => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{appModeValue === "gallery" &&
|
||||
(<GalleryRootComponent className="fixed h-full w-full z-1 bg-black" />)}
|
||||
{appModeValue === "gallery" && (
|
||||
<GalleryRootComponent className="z-1 fixed h-full w-full bg-black" />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import { CompletedCard } from "./CompletedCard";
|
||||
import { InProgressCard } from "./InProgressCard";
|
||||
import { useJobContext } from "~/components/JobContext";
|
||||
import { Api } from "~/KonvaApp/Api";
|
||||
import { toast } from "sonner";
|
||||
import { toast } from "@storyteller/shared/components";
|
||||
|
||||
// Dummy data types
|
||||
interface CompletedItem {
|
||||
@@ -199,7 +199,7 @@ export function Activity() {
|
||||
</div>
|
||||
) : completedItems.length === 0 && jobs.length === 0 ? (
|
||||
<div className="flex h-48 w-full flex-col justify-center gap-4 p-4 text-center align-middle">
|
||||
<h3 className="text-gray-300">No activities yet</h3>
|
||||
<h3 className="text-lg text-gray-300">No activities yet</h3>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"paths": {
|
||||
"~/*": ["./src/*"],
|
||||
"@ApiManager/*": ["./src/Classes/ApiManager/*"]
|
||||
"@ApiManager/*": ["./src/Classes/ApiManager/*"],
|
||||
"@storyteller/shared/*": ["../../shared/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src"]
|
||||
|
||||
@@ -52,7 +52,7 @@ export const TopBar = ({ pageName }: Props) => {
|
||||
<SceneTitleInput pageName={pageName} />
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-5">
|
||||
<div className="flex justify-end gap-3">
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
variant="secondary"
|
||||
|
||||
@@ -6,9 +6,8 @@ import { useBackgroundLoadingMedia } from "~/hooks/useBackgroundLoadingMedia";
|
||||
import { useQueueHandler } from "./hooks/useQueueHandler";
|
||||
import { ErrorDialog, LoadingDots } from "~/components";
|
||||
import { GenerateModals } from "~/pages/PageEnigma/comps/GenerateModals/GenerateModals";
|
||||
|
||||
import { Toaster } from "@storyteller/shared/components";
|
||||
import { EditorLoadingBar } from "./comps/EditorLoadingBar";
|
||||
|
||||
import { Wizard } from "~/pages/PageEnigma/Wizard/Wizard";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { useEffect, useState } from "react";
|
||||
@@ -17,7 +16,12 @@ import { UsersApi } from "~/Classes/ApiManager";
|
||||
import { PageEnigmaComponent } from "~/pages/PageEnigma/PageEnigmaComponent";
|
||||
import { TurnOnGpu } from "~/pages/PageEnigma/TurnOnGpu";
|
||||
import { PrecisionSelector } from "./comps/PrecisionSelector/PrecisionSelector";
|
||||
import { precisionSelectedValue, precisionSelectorMenuCoords, precisionSelectorValues, showPrecisionSelector } from "./signals/precisionSelectorMenu";
|
||||
import {
|
||||
precisionSelectedValue,
|
||||
precisionSelectorMenuCoords,
|
||||
precisionSelectorValues,
|
||||
showPrecisionSelector,
|
||||
} from "./signals/precisionSelectorMenu";
|
||||
|
||||
export const PageEnigma = ({ sceneToken }: { sceneToken?: string }) => {
|
||||
useSignals();
|
||||
@@ -104,6 +108,7 @@ export const PageEnigma = ({ sceneToken }: { sceneToken?: string }) => {
|
||||
<GenerateModals />
|
||||
<ErrorDialog />
|
||||
<Wizard />
|
||||
<Toaster topOffset={70} rightOffset={12} />
|
||||
</EngineProvider>
|
||||
<EditorLoadingBar />
|
||||
</TrackProvider>
|
||||
|
||||
@@ -4,11 +4,10 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { PopoverMenu } from "~/components/reusable/Popover/Popover";
|
||||
import { CompletedCard } from "./CompletedCard";
|
||||
import { InProgressCard } from "./InProgressCard";
|
||||
import { H3, P, Tooltip } from "~/components";
|
||||
import { activeImageGenerationJobs, toasts, userMovies } from "~/signals";
|
||||
import { useEffect, useState } from "react";
|
||||
import { H3, Tooltip } from "~/components";
|
||||
import { useEffect, useState, useRef, useCallback } from "react";
|
||||
import { JobsApi } from "~/Classes/ApiManager/JobsApi";
|
||||
import { toast } from "sonner";
|
||||
import { toast } from "@storyteller/shared/components";
|
||||
import { ActiveJob } from "~/pages/PageEnigma/models";
|
||||
// TODO ensure we de-dupe all this extra code.
|
||||
interface CompletedItem {
|
||||
@@ -60,26 +59,49 @@ interface CompletedItem {
|
||||
export function Activity() {
|
||||
useSignals();
|
||||
const [completedItems, setCompletedItems] = useState<CompletedItem[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [jobs, setJobs] = useState<ActiveJob[]>([]);
|
||||
const processedJobs = useRef(new Set<string>());
|
||||
const isFirstLoad = useRef(true);
|
||||
const toastTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
// Debounced toast function
|
||||
const showToast = useCallback((items: CompletedItem[]) => {
|
||||
if (toastTimeoutRef.current) {
|
||||
clearTimeout(toastTimeoutRef.current);
|
||||
}
|
||||
|
||||
toastTimeoutRef.current = setTimeout(() => {
|
||||
const count = items.length;
|
||||
toast.success(
|
||||
count === 1
|
||||
? `${items[0].maybe_title} completed successfully`
|
||||
: `${count} images completed successfully`,
|
||||
);
|
||||
toastTimeoutRef.current = null;
|
||||
}, 100); // Small delay to catch potential double calls
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const pollData = async () => {
|
||||
const fetchJobs = async () => {
|
||||
try {
|
||||
const jobsApi = new JobsApi();
|
||||
const jobsResponse = await jobsApi.ListRecentJobs();
|
||||
let mounted = true;
|
||||
|
||||
if (jobsResponse.success && jobsResponse.data) {
|
||||
// Process active jobs
|
||||
const activeJobs = jobsResponse.data
|
||||
.filter((job) => {
|
||||
const status = job.status?.status?.toLowerCase();
|
||||
return (
|
||||
status && status !== "complete_success" && status !== "failed"
|
||||
);
|
||||
})
|
||||
.map((job) => ({
|
||||
async function fetchJobs() {
|
||||
try {
|
||||
const jobsApi = new JobsApi();
|
||||
const response = await jobsApi.ListRecentJobs();
|
||||
|
||||
if (!mounted || !response.success || !response.data) return;
|
||||
|
||||
// Handle active jobs
|
||||
const activeJobs = response.data
|
||||
.filter((job) => {
|
||||
const status = job.status?.status?.toLowerCase();
|
||||
return (
|
||||
status && status !== "complete_success" && status !== "failed"
|
||||
);
|
||||
})
|
||||
.map(
|
||||
(job) =>
|
||||
({
|
||||
job_token: job.job_token,
|
||||
request: {
|
||||
maybe_model_title:
|
||||
@@ -89,79 +111,78 @@ export function Activity() {
|
||||
status: job.status?.status?.toUpperCase() || "",
|
||||
progress_percentage: job.status?.progress_percentage || 0,
|
||||
},
|
||||
}));
|
||||
|
||||
// Process completed items
|
||||
// Get completed items and filter out any that are already in our list
|
||||
const successfulJobs = jobsResponse.data.filter(
|
||||
(job) => job.status?.status?.toLowerCase() === "complete_success",
|
||||
);
|
||||
|
||||
// Create a set of existing tokens for faster lookup
|
||||
const existingTokens = new Set(
|
||||
completedItems.map((item) => item.token),
|
||||
);
|
||||
|
||||
// Filter out jobs we already have in our list
|
||||
const newCompletedItems = successfulJobs
|
||||
.filter((job) => !existingTokens.has(job.job_token))
|
||||
.map((job) => ({
|
||||
token: job.job_token,
|
||||
maybe_title:
|
||||
job.request?.maybe_model_title || "Image Generation",
|
||||
public_bucket_path:
|
||||
job.maybe_result?.maybe_public_bucket_media_path || "",
|
||||
created_at: job.created_at || new Date().toISOString(),
|
||||
updated_at: job.updated_at || new Date().toISOString(),
|
||||
}));
|
||||
maybe_result: job.maybe_result || null,
|
||||
}) as ActiveJob,
|
||||
);
|
||||
|
||||
// Show toast notification for newly completed items
|
||||
if (newCompletedItems.length > 0) {
|
||||
const count = newCompletedItems.length;
|
||||
const message =
|
||||
count === 1
|
||||
? `${newCompletedItems[0].maybe_title} completed successfully`
|
||||
: `${count} images completed successfully`;
|
||||
toast.success(message);
|
||||
}
|
||||
// Handle completed jobs
|
||||
const newlyCompleted = response.data.filter(
|
||||
(job) =>
|
||||
job.status?.status?.toLowerCase() === "complete_success" &&
|
||||
!processedJobs.current.has(job.job_token),
|
||||
);
|
||||
|
||||
// Update completed items with a maximum limit of 50 items
|
||||
setCompletedItems((prev) => {
|
||||
const combined = [...newCompletedItems, ...prev];
|
||||
// Remove duplicates based on token
|
||||
const uniqueItems = Array.from(
|
||||
new Map(combined.map((item) => [item.token, item])).values(),
|
||||
);
|
||||
// Sort by updated_at in descending order and limit to 50 items
|
||||
return uniqueItems
|
||||
.sort(
|
||||
(a, b) =>
|
||||
new Date(b.updated_at).getTime() -
|
||||
new Date(a.updated_at).getTime(),
|
||||
)
|
||||
.slice(0, 50);
|
||||
});
|
||||
setJobs(activeJobs as ActiveJob[]);
|
||||
setLoading(false);
|
||||
if (newlyCompleted.length > 0) {
|
||||
// Add to processed set
|
||||
newlyCompleted.forEach((job) =>
|
||||
processedJobs.current.add(job.job_token),
|
||||
);
|
||||
|
||||
// Create completed items
|
||||
const newItems = newlyCompleted.map((job) => ({
|
||||
token: job.job_token,
|
||||
maybe_title: job.request?.maybe_model_title || "Image Generation",
|
||||
public_bucket_path:
|
||||
job.maybe_result?.maybe_public_bucket_media_path || "",
|
||||
updated_at: job.updated_at || new Date().toISOString(),
|
||||
}));
|
||||
|
||||
// Show toast only if not first load
|
||||
if (!isFirstLoad.current) {
|
||||
showToast(newItems);
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error("Error Fetching Recent Jobs");
|
||||
console.error("Failed to fetch recent jobs:", error);
|
||||
|
||||
// Update state
|
||||
setCompletedItems((prev) => {
|
||||
const combined = [...newItems, ...prev];
|
||||
return combined
|
||||
.filter(
|
||||
(item, index, self) =>
|
||||
index === self.findIndex((t) => t.token === item.token),
|
||||
)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
new Date(b.updated_at).getTime() -
|
||||
new Date(a.updated_at).getTime(),
|
||||
)
|
||||
.slice(0, 50);
|
||||
});
|
||||
}
|
||||
};
|
||||
await fetchJobs();
|
||||
|
||||
setJobs(activeJobs);
|
||||
isFirstLoad.current = false;
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch jobs:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Initial fetch
|
||||
fetchJobs();
|
||||
|
||||
// Set up polling
|
||||
const interval = setInterval(fetchJobs, 5000);
|
||||
|
||||
// Cleanup
|
||||
return () => {
|
||||
mounted = false;
|
||||
clearInterval(interval);
|
||||
if (toastTimeoutRef.current) {
|
||||
clearTimeout(toastTimeoutRef.current);
|
||||
}
|
||||
};
|
||||
|
||||
// Initial load
|
||||
// Initial call to pollData
|
||||
pollData();
|
||||
// Set up polling interval (every 5 seconds)
|
||||
const interval = setInterval(async () => {
|
||||
await pollData();
|
||||
}, 5000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
}, [showToast]);
|
||||
|
||||
return (
|
||||
<Tooltip content="Activity" position="bottom" closeOnClick={true}>
|
||||
@@ -173,20 +194,19 @@ export function Activity() {
|
||||
align="end"
|
||||
triggerIcon={
|
||||
<div>
|
||||
{jobs && jobs.length > 0 ? (
|
||||
{jobs.length > 0 ? (
|
||||
<FontAwesomeIcon icon={faSpinnerThird} className="animate-spin" />
|
||||
) : (
|
||||
<FontAwesomeIcon icon={faBell} />
|
||||
)}
|
||||
{jobs && jobs.length > 0 && (
|
||||
<div className="bg-blue-500 absolute -right-1 -top-1 h-3 w-3 animate-pulse rounded-full" />
|
||||
{jobs.length > 0 && (
|
||||
<div className="absolute -right-1 -top-1 h-3 w-3 animate-pulse rounded-full bg-brand-primary-400" />
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="max-h-[480px] overflow-y-auto">
|
||||
{/* In progress */}
|
||||
{jobs && jobs.length > 0 && (
|
||||
{jobs.length > 0 && (
|
||||
<div>
|
||||
{jobs.map((job) => (
|
||||
<InProgressCard key={job.job_token} job={job} />
|
||||
@@ -194,7 +214,7 @@ export function Activity() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!userMovies.value && !activeImageGenerationJobs.value ? (
|
||||
{isFirstLoad.current ? (
|
||||
<div className="flex h-48 w-full flex-col justify-center gap-4 p-4 text-center align-middle">
|
||||
<FontAwesomeIcon
|
||||
icon={faSpinnerThird}
|
||||
@@ -204,18 +224,12 @@ export function Activity() {
|
||||
/>
|
||||
<H3 className="text-gray-300">Retrieving Activities</H3>
|
||||
</div>
|
||||
) : userMovies.value &&
|
||||
userMovies.value.length === 0 &&
|
||||
!activeImageGenerationJobs.value ? (
|
||||
) : jobs.length === 0 && completedItems.length === 0 ? (
|
||||
<div className="flex h-48 w-full flex-col justify-center gap-4 p-4 text-center align-middle">
|
||||
<H3 className="text-gray-300">No activities yet</H3>
|
||||
<P className="text-gray-400">
|
||||
Try generating something new from the featured scenes
|
||||
</P>
|
||||
<h3 className="text-lg text-gray-300">No activities yet</h3>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
{/* Completed */}
|
||||
<div className="flex flex-col">
|
||||
{completedItems.map((item) => (
|
||||
<CompletedCard key={item.token} job={item} />
|
||||
|
||||
@@ -58,6 +58,7 @@ interface ReferenceImage {
|
||||
import { EngineApi } from "~/Classes/ApiManager/EngineApi";
|
||||
import { UploaderStates } from "~/enums/UploaderStates";
|
||||
import { CameraSettingsModal } from "../CameraSettingsModal";
|
||||
import { toast } from "@storyteller/shared/components";
|
||||
|
||||
export const PromptBox = () => {
|
||||
useSignals();
|
||||
@@ -430,7 +431,7 @@ export const PromptBox = () => {
|
||||
screenshot: snapshot.file,
|
||||
sceneMediaToken: "",
|
||||
});
|
||||
|
||||
|
||||
console.log("useSystemPrompt", useSystemPrompt);
|
||||
await engineApi.enqueueImageGeneration({
|
||||
disableSystemPrompt: !useSystemPrompt,
|
||||
@@ -451,6 +452,7 @@ export const PromptBox = () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
} finally {
|
||||
setisEnqueueing(false);
|
||||
toast.success("Image generation enqueued");
|
||||
}
|
||||
}
|
||||
setisEnqueueing(false);
|
||||
|
||||
@@ -22,13 +22,14 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@storyteller/api": "file:../../libs/api",
|
||||
"@storyteller/shared": "file:../../shared/*",
|
||||
"@awesome.me/kit-fde2be5eb0": "^1.0.7",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
||||
"@fortawesome/pro-regular-svg-icons": "^6.5.1",
|
||||
"@fortawesome/pro-solid-svg-icons": "^6.5.1",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@headlessui/react": "^1.7.18",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
||||
"@fortawesome/pro-regular-svg-icons": "^6.7.2",
|
||||
"@fortawesome/pro-solid-svg-icons": "^6.7.2",
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
"@headlessui/react": "^2.1.3",
|
||||
"@mediapipe/tasks-vision": "^0.10.20",
|
||||
"@netlify/edge-functions": "^2.3.1",
|
||||
"@netlify/remix-edge-adapter": "^3.2.0",
|
||||
@@ -53,9 +54,9 @@
|
||||
"isbot": "^4.1.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"posthog-js": "^1.141.0",
|
||||
"react": "^18.2.0",
|
||||
"react": "^18.3.1",
|
||||
"react-copy-to-clipboard": "^5.1.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-drag-drop-files": "^2.3.10",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-image-crop": "^11.0.5",
|
||||
@@ -63,7 +64,7 @@
|
||||
"tailwind-merge": "^2.2.2",
|
||||
"terser": "^5.30.3",
|
||||
"three": "^0.162.0",
|
||||
"uuid": "^9.0.1",
|
||||
"uuid": "^10.0.0",
|
||||
"wavesurfer.js": "^7.7.11",
|
||||
"webm-writer": "^1.0.0"
|
||||
},
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
{
|
||||
"include": [
|
||||
"env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"netlify-edge-plugin.ts"
|
||||
],
|
||||
"include": ["env.d.ts", "**/*.ts", "**/*.tsx", "netlify-edge-plugin.ts"],
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"DOM",
|
||||
"DOM.Iterable",
|
||||
"ESNext"
|
||||
],
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"jsx": "react-jsx",
|
||||
@@ -24,9 +15,8 @@
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"~/*": [
|
||||
"./app/*"
|
||||
]
|
||||
"~/*": ["./app/*"],
|
||||
"@storyteller/shared/*": ["../../shared/*"]
|
||||
},
|
||||
// Vite takes care of building everything, not tsc.
|
||||
"noEmit": true
|
||||
|
||||
Generated
+80
-43
@@ -69,6 +69,7 @@
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
"@headlessui/react": "^2.1.3",
|
||||
"@preact/signals-react": "^2.2.0",
|
||||
"@storyteller/shared": "file:../../shared/*",
|
||||
"@tauri-apps/api": "^2.2.0",
|
||||
"@techstark/opencv-js": "^4.10.0-release.1",
|
||||
"@zip.js/zip.js": "^2.7.52",
|
||||
@@ -570,25 +571,6 @@
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"apps/editor2d/node_modules/@headlessui/react": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.1.tgz",
|
||||
"integrity": "sha512-daiUqVLae8CKVjEVT19P/izW0aGK0GNhMSAeMlrDebKmoVZHcRRwbxzgtnEadUVDXyBsWo9/UH4KHeniO+0tMg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/react": "^0.26.16",
|
||||
"@react-aria/focus": "^3.17.1",
|
||||
"@react-aria/interactions": "^3.21.3",
|
||||
"@tanstack/react-virtual": "^3.11.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18 || ^19 || ^19.0.0-rc",
|
||||
"react-dom": "^18 || ^19 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"apps/editor2d/node_modules/@preact/signals-react": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@preact/signals-react/-/signals-react-2.3.0.tgz",
|
||||
@@ -1179,12 +1161,12 @@
|
||||
"apps/editor3d": {
|
||||
"dependencies": {
|
||||
"@awesome.me/kit-fde2be5eb0": "^1.0.7",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
||||
"@fortawesome/pro-regular-svg-icons": "^6.5.1",
|
||||
"@fortawesome/pro-solid-svg-icons": "^6.5.1",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@headlessui/react": "^1.7.18",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
||||
"@fortawesome/pro-regular-svg-icons": "^6.7.2",
|
||||
"@fortawesome/pro-solid-svg-icons": "^6.7.2",
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
"@headlessui/react": "^2.1.3",
|
||||
"@mediapipe/tasks-vision": "^0.10.20",
|
||||
"@netlify/edge-functions": "^2.3.1",
|
||||
"@netlify/remix-edge-adapter": "^3.2.0",
|
||||
@@ -1196,6 +1178,7 @@
|
||||
"@remix-run/router": "^1.15.3",
|
||||
"@remix-run/serve": "^2.8.1",
|
||||
"@storyteller/api": "file:../../libs/api",
|
||||
"@storyteller/shared": "file:../../shared/*",
|
||||
"@tweenjs/tween.js": "^18.6.4",
|
||||
"@types/lodash": "^4.17.6",
|
||||
"@types/react-virtualized": "^9.22.2",
|
||||
@@ -1210,9 +1193,9 @@
|
||||
"isbot": "^4.1.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"posthog-js": "^1.141.0",
|
||||
"react": "^18.2.0",
|
||||
"react": "^18.3.1",
|
||||
"react-copy-to-clipboard": "^5.1.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-drag-drop-files": "^2.3.10",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-image-crop": "^11.0.5",
|
||||
@@ -1220,7 +1203,7 @@
|
||||
"tailwind-merge": "^2.2.2",
|
||||
"terser": "^5.30.3",
|
||||
"three": "^0.162.0",
|
||||
"uuid": "^9.0.1",
|
||||
"uuid": "^10.0.0",
|
||||
"wavesurfer.js": "^7.7.11",
|
||||
"webm-writer": "^1.0.0"
|
||||
},
|
||||
@@ -1685,6 +1668,10 @@
|
||||
"react": "^16.14.0 || 17.x || 18.x || 19.x"
|
||||
}
|
||||
},
|
||||
"apps/editor3d/node_modules/@storyteller/shared": {
|
||||
"resolved": "shared/components",
|
||||
"link": true
|
||||
},
|
||||
"apps/editor3d/node_modules/@types/react": {
|
||||
"version": "18.3.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz",
|
||||
@@ -1932,6 +1919,41 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"apps/editor3d/node_modules/react": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"apps/editor3d/node_modules/react-dom": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"scheduler": "^0.23.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.3.1"
|
||||
}
|
||||
},
|
||||
"apps/editor3d/node_modules/uuid": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
|
||||
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"apps/editor3d/node_modules/vite": {
|
||||
"version": "5.4.18",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.18.tgz",
|
||||
@@ -4715,20 +4737,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@headlessui/react": {
|
||||
"version": "1.7.19",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.19.tgz",
|
||||
"integrity": "sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==",
|
||||
"license": "MIT",
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.1.tgz",
|
||||
"integrity": "sha512-daiUqVLae8CKVjEVT19P/izW0aGK0GNhMSAeMlrDebKmoVZHcRRwbxzgtnEadUVDXyBsWo9/UH4KHeniO+0tMg==",
|
||||
"dependencies": {
|
||||
"@tanstack/react-virtual": "^3.0.0-beta.60",
|
||||
"client-only": "^0.0.1"
|
||||
"@floating-ui/react": "^0.26.16",
|
||||
"@react-aria/focus": "^3.17.1",
|
||||
"@react-aria/interactions": "^3.21.3",
|
||||
"@tanstack/react-virtual": "^3.11.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16 || ^17 || ^18",
|
||||
"react-dom": "^16 || ^17 || ^18"
|
||||
"react": "^18 || ^19 || ^19.0.0-rc",
|
||||
"react-dom": "^18 || ^19 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanfs/core": {
|
||||
@@ -9897,6 +9920,10 @@
|
||||
"resolved": "libs/api",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@storyteller/shared": {
|
||||
"resolved": "shared/*",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-add-jsx-attribute": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz",
|
||||
@@ -14582,12 +14609,6 @@
|
||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/client-only": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
@@ -30560,6 +30581,7 @@
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
@@ -31853,6 +31875,21 @@
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
}
|
||||
},
|
||||
"shared": {
|
||||
"name": "@storyteller/shared",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"sonner": "^1.4.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
}
|
||||
},
|
||||
"shared/*": {},
|
||||
"shared/components": {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
packages:
|
||||
- 'apps/*'
|
||||
- 'libs/*'
|
||||
|
||||
- "apps/*"
|
||||
- "libs/*"
|
||||
- "shared/*"
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Toaster as SonnerToaster } from "sonner";
|
||||
|
||||
interface ToasterProps {
|
||||
topOffset?: number;
|
||||
rightOffset?: number;
|
||||
}
|
||||
|
||||
export const Toaster = ({ topOffset = 0, rightOffset = 0 }: ToasterProps) => {
|
||||
return (
|
||||
<div className="relative z-[9]">
|
||||
<SonnerToaster
|
||||
position="top-right"
|
||||
expand={false}
|
||||
richColors
|
||||
closeButton
|
||||
style={{ top: topOffset, right: rightOffset }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// Re-export toast function from sonner for easy access
|
||||
export { toast } from "sonner";
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./Toaster";
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "@storyteller/shared",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"main": "./components/index.ts",
|
||||
"exports": {
|
||||
"./components": "./components/index.ts",
|
||||
"./contexts": "./contexts/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"sonner": "^1.4.3",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": ".",
|
||||
"declaration": true,
|
||||
"composite": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["dist", "node_modules"]
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"target": "es2022",
|
||||
"customConditions": ["development"]
|
||||
"customConditions": ["development"],
|
||||
"baseUrl": "."
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user