@memori.ai/memori-react 8.8.5 → 8.9.0

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.
Files changed (176) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +28 -0
  3. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +0 -1
  4. package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
  5. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +0 -10
  6. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
  7. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js +0 -9
  8. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js.map +1 -1
  9. package/dist/components/Chat/Chat.css +31 -0
  10. package/dist/components/Chat/Chat.js +18 -4
  11. package/dist/components/Chat/Chat.js.map +1 -1
  12. package/dist/components/ChatBubble/ChatBubble.js +1 -2
  13. package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
  14. package/dist/components/ChatInputs/ChatInputs.css +23 -0
  15. package/dist/components/ChatInputs/ChatInputs.d.ts +1 -0
  16. package/dist/components/ChatInputs/ChatInputs.js +37 -21
  17. package/dist/components/ChatInputs/ChatInputs.js.map +1 -1
  18. package/dist/components/ChatTextArea/ChatTextArea.css +31 -0
  19. package/dist/components/ChatTextArea/ChatTextArea.d.ts +1 -0
  20. package/dist/components/ChatTextArea/ChatTextArea.js +9 -2
  21. package/dist/components/ChatTextArea/ChatTextArea.js.map +1 -1
  22. package/dist/components/FilePreview/FilePreview.css +39 -0
  23. package/dist/components/Header/Header.js +3 -16
  24. package/dist/components/Header/Header.js.map +1 -1
  25. package/dist/components/MediaWidget/LinkItemWidget.js +1 -1
  26. package/dist/components/MediaWidget/LinkItemWidget.js.map +1 -1
  27. package/dist/components/MediaWidget/MediaItemWidget.js +5 -9
  28. package/dist/components/MediaWidget/MediaItemWidget.js.map +1 -1
  29. package/dist/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js +65 -51
  30. package/dist/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js.map +1 -1
  31. package/dist/components/MemoriArtifactSystem/utils/ArtifactAPI.d.ts +5 -0
  32. package/dist/components/MemoriArtifactSystem/utils/ArtifactAPI.js +287 -0
  33. package/dist/components/MemoriArtifactSystem/utils/ArtifactAPI.js.map +1 -0
  34. package/dist/components/MemoriWidget/MemoriWidget.d.ts +12 -0
  35. package/dist/components/MemoriWidget/MemoriWidget.js +12 -3
  36. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  37. package/dist/components/Snippet/Snippet.js +4 -3
  38. package/dist/components/Snippet/Snippet.js.map +1 -1
  39. package/dist/components/StartPanel/StartPanel.css +14 -0
  40. package/dist/components/StartPanel/StartPanel.js +2 -2
  41. package/dist/components/StartPanel/StartPanel.js.map +1 -1
  42. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js +0 -21
  43. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  44. package/dist/components/VenueWidget/VenueWidget.js +0 -1
  45. package/dist/components/VenueWidget/VenueWidget.js.map +1 -1
  46. package/dist/components/layouts/HiddenChat.js +0 -15
  47. package/dist/components/layouts/HiddenChat.js.map +1 -1
  48. package/dist/components/layouts/chat.css +2 -2
  49. package/dist/context/visemeContext.js +0 -6
  50. package/dist/context/visemeContext.js.map +1 -1
  51. package/dist/helpers/constants.d.ts +11 -0
  52. package/dist/helpers/constants.js +24 -2
  53. package/dist/helpers/constants.js.map +1 -1
  54. package/dist/helpers/tts/useTTS.js +0 -3
  55. package/dist/helpers/tts/useTTS.js.map +1 -1
  56. package/dist/helpers/utils.d.ts +1 -0
  57. package/dist/helpers/utils.js +6 -1
  58. package/dist/helpers/utils.js.map +1 -1
  59. package/dist/index.js.map +1 -1
  60. package/dist/locales/de.json +2 -0
  61. package/dist/locales/en.json +2 -0
  62. package/dist/locales/es.json +2 -0
  63. package/dist/locales/fr.json +2 -0
  64. package/dist/locales/it.json +2 -0
  65. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +0 -1
  66. package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
  67. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +0 -10
  68. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
  69. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js +0 -9
  70. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js.map +1 -1
  71. package/esm/components/Chat/Chat.css +31 -0
  72. package/esm/components/Chat/Chat.js +19 -5
  73. package/esm/components/Chat/Chat.js.map +1 -1
  74. package/esm/components/ChatBubble/ChatBubble.js +1 -2
  75. package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
  76. package/esm/components/ChatInputs/ChatInputs.css +23 -0
  77. package/esm/components/ChatInputs/ChatInputs.d.ts +1 -0
  78. package/esm/components/ChatInputs/ChatInputs.js +37 -21
  79. package/esm/components/ChatInputs/ChatInputs.js.map +1 -1
  80. package/esm/components/ChatTextArea/ChatTextArea.css +31 -0
  81. package/esm/components/ChatTextArea/ChatTextArea.d.ts +1 -0
  82. package/esm/components/ChatTextArea/ChatTextArea.js +9 -2
  83. package/esm/components/ChatTextArea/ChatTextArea.js.map +1 -1
  84. package/esm/components/FilePreview/FilePreview.css +39 -0
  85. package/esm/components/Header/Header.js +3 -16
  86. package/esm/components/Header/Header.js.map +1 -1
  87. package/esm/components/MediaWidget/LinkItemWidget.js +1 -1
  88. package/esm/components/MediaWidget/LinkItemWidget.js.map +1 -1
  89. package/esm/components/MediaWidget/MediaItemWidget.js +5 -9
  90. package/esm/components/MediaWidget/MediaItemWidget.js.map +1 -1
  91. package/esm/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js +65 -51
  92. package/esm/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js.map +1 -1
  93. package/esm/components/MemoriArtifactSystem/utils/ArtifactAPI.d.ts +5 -0
  94. package/esm/components/MemoriArtifactSystem/utils/ArtifactAPI.js +282 -0
  95. package/esm/components/MemoriArtifactSystem/utils/ArtifactAPI.js.map +1 -0
  96. package/esm/components/MemoriWidget/MemoriWidget.d.ts +12 -0
  97. package/esm/components/MemoriWidget/MemoriWidget.js +12 -3
  98. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  99. package/esm/components/Snippet/Snippet.js +4 -3
  100. package/esm/components/Snippet/Snippet.js.map +1 -1
  101. package/esm/components/StartPanel/StartPanel.css +14 -0
  102. package/esm/components/StartPanel/StartPanel.js +3 -3
  103. package/esm/components/StartPanel/StartPanel.js.map +1 -1
  104. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js +0 -21
  105. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  106. package/esm/components/VenueWidget/VenueWidget.js +0 -1
  107. package/esm/components/VenueWidget/VenueWidget.js.map +1 -1
  108. package/esm/components/layouts/HiddenChat.js +0 -15
  109. package/esm/components/layouts/HiddenChat.js.map +1 -1
  110. package/esm/components/layouts/chat.css +2 -2
  111. package/esm/context/visemeContext.js +0 -6
  112. package/esm/context/visemeContext.js.map +1 -1
  113. package/esm/helpers/constants.d.ts +11 -0
  114. package/esm/helpers/constants.js +22 -1
  115. package/esm/helpers/constants.js.map +1 -1
  116. package/esm/helpers/tts/useTTS.js +0 -3
  117. package/esm/helpers/tts/useTTS.js.map +1 -1
  118. package/esm/helpers/utils.d.ts +1 -0
  119. package/esm/helpers/utils.js +4 -0
  120. package/esm/helpers/utils.js.map +1 -1
  121. package/esm/index.js.map +1 -1
  122. package/esm/locales/de.json +2 -0
  123. package/esm/locales/en.json +2 -0
  124. package/esm/locales/es.json +2 -0
  125. package/esm/locales/fr.json +2 -0
  126. package/esm/locales/it.json +2 -0
  127. package/package.json +1 -1
  128. package/src/components/Avatar/AvatarView/AvatarComponent/avatarComponent.tsx +0 -1
  129. package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.tsx +0 -17
  130. package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.ts +0 -20
  131. package/src/components/Chat/Chat.css +31 -0
  132. package/src/components/Chat/Chat.stories.tsx +503 -9
  133. package/src/components/Chat/Chat.tsx +23 -3
  134. package/src/components/Chat/__snapshots__/Chat.test.tsx.snap +73 -73
  135. package/src/components/ChatBubble/ChatBubble.tsx +1 -2
  136. package/src/components/ChatBubble/__snapshots__/ChatBubble.test.tsx.snap +25 -25
  137. package/src/components/ChatInputs/ChatInputs.css +23 -0
  138. package/src/components/ChatInputs/ChatInputs.tsx +36 -14
  139. package/src/components/ChatTextArea/ChatTextArea.css +31 -0
  140. package/src/components/ChatTextArea/ChatTextArea.tsx +11 -1
  141. package/src/components/FilePreview/FilePreview.css +39 -0
  142. package/src/components/Header/Header.tsx +0 -13
  143. package/src/components/MediaWidget/LinkItemWidget.tsx +1 -1
  144. package/src/components/MediaWidget/MediaItemWidget.stories.tsx +33 -0
  145. package/src/components/MediaWidget/MediaItemWidget.tsx +7 -10
  146. package/src/components/MediaWidget/__snapshots__/LinkItemWidget.test.tsx.snap +4 -4
  147. package/src/components/MediaWidget/__snapshots__/MediaItemWidget.test.tsx.snap +6 -6
  148. package/src/components/MediaWidget/__snapshots__/MediaWidget.test.tsx.snap +2 -2
  149. package/src/components/MemoriArtifactSystem/ArtifactDrawer.stories.tsx +766 -2
  150. package/src/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.tsx +103 -89
  151. package/src/components/MemoriArtifactSystem/utils/ArtifactAPI.test.tsx +307 -0
  152. package/src/components/MemoriArtifactSystem/utils/ArtifactAPI.tsx +373 -0
  153. package/src/components/MemoriWidget/MemoriWidget.tsx +26 -4
  154. package/src/components/Snippet/Snippet.tsx +3 -2
  155. package/src/components/StartPanel/StartPanel.css +14 -0
  156. package/src/components/StartPanel/StartPanel.tsx +23 -10
  157. package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +206 -84
  158. package/src/components/UploadButton/UploadDocuments/UploadDocuments.tsx +0 -23
  159. package/src/components/VenueWidget/VenueWidget.tsx +0 -1
  160. package/src/components/layouts/HiddenChat.tsx +0 -16
  161. package/src/components/layouts/__snapshots__/Chat.test.tsx.snap +204 -82
  162. package/src/components/layouts/__snapshots__/FullPage.test.tsx.snap +408 -164
  163. package/src/components/layouts/__snapshots__/HiddenChat.test.tsx.snap +204 -82
  164. package/src/components/layouts/__snapshots__/Totem.test.tsx.snap +204 -82
  165. package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +204 -82
  166. package/src/components/layouts/chat.css +2 -2
  167. package/src/context/visemeContext.tsx +0 -7
  168. package/src/helpers/constants.ts +28 -3
  169. package/src/helpers/tts/useTTS.ts +0 -2
  170. package/src/helpers/utils.ts +5 -0
  171. package/src/index.tsx +0 -1
  172. package/src/locales/de.json +2 -0
  173. package/src/locales/en.json +2 -0
  174. package/src/locales/es.json +2 -0
  175. package/src/locales/fr.json +2 -0
  176. package/src/locales/it.json +2 -0
@@ -1,9 +1,10 @@
1
1
  // ArtifactSystem.stories.tsx
2
- import React from 'react';
2
+ import React, { useEffect } from 'react';
3
3
  import type { Meta, StoryObj } from '@storybook/react';
4
- import { ArtifactProvider } from './context/ArtifactContext';
4
+ import { ArtifactProvider, useArtifact } from './context/ArtifactContext';
5
5
  import ArtifactHandler from './components/ArtifactHandler/ArtifactHandler';
6
6
  import ArtifactDrawer from './components/ArtifactDrawer/ArtifactDrawer';
7
+ import { ArtifactAPIBridge } from './utils/ArtifactAPI';
7
8
  import Chat from '../Chat/Chat';
8
9
  import {
9
10
  Message,
@@ -11,6 +12,9 @@ import {
11
12
  Tenant,
12
13
  } from '@memori.ai/memori-api-client/dist/types';
13
14
  import { sanitizeText } from '../../helpers/sanitizer';
15
+ import { ArtifactData } from './types/artifact.types';
16
+
17
+ // Note: Window.MemoriArtifactAPI types are defined in MemoriWidget.tsx
14
18
 
15
19
  // Mock data for Chat component
16
20
  const mockMemori: Memori = {
@@ -69,6 +73,7 @@ const mockSetAttachmentsMenuOpen = (attachmentsMenuOpen: 'link' | 'media') => {
69
73
  // Story decorator to provide context
70
74
  const withArtifactProvider = (Story: any) => (
71
75
  <ArtifactProvider>
76
+ <ArtifactAPIBridge pushMessage={mockPushMessage} />
72
77
  <Story />
73
78
  </ArtifactProvider>
74
79
  );
@@ -578,6 +583,304 @@ This combination gives you a complete, styled web page ready for deployment.`,
578
583
  ),
579
584
  };
580
585
 
586
+ export const ThreeArtifactsInOneMessage: Story = {
587
+ args: {},
588
+ render: () => (
589
+ <Chat
590
+ memori={mockMemori}
591
+ tenant={mockTenant}
592
+ sessionID="test-session"
593
+ history={[
594
+ {
595
+ text: `I'll create a complete web component for you with HTML, CSS, and JavaScript:
596
+
597
+ <output class="memori-artifact" data-mimetype="html" data-title="Dashboard Component">
598
+ <!DOCTYPE html>
599
+ <html lang="en">
600
+ <head>
601
+ <meta charset="UTF-8">
602
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
603
+ <title>Dashboard</title>
604
+ </head>
605
+ <body>
606
+ <div id="dashboard" class="dashboard-container">
607
+ <h1>Sales Dashboard</h1>
608
+ <div class="stats-grid">
609
+ <div class="stat-card">
610
+ <h3>Revenue</h3>
611
+ <p id="revenue">$0</p>
612
+ </div>
613
+ <div class="stat-card">
614
+ <h3>Customers</h3>
615
+ <p id="customers">0</p>
616
+ </div>
617
+ <div class="stat-card">
618
+ <h3>Growth</h3>
619
+ <p id="growth">0%</p>
620
+ </div>
621
+ </div>
622
+ </div>
623
+ </body>
624
+ </html>
625
+ </output>
626
+
627
+ <output class="memori-artifact" data-mimetype="css" data-title="Dashboard Styles">
628
+ /* Dashboard Styles */
629
+ .dashboard-container {
630
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
631
+ max-width: 1200px;
632
+ margin: 0 auto;
633
+ padding: 40px 20px;
634
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
635
+ min-height: 100vh;
636
+ }
637
+
638
+ h1 {
639
+ color: white;
640
+ text-align: center;
641
+ font-size: 2.5rem;
642
+ margin-bottom: 40px;
643
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
644
+ }
645
+
646
+ .stats-grid {
647
+ display: grid;
648
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
649
+ gap: 24px;
650
+ margin-top: 30px;
651
+ }
652
+
653
+ .stat-card {
654
+ background: white;
655
+ border-radius: 16px;
656
+ padding: 32px;
657
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
658
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
659
+ text-align: center;
660
+ }
661
+
662
+ .stat-card:hover {
663
+ transform: translateY(-8px);
664
+ box-shadow: 0 15px 40px rgba(0, 0, 0, 0.3);
665
+ }
666
+
667
+ .stat-card h3 {
668
+ color: #667eea;
669
+ font-size: 1.2rem;
670
+ margin-bottom: 16px;
671
+ font-weight: 600;
672
+ text-transform: uppercase;
673
+ letter-spacing: 1px;
674
+ }
675
+
676
+ .stat-card p {
677
+ color: #333;
678
+ font-size: 2.5rem;
679
+ font-weight: bold;
680
+ margin: 0;
681
+ }
682
+ </output>
683
+
684
+ <output class="memori-artifact" data-mimetype="javascript" data-title="Dashboard Logic">
685
+ // Dashboard Data Management
686
+ class Dashboard {
687
+ constructor() {
688
+ this.data = {
689
+ revenue: 0,
690
+ customers: 0,
691
+ growth: 0
692
+ };
693
+ this.init();
694
+ }
695
+
696
+ init() {
697
+ // Simulate loading data
698
+ this.loadData();
699
+
700
+ // Update every 5 seconds
701
+ setInterval(() => this.updateData(), 5000);
702
+ }
703
+
704
+ loadData() {
705
+ // Simulate API call
706
+ this.data = {
707
+ revenue: 124500,
708
+ customers: 1234,
709
+ growth: 23.5
710
+ };
711
+ this.render();
712
+ }
713
+
714
+ updateData() {
715
+ // Simulate real-time updates
716
+ this.data.revenue += Math.floor(Math.random() * 1000);
717
+ this.data.customers += Math.floor(Math.random() * 10);
718
+ this.data.growth += (Math.random() - 0.5) * 2;
719
+ this.render();
720
+ }
721
+
722
+ render() {
723
+ const revenueEl = document.getElementById('revenue');
724
+ const customersEl = document.getElementById('customers');
725
+ const growthEl = document.getElementById('growth');
726
+
727
+ if (revenueEl) {
728
+ revenueEl.textContent = '$' + this.data.revenue.toLocaleString();
729
+ }
730
+
731
+ if (customersEl) {
732
+ customersEl.textContent = this.data.customers.toLocaleString();
733
+ }
734
+
735
+ if (growthEl) {
736
+ growthEl.textContent = '+' + this.data.growth.toFixed(1) + '%';
737
+ }
738
+ }
739
+ }
740
+
741
+ // Initialize when DOM is ready
742
+ if (document.readyState === 'loading') {
743
+ document.addEventListener('DOMContentLoaded', () => {
744
+ new Dashboard();
745
+ });
746
+ } else {
747
+ new Dashboard();
748
+ }
749
+ </output>
750
+
751
+ Each artifact serves a specific purpose:
752
+ - **HTML**: The structure and content
753
+ - **CSS**: Beautiful styling with gradients and animations
754
+ - **JavaScript**: Interactive data management and updates
755
+
756
+ You can click on each card to view and modify the code!`,
757
+ fromUser: false,
758
+ timestamp: new Date().toISOString(),
759
+ },
760
+ ]}
761
+ pushMessage={mockPushMessage}
762
+ simulateUserPrompt={mockSimulateUserPrompt}
763
+ onChangeUserMessage={mockOnChangeUserMessage}
764
+ sendMessage={mockSendMessage}
765
+ setEnableFocusChatInput={mockSetEnableFocusChatInput}
766
+ stopAudio={mockStopAudio}
767
+ startListening={mockStartListening}
768
+ stopListening={mockStopListening}
769
+ setSendOnEnter={mockSetSendOnEnter}
770
+ setAttachmentsMenuOpen={mockSetAttachmentsMenuOpen}
771
+ showInputs={false}
772
+ isChatlogPanel={false}
773
+ />
774
+ ),
775
+ };
776
+
777
+ export const FiveArtifactsMixedTypes: Story = {
778
+ args: {},
779
+ render: () => (
780
+ <Chat
781
+ memori={mockMemori}
782
+ tenant={mockTenant}
783
+ sessionID="test-session"
784
+ history={[
785
+ {
786
+ text: `Here's a complete project setup with multiple files:
787
+
788
+ <output class="memori-artifact" data-mimetype="html" data-title="index.html">
789
+ <!DOCTYPE html>
790
+ <html>
791
+ <head>
792
+ <title>My Project</title>
793
+ <link rel="stylesheet" href="styles.css">
794
+ </head>
795
+ <body>
796
+ <div id="app"></div>
797
+ <script src="app.js"></script>
798
+ </body>
799
+ </html>
800
+ </output>
801
+
802
+ <output class="memori-artifact" data-mimetype="css" data-title="styles.css">
803
+ body {
804
+ margin: 0;
805
+ padding: 20px;
806
+ font-family: Arial, sans-serif;
807
+ background: #f5f5f5;
808
+ }
809
+
810
+ #app {
811
+ max-width: 800px;
812
+ margin: 0 auto;
813
+ background: white;
814
+ padding: 30px;
815
+ border-radius: 8px;
816
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
817
+ }
818
+ </output>
819
+
820
+ <output class="memori-artifact" data-mimetype="javascript" data-title="app.js">
821
+ const app = document.getElementById('app');
822
+ app.innerHTML = '<h1>Hello World!</h1>';
823
+ console.log('App initialized');
824
+ </output>
825
+
826
+ <output class="memori-artifact" data-mimetype="json" data-title="package.json">
827
+ {
828
+ "name": "my-project",
829
+ "version": "1.0.0",
830
+ "description": "A simple web project",
831
+ "main": "app.js",
832
+ "scripts": {
833
+ "start": "serve .",
834
+ "build": "webpack"
835
+ },
836
+ "dependencies": {
837
+ "serve": "^14.0.0"
838
+ }
839
+ }
840
+ </output>
841
+
842
+ <output class="memori-artifact" data-mimetype="markdown" data-title="README.md">
843
+ # My Project
844
+
845
+ ## Overview
846
+ A simple web application starter template.
847
+
848
+ ## Getting Started
849
+ 1. Install dependencies: \`npm install\`
850
+ 2. Start the server: \`npm start\`
851
+ 3. Open http://localhost:3000
852
+
853
+ ## Features
854
+ - Clean HTML structure
855
+ - Modern CSS styling
856
+ - JavaScript functionality
857
+ - Package management with npm
858
+
859
+ ## License
860
+ MIT
861
+ </output>
862
+
863
+ All files are ready! You now have a complete project structure with HTML, CSS, JavaScript, configuration, and documentation.`,
864
+ fromUser: false,
865
+ timestamp: new Date().toISOString(),
866
+ },
867
+ ]}
868
+ pushMessage={mockPushMessage}
869
+ simulateUserPrompt={mockSimulateUserPrompt}
870
+ onChangeUserMessage={mockOnChangeUserMessage}
871
+ sendMessage={mockSendMessage}
872
+ setEnableFocusChatInput={mockSetEnableFocusChatInput}
873
+ stopAudio={mockStopAudio}
874
+ startListening={mockStartListening}
875
+ stopListening={mockStopListening}
876
+ setSendOnEnter={mockSetSendOnEnter}
877
+ setAttachmentsMenuOpen={mockSetAttachmentsMenuOpen}
878
+ showInputs={false}
879
+ isChatlogPanel={false}
880
+ />
881
+ ),
882
+ };
883
+
581
884
  export const ConversationFlow: Story = {
582
885
  args: {},
583
886
  render: () => (
@@ -670,3 +973,464 @@ export const NoArtifacts: Story = {
670
973
  />
671
974
  ),
672
975
  };
976
+
977
+ // ========================================
978
+ // ArtifactAPI Bridge Stories
979
+ // ========================================
980
+
981
+ export const APIBridge_CreateSimpleArtifact: Story = {
982
+ args: {},
983
+ render: () => {
984
+ const TestComponent = () => {
985
+ const { state } = useArtifact();
986
+
987
+ useEffect(() => {
988
+ // Wait a bit for the API to be available
989
+ setTimeout(() => {
990
+ console.log('MemoriArtifactAPI available:', !!window.MemoriArtifactAPI);
991
+ }, 100);
992
+ }, []);
993
+
994
+ const createHTMLArtifact = () => {
995
+ window.MemoriArtifactAPI?.createAndOpenArtifact(
996
+ '<h1>🎉 Created from API!</h1><p>This artifact was created using <code>window.MemoriArtifactAPI.createAndOpenArtifact()</code></p><p>You can use this API to create artifacts programmatically from any JavaScript code.</p>',
997
+ 'html',
998
+ 'API Test Artifact'
999
+ );
1000
+ };
1001
+
1002
+ const createMarkdownArtifact = () => {
1003
+ window.MemoriArtifactAPI?.createAndOpenArtifact(
1004
+ `# Artifact Created via API
1005
+
1006
+ ## This is a test
1007
+
1008
+ This artifact was created using the global API:
1009
+
1010
+ \`\`\`javascript
1011
+ window.MemoriArtifactAPI.createAndOpenArtifact(content, 'markdown', 'Title');
1012
+ \`\`\`
1013
+
1014
+ ### Features:
1015
+ - ✅ Programmatic control
1016
+ - ✅ Multiple MIME types
1017
+ - ✅ Easy integration`,
1018
+ 'markdown',
1019
+ 'API Markdown Example'
1020
+ );
1021
+ };
1022
+
1023
+ const createJavaScriptArtifact = () => {
1024
+ window.MemoriArtifactAPI?.createAndOpenArtifact(
1025
+ `// Example function created via API
1026
+ function greet(name) {
1027
+ console.log(\`Hello, \${name}!\`);
1028
+ return \`Welcome, \${name}\`;
1029
+ }
1030
+
1031
+ // Call it
1032
+ const message = greet('Developer');
1033
+ console.log(message);`,
1034
+ 'javascript',
1035
+ 'JavaScript via API'
1036
+ );
1037
+ };
1038
+
1039
+ const checkState = () => {
1040
+ const state = window.MemoriArtifactAPI?.getState();
1041
+ console.log('Current artifact state:', state);
1042
+ alert(JSON.stringify(state, null, 2));
1043
+ };
1044
+
1045
+ return (
1046
+ <>
1047
+ {/* Conditionally render ArtifactDrawer to avoid hooks error */}
1048
+ {state.isDrawerOpen && <ArtifactDrawer />}
1049
+
1050
+ <div style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}>
1051
+ <h1>🧪 Artifact API Test Lab</h1>
1052
+ <p>
1053
+ Test the global <code>window.MemoriArtifactAPI</code> by clicking the buttons below.
1054
+ Open the browser console to see the API in action.
1055
+ </p>
1056
+
1057
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '12px', marginTop: '20px' }}>
1058
+ <button
1059
+ onClick={createHTMLArtifact}
1060
+ style={{
1061
+ padding: '12px 20px',
1062
+ fontSize: '16px',
1063
+ cursor: 'pointer',
1064
+ backgroundColor: '#9333ea',
1065
+ color: 'white',
1066
+ border: 'none',
1067
+ borderRadius: '8px',
1068
+ }}
1069
+ >
1070
+ 📄 Create HTML Artifact
1071
+ </button>
1072
+
1073
+ <button
1074
+ onClick={createMarkdownArtifact}
1075
+ style={{
1076
+ padding: '12px 20px',
1077
+ fontSize: '16px',
1078
+ cursor: 'pointer',
1079
+ backgroundColor: '#7c3aed',
1080
+ color: 'white',
1081
+ border: 'none',
1082
+ borderRadius: '8px',
1083
+ }}
1084
+ >
1085
+ 📝 Create Markdown Artifact
1086
+ </button>
1087
+
1088
+ <button
1089
+ onClick={createJavaScriptArtifact}
1090
+ style={{
1091
+ padding: '12px 20px',
1092
+ fontSize: '16px',
1093
+ cursor: 'pointer',
1094
+ backgroundColor: '#6d28d9',
1095
+ color: 'white',
1096
+ border: 'none',
1097
+ borderRadius: '8px',
1098
+ }}
1099
+ >
1100
+ 💻 Create JavaScript Artifact
1101
+ </button>
1102
+
1103
+ <button
1104
+ onClick={checkState}
1105
+ style={{
1106
+ padding: '12px 20px',
1107
+ fontSize: '16px',
1108
+ cursor: 'pointer',
1109
+ backgroundColor: '#5b21b6',
1110
+ color: 'white',
1111
+ border: 'none',
1112
+ borderRadius: '8px',
1113
+ }}
1114
+ >
1115
+ 📊 Check Current State
1116
+ </button>
1117
+
1118
+ <button
1119
+ onClick={() => window.MemoriArtifactAPI?.closeArtifact()}
1120
+ style={{
1121
+ padding: '12px 20px',
1122
+ fontSize: '16px',
1123
+ cursor: 'pointer',
1124
+ backgroundColor: '#ef4444',
1125
+ color: 'white',
1126
+ border: 'none',
1127
+ borderRadius: '8px',
1128
+ }}
1129
+ >
1130
+ ❌ Close Artifact
1131
+ </button>
1132
+
1133
+ <button
1134
+ onClick={() => window.MemoriArtifactAPI?.toggleFullscreen()}
1135
+ style={{
1136
+ padding: '12px 20px',
1137
+ fontSize: '16px',
1138
+ cursor: 'pointer',
1139
+ backgroundColor: '#3b82f6',
1140
+ color: 'white',
1141
+ border: 'none',
1142
+ borderRadius: '8px',
1143
+ }}
1144
+ >
1145
+ ⛶ Toggle Fullscreen
1146
+ </button>
1147
+ </div>
1148
+
1149
+ <div style={{ marginTop: '30px', padding: '15px', backgroundColor: '#f3f4f6', borderRadius: '8px' }}>
1150
+ <h3>💡 Console Commands</h3>
1151
+ <p>Try these in the browser console:</p>
1152
+ <pre style={{ backgroundColor: 'white', padding: '10px', borderRadius: '4px', overflow: 'auto' }}>
1153
+ {`// Create an artifact
1154
+ window.MemoriArtifactAPI.createAndOpenArtifact(
1155
+ '<h1>Test</h1>',
1156
+ 'html',
1157
+ 'My Title'
1158
+ );
1159
+
1160
+ // Check state
1161
+ window.MemoriArtifactAPI.getState();
1162
+
1163
+ // Close
1164
+ window.MemoriArtifactAPI.closeArtifact();`}
1165
+ </pre>
1166
+ </div>
1167
+ </div>
1168
+ </>
1169
+ );
1170
+ };
1171
+
1172
+ return <TestComponent />;
1173
+ },
1174
+ };
1175
+
1176
+ export const APIBridge_ProcessOutputElements: Story = {
1177
+ args: {},
1178
+ render: () => {
1179
+ const TestComponent = () => {
1180
+ const { state } = useArtifact();
1181
+
1182
+ const createFromOutput = () => {
1183
+ const outputs = document.querySelectorAll('.memori-artifact[data-sample="true"]');
1184
+ outputs.forEach((output) => {
1185
+ const artifactId = window.MemoriArtifactAPI?.createFromOutputElement(output as HTMLOutputElement);
1186
+ console.log('Created artifact:', artifactId);
1187
+ });
1188
+ alert(`Processed ${outputs.length} artifacts. Check console for IDs.`);
1189
+ };
1190
+
1191
+ const addDynamicOutput = () => {
1192
+ const container = document.getElementById('dynamic-container');
1193
+ if (container) {
1194
+ const output = document.createElement('output');
1195
+ output.className = 'memori-artifact';
1196
+ output.setAttribute('data-mimetype', 'html');
1197
+ output.setAttribute('data-title', 'Dynamic Artifact');
1198
+ output.setAttribute('data-sample', 'true');
1199
+ output.innerHTML = `
1200
+ <div style="padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 8px;">
1201
+ <h2>🚀 Dynamically Added!</h2>
1202
+ <p>This artifact was added to the DOM dynamically and then processed.</p>
1203
+ <p>Timestamp: ${new Date().toLocaleTimeString()}</p>
1204
+ </div>
1205
+ `;
1206
+ container.appendChild(output);
1207
+ }
1208
+ };
1209
+
1210
+ return (
1211
+ <>
1212
+ {/* Conditionally render ArtifactDrawer to avoid hooks error */}
1213
+ {state.isDrawerOpen && <ArtifactDrawer />}
1214
+
1215
+ <div style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}>
1216
+ <h1>🔄 Process Output Elements</h1>
1217
+ <p>
1218
+ This story demonstrates processing <code>&lt;output class=&quot;memori-artifact&quot;&gt;</code> elements
1219
+ using <code>createFromOutputElement</code>.
1220
+ </p>
1221
+
1222
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '12px', marginTop: '20px' }}>
1223
+ <button
1224
+ onClick={createFromOutput}
1225
+ style={{
1226
+ padding: '12px 20px',
1227
+ fontSize: '16px',
1228
+ cursor: 'pointer',
1229
+ backgroundColor: '#9333ea',
1230
+ color: 'white',
1231
+ border: 'none',
1232
+ borderRadius: '8px',
1233
+ }}
1234
+ >
1235
+ 🔍 Create From Output Elements
1236
+ </button>
1237
+
1238
+ <button
1239
+ onClick={addDynamicOutput}
1240
+ style={{
1241
+ padding: '12px 20px',
1242
+ fontSize: '16px',
1243
+ cursor: 'pointer',
1244
+ backgroundColor: '#7c3aed',
1245
+ color: 'white',
1246
+ border: 'none',
1247
+ borderRadius: '8px',
1248
+ }}
1249
+ >
1250
+ ➕ Add Dynamic Output
1251
+ </button>
1252
+ </div>
1253
+
1254
+ <div id="dynamic-container" style={{ marginTop: '30px' }}>
1255
+ <h3>Existing Output Elements:</h3>
1256
+
1257
+ <output className="memori-artifact" data-mimetype="html" data-title="Sample HTML" data-sample="true">
1258
+ <div style={{ padding: '15px', border: '2px solid #9333ea', borderRadius: '8px' }}>
1259
+ <h3>Sample Artifact 1</h3>
1260
+ <p>This is a static output element in the DOM.</p>
1261
+ </div>
1262
+ </output>
1263
+
1264
+ <output className="memori-artifact" data-mimetype="markdown" data-title="Sample Markdown" data-sample="true">
1265
+ {`# Sample Markdown
1266
+
1267
+ This is **another** static output element.
1268
+
1269
+ - Item 1
1270
+ - Item 2
1271
+ - Item 3`}
1272
+ </output>
1273
+ </div>
1274
+
1275
+ <div style={{ marginTop: '30px', padding: '15px', backgroundColor: '#f3f4f6', borderRadius: '8px' }}>
1276
+ <h3>💡 How it works</h3>
1277
+ <ol>
1278
+ <li>Click &quot;Create From Output Elements&quot; to process <code>&lt;output&gt;</code> elements</li>
1279
+ <li>Each element gets converted to an artifact and added to history</li>
1280
+ <li>Click &quot;Add Dynamic Output&quot; to inject a new element</li>
1281
+ <li>Process again to handle the new element</li>
1282
+ <li>The artifacts will appear in the chat history</li>
1283
+ </ol>
1284
+ </div>
1285
+ </div>
1286
+ </>
1287
+ );
1288
+ };
1289
+
1290
+ return <TestComponent />;
1291
+ },
1292
+ };
1293
+
1294
+ export const APIBridge_WebSocketSimulation: Story = {
1295
+ args: {},
1296
+ render: () => {
1297
+ const TestComponent = () => {
1298
+ const { state } = useArtifact();
1299
+
1300
+ const simulateWebSocket = () => {
1301
+ // Simulate receiving a message with artifacts from WebSocket
1302
+ const artifactContent = `
1303
+ <div style="padding: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
1304
+ <h2>📊 Sales Report Q4 2024</h2>
1305
+ <div style="display: flex; gap: 20px; margin-top: 20px;">
1306
+ <div style="flex: 1; padding: 15px; background: #ecfdf5; border-radius: 8px;">
1307
+ <h3>Revenue</h3>
1308
+ <p style="font-size: 24px; font-weight: bold; color: #059669;">$124,500</p>
1309
+ </div>
1310
+ <div style="flex: 1; padding: 15px; background: #fef3c7; border-radius: 8px;">
1311
+ <h3>Customers</h3>
1312
+ <p style="font-size: 24px; font-weight: bold; color: #d97706;">1,234</p>
1313
+ </div>
1314
+ <div style="flex: 1; padding: 15px; background: #dbeafe; border-radius: 8px;">
1315
+ <h3>Growth</h3>
1316
+ <p style="font-size: 24px; font-weight: bold; color: #2563eb;">+23%</p>
1317
+ </div>
1318
+ </div>
1319
+ </div>
1320
+ `;
1321
+
1322
+ // Use the API to create and open the artifact
1323
+ window.MemoriArtifactAPI?.createAndOpenArtifact(
1324
+ artifactContent,
1325
+ 'html',
1326
+ 'Data Visualization'
1327
+ );
1328
+
1329
+ // Update chat display
1330
+ const chatContainer = document.getElementById('chat-simulation');
1331
+ if (chatContainer) {
1332
+ const messageHTML = `
1333
+ <div style="padding: 10px; margin: 10px 0; background: #f9fafb; border-radius: 8px;">
1334
+ <p><strong>Bot:</strong> I've created a visualization for you. Click the artifact card to view it.</p>
1335
+ <div style="padding: 10px; margin-top: 10px; background: #e0e7ff; border-radius: 4px; cursor: pointer;" onclick="window.MemoriArtifactAPI?.createAndOpenArtifact(\`${artifactContent.replace(/`/g, '\\`')}\`, 'html', 'Data Visualization')">
1336
+ 📊 Data Visualization
1337
+ </div>
1338
+ </div>
1339
+ `;
1340
+ chatContainer.innerHTML += messageHTML;
1341
+ }
1342
+
1343
+ console.log('WebSocket artifact created via API');
1344
+ };
1345
+
1346
+ const clearChat = () => {
1347
+ const chatContainer = document.getElementById('chat-simulation');
1348
+ if (chatContainer) {
1349
+ chatContainer.innerHTML = '<p style="color: #6b7280;">Chat cleared. Click "Simulate WebSocket Message" to add new content.</p>';
1350
+ }
1351
+ };
1352
+
1353
+ return (
1354
+ <>
1355
+ {/* Conditionally render ArtifactDrawer to avoid hooks error */}
1356
+ {state.isDrawerOpen && <ArtifactDrawer />}
1357
+
1358
+ <div style={{ padding: '20px', maxWidth: '900px', margin: '0 auto' }}>
1359
+ <h1>🌐 WebSocket Integration Simulation</h1>
1360
+ <p>
1361
+ This demonstrates how <code>createAndOpenArtifact</code> can be used with WebSocket or Action Cable
1362
+ to create artifacts from messages received dynamically.
1363
+ </p>
1364
+
1365
+ <div style={{ display: 'flex', gap: '12px', marginTop: '20px' }}>
1366
+ <button
1367
+ onClick={simulateWebSocket}
1368
+ style={{
1369
+ padding: '12px 20px',
1370
+ fontSize: '16px',
1371
+ cursor: 'pointer',
1372
+ backgroundColor: '#9333ea',
1373
+ color: 'white',
1374
+ border: 'none',
1375
+ borderRadius: '8px',
1376
+ }}
1377
+ >
1378
+ 📡 Simulate WebSocket Message
1379
+ </button>
1380
+
1381
+ <button
1382
+ onClick={clearChat}
1383
+ style={{
1384
+ padding: '12px 20px',
1385
+ fontSize: '16px',
1386
+ cursor: 'pointer',
1387
+ backgroundColor: '#64748b',
1388
+ color: 'white',
1389
+ border: 'none',
1390
+ borderRadius: '8px',
1391
+ }}
1392
+ >
1393
+ 🗑️ Clear Chat
1394
+ </button>
1395
+ </div>
1396
+
1397
+ <div
1398
+ id="chat-simulation"
1399
+ style={{
1400
+ marginTop: '30px',
1401
+ padding: '20px',
1402
+ backgroundColor: 'white',
1403
+ border: '1px solid #e5e7eb',
1404
+ borderRadius: '12px',
1405
+ minHeight: '200px',
1406
+ }}
1407
+ >
1408
+ <p style={{ color: '#6b7280' }}>Click &quot;Simulate WebSocket Message&quot; to receive a message with an artifact...</p>
1409
+ </div>
1410
+
1411
+ <div style={{ marginTop: '30px', padding: '15px', backgroundColor: '#f3f4f6', borderRadius: '8px' }}>
1412
+ <h3>💡 Implementation Example</h3>
1413
+ <pre style={{ backgroundColor: 'white', padding: '10px', borderRadius: '4px', overflow: 'auto', fontSize: '13px' }}>
1414
+ {`// Rails Action Cable
1415
+ consumer.subscriptions.create("ChatChannel", {
1416
+ received(data) {
1417
+ if (data.artifact) {
1418
+ // Create artifact directly from received data
1419
+ window.MemoriArtifactAPI?.createAndOpenArtifact(
1420
+ data.artifact.content,
1421
+ data.artifact.mimeType,
1422
+ data.artifact.title
1423
+ );
1424
+ }
1425
+ }
1426
+ });`}
1427
+ </pre>
1428
+ </div>
1429
+ </div>
1430
+ </>
1431
+ );
1432
+ };
1433
+
1434
+ return <TestComponent />;
1435
+ },
1436
+ };