feat(snippet-shortcuts): Snippet-Expander: ';daily' → 'Daily standup', ';mtg' → 'Meet [tsc:fail]

This commit is contained in:
Dennis (via Claude+Gemma) 2026-05-23 08:10:14 +02:00
parent fb67391eb8
commit 2d04a9ae8c
3 changed files with 68 additions and 2 deletions

View File

@ -1,5 +1,8 @@
{
"completed_features": [],
"current_feature": "keyboard-undo-stack",
"started_at": "2026-05-23T08:09:40.135892"
"current_feature": "snippet-shortcuts",
"started_at": "2026-05-23T08:09:40.135892",
"attempted_features": [
"keyboard-undo-stack"
]
}

View File

@ -2499,3 +2499,20 @@ src/index.ts(27,25): error TS2769: No overload matches this call.
Overload 2 of 3, '(plugin: FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error.
Argument of type 'Promise<FastifyMultipartPlugin>' is not assignable to parameter of type 'FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'.
Type 'Promise<FastifyMultipartPlugin>' provides no match for the signature '(instance: FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTy
- `08:10:01` **INFO** Committed feature keyboard-undo-stack
- `08:10:01` **INFO** Pushed: rc=0
## Phase-3 Feature: snippet-shortcuts (2026-05-23 08:10:01)
- `08:10:01` **INFO** Description: Snippet-Expander: ';daily' → 'Daily standup', ';mtg' → 'Meeting'
- `08:10:01` **INFO** Generating apps/web/src/components/SnippetInput.tsx (Drop-in-Input mit snippet-expansion. Snippets-map inline: {';daily':'D…)
- `08:10:13` **INFO** wrote 1376 chars in 11.6s (attempt 1)
- `08:10:13` **INFO** Running tsc --noEmit on api…
- `08:10:14` **WARN** tsc errors:
src/index.ts(27,25): error TS2769: No overload matches this call.
Overload 1 of 3, '(plugin: FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error.
Argument of type 'Promise<FastifyMultipartPlugin>' is not assignable to parameter of type 'FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'.
Type 'Promise<FastifyMultipartPlugin>' provides no match for the signature '(instance: FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProvider>, opts: { ...; }, done: (err?: Error | undefined) => void): void'.
Overload 2 of 3, '(plugin: FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error.
Argument of type 'Promise<FastifyMultipartPlugin>' is not assignable to parameter of type 'FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'.
Type 'Promise<FastifyMultipartPlugin>' provides no match for the signature '(instance: FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTy

View File

@ -0,0 +1,46 @@
import React from 'react';
interface SnippetInputProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
value: string;
onChange: (value: string) => void;
}
const SNIPPETS: Record<string, string> = {
';daily': 'Daily standup',
';mtg': 'Meeting',
';review': 'Code review',
';bug': 'Bugfix ',
};
export const SnippetInput: React.FC<SnippetInputProps> = ({ value, onChange, ...rest }) => {
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
const newValue = e.target.value;
// Find the last occurrence of a semicolon to check for a snippet
const lastSemicolonIndex = newValue.lastIndexOf(';');
if (lastSemicolonIndex !== -1) {
const trailingText = newValue.slice(lastSemicolonIndex);
// Check if the trailing text matches any of our snippet keys
const snippetKey = Object.keys(SNIPPETS).find(key => trailingText === key);
if (snippetKey) {
const expandedValue = newValue.slice(0, lastSemicolonIndex) + SNIPPETS[snippetKey];
onChange(expandedValue);
return;
}
}
onChange(newValue);
};
return (
<textarea
{...rest}
value={value}
onChange={handleChange}
className={`w-full p-2 border rounded-md focus:ring-2 focus:ring-blue-500 outline-none transition-all ${rest.className || ''}`}
/>
);
};