diff --git a/src/components/ai-assistant/AgentBadge.jsx b/src/components/ai-assistant/AgentBadge.tsx similarity index 97% rename from src/components/ai-assistant/AgentBadge.jsx rename to src/components/ai-assistant/AgentBadge.tsx index fb406b0..f0d9a50 100644 --- a/src/components/ai-assistant/AgentBadge.jsx +++ b/src/components/ai-assistant/AgentBadge.tsx @@ -57,8 +57,7 @@ function ConstrainedTag() { ); } -/** @param {any} props */ -export function AgentBadge({ page }) { +export function AgentBadge({ page }: any) { const { agent, covers } = useActiveAgent(); return ( diff --git a/src/components/ai-assistant/AgentContext.jsx b/src/components/ai-assistant/AgentContext.tsx similarity index 100% rename from src/components/ai-assistant/AgentContext.jsx rename to src/components/ai-assistant/AgentContext.tsx diff --git a/src/components/ai-assistant/AssistantMessage.jsx b/src/components/ai-assistant/AssistantMessage.tsx similarity index 98% rename from src/components/ai-assistant/AssistantMessage.jsx rename to src/components/ai-assistant/AssistantMessage.tsx index 8d67fc0..b3d5e59 100644 --- a/src/components/ai-assistant/AssistantMessage.jsx +++ b/src/components/ai-assistant/AssistantMessage.tsx @@ -86,9 +86,8 @@ function FeedbackControls({ feedback, onFeedback }) { } export const Message = React.memo( - /** @param {any} props */ ({ role, text, blocks, streaming, stopped, onPrompt, onConfirm = null, - feedback = null, onFeedback = null }) => { + feedback = null, onFeedback = null }: any) => { if (role === 'user') { return (
diff --git a/src/components/ai-assistant/AssistantPanel.jsx b/src/components/ai-assistant/AssistantPanel.tsx similarity index 100% rename from src/components/ai-assistant/AssistantPanel.jsx rename to src/components/ai-assistant/AssistantPanel.tsx diff --git a/src/components/ai-assistant/AssistantPanelContext.jsx b/src/components/ai-assistant/AssistantPanelContext.tsx similarity index 100% rename from src/components/ai-assistant/AssistantPanelContext.jsx rename to src/components/ai-assistant/AssistantPanelContext.tsx diff --git a/src/components/ai-assistant/AssistantTrigger.jsx b/src/components/ai-assistant/AssistantTrigger.tsx similarity index 98% rename from src/components/ai-assistant/AssistantTrigger.jsx rename to src/components/ai-assistant/AssistantTrigger.tsx index b1bf0b5..cde3c62 100644 --- a/src/components/ai-assistant/AssistantTrigger.jsx +++ b/src/components/ai-assistant/AssistantTrigger.tsx @@ -15,8 +15,7 @@ import { useAssistantPanel } from './AssistantPanelContext'; * It self-hides on pages with no assistant, so a page can render it * unconditionally and never needs to know the placement rules. */ -/** @param {any} props */ -export function AssistantTrigger({ className = '', size = 'default' }) { +export function AssistantTrigger({ className = '', size = 'default' }: any) { const { supported, isOpen, toggle, context } = useAssistantPanel(); if (!supported) return null; diff --git a/src/components/ai-assistant/KrowAssistant.jsx b/src/components/ai-assistant/KrowAssistant.tsx similarity index 100% rename from src/components/ai-assistant/KrowAssistant.jsx rename to src/components/ai-assistant/KrowAssistant.tsx diff --git a/src/components/ai-assistant/PageContext.jsx b/src/components/ai-assistant/PageContext.tsx similarity index 100% rename from src/components/ai-assistant/PageContext.jsx rename to src/components/ai-assistant/PageContext.tsx diff --git a/src/components/ai-assistant/PromptChips.jsx b/src/components/ai-assistant/PromptChips.tsx similarity index 99% rename from src/components/ai-assistant/PromptChips.jsx rename to src/components/ai-assistant/PromptChips.tsx index 29fcb68..a718778 100644 --- a/src/components/ai-assistant/PromptChips.jsx +++ b/src/components/ai-assistant/PromptChips.tsx @@ -23,14 +23,13 @@ import { cn } from '@/lib/utils'; * * Arrow keys move between chips, so the whole set is one tab stop. */ -/** @param {any} props */ export function PromptChips({ prompts = [], onSelect, max = 0, align = 'center', className = '', /* Taken out of the tab order while the row is collapsed but still mounted: a chip inside a zero-height container is invisible, and a Tab that lands on something invisible is a keyboard user losing their place. */ focusable = true, -}) { +}: any) { const chipRefs = React.useRef([]); const visible = max ? prompts.slice(0, max) : prompts; diff --git a/src/components/ai-assistant/PromptInput.jsx b/src/components/ai-assistant/PromptInput.tsx similarity index 99% rename from src/components/ai-assistant/PromptInput.jsx rename to src/components/ai-assistant/PromptInput.tsx index f2453da..1b346a9 100644 --- a/src/components/ai-assistant/PromptInput.jsx +++ b/src/components/ai-assistant/PromptInput.tsx @@ -17,7 +17,6 @@ import { cn } from '@/lib/utils'; * gain — the suggestion chips already teach the range of what can be asked, and * they do it without a timer or a rerender every four seconds. */ -/** @param {any} props */ export function PromptInput({ value, onChange, @@ -28,7 +27,7 @@ export function PromptInput({ autoFocus = false, align = 'left', className = '', -}) { +}: any) { const textareaRef = React.useRef(null); const [focused, setFocused] = React.useState(false); diff --git a/src/components/ai-assistant/ResizeDivider.jsx b/src/components/ai-assistant/ResizeDivider.tsx similarity index 100% rename from src/components/ai-assistant/ResizeDivider.jsx rename to src/components/ai-assistant/ResizeDivider.tsx diff --git a/src/components/ai-assistant/ResponseBlocks.jsx b/src/components/ai-assistant/ResponseBlocks.tsx similarity index 95% rename from src/components/ai-assistant/ResponseBlocks.jsx rename to src/components/ai-assistant/ResponseBlocks.tsx index 6d40381..439ccb2 100644 --- a/src/components/ai-assistant/ResponseBlocks.jsx +++ b/src/components/ai-assistant/ResponseBlocks.tsx @@ -121,14 +121,14 @@ const TONE_BADGE = { /* ── Individual blocks ──────────────────────────────────────────────────── */ -const TextBlock = React.memo(/** @param {any} props */ ({ block }) => ( +const TextBlock = React.memo(({ block }: any) => (

)); TextBlock.displayName = 'TextBlock'; -const HeadingBlock = React.memo(/** @param {any} props */ ({ block }) => ( +const HeadingBlock = React.memo(({ block }: any) => (

{block.text}

{block.sub &&

{block.sub}

} @@ -137,7 +137,7 @@ const HeadingBlock = React.memo(/** @param {any} props */ ({ block }) => ( HeadingBlock.displayName = 'HeadingBlock'; /** Headline figures. Two columns keeps the numbers large in a 380px panel. */ -const KpisBlock = React.memo(/** @param {any} props */ ({ block }) => ( +const KpisBlock = React.memo(({ block }: any) => (
{block.items.map((item) => (
( KpisBlock.displayName = 'KpisBlock'; /** Pass/warn checks. The icon carries the state so colour is not the only cue. */ -const StatusBlock = React.memo(/** @param {any} props */ ({ block }) => ( +const StatusBlock = React.memo(({ block }: any) => (
    {block.items.map((item) => (
  • @@ -204,7 +204,7 @@ const StatusBlock = React.memo(/** @param {any} props */ ({ block }) => ( )); StatusBlock.displayName = 'StatusBlock'; -const MetersBlock = React.memo(/** @param {any} props */ ({ block }) => ( +const MetersBlock = React.memo(({ block }: any) => (
    {block.items.map((item) => (
    @@ -226,7 +226,7 @@ MetersBlock.displayName = 'MetersBlock'; * A table. Scrolls horizontally inside its own container so a wide comparison * never widens the panel. */ -const TableBlock = React.memo(/** @param {any} props */ ({ block }) => { +const TableBlock = React.memo(({ block }: any) => { const cell = (value) => { if (value == null || value === '') return —; if (typeof value === 'object') { @@ -287,7 +287,7 @@ const TableBlock = React.memo(/** @param {any} props */ ({ block }) => { TableBlock.displayName = 'TableBlock'; /** Stage progression, widths relative to the largest stage. */ -const FunnelBlock = React.memo(/** @param {any} props */ ({ block }) => { +const FunnelBlock = React.memo(({ block }: any) => { const max = Math.max(...block.steps.map((s) => s.count), 1); return ( @@ -314,7 +314,7 @@ const FunnelBlock = React.memo(/** @param {any} props */ ({ block }) => { }); FunnelBlock.displayName = 'FunnelBlock'; -const ListBlock = React.memo(/** @param {any} props */ ({ block }) => { +const ListBlock = React.memo(({ block }: any) => { const Tag = block.ordered ? 'ol' : 'ul'; return ( @@ -357,7 +357,7 @@ ListBlock.displayName = 'ListBlock'; * clickable and doing nothing. An item may carry a hint *and* an action: the * hint explains the record, the action opens it. */ -const InsightsBlock = React.memo(/** @param {any} props */ ({ block, onPrompt }) => ( +const InsightsBlock = React.memo(({ block, onPrompt }: any) => (
    {block.items.map((item, i) => { const surface = cn( @@ -434,7 +434,7 @@ const InsightsBlock = React.memo(/** @param {any} props */ ({ block, onPrompt }) InsightsBlock.displayName = 'InsightsBlock'; /** Recommended steps — numbered, because order is the recommendation. */ -const ActionsBlock = React.memo(/** @param {any} props */ ({ block }) => ( +const ActionsBlock = React.memo(({ block }: any) => (
      {block.items.map((item, i) => (
    1. @@ -453,7 +453,7 @@ const ActionsBlock = React.memo(/** @param {any} props */ ({ block }) => ( )); ActionsBlock.displayName = 'ActionsBlock'; -const BadgesBlock = React.memo(/** @param {any} props */ ({ block }) => ( +const BadgesBlock = React.memo(({ block }: any) => (
      {block.items.map((item) => ( @@ -464,7 +464,7 @@ const BadgesBlock = React.memo(/** @param {any} props */ ({ block }) => ( )); BadgesBlock.displayName = 'BadgesBlock'; -const TimelineBlock = React.memo(/** @param {any} props */ ({ block }) => ( +const TimelineBlock = React.memo(({ block }: any) => (
        {block.items.map((item, i) => (
      1. @@ -497,7 +497,7 @@ const TimelineBlock = React.memo(/** @param {any} props */ ({ block }) => ( )); TimelineBlock.displayName = 'TimelineBlock'; -const NoteBlock = React.memo(/** @param {any} props */ ({ block }) => ( +const NoteBlock = React.memo(({ block }: any) => (

        @@ -514,7 +514,7 @@ NoteBlock.displayName = 'NoteBlock'; * shape the table does not carry renders nothing rather than something * improvised. */ -const SkillSectionBlock = React.memo(/** @param {any} props */ ({ block }) => { +const SkillSectionBlock = React.memo(({ block }: any) => { const section = block.section; const Component = SECTION_COMPONENTS[section?.shape || section?.type]; @@ -564,7 +564,7 @@ SkillSectionBlock.displayName = 'SkillSectionBlock'; * - **Not pretend to be finished.** Once approved, the block stays visible * and says so. Replacing it with a tick would lose what was agreed to. */ -const ConfirmationBlock = React.memo(/** @param {any} props */ ({ block, onConfirm }) => { +const ConfirmationBlock = React.memo(({ block, onConfirm }: any) => { const [state, setState] = React.useState('pending'); const approve = React.useCallback(() => { @@ -673,7 +673,7 @@ const RENDERERS = { * blocks has consistent rhythm — a heading hugs what follows it, everything * else breathes. */ -export const ResponseDocument = React.memo(/** @param {any} props */ ({ blocks = [], streaming = false, onPrompt, onConfirm }) => ( +export const ResponseDocument = React.memo(({ blocks = [], streaming = false, onPrompt, onConfirm }: any) => (
        {blocks.map((block, i) => { const Renderer = RENDERERS[block.type]; diff --git a/src/components/ai-assistant/index.jsx b/src/components/ai-assistant/index.tsx similarity index 100% rename from src/components/ai-assistant/index.jsx rename to src/components/ai-assistant/index.tsx