@tnkrai/tnkr-editor 0.3.4 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -75107,28 +75107,46 @@ handleNext: parentHandleNext, handlePrevious: parentHandlePrevious, onCameraSett
75107
75107
  React.useEffect(() => {
75108
75108
  isPreparingRef.current = isPreparingAnimation;
75109
75109
  }, [isPreparingAnimation]);
75110
- // Reverse explosion animation function
75111
- const performReverseExplosion = React.useCallback(async (specificTransforms) => {
75112
- if (!updateExplosion) {
75113
- return;
75114
- }
75115
- const duration = 2000;
75116
- const startTime = Date.now();
75117
- const startFactor = 1;
75118
- const endFactor = 0;
75119
- const animate = () => {
75120
- const elapsed = Date.now() - startTime;
75121
- const progress = Math.min(elapsed / duration, 1);
75122
- const easeOut = 1 - Math.pow(1 - progress, 3);
75123
- const currentFactor = startFactor + (endFactor - startFactor) * easeOut;
75124
- updateExplosion(currentFactor, specificTransforms);
75125
- if (progress < 1) {
75126
- requestAnimationFrame(animate);
75127
- }
75128
- };
75129
- requestAnimationFrame(animate);
75130
- await new Promise((resolve) => setTimeout(resolve, duration + 100));
75131
- }, [updateExplosion]);
75110
+ // Sequential animation function - animate parts one by one based on order
75111
+ const performSequentialAnimation = React.useCallback(async (orderedParts, hasDirectionalParts) => {
75112
+ const partDuration = 700; // Fixed duration per part (500ms each)
75113
+ const overlap = 0; // 30% overlap between parts for smoother flow
75114
+ for (let i = 0; i < orderedParts.length; i++) {
75115
+ // if (playAnimationControlRef.current.shouldStop) return;
75116
+ const part = orderedParts[i];
75117
+ const delay = i * partDuration * (1 - overlap);
75118
+ // Start this part's animation after the delay
75119
+ setTimeout(() => {
75120
+ // if (playAnimationControlRef.current.shouldStop) return;
75121
+ // console.log(`🎬 Animating part ${i + 1}/${orderedParts.length}:`, part.name);
75122
+ const startTime = Date.now();
75123
+ const startFactor = 1;
75124
+ const endFactor = 0;
75125
+ const animatePart = () => {
75126
+ // if (playAnimationControlRef.current.shouldStop) return;
75127
+ const elapsed = Date.now() - startTime;
75128
+ const progress = Math.min(elapsed / partDuration, 1);
75129
+ const easeOut = 1 - Math.pow(1 - progress, 3);
75130
+ const currentFactor = startFactor + (endFactor - startFactor) * easeOut;
75131
+ // Animate this single part
75132
+ if (hasDirectionalParts && updateDirectionalExplosion) {
75133
+ updateDirectionalExplosion(currentFactor, [part]);
75134
+ }
75135
+ else if (updateExplosion) {
75136
+ updateExplosion(currentFactor, [part]);
75137
+ }
75138
+ if (progress < 1) {
75139
+ requestAnimationFrame(animatePart);
75140
+ }
75141
+ };
75142
+ requestAnimationFrame(animatePart);
75143
+ }, delay);
75144
+ }
75145
+ // Wait for all animations to complete
75146
+ const totalAnimationTime = (orderedParts.length - 1) * partDuration * (1 - overlap) + partDuration;
75147
+ await new Promise((resolve) => setTimeout(resolve, totalAnimationTime + 200));
75148
+ // console.log('✅ Sequential animation completed');
75149
+ }, [updateExplosion, updateDirectionalExplosion]);
75132
75150
  // ========================================
75133
75151
  // NEW: Updated function to use partOperations.isolateShapes
75134
75152
  // ========================================
@@ -75345,29 +75363,9 @@ handleNext: parentHandleNext, handlePrevious: parentHandlePrevious, onCameraSett
75345
75363
  console.log("⏳ Parts in start position. Waiting 1.5 seconds before animating...");
75346
75364
  await new Promise((resolve) => setTimeout(resolve, 1500));
75347
75365
  console.log("🎬 Starting animation now!");
75348
- // Step 4: Animate back to assembled (reverse explosion) - only affects step-specific parts
75349
- if (hasDirectionalParts && updateDirectionalExplosion) {
75350
- // Animate directional parts back to assembled position
75351
- const duration = 2000;
75352
- const startTime = Date.now();
75353
- const startFactor = 1;
75354
- const endFactor = 0;
75355
- const animate = () => {
75356
- const elapsed = Date.now() - startTime;
75357
- const progress = Math.min(elapsed / duration, 1);
75358
- const easeOut = 1 - Math.pow(1 - progress, 3);
75359
- const currentFactor = startFactor + (endFactor - startFactor) * easeOut;
75360
- updateDirectionalExplosion(currentFactor, stepSpecificParts);
75361
- if (progress < 1) {
75362
- requestAnimationFrame(animate);
75363
- }
75364
- };
75365
- requestAnimationFrame(animate);
75366
- await new Promise((resolve) => setTimeout(resolve, duration + 100));
75367
- }
75368
- else {
75369
- await performReverseExplosion(stepSpecificParts);
75370
- }
75366
+ // Step 4: Execute sequential animation (always use this as default)
75367
+ console.log('🎬 EXECUTING SEQUENTIAL ANIMATION');
75368
+ await performSequentialAnimation(stepSpecificParts, hasDirectionalParts);
75371
75369
  }
75372
75370
  catch (error) {
75373
75371
  console.error("❌ Error in step animation:", error);
@@ -75392,7 +75390,7 @@ handleNext: parentHandleNext, handlePrevious: parentHandlePrevious, onCameraSett
75392
75390
  updateExplosion,
75393
75391
  updateDirectionalExplosion,
75394
75392
  handleShowAllParts,
75395
- performReverseExplosion,
75393
+ performSequentialAnimation,
75396
75394
  isolateMultipleStepParts,
75397
75395
  setIsAnimating,
75398
75396
  setIsPreparingAnimation,
@@ -77030,11 +77028,7 @@ const AssemblyViewMode = ({ phases, htmlContent, className = "", productTitle, p
77030
77028
  if (currentPhase === null || currentPhase === void 0 ? void 0 : currentPhase.id) {
77031
77029
  handlePhaseDescriptionChange(currentPhase.id, content);
77032
77030
  }
77033
- }, onUploadImage: onUploadImage, customExtensionSet: getBasicExtensions(), className: "text-white", minHeight: 20, readOnly: !editMode }, `phase-${currentPhase === null || currentPhase === void 0 ? void 0 : currentPhase.id}`) }), jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [jsxRuntimeExports.jsx("h2", { className: "text-xl font-semibold mb-4 text-white", children: "Steps" }), jsxRuntimeExports.jsx("div", { className: "space-y-4", children: (currentPhase === null || currentPhase === void 0 ? void 0 : currentPhase.steps) && currentPhase.steps.length > 0 ? (currentPhase.steps.map((step, index) => (jsxRuntimeExports.jsx("button", { onClick: () => handleStepClick(index), className: "w-full text-left rounded-2xl px-4 py-3 cursor-pointer border border-[#313133] transition-all", onMouseEnter: (e) => {
77034
- e.currentTarget.style.border = '2px solid white';
77035
- }, onMouseLeave: (e) => {
77036
- e.currentTarget.style.border = '1px solid #313133';
77037
- }, children: jsxRuntimeExports.jsxs("span", { className: "text-white/70", children: ["Step ", index + 1, ": ", step.title] }) }, step.id)))) : (
77031
+ }, onUploadImage: onUploadImage, customExtensionSet: getBasicExtensions(), className: "text-white", minHeight: 20, readOnly: !editMode }, `phase-${currentPhase === null || currentPhase === void 0 ? void 0 : currentPhase.id}`) }), jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [jsxRuntimeExports.jsx("h2", { className: "text-xl font-semibold mb-4 text-white", children: "Steps" }), jsxRuntimeExports.jsx("div", { className: "space-y-4", children: (currentPhase === null || currentPhase === void 0 ? void 0 : currentPhase.steps) && currentPhase.steps.length > 0 ? (currentPhase.steps.map((step, index) => (jsxRuntimeExports.jsx("button", { onClick: () => handleStepClick(index), className: "w-full text-left rounded-2xl px-4 py-3 cursor-pointer border border-[#313133] transition-all hover:border-[#AA423A]", children: jsxRuntimeExports.jsxs("span", { className: "text-white/70", children: ["Step ", index + 1, ": ", step.title] }) }, step.id)))) : (
77038
77032
  // Display message when phase has valid title but no steps
77039
77033
  jsxRuntimeExports.jsx("p", { className: "text-white/80 text-md max-w-[31rem]", children: "No steps yet. Add an assembly step and an animation to let your readers know what to do." })) })] }), (currentPhase === null || currentPhase === void 0 ? void 0 : currentPhase.steps) && currentPhase.steps.length > 0 && (jsxRuntimeExports.jsx("div", { className: "mt-8 max-w-[7rem] ml-auto", children: jsxRuntimeExports.jsx(Button, { onClick: handleBeginPhase, className: "bg-[#AA423A] hover:bg-[#8A322E] text-white px-6 py-2 rounded-lg font-medium w-full h-11", children: "Begin Phase" }) }))] }))) : (
77040
77034
  // Step Details
@@ -77590,7 +77584,7 @@ const PreviewCategoryItem = ({ category, level, selectedId, onSelect, onToggleEx
77590
77584
  }, className: "ml-2 p-0.5 hover:bg-gray-700 rounded transition-colors flex-shrink-0", "aria-label": isExpanded ? "Collapse" : "Expand", children: isExpanded ? (jsxRuntimeExports.jsx(lucideReact.ChevronDown, { size: 14, className: "text-gray-400" })) : (jsxRuntimeExports.jsx(lucideReact.ChevronRight, { size: 14, className: "text-gray-400" })) }))] }), isExpanded && hasChildren && (jsxRuntimeExports.jsx("div", { children: category.children.map((child) => (jsxRuntimeExports.jsx(PreviewCategoryItem, { category: child, level: level + 1, selectedId: selectedId, onSelect: onSelect, onToggleExpand: onToggleExpand }, child.id))) }))] }));
77591
77585
  };
77592
77586
  const PreviewSidebar = ({ categories, selectedCategoryId, onCategorySelect, onToggleExpand, className = "", }) => {
77593
- return (jsxRuntimeExports.jsx("div", { className: cn("w-64 flex flex-col px-2", className), children: jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto py-4", children: [categories.map((category, index) => (jsxRuntimeExports.jsx("div", { className: index > 0 ? "mt-8" : "", children: jsxRuntimeExports.jsx(PreviewCategoryItem, { category: category, level: 0, selectedId: selectedCategoryId, onSelect: onCategorySelect, onToggleExpand: onToggleExpand }) }, category.id))), categories.length === 0 && (jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center p-8 text-gray-500", children: jsxRuntimeExports.jsx("p", { children: "No content available" }) }))] }) }));
77587
+ return (jsxRuntimeExports.jsxs("div", { className: cn("w-64 flex flex-col px-2", className), children: [jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto py-4", children: [categories.map((category, index) => (jsxRuntimeExports.jsx("div", { className: index > 0 ? "mt-8" : "", children: jsxRuntimeExports.jsx(PreviewCategoryItem, { category: category, level: 0, selectedId: selectedCategoryId, onSelect: onCategorySelect, onToggleExpand: onToggleExpand }) }, category.id))), categories.length === 0 && (jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center p-8 text-gray-500", children: jsxRuntimeExports.jsx("p", { children: "No content available" }) }))] }), jsxRuntimeExports.jsx("div", { className: "px-4 py-3 border-t border-[#313133]", children: jsxRuntimeExports.jsxs("a", { href: "https://tnkr.ai", target: "_blank", rel: "noopener noreferrer", className: "flex items-center justify-center gap-2 text-xs text-gray-400 hover:text-gray-300 transition-colors", children: [jsxRuntimeExports.jsx("span", { children: "Powered by" }), jsxRuntimeExports.jsx("span", { className: "font-semibold text-[#AA423A]", children: "TnkrAI" })] }) })] }));
77594
77588
  };
77595
77589
 
77596
77590
  const PageContentNavigator = ({ content, className = "" }) => {