Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
173 commits
Select commit Hold shift + click to select a range
c493f26
forms editor v1
dwertheimer Dec 19, 2025
d120891
Merge branch 'main' into forms-editor
dwertheimer Dec 19, 2025
7fe305b
various improvements
dwertheimer Dec 19, 2025
57567ff
add xcallback to form
dwertheimer Dec 19, 2025
b0e8e5c
Added processing template creation
dwertheimer Dec 19, 2025
6bcb000
Forms: Fix code block replacement, add Form title suffix, update link…
dwertheimer Dec 19, 2025
7911ee7
fix string transform in wrong place
dwertheimer Dec 19, 2025
953d36e
Merge branch 'main' into forms-editor
dwertheimer Dec 19, 2025
a9a311f
Add heading-chooser field type and update communication strategy docs
dwertheimer Dec 21, 2025
e2f1341
Replace dropdown-select with searchable DropdownSelectChooser and add…
dwertheimer Dec 21, 2025
ccc595c
Fix Flow type error in dropdown-select options array
dwertheimer Dec 21, 2025
a7b879a
Fix icon display in choosers: remove icon from heading-chooser, add a…
dwertheimer Dec 21, 2025
42c051f
Fix dropdown arrow positioning to appear inside input field
dwertheimer Dec 21, 2025
240a633
Add background and border styling to DropdownSelectChooser dropdown
dwertheimer Dec 21, 2025
0880d3c
Add note-chooser options and test permutations
dwertheimer Dec 21, 2025
f6e26af
Fix note-chooser filtering: each field filters independently
dwertheimer Dec 21, 2025
02dc038
Add form-state-viewer field type for testing
dwertheimer Dec 21, 2025
721d37f
Fix JSON editor error and note-chooser default filtering
dwertheimer Dec 21, 2025
f53347e
Fix folder chooser display and personal notes filtering
dwertheimer Dec 21, 2025
05e27e4
Fix ESC key handling in SearchableChooser
dwertheimer Dec 21, 2025
dc2eeac
Fix personal notes not showing in dropdown
dwertheimer Dec 21, 2025
92c01d8
Fix note chooser display format for personal notes
dwertheimer Dec 21, 2025
f55654b
Add missing import for getDisplayTitleAndPathForRegularNote
dwertheimer Dec 21, 2025
9329d2f
Fix Flow type errors in NoteChooser getOptionText
dwertheimer Dec 21, 2025
d14dc39
Fix note chooser display format - implement path/title directly
dwertheimer Dec 21, 2025
70d75ec
Add showValue option to SearchableChooser and all chooser components
dwertheimer Dec 21, 2025
61c5b88
Fix note chooser path/title duplication issue
dwertheimer Dec 21, 2025
0da7e17
Fix short description duplication in note chooser
dwertheimer Dec 21, 2025
f65787a
Fix duplicate description in form-state-viewer
dwertheimer Dec 21, 2025
d5b1100
Remove short description duplication in note chooser
dwertheimer Dec 21, 2025
bc0a119
Add debug logging to verify maxResults in DropdownSelectChooser
dwertheimer Dec 21, 2025
fae5909
Set maxResults to 25 for all chooser components
dwertheimer Dec 21, 2025
52662ec
Fix linter error in NoteChooser shortDescription
dwertheimer Dec 21, 2025
4c0fdd4
Fix linter error by returning null directly in NoteChooser
dwertheimer Dec 21, 2025
5b737e9
Fix folder creation dialog and add folder reload support
dwertheimer Dec 21, 2025
a300e5e
Add onFoldersChanged prop to DynamicDialog type and pass it through
dwertheimer Dec 21, 2025
5716b26
Complete onFoldersChanged prop passing in DynamicDialog
dwertheimer Dec 21, 2025
dacb9d7
Add missing handleCreateInFolder function in FolderChooser
dwertheimer Dec 21, 2025
b6aedf5
Remove duplicate handleCreateInFolder function
dwertheimer Dec 21, 2025
9347589
Remove duplicate handleCreateInFolder function definition
dwertheimer Dec 21, 2025
abd777a
Add note creation and folder dependency to note chooser
dwertheimer Dec 21, 2025
70e60fd
Fix missing createNote function and complete prop passing
dwertheimer Dec 21, 2025
8bc05ab
Fix linter errors for note chooser folder dependency
dwertheimer Dec 21, 2025
6bb4225
Complete onNotesChanged prop passing through component chain
dwertheimer Dec 21, 2025
b2cf56c
Add missing onFoldersChanged and onNotesChanged to function parameters
dwertheimer Dec 21, 2025
d241214
Add onNotesChanged to TDynamicDialogProps type definition
dwertheimer Dec 21, 2025
e0aa40d
Add test cases for note chooser folder dependency and note creation
dwertheimer Dec 21, 2025
12ca56e
Add expandable textarea field type to DynamicDialog
dwertheimer Dec 21, 2025
0b412b0
Complete textarea integration in dialogElementRenderer and FormBuilder
dwertheimer Dec 21, 2025
8f3bbcc
Add minRows and maxRows to TSettingItem and textarea editor in FormBu…
dwertheimer Dec 21, 2025
8deb396
Add textarea editor controls to FormBuilder
dwertheimer Dec 21, 2025
3dba437
Add textarea to ENTER_CONSUMING_FIELD_TYPES
dwertheimer Dec 21, 2025
4946c75
Add data-field-type attribute to ExpandableTextarea container
dwertheimer Dec 21, 2025
701ccf8
Change dynamic dialog to use 90% of window width and height
dwertheimer Dec 21, 2025
2d834a5
Update dynamic-dialog-content to use flex: 1 for proper height
dwertheimer Dec 21, 2025
72dd376
Fix note chooser test fields and add missing itemsWithNewNote logic
dwertheimer Dec 21, 2025
e39c3b1
Add getOptionText handler for New Note option
dwertheimer Dec 21, 2025
735fa0a
Update filterFn to always show New Note option
dwertheimer Dec 21, 2025
d7ca174
Fix folder filtering in NoteChooser
dwertheimer Dec 21, 2025
f9229af
Close dropdown after creating new folder in FolderChooser
dwertheimer Dec 21, 2025
95a67e1
Complete implementation: close dropdown after creating new folder
dwertheimer Dec 21, 2025
51043dd
Close dropdown after creating new folder
dwertheimer Dec 22, 2025
2fb6783
Fix: Pass closeDropdown prop to SearchableChooser
dwertheimer Dec 22, 2025
68f22a1
Fix: Break long line to comply with 180 char limit
dwertheimer Dec 22, 2025
4cc5944
Add backward compatibility for receivingTemplateTitle
dwertheimer Dec 22, 2025
ca28850
Fix processing method choosers and button handlers
dwertheimer Dec 22, 2025
3d7f145
Add requestFromPlugin to form processor NoteChooser
dwertheimer Dec 22, 2025
9e8625b
Add debug logging to track data loading in FormBuilder
dwertheimer Dec 22, 2025
3aeca80
Fix data loading for processing method choosers
dwertheimer Dec 22, 2025
139b1fb
Fix loadFolders/loadNotes function calls
dwertheimer Dec 22, 2025
e9ecae4
Fix loadFolders/loadNotes function signatures
dwertheimer Dec 22, 2025
4f2739b
Update Write Location options and add React-based template tag inserter
dwertheimer Dec 22, 2025
e14bf3b
Fix TemplateTagInserter usage and import order
dwertheimer Dec 22, 2025
450a7e4
Fix TemplateTagInserter placement inside component
dwertheimer Dec 22, 2025
e6e4f96
Fix Write Location options and extract ProcessingMethodSection
dwertheimer Dec 22, 2025
f08af6e
Move TemplateTagInserter to ProcessingMethodSection and fix types
dwertheimer Dec 22, 2025
8bb8fe4
Remove duplicate TemplateTagInserter from FormBuilder
dwertheimer Dec 22, 2025
2e9ccb6
Fix onNotesChanged callbacks and remove unused imports
dwertheimer Dec 22, 2025
570dff4
Fix NoteChooser and HeadingChooser not populating in ProcessingMethod…
dwertheimer Dec 22, 2025
008b11c
Add manual entry support to SearchableChooser and JSON debug viewer
dwertheimer Dec 22, 2025
14d3561
Complete manual entry implementation and JSON debug viewer
dwertheimer Dec 22, 2025
f4b6412
Add JSON debug viewer to ProcessingMethodSection
dwertheimer Dec 22, 2025
a31ab17
Major updates to ProcessingMethodSection and template handling
dwertheimer Dec 22, 2025
0195b58
Fix Flow type errors in ExpandableTextarea and ProcessingMethodSection
dwertheimer Dec 22, 2025
3bbd6e7
Fix ExpandableTextarea ref handling and Flow types
dwertheimer Dec 22, 2025
eb0979f
Simplify ExpandableTextarea to use callback ref instead of forwardRef
dwertheimer Dec 22, 2025
44d0bd1
Fix Flow type error for style spread in ExpandableTextarea
dwertheimer Dec 22, 2025
88cf19a
Fix style spread Flow error using Object.assign
dwertheimer Dec 22, 2025
834af62
Move Template Body textarea to bottom and rename to Content to Insert
dwertheimer Dec 22, 2025
a0c186f
Fix TemplateTagInserter and move templateBody to codeblock
dwertheimer Dec 22, 2025
71e3c81
Generalize codeblock save/load functions
dwertheimer Dec 22, 2025
1c3782c
Filter out empty string values from frontmatter to prevent writing ""
dwertheimer Dec 22, 2025
8e54e89
Refactor updateFrontMatterVars to skip empty values and only quote wh…
dwertheimer Dec 22, 2025
f85268d
Fix updateFrontMatterVars to allow empty values but never quote them
dwertheimer Dec 22, 2025
1e91819
Fix TemplateTagInserter: separate Field/Date modes, improve styling
dwertheimer Dec 22, 2025
42da81f
Use moment.js for locale-specific date format examples in TemplateTag…
dwertheimer Dec 22, 2025
9377b37
Increase maxResults in TemplateTagInserter to show all date formats
dwertheimer Dec 22, 2025
b54010b
Convert New Note Title to expandable textarea with newline prevention
dwertheimer Dec 22, 2025
f7a0405
Add 'Content to Insert' field to 'Create New Note' processing method
dwertheimer Dec 22, 2025
2ae8ffa
Add InfoIcon component for form field explanations
dwertheimer Dec 22, 2025
283d03b
Fix Processing Template chooser value handling
dwertheimer Dec 22, 2025
3e97d65
Fix TemplateTagInserter insertion by ensuring ref is set on button click
dwertheimer Dec 22, 2025
1d520c6
Make receivingTemplateTitle optional based on processing method
dwertheimer Dec 22, 2025
ea19d64
Require processingMethod to be explicitly set instead of defaulting
dwertheimer Dec 22, 2025
e54fed9
Add info tip and validation for Window Size fields
dwertheimer Dec 22, 2025
6f88eeb
Fix window centering in showHTMLV2
dwertheimer Dec 22, 2025
bacda0d
Add NP_THEME support to showHTMLV2
dwertheimer Dec 22, 2025
ab82588
Merge branch 'main' into forms-editor
dwertheimer Dec 22, 2025
dd84453
Preserve newNoteTitle and templateBody during renderFrontmatter
dwertheimer Dec 22, 2025
ff3de1c
Move TemplateRunner processing variables to codeblock instead of fron…
dwertheimer Dec 22, 2025
8f7290c
Fix Flow type error in FormBuilder templateRunnerArgs merge
dwertheimer Dec 22, 2025
1271f66
Display field labels with keys in parentheses in TemplateTagInserter
dwertheimer Dec 22, 2025
12554f5
Render newNoteTitle template tags with form values before passing to …
dwertheimer Dec 22, 2025
a30e561
Fix newNoteFolder empty string causing notes to be created in 'null' …
dwertheimer Dec 22, 2025
e15de28
Pass form values to templateRunner as top-level properties for templa…
dwertheimer Dec 22, 2025
32e4e3b
Add success message to Save Form button using request/response pattern
dwertheimer Dec 22, 2025
ae052ed
Render templateBody with form values before passing to templateRunner
dwertheimer Dec 22, 2025
4037026
Add missing handleSaveRequest function definition
dwertheimer Dec 22, 2025
3c305f7
Clarify templateBody rendering strategy: only pre-render for create-new
dwertheimer Dec 22, 2025
a596230
Fix TemplateRunner to render templateBody in handleNewNoteCreation
dwertheimer Dec 22, 2025
f002577
Update comments to reflect that TemplateRunner handles rendering
dwertheimer Dec 22, 2025
f6ac6ea
Add rendering for newNoteTitle and getNoteTitled in TemplateRunner
dwertheimer Dec 22, 2025
0bd5de3
Add rendering for getNoteTitled (noteTitle) in TemplateRunner
dwertheimer Dec 22, 2025
80eb454
Fix getNoteTitled rendering to allow template tags with special values
dwertheimer Dec 22, 2025
174a5b3
Remove pre-rendering of newNoteTitle from Forms plugin
dwertheimer Dec 22, 2025
636fa37
Remove remaining pre-rendering code for newNoteTitle from Forms plugin
dwertheimer Dec 22, 2025
bcbcedc
Add rendering for writeUnderHeading and folder in TemplateRunner
dwertheimer Dec 22, 2025
7c59f0c
Fix folder rendering in handleNewNoteCreation and update CHANGELOG
dwertheimer Dec 22, 2025
6cfe93e
Update CHANGELOG to document writeUnderHeading and folder rendering
dwertheimer Dec 22, 2025
5eac722
Add TemplateTagEditor component for user-friendly template tag editing
dwertheimer Dec 22, 2025
4152813
Fix TemplateTagEditor toggle and implement drag-and-drop
dwertheimer Dec 23, 2025
89516ec
Add TemplateJS block field type to DynamicDialog
dwertheimer Dec 23, 2025
21c5ae4
Add executeTiming property to TSettingItem type for templatejs-block
dwertheimer Dec 23, 2025
48939c1
Improve Form Builder UI and TemplateTagEditor functionality
dwertheimer Dec 23, 2025
89e5ca7
Fix templateBody loading and improve TemplateTagEditor UI
dwertheimer Dec 23, 2025
4dcd4fc
Improve processing template creation UX
dwertheimer Dec 23, 2025
9fc9bcf
Fix handleOpenNote function and improve logging
dwertheimer Dec 23, 2025
40b62cf
Forms: Window management, coordinate system, and form submission impr…
dwertheimer Dec 24, 2025
07dc427
Fix form creation: frontmatter title, window defaults, and toast styling
dwertheimer Dec 25, 2025
8f08b05
Add Promise polyfills and fix duplicate form race condition
dwertheimer Dec 25, 2025
2e5227e
Add floating prop to MessageBanner for toast-like display
dwertheimer Dec 25, 2025
4483ae0
Add SpaceChooser component and fix SearchableChooser styling/navigation
dwertheimer Dec 26, 2025
50965cf
Fix space filtering for NoteChooser and FolderChooser
dwertheimer Dec 26, 2025
d07c61f
Fix EventChooser loading message and response timeout
dwertheimer Dec 26, 2025
effd1f5
Add generic itemFilter to SearchableChooser and filter relative notes…
dwertheimer Dec 26, 2025
e54b188
Add diagnostic logs for Open Form button debugging
dwertheimer Dec 26, 2025
2d263b3
Fix EventChooser not receiving responses - improve findFormWindowId t…
dwertheimer Dec 26, 2025
abeec56
EventChooser: Fix timezone issues, return full CalendarItem objects, …
dwertheimer Dec 26, 2025
51ff137
Fix infinite loop issues at root level and improve FormSettings UI
dwertheimer Dec 27, 2025
43bd0b3
Separate React components from back-end dependencies
dwertheimer Dec 27, 2025
25dbae8
Bundle React/ReactDOM into Root and make Forms bundles use them as ex…
dwertheimer Dec 27, 2025
db6514e
UI improvements: Move template tag editor buttons to left, toggle to …
dwertheimer Dec 27, 2025
a5d0e8d
Add Form Browser component with resizable columns and modular request…
dwertheimer Dec 27, 2025
1d99db3
Form Browser improvements: reorganize layout, add edit button, fix fo…
dwertheimer Dec 27, 2025
9d8c41e
Form Browser UX improvements and bug fixes
dwertheimer Dec 27, 2025
3a073ad
Add showInMainWindow command to np.Shared and refactor Form Browser w…
dwertheimer Dec 27, 2025
629a964
Fix for default icon
dwertheimer Dec 27, 2025
f225b20
fix for default icon
dwertheimer Dec 27, 2025
e43f6fa
re-use html creation
dwertheimer Dec 27, 2025
ebfc80a
fix to fm template
dwertheimer Dec 27, 2025
cd0bc82
Remove quoting edge case
dwertheimer Dec 27, 2025
8924bbb
Add SimpleDialog component and improve Form Browser UX
dwertheimer Dec 27, 2025
8050a17
Add Favorites Browser with React components and offline mock system f…
dwertheimer Dec 28, 2025
786be5b
fix height
dwertheimer Dec 28, 2025
fd94d9f
Refactor Favorites +New dialogs to use DynamicDialog directly
dwertheimer Dec 28, 2025
f0dea59
Add MarkdownPreview component to DynamicDialog and refactor field dep…
dwertheimer Dec 28, 2025
60e2a1e
make the window a little wider
dwertheimer Dec 28, 2025
4a0903a
Merge branch 'main' into favorites-sidebar
dwertheimer Dec 28, 2025
147b26d
Fix Favorites Browser toast/scroll/highlight and improve Form Preview…
dwertheimer Dec 29, 2025
85f9b8a
Merge main into favorites-sidebar: resolve HTMLView.js conflicts by a…
dwertheimer Dec 29, 2025
e4f4209
Format HTMLView.js: fix import formatting and whitespace
dwertheimer Dec 29, 2025
072599c
Fix: Remove merge conflict markers from HTMLView.js - use main's version
dwertheimer Dec 29, 2025
aa8cd7c
Fix toast positioning and replace FormPreview disclaimer DIV with toast
dwertheimer Dec 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions .cursor/rules/noteplan-programming-general.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
---
alwaysApply: true
---
For NotePlan code, never use require statements. Use import statements at the top of the file -- never inline/dynamically import modules. Rollup will not process them correctly.
You should not ever try to build the code with "npm run build" -- this will not work. The programmer will have to use Rollup to build the code. There is separate tooling for this described in @README.md.
NotePlan has global variables that are available to all plugins such as DataStore, CommandBar, Editor, and NotePlan. You can use these variables to access the NotePlan API. You do not need to import them.

## Promise Polyfills

NotePlan's JSContext may not have `Promise.resolve()` or `Promise.all()`. Use the polyfills in `@helpers/promisePolyfill.js`:

- **Import**: `import { initPromisePolyfills, promiseResolve, promiseAll, waitForCondition, setTimeoutPolyfill } from '@helpers/promisePolyfill'`
- **Initialize early**: Call `initPromisePolyfills()` at the top of your plugin file to add polyfills to the global Promise object
- **Use directly**: `promiseResolve(value)`, `promiseAll(promises)`, `waitForCondition(condition, options)`, `setTimeoutPolyfill(callback, delayMs)`
- **waitForCondition**: Useful for waiting for notes to appear in `DataStore.projectNotes` after creation/modification. Example:
```javascript
const found = await waitForCondition(
() => getFormTemplateList().find(opt => opt.label === title) != null,
{ maxWaitMs: 3000, checkIntervalMs: 100 }
)
```
- **Cache updates**: After creating or modifying notes, call `DataStore.updateCache(note, true)` to ensure the note is available in `DataStore.projectNotes` for searches.

## React Function Memoization (CRITICAL - Prevents Infinite Loops)

**ALWAYS wrap functions passed to React Context or child components in `useCallback`**. This is critical to prevent infinite render loops that crash the app.

### The Problem
Functions created in React components are recreated on every render. If these functions are:
- Passed to `AppContext` (via `AppProvider`)
- Used as dependencies in `useEffect` hooks
- Passed as props to child components

They will cause infinite loops because:
1. Function reference changes → Context value changes → All consumers re-render
2. Re-render creates new function → Function reference changes → Loop continues

### The Solution
**Always use `useCallback` for functions passed to context or used as dependencies:**

```javascript
// ❌ WRONG - Causes infinite loops
const requestFromPlugin = (command: string, dataToSend: any = {}) => {
// ... implementation
}

// ✅ CORRECT - Stable function reference
const requestFromPlugin = useCallback((command: string, dataToSend: any = {}) => {
// ... implementation
}, [dispatch, windowId]) // Only recreate if these dependencies change
```

### Functions That MUST Be Memoized
- `requestFromPlugin` - Request/response pattern function
- `sendActionToPlugin` - Action sender function
- `sendToPlugin` - Direct sender function
- Any function passed to `AppProvider` props
- Any function used in `useEffect` dependency arrays

### Dependencies
Keep dependencies minimal - usually just:
- `dispatch` (from props, usually stable)
- `windowId` (if used in the function)
- Other stable refs (not state/props that change frequently)

### AppContext Memoization
`AppContext` should use `useMemo` to memoize the context value:

```javascript
const contextValue = useMemo(() => ({
sendActionToPlugin,
sendToPlugin,
requestFromPlugin,
dispatch,
pluginData,
// ...
}), [sendActionToPlugin, sendToPlugin, requestFromPlugin, dispatch, pluginData, ...])
```

**This pattern has caused infinite loops 5+ times. Always check for `useCallback` when creating functions that go into context.**

### Why This Must Be Checked Every Time

**IMPORTANT FOR AI ASSISTANTS:** This rule must be checked at the start of EVERY coding session and whenever creating or modifying React components that:
- Create functions passed to `AppProvider`
- Use `useEffect` with function dependencies
- Pass functions as props to child components

**Why this isn't always caught:**
- The issue only manifests at runtime (infinite loops, app crashes)
- Linters may not catch missing `useCallback` in all cases
- The pattern looks correct syntactically but fails functionally
- Context consumers re-render silently, making the problem hard to trace

**Before writing ANY React component code, ask:**
1. Are any functions being passed to `AppProvider`? → Must use `useCallback`
2. Are any functions used in `useEffect` dependencies? → Must use `useCallback`
3. Is `AppContext` using `useMemo` for the context value? → Must use `useMemo`

**This is a CRITICAL pattern that has caused production issues multiple times. Always verify function memoization before considering code complete.**

## NotePlan Theme Colors

When using CSS variables for styling, use these NotePlan theme color variables with their default values:

```css
--bg-main-color: #eff1f5;
--fg-sidebar-color: #242E32;
--bg-sidebar-color: #ECECEC;
--divider-color: #CDCFD0;
--block-id-color: #79A0B5;
--fg-main-color: #4c4f69;
--h1-color: #5c5f77;
--h2-color: #5c5f77;
--h3-color: #5c5f77;
--bg-alt-color: #e6e9ef;
--tint-color: #dc8a78;
--bg-mid-color: #ebedf2;
--bg-apple-input-color: #fbfbfb;
--bg-apple-switch-color: #dadada;
--fg-apple-switch-color: #ffffff;
--bg-apple-button-color: #fcfcfc;
--item-icon-color: #1e66f5;
--fg-done-color: #04a5e5;
--fg-canceled-color: #4F57A0E0;
--hashtag-color: inherit;
--attag-color: inherit;
--code-color: #0091f8;
```

**Always use these CSS variables with their default fallback values** when styling React components. For example:
```css
background: var(--tint-color, #dc8a78);
color: var(--fg-main-color, #4c4f69);
```
233 changes: 233 additions & 0 deletions dwertheimer.Favorites/IMPLEMENTATION_PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
# Favorites Browser Implementation Plan

## Overview
This plan outlines the implementation of a React-based Favorites Browser for the dwertheimer.Favorites plugin, using reusable FilterableList and List components with NotePlan sidebar-style display.

## Components to Create

### 1. Reusable Components (in helpers/react/)

#### 1.1 List Component (`helpers/react/List.jsx`)
- **Purpose**: Core list rendering component that can work with different filter mechanisms
- **Props**:
- `items: Array<any>` - Array of items to display
- `displayType: 'noteplan-sidebar' | 'chips'` - Display style
- `renderItem: (item: any, index: number) => React$Node` - Custom render function for each item
- `onItemClick: (item: any, event: MouseEvent) => void` - Click handler
- `selectedIndex: ?number` - Currently selected item index
- `itemActions?: Array<{icon: string, onClick: (item: any, event: MouseEvent) => void, title?: string}>` - Actions to show on right side
- `emptyMessage?: string` - Message when list is empty
- `loading?: boolean` - Loading state
- **Features**:
- Two display styles:
- `noteplan-sidebar`: Hierarchical folder/file style (like NotePlan sidebar)
- `chips`: Card/chip style (like FormBrowser left side)
- Support for action buttons on the right side of each item
- Keyboard navigation support
- Selected/active states

#### 1.2 FilterableList Component (`helpers/react/FilterableList.jsx`)
- **Purpose**: Wrapper component that adds filtering capability to List
- **Props**:
- All List props
- `filterText: string` - Current filter text
- `onFilterChange: (text: string) => void` - Filter change handler
- `filterPlaceholder?: string` - Placeholder for filter input
- `renderFilter?: () => React$Node` - Custom filter component (optional)
- **Features**:
- Text input for filtering
- Filters items based on filterText
- Can be replaced with custom filter mechanism

#### 1.3 CSS Files
- `helpers/react/List.css` - Styles for List component
- `helpers/react/FilterableList.css` - Styles for FilterableList component

### 2. Favorites Plugin React Components

#### 2.1 FavoritesView Component (`dwertheimer.Favorites/src/components/FavoritesView.jsx`)
- **Purpose**: Main React component for the Favorites Browser
- **Features**:
- Uses FilterableList with noteplan-sidebar display style
- Toggle switch to switch between favorite notes and favorite commands
- Displays list of favorites (notes or commands)
- Handles click events (normal, opt-click, cmd-click)
- Uses AppContext for communication with plugin

#### 2.2 AppContext (`dwertheimer.Favorites/src/components/AppContext.jsx`)
- **Purpose**: React Context for plugin communication (copy from Forms plugin)
- **Features**:
- `sendActionToPlugin` - Send actions to plugin
- `sendToPlugin` - Send to plugin without saving scroll
- `requestFromPlugin` - Request/response pattern
- `dispatch` - Dispatch messages
- `pluginData` - Data from plugin
- `reactSettings` - Local React settings
- `setReactSettings` - Update React settings

#### 2.3 CSS Files
- `dwertheimer.Favorites/src/components/FavoritesView.css` - Styles for FavoritesView

### 3. Plugin Backend Files

#### 3.1 Window Management (`dwertheimer.Favorites/src/windowManagement.js`)
- **Purpose**: Handle opening React windows
- **Functions**:
- `openFavoritesBrowser()` - Opens the Favorites Browser window
- `createWindowInitData()` - Creates initial data for React window
- `getPluginData()` - Gathers data to pass to React window

#### 3.2 Request Handlers (`dwertheimer.Favorites/src/requestHandlers.js`)
- **Purpose**: Handle requests from React components
- **Functions**:
- `handleGetFavoriteNotes()` - Returns list of favorite notes
- `handleGetFavoriteCommands()` - Returns list of favorite commands
- `handleOpenNote()` - Opens a note (handles normal, opt-click, cmd-click)

#### 3.3 Main Handler (`dwertheimer.Favorites/src/index.js`)
- **Purpose**: Plugin entry point
- **Functions**:
- `openFavoritesBrowser()` - Command to open Favorites Browser
- `onFavoritesBrowserAction()` - Handler for actions from React window

### 4. Rollup Configuration

#### 4.1 Rollup Entry File (`dwertheimer.Favorites/src/support/rollup.FavoritesView.entry.js`)
- **Purpose**: Entry point for Rollup bundling
- **Content**: Exports FavoritesView as WebView

#### 4.2 Rollup Script (`dwertheimer.Favorites/src/support/performRollup.node.js`)
- **Purpose**: Rollup build script (similar to Forms plugin)
- **Features**:
- Builds FavoritesView bundle
- Development mode
- Watch mode support

### 5. Required Files Structure

```
dwertheimer.Favorites/
├── src/
│ ├── components/
│ │ ├── FavoritesView.jsx
│ │ ├── FavoritesView.css
│ │ └── AppContext.jsx
│ ├── support/
│ │ ├── rollup.FavoritesView.entry.js
│ │ └── performRollup.node.js
│ ├── windowManagement.js
│ ├── requestHandlers.js
│ ├── favorites.js (existing)
│ ├── NPFavorites.js (existing)
│ ├── NPFavoritePresets.js (existing)
│ └── index.js (existing - needs updates)
├── requiredFiles/
│ └── react.c.FavoritesView.bundle.dev.js (generated by rollup)
└── plugin.json (existing - needs new command)

helpers/react/
├── List.jsx (new)
├── List.css (new)
├── FilterableList.jsx (new)
└── FilterableList.css (new)
```

## Implementation Details

### 1. List Component Display Styles

#### NotePlan Sidebar Style
- Hierarchical display with folder/file icons
- Indentation for nested items
- Folder expansion/collapse (if needed)
- Similar to NotePlan's sidebar appearance
- Uses NotePlan theme variables

#### Chips Style
- Card/chip appearance
- Rounded corners
- Border and background
- Similar to FormBrowser left side
- Hover effects
- Selected state highlighting

### 2. Favorite Notes Display
- Show note title
- Show folder path (if applicable)
- Show favorite icon (⭐️)
- Use note decoration (icon, color) from `getNoteDecoration()`
- Display in NotePlan sidebar style

### 3. Favorite Commands Display
- Show command name
- Show command description (if available)
- Display in NotePlan sidebar style
- Icon for command type

### 4. Click Handling
- **Normal click**: `Editor.openNoteByFilename(filename, false, 0, 0, false)`
- **Option-click (Alt)**: `Editor.openNoteByFilename(filename, false, 0, 0, true)` - split view
- **Cmd-click (Meta)**: `Editor.openNoteByFilename(filename, true, 0, 0, false)` - floating window

### 5. Toggle Switch
- Located at top of FilterableList
- Switches between "Favorite Notes" and "Favorite Commands"
- Updates list when toggled
- Persists selection in reactSettings

### 6. Filtering
- Text input at top of FilterableList
- Filters items based on:
- For notes: title, folder path
- For commands: command name, description
- Case-insensitive search
- Updates as user types

### 7. Request/Response Pattern
- React components use `requestFromPlugin()` to request data
- Plugin handlers respond with data
- Uses correlation IDs for request matching
- Timeout handling (default 10 seconds)

### 8. Window Opening
- Uses `DataStore.invokePluginCommandByName('showInMainWindow', 'np.Shared', [data, windowOptions])`
- Opens in main window (not floating)
- Uses NotePlan theme CSS
- Includes FontAwesome icons

## Data Flow

1. User runs `/favorites-browser` command
2. Plugin calls `openFavoritesBrowser()`
3. `windowManagement.js` creates window data and calls `showInMainWindow`
4. React window loads `FavoritesView` component
5. `FavoritesView` requests favorite notes/commands via `requestFromPlugin`
6. Plugin handlers return data
7. `FavoritesView` displays data in FilterableList
8. User clicks item → React sends action → Plugin opens note

## Testing Checklist

- [ ] List component renders correctly in both display styles
- [ ] FilterableList filters items correctly
- [ ] Toggle switch switches between notes and commands
- [ ] Normal click opens note in Editor
- [ ] Option-click opens note in split view
- [ ] Cmd-click opens note in floating window
- [ ] Filtering works for both notes and commands
- [ ] Request/response pattern works correctly
- [ ] Window opens in main window
- [ ] NotePlan theme styling applied correctly
- [ ] Keyboard navigation works
- [ ] Action buttons work (if implemented)

## Next Steps

1. Create reusable List and FilterableList components
2. Set up React framework in Favorites plugin
3. Create FavoritesView component
4. Implement window management
5. Implement request handlers
6. Add command to plugin.json
7. Test and refine

Loading
Loading