Giter Club home page Giter Club logo

tokamak's People

Contributors

agg23 avatar ahti avatar andrewbarba avatar benedictst avatar carson-katri avatar ezraberch avatar filip-sakel avatar foscomputerservices avatar gregcotten avatar hodovani avatar j-f1 avatar joannis avatar kateinoigakukun avatar literalpie avatar mattpolzin avatar maxdesiatov avatar mbrandonw avatar mortenbekditlevsen avatar outcue avatar regexident avatar snowy1803 avatar twof avatar yonihemi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tokamak's Issues

Add Tokamak project linter

Create command-line util to lint projects that use Tokamak.

Todo:

  • Add Linter.md for linter documentation
  • Verify that SwiftSyntax 0.5 is able to parse the Example project
  • Add lint error Props is not Equatable
  • Add unit-tests to lint functions
  • Add lintFile -> [LintError]
  • Make lintFolder use lintFile
  • Make error output more user readable
  • Fix TokamakLint types access scope: remove public from TokenVisitor, Rule, Reporter, PropsIsEquatableRule
  • Fix TokenVisitor handling of Range, start and end are always equal to each other:
    node.range.startRow = row
    node.range.startColumn = column
    node.range.endRow = row
    node.range.endColumn = column
  • Fix processToken, kind variable is unused:
  private func processToken(_ token: TokenSyntax) {
    var kind = "\(token.tokenKind)"
    if let index = kind.firstIndex(of: "(") {
      kind = String(kind.prefix(upTo: index))
    }
    if kind.hasSuffix("Keyword") {
      kind = "keyword"
    }

    column += token.text.count
  }
  • Fix walkAndGrab, make it private, remove if node.children.count > 0 condition
  • Investigate if SwiftCLI package can be used in TokamakCLI module
  • Rename TokamakCLI to tokamak in Package.swift for Swift 5.0 and 4.2
.executable(name: "tokamak", targets: ["TokamakCLI"])
  • Lint "Only one render in component"
  • One render function rule should check all components, not only hooked components.
  • Lint "Rules of Hooks"
  • Lint "Components can only be declared as structs"
  • Integrate swift-log package
  • Remove direct usage of print, implement configurable output for stdout or files with a custom LogHandler implementation for swift-log

Long-term:

  • Lint "Arguments order"
  • Lint "Unused argument: hooks, children"
  • Lint "Declare non-static properties and functions in component"
  • Lint Rules of Hooks within extensions for all Hooks, not just state

Implement `hooks.effect`

The only standard hook currently available is state, which isn't enough to schedule and finalise side effects from components. Gluon should support hooks.effect corresponding to useEffect in React.

ScrollView host component

Implementation of this component in TokamakUIKit would need special care to make it work with auto layout. The approach I would try is to copy width constraint of a scroll view and its parent to the root subview. This would automatically do the same what people need to do manually when working with programmatic UIScrollView and auto layout. We should also provide a flag in props to turn off these additional helper constraints if a user would like to avoid that. We also need to support both vertical and horizontal scrolling and inference of those additional constraints for both cases.

Implement a test renderer

This renderer should use a new simple TestView class as a target, which stores references to subviews, also directly stores given props and is able to trigger events with a function like TestView.trigger(event: Event).

It would make sense to keep this renderer and TestView class in a separate module/subspec/target. This would make the core module smaller and allow importing the test renderer only in test targets. I imagine GluonTest is an ok name for the module.

Stepper missing props

Properties that should be added to Stepper.Props and be rendered in the UIKit renderer: autorepeat, wraps, minimumValue, maximumValue, stepValue, all are documented in UIStepper docs.

ZStack?

What about ZStack? Have you plans to implements it?

Implement basic AppKit renderer

AppKit renderer would be a great proof of concept for cross-platform Tokamak and also would make reconciler testing much easier without requiring iOS simulator overhead.

Add style support

Many views support some kind of .fooStyle() method that takes one of a variety of XFooStyle() objects. I took a quick look and it seems like this kind of thing has not been implemented for any of the views. Ideally having one implementation of this would provide a base from which to implement similar methods for other views.

Rename `EventHandlerProps` to `ControlProps`

Looks like there is an important property available on subclasses of UIControl that we need to make available on related control-like host components, namely isEnabled. It would make sense to add it on EventHandlerProps since that one is available for props of all control-like components. But then it would also make sense to rename it to ControlProps as the addition makes its purpose more general.

Custom CSS styles

I've been thinking about CSS-specific styles that one might want to add to further customize generated styles, somewhat similar in principle to the HTML view that allows injecting arbitrary HTML. I'm still not sure if there should be a modifier that allows adding arbitrary HTML attributes to a rendered HTML node, or specialized modifiers like cssStyle() for specifying styles and cssClassName() for specifying a class name.

I also had in mind something like protocol CustomCSSAttributes which would allow any user to conform their views (or existing views provided by Tokamak) to this protocol, providing their custom global attributes. The use case for this are popular styling libraries (and obviously proprietary design systems that people may use) that have existing CSS code. For example, Semantic UI requires buttons to have ui button classes on them:

<button class="ui button">
  Button
</button>

Tokamak could allow achieving that for all buttons globally like this:

extension Button: CustomCSSAttributes {
  var customAttributes: [String: String] { ["class": "ui button"] }
}

The protocol approach and the modifiers approach would not be mutually exclusive, the reasoning is that modifiers would apply tweaks only locally, while protocol conformance would be visible globally. There's some bikeshedding needed here, but overall what are your thoughts?

Don't know if creating a separate issue for this proposal would be more suitable.

Implement SubscriptionView compatible with OpenCombine

This is required for view subscriptions such as onReceive:

extension View {
  public func onReceive<P>(
    _ publisher: P, 
    perform action: @escaping (P.Output) -> ()
  ) -> some View where P : OpenCombine.Publisher, P.Failure == Never {
    SubscriptionView(content: self, publisher: publisher, action: action)
  }
}

0.2.0 release

Just kickstarting a possible discussion here of what you'd like to see in the first release with the SwiftUI API subset supporting WebAssembly. I am personally a fan of "release early and often" idea and wouldn't mind tagging a release with whatever API coverage we already have. It's more about letting people know that this thing exists and it can do basic stuff.

These seem to be release blockers, let me know if you think anything's missing:

  • Basic documentation
    The existing progress.md should be enough for this first release, I guess? We can integrate TokamakDocs somehow in later versions, unless @carson-katri has any objections.
  • Cleaning up the demo example
    I think even without NavigationView and friends, I'll just add some padding and headers to describe what's what
  • Updated CHANGELOG.md
  • Tagging and sharing on Twitter

What are your thoughts @carson-katri @j-f1?

Verify `.next` target for all layout constraints

Not sure if next sibling is correctly passed from the renderer/reconciler to auto layout extensions in TokamakUIKit, this needs to be verified and fixed if broken. Good to have some demo screens in the Example project for verification.

View has - by default - a Body of type Never.

This introduces bugs and almost defeats the purpose of compile-time errors. To prevent the program compiling successfully without producing an error for a type like Foo:

struct Foo: View {
    
}

There are two options - that I can think of:

  1. Add another _Never conditional conformances - to a dummy type like _Never that will require disambiguating when omitting the body:

    enum _Never: View {
        var body: Never { fatalError() }
    }
    
    extension View where Body == _Never {
        var body: _Never {
            fatalError("Can't access body of Never View.")
        }
    }

    That is a hack though and the error ("Type 'H' does not conform to protocol 'Block'") doesn't provide a fix possibly leaving a novice developer confused.

  2. Remove the extension that provides an automatic conformance when Body is of type Never and move that behaviour to the ViewDeferredToRenderer protocol - or to an underlying view protocol such as _StuctureView, _View, _FatalView:

    protocol _StuctureView: View where Body == Never {}
    
    extension _StuctureView {
         var body: Never {
            fatalError("Can't access body of Structure View.")
        }
    }

    That IMO is the best option, as it avoids automatic type-inference altogether and provides a useful error message - that offers a fix.

Image host component

Most of Image.Props should mirror properties of UIImage, but the actual target would be UIImageView. Properties that are read-only on UIImage would need to create a new instance when changed, one prominent example being renderingMode.

I imagine we could start with Image.Props looking like this:

public struct Props {
  public enum RenderingMode {
    // ...
  }
  public enum Source {
    case name(String)
    case data(Data)
  }
  // when changed initializes new image with `UIImage(named:)` or `UIImage(data:)`
  public let source: Source
  // when changed creates new image with `withRenderingMode`
  public let renderingMode: RenderingMode 
  // when changed initializes new image with given scale
  public let scale: Double 
  // mirrors `flipsForRightToLeftLayoutDirection`
  public let flipsForRTL: Bool
}

Add `hooks.context`

This would allow Tokamak to create contexts for passing values conforming to Equatable through deep component trees without needlessly updating all levels of the tree

Implement UserInterfaceSizeClass with media queries support

Shame that there are only two size classes in SwiftUI: compact and regular. Also not sure what the default breakpoint for these should be. Even if we decide on one, I think that users should be able redefine it, or maybe even add their own size classes with new breakpoints.

Set target refs in UIKitRenderer

Currently refs passed to nodes won't be initialized during rendering with UIKitRenderer. It's important to get targets stored in refs to enable usage of those targets in effects.

Implement all main layout constraints

Currently the only available auto layout constraint available is Edges.equal, we need to make all basic auto layout constraints available, working and tested with this new DSL, e.g. Width.equal, Height.equal, Leading.equal etc

Some primitive Views cannot access @Environment

For instance, the Text element inside of EnvironmentDemo will never get any Environment injected. You can see this by putting the following print after // Inject @Environment values in StackReconciler.swift:

print(compositeView.view.type)

The Text element is never logged.

I'm not sure how to fix this. Do you have any ideas @MaxDesiatov ?

Add scroll properties to `ListView`/`CollectionView` props

As both of these components are rendered to UIScrollView and NSScrollView subclasses on iOS and macOS respectively, it would make sense to create a structure for props of all of these components to be shared and handled uniformly in the renderers code.

Getting value of type 'String' has no member 'components'

Try to build with Swiftwasm in wasm-DEVELOPMENT-SNAPSHOT-2020-04-07-a.
Getting following error

.build/checkouts/Runtime/Sources/Runtime/Metadata/TupleMetadata.swift:33:68: error: value of type 'String' has no member 'components' var labels = String(cString: pointer.pointee.labelsString).components(separatedBy: " ")

Add ListView host component

I find it confusing that UITableView is named that way in UIKit, while it has no support for columns whatsoever, compare it to NSTableView in AppKit. I think it would be more fitting to name the corresponding host component in Gluon as ListView.

UICollectionView's component could keep that name, it's doing fine πŸ˜„

Expose priorities on auto layout constraints

Currently there's no way to customise priority of a constraint. This probably should be exposed as an optional argument to equal function, but different approaches could be explored.

Important caveat:

Priorities may not change from nonrequired to required, or from required to nonrequired. An exception will be thrown if a priority of required in macOS or UILayoutPriorityRequired in iOS is changed to a lower priority, or if a lower priority is changed to a required priority after the constraints is added to a view. Changing from one optional priority to another optional priority is allowed even after the constraint is installed on a view.

Add DatePicker component

This component should be rendered to UIDatePicker with UIKitRenderer. This is a subclass of UIControl, so it could reuse a lot of infrastructure from UIControlComponent protocol in GluonUIKit module.

Add `hooks.reducer`

This would allow Gluon to manage complex state without requiring additional libraries like Redux

Server-side rendering and static websites support

It would be great if Tokamak supported rendering to a static HTML string without requiring DOM access, similar to what React already can do (and numerous other JS libraries probably too). There are many use cases for this, the most beneficial would be to pre-render your Tokamak app into a static HTML, serve that by default, and then hydrate that after the WebAssembly binary is loaded. This is beneficial for performance and usability as a user wouldn't need to wait for the WebAssembly module to be loaded and compiled before they can see anything useful on a web page.

Additionally, many static websites (such as blogs) wouldn't need components that utilize @State, those wouldn't need a WebAssembly binary at all, pre-rendered HTML would be enough. Of course, you could write your HTML by hand, but the abundance of React-based static websites generators (such as Gatsby) proves that it is nice to be able to reuse your existing code. Additionally, views described with Tokamak (even without any @State and other stateful property wrappers) clearly compose better than plain HTML.

I think this could look like a separate TokamakHTML module that doesn't depend on JavaScriptKit and could be compiled for any platform, not just WebAssembly. Then you'd supply any view to this HTML renderer and get an HTML string as an output. I hope that TokamakHTML could then be reused in the TokamakDOM module.

Production readiness?

Hello,
I would like to ask you about confidence of using Tokamak in production applications for e-commerce.

TextField host component

In TokamakUIKit this would be rendered to UITextField. This is a subclass of UIControl, so for the first version TextField should conform to the UIControlComponent protocol. Essential props that would be great to have in the initial version are:

  • textColor (that uses Tokamak type Color)
  • textAlignment (there's probably already an existing enum TextAlignment from Label that can be reused here?)
  • placeholder
  • clearsOnBeginEditing
  • clearsOnInsertion
  • borderStyle
  • clearButtonMode
  • autocapitalizationType
  • autocorrectionType
  • spellCheckingType
  • keyboardType
  • keyboardAppearance
  • returnKeyType
  • secureTextEntry

all adding new enums to the Tokamak module where required.

Logo for the project

If you know of a suitable logo, or know anyone who could produce one, or can propose one yourself, please do. I've used stock images for the previous release with the React API, you can see them on the Twitter profile. If you're not familar with tokamaks, please use the Wikipedia page for inspirations. The whole idea was (and still is) to make a pun on React's atomic logo πŸ˜„

NavigationView/NavigationLink

Having this view ready would clean up the demo page and make it easier to add or fix just one view. It’s probably good to start with the 2-column iPad style and maybe expand later on to an iPhone style on narrower viewports.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.