react-x11 0.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/styles.js ADDED
@@ -0,0 +1,189 @@
1
+ // Style props → yoga setters (layout) and paint metadata. Flat, ink-style
2
+ // props: <box flexDirection="row" padding={8} backgroundColor="#eee">.
3
+ // Numbers are pixels; strings like '50%' / 'auto' pass through to yoga.
4
+ // Yoga comes from ntk (>= 3.1.0) so renderer and ntk widgets share one
5
+ // WASM instance and enum set.
6
+ import { Yoga } from 'ntk';
7
+
8
+ export { Yoga };
9
+
10
+ const FLEX_DIRECTION = {
11
+ row: Yoga.FLEX_DIRECTION_ROW,
12
+ 'row-reverse': Yoga.FLEX_DIRECTION_ROW_REVERSE,
13
+ column: Yoga.FLEX_DIRECTION_COLUMN,
14
+ 'column-reverse': Yoga.FLEX_DIRECTION_COLUMN_REVERSE,
15
+ };
16
+
17
+ const JUSTIFY = {
18
+ 'flex-start': Yoga.JUSTIFY_FLEX_START,
19
+ center: Yoga.JUSTIFY_CENTER,
20
+ 'flex-end': Yoga.JUSTIFY_FLEX_END,
21
+ 'space-between': Yoga.JUSTIFY_SPACE_BETWEEN,
22
+ 'space-around': Yoga.JUSTIFY_SPACE_AROUND,
23
+ 'space-evenly': Yoga.JUSTIFY_SPACE_EVENLY,
24
+ };
25
+
26
+ const ALIGN = {
27
+ auto: Yoga.ALIGN_AUTO,
28
+ 'flex-start': Yoga.ALIGN_FLEX_START,
29
+ center: Yoga.ALIGN_CENTER,
30
+ 'flex-end': Yoga.ALIGN_FLEX_END,
31
+ stretch: Yoga.ALIGN_STRETCH,
32
+ baseline: Yoga.ALIGN_BASELINE,
33
+ 'space-between': Yoga.ALIGN_SPACE_BETWEEN,
34
+ 'space-around': Yoga.ALIGN_SPACE_AROUND,
35
+ };
36
+
37
+ const FLEX_WRAP = {
38
+ nowrap: Yoga.WRAP_NO_WRAP,
39
+ wrap: Yoga.WRAP_WRAP,
40
+ 'wrap-reverse': Yoga.WRAP_WRAP_REVERSE,
41
+ };
42
+
43
+ const POSITION = {
44
+ static: Yoga.POSITION_TYPE_STATIC,
45
+ relative: Yoga.POSITION_TYPE_RELATIVE,
46
+ absolute: Yoga.POSITION_TYPE_ABSOLUTE,
47
+ };
48
+
49
+ const DISPLAY = {
50
+ flex: Yoga.DISPLAY_FLEX,
51
+ none: Yoga.DISPLAY_NONE,
52
+ };
53
+
54
+ const OVERFLOW = {
55
+ visible: Yoga.OVERFLOW_VISIBLE,
56
+ hidden: Yoga.OVERFLOW_HIDDEN,
57
+ scroll: Yoga.OVERFLOW_SCROLL,
58
+ };
59
+
60
+ const pick = (map, value, name) => {
61
+ if (value === undefined) return undefined;
62
+ if (!(value in map)) {
63
+ throw new Error(
64
+ `react-x11: invalid ${name} "${value}" (expected one of ${Object.keys(map).join(', ')})`,
65
+ );
66
+ }
67
+ return map[value];
68
+ };
69
+
70
+ // Each entry: prop name -> (yogaNode, value) applier. `undefined` resets.
71
+ const LAYOUT_APPLIERS = {
72
+ width: (n, v) => n.setWidth(v),
73
+ height: (n, v) => n.setHeight(v),
74
+ minWidth: (n, v) => n.setMinWidth(v),
75
+ minHeight: (n, v) => n.setMinHeight(v),
76
+ maxWidth: (n, v) => n.setMaxWidth(v),
77
+ maxHeight: (n, v) => n.setMaxHeight(v),
78
+ flexDirection: (n, v) =>
79
+ n.setFlexDirection(
80
+ pick(FLEX_DIRECTION, v, 'flexDirection') ?? Yoga.FLEX_DIRECTION_COLUMN,
81
+ ),
82
+ justifyContent: (n, v) =>
83
+ n.setJustifyContent(
84
+ pick(JUSTIFY, v, 'justifyContent') ?? Yoga.JUSTIFY_FLEX_START,
85
+ ),
86
+ alignItems: (n, v) =>
87
+ n.setAlignItems(pick(ALIGN, v, 'alignItems') ?? Yoga.ALIGN_STRETCH),
88
+ alignSelf: (n, v) =>
89
+ n.setAlignSelf(pick(ALIGN, v, 'alignSelf') ?? Yoga.ALIGN_AUTO),
90
+ alignContent: (n, v) =>
91
+ n.setAlignContent(pick(ALIGN, v, 'alignContent') ?? Yoga.ALIGN_FLEX_START),
92
+ flexWrap: (n, v) =>
93
+ n.setFlexWrap(pick(FLEX_WRAP, v, 'flexWrap') ?? Yoga.WRAP_NO_WRAP),
94
+ flexGrow: (n, v) => n.setFlexGrow(v ?? 0),
95
+ flexShrink: (n, v) => n.setFlexShrink(v ?? 1),
96
+ flexBasis: (n, v) => n.setFlexBasis(v),
97
+ position: (n, v) =>
98
+ n.setPositionType(
99
+ pick(POSITION, v, 'position') ?? Yoga.POSITION_TYPE_RELATIVE,
100
+ ),
101
+ top: (n, v) => n.setPosition(Yoga.EDGE_TOP, v),
102
+ right: (n, v) => n.setPosition(Yoga.EDGE_RIGHT, v),
103
+ bottom: (n, v) => n.setPosition(Yoga.EDGE_BOTTOM, v),
104
+ left: (n, v) => n.setPosition(Yoga.EDGE_LEFT, v),
105
+ margin: (n, v) => n.setMargin(Yoga.EDGE_ALL, v),
106
+ marginTop: (n, v) => n.setMargin(Yoga.EDGE_TOP, v),
107
+ marginRight: (n, v) => n.setMargin(Yoga.EDGE_RIGHT, v),
108
+ marginBottom: (n, v) => n.setMargin(Yoga.EDGE_BOTTOM, v),
109
+ marginLeft: (n, v) => n.setMargin(Yoga.EDGE_LEFT, v),
110
+ padding: (n, v) => n.setPadding(Yoga.EDGE_ALL, v),
111
+ paddingTop: (n, v) => n.setPadding(Yoga.EDGE_TOP, v),
112
+ paddingRight: (n, v) => n.setPadding(Yoga.EDGE_RIGHT, v),
113
+ paddingBottom: (n, v) => n.setPadding(Yoga.EDGE_BOTTOM, v),
114
+ paddingLeft: (n, v) => n.setPadding(Yoga.EDGE_LEFT, v),
115
+ gap: (n, v) => n.setGap(Yoga.GUTTER_ALL, v ?? 0),
116
+ rowGap: (n, v) => n.setGap(Yoga.GUTTER_ROW, v ?? 0),
117
+ columnGap: (n, v) => n.setGap(Yoga.GUTTER_COLUMN, v ?? 0),
118
+ aspectRatio: (n, v) => n.setAspectRatio(v),
119
+ display: (n, v) =>
120
+ n.setDisplay(pick(DISPLAY, v, 'display') ?? Yoga.DISPLAY_FLEX),
121
+ overflow: (n, v) =>
122
+ n.setOverflow(pick(OVERFLOW, v, 'overflow') ?? Yoga.OVERFLOW_VISIBLE),
123
+ borderWidth: (n, v) => n.setBorder(Yoga.EDGE_ALL, v ?? 0),
124
+ };
125
+
126
+ // Props that only affect painting, not geometry.
127
+ const PAINT_PROPS = new Set([
128
+ 'backgroundColor',
129
+ 'borderColor',
130
+ 'borderRadius',
131
+ 'zIndex',
132
+ ]);
133
+
134
+ // Text style props. All affect measurement except color.
135
+ export const TEXT_LAYOUT_PROPS = new Set([
136
+ 'fontFamily',
137
+ 'fontSize',
138
+ 'fontWeight',
139
+ 'fontStyle',
140
+ 'textAlign',
141
+ 'lineHeight',
142
+ ]);
143
+
144
+ export const isLayoutProp = (name) =>
145
+ Object.prototype.hasOwnProperty.call(LAYOUT_APPLIERS, name);
146
+ export const isPaintProp = (name) => PAINT_PROPS.has(name);
147
+ export const isEventProp = (name) => /^on[A-Z]/.test(name);
148
+
149
+ /**
150
+ * Apply changed layout props to a yoga node.
151
+ * @returns true if any layout-affecting prop changed
152
+ */
153
+ export function applyLayoutStyle(yogaNode, props, oldProps = {}) {
154
+ let changed = false;
155
+ for (const key of Object.keys(LAYOUT_APPLIERS)) {
156
+ if (props[key] !== oldProps[key]) {
157
+ LAYOUT_APPLIERS[key](yogaNode, props[key]);
158
+ changed = true;
159
+ }
160
+ }
161
+ return changed;
162
+ }
163
+
164
+ /** @returns true if any paint-only prop changed */
165
+ export function paintPropsChanged(props, oldProps = {}) {
166
+ for (const key of PAINT_PROPS) {
167
+ if (props[key] !== oldProps[key]) return true;
168
+ }
169
+ return props.color !== oldProps.color;
170
+ }
171
+
172
+ /** Resolved text style (TextLayout base style) from props + inherited. */
173
+ export function textStyleFrom(props, inherited) {
174
+ return {
175
+ family: props.fontFamily ?? inherited.family,
176
+ size: props.fontSize ?? inherited.size,
177
+ weight: props.fontWeight ?? inherited.weight,
178
+ style: props.fontStyle ?? inherited.style,
179
+ color: props.color ?? inherited.color,
180
+ };
181
+ }
182
+
183
+ export const DEFAULT_TEXT_STYLE = {
184
+ family: 'sans-serif',
185
+ size: 14,
186
+ weight: 'normal',
187
+ style: 'normal',
188
+ color: 'black',
189
+ };
package/.npmignore DELETED
@@ -1,17 +0,0 @@
1
- lib-cov
2
- *.seed
3
- *.log
4
- *.csv
5
- *.dat
6
- *.out
7
- *.pid
8
- *.gz
9
- .DS_Store
10
-
11
- tmp
12
- pids
13
- logs
14
-
15
- node_modules
16
- npm-debug.log
17
-
package/combobox.jsx DELETED
@@ -1,69 +0,0 @@
1
- var React = require('./react-x11');
2
- var View = React.View;
3
- var Text = React.Text;
4
- var P = React.P;
5
-
6
- module.exports = function() {
7
-
8
- this.render = function() {
9
- function handleClick(pt) {
10
- console.log('handle click!', pt);
11
- this.setProps({
12
- style: {
13
- color: parseInt(0.1*(pt.x - this.props.left)*(pt.y - this.props.top))
14
- }
15
- });
16
- console.log(this.props.style);
17
- }
18
-
19
- var p = <P onClick={ handleClick }>
20
- Lorem ipsum foo bar blah blah
21
- Lorem ipsum foo bar blah blah
22
- Lorem ipsum foo bar blah blah
23
- Lorem ipsum foo bar blah blah
24
- Lorem ipsum foo bar blah blah
25
- Lorem ipsum foo bar blah blah
26
- Lorem ipsum foo bar blah blah
27
- Lorem ipsum foo bar blah blah
28
- Lorem ipsum foo bar blah blah
29
- Lorem ipsum foo bar blah blah
30
- Lorem ipsum foo bar blah blah
31
- Lorem ipsum foo bar blah blah
32
- Lorem ipsum foo bar blah blah
33
- Lorem ipsum foo bar blah blah
34
- Lorem ipsum foo bar blah blah
35
- Lorem ipsum foo bar blah blah
36
- </P>
37
-
38
- var haha = 1;
39
-
40
- var pp = <View style={ { color: 0xffffff } }>
41
- <View style={{ color: 0xffff00 }} >A lot of flexboxes with flexWrap=wrap </View>
42
- <View style={{ color: 0xf0ff0f }}>{ p }</View>
43
- </View>
44
-
45
- var content = <View style={ { flexDirection: 'column', color: 0xfefefe, justifyContent: 'space-between', alignItems: 'stretch' } }>
46
- <View test="foo" onMousemove={ function(ev) { console.log(ev.x, ev.y); } }>
47
- <Text text={ "haha " + haha }/>
48
- </View>
49
- <View foo="test" style={ { color: 0xffa0a0 } } onClick={ function() { console.log(this.props.foo); } }>
50
- Subview 0.1
51
- </View>
52
- <View foo="test" style={ { color: 0xa0a0a0, padding: 20, alignItems: 'stretch' } }>
53
- { p }
54
- <View foo="test" style={ { color: 0xffffff, padding: 25 } } onMousemove={ handleClick }>
55
- Subview 0.2.1
56
- </View>
57
- </View>
58
- </View>
59
-
60
- //setInterval( function() {
61
- // console.log('set haha to ' + haha);
62
- // haha++;
63
- // content.props.children[0].props.children[0].props.text = ''+ haha;
64
- //}, 1000);
65
-
66
-
67
- return content;
68
- }
69
- }
package/react-x11.js DELETED
@@ -1,119 +0,0 @@
1
- //var x11 = require('x11');
2
- //var React = {}
3
- //React.createConnection = function(cb) {
4
- // x11.createConnection();
5
- //};
6
-
7
- var clone = function(obj) {
8
- return JSON.parse(JSON.stringify(obj));
9
- };
10
-
11
- module.exports = {
12
- createElement: function() {
13
- //return arguments;
14
-
15
- var component = arguments[0];
16
- var props = arguments[1];
17
- var children = [];
18
- var ch;
19
- for (var i=2; i < arguments.length; ++i) {
20
- ch = arguments[i];
21
- if (typeof ch == 'string') {
22
- children.push(new module.exports.Text({ text: ch }));
23
- }
24
- else
25
- children.push(arguments[i]);
26
- }
27
- var c = new component(props, children);
28
- c.hitTest = function(pt) {
29
- var res = [];
30
- if (c.props && c.props.left <= pt.x && c.props.top <= pt.y && c.props.left + c.props.width >= pt.x && c.props.top + c.props.height >= pt.y ) {
31
- res.push(this);
32
- if (this.props && this.props.children) {
33
- for (var i=0; i < this.props.children.length; ++i) {
34
- var ch = this.props.children[i];
35
- if (ch && ch.hitTest) {
36
- var hits = ch.hitTest(pt);
37
- res = res.concat(hits);
38
- }
39
- }
40
-
41
- }
42
- }
43
- return res;
44
- }
45
-
46
- c.setProps = function(newProps) {
47
- var e = c;
48
- var needsUpdate = false;
49
- for (var key in newProps) {
50
- if (this.props[key] != newProps[key]) {
51
- this.props[key] = newProps[key];
52
- needsUpdate = true;
53
- }
54
- }
55
- this._needsUpdate = needsUpdate;
56
- };
57
- return c;
58
- },
59
- View: function(args, children) {
60
- if (!args)
61
- args = {};
62
- this.props = args;
63
- this.props.children = children;
64
- this.props.style = args.style || { color: 0xa0a0a0 };
65
- this.render = function() {
66
- return this;
67
- };
68
- this.draw = function(ctx) {
69
- console.log(this.props.style.color);
70
- //ctx.setForeground(this.props.style.color);
71
- ctx.fillRect(this.props.left, this.props.top, this.props.width, this.props.height, 0.5, 0.5, 0.5, 1);
72
- //ctx.setForeground(0);
73
- //ctx.rectangle(this.props);
74
- if (this.props.children) {
75
- this.props.children.forEach(function(c) {
76
- c.draw(ctx);
77
- });
78
- }
79
- };
80
- },
81
- Text: function Text(args) {
82
- this.fontHeight = 12;
83
- this.fontWidth = 5;
84
- this.props = args;
85
- //var width = ctx.measureText(this.props.text).width;
86
- var width = this.props.text.length*15;
87
- this.props.style = { margin: 5, width: width, height: 2*this.fontHeight };
88
- if (!this.props.text)
89
- this.props.text = '';
90
- this.render = function() {
91
- return this;
92
- };
93
- this.draw = function(ctx) {
94
- //ctx.setForeground(0);
95
- ctx.fillText(this.props.text, this.props.left, this.props.top + this.fontHeight);
96
- };
97
- },
98
-
99
- P: function(args, children) {
100
- this.props = args || {};
101
- this.props.style = this.props.style || { flexDirection: 'row', flexWrap: 'wrap' };
102
- this.props.p = children[0].props.text;
103
- this.props.children = this.props.p.split(' ').map( function(w) { return new module.exports.createElement(module.exports.Text, { text: w, onMousemove: function() { console.log(this.props.text);} }); });
104
- this.render = function() {
105
- return this;
106
- };
107
- this.draw = function(ctx) {
108
- //ctx.setForeground(0xfef0f0); //this.props.style.color);
109
- console.log('P', this.props);
110
- //ctx.fillRect(this.props);
111
- //ctx.rectangle(this.props);
112
- this.props.children.forEach(function(c) {
113
- //ctx.setForeground(0);
114
- //ctx.rectangle(c.props);
115
- c.draw(ctx);
116
- });
117
- };
118
- }
119
- };
package/test-canvas.js DELETED
@@ -1,98 +0,0 @@
1
- require('node-jsx').install();
2
-
3
- var ntk = require('ntk');
4
-
5
- ntk.createClient(main);
6
-
7
- var computeLayout = require('css-layout');
8
- var React = require('./react-x11');
9
- var ComboBox = require('./combobox.jsx');
10
-
11
- var clone = function(obj) {
12
- return JSON.parse(JSON.stringify(obj));
13
- };
14
-
15
- function unprops(node) {
16
- var props = clone(node.props);
17
- delete props.children;
18
- if (node.props.children)
19
- props.children = node.props.children.map(unprops);
20
-
21
- //console.log('UNPROPS:', props);
22
- return props;
23
- }
24
-
25
- function reflow(node, width, height) {
26
- var window = { style: { width: width, height: height, justifyContent: 'stretch', alignItems: 'stretch' }, children: [ unprops(node) ] };
27
- window.children[0].style.width = width;
28
- window.children[0].style.height = height;
29
- var layout = computeLayout(window);
30
- //console.log(layout);
31
- function applyLayout(node, layout, left, top) {
32
-
33
- //console.log(left, top, node);
34
- //console.log(JSON.stringify(layout, null, 2));
35
- //debugger
36
-
37
- node.props.width = layout.width;
38
- node.props.height = layout.height;
39
- node.props.left = layout.left + left;
40
- node.props.top = layout.top + top;
41
-
42
- if (node.props.children)
43
- for (var i=0; i < node.props.children.length; ++i) {
44
- applyLayout(node.props.children[i], layout.children[i], layout.left + left, layout.top + top);
45
- }
46
- }
47
- applyLayout({ props: { children: [node] } }, layout, 0, 0);
48
- }
49
-
50
- function main(err, app) {
51
- var pix = app.createPixmap({ depth: 24, width: 1000, height: 1000 });
52
- var mainwnd = app.createWindow({title: "Layout demo", pixmap: pix}).map();
53
- var rootEle = React.createElement(ComboBox, { foo: 'blah blah' });
54
-
55
- var ctx = pix.getContext('2d');
56
- var ctxWin = mainwnd.getContext('2d');
57
- var black = ctx.createSolidPicture(0, 0, 0, 1);
58
- ctx.setBackground(black);
59
- ctx.font = '8mm CourierNew';
60
-
61
- var rootNode;
62
- var prevW = 0;
63
- var prevH = 0;
64
- mainwnd.on('resize', function(ev) {
65
- if ( (ev.width != prevW) || (ev.height != prevH) ) {
66
- console.log([prevW, ev.width, prevH, ev.height]);
67
- rootNode = rootEle.render();
68
- reflow(rootNode, ev.width, ev.height);
69
- rootNode.draw(ctx);
70
- // TODO
71
- ctxWin.draw(ctx);
72
- prevW = ev.width;
73
- prevH = ev.height;
74
- }
75
- }).on('expose', function(ev) {
76
- ctxWin.draw(ctx);
77
- }).on('mousedown', function(ev) {
78
- if (!rootNode) return;
79
- // 1 build list of matching views
80
- // 2 check for handlers up
81
- var hits = rootNode.hitTest(ev);
82
- for (var i=1; i <= hits.length; i++) {
83
- var component = hits[hits.length - i];
84
- if (component.props.onClick) {
85
- component.props.onClick.call(component, ev);
86
- }
87
- }
88
- }).on('mousemove', function(ev) {
89
- if (!rootNode) return;
90
- var hits = rootNode.hitTest(ev);
91
- for (var i=1; i <= hits.length; i++) {
92
- var component = hits[hits.length - i];
93
- if (component.props.onMousemove) {
94
- component.props.onMousemove.call(component, ev);
95
- }
96
- }
97
- });
98
- }