Giter Club home page Giter Club logo

hyperview's Introduction

logo

Native mobile apps, as easy as creating a website.

Hyperview is a new hypermedia format and React Native client for developing server-driven mobile apps.

  • Serve your app as XML: On the web, pages are rendered in a browser by fetching HTML content from a server. With Hyperview, screens are rendered in your mobile app by fetching Hyperview XML (HXML) content from a server. HXML's design reflects the UI and interaction patterns of today's mobile interfaces.
  • Work with any backend web technology: Use battle-tested web technologies like Django, Rails, or Node. Any HTTP server can host a Hyperview app. You can even deploy your app as a collection of static XML files if you want!
  • Update your apps instantly by deploying your backend: Say goodbye to slow release cycles and long app store review times. With Hyperview, your backend controls your app's layout, content, and available actions. This means you can update any aspect of your app with a server-side change. True CI/CD is finally attainable for mobile development.
  • Forget about API versioning and backwards compatibility: Unlike traditional native apps, every user always runs the most recent version of your code. With no version fragmentation, you can be more productive by eliminating the need to support and maintain older app versions.

See the Hyperview website for more information about Hyperview and Hyperview XML.

Hyperview XML

  • See examples of how to create rich, interactive apps with Hyperview XML here
  • See the full references for Hyperview XML here

Hyperview React Native Client

CircleCI

This repo contains a React Native implementation of the Hyperview Client. It can either be integrated into an existing React Native app, or used to create a self-contained RN app.

Requirements

The Hyperview client only has the following required dependencies:

  • @instawork/xmldom = 0.0.3
  • lodash = 4.17.21
  • tiny-emitter = 2.1.0
  • url-parse = 1.5.10

More importantly, the client is designed to be incorporated into an existing React Native project, and thus has the following peer dependencies:

  • @react-native-community/datetimepicker >= 7.6.2
  • @react-native-picker/picker >= 2.6.1
  • @react-navigation/bottom-tabs >= 6.5.7
  • @react-navigation/native >= 6.1.6
  • @react-navigation/stack >= 6.3.16
  • @types/react >= 17.0.67
  • react >= 17.0.2
  • react-native >= 0.67.4
  • react-native-gesture-handler >= 2.11.0
  • react-native-keyboard-aware-scrollview >= 2.1.0
  • react-native-safe-area-context >= 4.2.4
  • react-native-webview >= 13.2.2

Getting Started

This repo contains an example XML server that serves Hyperview XML to showcase the available features. It also contains a demo Expo project that can connect to the example XML server, or any other Hyperview endpoint.

1. Run the example server

From the repo root directory:

yarn
yarn test:xmlserver

This will start an HTTP server listening on port 8085.

2. Start the demo app

In a separate shell, install the demo dependencies and start the development server. From the repo root directory:

cd demo
yarn

The next step depends on whether you want to run the demo app in the iOS simulator, on an Android Virtual Device, or on a physical mobile device.

Running on the iOS simulator

From the demo/ directory:

yarn ios

This will open the iOS simulator and install the demo app in the simulator. It will then start the Expo development server to load the demo app.

Running on an Android Virtual Device

From the demo/ directory:

adb reverse tcp:8085 tcp:8085
yarn android

This will open an AVD and install the demo app in the emulator. It will then start the Expo development server to load the demo app.

Running on a physical device

On your physical mobile device, install the Expo client

Make sure your mobile device and development machine are connected to the same network.

Open /demo/src/constants.js in a text editor. In ENTRY_POINT_URL, replace the host in the url (http://0.0.0.0:8085/index.xml) with the IP of your machine. This is needed in order for your physical device to be able to request the example XML files from your development machine.

From the demo/ directory on your development machine:

cd demo
yarn start

This command will start an Expo development server and open a webpage (http://localhost:19002). This webpage will display a QR code.

  • On your iOS device, open the Camera app and point it at the QR code on your screen. The Camera app should show an "Open in Expo" notification. Tap this notification.
  • On your Android device, use the Expo app to scan the QR code on your screen.

Developing hyperview core features

As you're developing new features for hyperview core, you can use the demo app along with this special command to help you quickly test your changes:

yarn sync

This command will update the installed hyperview package to use the untransformed code (so that it can easily be debugged), watch any changes made to src/ and copy them into demo/node_modules/hyperview/src.

You can also pass as an additional argument the root path of your own react-native app where you've installed hyperview to perform the same sync/watch operation. e.g.

yarn sync ../projects/my-cool-app

Tip

You may stop this with Ctrl + C

3. You're all set!

Whether you're using a physical device or simulator, you should now see a Hyperview screen rendered from the example server:

example

The example server simply serves files from the ./examples directory. You can modify or add files in ./examples and the server will update without restarting.

Running storybook

  1. Run the following to generate storybook. You would need the application_key which is the string passed as a first argument to the method AppRegistry.registerComponent in your root react-native component:
yarn generate <application_key>
  1. Start the storybook by running following in repo root:
yarn storybook
  1. Now you may open http://localhost:7007 on your browser to view storybook controls.

  2. Start the app registered as application_key.

Note

If you're getting issues about duplicate modules try removing the node_modules from /demo and retry.

Troubleshooting

This version of the Expo app is out of date. Uninstall the app and run again to upgrade.

If you see this warning message on the Expo development server webpage, you need to uninstall the Expo app from the simulator or physical device and install the latest version. On a physical device, this means getting the latest version from an app store. In the simulator or AVD, this means uninstalling and re-running yarn ios or yarn android.

hyperview's People

Contributors

adamstep avatar ashwinibm avatar baptistegrimaud avatar believer avatar codetalcott avatar danielschaffer avatar dikarel avatar divyanshu013 avatar emhagman avatar ffcd00 avatar flochtililoch avatar hgray-instawork avatar jasonwei-11 avatar jasonwei1106 avatar lenwhite avatar malayh avatar msp95 avatar nevanscott avatar ovalerio280788 avatar palaparthi avatar pixelistik avatar ratneshpkn avatar reshavsingla avatar rodabt avatar rohankumar1999 avatar simhasrivatsa avatar sourabhdpunja avatar tecnoloco avatar terryatgithub avatar utkbansal 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  avatar

hyperview's Issues

Having a custom behavior action on an alert option does not work without href attribute

This action will not run properly:

<behavior
  action="alert"
  alert:title="Contact"
  trigger="press"
>
  <alert:option
    action="phone"
    alert:label="Call phone"
    phone:number="123456"
    xmlns:phone="https://instawork.com/hyperview-phone"
  />
</behavior>

However, this one would:

<behavior
  action="alert"
  alert:title="Contact"
  trigger="press"
>
  <alert:option
    action="phone"
    alert:label="Call phone"
    href="#"
    phone:number="123456"
    xmlns:phone="https://instawork.com/hyperview-phone"
  />
</behavior>

The alert element should be able to trigger the phone action without requiring href

Add dev tools support

When using the react dev tools, there is currently no way to map a rendered component in the tree to its source XML node. Dev tools are an integral part of UI development and we should look into integrations with the existing dev tools as a start.

Introduce a better way to pass JSON data

Currently we've a very tedious way of sending JSON data which looks something like this:

<behavior
	...
	redux:extra="{&quot;payload&quot;:{&quot;params&quot;:{&quot;title&quot;:&quot;{% trans 'FAQ' %}&quot;,&quot;url&quot;:&quot;{% trans faq.answer_link %}&quot;},&quot;routeName&quot;:&quot;MODALS/WEB_VIEW_MODAL&quot;}}"
/>

I don't think this is readable. Currently we've to copy paste it into editor, replace characters and then replace everything back and paste it into the XML and hope it works.

Repetitively triggering the same behavior with large delay leads to buggy behavior

When triggering a behavior multiple times with a large delay (say 1000), the UI becomes inconsistent and leads to buggy behavior. Please check the attached screen-cast. This probably happens since the newer behaviors will be added to the event loop and executed after the second screen has loaded.

We should figure out a better way to handle such cases. Probably ignoring the triggers after the first one (not sure if there is a use case for handling all the triggers with delay):

demo

iOS: when text-field is focused, throw exception: TypeError null is not an object (evaluating 'o.isFocused')

Hi,
lately I got an exception for hyperview text-field, but this error is a random error, it did NOT happen every time
image

** exception detailed **
open a hyperview form, press on the text-field, when the text-field is focused, it will throw an exception: TypeError null is not an object (evaluating 'o.isFocused'), please see this video for reference: text-field error screen capture video

to reproduce the error:

  • go to this Achieve My Goal page
  • input some value in the form then submit
  • go to other page
  • come back to edit the form

with above these steps 10% chance this error would happen

env:

  • "hyperview": "0.36.0" ( 0.34.2 also has this issue)
  • "react-native": "0.63.3"
  • "react-navigation": "^4.4.0",

Do you have any idea, what is going wrong here or how to avoid this error ?

please note that: the exception is catched by react-native-exception-handler, using below code:.

import { setJSExceptionHandler } from "react-native-exception-handler";

const errorHandler = (e, isFatal) => {
  if (isFatal) {
    Alert.alert(
      "Unexpected error occurred",
      `
        Error: ${isFatal ? "Fatal:" : ""} ${e.name} ${e.message}
      `,
      [
        {
          text: "OK",
          onPress: () => {},
        },
      ]
    );
  } else {
    // console.log("error:", e);
  }
};

setJSExceptionHandler(errorHandler, true);

this is the hyperview page xml:

<doc lang="en" xmlns="https://hyperview.org/hyperview" xmlns:th="http://www.thymeleaf.org">
    <screen>
        <body style="Body Bg-White">
            <header style="Header">
                <text action="back" href="#" style="Header__Back">
                    &lt;
                    <text style="Header__Title">
                        <![CDATA[ ]]>
                        Achieve My Goal
                    </text>
                </text>
            </header>
            <view style="M-20" scroll="true">
                <text style="Text2">this is the plan.</text>
                <text style="Text1 M-T-20">Account type</text>

                <form id="allocateSavingForm">
                    <select-single name="tab" style="Tabs">
                        <option id="atAccountTypeBankAccounts" value="users" style="Tab" selected="true">
                            <text style="Tab__Label">Bank accounts</text>
                            
                            <behavior trigger="select" action="set-value" new-value="BANKSAVE" target="accountType"/>
                        </option>
                        <option id="atAccountTypeCashSavings" value="groups" style="Tab">
                            <text style="Tab__Label">Cash savings</text>
                            
                            <behavior trigger="select" action="set-value" new-value="SAVINGS" target="accountType"/>
                        </option>
                        <option id="atAccountTypeEWallet" value="tab3" style="Tab">
                            <text style="Tab__Label">E-Wallet</text>
                            
                            <behavior trigger="select" action="set-value" new-value="EWALLETSAVE" target="accountType"/>
                        </option>
                    </select-single>
                    <text style="Text1 M-T-20">
                        Account name
                        <text style="Main-Red">*</text>
                    </text>
                    <text-field id="atAccountName" placeholder="Please input account name" placeholderTextColor="#8D9494" name="accountName" style="input" value="My account" />
                    <text style="Text1 M-T-20">
                        My balance for this goal
                        <text style="Main-Red">*</text>
                    </text>
                    <text-field id="atAccountBalance" placeholder="Please input balance" placeholderTextColor="#8D9494" mask="$ **********************" keyboard-type="number-pad" name="accountBalance" style="input" />
                    <text-field id="accountType" name="accountType" value="BANKSAVE" hide="true"/>
                    <text-field name="goalId" th:value="${goalId}" hide="true"/>
                    <view id="atAllocateSaving" style="Button Button-Big-Primary M-T-20">
                    	<behavior href="/preview" action="replace" target="allocateSavingForm" verb="get"/>
                        <text style="Button-Label Text-Center">Allocate Saving</text>
                    </view>
                </form>
                
                <spinner id="mySpinner" hide="true" />
                
            </view>
        </body>
        <styles>
            <style id="input" borderBottomColor="#E1E1E1" borderBottomWidth="1" borderColor="#4E4D4D" flex="1" fontSize="16" fontWeight="normal" paddingBottom="8" paddingTop="8" />
            <style id="input-error" borderBottomColor="#FF4847" color="#FF4847">
                <modifier focused="true">
                    <style borderBottomColor="#FF4847" />
                </modifier>
            </style>
            <style id="Title1" fontWeight="700" fontSize="18" color="#2E384D" />
            <style id="Title2" fontWeight="600" fontSize="16" />
            <style id="Button-Label-Bold" fontWeight="600" fontSize="20" />
            <style id="Button-Big-Primary" fontSize="18" height="48" />
            <style id="Text-Center" textAlign="center" justifyContent='center' alignItems='center' />
            <style id="Button" borderColor="#F52B39" backgroundColor="#F52B39" borderWidth="1" borderRadius="20" justifyContent="center" paddingLeft="26" paddingRight="26" height="40" />
            <style id="Button-Label" color="#fff" fontSize="16" />
            <style id="Text1" fontSize="14" color="#5A6170" />
            <style id="Text2" fontSize="14" color="#596980" />
            <style id="Main-Red" color="#ED1B2E" />
            <style id="Main-Black" color="#2E3B4D" />
            <style id="Grey3" color="#8F9EB2" />
            <style id="Orange" color="#FA8025" />
            <style id="Green" color="#27BDB3" />
            <style id="Color-White" color="#fff" />
            <style id="Bg-White" backgroundColor="#fff" />

            <style id="Grey-Line" borderBottomWidth="1" borderColor="#F3F3F5" marginTop="15" marginBottom="15" />
            <style id="Bg-Banner" height="12" backgroundColor="#F3F3F5" />
            <style id="M-20" margin="20" />
            <style id="M-T-20" marginTop="20" />
            <style id="M-T-10" marginTop="10" />
            <style id="Flex-Center-Wrap" display="flex" flexDirection="row" justifyContent="space-between" alignItems="center" alignContent="center" />
            <style id="Tabs" flexDirection="row" marginTop="20" height="28" justifyContent="flex-start" />
            <style id="Tab" alignItems="center" backgroundColor="white" marginRight="10" paddingLeft="10" paddingRight="10" flexDirection="row" borderColor="#C4C7CC" borderWidth="1" borderRadius="16" justifyContent="center">
                <modifier selected="true">
                    <style backgroundColor="#FFF5F5" borderColor="#F52B39" />
                </modifier>
            </style>
            <style id="Tab__Label" fontSize="12" color="#5A6170" fontWeight="normal">
                <modifier selected="true">
                    <style color="#ED1B2E" />
                </modifier>
            </style>
            <style id="Header" paddingLeft="21" paddingRight="20" paddingBottom="10" paddingTop="10" backgroundColor="white" borderColor="#eee" borderBottomWidth="1" flexDirection="row" justifyContent="space-between" alignItems="flex-end"/>
            <style id="Header__Back" color="black" fontSize="18" fontWeight="600" />
            <style id="Header__Title" color="black" fontSize="16" fontWeight="bold" />
            <style id="Header_Logo" width="106" height="21" />
            <style id="Body" flex="1" />
            <style id="Color-Warning" color="#F52B39" />
        </styles>
    </screen>
</doc>

Does this work for web?

First. thanks for the amazing framework you guys have created.

I was wondering if this works for web as well, and if not, are there any plans on porting it to web so you can write once and run it everywhere?

Thanks.

hyperscript

Hi there, this isn't a real issue but I couldn't dig up a good way to get in touch with @adamstep otherwise. I am the creator of intercooler.js (and now htmx) and I came down to SF a while ago to chat with y'all about it and to see your awesome port of the concept to mobile development w/ hyperview.

Adam mentioned that, like me, he had done some hypercard work, and I wanted to let him know that when I ported intercooler to htmx, I decided to pull the event attributes and somewhat hacky ic-action attribute out and create a new front end programming language that is based on HyperTalk:

https://hyperscript.org

I thought he might get a kick out of it.

Authentication

Would you have a complete example in order to provide authentication to an app by using username/password?
Would it be possible to use Bearer Authentication by passing a token in every request to the backend?

demo app , cannot find variable later

Hi ;

In demo app , any refresh part gives this error ::
(Like List with refresh )

ReferenceError: Can't find variable: later

This error is located at:
in HvOption (at render/index.js:81)
in RCTView (at View.js:44)
in HvSelectSingle (at render/index.js:81)
in RCTView (at View.js:44)
in HyperScreen (at HyperviewScreen.js:70)
in HyperviewScreen (at SceneView.js:9)
in SceneView (at StackViewLayout.js:483)
in RCTView (at View.js:44)
in AnimatedComponent (at screens.native.js:58)
in Screen (at StackViewCard.js:42)
in Card (at createPointerEventsContainer.js:26)
in Container (at StackViewLayout.js:507)
in RCTView (at View.js:44)
in ScreenContainer (at StackViewLayout.js:401)
in RCTView (at View.js:44)
in StackViewLayout (at withOrientation.js:30)
in withOrientation (at StackView.js:49)
in RCTView (at View.js:44)
in Transitioner (at StackView.js:19)
in StackView (at createNavigator.js:57)
in Navigator (at createKeyboardAwareNavigator.js:11)
in KeyboardAwareNavigator (at createNavigationContainer.js:376)
in NavigationContainer (at SceneView.js:9)
in SceneView (at StackViewLayout.js:483)
in RCTView (at View.js:44)
in AnimatedComponent (at screens.native.js:58)
in Screen (at StackViewCard.js:42)
in Card (at createPointerEventsContainer.js:26)
in Container (at StackViewLayout.js:507)
in RCTView (at View.js:44)
in ScreenContainer (at StackViewLayout.js:401)
in RCTView (at View.js:44)
in StackViewLayout (at withOrientation.js:30)
in withOrientation (at StackView.js:49)
in RCTView (at View.js:44)
in Transitioner (at StackView.js:19)
in StackView (at createNavigator.js:57)
in Navigator (at createKeyboardAwareNavigator.js:11)
in KeyboardAwareNavigator (at createNavigationContainer.js:376)
in NavigationContainer (at App.js:15)
in App (at registerRootComponent.js:17)
in RootErrorBoundary (at registerRootComponent.js:16)
in ExpoRootComponent (at renderApplication.js:34)
in RCTView (at View.js:44)
in RCTView (at View.js:44)
in AppContainer (at renderApplication.js:33)

onUpdateFragment
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:163922:16
onUpdate
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:163734:34

AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:167363:19
triggerSelectBehaviors
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:167354:32
componentDidUpdate
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:167412:38
commitLifeCycles
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:17582:46
commitAllLifeCycles
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:18736:29
invokeGuardedCallbackImpl
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:9710:21
invokeGuardedCallback
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:9796:42
commitRoot
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:18873:34
completeRoot
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:20017:19
performWorkOnRoot
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:19957:27
performWork
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:19877:30
performSyncWork
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:19852:20
batchedUpdates$1
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:20053:28
batchedUpdates
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:11127:37
_receiveRootNodeIDEvent
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:11184:23
receiveTouches
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:11214:34
__callFunction
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:3624:49

AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:3397:31
__guard
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:3578:15
callFunctionReturnFlushedQueue
AppEntry.bundle?platform=ios&dev=true&minify=false&hot=false&assetPlugin=%2FUsers%2Fmikail%2Fhyperview%2Fdemo%2Fnode_modules%2Fexpo%2Ftools%2FhashAssetFiles.js:3396:21

Feature: support customized ErrorPage

now, when hyperview detected xml href or format error, below error page will show.
but it can not satisfy our UX requirement.
we need replace it with a customized error component.
Do you consider support this feature in future?
thank you very much.

image

image

How does serverside render these xml?

I see your examples are all static files. The data to show in the pages will need query from db in server side and refer to the user's permissions. but how should I place these data into the xml which need to return to the client? Is there a reactlike lib for generate the page?

how to do jest unit test for hyperview custom component?

hi, one question: how do you do the unit test for custom component by using Jest?

for example, for below [hv-web-view] component, how do I write the unit test?

import * as Events from 'hyperview/src/services/events';
import * as Namespaces from 'hyperview/src/services/namespaces';
import { ActivityIndicator, StyleSheet } from 'react-native';
import React, { PureComponent } from 'react';
import type { HvComponentProps } from 'hyperview/src/types';
import { LOCAL_NAME } from 'hyperview/src/types';
import WebView from 'react-native-webview';
import { createProps } from 'hyperview/src/services';

export default class HvWebView extends PureComponent<HvComponentProps> {
  static namespaceURI = Namespaces.HYPERVIEW;

  static localName = LOCAL_NAME.WEB_VIEW;

  static localNameAliases = [];

  props: HvComponentProps;

  onMessage = (event: ?{ nativeEvent: { data: string } }) => {
    if (!event) {
      return;
    }
    const matches = event.nativeEvent.data.match(/^hyperview:(.*)$/);
    if (matches) {
      Events.dispatch(matches[1]);
    }
  };

  render() {
    const props: any = createProps(
      this.props.element,
      this.props.stylesheets,
      this.props.options,
    );
    const color = props['activity-indicator-color'];
    const injectedJavaScript = props['injected-java-script'];
    const source = { html: props.html, uri: props.url };
    return (
      <WebView
        injectedJavaScript={injectedJavaScript}
        onMessage={this.onMessage}
        renderLoading={() => (
          <ActivityIndicator
            color={color}
            style={StyleSheet.absoluteFillObject}
          />
        )}
        source={source}
        startInLoadingState
      />
    );
  }
}

thanks very much

Behavior trigger="load" triggers multiple times

With XML below, I would expect the behavior to only trigger once after the component has mounted. However, the two behaviors inside the select-single ("select" / "deselect") seem to cause the entire component to re-mount (not just the component backing the form).

<form style="Flex">
  <text style="H7">Why are you cancelling this shift?</text>
  <select-single style="Select" name="{{ form.business_cancelled_reason.name }}">
  {% for choice_value, choice_label in form.fields.business_cancelled_reason.choices %}
    <option style="Select__Option" value="{{choice_value}}"{% if choice_value == form.cleaned_data.business_cancelled_reason %} selected="true"{% endif %}>
      {% if choice_value == form.instance.CANCEL_REASON_OTHER %}
        <behavior trigger="select" href="#otherReasonInput" action="replace-inner" target="otherReason" />
        <behavior trigger="deselect" href="#null" action="replace-inner" target="otherReason" />
      {% endif %}
      <text style="Select__Option__Label">{{choice_label}}</text>
      <view style="Select__Option__RadioOuter"><view style="Select__Option__RadioInner" /></view>
    </option>
  {% endfor %}
  </select-single>
  <view id="otherReason" />
</form>
<view hide="true">
  <view id="null" />
  <view id="otherReasonInput">
    <text-field name="{{ form.business_cancelled_reason_other.name }}" style="Input" placeholder="Reason for cancelation" placeholderTextColor="#8D9494" />
  </view>
</view>
{% if form.cleaned_data.business_cancelled_reason == form.instance.CANCEL_REASON_OTHER %}
  <behavior trigger="load" href="#otherReasonInput" action="replace-inner" target="otherReason" />
{% endif %}

Remove the prettier related eslint configs

Now that eslint-plugin-instawork includes the necessary eslint configs and plugin. We can update the dependency version and get rid of the stale configs from hyperview repo.

Also explicitly set printWidth to 100 to match eslint config

Adding href to view can mess up flex styling

Currently, adding a behavior to a will wrap that view in a TouchableOpacity component in React Native. This can have unintended consequences if the view is using flexbox styling, because the view will be limited in its layout to the wrapping touchable component.

The current workaround is to set "href-style" attribute with styles that will get applied to the touchable component, but this is not intuitive and has led to developer confusion.

Ideally, we can somehow determine which flebox styles applied to the view should be automatically added to the wrapping component. Maybe it's as simple as applying all flex properties to the wrapper, and setting the view to flex="1"?

No text editor support

One of the problems with hyperview is 0 feedback from editor while writing code. This ends up creating a need to always keep on checking with existing XML files and the docs.

Ideally there should be some auto-complete feedback from the editor. I'm using VSCode but I guess grammar would be similar for all editors. Integrations and extensions might differ.

For example, this is how it works in react native code:

image

Add "disabled" modifier

The "disabled" modifier styles should be applied to the element when disabled. Elements that support being disabled can set disabled="true" as an attribute.

Add a reload button to hyperview screens in dev mode

While in dev mode, it's often required to make changes on the template on server side and reload the screen on mobile client.

True hot reloading might be tricky to handle for now; we can render an absolute positioned view which reloads the screen (probably using the reload action would just work)

App Store approval + Rendering ?

How easy is it to get a Hyperview app approved in the iOS App Store?

Since, as I understand it, the content of the app which is rendered is entirely controlled over-the-wire at runtime, the App Store reviewers won't know that what they are reviewing might be entirely changed immediately afterwards?

Or does Hyperview bundle and ship the views within the pre-downloaded app? Then merely allow the server to control navigation and select which of the pre-bundled views/components that are shown? That would be in line with Server-Driven Rendering, if I understand it correctly.

Improve error stack trace

When an error is thrown in hyperview the stack trace should point to the XML file (line and column) where the error was caused. The current workflow involves hit and trial, opening the XML in editor and trying to figure out what went wrong without much leads.

For example, here's how error stack trace looks like on JS (works directly in editor as well):

hv-syntax

how to include one common style for each hyperview page?

this is my situation:

  • I have several pages sharing the same common style, see below code between common style start and common style end
  • now I have to copy and paste the common styles to all pages, so I can use the common style in the page.

I think this is not a good practice, my question is: how can I include one common style for each hyperview page?so every time when there are changes for the common-style, I only need to update it in one place.

something just like when we working on a web project, we just need to include a common.css for all page

<link rel="stylesheet" type="text/css" href="css/common.css">

<doc lang="en"
	xmlns="https://hyperview.org/hyperview"
	xmlns:th="http://www.thymeleaf.org">
	<screen>
		<body style="Body">
			<header style="Header">
				<text action="back" delay='300' href="#" style="Header__Back">
					<text style="Header__Title">Title</text>
				</text>
			</header>
			<view scroll="true">
				<view style="m-16">
					<view style="flex-center-wrap">
						<text style="18-bold gray4">test text</text>
						<view style="btn btn-medium btn-primary">
							<text style="btn-label btn-primary"> === medium === </text>
						</view>
					</view>
				</view>
			</body>
			<styles>
				<style id="Header" paddingLeft="21" paddingRight="20" paddingBottom="10" paddingTop="10" backgroundColor="white" borderColor="#eee" borderBottomWidth="1" flexDirection="row" justifyContent="space-between" alignItems="flex-end"/>
				<style id="Header__Back" color="black" fontSize="18" fontWeight="500" />
				<style id="Header__Title" color="black" fontSize="16" fontWeight="bold" />
				<style id="Body" flex="1" backgroundColor="#fff" />
				<!-- common style start -->
				<!-- margin -->
				<style id="m-0" margin="0" />
				<style id="m-4" margin="4" />
				<style id="m-8" margin="8" />
				<style id="m-12" margin="12" />
				<style id="m-16" margin="16" />
				<style id="m-t-0" marginTop="0" />
				<style id="m-t-4" marginTop="4" />
				<style id="m-t-8" marginTop="8" />
				<style id="m-t-12" marginTop="12" />
				<style id="m-t-16" marginTop="16" />
				<style id="m-t-24" marginTop="24" />
				<style id="m-b-0" marginBottom="0" />
				<style id="m-b-4" marginBottom="4" />
				<style id="m-b-8" marginBottom="8" />
				<style id="m-b-12" marginBottom="12" />
				<style id="m-b-16" marginBottom="16" />
				<style id="m-b-24" marginBottom="24" />
				<style id="gray1" color="#283542"/>
				<style id="gray2" color="#596980"/>
				<style id="gray3" color="#8F9EB2"/>
				<style id="gray4" color="#BCC2CC"/>
				<style id="gray5" color="#E1E3E6"/>
				<style id="gray6" color="#E8E9EB"/>
				<style id="gray7" color="#F3F3F5"/>
				<style id="bold" fontWeight="700"/>
				<style id="medium" fontWeight="500"/>
				<style id="regular" fontWeight="400"/>
				<!-- button -->
				<style id="btn" borderColor="#ED1B2E" backgroundColor="#fff" borderWidth="1" borderRadius="24" justifyContent="center" paddingLeft="24" paddingRight="24" />
				<style id="btn-large" height="48" marginBottom="12"/>
				<style id="btn-medium" height="44" marginBottom="12"/>
				<style id="btn-small" height="36" marginBottom="12"/>
				<style id="btn-primary" backgroundColor="#ED1B2E" color="#fff" />
				<style id="btn-label" color="#ED1B2E" textAlign="center" fontSize="16" fontWeight="500"/>
				<style id="btn-label-small" fontSize="14" fontWeight="400"/>
				<!-- common style end -->
			</styles>
		</screen>
	</doc>

First class support for components

The concept of "components" helps in abstracting different pieces of the UI so we can work and collaborate in an easier way.

The current state of art is extending XMLs from different files and including them in an templating engine (for example Django) which only helps to a small extent.

Some of the advantages of a first class component system are:

  • Ability to pass attributes (props) to components for easier re usability.
  • Two components on the same XML root file wouldn't interfere with each other for example styles (or behaviors, scoping events?). Current state of art is any XML file can cause a change in any other XML file. If the person working on the feature is not the author, it's very hard to build a mental model and flow of behaviors.
  • A "context" like API. For example, you wouldn't want to propagate the "namespace" of a screen deep down the component chain.
  • Visualize each component in the dev tools, currently once the XML tree is constructed there is no way of telling where each piece came from. This causes a lot of time spent on debugging when something goes wrong.
  • Error boundaries

All of these are already available in the react ecosystem and heavily increase productivity and maintain sanity.

Add hot reloading / fast refresh support

Currently there is no way to take advantage of hot reload / fast refresh.

With hot reloading only the tree which is changing should reload and rest of the app should maintain its state. When hot reloading is not feasible (component tree throws some error or network connectivity) it should fallback to fast refresh (full tree reload).

Feature: introduce new actions include and include-inner

in order to implement some complicated UI like below two-layer cascading menu, it's found that current actions can not match this requirement.

image

And below actions are needed in this case

  • include
    include means replace the target element with the contents of source element, instead of source element itself.
  • include-inner
    include-inner means replace the target element's children with the contents of source element.

The name and meaning of both new actions are referred from the include syntax of Thymeleaf.

I'm testing these new actions now, and want to hear your opinions before raising a PR.
the implement code is like below:

// hyperview/src/services/behaviors/index.js
/**
 * Returns a new Document object where the given action was applied to the target element
 * with the new element.
 */
export const performUpdate = (
  action: UpdateAction,
  targetElement: Element,
  newElement: Element,
): Document => {
  if (action === ACTIONS.REPLACE) {
    const { parentNode } = targetElement;
    if (parentNode) {
      parentNode.replaceChild(newElement, targetElement);
      return shallowCloneToRoot((parentNode: any));
    }
  }

  if (action === ACTIONS.REPLACE_INNER) {
    let child: ?Node = targetElement.firstChild;
    // Remove the target's children
    while (child !== null && child !== undefined) {
      const nextChild: ?Node = child.nextSibling;
      targetElement.removeChild(child);
      child = nextChild;
    }
    targetElement.appendChild(newElement);
    return shallowCloneToRoot(targetElement);
  }

  // new action : include
  if (action === ACTIONS.INCLUDE) {
    const { parentNode } = targetElement;
    if (parentNode) {
      let child: ?Node = newElement.firstChild;
      // Insert the newElement's children
      while (child !== null && child !== undefined) {
        const nextChild: ?Node = child.nextSibling;
        parentNode.insertBefore(child, targetElement);
        child = nextChild;
      }
      parentNode.removeChild(targetElement);
      return shallowCloneToRoot((parentNode: any));
    }
  }

  // new action : include-inner
  if (action === ACTIONS.INCLUDE_INNER) {
    let child: ?Node = targetElement.firstChild;
    // Remove the target's children
    while (child !== null && child !== undefined) {
      const nextChild: ?Node = child.nextSibling;
      targetElement.removeChild(child);
      child = nextChild;
    }
    child = newElement.firstChild;
    // Append the newElement's children
    while (child !== null && child !== undefined) {
      const nextChild: ?Node = child.nextSibling;
      targetElement.appendChild(child);
      child = nextChild;
    }
    return shallowCloneToRoot(targetElement);
  }
 
 ...
};

Add editable attribute for text-field

image
Hi, I need editable attribute for text-field in some cases. There wasn't any issue when I add it on ios, however, editable does not supported on android devices. So I raise an issue here.

Hyperview - add style toggle behavior actions

Implement add/remove/toggle style actions for behaviors. Ideally, these should behavior similarly to jQuery's addClass/removeClass/toggleClass functions:

add-style adds the specified style(s) to the target, without creating duplicate style IDs

remove-style removes the specified style(s) from the target, no errors if the styles do not exist

toggle-style adds style(s) the target does not have, and removes style(s) the target does have

TBD: should toggle-style be allowed to mix operations (e.g. add some styles and remove others) for a single trigger?

[Feature] support 'focus' and 'blur' trigger event for text-field component

Hi @adamstep, sorry to disrupt you. We wonder if there are any plan or proposal to support the below feature:

[Feature] add the following triggers to the 'text-field' and 'text-area' component:

  • focus
  • blur

We found that in acutal work we often need to verify the correctness of the fields filled by the user, or have some linkage effects between fields. These situations all require timely feedback to the uses.

According to my understanding, now the only way to achieve this function is to encapsulate the 'Form' component of React Native by 'custom elements ' feature. but this method will be very inflexible, because the entire page would be a react native component, instead of a hyperview page.

In view of this, if hyperview can support 'focus' and 'blur' trigger for text-field component, there would be more flexibility to deal with the above cases.

Or would you have some other plans or suggestions on above requirements ?
Looking forward to reply, and thank you so much.

btw: now I am trying to implement it in my hyperview branch.

image

A few questions

Hi, I talked to one of your representatives a few days ago on twitter where I said I would reach out. So I did:

I have a few questions regarding how Hyperview works.

1.

As I understand it Hyperview renders views inside a react native client application based on the XML data it receives from the server. Though what is, at least to me, fairly unclear is how it does that. With that I mean, are the views the application renders based on that data actually native UI elements? Or are they more similar to web elements?

2.

Continuing from the first question: how does this approach differ from a webbrowser? You have a React native client which gets sent data that tells it how to render the UI. This concept appears to me very similar to a traditional webbrowser. So I wonder what the difference is and also, what the advantages are in using this approach over a traditional webbrowser. And that brings me to the next question.

3.

What advantage does Hyperview have over PWA's? When you come from a web background (like myself) what would be the advantage of using Hyperview over something like a PWA? It's a bit easier to write as they are basically websites that run in a webview on the device (and are in a sense the natural succession to something like Cordova).

4.

In what capacity can I mix web code with Hyperview? And by that I mean, can I run javascript libraries inside hyperview or does that only work inside the webview tag? or instance, can I choose to write Hyperview XML wherever I whish to have a native experience, and switch to a webview where I want to include something that the native UI doesn’t cover (for example: a custom navigation bar)? I’m mainly thinking about animation in this instance (libraries like greensock and the like).

5.

This may be a bit of an odd question but here it goes anyway: Since it is mentioned in the docs that Hyperview is supposed to work with any backend technology that is capable of handling HTTP requests, would it theoretically be possible to combine Hyperview with Wordpress? In the sense of having Wordpress build the XML files using PHP and serving that to the react native client? And if that would be possible, would you recommend it? why yes or why not? (or perhaps you are neutral about it).

I may follow up with a few more questions in the future as these are the ones that I had at the top of my head.

With kind regards

Roel Van Eyken

Requirement: detect swipe left, and back to specific page

when user swipe left(go back previous [specific] page) or swipe right(go to next [specific] page) in both iOS/Android,
Can the gestures be detected and handled by the same customized method with hardwareBackPress #268 ?

like the way #272 implemented by @ashwinibm about the Android physical back key.
if yes, how to implement it ?

Thanks a lot.

any suggestion on how to add dynamic graph into the screen? like bar/pie chart base on some data from server side

hi, this is a really great lib!!!
but i'm noticing there is no graph in the demo, can you tell me how to add dynamic graph into the screen?
for example: if i want some screen have a bar/pie chart base on some data from server side, what should i do?

another question: for some reason, if i want to change some screen with React-native UI (like page a is hyperview, and navigate to page b which is react-native page), is it possible?

when set action to back, it behaves not as expectation described in official doc

Hi, it seems that when set action to back in hyperview xml, it behaves not as expectation described in doc as below.
In official demo, press button "Back to other", it just goes back to previous page, does not make a new request to the new url.
Please help check, thanks a lot.

doc to action=back

When the user presses "Go to second screen", the second screen will be pushed onto the stack. Then, if the user pushes "Go back", the stack will unwind, and the user will see screen 1 again. However, if the user pushes "Go back to a different place", the stack will unwind, and Hyperview will make a request to https://mysite.com/third. The content of the first screen will be replaced with the content from the third request.
Any change in the URL will cause a reload, including changes in the search string.

Support custom RN components for loading state

  • When creating a Hyperview screen component, pass props to specify default for loading screens
  • nuance: need to show close or back button depending on where the screen is created

We recently added this for error screen, loading can be similar.

Requirement: How to go back specific page when use Android physical back key

hi, there is a question I'd like to ask:
How to go back specific page when use Android physical back key ? (key 2 in below pic)

Requirement:
when user press back key(key 1 in below pic), generally it will back to previous page.
but in some special case, it need go back further, like back to the home page.
in this case, I can set as below:

<text>
back
<behavior action="navigate" href="/home.xml"  />
</text>

The question is:
How to do if I want to achieve the same effect with the Android physical 'back key' ? (key 2 in below pic)
React Native backhandler

image

Failed solution

I tried to use custom-behavior as below, but it failed with error shown in below pic:

<behavior 
      action="android-back-action" 
      action-href="/home.xml" 
      action-action="navigate" 
/>
const androidBackBehavior = {
    action: 'android-back-action',
    callback: (element: Element, onUpdate: HvComponentOnUpdate, getRoot: HvGetRoot, updateRoot: HvUpdateRoot) => {
      const href = element?.getAttributeNode('action-href')?.nodeValue;
      const action = element?.getAttributeNode('action-action')?.nodeValue;
      hyperviewRef.current.onUpdate(href, action, {}, {});
    }
  };

 <Hyperview
        ref={hyperviewRef}
        back={goBack}
        closeModal={closeModal}
        fetch={(input: any) => {
          return fetchWrapper(input, customHeaders);
        }}
        navigate={navigate}
        navigation={navigation}
        openModal={openModal}
        push={push}
        replace={navigation.replace}
        formatDate={formatDate}
        behaviors={[androidBackBehavior]}
 />

image

Add proper linting support

Currently there is no linting support for HXML. This often leads to problematic issues which are hard to debug. For example, I once wasted quite a bit of time trying to debug scrolling on a view just to realize later that the attribute scroll was misspelled.

Some of the most basic features are:

  • Proper attributes being passed to elements
  • Using behaviors at the right place
  • Attribute names mismatch
  • Catch linting errors from another included XML (with include)
  • A template variable being used outside of its scope. For example, a loop variable being used outside the loop fails silently. (This should fail atleast in dev mode)

Authentication should be preserved via cookies

Authentication should be preserved via cookies (as per a web browser), so that when the server does a redirect authentication information is not lost.

Right now, if we return a 302 on a Hyperview page the user will land on the target page as if they're not authenticated.

How to send http post request from hyperview xml to java backend controller?

Hi genius, I have read the guide of basic form section here https://hyperview.org/docs/example_basic_form. But I fond some issues.

  1. Even if I use the "verb=post" property in xml it send a "GET" request.

  2. When I play with the case study examples of basic form section, after I click the Submit button whithout nothing input I got the bellow error.
    image
    image

  3. How to send http post request from hyperview xml to java backend controller?

My system version is Macos catalina 10.15.6. The simulator version is Iphone11pro-14.1

Could you pls help on above questions?

action="replace" doesn't take effect in some special cases

action="replace" doesn't take effect in some special case so far I found:

  1. in Official Demo:
    Behaviors -> Indicators -> Inline Indicator
    (source file in hyperview/examples/behaviors/inline_button_indicator.xml)
    issue is :
    when press the button 'Press me', after delay, the content of view which id="container" would not be replaced.
    I checked above issue by expo client app installed in emulator iPhone11(ios 14.3) and Android device(Android 10), both not work.
    for reference: it can work if remove the both attribute: 'show-during-load' and 'hide-during-load'

  2. in real project as below code,

  • in option 1: the loading effect will work, but replace action would NOT work;
  • in option 2: the loading effect and replace aciton would work both;
    the mere diffrence between two options is put spinner tag out of option tag scope, as you can find below:
   `<view>
          <text>select choice:</text>
          <select-single name="choice">
              <option value="1" trigger="select" action="replace"  delay="300" show-during-load="ID_Spinner1" target="modal-uninterested" href="/behaviors/_target_sibling_fragment.xml" >
                  <text>option 1</text>
                  <spinner id="ID_Spinner1" color="red" hide="true" />
              </option>
              <option value="2" trigger="select" action="replace" delay="300" show-during-load="ID_Spinner2"  target="modal-uninterested" href="/behaviors/_target_sibling_fragment.xml" >
                  <text>option 2</text>
              </option>
              <spinner id="ID_Spinner2" color="red" hide="true" />
          </select-single>
      </view>
`

I checked above issue in real project on Android device(Android 10);

please help check, feel free if need any more information, thanks a lot.

Fix errors from temporarily disabled eslint rules

Several rules from eslint-plugin-hyperview were disabled when upgrading the plugin in #125

Re-enable the following rules in .eslintrc and fix the errors:

  • import/no-cycle
  • lines-between-class-members
  • no-else-return
  • no-restricted-globals
  • prefer-destructuring
  • react/destructuring-assignment
  • react/jsx-sort-props
  • react/no-access-state-in-setstate
  • sort-keys

How to use SafeAreaView for hyperview

The purpose of SafeAreaView is to render content within the safe area boundaries of a device, so in my code I just wrap Hyperview with the SafeAreaView component.

actual result:
the first page in Hyperview is good, it display all content in the safe area, but when navigate to next hyperview page, the SafeAreaView is not working

expected result:
content expected to render in the safe area for all page

what should I do to make it work for all page?

in the demo it just set the Header height=72, I think this is not a best practices, so any solutions for this? thanks

<style id="Header"
             alignItems="center"
             backgroundColor="white"
             borderBottomColor="#eee"
             borderBottomWidth="1"
             flexDirection="row"
             height="72"
             paddingLeft="24"
             paddingRight="24"
             paddingTop="24" />

this is what I do for my code

import { SafeAreaView } from 'react-native-safe-area-view';

export default function MyAwesomeApp() {
  return (
    <SafeAreaView style={{ flex: 1 }}>
      <Hyperview
        entrypointUrl={url}
        fetch={fetch}
        back={this.back}
        closeModal={this.closeModal}
        openModal={this.openModal}
        navigate={this.navigate}
        push={this.push}
      />
    </SafeAreaView>
  );
}

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.