{"id":22362641,"url":"https://github.com/markbattistella/triggerkit","last_synced_at":"2026-02-04T04:01:25.400Z","repository":{"id":265982375,"uuid":"897029186","full_name":"markbattistella/TriggerKit","owner":"markbattistella","description":"TriggerKit is a lightweight Swift package designed for building reactive user interface behaviours by responding to state changes through modifiers or standard protocols. It is particularly useful for creating modular, reusable UI components and can be a powerful foundational building block for larger, more feature-rich packages.","archived":false,"fork":false,"pushed_at":"2026-01-08T23:54:52.000Z","size":12,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-22T06:16:46.515Z","etag":null,"topics":["ios","maccatalyst","macos","spm","swift","swift-package-manager","swiftui","tvos","watchos"],"latest_commit_sha":null,"homepage":"https://swiftpackageindex.com/markbattistella/TriggerKit/documentation","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/markbattistella.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null},"funding":{"github":["markbattistella"],"custom":["https://www.paypal.me/markbattistella/5AUD","https://www.paypal.me/markbattistella/10AUD","https://www.paypal.me/markbattistella/20AUD"]}},"created_at":"2024-12-01T22:01:46.000Z","updated_at":"2026-01-08T23:54:13.000Z","dependencies_parsed_at":"2025-04-12T21:09:32.687Z","dependency_job_id":"9e244d6c-d132-46ab-b6e2-e9464b4d4e12","html_url":"https://github.com/markbattistella/TriggerKit","commit_stats":null,"previous_names":["markbattistella/triggerkit"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/markbattistella/TriggerKit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markbattistella%2FTriggerKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markbattistella%2FTriggerKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markbattistella%2FTriggerKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markbattistella%2FTriggerKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/markbattistella","download_url":"https://codeload.github.com/markbattistella/TriggerKit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markbattistella%2FTriggerKit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29067628,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-04T03:31:03.593Z","status":"ssl_error","status_checked_at":"2026-02-04T03:29:50.742Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["ios","maccatalyst","macos","spm","swift","swift-package-manager","swiftui","tvos","watchos"],"created_at":"2024-12-04T17:10:05.213Z","updated_at":"2026-02-04T04:01:25.378Z","avatar_url":"https://github.com/markbattistella.png","language":"Swift","funding_links":["https://github.com/sponsors/markbattistella","https://www.paypal.me/markbattistella/5AUD","https://www.paypal.me/markbattistella/10AUD","https://www.paypal.me/markbattistella/20AUD"],"categories":[],"sub_categories":[],"readme":"\u003c!-- markdownlint-disable MD033 MD041 --\u003e\n\u003cdiv align=\"center\"\u003e\n\n# TriggerKit\n\n![Swift Versions](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fmarkbattistella%2FTriggerKit%2Fbadge%3Ftype%3Dswift-versions)\n\n![Platforms](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fmarkbattistella%2FTriggerKit%2Fbadge%3Ftype%3Dplatforms)\n\n![Licence](https://img.shields.io/badge/Licence-MIT-white?labelColor=blue\u0026style=flat)\n\n\u003c/div\u003e\n\n`TriggerKit` is a lightweight Swift package designed for building reactive user interface behaviours by responding to state changes through modifiers or standard protocols. It is particularly useful for creating modular, reusable UI components and can be a powerful foundational building block for larger, more feature-rich packages.\n\n## Features\n\n- **Reactive State Handling**: Easily define actions that are triggered when state values change.\n- **Extensible Modifier**: Use `StateChangeModifier` to add reactive behaviours to SwiftUI views.\n- **Reusable Protocol**: Implement `TriggerActionPerformable` to standardise how triggers and actions are handled across your app.\n- **Package Friendly**: Although it can be used directly, it is intended to be integrated into other packages.\n\n## Installation\n\nAdd `TriggerKit` to your Swift project using Swift Package Manager.\n\n```swift\ndependencies: [\n  .package(url: \"https://github.com/markbattistella/TriggerKit\", from: \"1.0.0\")\n]\n```\n\nAlternatively, you can add `TriggerKit` using Xcode by navigating to `File \u003e Add Packages` and entering the package repository URL.\n\n## Recommended Usage\n\n\u003e [!NOTE]\n\u003e While you can use this package directly in your code, it is recommended to wrap it in another package or library to integrate it into a larger system. This design pattern promotes loose coupling, making it easier to use and maintain your application. `StateChangeModifier` and `TriggerActionPerformable` are meant to serve as foundational building blocks for more complex state-driven behaviours in other packages, rather than being directly utilised in all instances.\n\n## Usage\n\n### Using `TriggerKit` in Another Swift Package\n\nInstead of directly using `TriggerKit` in your application code, consider wrapping it in a custom package that adds additional functionality. Below is an example of how you might use `TriggerKit` to manage haptic feedback through state changes.\n\n#### Wrapping `TriggerKit` for Haptic Feedback\n\n\u003e [!TIP]\n\u003e See: [HapticsManager](https://github.com/markbattistella/HapticsManager) Swift Package\n\nLet's create a package that implements haptic feedback using `TriggerKit`:\n\n1. Define Custom User Default Keys for Feedback Settings\n\n```swift\npublic struct HapticFeedbackSettings {\n    internal static var isAvailable: Bool { \n      CHHapticEngine.capabilitiesForHardware().supportsHaptics // system level checks\n    }\n    internal static var isEnabled: Bool { \n      userIsPayingCustomer \u0026\u0026 !userNeedsHapticFeedback // your custom checks\n    }\n}\n```\n\n2. Define a Custom Performer for Haptic Feedback\n\n```swift\npublic struct HapticFeedbackPerformer\u003cT: Equatable\u003e: TriggerActionPerformable, FeedbackSettingsConfigurable {\n    public typealias Trigger = T\n\n    public enum Feedback {\n        case impact(UIImpactFeedbackGenerator.FeedbackStyle)\n    }\n\n    public static var isAvailable: Bool { HapticFeedbackSettings.isAvailable }\n    public static var isEnabled: Bool { HapticFeedbackSettings.isEnabled }\n\n    public static func perform(_ feedback: Feedback) {\n      // your logic here\n    }\n\n    public static func canPerform() -\u003e Bool { isAvailable \u0026\u0026 isEnabled }\n}\n```\n\n3. Define a SwiftUI View Modifier for Haptic Feedback\n\nNext, we use `StateChangeModifier` to create a view modifier that provides haptic feedback based on trigger state changes:\n\n```swift\npublic extension View {\n    func hapticFeedback\u003cT: Equatable\u003e(\n        _ feedback: HapticFeedbackPerformer\u003cT\u003e.Feedback,\n        trigger: T\n    ) -\u003e some View {\n        self.modifier(\n            StateChangeModifier(\n                feedback,\n                trigger: trigger,\n                actionHandler: { feedback in\n                    guard HapticFeedbackPerformer\u003cT\u003e.canPerform() else { return }\n                    HapticFeedbackPerformer\u003cT\u003e.perform(feedback)\n                }\n            )\n        )\n    }\n}\n```\n\n### Example Usage in Another Package\n\n```swift\nimport SwiftUI\n\nstruct ContentView: View {\n    @State private var isButtonTapped = false\n\n    var body: some View {\n        Button(action: {\n            isButtonTapped.toggle()\n        }) {\n            Text(\"Tap Me\")\n        }\n        .hapticFeedback(\n            .impact(.light),\n            trigger: isButtonTapped\n        )\n    }\n}\n```\n\nIn this example, every time the button is tapped, a light haptic impact feedback is provided, but only if haptics are enabled and available.\n\n## Contributing\n\nContributions are welcome! Please fork the repository and submit a pull request for any features, fixes, or improvements.\n\n## License\n\n`TriggerKit` is available under the MIT license. See the LICENCE file for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkbattistella%2Ftriggerkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarkbattistella%2Ftriggerkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkbattistella%2Ftriggerkit/lists"}