-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathdatatypes.card.js
409 lines (347 loc) · 9.63 KB
/
datatypes.card.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
import devboard from '../';
import single from 'webpack-hmr-singleton';
import React from 'react';
import { sourceLink } from './misc';
var definecard = devboard.ns('2. Datatypes');
sourceLink(definecard, __dirname, __filename);
var mdn = 'https://developer.mozilla.org/en-US/docs/Web/Javascript';
definecard(`
The body of a card can be many different things,
here are some examples:
`);
definecard('string',
`Strings are rendered as CommonMark`,
`
* [Strings](${mdn}/Reference/Global_Objects/String)
* [CommonMark](http://commonmark.org/)
***
# ⚡️ TADA ⚡️ #
`
);
definecard('number',
`Numbers are rendered as – unsuprisingly – *numbers*`,
42
);
definecard('function',
`Functions get called, and their result rendered`,
function() {
return `
~~~js
function() { return 'an example'; }
~~~
`;
}
);
definecard('function with state',
`Functions can also receive a \`card\` argument, which allows
them to hold some state like a React component.
* \`card.state\` - the current value of the card's state
* \`card.setState(fn)\` - update the card's state.
The initial state can be passed using the \`state\` option.
To pretty-print the current value, enable the \`inspect\` option.
~~~jsx
${require('!!raw!part?token=func-state!' + __filename)}
~~~
`,
// func-state
function(card) {
return (
<div>
<p>
<button onClick={() => card.setState({ n: 0 })}>
ZERO
</button>
<button onClick={() => card.setState(s => ({ n: s.n + 1 }))}>
INC
</button>
<button onClick={() => card.setState(s => ({ n: s.n - 1 }))}>
DEC
</button>
</p>
<p>
The current value of <kbd>n</kbd> is <kbd>{card.state.n}</kbd>
</p>
</div>
);
},
{
state: { n: 0 },
inspect: true
}
// func-state
);
definecard('State and Timers',
`When a card has state, you can also supply options for a function that will
be called at set intervals which can modify the state.
This is most useful for automatically showing the transition between two
states of rendering. A button to disable the tick will get added into the
footer of the card.
* \`onTick(card)\` - a function to be called each tick, receives card with:
* \`card.state\` - the current value of the card's state
* \`card.setState(fn)\` - update the card's state.
* \`tickInterval\` - the time between ticks in ms, defaults to 2s.
* \`tickAutoplay\` - should the timer autoplay, defaults to true
~~~jsx
${require('!!raw!part?token=state-timer!' + __filename)}
~~~
`,
// state-timer
function(card) {
var bg = ['#333', '#ccc'][card.state];
return (
<div style={{
width: 100, height: 50,
lineHeight: '50px',
margin: '0 auto',
textAlign: 'center',
border: '1px solid black',
transition: 'background-color 3s',
backgroundColor: bg,
color: 'white'
}}>
{bg}
</div>
);
},
{
state: 0,
onTick: function(card) { card.setState(n => (n + 1) % 2); },
tickInterval: 3000, tickAutoplay: false
}
// state-timer
);
// reset-comp
var ComponentWithSideEffects = React.createClass({
render() {
this.n = (this.n || 0) + 1;
return <h3>I've been rendered {this.n} times</h3>;
}
});
// reset-comp
definecard('Resetting Cards',
`You can always reset a card by renaming it, this will force it to be
re-created.
You can also enable the \`resettable\` option to have a reset button
appear in the card footer. This can be especially useful with components
which have internal state or side effects.
~~~jsx
${require('!!raw!part?token=reset-comp&indent=2!' + __filename)}
~~~
~~~jsx
${require('!!raw!part?token=resettable!' + __filename)}
~~~
`,
// resettable
function(card) {
return (
<div>
<ComponentWithSideEffects />
<button onClick={() => card.setState(x => ({ n: x.n * 2 }))}>
Double State
</button>
</div>
);
},
{ state: {n: 2}, inspect: true, resettable: true }
// resettable
);
definecard('***********');
import ListToggle from './ListToggle';
definecard('React',
`Any ReactElement is rendered into the card
~~~jsx
<ListToggle />
~~~
`,
<ListToggle />
);
definecard('React Row',
`You can use \`devboard.Row\` wrapper to horizontally space small components
along a single card. If the row is too long to fit it will wrap onto
additional lines
~~~jsx
${require('!!raw!part?token=react-row!' + __filename)}
~~~
`,
// react-row
<devboard.Row>
<ListToggle default="1" />
<ListToggle default="0" />
<ListToggle default="3" />
<ListToggle default="2" />
</devboard.Row>
// react-row
);
definecard('DOM Elements',
`If you're not using React, you can still make cards with Devboard.
You can use the \`DOMNode\` wrapper for this. You pass a function, and
you'll be given a DOM Node you can do whatever you want to. If you pass a
second argument, you can use it to perform any clean up tasks.
~~~js
${require('!!raw!part?token=dom-node!' + __filename)}
~~~
`,
// dom-node
devboard.DOMNode(
function render(node) {
node.innerHTML = '<h1>Who needs React anyway?</h1>';
console.log("Rendering", node.innerHTML);
},
function cleanUp(node) {
console.log("Clearing", node.innerHTML);
}
)
// dom-node
);
definecard('DOM Elements with State',
`You can also combine the DOM Node helper with a function for state.
It's up to you to make sure this function is able to cleanly update from one
state to the next.
~~~js
${require('!!raw!part?token=dom-state!' + __filename)}
~~~
`,
// dom-state
function(card) {
return devboard.DOMNode(
function render(node) {
node.innerHTML = (
'<button>I can count to: ' +
card.state +
'</button>'
);
node.onclick = () => card.setState(n => n + 1);
}
);
},
{ state: 0 }
// dom-state
);
definecard('***********');
definecard('RegExp',
`Regular expressions also get displayed neatly.
If you type into the box, you can test what it matches.`,
/^([de]{2}v)(c|bo|ard){2}s?/
);
definecard('Date',
`Javascript date objects get converted to a readable form`,
new Date()
);
definecard(
`Datatype rendering is powered by [inspect-x]. This handles most built-in
Javascript datatypes, as well as any custom types which implement their own
\`inspect()\` method.
[inspect-x]: https://github.com/Xotic750/inspect-x
`
);
definecard('Array',
`Arrays get displayed neatly with some colour`,
[ 5, 6, 7, 8 ]
);
definecard('object',
`Ordinary JS objects also get displayed neatly with some colour`,
{ a: 1, b: 2, c: 3 }
);
if (typeof Set === 'function') {
definecard('ES6 Set',
`ES6 Sets get displayed neatly with some colour`,
new Set([5, 7, 11, 13, 17])
);
}
if (typeof Map === 'function') {
definecard('ES6 Map',
`ES6 Maps get displayed neatly with some colour`,
new Map([['a', 1], ['b', 2], [3, 'c']])
);
}
definecard('Large object formatting',
`Larger objects get formatted reasonably neatly with line-breaks`,
{
a: {
123: 456,
c: {
d: {
foo: "bar"
}
}
},
b: {
123: 456,
foo: {
baz: [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1e10,
"and", "some", "other", "related", "stuff"
]
},
plus: (x => typeof Map === 'function' ? new Map(x) : x)([
["key", "val"],
["key2", "val2"],
["key3", 999],
["key4", 1e7],
["key5", 9 * 9 * 9],
["key6", 24 * 3600],
])
}
}
);
definecard('Working with atoms',
`Devboard can also work with data which changes, it uses [js-atom]
as the wrapper to co-ordinate these changes.
To help make things easier the \`createAtom\` function is exposed
on the \`devboard\` module:
~~~js
var atom = devboard.atom({ stuff: 123 });
~~~
[js-atom]: https://github.com/cjohansen/js-atom
`,
null,
{ frame: false, title: false }
);
// make-atom
var atom1 = single(module, 'atom1', () => {
var atom = devboard.atom({ tick: 0 });
setInterval(
() => atom.swap(a => ({ tick: a.tick + 1 })),
1000
);
return atom;
});
// make-atom
definecard('atom',
`[Atoms][js-atom] can be rendered directly, which will attach a
subscription and re-render whenever the value changes.
This is done via duck typing on the \`deref()\`, \`addWatch()\` and
\`removeWatch()\` methods, so anything that looks like an atom
should work.
~~~js
${require('!!raw!part?token=make-atom!' + __filename)}
definecard('atom', '... description ...', atom1);
~~~
[js-atom]: https://github.com/cjohansen/js-atom
`,
atom1
);
definecard('sharing atoms',
`Atoms can be shared between cards. This can be very useful to
create an ad-hoc control panel for another card.
When the \`state\` option is detected to be an atom, the card
will subscribe to changes. This can also be combined with \`inspect\`
~~~jsx
var single = require('webpack-hmr-singleton');
${require('!!raw!part?token=shared-atoms!' + __filename)}
~~~
`
);
// shared-atoms
var sharedAtom = single(module, 'sharedAtom', () => devboard.atom(0));
definecard('shared-atom', sharedAtom);
definecard('shared-atom-render', ({ state }) => (
<h1>Value: {state.deref()}</h1>
), { state: sharedAtom, inspect: true });
definecard('shared-atom-inc', ({ state }) => (
<button onClick={() => state.swap(n => n + 1)}>INC</button>
), { state: sharedAtom });
definecard('shared-atom-dec', ({ state }) => (
<button onClick={() => state.swap(n => n - 1)}>DEC</button>
), { state: sharedAtom });
// shared-atoms