Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c01450b
Fix preview pane height issue in Form Builder
dwertheimer Jan 13, 2026
a108a5f
Fix updateReceivingTemplateWithFields to exclude display-only fields
dwertheimer Jan 13, 2026
d59f338
Add Comment field type for Form Builder
dwertheimer Jan 13, 2026
1a262f2
Fix Enter key submitting forms in textareas
dwertheimer Jan 13, 2026
850d7d9
Fix Open button for processing template - load notes if needed
dwertheimer Jan 13, 2026
08e4050
Forms: TemplateJS improvements and logging cleanup
dwertheimer Jan 13, 2026
9dbda04
Add getRenderContext command and integrate with Forms plugin
dwertheimer Jan 13, 2026
ba89cdc
Expand getFilteredTemplateList to search @Forms and use localized fol…
dwertheimer Jan 13, 2026
bd6dbd6
Update changelog for template folder expansion changes
dwertheimer Jan 13, 2026
643a499
Update template search functions to search in both @Templates and @Forms
dwertheimer Jan 13, 2026
e55ba8f
Update changelog for template search function updates
dwertheimer Jan 13, 2026
1d00197
Create shared utility function for template folder prefixes including…
dwertheimer Jan 13, 2026
cca2321
Update changelog for shared utility function refactoring
dwertheimer Jan 13, 2026
e6c4ce2
Update all template search functions to use shared utility and search…
dwertheimer Jan 13, 2026
d27b5c6
Update changelog for comprehensive template search updates
dwertheimer Jan 13, 2026
899424e
Enhance changelog entry for comprehensive template search refactoring
dwertheimer Jan 13, 2026
ff77cfb
Update chooseTemplate to use chooseNoteV2 and handle @Forms/teamspaces
dwertheimer Jan 14, 2026
4dbb18f
Fix tests for chooseNoteV2 migration and DataStore.preference
dwertheimer Jan 14, 2026
bb5d317
Replace chooseOption with chooseNoteV2 in getTemplateContent
dwertheimer Jan 14, 2026
d4ab2be
Enhance changelog entry for chooseNoteV2 migration
dwertheimer Jan 14, 2026
58bee72
Fix for template code with returns (prev assumed always strings)
dwertheimer Jan 14, 2026
b69f0c3
Fix Custom Width input validation preventing typing in FieldEditor
dwertheimer Jan 14, 2026
26184f3
Fix template form label alignment and add customizable compact mode s…
dwertheimer Jan 14, 2026
9ded3d6
Attempt to fix spacing between searchable choosers (issue not resolved)
dwertheimer Jan 14, 2026
ec2b4d1
Fix Enter key submitting form in ContainedMultiSelectChooser search i…
dwertheimer Jan 14, 2026
31a3af7
Fix newly created items not appearing in ContainedMultiSelectChooser
dwertheimer Jan 14, 2026
eb7c669
Update ContainedMultiSelectChooser: shorten button labels and add is:…
dwertheimer Jan 14, 2026
45b1975
Improve form UX: focus, tabbing, chooser controls, and template-form CSS
dwertheimer Jan 14, 2026
e893a0b
Fix SearchableChooser portal position on layout shifts
dwertheimer Jan 14, 2026
331233a
Fix SearchableChooser click selection after refocus
dwertheimer Jan 14, 2026
d8d5cbf
Fix Tab navigation when SearchableChooser dropdown is open
dwertheimer Jan 14, 2026
88c4d66
Bump version to 1.0.9 and update changelog
dwertheimer Jan 14, 2026
83fb2d1
chore(dwertheimer.Forms): bump version to 1.1.0 and add color system …
dwertheimer Jan 14, 2026
011a1a5
fix(SearchableChooser): hide short description when identical to label
dwertheimer Jan 14, 2026
7f48cee
Delete helpers changelog
dwertheimer Jan 14, 2026
78b1485
fix(FormBuilder): ensure default comment field appears for new forms
dwertheimer Jan 14, 2026
3d9d0d3
fix(FormBuilder): pass isNewForm flag from openFormBuilder to openFor…
dwertheimer Jan 14, 2026
8b5ff6c
fix(NoteChooser): display ISO date format when calendar picker select…
dwertheimer Jan 14, 2026
46cd7cb
docs(changelog): add NoteChooser ISO date format fix to v1.0.10 chang…
dwertheimer Jan 14, 2026
65bb0a5
chore: update plugin.json and FormBuilder.jsx for v1.0.10
dwertheimer Jan 14, 2026
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
101 changes: 101 additions & 0 deletions TEMPLATING_CONTEXT_OPTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Options for Providing Templating Context to TemplateJS Blocks

## Current Architecture

### How np.Templating Creates Render Context

1. **`TemplatingEngine.getRenderDataWithMethods()`** - Main function that builds context
- Creates module instances: `date`, `time`, `note`, `tasks`, `frontmatter`, `helpers`, `web`, `utility`, `system`
- Merges globals from `loadGlobalHelpers()` (which loads from `globals.js`)
- Merges userData
- Adds prompt error handlers
- Applies custom plugin modules
- Returns full renderData object

2. **`loadGlobalHelpers()`** - Adds globals to sessionData.methods
- Loads from `globals.js` (moment, affirmation, advice, etc.)
- Not exported (private function)

3. **Dependencies:**
- `TemplatingEngine` needs `templateConfig` (from settings)
- Module constructors need `templateConfig` for initialization
- Custom plugin modules are registered per instance

## Options

### Option 1: Import and Create Minimal Context (Recommended)
**Pros:**
- Reuses templating code (globals, modules)
- No changes to np.Templating
- Full access to all templating features

**Cons:**
- Need to import module classes and create instances
- Need templateConfig (can duplicate minimal config or get via command)
- Some complexity in setup

**Implementation:**
```javascript
// Import what we can
import TemplatingEngine from '../../np.Templating/lib/TemplatingEngine'
import globals from '../../np.Templating/lib/globals'
// Or get templateConfig via invokePluginCommandByName if available
// Create minimal TemplatingEngine instance
const engine = new TemplatingEngine(templateConfig, '', [])
const renderContext = await engine.getRenderDataWithMethods('', context)
// Use renderContext in Function constructor
```

### Option 2: Add New Command to np.Templating
**Pros:**
- Clean API
- No duplication
- Always uses latest templating logic

**Cons:**
- Requires editing np.Templating (user said not to)
- Adds new command to maintain

**Implementation:**
```javascript
// In np.Templating, add:
export async function getRenderContext(userData: any = {}): Promise<Object> {
await NPTemplating.setup()
const engine = new TemplatingEngine(NPTemplating.templateConfig, '', [])
return await engine.getRenderDataWithMethods('', userData)
}

// In Forms:
const renderContext = await DataStore.invokePluginCommandByName('getRenderContext', 'np.Templating', [context])
```

### Option 3: Duplicate Context Building Logic
**Pros:**
- No dependencies on np.Templating internals
- Full control

**Cons:**
- Lots of code to duplicate (~100+ lines)
- Must keep in sync with templating changes
- Risk of divergence

### Option 4: Use render() with JSON Wrapper (What We Tried)
**Pros:**
- Uses full templating system
- No duplication

**Cons:**
- Returns strings, need to parse JSON
- More complex error handling
- Performance overhead of full render pipeline

## Recommendation

**Option 1** - Import and create minimal context:
1. Import `TemplatingEngine` and `globals` directly
2. Get or create minimal `templateConfig` (can duplicate minimal config)
3. Create `TemplatingEngine` instance
4. Call `getRenderDataWithMethods()` to get full context
5. Merge into Function constructor parameters

This reuses the templating code without requiring changes to np.Templating.
40 changes: 40 additions & 0 deletions dwertheimer.Forms/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,46 @@

See Plugin [README](https://github.com/NotePlan/plugins/blob/main/dwertheimer.Forms/README.md) for details on available commands and use case.

## [1.0.10] 2026-01-14 @dwertheimer

### Added
- **Comprehensive Tailwind CSS color palette support**: Added full Tailwind color mapping (gray, red, orange, yellow, green, blue, indigo, purple, pink with shades 50-950) to `helpers/colors.js`
- **Color support for chooser icons and descriptions**: NoteChooser and SpaceChooser now display colored icons and short descriptions matching `chooseNoteV2` behavior
- **New `getColorStyle()` helper function**: Centralized color conversion utility that handles CSS variables, Tailwind color names, and direct hex/rgb colors with proper fallbacks

### Fixed
- Fixed empty label showing "?" in read-only text elements (now shows empty string)
- Fixed SpaceChooser using incorrect icons - now uses `fa-regular fa-cube` for teamspaces and `fa-solid fa-user` for private (matching Dashboard, Filer, NoteHelpers)
- Fixed teamspace colors appearing gray - now correctly displays green using `--teamspace-color` CSS variable with proper fallback
- Fixed default comment field not appearing when creating a new form - now explicitly passes `isNewForm: true` to FormBuilder (works for both command bar and FormBrowserView creation)
- Fixed NoteChooser calendar picker displaying filename (e.g., "20260117.md") instead of ISO date format (e.g., "2026-01-17") - now displays ISO 8601 format (YYYY-MM-DD) in the field

### Changed
- **SpaceChooser**: Updated to use proper Font Awesome icon classes (`TEAMSPACE_FA_ICON`, `PRIVATE_FA_ICON`) instead of generic icon names
- **Color system**: All Tailwind color names (e.g., `gray-500`, `blue-500`, `orange-500`, `green-700`) now automatically convert to their hex values via comprehensive palette mapping
- **Special color mappings**: `green-700` and `green-800` prefer `--teamspace-color` CSS variable when available, with Tailwind hex fallback
- **SearchableChooser**: Hide short description when it's identical to the label text to avoid redundant display

## [1.0.9] 2026-01-13 @dwertheimer

### Added
- Auto-focus first field when form opens for faster data entry
- Enter key reopens dropdown when closed (allows changing selection after initial choice)
- Tab key closes dropdown and moves to next field when dropdown is open
- ResizeObserver for portal dropdown positioning to handle dynamic form height changes

### Fixed
- Fixed click selection not working after programmatic refocus (dropdown was reopening immediately)
- Fixed tab navigation blocked when dropdown is open
- Fixed portal dropdown position when form layout shifts due to async data loading
- Fixed ContainedMultiSelectChooser preventing "is:checked" from being saved as a value
- Fixed bottom element clipping in scrolling dialogs (added extra padding)

### Changed
- Improved ContainedMultiSelectChooser header: narrower filter field (40% reduction), icon-only buttons (All/None/Filter/New)
- Refactored template-form CSS to use nested namespace selectors for better maintainability
- Improved compact mode label alignment using CSS variables for customizable widths

## [1.0.8] 2026-01-12 @dwertheimer

### Fixed
Expand Down
8 changes: 4 additions & 4 deletions dwertheimer.Forms/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"macOS.minVersion": "10.13.0",
"noteplan.minAppVersion": "3.4.0",
"plugin.id": "dwertheimer.Forms",
"plugin.name": "📝 Forms",
"plugin.version": "1.0.5",
"plugin.name": "📝 Template Forms",
"plugin.version": "1.0.10",
"plugin.releaseStatus": "beta",
"plugin.lastUpdateInfo": "Added folder-chooser and note-chooser field types with smart path truncation",
"plugin.description": "Dynamic Forms for NotePlan using Templating -- fill out a form and have the data sent to a template for processing",
"plugin.lastUpdateInfo": "Improved form UX: auto-focus, tab navigation, and chooser controls",
"plugin.description": "Dynamic Forms for NotePlan using Templating -- fill out a multi-field form and have the data sent to a template for processing",
"plugin.author": "dwertheimer",
"plugin.requiredFiles": ["react.c.FormView.bundle.dev.js", "react.c.FormBuilderView.bundle.dev.js", "react.c.FormBrowserView.bundle.dev.js"],
"plugin.dependsOn": [],
Expand Down
11 changes: 10 additions & 1 deletion dwertheimer.Forms/src/NPTemplateForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -272,16 +272,22 @@ export async function openTemplateForm(templateTitle?: string): Promise<void> {
// These contain template tags that reference form field values and should not be processed during form opening
if (templateNote) {
if (templateNote) {
// Remove customCSS from frontmatter (it should only come from codeblock)
delete frontmatterAttributes.customCSS

// Load templateBody from codeblock
const templateBodyFromCodeblock = await loadTemplateBodyFromTemplate(templateNote)
if (templateBodyFromCodeblock) {
frontmatterAttributes.templateBody = templateBodyFromCodeblock
}

// Load custom CSS from codeblock
// Load custom CSS from codeblock (always use codeblock, not frontmatter)
const customCSSFromCodeblock = await loadCustomCSSFromTemplate(templateNote)
if (customCSSFromCodeblock) {
frontmatterAttributes.customCSS = customCSSFromCodeblock
} else {
// Ensure it's empty if codeblock doesn't exist
frontmatterAttributes.customCSS = ''
}

// Load TemplateRunner args from codeblock
Expand Down Expand Up @@ -362,6 +368,7 @@ export async function openFormBuilder(templateTitle?: string): Promise<void> {
let selectedTemplate
let formFields: Array<Object> = []
let templateNote = null
let isNewForm = false // Track if this is a newly created form
const receivingTemplateTitle: string = '' // Track receiving template title for newly created forms

if (templateTitle?.trim().length) {
Expand Down Expand Up @@ -521,6 +528,7 @@ export async function openFormBuilder(templateTitle?: string): Promise<void> {
}

selectedTemplate = filename
isNewForm = true // Mark this as a new form so default comment field is added
logDebug(pluginJson, `openFormBuilder: Set frontmatter and selectedTemplate = ${selectedTemplate}, receivingTemplateTitle = "${receivingTemplateTitle}"`)

// Generate processing template link if receiving template exists
Expand Down Expand Up @@ -731,6 +739,7 @@ export async function openFormBuilder(templateTitle?: string): Promise<void> {
templateFilename: selectedTemplate,
templateTitle: templateNote?.title || '',
initialReceivingTemplateTitle: initialReceivingTemplateTitle,
isNewForm: isNewForm, // Pass isNewForm flag so default comment field is added
})
logDebug(pluginJson, `openFormBuilder: openFormBuilderWindow call completed`)
} catch (error) {
Expand Down
Loading