Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import { useState } from 'react';
import TextField from '@mui/material/TextField';
import FormItemWrapper from '../components/shared/FormItemWrapper';
import Tip from '../../Tip';
import { FieldAIAssistButton } from '../FieldAIAssistButton';
import { useField } from '../useField';
import type { StringField as StringFieldConfig } from '@quiqr/types';
interface Props {
compositeKey: string;
}
/**
* StringField - text input with optional multiLine support.
* Includes AI assist integration and insert buttons.
*/
function StringField({ compositeKey }: Props) {
const { field, value, setValue, meta } = useField<string>(compositeKey);
const config = field as StringFieldConfig;
const [localValue, setLocalValue] = useState(value ?? config.default ?? '');
// Sync local value when external value changes
Iif (value !== undefined && value !== localValue) {
setLocalValue(value);
}
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
setLocalValue(e.target.value);
setValue(e.target.value, 0);
};
const iconButtons: React.ReactNode[] = [];
Iif (config.tip) {
iconButtons.push(<Tip key="tip" markdown={config.tip} />);
}
Iif (config.txtInsertButtons) {
const insertButtons = config.txtInsertButtons.map((text, idx) => (
<button
key={idx}
onClick={() => {
setLocalValue(text);
setValue(text, 250);
}}
>
{text}
</button>
));
iconButtons.push(<span key="insert-buttons">{insertButtons}</span>);
}
// New field-level AI assist (template-based)
Iif (config.field_prompt_templates && config.field_prompt_templates.length > 0) {
// Determine if we're in a single or collection context
const isCollection = meta.collectionKey && meta.collectionItemKey;
iconButtons.push(
<FieldAIAssistButton
key="field-ai-assist"
fieldKey={config.key}
fieldType="string"
fieldContent={localValue}
availableTemplates={config.field_prompt_templates}
onReplace={(text: string) => {
setLocalValue(text);
setValue(text, 0);
}}
onAppend={(text: string) => {
const newValue = localValue ? `${localValue}\n${text}` : text;
setLocalValue(newValue);
setValue(newValue, 0);
}}
siteKey={meta.siteKey}
workspaceKey={meta.workspaceKey}
collectionKey={isCollection ? meta.collectionKey : undefined}
collectionItemKey={isCollection ? meta.collectionItemKey : undefined}
singleKey={!isCollection ? meta.collectionItemKey : undefined}
/>
);
}
return (
<FormItemWrapper
control={
<TextField
id={`text-field-${config.key}`}
onChange={handleChange}
value={localValue}
multiline={config.multiLine === true}
fullWidth
label={config.title ?? config.key}
/>
}
iconButtons={iconButtons}
/>
);
}
export default StringField;
|