Coder Social home page Coder Social logo

lilactown / helix Goto Github PK

View Code? Open in Web Editor NEW
614.0 15.0 51.0 3.39 MB

A simple, easy to use library for React development in ClojureScript.

License: Eclipse Public License 2.0

Clojure 98.22% HTML 1.05% CSS 0.02% JavaScript 0.69% Shell 0.03%
clojurescript hooks react interop cljs

helix's Introduction

Helix

ClojureScript optimized for modern React development.

(ns my-app.core
  (:require [helix.core :refer [defnc $]]
            [helix.hooks :as hooks]
            [helix.dom :as d]
            ["react-dom/client" :as rdom]))

;; define components using the `defnc` macro
(defnc greeting
  "A component which greets a user."
  [{:keys [name]}]
  ;; use helix.dom to create DOM elements
  (d/div "Hello, " (d/strong name) "!"))

(defnc app []
  (let [[state set-state] (hooks/use-state {:name "Helix User"})]
    (d/div
     (d/h1 "Welcome!")
      ;; create elements out of components
      ($ greeting {:name (:name state)})
      (d/input {:value (:name state)
                :on-change #(set-state assoc :name (.. % -target -value))}))))

;; start your app with your favorite React renderer
(defonce root (rdom/createRoot (js/document.getElementById "app")))
(.render root ($ app))

Installation

Clojars Project

Install the latest version from clojars in your project.

Install JS dependencies:

npm init # initialize NPM project if necessary
npm i react react-refresh # install react, and react-refresh for hot reloading support (see docs)
npm i react-dom # install renderer. alternatives could be react-native, react-three-fiber, etc.

shadow-cljs and react-native

See React Native.

lein-cljsbuild / figwheel-main / raw CLJS

Use CLJSJS or package react yourself using webpack, ensuring it is provided as the name "react".

Documentation

View formatted docs at cljdoc badge

Other resources:

Related projects and repos

Companies using it

amperity_logo

License

Copyright ยฉ 2023 Will Acton

Distributed under the EPL 2.0

helix's People

Contributors

aiba avatar alidcast avatar danieroux avatar darwin avatar dpassen avatar ferdinand-beyer avatar holyjak avatar jimmyhmiller avatar lilactown avatar lucywang000 avatar rafaeldelboni avatar riotrah avatar rome-user avatar saguywalker avatar severeoverfl0w avatar shaunlebron avatar spewolf avatar stanislas avatar tomconnors avatar tomekw avatar wilkerlucio avatar zackteo 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

helix's Issues

Not possible to create controlled component with nil value

After this commit, when the :value prop is nil, helix would replace it with undefined. But in react components like input etc. with :value nil is treated as a controlled component, while :value undefined is treated as uncontrolled.

This is a problem e.g. when using the Autocomplete component of material-ui, the :value prop must be either nil or one of the values in the options list. However when I try to give it a nil, helix changes it to undefined, which effectively make this component a uncontrolled one. Later when the user chooses a value from the auto complete list, the component would become a controlled element and cause errors.

screenshot

Use Closure syntax for helix/impl/class.js

Currently, we maintain a separate branch for using helix with vanilla CLJS (e.g. figwheel, :bundle, etc.): fix-figwheel

This is due to src/helix/impl/class.js originally being written using ES Module syntax (as that worked well with shadow-cljs), and when I tried to rewrite it using Google Closure syntax it didn't immediately work with shadow-cljs.

Ideally we would align the two branches so that it's less confusing for users.

fast-refresh with react-native

I'm trying to get started with helix and react-native, and am especially interested in getting react fast refresh working.

I couldn't get fast-refresh to work with helix 0.0.8. Perhaps someone could point me in the right direction toward getting fast refresh to work?

I tried to boil things down to a minimal example repo here: https://github.com/aiba/helix-react-native

using clojure.spec with components

clojure.spec would be very useful as a way to document props and assert at runtime that they are correct.

There are two fundamental issues that I would want to address by providing direct support for clojure.spec:

  • Speccing props means that you need to spec a JS object, so we need to provide some tools for creating specs for JS objects easily
  • The DX should be good: specs should only be turned on by default at development time; should be easily hot reloadable; and should removed at release time unless specifically opted in to maintain

A rough sketches of a potential API:

(ns app.feature
  (:require
    [clojure.spec.alpha :as s]
    [helix.core :refer (defnc $)]
    [helix.dom :as d]
    [helix.spec :as hs]))

;; can use regular specs
(s/def ::name string?)

;; `hs/def` is just like `s/def` but will be removed if goog/DEBUG is false
(hs/def ::on-name-change function?)

;; like `s/fdef` but for components
(hs/cdef greeting
  :props (s/keys :req-un [::name ::on-name-change]))

;; specs are separate from components, can be added on later or removed w/o
;; any change to component.
;; Later maybe add specific syntax for speccing inline?
(defnc greeting
  [{:keys [name on-name-change]}]
  (d/div
    (d/div โ€œHello, โ€œ name โ€œ!โ€)
    (d/input {:value name :on-change on-name-change})))

Pass class and id via shorthand in $

I propose that $ support the following: ($ "div.foo.bar#unique#id" {} โ€ฆ) where {:class ["foo" "bar"] :id "unique id"} would be set as a result of this.

Many hiccup-inspired tools utilize this kind of syntax, for example Reagent. The shorthand makes it a lot easier to sell a team on Helix that is currently using something with "less typing".

We've been using a $-wrapping macro at work since using Helix (~6 months at least) and have not found any downsides yet. Our code is definitely shorter! :)

Cursive Stub Generation Fails

Stub generation fails in Intellij Cursive with the following error:

Error generating stubs for module demo-app: clojure.lang.ExceptionInfo: Library name must be specified as a symbol in :require / :require-macros; offending spec: ["react" :as react] at line 1 jar:file:/Users/emmanuel.john/.m2/repository/lilactown/helix/0.0.13/helix-0.0.13.jar!/helix/core.cljs {:file #object[java.net.URL 0x790ed2d9 "jar:file:/Users/emmanuel.john/.m2/repository/lilactown/helix/0.0.13/helix-0.0.13.jar!/helix/core.cljs"], :line 1, :column 1, :tag :cljs/analysis-error}
				at cljs.analyzer$error.invokeStatic(analyzer.cljc:645)
				at cljs.analyzer$error.invoke(analyzer.cljc:641)
				at cljs.analyzer$error.invokeStatic(analyzer.cljc:643)
				at cljs.analyzer$error.invoke(analyzer.cljc:641)
				at cljs.analyzer$basic_validate_ns_spec.invokeStatic(analyzer.cljc:2008)
				at cljs.analyzer$basic_validate_ns_spec.invoke(analyzer.cljc:1999)
				at cljs.analyzer$parse_require_spec.invokeStatic(analyzer.cljc:2107)
				at cljs.analyzer$parse_require_spec.invoke(analyzer.cljc:2103)
				at clojure.lang.AFn.applyToHelper(AFn.java:171)
				at clojure.lang.AFn.apply... (show balloon)

I'm using the following deps:

org.clojure/clojurescript       {:mvn/version "1.10.773"}
thheller/shadow-cljs            {:mvn/version "2.11.6"}
lilactown/helix                       {:mvn/version "0.0.13"}

Cursive apparently do not like this. Is it possible to change the 'require' to use symbols only where possible?

Consider keyword version of the spread operator

& is a special symbol acting as a spread operator in $ macro expansion.

($ :div {:prop "val" & rest-props} ...)

This causes minor issue in Cursive which sees a normal map and complains about unresolved symbol &. I think adding support for :& to be optionally used in place of & should not hurt anynone.

($ :div {:prop "val" :& rest-props} ...)

See darwin@be5c3dc

Compile warnings using Figwheel

I'm getting the following compile warnings when using Figwheel - these hook macros are defined outside a reader conditional, but depend on things only defined under :clj:

deps-macro-body is only defined for :clj:

use-effect Use of undeclared Var helix.hooks/deps-macro-body at line 156, column 4 in file helix\hooks.cljc
use-layout-effect Use of undeclared Var helix.hooks/deps-macro-body at line 176, column 4 in file helix\hooks.cljc
use-memo Use of undeclared Var helix.hooks/deps-macro-body at line 196, column 4 in file helix\hooks.cljc
use-callback Use of undeclared Var helix.hooks/deps-macro-body at line 224, column 4 in file helix\hooks.cljc
use-imperative-handle Use of undeclared Var helix.hooks/deps-macro-body at line 243, column 4 in file helix\hooks.cljc

hana is only imported under :clj:

use-memo No such namespace: hana, could not locate hana.cljs, hana.cljc, or JavaScript source providing "hana"  helix\hooks.cljc   line:203  column:16
Use of undeclared Var hana/inferred-type helix\hooks.cljc   line:203  column:16
Use of undeclared Var hana/inferred-type helix\hooks.cljc   line:209  column:16

I'm using fix-figwheel :sha "43ed17b2828ae7f5b406f99d5dbb753321bf73d6".

Installing Helix into my project

I am installing helix into an app that is already using hx

I have included the library as so:
lilactown/helix {:mvn/version "0.0.6"}

Requiring [helix.core :refer [defnc]] throws the error bellow:

[Figwheel:WARNING] Could not Analyze: /_SLASH_impl_SLASH_class/js.cljs is not a relative path resources/public/js/helix/core.cljs [Figwheel:SEVERE] java.lang.IllegalArgumentException: /_SLASH_impl_SLASH_class/js.cljs is not a relative path

This basically applies to requiring anything.

Sanity check on using hx for hiccup from helix

I couldn't get either sablono or hicada to work with React Native elements, and I always had good success with hx, so I've been using this defnc macro:

(defmacro defnc [type params & body]
  (let [default-opts {:helix/features {:fast-refresh true}}
        [opts body] (if (map? (first body))
                      [(first body) (rest body)]
                      [{} body])]
    `(helix.core/defnc ~type ~params
       ~(merge default-opts opts)
       (hx.react/f (do ~@body)))))

Just wanted a sanity check that hx.react/f is the right way to wrap hiccup bodies.

I could also create a PR adding a note to docs/react-native that this seems to be the best way to get hiccup working for helix + react-native.

Deprecate $$

Deprecate $$ and replace it with a CLJS function $ when it needs to be taken as a value.

Runtime error if a nil map is passed for dynamic props

It appears that using a value of nil in the spread operator / dynamic props results in a runtime error as an attempt is made to index into the nil map.

A minimal reproduction is:

(let [x nil]
  ($ :div {& x}))

Seemingly, calling ($ :div {& nil}) doesn't trigger the issue.

The exception is thrown on this line:

https://github.com/Lokeh/helix/blob/6fc96e4ac330daeb1cb3e8372a13819f67570661/src/helix/impl/props.cljc#L77

The error appears as so:

image

It would be nice to gracefully handle this case as though an empty map were passed, in line with other behaviour throughout Clojure. For now this can be mitigated by constructing the component using the form:

($ :div {& (or x {})})

Factory component doesn't work with HOC that supplies props

helix/src/helix/core.cljs

Lines 131 to 137 in 51e758e

(defn extract-cljs-props
[o]
(when (and ^boolean goog/DEBUG (or (map? o) (nil? o)))
(throw (ex-info "Props received were a map. This probably means you're calling your component as a function." {:props o})))
(if-let [props (gobj/get o "helix/props")]
(assoc-some props :children (gobj/get o "children"))
(bean/bean o)))

If I define a factory component, that also uses a HOC which provides props (in this case withTooltip https://airbnb.io/visx/docs/tooltip which the docs say are deprecated but is still used in the examples) then the extra props provided by the HOC aren't included.

Maybe the props need to be bean'd as well?

(merge (bean/bean o) (assoc-some props :children (gobj/get o "children")))

Editing transitive dependencies doesn't trigger a refresh

When testing with web, transitive namespaces do not trigger a refresh. Example:

(ns app.a
  (:require
   [app.b]
   [helix.core :refer [defnc]])

(defnc app
  []
  (app.b/greet "Refresh"))
(ns app.b
  (:require 
   [app.c]))

(defn greet
  [name]
  (str app.c/greeting ", " name "!"))
(ns app.c)

(def greeting "Bonjour")

Editing app.c/greeting to "Hello" will not trigger app.a/app to refresh.

I'm not sure if this behavior is different in React Native; it is dependent on whether app.a gets reloaded when transitive namespaces are edited. shadow-cljs on the web currently only reloads namespaces that directly depend on the edited namespace.

use-memo and use-callback via metadata

We should be able to signal that an expression should be wrapped in a use-memo or use-callback by annotating it with metadata in the body of a defnc or a defhook.

(defnc my-component
  [{:keys [value]}]
  ^:memo (d/div value)) ;; returns the same react element for the save `value`

^:memo and ^:callback metadata should tell defnc and defhook to emit a use-memo or use-callback hook that will automatically fill dependencies using the same algorithm as :auto-deps.

A dependency seq can also be provided to override this behavior:

(defnc my-component
  [{:keys [foo bar baz]}]
  ^{:memo [foo]} (d/div value)) ;; ignores changes to `bar` and `baz`

^:memo and ^:callback metadata should be usable in let bindings:

(defnc my-component
  [{:keys [value]}]
  (let [calculated ^:memo (+ value 10)
        on-click ^:callback #(js/alert calculated)]
    ^:memo (d/button {:on-click on-click} "Click me!")))

^:memo and ^:callback should allow enforcement of the Rules of Hooks checks that are currently behind an experimental feature flag.

components wrapped in HOC can't refer to themselves w/o fully qualified name

Since we create the inner fn of the component with the same name as var we are defing, if you wrap the component in an HOC and call it recursively you end up getting the unwrapped component ๐Ÿ˜“

example psuedo-code of the bug:

(def node-view (-> (fn node-view [props]
                     ;; this refers to the inner fn, not the top-level def node-view!!
                     ($ node-view ,,,))
                   (helix.core/memo)))

Props translation cache

uix library also does props translation and uses cache[1] - prop names translation might be a hot code path.

I think helix should explore this possibility as well. I don't think it is that important for helix because 99% of time props get translated statically and is not worth optimizing of the rest of dynamic cases.

But in the other direction bean is dynamic so caching there would make more sense. So we could keep only cache from js names back to cljs keywords.

A prerequisity for this should be to have some reliable benchmarks to decide if this would be worth it.

[1] https://github.com/roman01la/uix/blob/fea214e15365f3f316f55a3524dd98f2fc6fa255/core/src/uix/compiler/alpha.cljs#L57-L75

React Refresh with JSValue

Currently, using a JS tagged literal i.e. #js [] inside of a hook will bust the react-refresh cache every time.

This is due to the fact that #js [] emits a value created via deftype, and then helix coverts this at compile time to a string to use as the cache key. The stringified object contains a memory reference, which is different every time.


Copying @SevereOverfl0w 's slack investigation here for posterity:

dominicm 1:09 PM
Ah, string/join runs in clojure-lang. Derp! Right, I bet it's getting something that looks very different then!

dominicm 1:10 PM
"hooks-key" "(hooks/use-state (do #object[cljs.tagged_literals.JSValue 0x73ca9fc4 \"cljs.tagged_literals.JSValue@73ca9fc4\"] \"Lisa\"))" That's why! It's printing out the object using the JSValue, which is an object so has a memory reference associated @alex J Henderson @lilactown here's the bug ๐Ÿ˜„

dominicm 1:21 PM
(string/join (map cljs.compiler/emit-constant hooks)) does the trick. But it's pretty verbose. Based on a cursory look around the source, you might only need to solve for regex/JSValue (based on the fact those are both things that broke Cljs' own caching in the past, and are still the only 2 custom ones: https://github.com/clojure/clojurescript/blob/9d3dfc369a01b31244eb925fef4c9fafa3824e24/src/main/clojure/cljs/analyzer.cljc#L94-L103).
As far as I can tell, JSValue is the only deftype in a cljc file in ClojureScript, so special casing JSValue probably makes sense.

(string/join
  (clojure.walk/postwalk
    (fn [x]
      (if (instance? JSValue x)
        (str "#js" (.val x) "")
        x))
    hooks))

Also works if you just special case JSValue types. (edited)

Non-exhaustive dependency warning

defnc should detect if dependencies are exhaustively filled in, and if not signal a compiler warning. It could be silenced by filling in the dependencies or annotating with metadata.

;; Warning! Non-exhaustive dependencies
(use-memo
 [foo]
 (+ foo bar))

;; Ignore specific dependency in the body
(use-memo
 ^{:ignore-deps [bar]} [foo]
 (+ foo bar))

;; Don't warn ever
(use-memo
 ^:ignore-deps []
 (+ foo bar))

Realize lazy seqs

Thheller:

the issue is that in development react "validates" the elements it gets immediately, walking the entire structure and thus forcing lazy seqs
in production that may be delayed since it doesn't validate
so the "work" potentially happens at different times. it is known to cause problems if you use any kind of bindings

Hooks not found inside JSValue

I think this should be trivial to fix after #86 is merged. Right now, hooks can't be found when they hide inside pesky #js tagged literals like so:

(when true
  #js [(use-state 10)])

Both the find-hooks and invalid-hooks-usage functions in the analyser need updating to know how to descend into a JSValue.

react glob import error in shadow-cljs

trying to use helix with shadow-cljs and getting following error

--- helix/impl/class.js:1
Namespace imports (goog:some.Namespace) cannot use import * as. Did you mean to import React from 'goog:shadow.js.shim.module$react';?

Anonymous components (aka `fnc`)

We discussed on slack a little while ago. This would be useful for something we're working on right now (dynamic dispatch of components based on server-side information) so I thought I'd create an issue to track it.

We're able to work without the anonymous stuff for now, so no urgency from my side.

Spread props do not work in (auto-defined) factory functions

Hello,

I've just noticed that if I define a component like

(helix.core/defnc Foo [{:keys [bar baz]}]
  {:helix/features {:define-factory true}}
  ($ "p" bar baz))

then I cannot pass through props like

(let [props {:baz "test"}]
  (Foo {:bar "yo" :& props}))

instead I must

(let [props {:baz "test"}]
  (Foo (merge {:bar "yo"} props)))

Is this a limitation of factory functions or just a bug? I can live without :& on factory functions if they are not possible, but maybe this should be documented at docs/creating-elements.md#factory-functions ?

Thank you! ๐Ÿ˜ƒ

unable to set inline styles with react native

example usage:

(defnc App []
  ($ rn/View
     {:style {:background "blue"}}
     ($ rn/Text "Hello World!")))

i'm receiving the following error:

Failed prop type: Invalid props.style key `meta` supplied to `View`.
Bad object: {
  "meta": null,
  "cnt": 1,
  "shift": 5,
  "root": {
    "edit": null,
    "arr": [
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null
    ]
  },
  "tail": [
    {
      "meta": null,
      "cnt": 1,
      "arr": [
        {
          "ns": null,
          "name": "flex",
          "fqn": "flex",
          "_hash": -1425124628,
          "cljs$lang$protocol_mask$partition0$": 2153775105,
          "cljs$lang$protocol_mask$partition1$": 4096
        },
        1
      ],
      "__hash": null,
      "cljs$lang$protocol_mask$partition0$": 16647951,
      "cljs$lang$protocol_mask$partition1$": 139268
    }
  ],
  "__hash": null,
  "cljs$lang$protocol_mask$partition0$": 167666463,
  "cljs$lang$protocol_mask$partition1$": 139268
}

however if i print output of component it looks fine (see below) so not sure why inline styles aren't working in react native if they work in regular dom (they both accept object styles, though react native also accepts an array of styles)

#js {"$$typeof" "Symbol(react.element)", 
:type #object[View], 
:key nil, 
:ref nil, 
:props #js {:style {:background "blue"}, 
:children #js { ... }

fast-refresh doesn't re-render with figwheel-main

Hi @Lokeh! Thank you for Helix!

I'm struggling to use fast-refresh with figwheel-main. I managed to add a ns to :preloads which injects a hook and set up a callback when code changes. Basically something like this:

(ns ^:figwheel-hooks fast-refresh
  (:require [helix.experimental.refresh :as r]))

(r/inject-hook!)

(defn ^:after-load refresh
  []
  (r/refresh!))

I know the refresh callback is invoked as it shows the component in the "updated" list but nothing changes on screen. The code is not re-rendered.

I used react 16.13.1, helix 0.0.11, and react-refresh 0.8.2.

Is there anything else needed? Am I missing something?

And of course I will drop a PR with documentation changes when I make it work :) ๐Ÿ‘‹

Helix clone-element

Provide a helix.core/clone-element macro which uses the same props conversion API as $.

What happened with hx?

What is the difference between hx and helix?

I think the community could get confused, maybe could add this difference in the Readme

RFC: use macro

One problem with the use-memo / use-effect / et al. macros is that their static analysis does not extend to custom hooks.

For instance, you cannot define a custom hook that uses the :auto-deps functionality without creating a macro and using some internal functions of helix.

The proposal here is to introduce a new macro (or two) with semantics that would allow users to define custom hooks that benefit from helix's static analysis.

;; using a built in hook
(use hooks/effect
  :once
  (foo))

;; using a custom hook
(use my-custom-hook
  :auto-deps
  #(foo))

Custom hooks could be defined using a defhook macro that could annotate the symbol with info about whether it takes deps or not.

(defhook my-custom-hook
  [^:deps deps f]
  (use hooks/effect
    deps
    (f)))

Spread props should work with a raw JS obj

Sometimes you get a JS object and want to forward it as props to a component.

What we'd like to do:

(defnc my-component []
  ;; `some-lib/Foo` is an external lib that uses a common pattern:
  ;; pass it a function-as-children which it then passes props to as a JS object
  ($ some-lib/Foo
   (fn [foo-props]
     (d/div {& foo-props} "I'm so foo-y!"))))

Currently, this requires converting or wrapping foo-props so that it is a CLJS map-alike, so that spread props works.

(defnc my-component []
  ($ some-lib/Foo
   (fn [foo-props]
     ;; wrap it in a bean, so that it can then be converted into a JS obj again... :sad:
     (d/div {& (cljs-bean.core/bean foo-props)} "I'm so foo-y!"))))

To support writing spread props like in the first snippet, spread props should check to see if it's a map-alike and if not, fall back to merging it in by Object.keys.

Changelog?

I find this library great enough already to use in an app I'm building. It would be really helpful to have a changelog file between releases. Would the maintainer be keep a log of notable changes?

Handle "native" props better for different renderers

We could remove a lot of the work involved with using different renderers (react-three-fiber, react-native, etc.) and make interop slightly easier if we defaulted to always converting kebab-case to camelCase when using $ / $$, and always transforming camelCase to kebab-case in defnc body via a bean with custom key->prop and prop->key as suggested by @darwin.

There might still need to be some determination of whether an element is "native" in order to decide whether to recursively convert the :style key, but this could be handled by helix.dom and / or other wrapper macros on a per-case basis.

defhook macro

Create a macro that will define new hooks, applying lint rules for rules of hooks as well as adding the ability to annotate certain behavior with metadata.

(defhook use-thing
  [foo bar]
  ,,,)

This can be a building block towards:

  • Interoping fast refresh to detect changes to custom hooks, in order to hot load them correctly.
  • Warning on using hooks in conditionals, loops.
  • Warning on not filling in deps inside defhook body
  • Add ability to flag an argument as deps to allow warnings about unfilled deps on usage

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.