Last active
March 18, 2021 17:23
-
-
Save kenwebb/d04eb6d9d8b428a6e980bf3b3c10d627 to your computer and use it in GitHub Desktop.
React[Native] Layout
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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