Zoomable view, day strip and edit events - #1
Open
stefanhp wants to merge 31 commits into
Open
Conversation
- add `onSelect` callback to `DayTimelineView` and pass it down to event blocks - wire `onTapGesture` on event blocks to invoke the callback with the tapped item - switch from `.offset()` to `.position()` so hit-testing regions align with rendered frames on macOS
- add a zoomable day timeline view supporting pinch-to-zoom on the hour grid, keeping the centered hour anchored on screen while scaling. - extract event column layout into a shared helper reused by the existing day timeline view. - raise the macOS deployment target to 15. - add preview scenarios and render support for views with onAppear-driven scroll state. - add unit tests covering zoom anchor and scroll offset math.
- add WeekStripView, a locale-aware 7-day week strip with swipe/chevron navigation and day selection - add WeekTimelineView, pairing WeekStripView with ZoomableDayTimelineView - add WeekDateMath enum with unit tests covering week boundaries, symbol ordering, and week shifting - extend RenderPreviews to render week strip and week timeline previews - document the new views in README and CLAUDE.md
- add `isEditable` flag and `rescheduled(startDate:endDate:)` helper to `TimelineItem` - add drag-to-move and drag-to-resize gestures to `TimelineEventBlock`, gated per-item by `isEditable` and coordinated via a shared `editingItemID` binding - snap dragged times to an adaptive granularity based on the current zoom level, with duration-preserving clamps on resize - show a live time label while dragging, and disable scrolling while a block is being edited - thread an `onReschedule` callback through `ZoomableDayTimelineView` and `WeekTimelineView` - add an all-day sample event to the render-previews and view preview data - add unit tests for the new snap/move/resize math and for `rescheduled(startDate:endDate:)`
- add root, Sources, and Tests cspell configs with project-specific words - disable markdownlint MD033 for README to allow inline HTML badge
- fix event vertical offset calculation to anchor on start-of-day instead of leaking the reference date's minutes into every event's position. - extract the offset math into a pure, testable EventPositionMath enum. - pin hour grid rows to top alignment so row content doesn't center-stretch. - add unit tests covering the new offset math. - update screenshots with corrected layout
- add drag-to-reschedule usage examples to README and getting started guide - document `isEditable` and `onReschedule` in CLAUDE.md and DocC pages - note `EventPositionMath`/`RescheduleMath` extraction convention in CLAUDE.md - add `ZoomableDayTimelineView`, `WeekStripView`, and `WeekTimelineView` to DocC topics - remove stale `TimelineEventBlock` reference from DocC event data topics
- add onCreate to ZoomableDayTimelineView/WeekTimelineView for click-drag (macOS) and long-press (iOS) creation of new events on empty background. - add onDelete to show a delete affordance on editable event blocks while in edit mode. - add onEditStart/onEditEnd to notify hosts once per edit session rather than per drag. - add EventPositionMath.date(atYOffset:) as the inverse of yOffset(of:), used to translate create-gesture positions back to dates. - add RescheduleMath.orderedRange to normalize a possibly-reversed drag pair and clamp it to a minimum duration. - render a live snapped preview of the in-progress create drag on macOS. - wire the new callbacks and onDelete/onEditStart/onEditEnd parameters through DayTimelineView. - add tests for date(atYOffset:) round-tripping and orderedRange.
- document create, delete, and edit-lifecycle callbacks in README, GettingStarted, and CLAUDE.md. - add edit-mode screenshots (light/dark) and reference them from README and docc guide. - add `initialEditingItemID` to `ZoomableDayTimelineView` initializers so previews/tests can start an item in edit mode without simulating a gesture. - add a `zoomable-day-editing` preview scenario to `RenderPreviews`. - reformat multi-line argument calls in `ZoomableDayTimelineView` for consistency.
- Add Keep a Changelog-formatted CHANGELOG.md documenting unreleased and past releases.
- add CI workflow running version, tests, and release jobs via nxlabs-ch shared workflows - add reusable tests workflow that runs formatting lint and unit tests - add cspell config for the .github directory - add mise lint task to check formatting without writing changes - pin swift toolchain to 6.3.3 instead of latest - document the new lint task in CLAUDE.md
Zoomable view, day strip and edit events
- add 1.2.0 section header with release date - add release tag link for 1.2.0
Merge pull request #3 from chronophy/develop
- compute event y-offset and its inverse from date components instead of elapsed-time diffs, so hour/minute values stay correct across DST transitions - rework RescheduleMath snapping and drag deltas to operate on minute-of-day derived from calendar components rather than raw time intervals - add spring-forward day tests for EventPositionMath round-tripping and RescheduleMath snapping
- add a timeout that clears a pending optimistic reschedule if the host never persists it by the time editing ends - prevents an event block from staying visually pinned at a rejected position indefinitely
- keep isEditing true while a block's own drag/resize gesture is still physically live, even after editingItemID moves to another block - only clear activeDrag on editingItemID change when no gesture is still live, preventing a second touch on another block from silently discarding an in-progress drag - extract the live-gesture check into a shared isGestureLive property used by both isEditing and the existing gesture-end cleanup
- remove the -7pt offset on hour labels so they line up with their hour lines instead of overlapping them - add top padding to the compact timeline body so the first hour line clears the container's rounded top edge - regenerate preview screenshots to reflect the corrected alignment
- clear editingItemID when it no longer matches the current day's items, preventing scroll from staying frozen after paging days mid-edit - drive scrollDisabled from a plain Bool instead of branching between view types, so toggling edit mode no longer remounts the ScrollView and loses its scroll position - add tests covering the new editing-id reset logic
- extract hour-range calculation into a testable HourRangeMath enum. - fix under-bounding when the base date has non-zero minutes. - add unit tests covering same-day, next-day, and previous-day cases. - regenerate affected screen shots
- only attach the card gesture recognizer when the block has an `onSelect` handler or can enter edit mode - prevents read-only blocks from swallowing touches meant for an ancestor tap gesture or scroll view
- compute column count per connected overlap group instead of globally across the day - prevent unrelated overlap clusters from inflating each other's column width - add tests covering grouped column assignment and totalColumns scoping
- add a `calendar` parameter to `ZoomableDayTimelineView`, used for hour-range, snap, and create/format logic instead of always defaulting to `Calendar.current`. - pass `WeekTimelineView`'s `calendar` down into its underlying `ZoomableDayTimelineView`. - add a Tokyo-timezone preview scenario proving the calendar reaches the day grid, not just the week strip.
- Add a liveness-only `isPinching` GestureState, since `pinchScale == 1` can occur mid-gesture and isn't a safe end-of-gesture signal. - Clear `activeAnchorHour` via `onChange(of: isPinching)` when the pinch gesture stops being live, including cancellation cases where `.onEnded` never runs. - Mirror the existing safety net pattern used for `TimelineEventBlock`'s drag state so a cancelled pinch can't leave the anchor stuck for the next pinch.
- thread the timeline's `calendar` through `TimelineEventBlock` for positioning and drag/resize snapping - keep `.current` as the default so callers without a calendar concept are unaffected - pass `ZoomableDayTimelineView`'s stored calendar into each event block
Fix review issues
- document custom calendar/timezone support for day and week timelines - document fixes - add release link for 1.3.0
Merge pull request #5 from chronophy/develop
- macOS now requires a double-click to enter edit mode instead of a single click, preventing accidental drags when clicking through several events. - extracted the editingItemID resolution logic for tap/double-click/long-press gestures into a pure, testable EditModeTapResolution enum. - added unit tests covering the new resolution logic. - updated documentation to reflect the double-click entry gesture on macOS.
- documents the 1.3.1 release adding the double-click requirement for macOS edit mode.
Merge pull request #6 from chronophy/develop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hello,
I forked CleanCocoa/timeline-ui because I needed a pure SwiftUI calendar day view. Alternatives like KVKCalendar and CalendarKit are UIKit-based, which makes them awkward to use in a macOS + iOS/iPadOS SwiftUI app sharing common UI code.
I also needed some specific additions: a zoomable view, a week strip similar to the Apple iOS Calendar app, and editing capabilities.
I implemented those, and I'd like to contribute these features back if you're interested.
I understand the GitHub repo is a mirror, but GitHub is my main platform. I'm not sure how, or if, I can open a PR against the original on Codeberg — let me know if there's another way to do this.
The new features are detailed below.
New views
ZoomableDayTimelineView— full-day timeline, always scrollable, pinch-to-zoom, fixed 24h rangeWeekStripView/WeekTimelineView— locale-aware 7-day week strip (swipe/chevron navigation) pinned above aZoomableDayTimelineViewDayTimelineViewevent blocksEditing capabilities
TimelineItem.isEditableeditingItemIDbindingonReschedule,onDelete,onCreate,onEditStart,onEditEndTimezone support
calendar/timezone support forZoomableDayTimelineViewandWeekTimelineViewFixes
.position()instead of.offset()so tap targets align with rendered frames on macOSOther
.cspell.jsonspell-check config added throughoutEventPositionMathTests,RescheduleMathTests,WeekDateMathTests,ZoomAnchorTestsGettingStarted.md,TimelineUI.md) and README with the new views/screenshotsCHANGELOG.mdadded (Keep a Changelog format)