{"id":18060252,"url":"https://github.com/obilet/obcalendar","last_synced_at":"2025-04-05T06:05:08.407Z","repository":{"id":258583866,"uuid":"861792632","full_name":"oBilet/OBCalendar","owner":"oBilet","description":"OBCalendar is designed for simplicity and customization, it allows you to build beautiful and functional calendar interfaces effortlessly.","archived":false,"fork":false,"pushed_at":"2024-12-26T10:58:30.000Z","size":1069,"stargazers_count":133,"open_issues_count":0,"forks_count":3,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-04-05T06:04:58.125Z","etag":null,"topics":["calendar","calendar-view","spm","swift","swiftui","swiftui-calendar","swiftuicalendar"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oBilet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-23T14:19:30.000Z","updated_at":"2025-03-11T19:43:57.000Z","dependencies_parsed_at":"2025-01-06T13:25:01.710Z","dependency_job_id":"ad347aa0-36c1-441c-9df1-7c4192b6a239","html_url":"https://github.com/oBilet/OBCalendar","commit_stats":null,"previous_names":["obilet/obcalendar"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oBilet%2FOBCalendar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oBilet%2FOBCalendar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oBilet%2FOBCalendar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oBilet%2FOBCalendar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oBilet","download_url":"https://codeload.github.com/oBilet/OBCalendar/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247294538,"owners_count":20915340,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["calendar","calendar-view","spm","swift","swiftui","swiftui-calendar","swiftuicalendar"],"created_at":"2024-10-31T04:06:42.318Z","updated_at":"2025-04-05T06:05:08.386Z","avatar_url":"https://github.com/oBilet.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# OBCalendar\n\n\n- `OBCalendar` is a SwiftUI-based calendar library designed to allow you to easily create your own custom calendars. With this structure, you can customize the days, months, and years. Additionally, you can change the localization of the calendar and display days within specific ranges.\n- Users set the `startDate` and `endDate` in `OBCalendar`, and the range is created automatically.\n\n\n\n## Documentation and Tutorial\n- You can visit for the \u003ca href=\"https://obilet.github.io/OBCalendarDocument/documentation/obiletcalendar/\" target=\"_blank\"\u003edocumentation\u003c/a\u003e\n- You can visit for the \u003ca href=\"https://obilet.github.io/OBCalendarDocument/tutorials/meetobiletcalendar\" target=\"_blank\"\u003etutorial\u003c/a\u003e step by step\n\n## Example Designs\n\n\u003cdiv align=\"center\"\u003e\n  \u003ctable\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003cimg width=300 src=\"https://github.com/oBilet/OBCalendar/blob/main/SSForReadme/firstSS.png\"\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cimg width=300 src=\"https://github.com/oBilet/OBCalendar/blob/main/SSForReadme/secondSS.png\"\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cimg width=300 src=\"https://github.com/oBilet/OBCalendar/blob/main/SSForReadme/thirdSS.png\"\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n     \u003ctd\u003e\u003cimg width=300 src=\"https://github.com/oBilet/OBCalendar/blob/main/SSForReadme/fourthSS.png\"\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cimg width=300 src=\"https://github.com/oBilet/OBCalendar/blob/main/SSForReadme/fifthSS.png\"\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cimg width=300 src=\"https://github.com/oBilet/OBCalendar/blob/main/SSForReadme/sixthSS.png\"\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/table\u003e\n\u003c/div\u003e\n\n## Requirements\n- iOS 14+\n- Swift 5.10+\n\n## Installation\nTo integrate `OBCalendar` into your project using Swift Package Manager, follow these steps:\n- Open your Xcode project.\n- Go to File \u003e Add Packages.\n- In the search bar, enter the following URL :\n  \n    ```\n    https://github.com/oBilet/OBCalendar.git\n    ```\n- Choose the package version or branch and click Add Package.\n\n## Note\nFor better performance, use `lazyDays: true` and `lazyMonths: true`.\nIf you are using programmatic scroll, set `lazyYears: false` because subviews need to be loaded into memory once for ScrollViewProxy to recognize their id values.\n\n## Usage\n\n- You can create `OBCalendar` specifying `startDate` (default is now) and DrawingRange (day, month or year from startDate) (default `drawingRange` is `.year(1)`).\n- Modifiers are optional and you can choose to use `baseView` or use the packed views (daysView, monthsView) inside the modifiers or you can return your custom view.\n- The first model consists of `CalendarModel.Year`, `CalendarModel.Month` and `CalendarModel.Day` and a view is created for each day using this model in the first block.\n- Modifiers should be written in this order: dayModifier -\u003e monthModifier -\u003e yearModifier\n- `baseView` in the modifier closures is the default view that has its own custom modification over the previous modifier method's return type, like having a header in months for example.\n- `daysView` in the monthModifier and `monthsView` in the yearModifier are the untouched pack of views that will have the modifications from previous modifiers.\n- Every modifier has its own related data type packed as a tuple in the closure parameter list. Default name is \"model\" and it has `CalendarModel.Year`, `CalendarModel.Month` and `CalendarModel.Month`.\n- The models provided to the closures are: `Day` + `Month` + `Year` for dayModifier, `Month` +`Year` for month modifier and only `Year` for yearModifier.\n\n- You can fully customize the view for each day, month, and year using `dayModifier`, `monthModifier` and `yearModifier` which do take `ViewBuilder` blocks.\n- This structure provides a seamless and dynamic user experience.\n\n- If you'd like to create the calendar from scratch, you can use the base version of it as well. You can customize it even further by setting sart and end dates to generating and providing your own date array for custom layouts.\n\nDefault:\n```swift\n// 1 year of drawing range\nOBCalendar(drawingRange: .year(1))\n\n// 3 months of drawing range\nOBCalendar(drawingRange: .month(3))\n\n// 60 days of drawing range\nOBCalendar(drawingRange: .day(60))\n```\n\nDouble selection example:\n```swift\nOBCalendar()\n   .dayModifier { baseView, model in\n      let date = model.day.date\n      let targetView = baseView\n         .onTapGesture {\n            if firstSelectedDate == nil {\n               firstSelectedDate = date\n            } else if secondSelectedDate == nil {\n               secondSelectedDate = date\n            } else {\n               secondSelectedDate = nil\n               firstSelectedDate = date\n            }\n         }\n   \n      if date == firstSelectedDate {\n         targetView\n            .background(firstSelectedBackground)\n      } else if date == secondSelectedDate {\n         targetView\n            .background(secondSelectedBackground)\n      } else if isBetweenSelected(date: date) { //date \u003e firstSelectedDate \u0026\u0026 date \u003c secondSelectedDate\n         targetView\n            .background(betweenSelectedBackground)\n      } else {\n         targetView\n      }\n   }\n```\n\n\nHorizontal Scroll:\n```swift\nGeometryReader { geometry in\n      OBCalendar(\n          monthScrollAxis: .horizontal,\n          yearScrollAxis: .horizontal\n      )\n      .monthModifier { baseView, daysView, model in\n          baseView\n              .padding()\n              .frame(width: geometry.size.width)\n      }\n}\n```\n\nDayModifier:\n```swift\n OBCalendar()\n      .dayModifier { baseView, model in\n          baseView\n              .background(Color.blue)\n              .padding(2)\n              .foregroundColor(.white)\n      }\n```\n\nMonthModifier:\n```swift\nOBCalendar()\n      .monthModifier{ baseView, daysView, model in\n          VStack {\n              Text(\"Modified Months\")\n              daysView\n          }\n          .padding()\n      }\n```\n\nModified Day + Modified Month:\n```swift\nOBCalendar()\n      .dayModifier { baseView, model in\n          baseView\n              .foregroundColor(Color(.red))\n      }\n      .monthModifier { baseView, daysView, model in\n          VStack {\n              Text(\"Modified Months\")\n              daysView\n          }\n          .padding()\n      }\n```\n\nBaseCalendar\n```swift\nlet today = Date()\nlet twoYearsLater = calendar.date(byAdding: .year, value: 2, to: today)!\n\nOBBaseCalendar(startDate: today, endDate: twoYearsLater) { model, scrollProxy in\n    // day view goes here\n    let day = model.day\n    Text(\"\\(day.day)\")\n} monthContent: { model, scrollProxy, daysView in\n    // month view goes here\n    daysView\n} yearContent: { model, scrollProxy, monthsView in\n    // year view goes here\n    monthsView\n}\n```\n\nBaseCalendar + Custom layouts\n```swift\n//Implement your own layout\nlet years = [CalendarModel.Year]() \n\n// Or use default layout\nlet defaultLayout = CalendarModelBuilder.defaultLayout(\n      calendar: .current,\n      startDate: Date(),\n      endDate: Date().addingTimeInterval(3600 * 24 * 365)\n)\n\nOBBaseCalendar(years: years) { model, scrollProxy in\n    // day view goes here\n    let day = model.day\n    Text(\"\\(day.day)\")\n} monthContent: { model, scrollProxy, daysView in\n    // month view goes here\n    daysView\n} yearContent: { model, scrollProxy, monthsView in\n    // year view goes here\n    monthsView\n}\n```\n\n****\n\nFeel free to explore the SwiftUI-powered flexibility of `OBCalendar` to meet your custom calendar needs!\n\n\n\n\n\n\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobilet%2Fobcalendar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fobilet%2Fobcalendar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobilet%2Fobcalendar/lists"}