├── .editorconfig ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── bug_report.md └── workflows │ ├── ci.yml │ ├── codecov.yml │ ├── label.yml │ └── swiftlint.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .swift-version ├── .swiftformat ├── .swiftlint.yml ├── .vscode ├── settings.json └── tasks.json ├── Brewfile ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── NativeDemo ├── Info.plist ├── LaunchScreen.storyboard ├── NSAppDelegate.swift ├── TokamakDemo Native.entitlements ├── TokamakDemo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── UIAppDelegate.swift ├── iOS Info.plist └── macOS.storyboard ├── Package.resolved ├── Package.swift ├── README.md ├── Sources ├── CGDK │ ├── CGDK-Bridging-Header.h │ ├── module.modulemap │ └── termios-Header.h ├── CGTK │ ├── CGTK-Bridging-Header.h │ ├── module.modulemap │ └── termios-Header.h ├── TokamakCore │ ├── Animation │ │ ├── Animatable.swift │ │ ├── AnimatableModifier.swift │ │ ├── Animation.swift │ │ ├── Transaction.swift │ │ ├── VectorArithmetic.swift │ │ ├── _AnimationBoxBase.swift │ │ ├── _AnimationSolvers.swift │ │ ├── _AnyAnimatableData.swift │ │ └── _VectorMath.swift │ ├── App │ │ ├── App.swift │ │ ├── AppStorage.swift │ │ ├── Scenes │ │ │ ├── Scene.swift │ │ │ ├── SceneBuilder.swift │ │ │ ├── ScenePhase.swift │ │ │ ├── SceneStorage.swift │ │ │ ├── WindowGroup.swift │ │ │ └── _SceneModifier.swift │ │ ├── _AnyApp.swift │ │ ├── _AnyScene.swift │ │ ├── _StorageProvider.swift │ │ └── _TupleScene.swift │ ├── DynamicProperty.swift │ ├── Environment │ │ ├── Environment.swift │ │ ├── EnvironmentKey.swift │ │ ├── EnvironmentObject.swift │ │ ├── EnvironmentValues.swift │ │ └── EnvironmentalModifier.swift │ ├── Fiber │ │ ├── AlignmentID.swift │ │ ├── App │ │ │ └── AppVisitor.swift │ │ ├── Fiber+Content.swift │ │ ├── Fiber+CustomDebugStringConvertible.swift │ │ ├── Fiber.swift │ │ ├── FiberElement.swift │ │ ├── FiberReconciler+TreeReducer.swift │ │ ├── FiberReconciler.swift │ │ ├── FiberRenderer.swift │ │ ├── Layout │ │ │ ├── ContainedZLayout.swift │ │ │ ├── Layout.swift │ │ │ ├── LayoutPriority.swift │ │ │ ├── LayoutProperties.swift │ │ │ ├── LayoutSubviews.swift │ │ │ ├── LayoutValueKey.swift │ │ │ ├── PaddingLayout+Layout.swift │ │ │ ├── ProposedViewSize.swift │ │ │ ├── StackLayout.swift │ │ │ ├── ViewSpacing.swift │ │ │ ├── _AspectRatioLayout+Layout.swift │ │ │ ├── _FlexFrameLayout+Layout.swift │ │ │ └── _FrameLayout+Layout.swift │ │ ├── Mutation.swift │ │ ├── Passes │ │ │ ├── FiberReconcilerPass.swift │ │ │ ├── LayoutPass.swift │ │ │ └── ReconcilePass.swift │ │ ├── Scene │ │ │ ├── SceneArguments.swift │ │ │ └── SceneVisitor.swift │ │ ├── ViewArguments.swift │ │ ├── ViewGeometry.swift │ │ ├── ViewVisitor.swift │ │ └── walk.swift │ ├── Modifiers │ │ ├── AppearanceActionModifier.swift │ │ ├── AspectRatioLayout.swift │ │ ├── Effects │ │ │ ├── ClipEffect.swift │ │ │ ├── GeometryEffect.swift │ │ │ ├── OffsetEffect.swift │ │ │ ├── OpacityEffect.swift │ │ │ ├── RotationEffect.swift │ │ │ └── ScaleEffect.swift │ │ ├── FlexFrameLayout.swift │ │ ├── FrameLayout.swift │ │ ├── HoverActionModifier.swift │ │ ├── LifecycleModifier.swift │ │ ├── ModifiedContent.swift │ │ ├── Navigation.swift │ │ ├── PaddingLayout.swift │ │ ├── RedactionReasons.swift │ │ ├── ShadowLayout.swift │ │ ├── StyleModifiers.swift │ │ ├── TaskModifier.swift │ │ ├── ViewModifier.swift │ │ └── ZIndexModifier.swift │ ├── MountedViews │ │ ├── MountedApp.swift │ │ ├── MountedCompositeElement.swift │ │ ├── MountedCompositeView.swift │ │ ├── MountedElement.swift │ │ ├── MountedEmptyView.swift │ │ ├── MountedHostView.swift │ │ ├── MountedScene.swift │ │ └── UnmountTask.swift │ ├── Preferences │ │ ├── PreferenceKey.swift │ │ ├── _PreferenceActionModifier.swift │ │ ├── _PreferenceReadingView.swift │ │ ├── _PreferenceTransformModifier.swift │ │ └── _PreferenceWritingModifier.swift │ ├── PreviewProvider.swift │ ├── Reflection │ │ ├── Layouts │ │ │ ├── ExistentialContainter.swift │ │ │ ├── FieldDescriptor.swift │ │ │ ├── ProtocolTypeContainer.swift │ │ │ ├── StructMetadataLayout.swift │ │ │ ├── StructTypeDescriptor.swift │ │ │ ├── TargetTypeGenericContextDescriptorHeader.swift │ │ │ └── ValueWitnessTable.swift │ │ ├── Metadata │ │ │ ├── Metadata.swift │ │ │ ├── MetadataState.swift │ │ │ └── StructMetadata.swift │ │ ├── Models │ │ │ ├── Kind.swift │ │ │ ├── PropertyInfo.swift │ │ │ └── TypeInfo.swift │ │ ├── Pointers │ │ │ ├── MetadataOffset.swift │ │ │ ├── Pointers.swift │ │ │ └── RelativeVectorPointer.swift │ │ ├── Utilities │ │ │ ├── GettersSetters.swift │ │ │ └── Pointer+Extensions.swift │ │ └── typeConstructorName.swift │ ├── Renderer.swift │ ├── Shapes │ │ ├── AnyShape.swift │ │ ├── ContainerRelativeShape.swift │ │ ├── Ellipse.swift │ │ ├── FixedRoundedRect.swift │ │ ├── ModifiedShapes.swift │ │ ├── Path │ │ │ ├── Path.swift │ │ │ ├── PathLayout.swift │ │ │ ├── PathMutations.swift │ │ │ └── PathSizing.swift │ │ ├── Rectangle.swift │ │ ├── Shape.swift │ │ ├── ShapeModifiers.swift │ │ ├── ShapeStyles │ │ │ ├── BackgroundStyle.swift │ │ │ ├── ForegroundStyle.swift │ │ │ ├── Gradients │ │ │ │ ├── AngularGradient.swift │ │ │ │ ├── EllipticalGradient.swift │ │ │ │ ├── Gradient.swift │ │ │ │ ├── LinearGradient.swift │ │ │ │ └── RadialGradient.swift │ │ │ ├── HierarchicalShapeStyle.swift │ │ │ ├── Material.swift │ │ │ └── ShapeStyle.swift │ │ ├── StrokeStyle.swift │ │ ├── StrokedPath.swift │ │ └── TrimmedPath.swift │ ├── StackReconciler.swift │ ├── State │ │ ├── Binding.swift │ │ ├── ObservedObject.swift │ │ ├── State.swift │ │ ├── StateObject.swift │ │ └── TargetRef.swift │ ├── Stubs │ │ ├── CGStubs.swift │ │ └── UIColor.swift │ ├── Styles │ │ ├── ButtonStyle.swift │ │ ├── ControlGroupStyle.swift │ │ ├── ListStyle.swift │ │ ├── NavigationLinkStyle.swift │ │ ├── OutlineGroupStyle.swift │ │ ├── PickerStyle.swift │ │ ├── PrimitiveButtonStyle.swift │ │ ├── TextFieldStyle.swift │ │ └── ToggleStyle.swift │ ├── Target.swift │ ├── Tokens │ │ ├── Angle.swift │ │ ├── AnyTokenBox.swift │ │ ├── Axis.swift │ │ ├── Color │ │ │ ├── Color.swift │ │ │ ├── ColorBoxes.swift │ │ │ └── ColorKeys.swift │ │ ├── ColorScheme.swift │ │ ├── Controls │ │ │ ├── ButtonRole.swift │ │ │ ├── ControlSize.swift │ │ │ └── Prominence.swift │ │ ├── Edge.swift │ │ ├── Font │ │ │ ├── Font.swift │ │ │ ├── FontBoxes.swift │ │ │ └── FontModifiers.swift │ │ ├── GridItem.swift │ │ ├── LayoutDirection.swift │ │ ├── LineBreakMode.swift │ │ ├── TextAlignment.swift │ │ └── UnitPoint.swift │ ├── ViewTraits │ │ ├── TagValueTraitKey.swift │ │ ├── Transition │ │ │ ├── Transition.swift │ │ │ └── TransitionBoxes.swift │ │ ├── _ViewTraitKey.swift │ │ └── _ViewTraitStore.swift │ └── Views │ │ ├── AnyView.swift │ │ ├── Canvas │ │ ├── Canvas.swift │ │ ├── GraphicsContext │ │ │ ├── BlendMode.swift │ │ │ ├── Filter.swift │ │ │ ├── GraphicsContext.swift │ │ │ ├── Resolvables.swift │ │ │ └── Shading.swift │ │ └── TimelineView.swift │ │ ├── Containers │ │ ├── DisclosureGroup.swift │ │ ├── ForEach.swift │ │ ├── Group.swift │ │ ├── List │ │ │ ├── List+Init.swift │ │ │ ├── List+SelectionValue.swift │ │ │ └── List.swift │ │ ├── OutlineGroup.swift │ │ ├── Section.swift │ │ ├── TupleView.swift │ │ └── VariadicView.swift │ │ ├── Controls │ │ ├── Button.swift │ │ ├── ControlGroup.swift │ │ ├── Link.swift │ │ └── Selectors │ │ │ ├── DatePicker.swift │ │ │ ├── Picker.swift │ │ │ ├── Slider.swift │ │ │ └── Toggle.swift │ │ ├── Image.swift │ │ ├── Layout │ │ ├── GeometryReader.swift │ │ ├── HStack.swift │ │ ├── LazyHGrid.swift │ │ ├── LazyVGrid.swift │ │ ├── ScrollView.swift │ │ ├── VStack.swift │ │ └── ZStack.swift │ │ ├── Navigation │ │ ├── NavigationBarItem.swift │ │ ├── NavigationLink.swift │ │ ├── NavigationView.swift │ │ ├── Toolbar.swift │ │ ├── ToolbarContentBuilder.swift │ │ └── ToolbarItem.swift │ │ ├── Progress │ │ ├── ProgressView.swift │ │ └── ProgressViewStyle.swift │ │ ├── Spacers │ │ ├── Divider.swift │ │ └── Spacer.swift │ │ ├── Text │ │ ├── SecureField.swift │ │ ├── Text.swift │ │ ├── TextEditor.swift │ │ └── TextField.swift │ │ ├── View.swift │ │ └── ViewBuilder.swift ├── TokamakCoreBenchmark │ └── main.swift ├── TokamakDOM │ ├── App │ │ ├── App.swift │ │ ├── ColorSchemeObserver.swift │ │ └── ScenePhaseObserver.swift │ ├── Core.swift │ ├── DOMFiberRenderer.swift │ ├── DOMNode.swift │ ├── DOMRef.swift │ ├── DOMRenderer.swift │ ├── Modifiers │ │ ├── ActionModifier.swift │ │ ├── Hover.swift │ │ ├── ModifiedContent.swift │ │ └── Transitions.swift │ ├── Storage │ │ ├── LocalStorage.swift │ │ ├── SessionStorage.swift │ │ └── WebStorage.swift │ ├── Styles │ │ ├── ColorScheme.swift │ │ └── ToggleStyle.swift │ └── Views │ │ ├── Buttons │ │ └── Button.swift │ │ ├── Canvas │ │ ├── Canvas.swift │ │ ├── ImageOperations.swift │ │ ├── PathOperations.swift │ │ ├── SymbolOperations.swift │ │ ├── TextOperations.swift │ │ └── TimelineView.swift │ │ ├── Containers │ │ └── DisclosureGroup.swift │ │ ├── DynamicHTML.swift │ │ ├── Layout │ │ └── GeometryReader.swift │ │ ├── Navigation │ │ └── NavigationLink.swift │ │ ├── Selectors │ │ ├── DatePicker.swift │ │ ├── Picker.swift │ │ └── Slider.swift │ │ └── Text │ │ ├── SecureField.swift │ │ ├── TextEditor.swift │ │ └── TextField.swift ├── TokamakDemo │ ├── Buttons │ │ ├── ButtonStyleDemo.swift │ │ └── Counter.swift │ ├── Containers │ │ ├── ForEachDemo.swift │ │ ├── ListDemo.swift │ │ ├── OutlineGroupDemo.swift │ │ └── SidebarDemo.swift │ ├── DOM │ │ ├── DOMRefDemo.swift │ │ └── URLHashDemo.swift │ ├── Drawing │ │ ├── CanvasDemo.swift │ │ ├── ColorDemo.swift │ │ ├── PathDemo.swift │ │ └── ShapeStyleDemo.swift │ ├── Layout │ │ ├── GeometryReaderDemo.swift │ │ ├── GridDemo.swift │ │ ├── SpacerDemo.swift │ │ └── StackDemo.swift │ ├── Misc │ │ ├── AnimationDemo.swift │ │ ├── AppStorageDemo.swift │ │ ├── EnvironmentDemo.swift │ │ ├── PreferenceKeyDemo.swift │ │ ├── ProgressViewDemo.swift │ │ ├── RedactDemo.swift │ │ └── TransitionDemo.swift │ ├── Modifiers │ │ ├── ShadowDemo.swift │ │ └── TaskDemo.swift │ ├── Selectors │ │ ├── DatePickerDemo.swift │ │ ├── PickerDemo.swift │ │ ├── SliderDemo.swift │ │ └── ToggleDemo.swift │ ├── Text │ │ ├── TextDemo.swift │ │ ├── TextEditorDemo.swift │ │ └── TextFieldDemo.swift │ ├── TokamakDemo.swift │ ├── logo-header.png │ └── main.swift ├── TokamakGTK │ ├── App │ │ └── App.swift │ ├── Core.swift │ ├── GSignal.swift │ ├── GTKRenderer.swift │ ├── GtkContainer+forEach.swift │ ├── Modifiers │ │ ├── LayoutModifiers.swift │ │ └── WidgetModifier.swift │ ├── Scenes │ │ ├── SceneContainerView.swift │ │ └── WindowGroup.swift │ ├── Shapes │ │ └── Shape.swift │ ├── Tokens │ │ └── BuiltinColors.swift │ ├── Views │ │ ├── Button.swift │ │ ├── Image.swift │ │ ├── List.swift │ │ ├── NavigationView.swift │ │ ├── Picker.swift │ │ ├── ScrollView.swift │ │ ├── Stack.swift │ │ ├── Text.swift │ │ └── TextField.swift │ └── Widget.swift ├── TokamakGTKCHelpers │ ├── include │ │ └── type_check.h │ └── type_check.c ├── TokamakGTKDemo │ ├── logo-header.png │ └── main.swift ├── TokamakShim │ └── TokamakShim.swift ├── TokamakStaticHTML │ ├── App.swift │ ├── Core.swift │ ├── Modifiers │ │ ├── Effects │ │ │ ├── OffsetEffect.swift │ │ │ ├── OpacityEffect.swift │ │ │ ├── RotationEffect.swift │ │ │ └── ScaleEffect.swift │ │ ├── LayoutModifiers.swift │ │ ├── ModifiedContent.swift │ │ ├── ViewModifier.swift │ │ ├── _BackgroundShapeModifier.swift │ │ ├── _BackgroundStyleModifier.swift │ │ └── _DomTextSanitizer.swift │ ├── Preferences │ │ └── Preferences.swift │ ├── Resources │ │ └── TokamakStyles.swift │ ├── Sanitizer.swift │ ├── Scenes │ │ └── WindowGroup.swift │ ├── Shapes │ │ ├── Path.swift │ │ ├── Shape.swift │ │ └── _ShapeView.swift │ ├── StaticHTMLFiberRenderer.swift │ ├── StaticHTMLRenderer.swift │ ├── Tokens │ │ ├── BuiltinColors.swift │ │ └── Tokens.swift │ └── Views │ │ ├── Buttons │ │ └── Link.swift │ │ ├── Containers │ │ └── List.swift │ │ ├── HTML.swift │ │ ├── Head │ │ ├── Meta.swift │ │ └── Title.swift │ │ ├── Images │ │ └── Image.swift │ │ ├── Layout │ │ ├── HStack.swift │ │ ├── LazyHGrid.swift │ │ ├── LazyVGrid.swift │ │ ├── ScrollView.swift │ │ ├── VStack.swift │ │ └── ZStack.swift │ │ ├── Navigation │ │ └── NavigationView.swift │ │ ├── Progress │ │ └── ProgressView.swift │ │ ├── Spacers │ │ ├── Divider.swift │ │ └── Spacer.swift │ │ └── Text │ │ └── Text.swift ├── TokamakStaticHTMLBenchmark │ └── main.swift ├── TokamakStaticHTMLDemo │ ├── ContentView.swift │ └── main.swift └── TokamakTestRenderer │ ├── App.swift │ ├── TestFiberRenderer.swift │ ├── TestRenderer.swift │ ├── TestView.swift │ ├── TestViewProxy.swift │ └── WindowGroup.swift ├── Tests ├── TokamakLayoutTests │ ├── Alignment+allCases.swift │ ├── AspectRatioTests.swift │ ├── ContainedZLayoutTests.swift │ ├── FrameTests.swift │ ├── StackTests.swift │ └── compare.swift ├── TokamakReconcilerTests │ ├── PreferenceTests.swift │ └── VisitorTests.swift ├── TokamakStaticHTMLTests │ ├── HTMLStrategy.swift │ ├── HTMLTests.swift │ ├── RenderingTests │ │ ├── LayoutTests.swift │ │ ├── ShapeTests.swift │ │ ├── Snapshotting+Image.swift │ │ ├── ViewTests.swift │ │ ├── VisualTests.swift │ │ └── __Snapshots__ │ │ │ ├── LayoutTests │ │ │ ├── testAnchoredModifiers.1.png │ │ │ ├── testAspectRatio.1.png │ │ │ ├── testAspectRatio.2.png │ │ │ ├── testBackground.1.png │ │ │ ├── testBackground.2.png │ │ │ ├── testFrames.1.png │ │ │ ├── testOverlay.1.png │ │ │ ├── testOverlay.2.png │ │ │ ├── testStacks.1.png │ │ │ └── testStacks.2.png │ │ │ ├── ShapeTests │ │ │ ├── testContainerRelativeShape.1.png │ │ │ ├── testPath.1.png │ │ │ └── testStrokedCircle.1.png │ │ │ ├── ViewTests │ │ │ └── testProgressView.1.png │ │ │ └── VisualTests │ │ │ ├── testContentStyles.1.png │ │ │ ├── testContentStyles.2.png │ │ │ ├── testForegroundStyle.1.png │ │ │ ├── testGradients-A.1.png │ │ │ ├── testGradients-B.1.png │ │ │ ├── testMaterial.1.png │ │ │ ├── testOpacity.1.png │ │ │ └── testScaleEffect.1.png │ ├── SanitizerTests.swift │ └── __Snapshots__ │ │ └── HTMLTests │ │ ├── testDoubleTitle.1.html │ │ ├── testDoubleTitleModifier.1.html │ │ ├── testFontStacks.1.html │ │ ├── testFontStacks.2.html │ │ ├── testHTMLSanitizer.1.html │ │ ├── testHTMLSanitizer.2.html │ │ ├── testMetaAll.1.html │ │ ├── testMetaCharset.1.html │ │ ├── testMetaCharsetModifier.1.html │ │ ├── testOptional.1.html │ │ ├── testPaddingFusion.1.html │ │ ├── testPaddingFusion.2.html │ │ ├── testPreferencePropagation.1.html │ │ ├── testTitle.1.html │ │ └── testTitleModifier.1.html └── TokamakTests │ ├── ColorTests.swift │ ├── EnvironmentTests.swift │ ├── GetSetStructTests.swift │ ├── MetadataTests.swift │ ├── ReconcilerStressTests.swift │ ├── ReconcilerTests.swift │ ├── ValuePointerTests.swift │ └── ValueWitnessTableTests.swift ├── benchmark.sh └── docs ├── FAQ.md ├── RenderersGuide.md └── progress.md /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = lf 3 | insert_final_newline = true 4 | indent_style = space 5 | indent_size = 2 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [carson-katri, kateinoigakukun, MaxDesiatov] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: carson-katri 7 | 8 | --- 9 | 10 | 11 | 12 | **Describe the bug** 13 | A clear and concise description of what the bug is. 14 | 15 | **To Reproduce** 16 | Steps to reproduce the behavior: 17 | 1. Go to '...' 18 | 2. Click on '....' 19 | 3. Scroll down to '....' 20 | 4. See error 21 | 22 | 23 | 24 | **Expected behavior** 25 | A clear and concise description of what you expected to happen. 26 | 27 | **Screenshots** 28 | If this is a layout/rendering issue, please provide screenshots for both Tokamak and SwiftUI that highlight the difference. 29 | 30 | **Desktop (please complete the following information):** 31 | - OS: [e.g. macOS 12.4] 32 | - Browser [e.g. chrome, safari] 33 | - Version of the browser [e.g. 22] 34 | - Version of Tokamak [e.g. 0.10.1] 35 | 36 | **Smartphone (please complete the following information):** 37 | - Device: [e.g. iPhone 6] 38 | - OS: [e.g. iOS15.1] 39 | - Browser [e.g. stock browser, safari] 40 | - Version of the browser [e.g. 22] 41 | - Version of Tokamak [e.g. 0.10.1] 42 | 43 | **Additional context** 44 | Add any other context about the problem here. 45 | -------------------------------------------------------------------------------- /.github/workflows/codecov.yml: -------------------------------------------------------------------------------- 1 | name: Codecov 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: [main] 7 | 8 | jobs: 9 | codecov: 10 | container: 11 | image: swiftlang/swift:nightly-5.7-focal 12 | runs-on: ubuntu-latest 13 | steps: 14 | - run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y gtk+-3.0 libgtk+-3.0 15 | - name: Checkout Branch 16 | uses: actions/checkout@v2 17 | - name: Build Test Target 18 | run: swift build -Xswiftc -profile-coverage-mapping -Xswiftc -profile-generate --product TokamakPackageTests 19 | - name: Run Tests 20 | run: swift test --enable-code-coverage --skip-build 21 | - name: Generate Branch Coverage Report 22 | uses: mattpolzin/swift-codecov-action@0.7.1 23 | id: cov 24 | with: 25 | MINIMUM_COVERAGE: 15 26 | - name: Post Positive Results 27 | if: ${{ success() }} 28 | run: | 29 | echo "::warning file=Package.swift,line=1,col=1::The current code coverage percentage is passing with ${{ steps.cov.outputs.codecov }} (minimum allowed: ${{ steps.cov.outputs.minimum_coverage }}%)." 30 | - name: Post Negative Results 31 | if: ${{ failure() }} 32 | run: | 33 | echo "::error file=Package.swift,line=1,col=1::The current code coverage percentage is failing with ${{ steps.cov.outputs.codecov }} (minimum allowed: ${{ steps.cov.outputs.minimum_coverage }}%)." 34 | -------------------------------------------------------------------------------- /.github/workflows/label.yml: -------------------------------------------------------------------------------- 1 | name: Check PR labels 2 | 3 | # Controls when the action will run. Triggers the workflow on push or pull request 4 | # events but only for the `main` branch 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | types: [ opened, synchronize, reopened, labeled, unlabeled ] 9 | 10 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 11 | jobs: 12 | check-labels: 13 | # The type of runner that the job will run on 14 | runs-on: ubuntu-20.04 15 | 16 | steps: 17 | - name: Match PR Label 18 | uses: zwaldowski/match-label-action@v2 19 | with: 20 | allowed_multiple: > 21 | API design, 22 | bug, 23 | continuous integration, 24 | dependencies, 25 | documentation, 26 | enhancement, 27 | Fiber, 28 | refactor, 29 | SwiftUI compatibility, 30 | test suite, 31 | GTK renderer, 32 | -------------------------------------------------------------------------------- /.github/workflows/swiftlint.yml: -------------------------------------------------------------------------------- 1 | name: SwiftLint 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/swiftlint.yml" 7 | - ".swiftlint.yml" 8 | - "**/*.swift" 9 | 10 | jobs: 11 | SwiftLint: 12 | runs-on: ubuntu-20.04 13 | steps: 14 | - uses: actions/checkout@v1 15 | # Fetch current versions of files 16 | - name: Fetch base ref 17 | run: | 18 | git fetch --prune --no-tags --depth=1 origin +refs/heads/${{ github.base_ref }}:refs/heads/${{ github.base_ref }} 19 | # Diff pull request to current files, then SwiftLint changed files 20 | - name: GitHub Action for SwiftLint 21 | uses: mayk-it/action-swiftlint@3.2.2 22 | env: 23 | DIFF_BASE: ${{ github.base_ref }} 24 | DIFF_HEAD: HEAD 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | .swiftpm/xcode 22 | *.xcodeproj 23 | 24 | # Bundler 25 | .bundle 26 | 27 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 28 | # Carthage/Checkouts 29 | 30 | Carthage/Build 31 | 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 35 | # 36 | # Note: if you ignore the Pods directory, make sure to uncomment 37 | # `pod install` in .travis.yml 38 | # 39 | Pods/ 40 | 41 | # SwiftPM 42 | .build 43 | /Packages 44 | 45 | # VS Code 46 | .vscode/launch.json 47 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # See https://pre-commit.com for more information 2 | # See https://pre-commit.com/hooks.html for more hooks 3 | exclude: __Snapshots__ 4 | repos: 5 | - repo: https://github.com/pre-commit/pre-commit-hooks 6 | rev: v2.5.0 7 | hooks: 8 | - id: trailing-whitespace 9 | - id: end-of-file-fixer 10 | - id: check-yaml 11 | - id: check-added-large-files 12 | - id: detect-private-key 13 | - id: check-merge-conflict 14 | - repo: https://github.com/hodovani/pre-commit-swift 15 | rev: master 16 | hooks: 17 | - id: swift-lint 18 | - id: swift-format 19 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | wasm-5.6.0-RELEASE 2 | -------------------------------------------------------------------------------- /.swiftformat: -------------------------------------------------------------------------------- 1 | --indent 2 2 | --indentcase false 3 | --trimwhitespace always 4 | --voidtype tuple 5 | --nospaceoperators ..<,... 6 | --ifdef noindent 7 | --stripunusedargs closure-only 8 | --maxwidth 100 9 | --wraparguments before-first 10 | --funcattributes prev-line 11 | --typeattributes prev-line 12 | --varattributes prev-line 13 | --disable andOperator 14 | --swiftversion 5.6 15 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | disabled_rules: 2 | - trailing_comma 3 | - identifier_name 4 | - void_return 5 | - operator_whitespace 6 | - nesting 7 | - cyclomatic_complexity 8 | - multiple_closures_with_trailing_closure 9 | - type_name 10 | - todo 11 | - large_tuple 12 | - opening_brace 13 | 14 | line_length: 100 15 | 16 | function_body_length: 17 | - 50 18 | 19 | included: 20 | - Sources 21 | - Tests 22 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "licenser.author": "Tokamak contributors", 4 | "cSpell.words": [ 5 | "Tokamak" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "swift build", 8 | "type": "shell", 9 | "command": "swift build" 10 | }, 11 | { 12 | "label": "swift test", 13 | "type": "shell", 14 | "command": "swift build --product TokamakPackageTests && `xcrun --find xctest` .build/debug/TokamakPackageTests.xctest" 15 | }, 16 | { 17 | "label": "carton dev", 18 | "type": "shell", 19 | "command": "carton dev --product TokamakDemo" 20 | }, 21 | { 22 | "label": "benchmark", 23 | "type": "shell", 24 | "command": "./benchmark.sh" 25 | }, 26 | { 27 | "label": "make", 28 | "type": "shell", 29 | "command": "make", 30 | "problemMatcher": [], 31 | "group": { 32 | "kind": "build", 33 | "isDefault": true 34 | } 35 | }, 36 | { 37 | "label": "make run", 38 | "type": "shell", 39 | "command": "make run", 40 | "problemMatcher": [], 41 | "group": { 42 | "kind": "build", 43 | "isDefault": true 44 | } 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /Brewfile: -------------------------------------------------------------------------------- 1 | brew "pre-commit" 2 | brew "swiftformat" 3 | brew "swiftlint" 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LINKER_FLAGS := $(shell pkg-config --libs gtk+-3.0 gdk-3.0) 2 | C_FLAGS := $(shell pkg-config --cflags gtk+-3.0) 3 | SWIFT_LINKER_FLAGS ?= -Xlinker $(shell echo $(LINKER_FLAGS) | sed -e "s/ / -Xlinker /g" | sed -e "s/-Xlinker -Wl,-framework,/-Xlinker -framework -Xlinker /g") 4 | SWIFT_C_FLAGS ?= -Xcc $(shell echo $(C_FLAGS) | sed -e "s/ / -Xcc /g") 5 | 6 | all: build 7 | 8 | build: 9 | swift build --enable-test-discovery --product TokamakGTKDemo $(SWIFT_C_FLAGS) $(SWIFT_LINKER_FLAGS) 10 | 11 | run: build 12 | .build/debug/TokamakGTKDemo 13 | -------------------------------------------------------------------------------- /NativeDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSMainStoryboardFile 26 | macOS 27 | NSPrincipalClass 28 | NSApplication 29 | 30 | 31 | -------------------------------------------------------------------------------- /NativeDemo/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /NativeDemo/NSAppDelegate.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2019-2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Jed Fox on 07/01/2020. 16 | // 17 | 18 | import Cocoa 19 | import SwiftUI 20 | 21 | @NSApplicationMain 22 | class AppDelegate: NSObject, NSApplicationDelegate { 23 | var window: NSWindow! 24 | 25 | func applicationDidFinishLaunching(_ aNotification: Notification) { 26 | window = NSWindow( 27 | contentRect: NSRect(x: 0, y: 0, width: 480, height: 300), 28 | styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], 29 | backing: .buffered, defer: false 30 | ) 31 | window.isReleasedWhenClosed = false 32 | window.center() 33 | window.contentView = NSHostingView(rootView: TokamakDemoView()) 34 | window.makeKeyAndOrderFront(nil) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /NativeDemo/TokamakDemo Native.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.network.client 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /NativeDemo/TokamakDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /NativeDemo/TokamakDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /NativeDemo/UIAppDelegate.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2019-2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Jed Fox on 07/01/2020. 16 | // 17 | 18 | import SwiftUI 19 | import UIKit 20 | 21 | // so we only need one Info.plist 22 | public class NSApplication: UIApplication {} 23 | 24 | @UIApplicationMain 25 | class AppDelegate: UIResponder, UIApplicationDelegate { 26 | var window: UIWindow? 27 | func application( 28 | _: UIApplication, 29 | didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil 30 | ) -> Bool { 31 | window = UIWindow() 32 | window?.rootViewController = UIHostingController(rootView: TokamakDemoView()) 33 | window?.makeKeyAndVisible() 34 | return true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/CGDK/CGDK-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /Sources/CGDK/module.modulemap: -------------------------------------------------------------------------------- 1 | module CGDK { 2 | header "./termios-Header.h" 3 | header "./CGDK-Bridging-Header.h" 4 | 5 | link "gdk-3" 6 | 7 | export * 8 | } 9 | -------------------------------------------------------------------------------- /Sources/CGDK/termios-Header.h: -------------------------------------------------------------------------------- 1 | #include -------------------------------------------------------------------------------- /Sources/CGTK/CGTK-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #include -------------------------------------------------------------------------------- /Sources/CGTK/module.modulemap: -------------------------------------------------------------------------------- 1 | module CGTK { 2 | header "./termios-Header.h" 3 | header "./CGTK-Bridging-Header.h" 4 | 5 | link "gtk-3" 6 | 7 | export * 8 | } -------------------------------------------------------------------------------- /Sources/CGTK/termios-Header.h: -------------------------------------------------------------------------------- 1 | #include -------------------------------------------------------------------------------- /Sources/TokamakCore/Animation/AnimatableModifier.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/11/21. 16 | // 17 | 18 | public protocol AnimatableModifier: Animatable, ViewModifier {} 19 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Animation/VectorArithmetic.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/11/21. 16 | // 17 | 18 | import Foundation 19 | 20 | public protocol VectorArithmetic: AdditiveArithmetic { 21 | mutating func scale(by rhs: Double) 22 | var magnitudeSquared: Double { get } 23 | } 24 | 25 | extension Float: VectorArithmetic { 26 | @_transparent 27 | public mutating func scale(by rhs: Double) { self *= Float(rhs) } 28 | 29 | @_transparent 30 | public var magnitudeSquared: Double { 31 | @_transparent get { Double(self * self) } 32 | } 33 | } 34 | 35 | extension Double: VectorArithmetic { 36 | @_transparent 37 | public mutating func scale(by rhs: Double) { self *= rhs } 38 | 39 | @_transparent 40 | public var magnitudeSquared: Double { 41 | @_transparent get { self * self } 42 | } 43 | } 44 | 45 | extension CGFloat: VectorArithmetic { 46 | @_transparent 47 | public mutating func scale(by rhs: Double) { self *= CGFloat(rhs) } 48 | 49 | @_transparent 50 | public var magnitudeSquared: Double { 51 | @_transparent get { Double(self * self) } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Sources/TokamakCore/App/Scenes/ScenePhase.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/19/20. 16 | // 17 | 18 | public enum ScenePhase: Comparable { 19 | case active 20 | case inactive 21 | case background 22 | } 23 | 24 | struct ScenePhaseKey: EnvironmentKey { 25 | static let defaultValue: ScenePhase = .active 26 | } 27 | 28 | public extension EnvironmentValues { 29 | var scenePhase: ScenePhase { 30 | get { 31 | self[ScenePhaseKey.self] 32 | } 33 | set { 34 | self[ScenePhaseKey.self] = newValue 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Sources/TokamakCore/App/Scenes/_SceneModifier.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/20/20. 16 | // 17 | 18 | public protocol _SceneModifier { 19 | associatedtype Body: Scene 20 | typealias SceneContent = _SceneModifier_Content 21 | func body(content: SceneContent) -> Self.Body 22 | } 23 | 24 | public struct _SceneModifier_Content: Scene where Modifier: _SceneModifier { 25 | public let modifier: Modifier 26 | public let scene: _AnyScene 27 | 28 | @_spi(TokamakCore) 29 | public var body: Never { 30 | neverScene("_SceneModifier_Content") 31 | } 32 | } 33 | 34 | public extension Scene { 35 | func modifier(_ modifier: Modifier) -> ModifiedContent { 36 | .init(content: self, modifier: modifier) 37 | } 38 | } 39 | 40 | public extension _SceneModifier where Body == Never { 41 | func body(content: SceneContent) -> Body { 42 | fatalError(""" 43 | \(self) is a primitive `_SceneModifier`, you're not supposed to run `body(content:)` 44 | """) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Sources/TokamakCore/App/_StorageProvider.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/22/20. 16 | // 17 | 18 | import OpenCombineShim 19 | 20 | public protocol _StorageProvider { 21 | func store(key: String, value: Bool?) 22 | func store(key: String, value: Int?) 23 | func store(key: String, value: Double?) 24 | func store(key: String, value: String?) 25 | 26 | func read(key: String) -> Bool? 27 | func read(key: String) -> Int? 28 | func read(key: String) -> Double? 29 | func read(key: String) -> String? 30 | 31 | static var standard: _StorageProvider { get } 32 | var publisher: ObservableObjectPublisher { get } 33 | } 34 | -------------------------------------------------------------------------------- /Sources/TokamakCore/App/_TupleScene.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/16/20. 16 | // 17 | 18 | struct _TupleScene: Scene, GroupScene { 19 | let value: T 20 | let children: [_AnyScene] 21 | let visit: (SceneVisitor) -> () 22 | 23 | init( 24 | _ value: T, 25 | children: [_AnyScene], 26 | visit: @escaping (SceneVisitor) -> () 27 | ) { 28 | self.value = value 29 | self.children = children 30 | self.visit = visit 31 | } 32 | 33 | var body: Never { 34 | neverScene("_TupleScene") 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/TokamakCore/DynamicProperty.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/17/20. 16 | // 17 | 18 | public protocol DynamicProperty { 19 | mutating func update() 20 | } 21 | 22 | public extension DynamicProperty { 23 | mutating func update() {} 24 | } 25 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Environment/EnvironmentalModifier.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/11/21. 16 | // 17 | 18 | /// A modifier that resolves to a concrete modifier in an environment. 19 | public protocol EnvironmentalModifier: ViewModifier { 20 | associatedtype ResolvedModifier: ViewModifier 21 | func resolve(in environment: EnvironmentValues) -> ResolvedModifier 22 | static var _requiresMainThread: Bool { get } 23 | } 24 | 25 | private struct EnvironmentalModifierResolver: ViewModifier, EnvironmentReader 26 | where M: EnvironmentalModifier 27 | { 28 | let modifier: M 29 | var resolved: M.ResolvedModifier! 30 | 31 | func body(content: Content) -> some View { 32 | content.modifier(resolved) 33 | } 34 | 35 | mutating func setContent(from values: EnvironmentValues) { 36 | resolved = modifier.resolve(in: values) 37 | } 38 | } 39 | 40 | public extension EnvironmentalModifier { 41 | static var _requiresMainThread: Bool { true } 42 | 43 | func body(content: _ViewModifier_Content) -> some View { 44 | content.modifier(EnvironmentalModifierResolver(modifier: self)) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Fiber/App/AppVisitor.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 5/31/22. 16 | // 17 | 18 | /// A type that can visit an `App`. 19 | public protocol AppVisitor: ViewVisitor { 20 | func visit(_ app: A) 21 | } 22 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Fiber/FiberElement.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 2/15/22. 16 | // 17 | 18 | /// A reference type that points to a `Renderer`-specific element that has been mounted. 19 | /// For instance, a DOM node in the `DOMFiberRenderer`. 20 | public protocol FiberElement: AnyObject { 21 | associatedtype Content: FiberElementContent 22 | var content: Content { get } 23 | init(from content: Content) 24 | func update(with content: Content) 25 | } 26 | 27 | /// The data used to create an `FiberElement`. 28 | /// 29 | /// We re-use `FiberElement` instances in the `Fiber` tree, 30 | /// but can re-create and copy `FiberElementContent` as often as needed. 31 | public protocol FiberElementContent: Equatable { 32 | init(from primitiveView: V, useDynamicLayout: Bool) 33 | } 34 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Fiber/Layout/LayoutPriority.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 6/22/22. 16 | // 17 | 18 | import Foundation 19 | 20 | @usableFromInline 21 | enum LayoutPriorityTraitKey: _ViewTraitKey { 22 | @inlinable 23 | static var defaultValue: Double { 0 } 24 | } 25 | 26 | public extension View { 27 | @inlinable 28 | func layoutPriority(_ value: Double) -> some View { 29 | _trait(LayoutPriorityTraitKey.self, value) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Fiber/Layout/LayoutProperties.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 6/20/22. 16 | // 17 | 18 | /// Metadata about a `Layout`. 19 | public struct LayoutProperties { 20 | public var stackOrientation: Axis? 21 | 22 | public init() { 23 | stackOrientation = nil 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Fiber/Layout/LayoutValueKey.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 6/20/22. 16 | // 17 | 18 | /// A key that stores a value that can be accessed via a `LayoutSubview`. 19 | public protocol LayoutValueKey { 20 | associatedtype Value 21 | static var defaultValue: Self.Value { get } 22 | } 23 | 24 | public extension View { 25 | @inlinable 26 | func layoutValue(key: K.Type, value: K.Value) -> some View where K: LayoutValueKey { 27 | // LayoutValueKey uses trait keys under the hood. 28 | _trait(_LayoutTrait.self, value) 29 | } 30 | } 31 | 32 | public struct _LayoutTrait: _ViewTraitKey where K: LayoutValueKey { 33 | public static var defaultValue: K.Value { 34 | K.defaultValue 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Fiber/Layout/ProposedViewSize.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 6/20/22. 16 | // 17 | 18 | import Foundation 19 | 20 | @frozen 21 | public struct ProposedViewSize: Equatable { 22 | public var width: CGFloat? 23 | public var height: CGFloat? 24 | public static let zero: ProposedViewSize = .init(width: 0, height: 0) 25 | public static let unspecified: ProposedViewSize = .init(width: nil, height: nil) 26 | public static let infinity: ProposedViewSize = .init(width: .infinity, height: .infinity) 27 | @inlinable 28 | public init(width: CGFloat?, height: CGFloat?) { 29 | (self.width, self.height) = (width, height) 30 | } 31 | 32 | @inlinable 33 | public init(_ size: CGSize) { 34 | self.init(width: size.width, height: size.height) 35 | } 36 | 37 | @inlinable 38 | public func replacingUnspecifiedDimensions(by size: CGSize = CGSize( 39 | width: 10, 40 | height: 10 41 | )) -> CGSize { 42 | CGSize(width: width ?? size.width, height: height ?? size.height) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Fiber/Mutation.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 2/15/22. 16 | // 17 | 18 | import Foundation 19 | 20 | public enum Mutation { 21 | case insert( 22 | element: Renderer.ElementType, 23 | parent: Renderer.ElementType, 24 | index: Int 25 | ) 26 | case remove(element: Renderer.ElementType, parent: Renderer.ElementType?) 27 | case replace( 28 | parent: Renderer.ElementType, 29 | previous: Renderer.ElementType, 30 | replacement: Renderer.ElementType 31 | ) 32 | case update( 33 | previous: Renderer.ElementType, 34 | newContent: Renderer.ElementType.Content, 35 | geometry: ViewGeometry 36 | ) 37 | case layout(element: Renderer.ElementType, geometry: ViewGeometry) 38 | } 39 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Fiber/Scene/SceneArguments.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 5/30/22. 16 | // 17 | 18 | import Foundation 19 | 20 | public extension Scene { 21 | // By default, we simply pass the inputs through without modifications. 22 | static func _makeScene(_ inputs: SceneInputs) -> SceneOutputs { 23 | .init(inputs: inputs) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Modifiers/AppearanceActionModifier.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | protocol AppearanceActionType { 16 | var appear: (() -> ())? { get } 17 | var disappear: (() -> ())? { get } 18 | } 19 | 20 | /// Underscore is present in the name for SwiftUI compatibility. 21 | struct _AppearanceActionModifier: ViewModifier { 22 | var appear: (() -> ())? 23 | var disappear: (() -> ())? 24 | 25 | typealias Body = Never 26 | } 27 | 28 | extension ModifiedContent: AppearanceActionType 29 | where Content: View, Modifier == _AppearanceActionModifier 30 | { 31 | var appear: (() -> ())? { modifier.appear } 32 | var disappear: (() -> ())? { modifier.disappear } 33 | } 34 | 35 | public extension View { 36 | func onAppear(perform action: (() -> ())? = nil) -> some View { 37 | modifier(_AppearanceActionModifier(appear: action)) 38 | } 39 | 40 | func onDisappear(perform action: (() -> ())? = nil) -> some View { 41 | modifier(_AppearanceActionModifier(disappear: action)) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Modifiers/Effects/OffsetEffect.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/12/21. 16 | // 17 | 18 | import Foundation 19 | 20 | @frozen 21 | public struct _OffsetEffect: GeometryEffect, Equatable { 22 | public var offset: CGSize 23 | 24 | @inlinable 25 | public init(offset: CGSize) { 26 | self.offset = offset 27 | } 28 | 29 | public func effectValue(size: CGSize) -> ProjectionTransform { 30 | .init(.init(translationX: offset.width, y: offset.height)) 31 | } 32 | 33 | public var animatableData: CGSize.AnimatableData { 34 | get { 35 | offset.animatableData 36 | } 37 | set { 38 | offset.animatableData = newValue 39 | } 40 | } 41 | 42 | public func body(content: Content) -> some View { 43 | content 44 | } 45 | } 46 | 47 | public extension View { 48 | @inlinable 49 | func offset(_ offset: CGSize) -> some View { 50 | modifier(_OffsetEffect(offset: offset)) 51 | } 52 | 53 | @inlinable 54 | func offset(x: CGFloat = 0, y: CGFloat = 0) -> some View { 55 | offset(CGSize(width: x, height: y)) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Modifiers/Effects/OpacityEffect.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 1/20/21. 16 | // 17 | 18 | public struct _OpacityEffect: Animatable, ViewModifier, Equatable { 19 | public var opacity: Double 20 | 21 | public init(opacity: Double) { 22 | self.opacity = opacity 23 | } 24 | 25 | public func body(content: Content) -> some View { 26 | content 27 | } 28 | 29 | public var animatableData: Double { 30 | get { opacity } 31 | set { opacity = newValue } 32 | } 33 | } 34 | 35 | public extension View { 36 | func opacity(_ opacity: Double) -> some View { 37 | modifier(_OpacityEffect(opacity: opacity)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Modifiers/Effects/RotationEffect.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/3/20. 16 | // 17 | 18 | import Foundation 19 | 20 | public struct _RotationEffect: GeometryEffect { 21 | public var angle: Angle 22 | public var anchor: UnitPoint 23 | 24 | public init(angle: Angle, anchor: UnitPoint = .center) { 25 | self.angle = angle 26 | self.anchor = anchor 27 | } 28 | 29 | public func effectValue(size: CGSize) -> ProjectionTransform { 30 | .init(CGAffineTransform.identity.rotated(by: CGFloat(angle.radians))) 31 | } 32 | 33 | public func body(content: Content) -> some View { 34 | content 35 | } 36 | 37 | public var animatableData: AnimatablePair { 38 | get { 39 | .init(angle.animatableData, anchor.animatableData) 40 | } 41 | set { 42 | (angle.animatableData, anchor.animatableData) = newValue[] 43 | } 44 | } 45 | } 46 | 47 | public extension View { 48 | func rotationEffect(_ angle: Angle, anchor: UnitPoint = .center) -> some View { 49 | modifier(_RotationEffect(angle: angle, anchor: anchor)) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Modifiers/FrameLayout.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import Foundation 16 | 17 | public struct _FrameLayout: ViewModifier { 18 | public let width: CGFloat? 19 | public let height: CGFloat? 20 | public let alignment: Alignment 21 | 22 | init(width: CGFloat?, height: CGFloat?, alignment: Alignment) { 23 | self.width = width 24 | self.height = height 25 | self.alignment = alignment 26 | } 27 | 28 | public func body(content: Content) -> some View { 29 | content 30 | } 31 | } 32 | 33 | extension _FrameLayout: Animatable { 34 | public typealias AnimatableData = EmptyAnimatableData 35 | } 36 | 37 | public extension View { 38 | func frame( 39 | width: CGFloat? = nil, 40 | height: CGFloat? = nil, 41 | alignment: Alignment = .center 42 | ) -> some View { 43 | modifier(_FrameLayout(width: width, height: height, alignment: alignment)) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Modifiers/HoverActionModifier.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | /// Underscore is present in the name for SwiftUI compatibility. 15 | public struct _HoverActionModifier: ViewModifier { 16 | public var hover: ((Bool) -> ())? 17 | 18 | public typealias Body = Never 19 | } 20 | 21 | extension ModifiedContent 22 | where Content: View, Modifier == _HoverActionModifier 23 | { 24 | var hover: ((Bool) -> ())? { modifier.hover } 25 | } 26 | 27 | public extension View { 28 | func onHover(perform action: ((Bool) -> ())?) -> some View { 29 | modifier(_HoverActionModifier(hover: action)) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Modifiers/LifecycleModifier.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // FIXME: these should have standalone implementations 16 | public extension View { 17 | @_spi(TokamakCore) 18 | func _onMount(perform action: (() -> ())? = nil) -> some View { 19 | modifier(_AppearanceActionModifier(appear: action)) 20 | } 21 | 22 | @_spi(TokamakCore) 23 | func _onUpdate(perform action: (() -> ())? = nil) -> some View { 24 | modifier(_LifecycleActionModifier(update: action)) 25 | } 26 | 27 | @_spi(TokamakCore) 28 | func _onUnmount(perform action: (() -> ())? = nil) -> some View { 29 | modifier(_AppearanceActionModifier(disappear: action)) 30 | } 31 | } 32 | 33 | protocol LifecycleActionType { 34 | var update: (() -> ())? { get } 35 | } 36 | 37 | struct _LifecycleActionModifier: ViewModifier { 38 | var update: (() -> ())? 39 | 40 | typealias Body = Never 41 | } 42 | 43 | extension ModifiedContent: LifecycleActionType 44 | where Content: View, Modifier == _LifecycleActionModifier 45 | { 46 | var update: (() -> ())? { modifier.update } 47 | } 48 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Modifiers/RedactionReasons.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/31/20. 16 | // 17 | 18 | public struct RedactionReasons: OptionSet { 19 | public let rawValue: Int 20 | public init(rawValue: Int) { 21 | self.rawValue = rawValue 22 | } 23 | 24 | public static let placeholder: Self = .init(rawValue: 1 << 0) 25 | } 26 | 27 | public extension View { 28 | func redacted(reason: RedactionReasons) -> some View { 29 | environment(\.redactionReasons, reason) 30 | } 31 | 32 | func unredacted() -> some View { 33 | environment(\.redactionReasons, []) 34 | } 35 | } 36 | 37 | private struct RedactionReasonsKey: EnvironmentKey { 38 | static let defaultValue: RedactionReasons = [] 39 | } 40 | 41 | public extension EnvironmentValues { 42 | var redactionReasons: RedactionReasons { 43 | get { 44 | self[RedactionReasonsKey.self] 45 | } 46 | set { 47 | self[RedactionReasonsKey.self] = newValue 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Modifiers/TaskModifier.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | public extension View { 16 | func task( 17 | priority: TaskPriority = .userInitiated, 18 | _ action: @escaping @Sendable () async -> () 19 | ) -> some View { 20 | var task: Task<(), Never>? 21 | return onAppear { 22 | task = Task(priority: priority, operation: action) 23 | } 24 | .onDisappear { 25 | task?.cancel() 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Modifiers/ZIndexModifier.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | public struct _ZIndexModifier: ViewModifier { 16 | public let index: Double 17 | 18 | public func body(content: Content) -> some View { 19 | content 20 | } 21 | } 22 | 23 | public extension View { 24 | /// Controls the display order of overlapping views. 25 | /// - Parameters: 26 | /// - value: A relative front-to-back ordering for this view; the default is 0. 27 | func zIndex(_ value: Double = 0) -> some View { 28 | modifier(_ZIndexModifier(index: value)) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Sources/TokamakCore/MountedViews/MountedEmptyView.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2019-2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Max Desiatov on 05/01/2019. 16 | // 17 | 18 | final class MountedEmptyView: MountedElement { 19 | override func mount( 20 | before sibling: R.TargetType? = nil, 21 | on parent: MountedElement? = nil, 22 | in reconciler: StackReconciler, 23 | with transaction: Transaction 24 | ) { 25 | super.prepareForMount(with: transaction) 26 | super.mount(before: sibling, on: parent, in: reconciler, with: transaction) 27 | } 28 | 29 | override func unmount( 30 | in reconciler: StackReconciler, 31 | with transaction: Transaction, 32 | parentTask: UnmountTask? 33 | ) { 34 | super.unmount(in: reconciler, with: transaction, parentTask: parentTask) 35 | } 36 | 37 | override func update(in reconciler: StackReconciler, with transaction: Transaction?) {} 38 | } 39 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Reflection/Layouts/ExistentialContainter.swift: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // 3 | // Copyright (c) 2017-2021 Wesley Wickwire and Tokamak contributors 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | struct ExistentialContainer { 24 | let buffer: ExistentialContainerBuffer 25 | let type: Any.Type 26 | let witnessTable: Int 27 | } 28 | 29 | struct ExistentialContainerBuffer { 30 | let buffer1: Int 31 | let buffer2: Int 32 | let buffer3: Int 33 | } 34 | 35 | extension ExistentialContainerBuffer { 36 | static func size() -> Int { 37 | MemoryLayout.size 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Reflection/Layouts/ProtocolTypeContainer.swift: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // 3 | // Copyright (c) 2017-2021 Wesley Wickwire and Tokamak contributors 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | struct ProtocolTypeContainer { 24 | let type: Any.Type 25 | let witnessTable: Int 26 | } 27 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Reflection/Layouts/StructMetadataLayout.swift: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // 3 | // Copyright (c) 2017-2021 Wesley Wickwire and Tokamak contributors 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | struct StructMetadataLayout { 24 | let _kind: Int 25 | let typeDescriptor: UnsafePointer 26 | } 27 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Reflection/Layouts/TargetTypeGenericContextDescriptorHeader.swift: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // 3 | // Copyright (c) 2017-2021 Wesley Wickwire and Tokamak contributors 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | struct TargetTypeGenericContextDescriptorHeader { 24 | let instantiationCache: Int32 25 | let defaultInstantiationPattern: Int32 26 | let base: TargetGenericContextDescriptorHeader 27 | } 28 | 29 | struct TargetGenericContextDescriptorHeader { 30 | let numberOfParams: UInt16 31 | let numberOfRequirements: UInt16 32 | let numberOfKeyArguments: UInt16 33 | let numberOfExtraArguments: UInt16 34 | } 35 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Reflection/Metadata/Metadata.swift: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // 3 | // Copyright (c) 2017-2021 Wesley Wickwire and Tokamak contributors 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | func metadataPointer(type: Any.Type) -> UnsafePointer { 24 | unsafeBitCast(type, to: UnsafePointer.self) 25 | } 26 | 27 | func metadata(of type: Any.Type) -> StructMetadata { 28 | guard Kind(type: type) == .struct else { fatalError("Reflection is supported only for structs") } 29 | 30 | return StructMetadata(type: type) 31 | } 32 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Reflection/Metadata/MetadataState.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | enum MetadataState: UInt { 16 | case complete = 0x00 17 | case nonTransitiveComplete = 0x01 18 | case layoutComplete = 0x3F 19 | case abstract = 0xFF 20 | } 21 | 22 | private let isBlockingMask: UInt = 0x100 23 | 24 | struct MetadataRequest { 25 | private let bits: UInt 26 | 27 | init(desiredState: MetadataState, isBlocking: Bool) { 28 | if isBlocking { 29 | bits = desiredState.rawValue | isBlockingMask 30 | } else { 31 | bits = desiredState.rawValue & ~isBlockingMask 32 | } 33 | } 34 | } 35 | 36 | struct MetadataResponse { 37 | let metadata: UnsafePointer 38 | let state: MetadataState 39 | } 40 | 41 | @_silgen_name("swift_checkMetadataState") 42 | func _checkMetadataState(_ request: MetadataRequest, _ type: StructMetadata) -> MetadataResponse 43 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Reflection/Pointers/RelativeVectorPointer.swift: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // 3 | // Copyright (c) 2017-2021 Wesley Wickwire and Tokamak contributors 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | struct RelativeVectorPointer { 24 | let offset: Offset 25 | func vector(metadata: UnsafePointer, n: Int) -> UnsafeBufferPointer { 26 | metadata.advanced(by: numericCast(offset)) 27 | .raw.assumingMemoryBound(to: Pointee.self) 28 | .buffer(n: n) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Reflection/typeConstructorName.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /** Returns name of a given unapplied generic type. `Button` and 16 | `Button` types are different, but when reconciling the tree of mounted views 17 | they are treated the same, thus the `Button` part of the type (the type constructor) 18 | is returned. 19 | */ 20 | public func typeConstructorName(_ type: Any.Type) -> String { 21 | String(String(reflecting: type).prefix { $0 != "<" }) 22 | } 23 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Shapes/FixedRoundedRect.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/22/20. 16 | // 17 | 18 | import Foundation 19 | 20 | public struct FixedRoundedRect: Equatable { 21 | public let rect: CGRect 22 | public let cornerSize: CGSize? 23 | public let style: RoundedCornerStyle 24 | 25 | public init(rect: CGRect, cornerSize: CGSize, style: RoundedCornerStyle) { 26 | (self.rect, self.cornerSize, self.style) = (rect, cornerSize, style) 27 | } 28 | 29 | init(capsule rect: CGRect, style: RoundedCornerStyle) { 30 | (self.rect, cornerSize, self.style) = (rect, nil, style) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Shapes/Path/PathSizing.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/21/20. 16 | // 17 | 18 | public extension Path { 19 | enum _Sizing { 20 | case fixed 21 | case flexible 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Shapes/StrokedPath.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/22/20. 16 | // 17 | 18 | public struct StrokedPath: Equatable { 19 | public let path: Path 20 | public let style: StrokeStyle 21 | 22 | public init(path: Path, style: StrokeStyle) { 23 | self.path = path 24 | self.style = style 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Shapes/TrimmedPath.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/22/20. 16 | // 17 | 18 | import Foundation 19 | 20 | public struct TrimmedPath: Equatable { 21 | public let path: Path 22 | public let from: CGFloat 23 | public let to: CGFloat 24 | 25 | public init(path: Path, from: CGFloat, to: CGFloat) { 26 | self.path = path 27 | self.from = from 28 | self.to = to 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Sources/TokamakCore/State/StateObject.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import OpenCombineShim 16 | 17 | @propertyWrapper 18 | public struct StateObject: DynamicProperty { 19 | public var wrappedValue: ObjectType { (getter?() as? ObservedObject.Wrapper)?.root ?? initial() } 20 | 21 | let initial: () -> ObjectType 22 | var getter: (() -> Any)? 23 | 24 | public init(wrappedValue initial: @autoclosure @escaping () -> ObjectType) { 25 | self.initial = initial 26 | } 27 | 28 | public var projectedValue: ObservedObject.Wrapper { 29 | getter?() as? ObservedObject.Wrapper ?? ObservedObject.Wrapper(root: initial()) 30 | } 31 | } 32 | 33 | extension StateObject: ObservedProperty { 34 | var objectWillChange: AnyPublisher<(), Never> { 35 | wrappedValue.objectWillChange.map { _ in }.eraseToAnyPublisher() 36 | } 37 | } 38 | 39 | extension StateObject: ValueStorage { 40 | var anyInitialValue: Any { 41 | ObservedObject.Wrapper(root: initial()) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Sources/TokamakCore/State/TargetRef.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// A helper protocol for erasing generic parameters of the `_TargetRef` type. 16 | protocol TargetRefType { 17 | var target: Target? { get set } 18 | } 19 | 20 | /** Allows capturing target instance of aclosest descendant host view. The resulting instance 21 | is written to a given `binding`. The actual assignment to this binding is done within the 22 | `MountedCompositeView` implementation. */ 23 | public struct _TargetRef: View, TargetRefType { 24 | let binding: Binding 25 | 26 | let view: V 27 | 28 | var target: Target? { 29 | get { binding.wrappedValue as? Target } 30 | 31 | set { binding.wrappedValue = newValue as? T } 32 | } 33 | 34 | public var body: V { view } 35 | } 36 | 37 | public extension View { 38 | /** A modifier that returns a `_TargetRef` value, which captures a target instance of a 39 | closest descendant host view. 40 | The resulting instance is written to a given `binding`. */ 41 | @_spi(TokamakCore) 42 | func _targetRef(_ binding: Binding) -> _TargetRef { 43 | .init(binding: binding, view: self) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Stubs/UIColor.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | public struct UIColor { 16 | let color: Color 17 | 18 | public static let clear: Self = .init(color: .clear) 19 | public static let black: Self = .init(color: .black) 20 | public static let white: Self = .init(color: .white) 21 | public static let gray: Self = .init(color: .gray) 22 | public static let red: Self = .init(color: .red) 23 | public static let green: Self = .init(color: .green) 24 | public static let blue: Self = .init(color: .blue) 25 | public static let orange: Self = .init(color: .orange) 26 | public static let yellow: Self = .init(color: .yellow) 27 | public static let pink: Self = .init(color: .pink) 28 | public static let purple: Self = .init(color: .purple) 29 | } 30 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Styles/ButtonStyle.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Gene Z. Ragan on 07/22/2020. 16 | 17 | public protocol ButtonStyle { 18 | associatedtype Body: View 19 | @ViewBuilder 20 | func makeBody(configuration: Self.Configuration) -> Self.Body 21 | typealias Configuration = ButtonStyleConfiguration 22 | } 23 | 24 | public struct ButtonStyleConfiguration { 25 | public struct Label: View { 26 | public let body: AnyView 27 | } 28 | 29 | public let role: ButtonRole? 30 | public let label: ButtonStyleConfiguration.Label 31 | public let isPressed: Bool 32 | } 33 | 34 | struct AnyButtonStyle: ButtonStyle { 35 | let bodyClosure: (ButtonStyleConfiguration) -> AnyView 36 | let type: Any.Type 37 | 38 | init(_ style: S) { 39 | type = S.self 40 | bodyClosure = { 41 | AnyView(style.makeBody(configuration: $0)) 42 | } 43 | } 44 | 45 | func makeBody(configuration: Configuration) -> some View { 46 | bodyClosure(configuration) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Styles/OutlineGroupStyle.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/4/20. 16 | // 17 | 18 | public protocol _OutlineGroupStyle {} 19 | 20 | public struct _DefaultOutlineGroupStyle: _OutlineGroupStyle { 21 | public init() {} 22 | } 23 | 24 | public struct _ListOutlineGroupStyle: _OutlineGroupStyle { 25 | public init() {} 26 | } 27 | 28 | enum _OutlineGroupStyleKey: EnvironmentKey { 29 | static let defaultValue: _OutlineGroupStyle = _DefaultOutlineGroupStyle() 30 | } 31 | 32 | extension EnvironmentValues { 33 | var _outlineGroupStyle: _OutlineGroupStyle { 34 | get { 35 | self[_OutlineGroupStyleKey.self] 36 | } 37 | set { 38 | self[_OutlineGroupStyleKey.self] = newValue 39 | } 40 | } 41 | } 42 | 43 | extension View { 44 | func outlineGroupStyle(_ style: _OutlineGroupStyle) -> some View { 45 | environment(\._outlineGroupStyle, style) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Styles/PickerStyle.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | public protocol PickerStyle {} 16 | 17 | public struct PopUpButtonPickerStyle: PickerStyle {} 18 | 19 | public struct RadioGroupPickerStyle: PickerStyle {} 20 | 21 | public struct SegmentedPickerStyle: PickerStyle {} 22 | 23 | public struct WheelPickerStyle: PickerStyle {} 24 | 25 | public struct DefaultPickerStyle: PickerStyle {} 26 | 27 | enum PickerStyleKey: EnvironmentKey { 28 | static var defaultValue: PickerStyle = DefaultPickerStyle() 29 | } 30 | 31 | extension EnvironmentValues { 32 | var pickerStyle: PickerStyle { 33 | get { 34 | self[PickerStyleKey.self] 35 | } 36 | set { 37 | self[PickerStyleKey.self] = newValue 38 | } 39 | } 40 | } 41 | 42 | public extension View { 43 | func pickerStyle(_ style: PickerStyle) -> some View { 44 | environment(\.pickerStyle, style) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Target.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2019-2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Max Desiatov on 10/02/2019. 16 | // 17 | 18 | public protocol Target: AnyObject { 19 | var view: AnyView { get set } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Tokens/AnyTokenBox.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 10/24/2020. 16 | // 17 | 18 | /// Allows "late-binding tokens" to be resolved in an environment by a `Renderer` (or `TokamakCore`) 19 | public protocol AnyTokenBox: AnyObject { 20 | associatedtype ResolvedValue 21 | func resolve(in environment: EnvironmentValues) -> ResolvedValue 22 | } 23 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Tokens/Axis.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 06/29/2020. 16 | // 17 | 18 | public enum Axis: Int8, CaseIterable { 19 | case horizontal 20 | case vertical 21 | 22 | public struct Set: OptionSet { 23 | public let rawValue: Int8 24 | public init(rawValue: Int8) { 25 | self.rawValue = rawValue 26 | } 27 | 28 | public static let horizontal: Axis.Set = .init(rawValue: 1 << 0) 29 | public static let vertical: Axis.Set = .init(rawValue: 1 << 1) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Tokens/Color/ColorKeys.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/12/21. 16 | // 17 | 18 | import Foundation 19 | 20 | struct AccentColorKey: EnvironmentKey { 21 | static let defaultValue: Color? = nil 22 | } 23 | 24 | public extension EnvironmentValues { 25 | var accentColor: Color? { 26 | get { 27 | self[AccentColorKey.self] 28 | } 29 | set { 30 | self[AccentColorKey.self] = newValue 31 | } 32 | } 33 | } 34 | 35 | public extension View { 36 | func accentColor(_ accentColor: Color?) -> some View { 37 | environment(\.accentColor, accentColor) 38 | } 39 | } 40 | 41 | struct ForegroundColorKey: EnvironmentKey { 42 | static let defaultValue: Color? = nil 43 | } 44 | 45 | public extension EnvironmentValues { 46 | var foregroundColor: Color? { 47 | get { 48 | self[ForegroundColorKey.self] 49 | } 50 | set { 51 | self[ForegroundColorKey.self] = newValue 52 | } 53 | } 54 | } 55 | 56 | public extension View { 57 | func foregroundColor(_ color: Color?) -> some View { 58 | environment(\.foregroundColor, color) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Tokens/ColorScheme.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | public enum ColorScheme: CaseIterable, Equatable { 16 | case dark 17 | case light 18 | } 19 | 20 | public struct _ColorSchemeKey: EnvironmentKey { 21 | public static var defaultValue: ColorScheme { 22 | fatalError("\(self) must have a renderer-provided default value") 23 | } 24 | } 25 | 26 | public extension EnvironmentValues { 27 | var colorScheme: ColorScheme { 28 | get { self[_ColorSchemeKey.self] } 29 | set { self[_ColorSchemeKey.self] = newValue } 30 | } 31 | } 32 | 33 | public extension View { 34 | func colorScheme(_ colorScheme: ColorScheme) -> some View { 35 | environment(\.colorScheme, colorScheme) 36 | } 37 | } 38 | 39 | public struct PreferredColorSchemeKey: PreferenceKey { 40 | public typealias Value = ColorScheme? 41 | public static func reduce(value: inout Value, nextValue: () -> Value) { 42 | value = nextValue() 43 | } 44 | } 45 | 46 | public extension View { 47 | func preferredColorScheme(_ colorScheme: ColorScheme?) -> some View { 48 | preference(key: PreferredColorSchemeKey.self, value: colorScheme) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Tokens/Controls/ButtonRole.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/12/21. 16 | // 17 | 18 | public struct ButtonRole: Equatable { 19 | public static let destructive = ButtonRole(rawValue: 0) 20 | public static let cancel = ButtonRole(rawValue: 1) 21 | 22 | private let rawValue: Int 23 | private init(rawValue: Int) { 24 | self.rawValue = rawValue 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Tokens/Controls/ControlSize.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/12/21. 16 | // 17 | 18 | public enum ControlSize: CaseIterable, Hashable { 19 | case mini 20 | case small 21 | case regular 22 | case large 23 | } 24 | 25 | extension EnvironmentValues { 26 | private enum ControlSizeKey: EnvironmentKey { 27 | static var defaultValue: ControlSize = .regular 28 | } 29 | 30 | public var controlSize: ControlSize { 31 | get { 32 | self[ControlSizeKey.self] 33 | } 34 | set { 35 | self[ControlSizeKey.self] = newValue 36 | } 37 | } 38 | } 39 | 40 | public extension View { 41 | @inlinable 42 | func controlSize( 43 | _ controlSize: ControlSize 44 | ) -> some View { 45 | environment(\.controlSize, controlSize) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Tokens/Controls/Prominence.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/12/21. 16 | // 17 | 18 | public enum Prominence: Hashable { 19 | case standard 20 | case increased 21 | } 22 | 23 | extension EnvironmentValues { 24 | private enum HeaderProminenceKey: EnvironmentKey { 25 | static var defaultValue: Prominence = .standard 26 | } 27 | 28 | public var headerProminence: Prominence { 29 | get { 30 | self[HeaderProminenceKey.self] 31 | } 32 | set { 33 | self[HeaderProminenceKey.self] = newValue 34 | } 35 | } 36 | } 37 | 38 | public extension View { 39 | func headerProminence(_ prominence: Prominence) -> some View { 40 | environment(\.headerProminence, prominence) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Tokens/Font/FontModifiers.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import Foundation 16 | 17 | public extension Font { 18 | func italic() -> Self { 19 | .init(_ModifiedFontBox(previously: provider) { 20 | $0._italic = true 21 | }) 22 | } 23 | 24 | func smallCaps() -> Self { 25 | .init(_ModifiedFontBox(previously: provider) { 26 | $0._smallCaps = true 27 | }) 28 | } 29 | 30 | func lowercaseSmallCaps() -> Self { 31 | smallCaps() 32 | } 33 | 34 | func uppercaseSmallCaps() -> Self { 35 | smallCaps() 36 | } 37 | 38 | func monospacedDigit() -> Self { 39 | .init(_ModifiedFontBox(previously: provider) { 40 | $0._monospaceDigit = true 41 | }) 42 | } 43 | 44 | func weight(_ weight: Weight) -> Self { 45 | .init(_ModifiedFontBox(previously: provider) { 46 | $0._weight = weight 47 | }) 48 | } 49 | 50 | func bold() -> Self { 51 | .init(_ModifiedFontBox(previously: provider) { 52 | $0._bold = true 53 | }) 54 | } 55 | 56 | func leading(_ leading: Leading) -> Self { 57 | .init(_ModifiedFontBox(previously: provider) { 58 | $0._leading = leading 59 | }) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Tokens/GridItem.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2019-2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/13/20. 16 | // 17 | 18 | import Foundation 19 | 20 | public struct GridItem { 21 | public enum Size { 22 | case fixed(CGFloat) 23 | case flexible(minimum: CGFloat = 10, maximum: CGFloat = .infinity) 24 | case adaptive(minimum: CGFloat, maximum: CGFloat = .infinity) 25 | } 26 | 27 | public var size: GridItem.Size 28 | public var spacing: CGFloat 29 | public var alignment: Alignment 30 | 31 | public init( 32 | _ size: GridItem.Size = .flexible(), 33 | spacing: CGFloat? = nil, 34 | alignment: Alignment? = nil 35 | ) { 36 | self.size = size 37 | self.spacing = spacing ?? 4 38 | self.alignment = alignment ?? .center 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Tokens/LayoutDirection.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 6/20/22. 16 | // 17 | 18 | public enum LayoutDirection: Hashable, CaseIterable { 19 | case leftToRight 20 | case rightToLeft 21 | } 22 | 23 | extension EnvironmentValues { 24 | private enum LayoutDirectionKey: EnvironmentKey { 25 | static var defaultValue: LayoutDirection = .leftToRight 26 | } 27 | 28 | public var layoutDirection: LayoutDirection { 29 | get { self[LayoutDirectionKey.self] } 30 | set { self[LayoutDirectionKey.self] = newValue } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Tokens/LineBreakMode.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2019-2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Max Desiatov on 14/02/2019. 16 | // 17 | 18 | public enum LineBreakMode { 19 | case wordWrap 20 | case charWrap 21 | case clip 22 | case truncateHead 23 | case truncateTail 24 | case truncateMiddle 25 | } 26 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Tokens/TextAlignment.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Max Desiatov on 30/12/2018. 16 | // 17 | 18 | public enum TextAlignment: Hashable, CaseIterable { 19 | case leading, 20 | center, 21 | trailing 22 | } 23 | 24 | extension EnvironmentValues { 25 | private struct _MultilineTextAlignmentKey: EnvironmentKey { 26 | static var defaultValue: TextAlignment = .leading 27 | } 28 | 29 | public var multilineTextAlignment: TextAlignment { 30 | get { 31 | self[_MultilineTextAlignmentKey.self] 32 | } 33 | set { 34 | self[_MultilineTextAlignmentKey.self] = newValue 35 | } 36 | } 37 | } 38 | 39 | public extension View { 40 | @inlinable 41 | func multilineTextAlignment(_ alignment: TextAlignment) -> some View { 42 | environment(\.multilineTextAlignment, alignment) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Sources/TokamakCore/ViewTraits/TagValueTraitKey.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 9/23/21. 16 | // 17 | 18 | import Foundation 19 | 20 | public extension View { 21 | @inlinable 22 | func tag(_ tag: V) -> some View where V: Hashable { 23 | _trait(TagValueTraitKey.self, .tagged(tag)) 24 | } 25 | 26 | @inlinable 27 | func _untagged() -> some View { 28 | _trait(IsAuxiliaryContentTraitKey.self, true) 29 | } 30 | } 31 | 32 | @usableFromInline 33 | struct TagValueTraitKey: _ViewTraitKey where V: Hashable { 34 | @usableFromInline 35 | enum Value { 36 | case untagged 37 | case tagged(V) 38 | } 39 | 40 | @inlinable 41 | static var defaultValue: Value { .untagged } 42 | } 43 | 44 | @usableFromInline 45 | struct IsAuxiliaryContentTraitKey: _ViewTraitKey { 46 | @inlinable 47 | static var defaultValue: Bool { false } 48 | @usableFromInline typealias Value = Bool 49 | } 50 | -------------------------------------------------------------------------------- /Sources/TokamakCore/ViewTraits/_ViewTraitStore.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/10/21. 16 | // 17 | 18 | public struct _ViewTraitStore { 19 | public var values = [ObjectIdentifier: Any]() 20 | 21 | public init(values: [ObjectIdentifier: Any] = [:]) { 22 | self.values = values 23 | } 24 | 25 | public func value(forKey key: Key.Type = Key.self) -> Key.Value 26 | where Key: _ViewTraitKey 27 | { 28 | values[ObjectIdentifier(key)] as? Key.Value ?? Key.defaultValue 29 | } 30 | 31 | public mutating func insert(_ value: Key.Value, forKey key: Key.Type = Key.self) 32 | where Key: _ViewTraitKey 33 | { 34 | values[ObjectIdentifier(key)] = value 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Views/Canvas/GraphicsContext/BlendMode.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2021 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 9/18/21. 16 | // 17 | 18 | import Foundation 19 | 20 | public extension GraphicsContext { 21 | enum BlendMode: Int32, Equatable { 22 | case normal 23 | case multiply 24 | case screen 25 | case overlay 26 | case darken 27 | case lighten 28 | case colorDodge 29 | case colorBurn 30 | case softLight 31 | case hardLight 32 | case difference 33 | case exclusion 34 | case hue 35 | case saturation 36 | case color 37 | case luminosity 38 | case clear 39 | case copy 40 | case sourceIn 41 | case sourceOut 42 | case sourceAtop 43 | case destinationOver 44 | case destinationIn 45 | case destinationOut 46 | case destinationAtop 47 | case xor 48 | case plusDarker 49 | case plusLighter 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Views/Containers/Group.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | public struct Group { 16 | let content: Content 17 | public init(@ViewBuilder content: () -> Content) { 18 | self.content = content() 19 | } 20 | } 21 | 22 | extension Group: _PrimitiveView, View where Content: View { 23 | public func _visitChildren(_ visitor: V) where V: ViewVisitor { 24 | visitor.visit(content) 25 | } 26 | } 27 | 28 | extension Group: ParentView where Content: View { 29 | @_spi(TokamakCore) 30 | public var children: [AnyView] { (content as? ParentView)?.children ?? [AnyView(content)] } 31 | } 32 | 33 | extension Group: GroupView where Content: View {} 34 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Views/Controls/ControlGroup.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 7/12/21. 16 | // 17 | 18 | public struct ControlGroup: View where Content: View { 19 | let content: Content 20 | 21 | @Environment(\.controlGroupStyle) 22 | var style 23 | 24 | public init(@ViewBuilder content: () -> Content) { 25 | self.content = content() 26 | } 27 | 28 | public var body: some View { 29 | style.makeBody(configuration: .init(content: .init(body: AnyView(content)))) 30 | } 31 | } 32 | 33 | public extension ControlGroup where Content == ControlGroupStyleConfiguration.Content { 34 | init(_ configuration: ControlGroupStyleConfiguration) { 35 | content = configuration.content 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Sources/TokamakCore/Views/Controls/Link.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2020 Tokamak contributors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Created by Carson Katri on 9/9/20. 16 | // 17 | 18 | import struct Foundation.URL 19 | 20 | public struct Link