{"id":18031760,"url":"https://github.com/dagronf/dsfpagercontrol","last_synced_at":"2025-03-27T05:30:57.789Z","repository":{"id":63907294,"uuid":"406261651","full_name":"dagronf/DSFPagerControl","owner":"dagronf","description":"A simple macOS pager control","archived":false,"fork":false,"pushed_at":"2022-11-07T22:04:35.000Z","size":53,"stargazers_count":14,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-18T17:22:23.981Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/dagronf.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}},"created_at":"2021-09-14T07:06:11.000Z","updated_at":"2024-04-05T06:23:34.000Z","dependencies_parsed_at":"2022-11-28T22:53:26.886Z","dependency_job_id":null,"html_url":"https://github.com/dagronf/DSFPagerControl","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FDSFPagerControl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FDSFPagerControl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FDSFPagerControl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FDSFPagerControl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dagronf","download_url":"https://codeload.github.com/dagronf/DSFPagerControl/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245791341,"owners_count":20672665,"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":[],"created_at":"2024-10-30T10:10:42.283Z","updated_at":"2025-03-27T05:30:56.861Z","avatar_url":"https://github.com/dagronf.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DSFPagerControl\n\n\u003cp align=\"center\"\u003e\n   \u003cimg src=\"./art/dark.png?raw=true\" width=\"130\" /\u003e\u0026nbsp;\n   \u003cimg src=\"./art/light.png?raw=true\" width=\"130\" /\u003e\n\u003c/p\u003e\n\n\n\u003cp align=\"center\"\u003eA simple macOS pager control.\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/v/tag/dagronf/DSFPagerControl\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/macOS-10.11+-blue\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Xcode-12+-yellow\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Swift-5.1-orange.svg\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/License-MIT-lightgrey\" /\u003e\n    \u003ca href=\"https://swift.org/package-manager\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/spm-compatible-brightgreen.svg?style=flat\" alt=\"Swift Package Manager\" /\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n## Why?\n\nI was a bit surprised there isn't a built-in control for displaying a pager (the dots) given macOS has a NSPageController control.\n\nSo here's a relatively simple packaged drop-in version.\n\n## Features\n\n* Horizontal or vertical alignments\n* Light/Dark mode aware\n* High-constrast support\n* Delegate feedback support\n* Custom color scheme supported\n* Optional keyboard selection support\n* Optional mouse selection support\n\nThe control is designed to be driven by :- \n* Direct interaction, for example using to drive the visible page of a theme selector.\n* Purely display, for example displaying the current page being displayed in an `NSPageController` instance\n* … or a combination of both! \n\n## Installation\n\nUsing Swift Package Manager, add `https://github.com/dagronf/DSFPagerControl` to your project.\n\n## Properties\n\nMany of these properties are `@IBInspectable` so you can set them directly within interface builder when Apple fixes IBDesignable support for packaged NSViews (Boooo! - its only been five years - FB8358478).\n\nIf you copy the package source files into your project IBDesignables will show as expected.\n\n| Name                     | Type           | Description                                         |\n|:-------------------------|:---------------|:----------------------------------------------------|\n| orientation              | `Orientation`  | Is the page control vertically or horizontally oriented? |\n| pageCount                | `Int`          | The number of page indicators to display in the control |\n| selectedPage             | `Int`          | The current page selection (Observable) |\n| selectedColor            | `NSColor?`     | The color to draw a selected page (nil to use default colors) |\n| unselectedColor          | `NSColor?`     | The color to draw an unselected page (nil to use default colors) |\n| bordered                 | `Bool`         | If true, draws a border around the unselected page indicators) |\n| boundsSize               | `CGSize`       | The size of the page indicator |\n| dotSize                  | `CGFloat`      | The size of the dot to be displayed in the center of the page indicator |\n| allowsKeyboardSelection  | `Bool`         | Allow the user to use the keyboard to focus and change the page selection |\n| allowsMouseSelection     | `Bool`         | Allow the user to use the mouse to change the page selection |\n\n## Observables\n\nThese are member variables you can observe for changes\n\n| Name                     | Type     | Description                          |\n|:-------------------------|:---------|:-------------------------------------|\n| pageCount                | `Int`    | The number of pages                  |\n| selectedPage             | `Int`    | The selected page                    |\n| isFirstPage              | `Bool`   | Is the selection the first page?     |\n| isLastPage               | `Bool`   | Is the selection the last page?      |\n\n## Delegate\n\n```swift\nfunc pagerControl(_ pager: DSFPagerControl, willMoveToPage page: Int) -\u003e Bool\n```\n\nCalled when the user attempts to change the selection of the pager control is asked to change to a new page. You can deny the page change by returning `false`\n\nNote this is only called when allowsKeyboardFocus\n\n```swift\nfunc pagerControl(_ pager: DSFPagerControl, didMoveToPage page: Int)\n```\n\nCalled when the pager control has changed to a new page.\n\n## SwiftUI support\n\nYou use `DSFPagerControlUI` to create a pager control within SwiftUI\n\n```swift\nDSFPagerControlUI(\n   pageCount: 10,\n   selectedPage: $selection,\n   allowsMouseSelection: true\n)\n```\n\nSee the SwiftUI demo in the `Demo` subfolder.\n\n## User interaction\n\nThe control optionally supports keyboard and mouse interactions. When the user interacts with the control you can decide whether to perform the change via the use of a delegate.\n\n### Keyboard\n\nWhen `allowsKeyboardSelection` is true, the control will accept focus events and reacts to the following keys :-\n\n* Up/Left: Move to the previous page\n* Down/Right: Move to the next page\n\nWhen a key is pressed, the delegate is called (`willMoveToPage`) to ask whether the change is valid. If so, the pager will update its display and call `didMoveToPage` on the delegate.\n\n### Mouse\n\nWhen `allowsMouseSelection` is true, the cursor will change to a hand when its over the control.  \n\nWhen the user clicks a page indicator, the delegate is called (`willMoveToPage`) to ask whether the change is valid. If so, the pager will update its display and call `didMoveToPage` on the delegate. \n\n## Custom color support\n\nBy default, DSFPagerControl supplies a standard color palette, adapting automatically to the user's light/dark modes and contrast settings.\n\nIf you want to customize your display, the control provides two block callbacks you can supply to return your own custom colors for selected and unselected states.\n\n### selectedColorBlock\n\nProvide a block that returns a custom color to be used when drawing the selected page indicator.\n\n### unselectedColorBlock\n\nProvide a block that returns a custom color to be used when drawing the unselected page indicator.\n\n## License\n\nMIT. Use it and abuse it for anything you want, just attribute my work. Let me know if you do use it somewhere, it'd be great to hear about it!\n\n```\nMIT License\n\nCopyright (c) 2024- Darren Ford\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdagronf%2Fdsfpagercontrol","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdagronf%2Fdsfpagercontrol","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdagronf%2Fdsfpagercontrol/lists"}