Skip to content

Conversation

@iddan
Copy link
Owner

@iddan iddan commented Jun 13, 2023

This PR introduces an Excel-style auto-fill handle and a modular auto-fill architecture that intelligently detects and continues patterns when dragging.

What's New

Auto-Fill Handle

  • Small draggable handle appears on the bottom-right corner of selected cells
  • Drag to fill cells with smart pattern continuation
  • Visual feedback with dashed border during auto-fill operation

Architecture

The auto-fill system uses a plugin-based architecture with specialized pattern matchers:

src/auto-fill/
├── auto-fill-range.ts      # Main orchestrator
├── types.ts                 # Core AutoFiller interface
├── numeric.ts               # Numeric patterns (1, 2, 3...)
├── text-with-number.ts      # Text with numbers (Task 1 → Task 2)
├── date.ts                  # Days/months lists
├── formula.ts               # Formula reference updating
└── general.ts               # Fallback (repeating values)

How it works:

  1. Pattern Detection: When auto-fill ends, the system checks the selected cells against each auto-filler
  2. Priority Order: More specific patterns (formulas, numbers) are checked before general ones (repeating)
  3. Value Generation: The matched auto-filler generates values for empty cells based on the detected pattern

Supported Patterns:

  • ✅ Formulas with relative/absolute references (=A1=A2, =$A$1 stays =$A$1)
  • ✅ Numeric sequences (1, 2, 3... or 10, 5, 0...)
  • ✅ Text with numbers (Task 1 → Task 2, Item 001 → Item 002)
  • ✅ Days of week (Monday → Tuesday → Wednesday)
  • ✅ Months (January → February, Jan → Feb)
  • ✅ Repeating values (fallback)

Feature Coverage

32 passing tests covering all pattern types and edge cases including formula updates, case preservation, and wrapping behavior. Missing cases are highlighted with .skip()

Todo

  • Fix dragging back to single cell
  • Separate between the selected and auto-filled ranges, and update auto-fillter accordingly
  • Limit autofill drag to a single axis
  • Implement all autofill behaviours

@andrewLapshov
Copy link

Hi! Are you planning to merge this PR?

@sandzone
Copy link

Hi! Are you planning to merge this PR?

Wondering the same. Are you planning to merge this PR?

@iddan iddan force-pushed the feature/handle branch 5 times, most recently from 64806b2 to 9d79c44 Compare November 17, 2025 23:24
@iddan iddan self-assigned this Nov 17, 2025
@iddan iddan changed the base branch from master to carlosbaraza-handle-formula-parse-error November 17, 2025 23:26
@iddan iddan changed the base branch from carlosbaraza-handle-formula-parse-error to master November 17, 2025 23:26
@iddan iddan requested a review from Copilot November 17, 2025 23:29
Copy link

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 an Excel-style auto-fill feature with a plugin-based architecture that intelligently detects and continues patterns when dragging a handle. The implementation includes specialized pattern matchers for numeric sequences, text with numbers, date lists, formulas, and a general fallback for repeating values.

Key Changes:

  • Modular auto-fill system with 5 specialized pattern matchers (formulas, numeric, text-with-number, date lists, general)
  • Visual auto-fill handle component with drag interaction support
  • State management updates to track auto-fill operations
  • Comprehensive test suite covering 32 test cases across different pattern types

Reviewed Changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
src/auto-fill/types.ts Core type definitions for the auto-filler interface and context
src/auto-fill/auto-fill-range.ts Main orchestrator that applies auto-fillers in priority order
src/auto-fill/numeric.ts Numeric pattern detection (increasing/decreasing sequences)
src/auto-fill/text-with-number.ts Text with numeric suffix patterns (e.g., "Task 1" → "Task 2")
src/auto-fill/date.ts Day/month list patterns with case preservation
src/auto-fill/formula.ts Formula reference updating with relative/absolute reference support
src/auto-fill/general.ts Fallback repeating pattern matcher
src/auto-fill/index.ts Module exports and architecture documentation
src/auto-fill/auto-fill-range.test.ts Comprehensive test suite for all auto-fill patterns
src/reducer.ts Action handlers for auto-fill start/end and helper functions
src/reducer.test.ts Unit tests for getNextPoint helper function
src/types.ts Added autoFilling state property
src/actions.ts New action types for auto-fill operations
src/AutoFillHandle.tsx React component for draggable auto-fill handle
src/Selected.tsx Integration of auto-fill handle into selected cell UI
src/FloatingRect.tsx Visual feedback support for auto-fill operations
src/Spreadsheet.css Styling for auto-fill handle and visual feedback
src/util.test.ts Updated test fixture with autoFilling state
src/ActiveCell.tsx Formatting changes only (added blank lines)

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

Comment on lines 28 to 30
return series.every((item) => {
return !item || item.value === undefined || !isNaN(Number(item.value));
});
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

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

The isNumberSeries function returns true if all items are undefined or have numeric values, but the condition !item makes undefined items pass. However, an array of all undefined values would incorrectly return true as a number series. Consider adding a check to ensure at least one non-undefined numeric item exists before returning true.

Suggested change
return series.every((item) => {
return !item || item.value === undefined || !isNaN(Number(item.value));
});
// Must have at least one valid numeric item, and all items must be undefined or numeric
return (
series.every((item) => !item || item.value === undefined || !isNaN(Number(item.value))) &&
series.some((item) => item && item.value !== undefined && !isNaN(Number(item.value)))
);

Copilot uses AI. Check for mistakes.
Comment on lines +44 to +65
for (const [index, item] of series.entries()) {
const nextItem = series[index + 1];
if (item === undefined) continue;
if (nextItem === undefined) continue;
const nextResult = condition(Number(item.value), Number(nextItem.value));
if (!isFinite(nextResult)) return;
if (!curr) {
curr = nextResult;
continue;
}
if (curr !== nextResult) {
return;
}
}
return curr;
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

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

In the matchNumberSeries function, when curr is initially undefined (line 50), it's set to nextResult. However, if the series has only one pair of consecutive non-undefined items, the function returns that single computed value without verifying the pattern holds across multiple pairs. This could lead to false pattern matches with sparse data. Consider requiring at least 2 consecutive pairs to establish a pattern.

Suggested change
for (const [index, item] of series.entries()) {
const nextItem = series[index + 1];
if (item === undefined) continue;
if (nextItem === undefined) continue;
const nextResult = condition(Number(item.value), Number(nextItem.value));
if (!isFinite(nextResult)) return;
if (!curr) {
curr = nextResult;
continue;
}
if (curr !== nextResult) {
return;
}
}
return curr;
let matchCount = 0;
for (const [index, item] of series.entries()) {
const nextItem = series[index + 1];
if (item === undefined) continue;
if (nextItem === undefined) continue;
const nextResult = condition(Number(item.value), Number(nextItem.value));
if (!isFinite(nextResult)) return;
if (curr === undefined) {
curr = nextResult;
matchCount = 1;
continue;
}
if (curr !== nextResult) {
return;
}
matchCount++;
}
// Require at least two consecutive pairs to establish a pattern
if (matchCount >= 2) {
return curr;
}
return undefined;

Copilot uses AI. Check for mistakes.
@iddan iddan force-pushed the feature/handle branch 2 times, most recently from 685f9c6 to 58f25a6 Compare November 17, 2025 23:39
Add auto-fill handle to autofill values
@iddan iddan force-pushed the feature/handle branch 2 times, most recently from 2404341 to 7cd8ca2 Compare November 19, 2025 19:11
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.

3 participants