Skip to content

Commit 90da337

Browse files
committed
Merge branch 'edge' of github.com:hyperstack-org/hyperstack into edge
2 parents 9e37c1f + bcf5ac5 commit 90da337

File tree

2 files changed

+84
-63
lines changed

2 files changed

+84
-63
lines changed

docs/dsl-client/hyper-component.md

Lines changed: 83 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,8 +1212,6 @@ Event names:
12121212

12131213
## Javascript Components
12141214

1215-
**TODO - improve this section**
1216-
12171215
Hyperstack gives you full access to the entire universe of JavaScript libraries and components directly within your Ruby code.
12181216

12191217
Everything you can do in JavaScript is simple to do in Ruby; this includes passing parameters between Ruby and JavaScript and even passing Ruby methods as JavaScript callbacks. See the JavaScript section for more information.
@@ -1222,9 +1220,9 @@ While it is quite possible to develop large applications purely in Hyperstack Co
12221220

12231221
Either way you are going to need to import Javascript components into the Hyperstack namespace. Hyperstack provides both manual and automatic mechanisms to do this depending on the level of control you need.
12241222

1225-
### Importing Components
1223+
### Importing React Components
12261224

1227-
Lets say you have an existing React Component written in javascript that you would like to access from Hyperstack.
1225+
Let's say you have an existing React Component written in Javascript that you would like to access from Hyperstack.
12281226

12291227
Here is a simple hello world component:
12301228

@@ -1254,75 +1252,70 @@ end
12541252

12551253
The `imports` directive takes a string (or a symbol) and will simply evaluate it and check to make sure that the value looks like a React component, and then set the underlying native component to point to the imported component.
12561254

1257-
### The dom_node method
1255+
### Importing Javascript or React Libraries
12581256

1259-
Returns the HTML dom_node that this component instance is mounted to. Typically used in the `after_mount` method to setup linkages to external libraries.
1257+
Importing and using React libraries from inside Hyperstack is very simple and very powerful. Any JavaScript or React based library can be accessible in your Ruby code.
12601258

1261-
Example:
1259+
Using Webpacker (or Webpack) there are just a few simple steps:
12621260

1263-
TODO
1261+
+ Add the library source to your project using `yarn` or `npm`
1262+
+ Import the JavaScript objects you require
1263+
+ Package your bundle with `webpack`
1264+
+ Use the JavaScript or React component as if it were a Ruby class
12641265

1265-
### Importing Libraries
1266+
Here is an example of setting up [Material UI](https://material-ui.com/):
12661267

1267-
Many React components come in libraries. The `ReactBootstrap` library is one example. You can import the whole library at once using the `React::NativeLibrary` class. Assuming that you have initialized `ReactBootstrap` elsewhere, this is how you would bring it into Hyperstack.
1268+
Firstly, you install the library:
12681269

1269-
```ruby
1270-
class RBS < React::NativeLibrary
1271-
imports 'ReactBootstrap'
1272-
end
1270+
```
1271+
// with yarn
1272+
yarn add @material-ui/core
1273+
1274+
// or with npm
1275+
npm install @material-ui/core
12731276
```
12741277

1275-
We can now access our bootstrap components as components defined within the RBS scope:
1278+
Next you import the objects you plan to us (or you can import the whole library)
12761279

12771280
```ruby
1278-
class Show < HyperComponent
1281+
# app/javascript/packs/hyperstack.js
12791282

1280-
def say_hello(i)
1281-
alert "Hello from number #{i}"
1282-
end
1283+
# to import the whole library
1284+
import * as Mui from '@material-ui/core';
1285+
global.Mui = Mui;
12831286

1284-
render RBS::Navbar, bsStyle: :inverse do
1285-
RBS::Nav() do
1286-
RBS::NavbarBrand() do
1287-
A(href: '#') { 'Hyperstack Showcase' }
1288-
end
1289-
RBS::NavDropdown(eventKey: 1, title: 'Things', id: :drop_down) do
1290-
(1..5).each do |n|
1291-
RBS::MenuItem(href: '#', key: n, eventKey: "1.#{n}") do
1292-
"Number #{n}"
1293-
end.on(:click) { say_hello(n) }
1294-
end
1295-
end
1296-
end
1297-
end
1298-
end
1287+
# or if you just want one component from the library
1288+
import Button from '@material-ui/core/Button';
1289+
global.Button = Button;
12991290
```
13001291

1301-
Besides the `imports` directive, `React::NativeLibrary` also provides a rename directive that takes pairs in the form `oldname => newname`. For example:
1292+
The run webpack to build your bundle:
13021293

1303-
```ruby
1304-
rename 'NavDropdown' => 'NavDD', 'Navbar' => 'NavBar', 'NavbarBrand' => 'NavBarBrand'
1294+
```
1295+
bin/webpack
13051296
```
13061297

1307-
`React::NativeLibrary` will import components that may be deeply nested in the library. For example consider a component was defined as `MyLibrary.MySubLibrary.MyComponent`:
1298+
Now you can use Material UI Components in your Ruby code:
13081299

13091300
```ruby
1310-
class MyLib < React::NativeLibrary
1311-
imports 'MyLibrary'
1301+
# if you imported the whole library
1302+
Mui.Button(variant: :contained, color: :primary) { "Click me" }.on(:click) do
1303+
alert 'you clicked the button!'
13121304
end
13131305

1314-
class App < React::NativeLibrary
1315-
render do
1316-
...
1317-
MyLib::MySubLibrary::MyComponent ...
1318-
...
1319-
end
1306+
# if you just imported the Button component
1307+
Button(variant: :contained, color: :primary) { "Click me" }.on(:click) do
1308+
alert 'you clicked the button!'
13201309
end
13211310
```
13221311

1323-
Note that the `rename` directive can be used to rename both components and sublibraries, giving you full control over the ruby names of the components and libraries.
1312+
Libraries used often with Hyperstack projects:
13241313

1325-
### Importing Webpack Images
1314+
+ [Material UI](https://material-ui.com/) Google's Material UI as React components
1315+
+ [Semantic UI](https://react.semantic-ui.com/) A React wrapper for the Semantic UI stylesheet
1316+
+ [ReactStrap](https://reactstrap.github.io/) Bootstrap 4 React wrapper
1317+
1318+
### Importing Image Assets via Webpack
13261319

13271320
If you store your images in app/javascript/images directory and want to display them in components, please add the following code to app/javascript/packs/application.js
13281321

@@ -1354,7 +1347,7 @@ Add the following helper
13541347

13551348
module ImagesImport
13561349
def img_src(filepath)
1357-
img_map = Native(`webpackImagesMap`)
1350+
img_map = Native(`webpackImagesMap`)
13581351
img_map["./#{filepath}"]
13591352
end
13601353
end
@@ -1377,22 +1370,55 @@ IMG(src: img_src('logo.png')) # app/javascript/images/logo.png
13771370
IMG(src: img_src('landing/some_image.png')) # app/javascript/images/landing/some_image.png
13781371
```
13791372

1373+
### The dom_node method
1374+
1375+
Returns the HTML dom_node that this component instance is mounted to. Typically used in the `after_mount` method to setup linkages to external libraries.
1376+
1377+
Example:
1378+
1379+
TODO - write example
13801380

1381-
### Auto Import
1381+
### The `as_node` and `to_n` methods
13821382

1383-
If you use a lot of libraries and are using a Javascript tool chain with Webpack, having to import the libraries in both Hyperstack and Webpack is redundant and just hard work.
1383+
Sometimes you need to create a Component without rendering it so you can pass it as a parameter of a method. This model is used often in the React world.
13841384

1385-
Instead you can opt-in for *auto importing* Javascript components into Hyperstack as you need them. Simply `require hyper-react/auto-import` immediately after you `require hyper-react`.
1385+
The example below is taken from Semantic UI, building a [Tab Component](https://react.semantic-ui.com/modules/tab/#types-basic) with multiple tabs:
13861386

1387-
Now you do not have to use component `imports` directive or `React::NativeLibrary` unless you need to rename a component.
1387+
Here is the Javascript example:
13881388

1389-
In Ruby all module and class names normally begin with an uppercase letter. However in Javascript this is not always the case, so the auto import will first try the Javascript name that exactly matches the Ruby name, and if that fails it will try the same name with the first character downcased. For example
1389+
```javascript
1390+
import React from 'react'
1391+
import { Tab } from 'semantic-ui-react'
13901392

1391-
`MyComponent` will first try `MyComponent` in the Javascript name space, then `myComponent`.
1393+
const panes = [
1394+
{ menuItem: 'Tab 1', render: () => <Tab.Pane>Tab 1 Content</Tab.Pane> },
1395+
{ menuItem: 'Tab 2', render: () => <Tab.Pane>Tab 2 Content</Tab.Pane> },
1396+
]
13921397

1393-
Likewise MyLib::MyComponent would match any of the following in the Javascript namespace: `MyLib.MyComponent`, `myLib.MyComponent`, `MyLib.myComponent`, `myLib.myComponent`
1398+
const TabExampleBasic = () => <Tab panes={panes} />
1399+
1400+
export default TabExampleBasic
1401+
```
13941402

1395-
*How it works: The first time Ruby hits a native library or component name, the constant value will not be defined. This will trigger a lookup in the javascript name space for the matching component or library name. This will generate either a new subclass of HyperComponent or React::NativeLibrary that imports the javascript object, and no further lookups will be needed.*
1403+
And here is the same example converted to Ruby:
1404+
1405+
```ruby
1406+
# notice we use .as_node to create the Component without rendering it
1407+
tab_1 = Sem.TabPane do
1408+
P { 'Tab 1 Content' }
1409+
end.as_node
1410+
1411+
tab_2 = Sem.TabPane do
1412+
P { 'Tab 2 Content' }
1413+
end.as_node
1414+
1415+
# notice how we use .to_n to convert the Ruby component to a native JS object
1416+
panes = [ {menuItem: 'Tab 1', render: -> { tab_1.to_n } },
1417+
{menuItem: 'Tab 2', render: -> { tab_2.to_n } }
1418+
]
1419+
1420+
Sem.Tab(panes: panes.to_n )
1421+
```
13961422

13971423
### Including React Source
13981424

@@ -1404,12 +1430,6 @@ However it gets a little tricky if you are using the react-rails gem. Each vers
14041430
14051431
```
14061432

1407-
### Using Webpack
1408-
1409-
Just a word on Webpack: If you a Ruby developer who is new to using Javascript libraries then we recommend using Webpack to manage javascript component dependencies. Webpack is essentially bundler for Javascript. Please see our Tutorials section for more information.
1410-
1411-
There are also good tutorials on integrating Webpack with existing rails apps a google search away.
1412-
14131433

14141434
## Elements and Rendering
14151435

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Hyperstack is evolving; we are improving it all the time. As much as we love Rub
5252
Please see the [ROADMAP][] file for more information.
5353

5454
[roadmap]: ROADMAP.md
55+
[current status]: current-status.md
5556

5657
## Contributing
5758

0 commit comments

Comments
 (0)