From 2d04a9ae8c54c7004d4aa3cc1586a253652525ed Mon Sep 17 00:00:00 2001 From: "Dennis (via Claude+Gemma)" Date: Sat, 23 May 2026 08:10:14 +0200 Subject: [PATCH] =?UTF-8?q?feat(snippet-shortcuts):=20Snippet-Expander:=20?= =?UTF-8?q?';daily'=20=E2=86=92=20'Daily=20standup',=20';mtg'=20=E2=86=92?= =?UTF-8?q?=20'Meet=20[tsc:fail]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .phase21-state.json | 7 ++-- GENERATION_LOG.md | 17 +++++++++ apps/web/src/components/SnippetInput.tsx | 46 ++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 apps/web/src/components/SnippetInput.tsx diff --git a/.phase21-state.json b/.phase21-state.json index 1361727..43e54e1 100644 --- a/.phase21-state.json +++ b/.phase21-state.json @@ -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" + ] } \ No newline at end of file diff --git a/GENERATION_LOG.md b/GENERATION_LOG.md index 8704d96..3f94336 100644 --- a/GENERATION_LOG.md +++ b/GENERATION_LOG.md @@ -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' is not assignable to parameter of type 'FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. Type 'Promise' provides no match for the signature '(instance: FastifyInstance, 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' is not assignable to parameter of type 'FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. + Type 'Promise' provides no match for the signature '(instance: FastifyInstance, 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' is not assignable to parameter of type 'FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. + Type 'Promise' provides no match for the signature '(instance: FastifyInstance, FastifyBaseLogger, FastifyTy diff --git a/apps/web/src/components/SnippetInput.tsx b/apps/web/src/components/SnippetInput.tsx new file mode 100644 index 0000000..187ddb2 --- /dev/null +++ b/apps/web/src/components/SnippetInput.tsx @@ -0,0 +1,46 @@ +import React from 'react'; + +interface SnippetInputProps extends React.TextareaHTMLAttributes { + value: string; + onChange: (value: string) => void; +} + +const SNIPPETS: Record = { + ';daily': 'Daily standup', + ';mtg': 'Meeting', + ';review': 'Code review', + ';bug': 'Bugfix ', +}; + +export const SnippetInput: React.FC = ({ value, onChange, ...rest }) => { + const handleChange = (e: React.ChangeEvent) => { + 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 ( +