Skip to content

Conversation

@dan-niles
Copy link
Contributor

@dan-niles dan-niles commented Nov 13, 2025

Purpose

Closes wso2/product-ballerina-integrator#1840

This PR introduces support for inserting multi-modal documents (images, files, and audio) into prompts for model providers via the expression helper pane. This enhancement removes the need for users to manually type the document syntax and significantly improves the low-code user experience.

Adding new documents through helper pane:

Screen.Recording.2025-11-14.at.9.15.32.AM.mov

Replacing existing document chips:

Screen.Recording.2025-11-14.at.9.45.07.AM.mov

Template <-> Expression mode switcher:

Screen.Recording.2025-11-19.at.12.30.00.PM.mov

Expanded editor with markdown toolbar and preview:

Screen.Recording.2025-11-19.at.12.32.22.PM.mov

Goals

This feature enables users to easily add ai:ImageDocument, ai:FileDocument, and ai:AudioDocument objects into the expression editor through the helper pane, addressing the current limitation where users must manually type complex syntax.
It also enhances the helper pane to filter and display only valid variable types when inserting documents (AI Document types, string, ai:Url, byte[]) and introduces a more intuitive UI for selecting or providing document inputs.

Approach

  • Added a new Documents section to the expression helper pane, visible only when editing fields of type ai:Prompt.
  • Implemented a dedicated Documents page listing the supported document types (Image, File, Audio).
  • Added a variable selection view showing only fields and variables compatible with document creation.
  • Implemented Add from URL support for direct URL-based document inputs.
  • Introduced a reusable chip UI component to represent document types visually.
  • Hid backticks when editing prompt expressions

(See screenshots above for the updated UI.)

User stories

This PR addresses the following user stories:

  • As a low-code user, I want to insert document objects into prompts without needing to know or manually type the syntax.
  • As a developer, I want the helper pane to intelligently filter variables and show only the supported types for document creation.
  • As a user working with multi-modal AI features, I want a clearer and more intuitive UI for attaching documents.

Release note

Introduces support for inserting Image, File, and Audio documents into prompt expressions via an improved helper pane, enhancing multi-modal prompt creation in the expression editor.

Summary by CodeRabbit

  • New Features

    • Template mode: rich Markdown editor with formatting toolbar, preview rendering token "chips", and template-aware transformations.
    • New Documents area and Document Config pane (file/image/audio) with URL-based document creation.
    • Helper pane and completions support template-mode wrapping and propagate a template-aware input mode.
    • Editor: preserves cursor/selection when interacting with helper panes; exposes helper-pane toggle.
  • Bug Fixes

    • Improved error/diagnostic display in expanded editors.
    • Fixed overflow/scrolling in sliding and editor panes.
  • UI/UX

    • Redesigned token chips, icons, and markdown preview styles for clearer expression rendering.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 13, 2025

Walkthrough

Adds a Template editing mode and Markdown tooling; migrates expression token handling to a CodeMirror parsed-token/compound-token model with document-token support and new chip styles; removes legacy tokenized components; and threads InputMode/template interpolation through helper panes, forms, and visualizer pages.

Changes

Cohort / File(s) Summary
Editor wiring
workspaces/ballerina/ballerina-side-panel/src/components/editors/EditorFactory.tsx
Rebinds RAW_TEMPLATE/ai:Prompt and expression branches to ContextAwareRawExpressionEditor / ContextAwareExpressionEditor and adjusts props passed (openSubPanel, subPanelView, focus/blur, autoFocus, recordTypeField).
Expanded editor core & types
.../ExpandedEditor.tsx, .../modes/types.ts, .../modes/ExpressionMode.tsx
Adds TemplateMode, registers "template" in MODE_COMPONENTS, expands props (sanitizedExpression, rawExpression, error, formDiagnostics), updates EditorMode union, and renders ErrorBanner in expression mode.
Template mode & UI
.../modes/TemplateMode.tsx, .../controls/TemplateMarkdownToolbar.tsx, .../controls/MarkdownPreview.tsx, .../styles/markdown-preview.css
New TemplateMode component with edit/preview, toolbar, token→markdown transform; Markdown preview uses rehype-raw/remark-gfm and custom chip rendering; adds CSS for markdown.
Markdown editing utils
.../utils/templateUtils.ts, .../utils/transformToMarkdown.ts
Adds markdown editing utilities (formatting, lists, link, header toggles, Enter continuation) and transformExpressionToMarkdown / hasTokens for chipified previews.
CodeMirror token engine & editor
.../ChipExpressionEditor/CodeUtils.ts, .../components/ChipExpressionEditor.tsx
Introduces tokenField state, chipPlugin, keymaps/listeners, createChip with metadata, tokensChange effects, saved-selection handling, onEditorViewReady hook, and sanitization-aware flows.
Token types & parsing utils
.../ChipExpressionEditor/types.ts, .../utils.ts
Introduces TokenType/DocumentType/TokenMetadata, ParsedToken, CompoundTokenSequence, TOKEN_PATTERNS, and mapping utilities (mapRawToSanitized / mapSanitizedToRaw) plus pattern detection and metadata extractors.
Chip styling & components
.../ChipExpressionEditor/styles.tsx, .../chipStyles.ts, ExpandedEditor/controls/ChipComponent.tsx
New chip style utilities, DocumentChip family, icon/color maps, and a ChipComponent for rendering token chips (supports documentType).
Removed legacy token UI
.../AutoExpandingEditableDiv.tsx, .../ChipComponent.tsx, .../TokenizedExpression.tsx, .../TextElement.tsx, .../CHipTest.tsx
Deletes legacy contentEditable/tokenized components and test harnesses as part of migration to the CodeMirror/token-stream model.
Expression editor wiring & props
ExpressionEditor.tsx, ExpressionField.tsx, RawExpressionEditor.tsx, Form/types.ts
Adds TEMPLATE mode logic, inputMode handling, targetLineRange/helperPaneZIndex propagation, sanitized/raw forwarding, onOpenRecordConfigPage hook, and extends getHelperPane signature with inputMode.
Helper pane pages & navigation
visualizer/.../Views/* (Documents.tsx, DocumentConfig.tsx, Configurables.tsx, Inputs.tsx, Variables.tsx, Functions.tsx), hooks/useHelperPaneNavigation.tsx, index.tsx, utils/*
Adds Documents and DocumentConfig pages, AIDocumentType, wrapInTemplateInterpolation helper, navigation API changes (navigateToNext/navigateToBreadcrumb signatures removed onChange), getCurrentNavigationPath, and threads inputMode through panes.
Visualizer & helper infra
visualizer/Context.tsx, .../utils/iconUtils.tsx, .../utils/types.ts
Adds DOCUMENT_URL popup id, DOCUMENT icon mapping, and updates navigation-arrow logic to treat "Record" description as navigable.
Chip editor internals & styles
.../ChipExpressionEditor/chipStyles.ts, .../CodeUtils.ts
New chipStyles file, chip rendering helpers, and CodeUtils updates for metadata-aware chips, compound deletion, iterateTokenStream, and public exports.
Exports & deps
editors/index.ts, workspaces/ballerina/ballerina-side-panel/package.json, ui-toolkit/*, Commons/ErrorBanner.tsx, ModeSwitcher/styles.tsx
Exports InputMode, adds rehype-raw & remark-gfm deps, re-exports useSlidingPane, exposes ErrorBanner sx prop, and adjusts ModeSwitcher sizing.
Forms integration
workspaces/ballerina-visualizer/src/views/BI/Forms/*
Threads inputMode through form generator helper-pane creation calls and related APIs (handleGetHelperPane).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ExpressionEditor
    participant ExpandedEditor
    participant TemplateMode
    participant CodeMirror
    participant HelperPane

    User->>ExpressionEditor: choose TEMPLATE mode / edit
    ExpressionEditor->>ExpandedEditor: open(mode="template", sanitizedExpression, rawExpression)
    ExpandedEditor->>TemplateMode: render TemplateMode
    TemplateMode->>CodeMirror: init ChipExpressionEditor (sanitized/raw)
    CodeMirror-->>TemplateMode: EditorView ready (onEditorViewReady)
    User->>TemplateMode: open HelperPane / select item
    HelperPane->>HelperPane: compute completionContext (getCurrentNavigationPath)
    HelperPane-->>TemplateMode: onChange(wrappedValue) [wrapInTemplateInterpolation if TEMPLATE]
    TemplateMode->>CodeMirror: insert token / update tokenField
    User->>TemplateMode: toggle preview
    TemplateMode->>TemplateMode: transformExpressionToMarkdown(value, tokens)
    TemplateMode->>User: render MarkdownPreview with <chip> tokens
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Pay attention to:
    • CodeUtils.ts (CodeMirror plugins, state effects, undo/redo/refetch listeners)
    • MultiModeExpressionEditor utils (detectTokenPatterns, mapSanitized↔raw, metadata extraction)
    • transformExpressionToMarkdown token replacements and HTML escaping
    • useHelperPaneNavigation API signature changes and updated call sites
    • Deleted legacy components to ensure no remaining imports/usages

Possibly related PRs

Suggested reviewers

  • hevayo
  • gigara
  • kanushka

Poem

🐰 Hopping through tokens with gentle cheer,

Chips and markdown snuggle close and near.
Templates curl in braces, tidy and bright,
Helper panes guide each nibble day and night.
CodeRabbit hums — the editor’s set just right.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description covers Purpose, Goals, Approach, User Stories, and Release Note sections from the template. However, several required sections are missing or incomplete: UI Component Development, Manage Icons, Documentation, Training, Certification, Marketing, Automation tests, Security checks, Samples, Related PRs, Migrations, Test environment, and Learning. Complete the missing sections from the template, including UI/Icon development rationale, documentation links, test coverage details, security verification, and test environment specifications.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main feature: adding support for inserting multi-modal documents via the helper pane, which aligns with the primary objective of the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 78c8ce0 and af669a2.

📒 Files selected for processing (2)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/TemplateMode.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipExpressionEditor.tsx (15 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/TemplateMode.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipExpressionEditor.tsx

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dan-niles dan-niles force-pushed the document-support-in-expression-helper branch from 66dc60f to a1b33f8 Compare November 13, 2025 06:50
@dan-niles dan-niles changed the title [WIP] Add support for inserting multi-modal documents via the helper pane Add support for inserting multi-modal documents via the helper pane Nov 14, 2025
@dan-niles dan-niles marked this pull request as ready for review November 14, 2025 05:00
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Variables.tsx (1)

55-93: Align VariableItem’s onItemSelect type with actual handlers

VariableItemProps defines onItemSelect: (value: string, item: CompletionItem) => void; and VariableItem calls it as onItemSelect(item.label, item), but the local handleItemSelect in Variables is defined as (value: string) => { ... }. This mismatch can cause TypeScript issues now that VariableItem and its props are exported and intended for reuse.

A minimal, backward‑compatible fix is to make the second parameter optional:

-export type VariableItemProps = {
-    item: CompletionItem;
-    onItemSelect: (value: string, item: CompletionItem) => void;
-    onMoreIconClick: (value: string) => void;
-    hideArrow?: boolean;
-}
+export type VariableItemProps = {
+    item: CompletionItem;
+    onItemSelect: (value: string, item?: CompletionItem) => void;
+    onMoreIconClick: (value: string) => void;
+    hideArrow?: boolean;
+}

VariableItem can continue to call onItemSelect(item.label, item); existing handlers that only accept (value: string) will keep working because the extra argument is ignored, and the type now reflects that.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/ChipExpressionBaseComponent.tsx (1)

148-162: Potential runtime crash: targetLineRange is optional but dereferenced unconditionally

ChipExpressionBaseComponentProps declares targetLineRange as optional:

targetLineRange?: LineRange;

but fetchUpdatedFilteredTokens uses it as if it’s always defined:

const response = await expressionEditorRpcManager?.getExpressionTokens(
    value,
    props.fileName,
    props.targetLineRange.startLine
);

If any caller omits targetLineRange, this will throw at runtime (Cannot read properties of undefined). Either the prop should be required, or the call-site must guard against undefined.

One local fix that keeps the prop optional:

const fetchUpdatedFilteredTokens = useCallback(async (value: string): Promise<number[]> => {
    setIsLoading(true);
    try {
+       if (!props.targetLineRange) {
+           setIsLoading(false);
+           return [];
+       }
        const response = await expressionEditorRpcManager?.getExpressionTokens(
            value,
            props.fileName,
            props.targetLineRange.startLine
        );
        setIsLoading(false);
        return response || [];
    } catch (error) {
        setIsLoading(false);
        return [];
    }
}, [expressionEditorRpcManager, props.targetLineRange, props.fileName]);

(Dependencies adjusted accordingly.) If in practice targetLineRange is always present, consider making it non-optional in the prop type instead.

🧹 Nitpick comments (10)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (1)

32-66: Navigation path building is correct; consider de‑duplicating getters

The updated navigateToNext logic with separator builds dotted paths correctly for both root and nested levels, and navigateToBreadcrumb cleanly trims steps. getCurrentNavigationPath currently duplicates getCurrentPath logic; you can avoid duplication by implementing one in terms of the other (or aliasing) to keep the source of truth in a single place.

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Inputs.tsx (1)

88-121: Navigation‑aware completion context and offsets look correct

Using getCurrentNavigationPath to derive navigationPath and then completionContext (navigationPath + '.' when nested, otherwise currentValue) matches the expected semantics for field navigation. The offset calculation (navigationPath ? completionContext.length : 0) correctly positions the cursor after the dot for nested paths, while still requesting root‑level completions with offset 0.

You could optionally include getCurrentNavigationPath in the useMemo dependency array for lint friendliness, though it’s stable in practice.

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Variables.tsx (1)

103-117: Navigation‑aware completion context for Variables matches Inputs behavior

The navigationPath + completionContext pattern mirrors Inputs: when navigating inside a variable, you build navigationPath + '.', otherwise you fall back to currentValue. This is consistent and should give predictable completion behavior for nested variable structures.

You could simplify the useMemo returning path to useMemo(() => getCurrentNavigationPath(), [breadCrumbSteps]) or even call getCurrentNavigationPath() directly if you don’t need memoization.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/TokenizedExpression.tsx (1)

23-39: TokenType integration is correct; consider tightening types

Switching to TokenType and TOKEN_TYPE_INDEX_MAP in getTokenTypeFromIndex / getTokenChip aligns this module with the new token model and is functionally correct. A couple of small type cleanups would improve safety:

  • getTokenTypeFromIndex can return TokenType instead of string to reflect the actual values:
-export const getTokenTypeFromIndex = (index: number): string => {
-    return TOKEN_TYPE_INDEX_MAP[index] || TokenType.FUNCTION;
-};
+export const getTokenTypeFromIndex = (index: number): TokenType => {
+    return TOKEN_TYPE_INDEX_MAP[index] || TokenType.FUNCTION;
+};
  • The type parameter in TokenizedExpressionProps callbacks (onChipClick, onChipFocus) is still typed as string even though getTokenChip now passes a TokenType. If callers already work with the enum, consider updating these to type: TokenType for better type checking.

  • documentType is currently passed as documentType={documentType as any}. If you have a DocumentType type in ../types, wiring that through instead of string/any would avoid accidental misuse.

These are non-breaking at runtime but will make the API clearer for future changes.

Also applies to: 70-77

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipComponent.tsx (1)

35-46: Consider removing the unreachable default case.

The default case in getDocumentIcon will never be reached due to TypeScript's exhaustive type checking on DocumentType. You can simplify this or add an assertion for extra safety.

Apply this diff for a cleaner implementation:

 const getDocumentIcon = (documentType: DocumentType): React.ReactNode => {
     switch (documentType) {
         case 'ImageDocument':
             return <Icon name="bi-image" sx={{ width: 16, height: 16, fontSize: 16 }} />;
         case 'FileDocument':
             return <Icon name="bi-doc" sx={{ width: 16, height: 16, fontSize: 16 }} />;
         case 'AudioDocument':
             return <Icon name="bi-audio" sx={{ width: 16, height: 16, fontSize: 16 }} />;
-        default:
-            return <Icon name="bi-attach-file" sx={{ width: 16, height: 16, fontSize: 16 }} />;
     }
 };
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/DocumentConfig.tsx (2)

80-110: Completion retrieval effect: consider dependencies and stale closures

The useEffect that calls handleRetrieveCompletions depends on targetLineRange, breadCrumbSteps, and completionContext, but uses field, triggerCharacters, handleRetrieveCompletions, filteredCompletions, and showContent from the closure. If any of those can change without unmounting (e.g., different field, updated trigger characters, or a re-created handleRetrieveCompletions), the effect will keep using stale values.

If that’s a realistic scenario, it’d be safer to include the relevant items in the dependency array (and gate re-fetching with a separate flag if needed) to avoid subtle bugs where the pane doesn’t refresh completions as expected.


216-256: URL input: consider minimal validation or feedback for invalid URLs

URLInputModal currently only checks that the URL is non-empty before wrapping it in a document expression:

if (!url.trim()) {
    return;
}
const wrappedValue = wrapInDocumentType(documentType, `"${url.trim()}"`);

If users paste clearly invalid values, they get no feedback and the expression will still be inserted. Not strictly wrong, but a simple validation (e.g., basic URL shape or requiring a scheme) and/or an inline error message would improve UX and help avoid obviously broken inputs.

If you prefer to keep the server as the only validator, even just disabling Create for inputs that don’t match a simple regex would be a low-cost safeguard.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/ChipExpressionBaseComponent.tsx (3)

95-146: Backtick sanitization works, but sanitizedExpression prop is only used as a boolean flag

sanitizeExpressionModel correctly strips a single leading/trailing backtick from the first/last literal and drops now-empty literals, which achieves the goal of hiding wrapper backticks in the editor.

However, the sanitizedExpression?: (value: string) => string; prop is only used as a truthy check:

if (!props.sanitizedExpression || model.length === 0) {
    return model;
}

The callback itself is never invoked in this component. If the intent is that the parent controls the actual string-level sanitization (e.g., mapping between stored/raw expressions and UI-friendly ones), you might want either:

  • A clearer boolean prop name (e.g., hideWrapperBackticks?: boolean), or
  • Actually applying props.sanitizedExpression to updatedValue before calling props.onChange, if the parent expects to receive a transformed expression.

Right now the API shape suggests caller-provided sanitization logic, but the implementation only uses it as an on/off switch.


246-278: Merged-token handling: behavior looks correct, but worth verifying token-refresh assumptions

The merged-token guard and fetch trigger logic look sensible:

  • hasMergedTokens checks el.metadata to detect merged document/variable tokens.
  • Manual token updates via updateTokens are skipped when merged tokens exist.
  • You then force a full token refresh by setting fetchnewTokensRef.current = true when hasMergedTokens is true.

This should help avoid corrupting merged document tokens while still keeping tokens in sync.

Given how central tokens are to chip rendering, it’s worth double-checking that downstream helpers (e.g., mergeDocumentTokens in utils.ts) aren’t relying on the pre-sanitized invariant of always having leading/trailing literal elements, since sanitizeExpressionModel now filters empty literals. If they do, they may also need a corresponding adjustment.


148-169: Loading skeleton: consider consolidating isLoading usage and guarding function-signature errors

isLoading drives the SkeletonLoader overlay and is toggled both in fetchUpdatedFilteredTokens and getFnSignature. That’s fine, but:

  • If props.extractArgsFromFunction ever throws or rejects, setIsLoading(false) in getFnSignature won’t run and the skeleton may stay visible indefinitely.
  • Multiple overlapping calls (tokens + signature) will race on isLoading, which is acceptable visually but something to be aware of.

A small refinement would be to wrap extractArgsFromFunction in a try/finally similar to fetchUpdatedFilteredTokens:

const getFnSignature = useCallback(async (value: string, cursorPosition: number) => {
    if (props.extractArgsFromFunction) {
-       setIsLoading(true);
-       const fnSignature = await props.extractArgsFromFunction(value, cursorPosition);
-       setIsLoading(false);
+       setIsLoading(true);
+       try {
+           const fnSignature = await props.extractArgsFromFunction(value, cursorPosition);
+           if (fnSignature) {
+               return fnSignature;
+           }
+       } finally {
+           setIsLoading(false);
+       }
-       if (fnSignature) {
-           return fnSignature
-       }
    }
    return undefined;
}, [props.extractArgsFromFunction]);

This keeps the skeleton from getting “stuck” in the face of unexpected errors.

Also applies to: 380-483, 622-623

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 20f6525 and 82e9f0b.

⛔ Files ignored due to path filters (3)
  • workspaces/common-libs/font-wso2-vscode/src/icons/bi-attach-file.svg is excluded by !**/*.svg
  • workspaces/common-libs/font-wso2-vscode/src/icons/bi-audio.svg is excluded by !**/*.svg
  • workspaces/common-libs/font-wso2-vscode/src/icons/bi-image.svg is excluded by !**/*.svg
📒 Files selected for processing (25)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/EditorFactory.tsx (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/ExpandedEditor.tsx (3 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/ExpressionMode.tsx (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/types.ts (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionEditor.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionField.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/ChipExpressionBaseComponent.tsx (11 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/AutoExpandingEditableDiv.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipComponent.tsx (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/TokenizedExpression.tsx (3 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/styles.tsx (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (13 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (1 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/Context.tsx (1 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Configurables.tsx (1 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/DocumentConfig.tsx (1 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Documents.tsx (1 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Inputs.tsx (3 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Variables.tsx (6 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (2 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx (6 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/iconUtils.tsx (2 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/types.ts (2 hunks)
  • workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-10T15:05:11.309Z
Learnt from: madushajg
Repo: wso2/vscode-extensions PR: 868
File: workspaces/bi/bi-extension/src/utils.ts:224-242
Timestamp: 2025-11-10T15:05:11.309Z
Learning: The workspaces/bi/bi-extension and workspaces/ballerina/ballerina-extension are separate VS Code extensions that are packaged and distributed independently, so they cannot share code via imports and must maintain their own implementations of common utilities.

Applied to files:

  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx
🧬 Code graph analysis (10)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx (4)
workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (3)
  • SlidingPaneNavContainer (224-258)
  • SlidingPane (125-155)
  • SlidingPaneHeader (281-288)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/iconUtils.tsx (1)
  • getHelperPaneIcon (40-46)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Documents.tsx (1)
  • Documents (28-72)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/DocumentConfig.tsx (1)
  • DocumentConfig (68-307)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Documents.tsx (1)
workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (1)
  • SlidingPaneNavContainer (224-258)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipComponent.tsx (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (1)
  • DocumentType (59-59)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/styles.tsx (4)
  • Chip (54-81)
  • DocumentChip (83-110)
  • DocumentChipIcon (112-118)
  • DocumentChipText (120-128)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Inputs.tsx (3)
workspaces/common-libs/ui-toolkit/src/components/Codicon/Codicon.tsx (1)
  • Codicon (44-56)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (2)
  • useHelperPaneNavigation (26-67)
  • BreadCrumbStep (21-24)
workspaces/ballerina/ballerina-side-panel/src/components/editors/utils.ts (1)
  • getPropertyFromFormField (64-81)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/DocumentConfig.tsx (7)
workspaces/ballerina/bi-diagram/src/utils/types.ts (1)
  • LineRange (53-53)
workspaces/ballerina/ballerina-core/src/interfaces/extended-lang-client.ts (1)
  • ExpressionProperty (1077-1077)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (2)
  • useHelperPaneNavigation (26-67)
  • BreadCrumbStep (21-24)
workspaces/ballerina/ballerina-visualizer/src/Context.tsx (2)
  • useModalStack (189-189)
  • POPUP_IDS (136-144)
workspaces/ballerina/ballerina-side-panel/src/components/editors/utils.ts (1)
  • getPropertyFromFormField (64-81)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Variables.tsx (1)
  • VariableItem (62-93)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/BreadcrumbNavigation.tsx (1)
  • BreadcrumbNavigation (28-128)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/TokenizedExpression.tsx (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (1)
  • TOKEN_TYPE_INDEX_MAP (29-37)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipComponent.tsx (1)
  • ChipComponent (48-114)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/ChipExpressionBaseComponent.tsx (4)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (1)
  • ExpressionModel (67-79)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (3)
  • createExpressionModelFromTokens (381-499)
  • getTextValueFromExpressionModel (181-189)
  • updateTokens (1343-1382)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/constants.ts (1)
  • BACKSPACE_MARKER (33-33)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/styles.tsx (1)
  • SkeletonLoader (353-366)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Variables.tsx (5)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/types.ts (1)
  • shouldShowNavigationArrow (89-92)
workspaces/common-libs/ui-toolkit/src/components/Codicon/Codicon.tsx (1)
  • Codicon (44-56)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/HelperPaneListItem.tsx (1)
  • HelperPaneListItem (77-124)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (2)
  • useHelperPaneNavigation (26-67)
  • BreadCrumbStep (21-24)
workspaces/ballerina/ballerina-side-panel/src/components/editors/utils.ts (1)
  • getPropertyFromFormField (64-81)
workspaces/ballerina/ballerina-side-panel/src/components/editors/EditorFactory.tsx (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (1)
  • ContextAwareRawExpressionEditor (23-38)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionEditor.tsx (1)
  • ContextAwareExpressionEditor (293-306)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (2)
  • DocumentType (59-59)
  • ExpressionModel (67-79)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/TokenizedExpression.tsx (1)
  • getTokenTypeFromIndex (26-28)
🔇 Additional comments (28)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Configurables.tsx (1)

207-207: Navigation API simplification is correct and verified.

The navigateToBreadcrumb function signature accepts only the step parameter (as confirmed in the hook implementation at line 41 of useHelperPaneNavigation.tsx). All usages across the Helper Pane components—Variables, Inputs, DocumentConfig, and Configurables—consistently pass only the step parameter. Breadcrumb navigation state updates are handled internally by the hook via setBreadCrumbSteps, so no side effects are lost with this change.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/AutoExpandingEditableDiv.tsx (1)

286-290: Layout change is intentional and correct — no issues found.

The change to maxHeight: 'none' in expanded mode is a well-designed layout pattern. The outer container (ChipEditorField) can grow unbounded while the inner editor content remains fixed at EXPANDED_EDITOR_HEIGHT (500px) with scrolling. This allows helper buttons, completions menu, and UI controls to render outside the fixed scrollable area. The DocumentChip components integrate properly as non-editable elements within the tokenized expression. The minimum height constraint ensures the outer container never collapses below 500px.

workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (2)

33-43: Overflow hidden on SlidingWindowContainer looks safe

Switching to overflow-x: hidden / overflow-y: hidden at the pane container level is consistent with using inner scrollable sections (e.g., ScrollableContainer) and avoids double scrollbars. As long as all scrollable content is inside those inner containers—as it is in the helper-pane views—this is fine.


298-298: Re‑exporting useSlidingPane is a useful API addition

Re‑exporting useSlidingPane from this module simplifies consumers’ imports and aligns the hook with the rest of the SlidingPane API.

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Inputs.tsx (3)

66-71: Codicon end action usage is fine

Rendering the navigation arrow via Codicon name="chevron-right" remains functionally identical and keeps the intent clear.


124-139: Root vs nested filtering for inputs is clear and safe

The root‑level filter that restricts items to kind === "variable" with "Parameter" in the description, and the nested filter that allows both fields and variables (excluding self), gives a sensible distinction between top‑level parameters and object members. The optional chaining on labelDetails?.description prevents runtime errors when metadata is missing.


152-164: Path construction and navigation wiring for Inputs are consistent

handleItemSelect correctly constructs a full dotted path from navigationPath plus the selected value before calling onChange, and handleInputsMoreIconClick + handleBreadCrumbItemClicked delegate to navigateToNext/navigateToBreadcrumb using the same navigationPath basis. This keeps completion navigation and inserted expressions in sync.

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Variables.tsx (3)

122-145: Completion retrieval and offset logic for Variables look sound

Using completionContext to derive the trigger character and offset (navigationPath ? completionContext.length : 0) is consistent with the navigation model and parallels Inputs. The effect dependencies on targetLineRange, breadCrumbSteps, and completionContext are enough to refresh completions when navigation or context changes.


172-183: Variable dropdown filtering with excludedDescriptions is clear

Filtering out variables whose labelDetails.description includes "Configurable", "Parameter", "Listener", or "Client" while still requiring kind === "field" || kind === "variable" and excluding self gives a well-scoped set of user-facing variables. Optional chaining around labelDetails?.description avoids runtime errors if metadata is missing.


196-200: Full-path selection and navigation wiring for Variables are consistent

handleItemSelect correctly builds a full dotted path from navigationPath and passes it to onChange, and the “more” and breadcrumb handlers delegate to navigateToNext(value, navigationPath) / navigateToBreadcrumb(step) respectively. This keeps navigation, selection, and the inserted expression aligned.

Also applies to: 219-224, 231-236

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/TokenizedExpression.tsx (1)

96-117: Renderable token filtering and document chip rendering look correct

Using isRenderableToken to skip START_EVENT, END_EVENT, TYPE_CAST, and VALUE from chip rendering (falling back to TextElement for those) matches the expectation that only semantic tokens (variables, properties, documents, etc.) become chips. Passing element.metadata?.content || element.value as the chip text and element.metadata?.documentType through to getTokenChip ensures document tokens can render with the correct label and icon while still preserving raw text in the non-token branch.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (2)

203-379: LGTM: Well-structured document token merging logic.

The token merging implementation is well-organized with clear helper functions and proper validation of token sequences. The separation between variable and document token merging patterns is appropriate.


501-503: The review comment is based on a misunderstanding.

The getTokenTypeFromIndex at lines 501-503 in utils.ts is a separate, locally-scoped function from the exported getTokenTypeFromIndex in TokenizedExpression.tsx. These are two different functions serving different purposes, not inconsistent implementations of the same code. The TokenType.VARIABLE default in utils.ts is appropriate for its tokenizer parsing context, while the TokenType.FUNCTION default in TokenizedExpression.tsx is appropriate for its separate context.

Likely an incorrect or invalid review comment.

workspaces/ballerina/ballerina-visualizer/src/Context.tsx (1)

143-143: LGTM: New popup ID for document URL functionality.

The addition of DOCUMENT_URL to POPUP_IDS follows the established pattern and supports the new document-related UI flows introduced in this PR.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionField.tsx (1)

158-158: LGTM: Prop forwarding to support expression sanitization.

The sanitizedExpression prop is correctly forwarded to ChipExpressionBaseComponent, enabling the expression sanitization feature for chip-based expression editing.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/ExpandedEditor.tsx (1)

44-44: LGTM: Clean prop threading for expression sanitization.

The sanitizedExpression prop is appropriately added to the expanded editor and forwarded only to the expression mode path, maintaining separation of concerns between different editor modes.

Also applies to: 128-128, 185-185

workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (1)

29-33: LGTM: Explicit prop handling with proper override precedence.

The reordering ensures that targetLineRange and helperPaneZIndex are passed explicitly, while {...props} at the end allows for prop overrides. This provides better control over prop precedence and aligns with the expanded prop surface for expression editors.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/types.ts (1)

55-56: LGTM: Type extension for expression sanitization.

The addition of the optional sanitizedExpression prop to EditorModeExpressionProps properly extends the interface to support the new sanitization feature in expression mode.

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx (2)

24-25: LGTM: Documents integration follows established patterns.

The Documents and DocumentConfig panes are properly integrated into the SlidingPane navigation structure, following the same pattern as Variables, Inputs, and other existing panes. The prop wiring is consistent and complete.

Also applies to: 453-474


41-41: AI_PROMPT_TYPE constant value is correct.

Verification confirms that the AI_PROMPT_TYPE constant value "ai:Prompt" matches the Ballerina type constraint system. The string is used consistently in the codebase, including independent validation in EditorFactory.tsx where field.valueTypeConstraint === "ai:Prompt" appears. The constant is properly used for conditional menu item rendering in the helper pane.

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/iconUtils.tsx (1)

28-28: LGTM!

The DOCUMENT icon type addition is consistent with the existing pattern and properly maps to the "bi-attach-file" icon.

Also applies to: 37-37

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionEditor.tsx (1)

731-731: LGTM!

Properly forwards sanitizedExpression to ExpandedEditor, enabling consistent expression sanitization in expanded mode.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/ExpressionMode.tsx (1)

41-41: LGTM!

Correctly threads sanitizedExpression through to ChipExpressionBaseComponent, maintaining the sanitization pipeline.

Also applies to: 56-56

workspaces/ballerina/ballerina-side-panel/src/components/editors/EditorFactory.tsx (1)

158-182: LGTM! Editor routing updated for document support.

The editor routing logic has been updated to use ContextAwareRawExpressionEditor for RAW_TEMPLATE or ai:Prompt fields, with enhanced context props (openSubPanel, recordTypeField, etc.) enabling richer document editing experiences.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (1)

29-40: LGTM!

The TokenType enum, DocumentType, and TokenMetadata types provide proper type safety for the document token system. The optional metadata field correctly handles both document and non-document tokens.

Also applies to: 59-65, 74-78

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/styles.tsx (1)

83-128: LGTM!

The DocumentChip styled components provide clear visual distinction for document tokens with appropriate theming and layout.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipComponent.tsx (1)

69-94: LGTM!

The document chip rendering logic properly handles TokenType.DOCUMENT with icon and text, maintaining consistency with existing variable and property chip patterns.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/ChipExpressionBaseComponent.tsx (1)

347-354: Expanded token fetch triggers (comma, newline, paste) look good

The updated shouldFetchNewTokens logic to include commas, newlines, and multi-character “paste-like” input as triggers is a good addition for keeping tokens and completions consistent with user edits:

const endsWithTriggerChar = lastTypedText.endsWith('+')
    || lastTypedText.endsWith(' ')
    || lastTypedText.endsWith(',')
    || lastTypedText.endsWith('\n');

// Detect paste
const isPaste = lastTypedText.length > 1 && !isSpecialKey;

return endsWithTriggerChar || isSpecialKey || isPaste;

This is a nice usability improvement and aligns with expected editor behavior.

@dan-niles dan-niles force-pushed the document-support-in-expression-helper branch from 82e9f0b to bff07a2 Compare November 15, 2025 14:17
@dan-niles dan-niles marked this pull request as draft November 15, 2025 14:18
@dan-niles dan-niles changed the base branch from main to bi-1.5.x November 15, 2025 14:18
@dan-niles dan-niles force-pushed the document-support-in-expression-helper branch 4 times, most recently from 415ad73 to d3341bc Compare November 19, 2025 03:48
@dan-niles dan-niles marked this pull request as ready for review November 19, 2025 06:50
@dan-niles dan-niles force-pushed the document-support-in-expression-helper branch 2 times, most recently from d339dce to 094fda6 Compare November 19, 2025 11:21
@dan-niles dan-niles changed the base branch from bi-1.5.x to main November 19, 2025 14:38
@dan-niles dan-niles force-pushed the document-support-in-expression-helper branch from 65a9328 to 12b4080 Compare November 19, 2025 14:38
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/MarkdownPreview.tsx (1)

19-27: Fix plugin configuration error and implement proper content sanitization for user-supplied markdown.

Two critical issues found:

  1. Plugin Configuration Error (line 61): remarkGfm is incorrectly placed in rehypePlugins array. Remark plugins must be in remarkPlugins. This likely breaks GitHub Flavored Markdown support.

  2. XSS Vulnerability: User-controlled markdown from PromptMode.tsx (line 172: content={value}) and template expressions from TemplateMode.tsx (line 132: content={transformedContent}) are rendered with rehypeRaw enabled. The disallowedElements approach is insufficient—it blocks only specific tags but cannot prevent XSS via event handlers on allowed elements (<img onerror="...">), SVG-based attacks, or style expressions.

Move remarkGfm to a new remarkPlugins prop and either:

  • Remove rehypeRaw and use markdown-safe rendering only, or
  • Sanitize content with a proper HTML sanitizer (e.g., DOMPurify) before passing to MarkdownPreview
🧹 Nitpick comments (7)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/TemplateMode.tsx (1)

70-103: Harden preview fallback and optional onTogglePreview handling.

Two small robustness points:

  1. Preview when tokens / rpcManager aren’t available

transformContent only updates transformedContent when isPreviewMode && value && expressionEditorRpcManager are all truthy. If preview is toggled on before expressionEditorRpcManager is ready (or if it’s ever null), MarkdownPreview will render with the initial empty string. It would be safer to always fall back to the sanitized (or raw) value whenever tokens aren’t available, e.g.:

if (!expressionEditorRpcManager) {
    const displayValue = sanitizedExpression ? sanitizedExpression(value) : value;
    setTransformedContent(displayValue);
    return;
}
  1. onTogglePreview is optional

onTogglePreview is typed as optional, but inside the toolbar props you call it unguarded:

onTogglePreview={() => onTogglePreview(!isPreviewMode)}

Given it’s optional, it’s cleaner (and more TypeScript‑friendly) to either:

  • Guard directly on onTogglePreview:
{onTogglePreview && (
    <TemplateMarkdownToolbar
        ...
        onTogglePreview={() => onTogglePreview(!isPreviewMode)}
    />
)}
  • Or use optional chaining in the callback:
onTogglePreview={() => onTogglePreview?.(!isPreviewMode)}

The outer hasPreviewSupport check already prevents runtime issues, but tightening this up avoids relying on implicit assumptions about the prop always being passed.

Also applies to: 120-160

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/DocumentConfig.tsx (1)

33-42: Document helper pane behavior for TEMPLATE vs expression looks correct

The document helper correctly:

  • Narrows completions to compatible types per documentType.
  • Distinguishes AI document variables vs values needing wrapping.
  • Uses InputMode.TEMPLATE to decide whether to wrap in interpolation (${…}) or insert plain expressions, both for variables and the “Add from URL” flow.

The control flow (breadcrumb navigation, completion context, and minimal loader) also looks sound; no functional problems stand out.

Also applies to: 44-50, 52-92, 96-134, 147-179, 189-201, 207-218, 248-297

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/chipStyles.ts (1)

19-37: Chip styling & icon helpers are consistent with the new token model

The chip styles and helpers (TOKEN_TYPE_COLORS, icon maps, getTokenIconClass, getChipDisplayContent) align well with the new TokenType / DocumentType setup and should give clear visual differentiation for variables, parameters, properties, and documents. You might optionally tighten the typing of getTokenIconClass’s subType to DocumentType for extra safety, but functionally this looks good.

Also applies to: 39-49, 50-77, 79-90, 92-101, 103-109, 111-127

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionEditor.tsx (2)

384-406: Verify use of rawExpression when computing fieldValue for diagnostics

Line 384 computes:

const fieldValue = inputModeRef.current === InputMode.TEMPLATE && rawExpression
    ? rawExpression(watch(key))
    : watch(key);

If the form value (watch(key)) is already the raw expression (as implied by later onChange(rawValue) paths and how TemplateMode calls the language server), calling rawExpression on it again is likely backwards: rawExpression is intended to map from sanitized → raw, not raw → raw.

This could skew the string that diagnostics run against in TEMPLATE mode. It might be safer to:

  • Use watch(key) directly for diagnostics, or
  • If the stored value is actually sanitized, use rawExpression(watch(key)) consistently in all LS calls (including TemplateMode).

Worth double-checking the intended contract of sanitizedExpression/rawExpression and ensuring they’re only applied in one direction.


498-516: Template mode plumbing and helper-pane integration look good overall

The use of inputModeRef.current when:

  • Passing the current mode into getHelperPane (line 498-516),
  • Translating editor values with rawExpression in the ExpressionField and ExpandedEditor onChange handlers (lines 670-701, 760-795),
  • Restricting diagnostics to EXP/TEMPLATE,

is consistent and should avoid stale-closure issues in async callbacks. Once the small issues above are addressed, the TEMPLATE mode flow here looks structurally sound.

Also applies to: 670-701, 750-810

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (1)

20-41: Token parsing & compound detection are well-structured; be mindful of mapping/regex assumptions

The token utilities (ParsedToken, getParsedExpressionTokens, TOKEN_PATTERNS, detectTokenPatterns, and the document/variable metadata extractors) are nicely factored and line up with how CodeUtils.ts consumes them for chips and compound sequences.

Two assumptions to keep in mind:

  • mapRawToSanitized / mapSanitizedToRaw rely on sanitizedExpression being a contiguous substring of the raw expression. If sanitization ever rewrites or reorders content more aggressively (e.g., stripping tags from the middle), these mappings may become inaccurate.
  • extractDocumentMetadata uses /\$\{<ai:(\w+)>\{content:\s*([^}]+)\}\}/, so document content can’t contain } and must follow that exact pattern. That matches what wrapInDocumentType currently generates, but could miss more complex document expressions.

Given current usage, this is acceptable; just worth revisiting if sanitization or document syntax evolves.

Also applies to: 94-101, 103-137, 145-156, 158-199, 201-257, 261-274, 276-331

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CodeUtils.ts (1)

21-35: Chip widgets, token state, and Backspace behavior look robust

The refactor to:

  • Build chips via createChip with shared BASE_* styles and token-type colors/icons,
  • Track { tokens, compounds } in tokenField and recompute compounds on token changes/removals,
  • Use iterateTokenStream to decorate both compound and standalone tokens, and
  • Make Backspace delete entire compound sequences when the cursor is inside them,

is coherent and should give a much better UX for document/variable chips without breaking existing tokens. No functional problems stand out here.

Also applies to: 55-71, 84-117, 197-258, 261-322, 324-371, 378-419, 507-515

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 82e9f0b and 12b4080.

⛔ Files ignored due to path filters (4)
  • common/config/rush/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • workspaces/common-libs/font-wso2-vscode/src/icons/bi-attach-file.svg is excluded by !**/*.svg
  • workspaces/common-libs/font-wso2-vscode/src/icons/bi-audio.svg is excluded by !**/*.svg
  • workspaces/common-libs/font-wso2-vscode/src/icons/bi-image.svg is excluded by !**/*.svg
📒 Files selected for processing (45)
  • workspaces/ballerina/ballerina-side-panel/package.json (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/Form/types.ts (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/ModeSwitcher/styles.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/EditorFactory.tsx (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/ExpandedEditor.tsx (8 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/ChipComponent.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/MarkdownPreview.tsx (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/TemplateMarkdownToolbar.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/ExpressionMode.tsx (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/TemplateMode.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/types.ts (3 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/styles/markdown-preview.css (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/templateUtils.ts (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/transformToMarkdown.ts (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionEditor.tsx (15 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionField.tsx (3 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CHipTest.tsx (0 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CodeUtils.ts (8 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/chipStyles.ts (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/AutoExpandingEditableDiv.tsx (0 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipComponent.tsx (0 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipExpressionEditor.tsx (16 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/HelperPaneToggleButton.tsx (4 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/TextElement.tsx (0 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/TokenizedExpression.tsx (0 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/styles.tsx (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (3 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts (1 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/Context.tsx (1 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx (3 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsx (3 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Configurables.tsx (8 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/DocumentConfig.tsx (1 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Documents.tsx (1 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Inputs.tsx (5 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Variables.tsx (8 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (2 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx (10 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/iconUtils.tsx (2 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/types.ts (2 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/utils.ts (1 hunks)
  • workspaces/common-libs/ui-toolkit/src/components/Commons/ErrorBanner.tsx (2 hunks)
  • workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (2 hunks)
💤 Files with no reviewable changes (5)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipComponent.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/TextElement.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CHipTest.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/TokenizedExpression.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/AutoExpandingEditableDiv.tsx
🚧 Files skipped from review as they are similar to previous changes (9)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/iconUtils.tsx
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Configurables.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/HelperPaneToggleButton.tsx
  • workspaces/ballerina/ballerina-visualizer/src/Context.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/EditorFactory.tsx
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/styles.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/ModeSwitcher/styles.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-10T15:05:11.309Z
Learnt from: madushajg
Repo: wso2/vscode-extensions PR: 868
File: workspaces/bi/bi-extension/src/utils.ts:224-242
Timestamp: 2025-11-10T15:05:11.309Z
Learning: The workspaces/bi/bi-extension and workspaces/ballerina/ballerina-extension are separate VS Code extensions that are packaged and distributed independently, so they cannot share code via imports and must maintain their own implementations of common utilities.

Applied to files:

  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx
🧬 Code graph analysis (21)
workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionEditor.tsx (2)
  • ContextAwareExpressionEditorProps (49-65)
  • ExpressionEditor (306-825)
workspaces/ballerina/ballerina-side-panel/src/context/form.tsx (1)
  • useFormContext (70-70)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/ChipComponent.tsx (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (1)
  • DocumentType (61-61)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/chipStyles.ts (5)
  • getTokenIconClass (92-97)
  • StandardChip (113-120)
  • StandardIcon (123-125)
  • ChipText (127-127)
  • getChipDisplayContent (107-109)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/TemplateMarkdownToolbar.tsx (4)
workspaces/common-libs/ui-toolkit/src/styles/Theme.ts (1)
  • ThemeColors (79-104)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/templateUtils.ts (7)
  • insertMarkdownFormatting (24-74)
  • insertMarkdownLink (103-154)
  • insertMarkdownHeader (79-98)
  • insertMarkdownBlockquote (159-192)
  • insertMarkdownUnorderedList (251-257)
  • insertMarkdownOrderedList (259-265)
  • insertMarkdownTaskList (267-273)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/HelperPaneToggleButton.tsx (1)
  • HelperPaneToggleButton (81-104)
workspaces/common-libs/ui-toolkit/src/components/Swich/Swich.tsx (1)
  • Switch (146-176)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/transformToMarkdown.ts (3)
workspaces/ballerina/ballerina-extension/src/features/tracing/webview.ts (1)
  • escapeHtml (266-275)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (2)
  • getParsedExpressionTokens (111-137)
  • detectTokenPatterns (277-331)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CodeUtils.ts (1)
  • iterateTokenStream (261-322)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/MarkdownPreview.tsx (3)
workspaces/common-libs/ui-toolkit/src/styles/Theme.ts (1)
  • ThemeColors (79-104)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/ChipComponent.tsx (1)
  • ChipComponent (36-44)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (1)
  • DocumentType (61-61)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/DocumentConfig.tsx (8)
workspaces/ballerina/ballerina-core/src/interfaces/extended-lang-client.ts (1)
  • ExpressionProperty (1077-1077)
workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts (1)
  • InputMode (31-31)
workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (2)
  • useSlidingPane (298-298)
  • ScrollableContainer (182-186)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (2)
  • useHelperPaneNavigation (26-64)
  • BreadCrumbStep (21-24)
workspaces/ballerina/ballerina-visualizer/src/Context.tsx (2)
  • useModalStack (189-189)
  • POPUP_IDS (136-144)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Variables.tsx (1)
  • VariableItem (64-95)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/BreadcrumbNavigation.tsx (1)
  • BreadcrumbNavigation (28-128)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/EmptyItemsPlaceHolder.tsx (1)
  • EmptyItemsPlaceHolder (23-35)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/ExpressionMode.tsx (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipExpressionEditor.tsx (1)
  • ChipExpressionEditorComponent (96-453)
workspaces/common-libs/ui-toolkit/src/components/Commons/ErrorBanner.tsx (1)
  • ErrorBanner (46-55)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (1)
workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts (1)
  • InputMode (31-31)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Variables.tsx (3)
workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts (1)
  • InputMode (31-31)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (2)
  • useHelperPaneNavigation (26-64)
  • BreadCrumbStep (21-24)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/utils.ts (1)
  • wrapInTemplateInterpolation (22-24)
workspaces/ballerina/ballerina-side-panel/src/components/Form/types.ts (1)
workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts (1)
  • InputMode (31-31)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/chipStyles.ts (1)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (1)
  • DocumentType (61-61)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (1)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (4)
  • TokenMetadata (63-67)
  • DocumentType (61-61)
  • TokenPattern (100-105)
  • CompoundTokenSequence (89-97)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/ExpandedEditor.tsx (3)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/ExpressionMode.tsx (1)
  • ExpressionMode (36-78)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/TemplateMode.tsx (1)
  • TemplateMode (39-162)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/types.ts (1)
  • EditorMode (86-86)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipExpressionEditor.tsx (3)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CodeUtils.ts (5)
  • buildOnFocusListner (427-458)
  • CursorInfo (44-48)
  • buildOnSelectionChange (462-495)
  • expressionEditorKeymap (378-423)
  • tokensChangeEffect (197-197)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (1)
  • mapSanitizedToRaw (183-199)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/templateUtils.ts (1)
  • listContinuationKeymap (348-353)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx (5)
workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts (1)
  • InputMode (31-31)
workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (3)
  • SlidingPaneNavContainer (224-258)
  • SlidingPane (125-155)
  • SlidingPaneHeader (281-288)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/iconUtils.tsx (1)
  • getHelperPaneIcon (40-46)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Documents.tsx (1)
  • Documents (28-72)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/DocumentConfig.tsx (1)
  • DocumentConfig (52-299)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Documents.tsx (1)
workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (1)
  • SlidingPaneNavContainer (224-258)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Inputs.tsx (3)
workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts (1)
  • InputMode (31-31)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (2)
  • useHelperPaneNavigation (26-64)
  • BreadCrumbStep (21-24)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/utils.ts (1)
  • wrapInTemplateInterpolation (22-24)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/TemplateMode.tsx (7)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/types.ts (1)
  • EditorModeExpressionProps (50-81)
workspaces/ballerina/ballerina-side-panel/src/context/form.tsx (1)
  • useFormContext (70-70)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/transformToMarkdown.ts (1)
  • transformExpressionToMarkdown (45-106)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/TemplateMarkdownToolbar.tsx (1)
  • TemplateMarkdownToolbar (105-198)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/MarkdownPreview.tsx (1)
  • MarkdownPreview (56-86)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipExpressionEditor.tsx (1)
  • ChipExpressionEditorComponent (96-453)
workspaces/common-libs/ui-toolkit/src/components/Commons/ErrorBanner.tsx (1)
  • ErrorBanner (46-55)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CodeUtils.ts (3)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (2)
  • TokenMetadata (63-67)
  • CompoundTokenSequence (89-97)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/chipStyles.ts (6)
  • getChipDisplayContent (107-109)
  • getTokenTypeColor (99-101)
  • BASE_CHIP_STYLES (22-37)
  • getTokenIconClass (92-97)
  • BASE_ICON_STYLES (39-42)
  • CHIP_TEXT_STYLES (44-48)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (4)
  • ParsedToken (104-109)
  • getParsedExpressionTokens (111-137)
  • mapRawToSanitized (159-180)
  • detectTokenPatterns (277-331)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionEditor.tsx (1)
workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/utils/token.ts (1)
  • setValue (103-145)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/utils.ts (1)
workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts (1)
  • InputMode (31-31)
🪛 Biome (2.1.2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/styles/markdown-preview.css

[error] 232-232: Duplicate font names are redundant and unnecessary: Mono

Remove duplicate font names within the property

(lint/suspicious/noDuplicateFontNames)


[error] 321-321: Duplicate font names are redundant and unnecessary: Mono

Remove duplicate font names within the property

(lint/suspicious/noDuplicateFontNames)


[error] 328-328: Duplicate font names are redundant and unnecessary: Mono

Remove duplicate font names within the property

(lint/suspicious/noDuplicateFontNames)

🔇 Additional comments (46)
workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (2)

297-298: LGTM! Clean API expansion.

Re-exporting useSlidingPane makes the hook conveniently available to external consumers of this module.


38-39: No issues found. Overflow change correctly implements fixed-viewport pattern.

The change from overflow-x: scroll to hidden is intentional and correct. The SlidingWindowContainer acts as a fixed-size viewport (320px × max 350px), while scrolling responsibility is delegated to child components—specifically the ScrollableContainer component (which has overflow: auto). All actual content throughout the codebase is properly wrapped in ScrollableContainer or similar scrollable children, ensuring no content becomes inaccessible. This is standard viewport architecture with no double-scrollbar issues.

workspaces/ballerina/ballerina-side-panel/package.json (1)

31-32: LGTM! Markdown dependencies added appropriately.

The addition of rehype-raw and remark-gfm aligns with the markdown rendering enhancements in the ExpandedEditor/MarkdownPreview components.

workspaces/common-libs/ui-toolkit/src/components/Commons/ErrorBanner.tsx (2)

23-30: LGTM! Style customization support added correctly.

The optional sx prop is properly typed and threaded through to the Container's inline styles, enabling flexible style overrides while maintaining backward compatibility.


46-50: LGTM! Public API extended appropriately.

The ErrorBanner now accepts and forwards the sx prop, maintaining backward compatibility while enabling style customization.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/styles/markdown-preview.css (1)

1-580: LGTM! Comprehensive markdown stylesheet added.

This CSS provides extensive, well-structured styling for markdown content including typography, accessibility features, and interactive elements. The implementation follows standard markdown rendering patterns.

Note: The Biome lint warnings about "duplicate font names" at lines 232, 321, and 328 are false positives. The font stacks correctly specify "Liberation Mono" (a specific font) followed by monospace (a generic font family fallback), which is standard practice.

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (2)

32-39: LGTM! Navigation logic improved.

The separator logic correctly prevents a leading dot when currentValue is empty, and the refactored internal state management simplifies the API by removing the external onChange callback.


54-62: LGTM! Public API extended appropriately.

The new getCurrentNavigationPath export provides a clear, purpose-specific alias for accessing the navigation path, improving API clarity for consumers.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipExpressionEditor.tsx (8)

83-94: LGTM! Public API extended to support sanitization and template modes.

The new props enable sanitization-aware editing, helper pane state exposure, and template-specific features like list continuation. The type signatures are well-defined and backward-compatible.


106-106: LGTM! Selection tracking added.

The savedSelectionRef enables cursor position preservation across helper pane interactions, ensuring smooth user experience when inserting completions.


155-202: LGTM! Sanitization-aware completion handling implemented correctly.

The logic properly:

  • Uses saved selection when available
  • Converts between sanitized and raw expressions for API calls via mapSanitizedToRaw
  • Preserves cursor position for function argument templates
  • Clears saved selection after use to prevent stale state

241-249: LGTM! Helper pane state exposed to parent.

The onHelperPaneStateChange callback enables parent components to coordinate with the helper pane state, supporting advanced UI interactions.


257-261: LGTM! List continuation conditionally enabled.

The listContinuationKeymap is only included when enableListContinuation is true, providing opt-in support for markdown list editing.


317-336: LGTM! Sanitization integrated into token updates.

The editor correctly:

  • Applies sanitizedExpression to the displayed value
  • Passes both rawValue and sanitizedValue to token effects
  • Triggers external updates only when sanitized value differs from current doc

357-359: LGTM! Token refresh triggered on sanitization mode changes.

Scheduling a token update when sanitization props change ensures tokens are re-rendered appropriately when switching between expression and template modes.


381-388: LGTM! Escape key handling added.

The Escape key handler properly closes the helper pane and prevents event propagation, improving keyboard navigation.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/templateUtils.ts (4)

24-74: LGTM! Markdown formatting toggle implemented correctly.

The function properly handles both wrapping and unwrapping scenarios, checking both the selection itself and the surrounding text. The cursor positioning logic maintains a good user experience.


103-154: LGTM! Link formatting with smart toggling.

The link insertion logic:

  • Detects and unwraps existing [text](url) patterns
  • Handles surrounding link context with heuristics
  • Selects the URL portion for easy editing when creating new links

202-249: LGTM! Robust list toggling implementation.

The toggleList helper correctly:

  • Handles both single-line and multi-line selections
  • Preserves indentation when adding/removing list markers
  • Maintains selection range for toggle operations
  • Moves cursor to end for typing convenience

300-346: LGTM! List continuation logic well-designed.

The handleEnterForListContinuation function:

  • Detects task lists, unordered lists, and ordered lists correctly
  • Exits lists on empty items (deletes the marker)
  • Increments ordered list numbers appropriately
  • Splits lines at cursor position for partial-line edits
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/types.ts (2)

38-86: LGTM! Comprehensive primitive type detection.

The isPrimitiveType function correctly handles:

  • Direct primitive types (string, int, boolean, etc.)
  • Arrays of primitives (string[])
  • Maps with primitive values (map<string>)
  • Union types including optional types (string|int, int?)

The improved spacing enhances readability.


89-91: LGTM! Navigation arrow logic refined.

The function correctly shows navigation arrows for non-primitive types and Records, enabling drill-down navigation in the helper pane.

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/utils.ts (1)

22-24: LGTM! Template interpolation wrapper implemented correctly.

The function properly wraps values in ${} syntax when in template mode, supporting the template-aware expression insertion in helper panes.

workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts (1)

31-31: LGTM!

Clean addition to the module's public API. The export follows the established pattern and makes InputMode accessible to consumers without requiring deep imports.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/TemplateMarkdownToolbar.tsx (3)

1-32: LGTM!

Imports are well-organized and all dependencies are necessary for the toolbar functionality.


34-103: LGTM!

The styled components and interface are well-structured with proper theme integration, accessibility support (focus-visible states), and comprehensive interaction states (hover, active, disabled).


105-200: LGTM!

The component implementation follows React best practices with proper use of forwardRef, displayName, and event handling. The mouseDown prevention pattern (line 112-114) correctly maintains editor focus while allowing toolbar interactions.

workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (4)

23-37: LGTM!

The template configuration correctly handles different value type constraints with appropriate prefix/suffix patterns for ai:Prompt and string types.


39-45: LGTM!

The function handles various input types correctly with appropriate fallbacks for undefined constraints and array types.


73-84: LGTM!

The component correctly computes the template configuration and passes the helper functions to ExpressionEditor. The prop spreading order ensures explicit props take precedence appropriately.


51-71: ****

The template wrapping logic is correct and appropriately designed for Ballerina template expressions. The functions handle the intended use case properly:

  • getSanitizedExp correctly unwraps properly formatted templates (e.g., "string hello" → "hello")
  • getRawExp correctly wraps unwrapped expressions
  • The symmetrical logic prevents double-wrapping

The edge case concern (coincidental prefix/suffix matching) is negligible given the specific template syntax patterns ("string " and "") and the context of template expression editing rather than arbitrary string processing. No actual implementation issues found.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/ChipComponent.tsx (1)

1-44: LGTM!

Clean, focused component with proper TypeScript typing. The integration with utility functions (getTokenIconClass, getChipDisplayContent) and styled components follows the established patterns in the codebase.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionField.tsx (2)

44-44: LGTM!

The addition of the rawExpression prop is consistent with the existing sanitizedExpression pattern and properly typed.


126-162: LGTM!

The rawExpression prop is correctly forwarded to ChipExpressionEditorComponent alongside sanitizedExpression, maintaining symmetry in the template expression handling flow.

workspaces/ballerina/ballerina-side-panel/src/components/Form/types.ts (2)

23-23: LGTM!

Import is necessary for the type signature extension and follows standard import patterns.


188-189: LGTM!

The optional inputMode parameter extends the helper pane API to support mode-aware behavior while maintaining backward compatibility.

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Documents.tsx (2)

22-26: LGTM!

The AIDocumentType enum values correctly use the ai: namespace prefix for Ballerina document types. The previous enum value mismatch has been properly addressed.


28-72: LGTM!

The component provides a clean, consistent interface for selecting document types. The three items follow a uniform pattern with appropriate icons and navigation wiring.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/MarkdownPreview.tsx (2)

29-46: LGTM!

The styling updates properly integrate with the imported markdown-preview.css and use theme colors for consistency.


56-86: LGTM with security measures in place.

The implementation includes appropriate security controls:

  • Dangerous elements (script, iframe, object, embed) are disabled/disallowed
  • Custom chip renderer safely extracts node properties with optional chaining

The custom chip component (lines 67-76) handles token rendering with sensible defaults (TokenType.VARIABLE fallback on line 71).

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx (1)

39-42: inputMode and Documents wiring looks consistent.

The new inputMode?: InputMode prop is correctly threaded from HelperPaneNewProps into HelperPaneNewEl, passed down to Variables, Inputs, Configurables, and DocumentConfig, and forwarded via getHelperPaneNew. The Documents and DocumentConfig panes are also correctly registered in the sliding window and gated on forcedValueTypeConstraint?.includes(AI_PROMPT_TYPE), which lines up with the AI prompt use case.

Also applies to: 72-73, 98-100, 370-371, 387-388, 429-431, 433-455, 531-532

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/ExpressionMode.tsx (1)

23-24: Expression mode wiring for sanitization and errors looks good.

Passing sanitizedExpression, rawExpression, and getHelperPane through to ChipExpressionEditorComponent matches the multi-mode editor design, and the conditional ErrorBanner rendering based on error vs formDiagnostics keeps error display centralized without changing editor behavior.

Also applies to: 42-48, 55-75

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Inputs.tsx (1)

24-25: Template-aware input insertion and navigation look correct.

Using useHelperPaneNavigation("Inputs") to derive navigationPath and then:

  • Building completionContext from navigationPath vs currentValue,
  • Computing offset from completionContext.length, and
  • Wrapping the final fullPath with wrapInTemplateInterpolation(fullPath, inputMode)

gives the expected behavior for both expression and template modes while keeping the breadcrumb navigation coherent. The updated completion fetch and filtering logic still respects the root/parameter vs nested-field distinction.

Also applies to: 34-43, 85-100, 112-118, 154-160

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/types.ts (1)

22-24: Extended EditorModeExpressionProps and EditorMode union align with new modes.

Adding sanitizedExpression, rawExpression, optional preview controls, and error / formDiagnostics to EditorModeExpressionProps, plus extending EditorMode with "template", matches how ExpressionMode and TemplateMode are now wired. The surface area looks consistent with the multi-mode editor and form‑diagnostics needs.

Also applies to: 50-81, 86-86

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (1)

19-29: Token/type model for TEMPLATE & documents looks coherent

The new InputMode.TEMPLATE, TokenType enum, DocumentType, TokenMetadata, CompoundTokenSequence, and TokenPattern definitions are internally consistent and line up with how they’re consumed in chipStyles.ts, utils.ts, and CodeMirror utilities. Only thing to double‑check is that DocumentType string literals ("ImageDocument" | "FileDocument" | "AudioDocument") stay in sync with the values emitted in document expressions and in AIDocumentType to avoid icon/metadata mismatches.

Also applies to: 31-42, 61-68, 69-81, 88-105

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/ExpandedEditor.tsx (1)

28-34: Expanded editor TEMPLATE mode wiring looks solid

Template mode is cleanly integrated into MODE_COMPONENTS, props (including sanitizedExpression, rawExpression, getHelperPane, error, formDiagnostics) are correctly scoped to expression/template modes, and the mode state reset on defaultMode change avoids stale mode when switching fields. No functional issues spotted here.

Also applies to: 35-64, 107-113, 148-153, 155-172, 180-187, 215-250

@dan-niles dan-niles force-pushed the document-support-in-expression-helper branch from 12b4080 to 458b5b3 Compare November 19, 2025 15:46
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (1)

32-45: Breadcrumb navigation should not rely solely on label matching

navigateToBreadcrumb locates the step by label:

const index = breadCrumbSteps.findIndex(item => item.label === step.label);

If different levels share the same label (e.g. nested records with the same field name), clicking a deeper breadcrumb will jump to the first occurrence instead of the intended one.

Since you already have replaceText and the caller passes the full BreadCrumbStep, it would be more robust to match on something unique (e.g. replaceText or the array index passed from the UI) rather than just label.

Also applies to: 54-55, 57-63

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CodeUtils.ts (1)

55-125: Ensure ChipWidget.eq accounts for type/metadata to avoid stale chip rendering

ChipWidget.eq only compares text, start, and end. Now that styling and content can depend on type and metadata (e.g., documentType affecting icon/color and metadata.content for display), a change in metadata with identical text and range will not cause the widget to re-render, leaving the chip visually out of sync.

Consider including type and at least the relevant metadata fields in the equality check:

-        eq(other: ChipWidget) {
-            return other.text === this.text && other.start === this.start && other.end === this.end;
-        }
+        eq(other: ChipWidget) {
+            return (
+                other.text === this.text &&
+                other.start === this.start &&
+                other.end === this.end &&
+                other.type === this.type &&
+                JSON.stringify(other.metadata) === JSON.stringify(this.metadata)
+            );
+        }

You can optimize the metadata comparison if you know exactly which fields drive rendering.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/MarkdownPreview.tsx (1)

23-83: Wire remarkGfm under remarkPlugins, not rehypePlugins, to enable GFM correctly

The remark-gfm plugin is a remark plugin that should be passed via ReactMarkdown's remarkPlugins prop, while raw HTML is enabled via rehype-raw in rehypePlugins. Currently, remarkGfm is incorrectly passed in rehypePlugins, which prevents GitHub-Flavored Markdown features (tables, task lists, etc.) from being applied correctly and may cause incompatibilities with the rehype stage.

-            <div className="markdown-body">
-                <ReactMarkdown
-                    rehypePlugins={[rehypeRaw, remarkGfm]}
+            <div className="markdown-body">
+                <ReactMarkdown
+                    remarkPlugins={[remarkGfm]}
+                    rehypePlugins={[rehypeRaw]}
                     components={{
                         // Prevent rendering of potentially dangerous elements
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx (1)

271-346: Hard-coded menu item ref indices are fragile.

The menu items use sparse, hard-coded indices (0, 2, 1, 3, 4, 5) for menuItemRefs.current[index]. If the conditional rendering logic changes (e.g., "Create Value" visibility), these indices could point to the wrong elements or become invalid, breaking keyboard navigation and focus management.

Consider deriving indices dynamically based on the actual render order to keep the ref array aligned with the visual order.

♻️ Duplicate comments (2)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx (1)

102-105: Keyboard navigation count can desync from visible menu items.

This issue was already flagged in a previous review. The currentMenuItemCount is calculated based on constraints, but the actual number of rendered menu items depends on runtime conditions (e.g., valueCreationOptions.length > 0 for "Create Value", forcedValueTypeConstraint?.includes(AI_PROMPT_TYPE) for "Documents"). This can cause keyboard navigation to skip or miss rendered items.

Also applies to: 271-287, 289-346

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionEditor.tsx (1)

567-575: The field reset issue flagged in previous reviews is still present.

Lines 571-572 call setValue(key, rawExpression("")), which clears the field value when confirming an EXP→TEMPLATE mode switch. The past review comment indicated this was "Addressed in commits 3c35b23 to 458b5b3", but the code remains unchanged.

This should either:

  1. Be removed entirely if no transformation is needed: just switch the mode
  2. Transform the current value: setValue(key, rawExpression(watch(key)))

Clearing the field on mode switch is unexpected UX and discards user input.

🧹 Nitpick comments (10)
workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (2)

73-84: Consider reordering props for clearer precedence.

The explicit props at lines 75-77 are placed before the spreads, meaning they can be overridden by ...form, ...expressionEditor, or ...props. While ExpressionEditor likely handles this with fallback logic, placing explicit props after spreads would make the intended precedence more obvious and improve maintainability.

Apply this diff to clarify precedence:

     return (
         <ExpressionEditor
-            fileName={fileName}
-            targetLineRange={targetLineRange}
-            helperPaneZIndex={props.helperPaneZIndex}
             {...form}
             {...expressionEditor}
             {...props}
+            fileName={fileName}
+            targetLineRange={targetLineRange}
+            helperPaneZIndex={props.helperPaneZIndex}
             rawExpression={getRawExp}
             sanitizedExpression={getSanitizedExp}
         />
     );

49-71: Consider memoizing helper functions to prevent unnecessary re-renders.

The templateConfig, getSanitizedExp, and getRawExp are recreated on every render. If ExpressionEditor or its children use these in dependency arrays, it could trigger unnecessary re-renders. Consider memoizing them for better performance.

Apply this diff to memoize the values:

+import React, { useMemo, useCallback } from "react";
-import React from "react";
 import { useFormContext } from "../../context";
 import { ContextAwareExpressionEditorProps, ExpressionEditor } from "./ExpressionEditor";

 export const ContextAwareRawExpressionEditor = (props: ContextAwareExpressionEditorProps) => {
     const { form, expressionEditor, targetLineRange, fileName } = useFormContext();
-    const templateConfig = getTemplateConfig(props.field.valueTypeConstraint);
+    const templateConfig = useMemo(
+        () => getTemplateConfig(props.field.valueTypeConstraint),
+        [props.field.valueTypeConstraint]
+    );
 
-    const getSanitizedExp = (value: string) => {
+    const getSanitizedExp = useCallback((value: string) => {
         if (!value) {
             return value;
         }
         const { prefix, suffix } = templateConfig;
         if (value.startsWith(prefix) && value.endsWith(suffix)) {
             return value.slice(prefix.length, -suffix.length);
         }
         return value;
-    };
+    }, [templateConfig]);
 
-    const getRawExp = (value: string) => {
+    const getRawExp = useCallback((value: string) => {
         if (!value) {
             return value;
         }
         const { prefix, suffix } = templateConfig;
         if (!value.startsWith(prefix) && !value.endsWith(suffix)) {
             return `${prefix}${value}${suffix}`;
         }
         return value;
-    };
+    }, [templateConfig]);
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/DocumentConfig.tsx (1)

64-69: Hook dependencies rely on state props; verify against your lint rules

Both navigationPath and the useEffect for completions key off breadCrumbSteps/completionContext but omit several referenced values (e.g., getCurrentNavigationPath, handleRetrieveCompletions, field, triggerCharacters, filteredCompletions, showContent) from their dependency arrays.

Behavior‑wise this is probably fine given these values are stable in practice, but if you have react-hooks/exhaustive-deps enabled you may get warnings. If that’s the case, either:

  • Add the missing deps and rely on memoized callbacks/contexts, or
  • Explicitly disable the rule for these hooks with a comment and a short justification.

Also applies to: 71-94

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (1)

139-156: Completion filtering behavior changed; validate UX impact

filterCompletionsByPrefixAndType now:

  • For empty prefix: returns only kind === 'field'.
  • For non‑empty prefix: returns function | variable | field whose label starts with the prefix.

This is a reasonable heuristic, but it does change the surface of what users see initially (no functions/variables until they start typing). It’s worth double‑checking this against expected UX and any existing tests to ensure it matches the intended discovery behavior for the helper pane.

If you’d like, I can sketch a small set of unit tests around this helper to lock in the desired filtering semantics.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CodeUtils.ts (1)

261-371: iterateTokenStream + chipPlugin decoration pipeline is well-structured; consider tightening types

The new iterateTokenStream abstraction correctly:

  • Emits compounds first (grouped by startIndex).
  • Skips tokens consumed by compounds.
  • Skips START/END event tokens and validates ranges against docLength.

chipPlugin.buildDecorations using this iterator and createChip with metadata is a nice separation of concerns. The only minor nit is typing widgets as any[]; you can make this more explicit without changing behavior:

-            const widgets: any[] = []; // Type as any[] to allow pushing Range<Decoration>
+            const widgets: Range<Decoration>[] = [];

This keeps the API surface cleaner for future refactors.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/TemplateMarkdownToolbar.tsx (1)

34-198: Toolbar wiring to markdown insert utilities and preview toggle looks correct

The toolbar correctly:

  • Routes actions to insertMarkdown* helpers with the provided editorView.
  • Keeps editor focus by preventing default on onMouseDown.
  • Disables formatting actions and the helper-pane toggle when isPreviewMode is true.
  • Integrates cleanly with the Switch for Edit/Preview.

Given the helpers already no-op on null views, the behavior is safe as-is.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/styles/markdown-preview.css (1)

229-337: Address Biome duplicate-font-name warnings in monospace stacks

Static analysis flags duplicate font names (e.g., Mono) in the monospace font stacks used for kbd and code-related elements. While behavior is fine at runtime, these warnings may fail CI.

You can either:

  • Slightly simplify the stacks (e.g., drop one of the overlapping *Mono entries), or
  • Suppress this specific lint rule for these declarations if you prefer to keep the GitHub-equivalent stack verbatim.

No functional impact, but worth resolving for a clean lint run.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/templateUtils.ts (1)

103-154: Link insertion logic works but has a minor inconsistency.

The link unwrapping/wrapping logic is functional, but line 132 has a comment noting "−1 to keep the ')' logic aligned", which suggests the calculation might not be entirely correct.

Consider verifying the surrounding link unwrapping logic more carefully:

{ from: to, to: to + urlLen - 1, insert: '' } // Line 132

Should this be to + urlLen without the -1? The urlMatch[0] includes the full ](url) pattern, so the length should be correct without adjustment.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/styles.tsx (2)

83-110: Refactor to reduce duplication and use theme colors.

The DocumentChip component shares most of its styling with the Chip component (lines 54-81), differing only in colors and border. Additionally, the hardcoded rgba(59, 130, 246, ...) values bypass the theme system.

Consider refactoring to:

  1. Extract shared styles into a base component or use props to customize colors
  2. Replace hardcoded rgba values with ThemeColors constants or CSS variables for theme consistency

Example refactor using a prop-based approach:

const BaseChip = styled.div<{ variant?: 'default' | 'document' }>`
    border-radius: 4px;
    background-color: ${props => 
        props.variant === 'document' 
            ? 'rgba(59, 130, 246, 0.15)' 
            : 'rgba(0, 122, 204, 0.3)'
    };
    color: var(--vscode-input-foreground, ${props => props.variant === 'document' ? 'inherit' : 'white'});
    ${props => props.variant === 'document' && 'border: 1px solid rgba(59, 130, 246, 0.4);'}
    cursor: pointer;
    margin: 2px 0px;
    font-size: 12px;
    padding: 2px 10px;
    display: inline-flex;
    justify-content: center;
    align-items: center;
    min-height: 20px;
    min-width: 25px;
    transition: all 0.2s ease;
    outline: none;
    vertical-align: middle;
    user-select: none;
    -webkit-user-select: none;

    &:hover {
        background-color: ${props => 
            props.variant === 'document' 
                ? 'rgba(59, 130, 246, 0.25)' 
                : 'rgba(0, 122, 204, 0.5)'
        };
    }

    &:active {
        box-shadow: ${props => 
            props.variant === 'document' 
                ? '0 0 0 2px rgba(59, 130, 246, 0.8)' 
                : '0 0 0 2px rgba(0, 122, 204, 0.8)'
        };
        ${props => props.variant === 'default' && `background-color: ${ThemeColors.PRIMARY};`}
    }
`;

export const Chip = styled(BaseChip)``;
export const DocumentChip = styled(BaseChip).attrs({ variant: 'document' })``;

Then update the hardcoded colors to use ThemeColors or add new theme color constants.


112-118: Consider using theme colors for consistency.

The icon color uses the same hardcoded rgba(59, 130, 246, 0.9) as DocumentChip. For better theme support, consider using a theme color constant.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 12b4080 and 458b5b3.

⛔ Files ignored due to path filters (4)
  • common/config/rush/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • workspaces/common-libs/font-wso2-vscode/src/icons/bi-attach-file.svg is excluded by !**/*.svg
  • workspaces/common-libs/font-wso2-vscode/src/icons/bi-audio.svg is excluded by !**/*.svg
  • workspaces/common-libs/font-wso2-vscode/src/icons/bi-image.svg is excluded by !**/*.svg
📒 Files selected for processing (47)
  • workspaces/ballerina/ballerina-extension/grammar/ballerina-grammar (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/package.json (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/Form/types.ts (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/ModeSwitcher/styles.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/EditorFactory.tsx (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/ExpandedEditor.tsx (8 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/ChipComponent.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/MarkdownPreview.tsx (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/TemplateMarkdownToolbar.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/ExpressionMode.tsx (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/TemplateMode.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/types.ts (3 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/styles/markdown-preview.css (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/templateUtils.ts (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/transformToMarkdown.ts (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionEditor.tsx (15 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionField.tsx (3 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CHipTest.tsx (0 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CodeUtils.ts (8 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/chipStyles.ts (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/AutoExpandingEditableDiv.tsx (0 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipComponent.tsx (0 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipExpressionEditor.tsx (16 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/HelperPaneToggleButton.tsx (4 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/TextElement.tsx (0 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/TokenizedExpression.tsx (0 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/styles.tsx (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (2 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (3 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (1 hunks)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts (1 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/Context.tsx (1 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx (3 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsx (3 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Configurables.tsx (8 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/DocumentConfig.tsx (1 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Documents.tsx (1 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Functions.tsx (5 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Inputs.tsx (5 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Variables.tsx (8 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (2 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx (11 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/iconUtils.tsx (2 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/types.ts (2 hunks)
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/utils.ts (1 hunks)
  • workspaces/common-libs/ui-toolkit/src/components/Commons/ErrorBanner.tsx (2 hunks)
  • workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (2 hunks)
💤 Files with no reviewable changes (5)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/TextElement.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CHipTest.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/AutoExpandingEditableDiv.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipComponent.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/TokenizedExpression.tsx
✅ Files skipped from review due to trivial changes (1)
  • workspaces/ballerina/ballerina-extension/grammar/ballerina-grammar
🚧 Files skipped from review as they are similar to previous changes (20)
  • workspaces/ballerina/ballerina-side-panel/src/components/Form/types.ts
  • workspaces/ballerina/ballerina-visualizer/src/Context.tsx
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/iconUtils.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/EditorFactory.tsx
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/types.ts
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/HelperPaneToggleButton.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/ChipComponent.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/transformToMarkdown.ts
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGenerator/index.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Variables.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/chipStyles.ts
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionField.tsx
  • workspaces/common-libs/ui-toolkit/src/components/Commons/ErrorBanner.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts
  • workspaces/ballerina/ballerina-side-panel/package.json
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/Forms/FormGeneratorNew/index.tsx
  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Configurables.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/ExpressionMode.tsx
  • workspaces/ballerina/ballerina-side-panel/src/components/ModeSwitcher/styles.tsx
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-10T15:05:11.309Z
Learnt from: madushajg
Repo: wso2/vscode-extensions PR: 868
File: workspaces/bi/bi-extension/src/utils.ts:224-242
Timestamp: 2025-11-10T15:05:11.309Z
Learning: The workspaces/bi/bi-extension and workspaces/ballerina/ballerina-extension are separate VS Code extensions that are packaged and distributed independently, so they cannot share code via imports and must maintain their own implementations of common utilities.

Applied to files:

  • workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx
🧬 Code graph analysis (15)
workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionEditor.tsx (2)
  • ContextAwareExpressionEditorProps (49-65)
  • ExpressionEditor (306-826)
workspaces/ballerina/ballerina-side-panel/src/context/form.tsx (1)
  • useFormContext (70-70)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/utils.ts (1)
workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts (1)
  • InputMode (31-31)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/types.ts (1)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/index.ts (1)
  • EditorMode (20-20)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/MarkdownPreview.tsx (3)
workspaces/common-libs/ui-toolkit/src/styles/Theme.ts (1)
  • ThemeColors (79-104)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/ChipComponent.tsx (1)
  • ChipComponent (36-44)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (1)
  • DocumentType (61-61)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Documents.tsx (1)
workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (1)
  • SlidingPaneNavContainer (224-258)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx (4)
workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts (1)
  • InputMode (31-31)
workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (3)
  • SlidingPaneNavContainer (224-258)
  • SlidingPane (125-155)
  • SlidingPaneHeader (281-288)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Documents.tsx (1)
  • Documents (28-72)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/DocumentConfig.tsx (1)
  • DocumentConfig (52-299)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipExpressionEditor.tsx (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CodeUtils.ts (5)
  • buildOnFocusListner (427-458)
  • CursorInfo (44-48)
  • buildOnSelectionChange (462-495)
  • expressionEditorKeymap (378-423)
  • tokensChangeEffect (197-197)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/templateUtils.ts (1)
  • listContinuationKeymap (348-353)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/TemplateMarkdownToolbar.tsx (4)
workspaces/common-libs/ui-toolkit/src/styles/Theme.ts (1)
  • ThemeColors (79-104)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/templateUtils.ts (7)
  • insertMarkdownFormatting (24-74)
  • insertMarkdownLink (103-154)
  • insertMarkdownHeader (79-98)
  • insertMarkdownBlockquote (159-192)
  • insertMarkdownUnorderedList (251-257)
  • insertMarkdownOrderedList (259-265)
  • insertMarkdownTaskList (267-273)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/HelperPaneToggleButton.tsx (1)
  • HelperPaneToggleButton (81-104)
workspaces/common-libs/ui-toolkit/src/components/Swich/Swich.tsx (1)
  • Switch (146-176)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (1)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (4)
  • TokenMetadata (63-67)
  • DocumentType (61-61)
  • TokenPattern (100-105)
  • CompoundTokenSequence (89-97)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Inputs.tsx (2)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (2)
  • useHelperPaneNavigation (26-64)
  • BreadCrumbStep (21-24)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/utils.ts (1)
  • wrapInTemplateInterpolation (22-24)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/TemplateMode.tsx (7)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/types.ts (1)
  • EditorModeExpressionProps (50-81)
workspaces/ballerina/ballerina-side-panel/src/context/form.tsx (1)
  • useFormContext (70-70)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/transformToMarkdown.ts (1)
  • transformExpressionToMarkdown (45-106)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/TemplateMarkdownToolbar.tsx (1)
  • TemplateMarkdownToolbar (105-198)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/controls/MarkdownPreview.tsx (1)
  • MarkdownPreview (56-86)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipExpressionEditor.tsx (1)
  • ChipExpressionEditorComponent (96-463)
workspaces/common-libs/ui-toolkit/src/components/Commons/ErrorBanner.tsx (1)
  • ErrorBanner (46-55)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Functions.tsx (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/index.ts (1)
  • InputMode (31-31)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/utils.ts (1)
  • wrapInTemplateInterpolation (22-24)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/DocumentConfig.tsx (7)
workspaces/ballerina/ballerina-core/src/interfaces/extended-lang-client.ts (1)
  • ExpressionProperty (1077-1077)
workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (1)
  • useSlidingPane (298-298)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/hooks/useHelperPaneNavigation.tsx (2)
  • useHelperPaneNavigation (26-64)
  • BreadCrumbStep (21-24)
workspaces/ballerina/ballerina-visualizer/src/Context.tsx (2)
  • useModalStack (189-189)
  • POPUP_IDS (136-144)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Variables.tsx (1)
  • VariableItem (64-95)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/BreadcrumbNavigation.tsx (1)
  • BreadcrumbNavigation (28-128)
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Components/EmptyItemsPlaceHolder.tsx (1)
  • EmptyItemsPlaceHolder (23-35)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/ExpandedEditor.tsx (3)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/ExpressionMode.tsx (1)
  • ExpressionMode (36-78)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/TemplateMode.tsx (1)
  • TemplateMode (39-162)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/types.ts (1)
  • EditorMode (86-86)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CodeUtils.ts (3)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (2)
  • TokenMetadata (63-67)
  • CompoundTokenSequence (89-97)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/chipStyles.ts (6)
  • getChipDisplayContent (107-109)
  • getTokenTypeColor (99-101)
  • BASE_CHIP_STYLES (22-37)
  • getTokenIconClass (92-97)
  • BASE_ICON_STYLES (39-42)
  • CHIP_TEXT_STYLES (44-48)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (4)
  • ParsedToken (104-109)
  • getParsedExpressionTokens (111-137)
  • mapRawToSanitized (159-180)
  • detectTokenPatterns (277-331)
🪛 Biome (2.1.2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/styles/markdown-preview.css

[error] 232-232: Duplicate font names are redundant and unnecessary: Mono

Remove duplicate font names within the property

(lint/suspicious/noDuplicateFontNames)


[error] 321-321: Duplicate font names are redundant and unnecessary: Mono

Remove duplicate font names within the property

(lint/suspicious/noDuplicateFontNames)


[error] 328-328: Duplicate font names are redundant and unnecessary: Mono

Remove duplicate font names within the property

(lint/suspicious/noDuplicateFontNames)

🔇 Additional comments (30)
workspaces/common-libs/ui-toolkit/src/components/ExpressionEditor/components/Common/SlidingPane/index.tsx (2)

33-43: Verify scroll behavior after changing SlidingWindowContainer to overflow-y: hidden.

With max-height: 350px and overflow-y: hidden, any pane content that isn’t wrapped in ScrollableContainer (or another scrollable child) will now be clipped instead of scrolling on the outer container. Please double‑check existing SlidingPane usages to ensure long content is always inside a scrollable child so we don’t regress accessibility/scroll behavior in older panes.


297-298: Re‑exporting useSlidingPane looks good.

Re‑exporting the hook from this index module is consistent with how the rest of the API is exposed and should simplify consumers of the helper pane without changing semantics.

workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (2)

23-37: LGTM! Clear template configuration structure.

The TemplateConfig interface and TEMPLATE_CONFIGS mapping provide a clean way to define prefix/suffix rules for different type constraints. The distinction between ai:Prompt (backticks only) and string (with "string " prefix) is appropriate.


39-45: LGTM! Consider union type scenarios.

The function correctly resolves template configuration. Line 43 takes the first element when the constraint is an array, which is reasonable for most cases. If union types with conflicting template requirements become a concern, this logic may need refinement.

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/utils/utils.ts (1)

19-24: Template interpolation wrapper looks good

The helper cleanly centralizes ${...} wrapping for template mode and keeps behavior transparent for other modes. No issues from a correctness or API‑shape perspective.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (1)

28-40: Parsed token construction matches semantic token encoding

The combination of TOKEN_TYPE_INDEX_MAP, getTokenChunks, and getParsedExpressionTokens correctly applies the (deltaLine, deltaStartChar) semantics from semantic tokens to reconstruct absolute [start, end) ranges and map numeric types to TokenType.

This provides a solid base for the downstream pattern detection and metadata extraction.

Also applies to: 103-137

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CodeUtils.ts (4)

197-259: TokenFieldState update and tokensChangeEffect/compounds recomputation look solid

The TokenFieldState structure and tokenField.update logic (mapping positions through tr.changes, parsing tokens from the payload, mapping raw→sanitized positions, and recomputing compounds on both tokensChangeEffect and removeChipEffect) are consistent and defensive. Recomputing compounds once per token change/removal keeps decoration logic simple and predictable.

No issues from a correctness standpoint here.


379-419: Backspace compound deletion behavior is consistent and safe

The Backspace handler correctly:

  • Deletes entire compound sequences when the cursor is inside a compound (dispatching multiple removeChipEffects and clearing the underlying range).
  • Falls back to per-token deletion outside compounds.
  • Returns false when no token/compound is affected, allowing the default keymap to handle standard text deletion.

The cursor range checks and use of tokenField(state, false) look good; no functional issues spotted.


507-515: Undo/redo-triggered token refetch is a useful addition

The new undo/redo branch in buildNeedTokenRefetchListner ensures tokens are re-fetched whenever the document changes via history operations, not just direct input. That closes a common desync gap between doc text and token metadata.

Implementation is straightforward and fits well with the existing listener.


609-619: Helper pane Escape key handling remains correct with explicit EditorView typing

Typing the _view parameter as EditorView in buildHelperPaneKeymap is a small but helpful clarity improvement. The logic (closing the helper pane only when open, otherwise delegating) is unchanged and correct.

No action needed.

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Documents.tsx (1)

22-71: Documents view and AIDocumentType enum are consistent and well-structured

The AIDocumentType enum values align with the AI document type strings, and each SlidingPaneNavContainer correctly passes the corresponding type into DOCUMENT_CONFIG. Labels and icons are clear for File/Image/Audio entries.

No issues spotted here.

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Functions.tsx (1)

20-20: LGTM: Clean template mode integration for function insertions.

The inputMode prop is properly threaded through and used to wrap function insertion values in template interpolation syntax (${...}) when in template mode. This implementation is consistent with the pattern used in other helper pane views.

Also applies to: 39-39, 50-50, 62-62, 181-182

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/index.tsx (1)

24-25: LGTM: Documents support and inputMode threading implemented correctly.

The Documents and DocumentConfig panes are properly wired into the sliding pane system, conditionally rendered when AI_PROMPT_TYPE is in forcedValueTypeConstraint, and the inputMode prop is correctly threaded through all child components (Variables, Inputs, Functions, Configurables, DocumentConfig).

Also applies to: 39-39, 72-72, 334-346, 434-456, 532-532

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/types.ts (1)

22-23: LGTM: Clean type extensions for template mode and preview support.

The type additions properly extend EditorModeExpressionProps with preview-related props (isPreviewMode, onTogglePreview), expression transformation functions (sanitizedExpression, rawExpression), and diagnostics (error, formDiagnostics). All new props are optional, maintaining backward compatibility. The addition of "template" to the EditorMode union is straightforward.

Also applies to: 49-81, 86-86

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/TemplateMode.tsx (1)

39-162: Well-structured template mode implementation with preview support.

The component cleanly separates editing mode (using ChipExpressionEditorComponent) from preview mode (using MarkdownPreview), with proper toolbar integration for markdown formatting. The token-based transformation to markdown and error banner rendering are well implemented.

workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Inputs.tsx (1)

24-24: LGTM: Navigation-based context and template mode integration are correct.

The refactor to use getCurrentNavigationPath() for building completion context is sound. The offset logic correctly uses completionContext.length when navigating into objects and 0 at the root. The handleItemSelect properly builds the full path from navigationPath and wraps it in template interpolation when inputMode is TEMPLATE. This aligns with the broader template mode integration across helper pane views.

Also applies to: 29-29, 42-42, 86-86, 90-90, 94-123, 154-168

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/ExpandedEditor.tsx (1)

184-186: LGTM!

The effect correctly resets the mode when the defaultMode prop changes, ensuring the local state stays synchronized with parent-driven mode changes.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionEditor.tsx (3)

345-360: LGTM! Good use of ref to avoid stale closures.

Using inputModeRef and keeping it synchronized with the inputMode state correctly prevents stale closure issues in callbacks like onChange and getExpressionEditorDiagnostics, where the mode needs to be checked at the time of execution rather than at the time of callback creation.


524-525: LGTM! Guards against runtime errors.

Normalizing watch(key) before calling trim() correctly prevents runtime errors when the field value is undefined or not a string, addressing the concern from previous reviews.


432-440: Verify the template mode initialization logic for edge cases.

The condition on line 435 checks sanitized !== initialFieldValue.current || !initialFieldValue.current || initialFieldValue.current.trim() === '', which decides between TEMPLATE and EXP modes.

Consider the edge case where initialFieldValue.current is a non-empty string but sanitized is an empty string (e.g., a value that gets completely sanitized away). This would trigger TEMPLATE mode, which might be correct, but verify this is the intended behavior.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/components/ChipExpressionEditor.tsx (5)

106-225: LGTM! Well-implemented cursor preservation pattern.

The savedSelectionRef correctly preserves the user's cursor position across helper pane interactions. The implementation:

  • Saves selection on relevant events (change, focus, selection change)
  • Falls back to current selection if saved is null
  • Clears after use to avoid stale state

This ensures a smooth UX when inserting items from the helper pane.


167-194: Function argument extraction logic handles template interpolation correctly.

The enhanced logic correctly handles both plain function calls (func()) and string template interpolations (${func()}). The regex pattern and cursor position adjustments properly extract the function definition for argument retrieval.

The comment on line 162-166 correctly notes this is a workaround until the API provides proper completion templates with $1, $2 placeholders.


267-271: LGTM! Conditional keymap inclusion.

Conditionally merging the listContinuationKeymap based on the enableListContinuation prop correctly enables markdown list continuation only when template mode requires it, avoiding unintended behavior in other editor contexts.


391-398: LGTM! Standard escape key handling.

The Escape key handler correctly closes the helper pane with proper event handling (preventDefault and stopPropagation) to prevent interference with other handlers.


327-343: LGTM! Proper sanitization handling for display and tokenization.

The code correctly:

  • Uses sanitizedExpression to compute the display value (line 327)
  • Passes both rawValue and sanitizedValue to tokensChangeEffect (lines 339-343)

This separation enables template mode to render chips while preserving the underlying raw expression value.

workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/utils/templateUtils.ts (3)

24-74: LGTM! Well-structured markdown formatting toggle.

The insertMarkdownFormatting function correctly:

  • Detects and unwraps internally formatted text
  • Detects and unwraps surrounding formatting
  • Wraps unformatted selections
  • Preserves selection/cursor position throughout

The logic handles edge cases properly and maintains good UX.


202-249: LGTM! Robust generic list toggle implementation.

The toggleList function correctly handles:

  • Both multi-line selections and single-line/cursor cases
  • Indentation preservation
  • Toggling all lines uniformly (on or off)
  • Selection preservation for multi-line edits vs. cursor positioning for typing

The hasSelection check (line 209) provides good UX by preserving the selection range when toggling existing lists but moving the cursor to the end when creating a new list item.


300-346: LGTM! Proper list continuation on Enter.

The handleEnterForListContinuation function implements standard markdown editor behavior:

  • Exits the list when Enter is pressed on an empty list item (lines 318-324)
  • Continues the list with the next marker when pressed on non-empty items (lines 327-342)
  • Handles cursor position correctly when splitting lines mid-content

This provides a smooth markdown editing experience.

workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/styles.tsx (2)

54-81: LGTM! Improved chip centering and visual styling.

The changes to use inline-flex with justify-content and align-items center improve the chip alignment, and the reduced background opacity (0.3) provides better visual hierarchy.


120-128: LGTM! Proper text overflow handling.

The component correctly implements text truncation with ellipsis, which is appropriate for chip-based UI elements with limited space.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (2)

39-45: Handle array valueTypeConstraint more robustly in getTemplateConfig

When valueTypeConstraint is an array, always taking index 0 can ignore later entries that actually have a template config (e.g., unions where the first element is unsupported but a later one is "ai:Prompt" or "string"). Consider iterating and returning the first constraint that exists in TEMPLATE_CONFIGS, falling back only if none match.

-const getTemplateConfig = (valueTypeConstraint?: string | string[]): TemplateConfig => {
-    if (!valueTypeConstraint) {
-        return { prefix: "`", suffix: "`" };
-    }
-    const constraint = Array.isArray(valueTypeConstraint) ? valueTypeConstraint[0] : valueTypeConstraint;
-    return TEMPLATE_CONFIGS[constraint] || { prefix: "`", suffix: "`" };
-};
+const DEFAULT_TEMPLATE_CONFIG: TemplateConfig = { prefix: "`", suffix: "`" };
+
+const getTemplateConfig = (valueTypeConstraint?: string | string[]): TemplateConfig => {
+    if (!valueTypeConstraint) {
+        return DEFAULT_TEMPLATE_CONFIG;
+    }
+    const constraints = Array.isArray(valueTypeConstraint)
+        ? valueTypeConstraint
+        : [valueTypeConstraint];
+
+    for (const c of constraints) {
+        const config = TEMPLATE_CONFIGS[c];
+        if (config) {
+            return config;
+        }
+    }
+
+    return DEFAULT_TEMPLATE_CONFIG;
+};

73-83: Minor JSX cleanup and optional callback memoization

helperPaneZIndex is passed explicitly and then again via {...props}, so the explicit prop is redundant and can be dropped. Also, if ExpressionEditor ever depends on stable function identities for rawExpression/sanitizedExpression (e.g., in useEffect deps or memoization), consider wrapping getRawExp/getSanitizedExp in useCallback; otherwise the current inline definitions are fine.

-        <ExpressionEditor
-            fileName={fileName}
-            targetLineRange={targetLineRange}
-            helperPaneZIndex={props.helperPaneZIndex}
-            {...form}
-            {...expressionEditor}
-            {...props}
-            rawExpression={getRawExp}
-            sanitizedExpression={getSanitizedExp}
-        />
+        <ExpressionEditor
+            fileName={fileName}
+            targetLineRange={targetLineRange}
+            {...form}
+            {...expressionEditor}
+            {...props}
+            rawExpression={getRawExp}
+            sanitizedExpression={getSanitizedExp}
+        />
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 458b5b3 and e080371.

📒 Files selected for processing (1)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionEditor.tsx (2)
  • ContextAwareExpressionEditorProps (49-65)
  • ExpressionEditor (306-826)
workspaces/ballerina/ballerina-side-panel/src/context/form.tsx (1)
  • useFormContext (70-70)
🔇 Additional comments (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/RawExpressionEditor.tsx (2)

23-37: TemplateConfig mapping looks correct for current template types

The TemplateConfig shape and TEMPLATE_CONFIGS entries for "ai:Prompt" and "string" align with the expected template syntaxes and are clear to extend later.


51-71: Sanitized/raw expression helpers are now symmetric and safe against double‑wrapping

getSanitizedExp and getRawExp correctly mirror each other for the configured prefix/suffix, only wrapping when both are missing and stripping when both are present, which avoids double-wrapping and keeps partially wrapped values unchanged (which seems like a sensible conservative behavior).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (5)

20-40: Token type index mapping is clear; consider making unknown indices explicit

The semantic-token index constants and TOKEN_TYPE_INDEX_MAP line up with the 5‑tuple chunk format and keep decoding readable. Right now any unmapped type index falls back to TokenType.VARIABLE, which could silently misclassify tokens if the provider adds new token types.

To make mismatches easier to spot, consider handling unknown indices explicitly (e.g., logging, throwing in dev, or mapping to a dedicated UNKNOWN token type if you have one) instead of defaulting to VARIABLE. This will surface integration issues earlier if the semantic token legend drifts.

Also applies to: 94-101


139-156: Completion filtering logic is sensible; just be aware of the kind whitelist

getWordBeforeCursorPosition and filterCompletionsByPrefixAndType are straightforward and read well. Note that:

  • With an empty prefix you only surface items with kind === 'field'.
  • With a non‑empty prefix you only surface items whose kind is 'function' | 'variable' | 'field'.

If the toolkit ever introduces additional CompletionItem.kind values you want to show (e.g., methods or properties under other labels), they will be silently filtered out. That’s fine if these are the only expected kinds, but worth keeping in mind.


158-199: Raw ↔ sanitized mapping assumes a single contiguous sanitized slice—document this invariant

mapRawToSanitized / mapSanitizedToRaw correctly handle the “sanitized is a contiguous substring of raw” case by mapping:

  • any position before the sanitized slice to 0,
  • positions inside to a relative offset,
  • positions after to the end of the sanitized string.

This matches the typical “trim wrapper noise” scenario. The main hidden assumption is that sanitizedExpression occurs exactly once and is the only region you care about. If that invariant ever changes (e.g., multiple identical snippets, or sanitized text built from disjoint parts), these helpers will start to behave unexpectedly.

I’d at least document this invariant in a short comment/JSDoc, and optionally add a unit test that pins the current behavior for prefix/suffix positions so future refactors don’t accidentally change it.


201-257: Metadata extractors work; consider tightening regexes and validating document types

Both extractDocumentMetadata and extractVariableMetadata correctly derive content and fullValue from the token span. A couple of small robustness tweaks could help:

  • The regexes are currently unanchored (/.../), so any extra characters in fullValue would still produce a match. Anchoring to the full span makes mis‑tokenization fail safe:
-    const documentRegex = /\$\{<ai:(\w+)>\{content:\s*([^}]+)\}\}/;
+    const documentRegex = /^\$\{<ai:(\w+)>\{content:\s*([^}]+)\}\}$/;
...
-    const variableRegex = /\$\{([^}]+)\}/;
+    const variableRegex = /^\$\{([^}]+)\}$/;
  • match[1] is cast to DocumentType without runtime validation. If the expression grammar ever emits an unsupported ai: type, it will sneak through as an apparently valid DocumentType. You could guard this with a small whitelist:
+const SUPPORTED_DOCUMENT_TYPES: DocumentType[] = ['ImageDocument', 'FileDocument', 'AudioDocument'];
...
-    const documentType = match[1] as DocumentType;
+    const candidateType = match[1] as string;
+    if (!SUPPORTED_DOCUMENT_TYPES.includes(candidateType as DocumentType)) {
+        return null;
+    }
+    const documentType = candidateType as DocumentType;

Not mandatory, but it will make failures in upstream parsing/tokenization much easier to diagnose.


277-331: Pattern detection algorithm is correct; minor micro‑optimization possible

The sliding‑window matcher over ParsedToken[] is clear and correctly:

  • Sorts patterns by priority,
  • Enforces non‑overlapping matches via usedIndices,
  • Delegates to extractors and pushes well‑structured CompoundTokenSequence objects.

The only small nit is the allocation in the “already used?” check:

if (Array.from({ length: sequenceLength }, (_, j) => i + j).some(idx => usedIndices.has(idx))) {
    continue;
}

You can avoid creating a temporary array on every window with a simple loop:

-            if (Array.from({ length: sequenceLength }, (_, j) => i + j).some(idx => usedIndices.has(idx))) {
-                continue;
-            }
+            let overlaps = false;
+            for (let j = 0; j < sequenceLength; j++) {
+                if (usedIndices.has(i + j)) {
+                    overlaps = true;
+                    break;
+                }
+            }
+            if (overlaps) {
+                continue;
+            }

Not critical given typical token counts, but it tightens the inner loop a bit.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e080371 and 78c8ce0.

📒 Files selected for processing (1)
  • workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (1)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts (4)
  • TokenMetadata (63-67)
  • DocumentType (61-61)
  • TokenPattern (100-105)
  • CompoundTokenSequence (89-97)
🔇 Additional comments (2)
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/utils.ts (2)

103-137: Semantic token → absolute ParsedToken conversion looks correct

The getParsedExpressionTokens implementation correctly applies LSP‑style deltas for line and startChar and then converts to absolute offsets via getAbsoluteColumnOffset. Incrementing a separate tokenId and normalizing the raw type through getTokenTypeFromIndex gives you a clean, stable token surface for the rest of the pipeline. No issues spotted here.


259-275: Token pattern priorities now match the comment and intent

TOKEN_PATTERNS defines DOCUMENT with priority: 2 and VARIABLE with priority: 1, and detectTokenPatterns sorts by descending priority. This now matches the “higher priority number = higher priority” comment and ensures document patterns are attempted before variable patterns. This resolves the earlier ambiguity around pattern precedence.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dan-niles did you change this or is it from a merge commit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it came from rebasing. Previously I sent the PR to bi-1.5.x branch and switched it to main.

@kanushka kanushka requested a review from Copilot November 20, 2025 07:53
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces comprehensive support for inserting multi-modal documents (images, files, and audio) into AI prompts via the expression helper pane, enhancing the low-code user experience. The implementation includes a new template mode with markdown editing capabilities, token-based expression rendering, and improved UI for document selection.

Key Changes:

  • Added Documents section to helper pane for ai:Prompt fields with support for Image, File, and Audio document types
  • Implemented template mode with markdown toolbar, preview functionality, and chip-based token rendering
  • Enhanced expression editor with backtick hiding and improved cursor/selection management
  • Added URL-based document creation and variable filtering for compatible types

Reviewed Changes

Copilot reviewed 47 out of 51 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/Documents.tsx New Documents view listing supported AI document types
workspaces/ballerina/ballerina-visualizer/src/views/BI/HelperPaneNew/Views/DocumentConfig.tsx Document configuration page with variable selection and URL input
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpandedEditor/modes/TemplateMode.tsx New template mode component with markdown toolbar and preview
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/types.ts Extended type system for template mode and document tokens
workspaces/ballerina/ballerina-side-panel/src/components/editors/MultiModeExpressionEditor/ChipExpressionEditor/CodeUtils.ts Enhanced token handling with compound sequence detection
workspaces/ballerina/ballerina-side-panel/src/components/editors/ExpressionEditor.tsx Updated to support template mode with sanitization logic
workspaces/ballerina/ballerina-side-panel/package.json Added rehype-raw and remark-gfm dependencies for markdown rendering
Files not reviewed (1)
  • common/config/rush/pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)

workspaces/common-libs/ui-toolkit/src/components/Commons/ErrorBanner.tsx:1

  • The inline type annotation and spreading of sx prop is redundant. The component already has sx typed in the props interface (line 23). Remove the inline type annotation and simplify to ${props => props.sx && { ...props.sx }}.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants