Skip to content

Instantly share code, notes, and snippets.

@kenwebb
Last active March 18, 2021 17:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenwebb/d04eb6d9d8b428a6e980bf3b3c10d627 to your computer and use it in GitHub Desktop.
Save kenwebb/d04eb6d9d8b428a6e980bf3b3c10d627 to your computer and use it in GitHub Desktop.
React[Native] Layout
<?xml version="1.0" encoding="UTF-8"?>
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Thu Mar 18 2021 13:22:48 GMT-0400 (Eastern Daylight Time)-->
<XholonWorkbook>
<Notes><![CDATA[
Xholon
------
Title: React[Native] Layout
Description:
Url: http://www.primordion.com/Xholon/gwt/
InternalName: d04eb6d9d8b428a6e980bf3b3c10d627
Keywords:
My Notes
--------
March 15, 2021
This is a simple Xholon-based tool to explore layouts in React and React Native, especially flexbox.
I can use the Xholon graphviz exporter to display the clustered structure.
Graphviz
--------
/*
Automatically generated by Xholon version 0.9.1, using org.primordion.ef.Xholon2Graphviz.java
Mon Mar 15 10:28:33 GMT-400 2021 1615818513505
model: React[Native] Layout
www.primordion.com/Xholon
To view this file, use Graphviz dot|fdp|neato|twopi|circo|sfdp from http://www.graphviz.org/
For example, to generate an SVG file:
dot -Tsvg -O div_50_1615818513505.gv
Alternatively try one of these:
dot -Tsvg -O div_50_1615818513505.gv
dot -Tsvg -O -Grankdir=LR div_50_1615818513505.gv
fdp -Tsvg -O div_50_1615818513505.gv
neato -Tsvg -O div_50_1615818513505.gv
circo -Tsvg -O div_50_1615818513505.gv
Or use one of: -Tgif -Tjpg -Tpdf -Tpng -Txdot -Txlib
See also: http://www.webgraphviz.com/
See also: http://rise4fun.com/agl/
To repeat this Xholon export:
$wnd.xh.xport("Graphviz", $wnd.xh.root().parent().xpath("Chameleon/PhysicalSystem/div"), '{"gvFileExt":".gv","gvGraph":"digraph","layout":"dot","edgeOp":"->","gvCluster":"cluster","shouldShowStateMachineEntities":false,"filter":"--Behavior,Script","nameTemplateNodeId":"^^^^i^","nameTemplateNodeLabel":"R^^^^^","shouldQuoteLabels":false,"shouldShowLinks":false,"shouldShowLinkLabels":false,"shouldSpecifyLayout":false,"maxLabelLen":-1,"shouldColor":true,"defaultNodeColor":"#f0f8ff","bgGraphColor":"white","shouldSpecifyShape":true,"shape":"box","shouldSpecifySize":true,"size":"22","shouldSpecifyFontname":false,"fontname":"\"Courier New\"","shouldSpecifyArrowhead":true,"arrowhead":"vee","shouldSpecifyStylesheet":true,"stylesheet":"Xholon.css","shouldSpecifyRankdir":true,"rankdir":"RL","shouldDisplayGraph":true,"outputFormat":"svg"}');
*/
digraph 50 {
graph [label=div,id="div",stylesheet="Xholon.css",rankdir=RL,size=22,compound=true,bgcolor=white]
node [style=filled,fillcolor="#f0f8ff",shape=box]
edge [arrowhead=vee]
51 [label=header id="div/header"]
52 [label=nav id="div/nav"]
subgraph cluster53 { label=main id="div/main"
subgraph cluster54 { label=article id="div/main/article"
55 [label=section id="div/main/article/section[1]"]
56 [label=section id="div/main/article/section[2]"]
57 [label=aside id="div/main/article/aside"]
}
}
58 [label=footer id="div/footer"]
}
React Native app
----------------
import React from 'react';
import { Text, View, StyleSheet } from 'react-native';
const Cat = () => {
return (
<View style={[styles.view, {backgroundColor: "pink"}]}>
<View style={[styles.view, {backgroundColor: "red"}]}>
<Text>One</Text>
</View>
<View style={[styles.view, {backgroundColor: "cyan"}]}>
<View style={[styles.view, {backgroundColor: "orange"}]}>
<Text>Two</Text>
</View>
<View style={[styles.view, {backgroundColor: "yellow"}]}>
<Text>Three</Text>
</View>
<Text>Four</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
view: {borderWidth: 1, margin: 2}
});
export default Cat;
RN app
------
import React from 'react';
import { Text, View, StyleSheet } from 'react-native';
const Cat = () => {
return (
<View style={[styles.view, {backgroundColor: "#ff0000", flexDirection: "column", justifyContent: "flex-start", alignItems: "stretch", flexWrap: "nowrap"}]}>
<Text>Zero Dogs</Text>
<View style={[styles.view, {backgroundColor: "#ed3600", flexDirection: "column", justifyContent: "flex-start", alignItems: "stretch", flexWrap: "nowrap"}]}>
<Text>One Dog</Text>
</View>
<View style={[styles.view, {backgroundColor: "#da4b00", flexDirection: "column", justifyContent: "flex-start", alignItems: "stretch", flexWrap: "nowrap"}]}>
<View style={[styles.view, {backgroundColor: "#c85900", flexDirection: "column", justifyContent: "flex-start", alignItems: "stretch", flexWrap: "nowrap"}]}>
<Text>2 Dogs</Text>
</View>
<View style={[styles.view, {backgroundColor: "#b56300", flexDirection: "row", justifyContent: "space-between", alignItems: "stretch", flexWrap: "nowrap"}]}>
<Text>3 Dogs</Text>
<Text>4 Dogs</Text>
<Text>5 Dogs</Text>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
view: {borderWidth: 1, margin: 5}
});
export default Cat;
d3 colors
---------
(() => {
var i = d3.interpolateNumber(10, 20);
i(0.0); // 10
i(0.2); // 12
i(0.5); // 15
i(1.0); // 20
d3.interpolateLab("steelblue", "brown")(0.5);
const ntrpcolors = d3.interpolateLab("red", "purple")
const size = 7
const colors = Array(size).fill(0).map((item, index) => ntrpcolors(index / (size-1)))
console.log(colors)
)()
References
----------
(1) Web Design Playground, book by Christina Truong
especially chapters 11 and 12
"When you work with flexbox, you work with two kinds of page objects: containers and items" ch 12
() https://christinatruong.com
() https://reactnative.dev/docs/flexbox
() https://reactnative.dev/docs/intro-react
React Fundamentals
I can test my View layouts inside any of the examples on this page, such as "Your first component"
() https://reactnative.dev/docs/components-and-apis
() https://reactnative.dev/docs/layout-props
]]></Notes>
<_-.XholonClass>
<PhysicalSystem/>
<Container>
<!-- React, HTML -->
<div/>
<body/>
<p/>
<header/>
<nav/>
<main/>
<article/>
<section/>
<aside/>
<footer/>
<!-- React Native -->
<View/>
<ScrollView/>
<!-- etc. -->
</Container>
<Item>
<!-- React Native -->
<!-- Basic Components -->
<Text superClass="Attribute_String"/>
<Image/>
<TextInput/>
<!-- User Interface -->
<Button/>
<Switch/>
<TouchableOpacity/>
<!-- etc. -->
</Item>
<StyleSheet/>
<Style superClass="Attribute_String"/>
<StartContent superClass="Attribute_String"/>
<EndContent superClass="Attribute_String"/>
<ReactApp/>
<ReactNativeApp/>
<!-- testing visit(), see 568ffc4faf650b8e8ef4317bc0bc561b -->
<VisitTest superClass="script"/>
<Example/>
<Block/>
</_-.XholonClass>
<xholonClassDetails>
</xholonClassDetails>
<PhysicalSystem>
<!-- an HTML page/layout, that could be part of a React application -->
<div>
<header/>
<nav/>
<main>
<article>
<section/>
<section/>
<aside/>
</article>
</main>
<footer/>
</div>
<!-- a React-Native page/layout -->
<ReactNativeApp roleName="one" active="false">
<View>
<Text>Zero Dogs</Text>
<View>
<Text>One Dog</Text>
</View>
<View>
<View>
<Text>2 Dogs</Text>
<TouchableOpacity>
<Text>Click me</Text>
</TouchableOpacity>
</View>
<View>
<Text>3 Dogs</Text>
<Text>4 Dogs</Text>
<Text>5 Dogs</Text>
</View>
</View>
</View>
</ReactNativeApp>
<ReactNativeApp roleName="GWP Query" active="true">
<StartContent>
import React from 'react';
import { Text, View, TouchableOpacity, StyleSheet } from 'react-native';
const Dragon = () => {
return (
</StartContent>
<View roleName="outer">
<Style>{"backgroundColor":"#ffffff","justifyContent":"space-between"}</Style>
<View roleName="head">
<Style>{"flexDirection":"row","justifyContent":"flex-end","alignItems":"center"}</Style>
<View styleKey="view2">
<Style>{"flex": 1,"justifyContent":"flex-start","alignItems":"center"}</Style>
<Text>Flower Search</Text>
<Text>241 results</Text>
</View>
<TouchableOpacity>
<Text> </Text>
<Text>Done</Text>
</TouchableOpacity>
</View>
<View roleName="body" multiplicity="7">
<Style>{"flexDirection": "row", "justifyContent": "space-between"}</Style>
<Text>text</Text><TouchableOpacity><Text>button</Text></TouchableOpacity>
</View>
</View>
<EndContent>
);
}
const styles = StyleSheet.create({
view: {borderWidth: 1, padding: 5, margin: 5},
view2: {borderWidth: 0, margin: 5}
});
export default Dragon;
</EndContent>
</ReactNativeApp>
<!-- in the above, "head" should be:
the following is a goodstart:
<View style={[styles.view, {backgroundColor: "#fa1c00", flexDirection: "row", justifyContent: "flex-end", alignItems: "center", flexWrap: "nowrap"}]}>
<Text> </Text>
<View style={[styles.view2, {flex: 1, backgroundColor: "#f42900", flexDirection: "column", justifyContent: "flex-start", alignItems: "center", flexWrap: "nowrap"}]}>
<Text>Flower Search</Text>
<Text>241 results</Text>
</View>
<TouchableOpacity>
<Text> </Text>
<Text>Done</Text>
</TouchableOpacity>
</View>
with styles:
const styles = StyleSheet.create({
view: {borderWidth: 1, padding: 5, margin: 5},
view2: {borderWidth: 0, margin: 5}
});
-->
<!--<Example roleName="two">
<Block multiplicity="5"/>
<VisitTest roleName="zwei" initval="0"><![CDATA[
var vstee, count;
var beh = {
postConfigure: function() {
vstee = this.cnode;
vstee.println(vstee);
vstee.println(vstee.initval);
count = vstee.initval;
this.cnode.parent().visit(vstee);
vstee.println(vstee.name() + " count: " + count);
this.cnode.remove();
},
visit: function(visitor) {
vstee.println(vstee.name() + " was visited by " + visitor);
count++;
return true;
}
}
//# sourceURL=zwei.js
]]></VisitTest>
</Example>-->
</PhysicalSystem>
<ReactNativeAppxbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
// NOTE: visit() won't work because I don't have a way to write the end tags; I need access to the recursion as it occurs
var vstee, count = 0, beh = {
postConfigure: function() {
vstee = this.cnode;
vstee.parent().first().visit(vstee);
vstee.println(vstee.name() + " count: " + count);
this.cnode.remove();
},
visit: function(visitor) {
vstee.println(vstee.name() + " was visited by " + visitor);
count++;
return true;
}
}
//# sourceURL=ReactNativeAppbehavior.js
]]></ReactNativeAppxbehavior>
<ReactNativeAppbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[
var me, count = 0, ntrpcolors, colors, colorix = 0, jsxStr = "", indents, beh = {
postConfigure: function() {
me = this.cnode;
if (me.parent().active === "true") {
count = me.parent().first().next().numChildren(true) + 1;
ntrpcolors = $wnd.d3.interpolateLab("red", "green");
colors = Array(count).fill(0).map((item, index) => ntrpcolors(index / (count-1)))
indents = [" ", " ", " ", " ", " "];
this.writeNode(me.parent().first(), 0);
me.println(jsxStr);
}
this.cnode.remove();
},
writeNode: function(node, level) {
if (node) {
switch (node.xhc().name()) {
case "View": this.writeViewNode(node, level); break;
case "Text": this.writeTextNode(node, level); break;
case "TouchableOpacity": this.writeTouchableOpacityNode(node, level); break;
case "StartContent": jsxStr += node.text() + "\n"; break;
case "EndContent": jsxStr += node.text() + "\n"; break;
default: break;
}
if (node.next()) {
this.writeNode(node.next(), level);
}
}
},
writeViewNode: function(node, level) {
const dstyle = {backgroundColor: `${colors[colorix++]}`, flexDirection: "column", justifyContent: "flex-start", alignItems: "stretch", flexWrap: "nowrap"};
const style = node.first().xhc().name() === "Style" ? Object.assign(dstyle, JSON.parse(node.first().remove().text())) : dstyle
jsxStr += `${indents[level]}<View style={[styles.${node.styleKey || "view"}, ${JSON.stringify(style)}]}>\n`;
this.writeNode(node.first(), level+1);
jsxStr += `${indents[level]}</View>\n`
},
writeTextNode: function(node, level) {
jsxStr += `${indents[level]}<Text>${node.text() ? node.text() : " "}</Text>\n`;
},
writeTouchableOpacityNode: function(node, level) {
jsxStr += `${indents[level]}<TouchableOpacity>\n`;
this.writeNode(node.first(), level+1);
jsxStr += `${indents[level]}</TouchableOpacity>\n`
}
}
//# sourceURL=ReactNativeAppbehavior.js
]]></ReactNativeAppbehavior>
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml,
<svg width="100" height="50" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Block</title>
<rect id="PhysicalSystem/ReactNativeApp" fill="#98FB98" height="50" width="50" x="25" y="0"/>
<g>
<title>Height</title>
<rect id="PhysicalSystem/ReactNativeApp/*" fill="#6AB06A" height="50" width="10" x="80" y="0"/>
</g>
</g>
</svg>
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient>
</XholonWorkbook>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment