astro-tractstack 2.0.10 → 2.0.12

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.
@@ -1,107 +0,0 @@
1
- import { useState } from 'react';
2
- import { AddPanePanel_newAICopy_modal } from './AddPanePanel_newAICopy_modal';
3
- import { panePrompts, contextPanePrompts } from '@/constants/prompts.json';
4
-
5
- interface AddPaneNewAICopyProps {
6
- onChange: (value: string) => void;
7
- isContextPane: boolean;
8
- }
9
-
10
- export const AddPanePanel_newAICopy = ({
11
- onChange,
12
- isContextPane,
13
- }: AddPaneNewAICopyProps) => {
14
- const [customizedPrompt, setCustomizedPrompt] = useState(
15
- isContextPane
16
- ? contextPanePrompts.shortformcontext
17
- : panePrompts.shortformcontext
18
- );
19
- const [referenceContext, setReferenceContext] = useState('');
20
- const [additionalInstructions, setAdditionalInstructions] = useState('');
21
- const [showModal, setShowModal] = useState(false);
22
-
23
- const handleGenerate = () => {
24
- setShowModal(true);
25
- };
26
-
27
- const handleModalClose = () => {
28
- setShowModal(false);
29
- };
30
-
31
- const handleContentGenerated = (content: string) => {
32
- onChange(content);
33
- setShowModal(false);
34
- };
35
-
36
- return (
37
- <div className="w-full rounded-lg bg-white shadow">
38
- <div className="space-y-6 p-6">
39
- <div>
40
- <label className="mb-2 block text-sm font-bold text-gray-900">
41
- Customize Writing Style (Optional)
42
- </label>
43
- <textarea
44
- rows={6}
45
- className="w-full rounded-md border-gray-300 p-3.5 shadow-sm focus:border-cyan-500 focus:ring-cyan-500"
46
- value={customizedPrompt}
47
- onChange={(e) => setCustomizedPrompt(e.target.value)}
48
- maxLength={1000}
49
- />
50
- </div>
51
-
52
- <div>
53
- <label className="block text-sm font-bold text-gray-900">
54
- Reference Content &ndash; copy and paste dump here; no formatting
55
- required...
56
- </label>
57
- <textarea
58
- rows={8}
59
- className="w-full rounded-md border-gray-300 p-3.5 shadow-sm focus:border-cyan-500 focus:ring-cyan-500"
60
- value={referenceContext}
61
- onChange={(e) => setReferenceContext(e.target.value)}
62
- maxLength={200000}
63
- placeholder="Paste your reference content here..."
64
- />
65
- </div>
66
-
67
- <div>
68
- <label className="mb-2 block text-sm font-bold text-gray-900">
69
- Additional Instructions (Optional)
70
- </label>
71
- <textarea
72
- rows={4}
73
- className="w-full rounded-md border-gray-300 p-3.5 shadow-sm focus:border-cyan-500 focus:ring-cyan-500"
74
- value={additionalInstructions}
75
- onChange={(e) => setAdditionalInstructions(e.target.value)}
76
- maxLength={2000}
77
- placeholder="Any additional instructions or requirements..."
78
- />
79
- </div>
80
-
81
- <div className="flex justify-end">
82
- <button
83
- onClick={handleGenerate}
84
- disabled={!referenceContext.trim()}
85
- className={`rounded-md px-4 py-2 text-sm font-bold text-white focus:outline-none focus:ring-2 focus:ring-cyan-500 focus:ring-offset-2 ${
86
- referenceContext.trim()
87
- ? 'bg-cyan-600 hover:bg-cyan-700'
88
- : 'cursor-not-allowed bg-gray-300'
89
- }`}
90
- >
91
- Generate Content
92
- </button>
93
- </div>
94
- </div>
95
-
96
- <AddPanePanel_newAICopy_modal
97
- show={showModal}
98
- onClose={handleModalClose}
99
- prompt={customizedPrompt}
100
- referenceContext={referenceContext}
101
- additionalInstructions={additionalInstructions}
102
- onChange={handleContentGenerated}
103
- isContextPane={isContextPane}
104
- />
105
- </div>
106
- );
107
- };
@@ -1,217 +0,0 @@
1
- import { useRef, useState, useEffect } from 'react';
2
- import { Dialog } from '@ark-ui/react/dialog';
3
- import { Portal } from '@ark-ui/react/portal';
4
- import { paneFormatPrompt, formatPrompt } from '@/constants/prompts.json';
5
-
6
- type GenerationStatus = 'idle' | 'generating' | 'success' | 'error';
7
-
8
- interface AddPaneNewAICopyModalProps {
9
- show: boolean;
10
- onClose: () => void;
11
- prompt: string;
12
- referenceContext: string;
13
- additionalInstructions: string;
14
- onChange: (value: string) => void;
15
- isContextPane: boolean;
16
- }
17
-
18
- export const AddPanePanel_newAICopy_modal = ({
19
- show,
20
- onClose,
21
- prompt,
22
- referenceContext,
23
- additionalInstructions,
24
- onChange,
25
- isContextPane,
26
- }: AddPaneNewAICopyModalProps) => {
27
- const [generationStatus, setGenerationStatus] =
28
- useState<GenerationStatus>('idle');
29
- const [error, setError] = useState<string | null>(null);
30
- const [generatedContent, setGeneratedContent] = useState<string | null>(null);
31
- const dialogButtonRef = useRef<HTMLButtonElement>(null);
32
-
33
- const handleModalClose = (details: { open: boolean }) => {
34
- if (generationStatus === 'generating') {
35
- return;
36
- }
37
- if (generationStatus === 'success' && generatedContent && !details.open) {
38
- onChange(generatedContent);
39
- onClose();
40
- setGenerationStatus('idle');
41
- setGeneratedContent(null);
42
- setError(null);
43
- return;
44
- }
45
- onClose();
46
- setGenerationStatus('idle');
47
- };
48
-
49
- const handleButtonClick = () => {
50
- if (generationStatus === 'success' && generatedContent) {
51
- onChange(generatedContent);
52
- onClose();
53
- setGenerationStatus('idle');
54
- setGeneratedContent(null);
55
- setError(null);
56
- } else if (generationStatus === 'error') {
57
- onClose();
58
- setGenerationStatus('idle');
59
- }
60
- };
61
-
62
- const handleGenerate = async () => {
63
- setGenerationStatus('generating');
64
- setError(null);
65
-
66
- const finalPrompt = `${isContextPane ? formatPrompt : paneFormatPrompt}
67
-
68
- Writing Style Instructions:
69
- ${prompt}
70
-
71
- Additional Instructions:
72
- ${additionalInstructions}`;
73
-
74
- try {
75
- const goBackend =
76
- import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
77
- const tenantId = import.meta.env.PUBLIC_TENANTID || 'default';
78
-
79
- const response = await fetch(`${goBackend}/api/v1/aai/askLemur`, {
80
- method: 'POST',
81
- headers: {
82
- 'Content-Type': 'application/json',
83
- 'X-Tenant-ID': tenantId,
84
- },
85
- credentials: 'include',
86
- body: JSON.stringify({
87
- prompt: finalPrompt,
88
- input_text: referenceContext,
89
- final_model: 'anthropic/claude-3-5-sonnet',
90
- temperature: 0.7,
91
- max_tokens: 4000,
92
- }),
93
- });
94
-
95
- if (!response.ok) {
96
- throw new Error('Generation failed');
97
- }
98
-
99
- const result = await response.json();
100
-
101
- if (!result.success || !result.data?.response) {
102
- throw new Error(result.error || 'Generation failed');
103
- }
104
-
105
- let content = result.data.response;
106
- if (typeof content === 'object') {
107
- content = JSON.stringify(content, null, 2);
108
- }
109
-
110
- setGeneratedContent(content);
111
- setGenerationStatus('success');
112
- } catch (err) {
113
- setError(err instanceof Error ? err.message : 'An error occurred');
114
- setGenerationStatus('error');
115
- }
116
- };
117
-
118
- useEffect(() => {
119
- if (show && generationStatus === 'idle') {
120
- handleGenerate();
121
- }
122
- }, [show]);
123
-
124
- const dialogStyles = `
125
- [data-part="backdrop"] {
126
- background-color: rgba(0, 0, 0, 0.3);
127
- }
128
- [data-part="content"] {
129
- background-color: white;
130
- border-radius: 1rem;
131
- box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
132
- padding: 1.5rem;
133
- max-width: 42rem;
134
- width: 100%;
135
- }
136
- [data-part="title"] {
137
- font-size: 1.125rem;
138
- font-weight: bold;
139
- color: #1f2937;
140
- }
141
- `;
142
-
143
- return (
144
- <>
145
- <style>{dialogStyles}</style>
146
- <Dialog.Root open={show} onOpenChange={handleModalClose}>
147
- <Portal>
148
- <Dialog.Backdrop className="fixed inset-0" />
149
- <Dialog.Positioner className="fixed inset-0 z-50 flex items-center justify-center p-4">
150
- <Dialog.Content className="overflow-hidden text-left">
151
- <Dialog.Title className="text-lg font-bold leading-6 text-gray-900">
152
- {generationStatus === 'error'
153
- ? 'Generation Error'
154
- : generationStatus === 'success'
155
- ? 'Content Generated'
156
- : 'Generating Content'}
157
- </Dialog.Title>
158
-
159
- <div className="mt-4">
160
- {generationStatus === 'error' ? (
161
- <p className="text-sm text-red-600">{error}</p>
162
- ) : generationStatus === 'success' ? (
163
- <div className="space-y-4">
164
- <p className="text-sm text-gray-600">
165
- Content has been generated successfully! Click "Apply
166
- Content" to use this content with your selected design.
167
- </p>
168
- <div className="overflow-y-auto rounded-md border border-gray-200 bg-gray-50 p-4">
169
- <pre className="whitespace-pre-wrap font-mono text-sm text-gray-800">
170
- {generatedContent}
171
- </pre>
172
- </div>
173
- </div>
174
- ) : (
175
- <div className="flex items-center gap-3">
176
- <div className="h-5 w-5 animate-spin rounded-full border-b-2 border-cyan-600"></div>
177
- <p className="text-sm text-gray-500">
178
- Generating your content...
179
- </p>
180
- </div>
181
- )}
182
- </div>
183
-
184
- <div className="mt-6 flex justify-end gap-3">
185
- {generationStatus !== 'generating' && (
186
- <button
187
- type="button"
188
- className="rounded-md border border-gray-300 bg-gray-100 px-4 py-2 text-sm font-bold text-gray-700 hover:bg-gray-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-gray-500 focus-visible:ring-offset-2"
189
- onClick={() => {
190
- onClose();
191
- setGenerationStatus('idle');
192
- }}
193
- >
194
- Cancel
195
- </button>
196
- )}
197
- <button
198
- ref={dialogButtonRef}
199
- type="button"
200
- className="inline-flex justify-center rounded-md border border-transparent bg-cyan-600 px-4 py-2 text-sm font-bold text-white hover:bg-cyan-700 focus:outline-none focus-visible:ring-2 focus-visible:ring-cyan-500 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:bg-gray-300"
201
- onClick={handleButtonClick}
202
- disabled={generationStatus === 'generating'}
203
- >
204
- {generationStatus === 'error'
205
- ? 'Try Again'
206
- : generationStatus === 'success'
207
- ? 'Apply Content'
208
- : 'Please Wait...'}
209
- </button>
210
- </div>
211
- </Dialog.Content>
212
- </Dialog.Positioner>
213
- </Portal>
214
- </Dialog.Root>
215
- </>
216
- );
217
- };
@@ -1,109 +0,0 @@
1
- import { RadioGroup } from '@ark-ui/react/radio-group';
2
- import CheckCircleIcon from '@heroicons/react/24/outline/CheckCircleIcon';
3
- import { hasAssemblyAIStore } from '@/stores/storykeep';
4
-
5
- export type CopyMode = 'design' | 'ai' | 'custom' | 'blank';
6
-
7
- interface AddPaneNewCopyModeProps {
8
- selected: CopyMode;
9
- onChange: (mode: CopyMode) => void;
10
- }
11
-
12
- export const AddPaneNewCopyMode = ({
13
- selected,
14
- onChange,
15
- }: AddPaneNewCopyModeProps) => {
16
- const hasAssemblyAI = hasAssemblyAIStore.get();
17
-
18
- const baseModesConfig = [
19
- {
20
- id: 'design',
21
- name: 'Quick start',
22
- description: 'Use pre-designed copy templates',
23
- },
24
- {
25
- id: 'custom',
26
- name: 'Provide your own Copy',
27
- description: 'Write your own markdown content',
28
- },
29
- {
30
- id: 'blank',
31
- name: 'Blank',
32
- description: 'Start with a styled blank slate',
33
- },
34
- ];
35
-
36
- const aiModeConfig = {
37
- id: 'ai',
38
- name: 'Write with AI',
39
- description: 'Let AI help write your content',
40
- };
41
-
42
- // Include "ai" mode only if hasAssemblyAI is true
43
- const modes = hasAssemblyAI
44
- ? [baseModesConfig[0], aiModeConfig, ...baseModesConfig.slice(1)]
45
- : baseModesConfig;
46
-
47
- // Custom styles for the radio group component
48
- const radioGroupStyles = `
49
- .radio-control[data-state="unchecked"] .radio-dot {
50
- background-color: #d1d5db; /* gray-300 */
51
- }
52
- .radio-control[data-state="checked"] .radio-dot {
53
- background-color: #0891b2; /* bg-cyan-600 */
54
- }
55
- .radio-control[data-state="checked"] {
56
- border-color: #0891b2; /* bg-cyan-600 */
57
- }
58
- .radio-item[data-state="checked"] {
59
- background-color: #0891b2; /* bg-cyan-600 */
60
- color: white;
61
- }
62
- .radio-item:hover:not([data-state="checked"]) {
63
- background-color: #f3f4f6; /* bg-gray-100 */
64
- }
65
- `;
66
-
67
- return (
68
- <div className="w-full pr-4">
69
- <style>{radioGroupStyles}</style>
70
- <div className="max-w-4xl">
71
- <RadioGroup.Root
72
- defaultValue={selected}
73
- onValueChange={(details) => {
74
- if (details.value) {
75
- onChange(details.value as CopyMode);
76
- }
77
- }}
78
- >
79
- <RadioGroup.Label className="sr-only">Copy Mode</RadioGroup.Label>
80
- <div className="grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3">
81
- {modes.map((mode) => (
82
- <RadioGroup.Item
83
- key={mode.id}
84
- value={mode.id}
85
- className="radio-item relative flex cursor-pointer rounded-lg px-5 py-4 shadow-md focus:outline-none"
86
- >
87
- <div className="flex w-full items-center justify-between">
88
- <div className="flex items-center">
89
- <RadioGroup.ItemText>
90
- <div className="text-sm">
91
- <p className="font-bold">{mode.name}</p>
92
- <span className="inline">{mode.description}</span>
93
- </div>
94
- </RadioGroup.ItemText>
95
- </div>
96
- <div className="hidden shrink-0 data-[state=checked]:block">
97
- <CheckCircleIcon className="h-6 w-6" />
98
- </div>
99
- </div>
100
- <RadioGroup.ItemControl className="hidden" />
101
- <RadioGroup.ItemHiddenInput />
102
- </RadioGroup.Item>
103
- ))}
104
- </div>
105
- </RadioGroup.Root>
106
- </div>
107
- </div>
108
- );
109
- };