",
18 | "license": "ISC",
19 | "devDependencies": {
20 | "autoprefixer-loader": "^3.1.0",
21 | "babel-loader": "^5.3.3",
22 | "cpy": "^3.4.1",
23 | "css-loader": "^0.21.0",
24 | "exports-loader": "^0.6.2",
25 | "extract-text-webpack-plugin": "^0.8.2",
26 | "firebase-tools": "^2.0.2",
27 | "http-server": "^0.8.5",
28 | "less-loader": "^2.2.0",
29 | "normalize.css": "^3.0.3",
30 | "source-map-loader": "^0.1.5",
31 | "style-loader": "^0.13.0",
32 | "webpack": "^1.12.1",
33 | "webpack-dev-server": "^1.10.1"
34 | },
35 | "dependencies": {
36 | "babel-runtime": "^5.8.20",
37 | "decko": "^1.1.0",
38 | "material-design-lite": "^1.0.5",
39 | "object-assign": "^4.0.1",
40 | "preact": "^1.5.1"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/components/app.js:
--------------------------------------------------------------------------------
1 | import { h, Component } from 'preact';
2 | import { bind } from 'decko';
3 | import assign from 'object-assign';
4 | import { Layout } from 'preact-mdl';
5 | import Header from './header';
6 | import Sidebar from './sidebar';
7 | import Main from './main';
8 |
9 | const DEMO = 'https://github.com/documentationjs/documentation/blob/master/test/fixture/class.output.json';
10 |
11 | export default class App extends Component {
12 | componentDidMount() {
13 | let url = (location.hash || '').substring(1);
14 | this.load(url || DEMO);
15 | }
16 |
17 | @bind
18 | load(url) {
19 | let resolvedUrl = url;
20 |
21 | // convert github URLs:
22 | let gh = resolvedUrl.match(/^https?:\/\/github\.com\/([^/]+\/[^/]+)\/blob\/(.+)$/i);
23 | if (gh) resolvedUrl = `https://raw.githubusercontent.com/${gh[1]}/${gh[2]}`;
24 |
25 | // convert gist URLs:
26 | let gist = resolvedUrl.match(/^https?:\/\/gist\.github\.com\/(.+)$/i);
27 | if (gist) resolvedUrl = `https://gist.githubusercontent.com/${gist[1]}/raw`;
28 |
29 | fetch(resolvedUrl)
30 | .catch( error => this.setState({ error }) )
31 | .then( r => r.json() )
32 | .then( docs => {
33 | assign(docs, { url, resolvedUrl });
34 | console.log(docs);
35 | this.setState({ docs, error:null });
36 | });
37 | }
38 |
39 | @bind
40 | go(to) {
41 | if (to==='/home') return this.setState({ error:null, symbol:null });
42 |
43 | let { docs } = this.state,
44 | symbol = docs.filter( s => s.name.match(to) )[0],
45 | error = symbol ? null : `Symbol "${to}" not found`;
46 | this.setState({ error, symbol });
47 | }
48 |
49 | render({}, { error, docs, symbol }) {
50 | let actions = { go:this.go, load:this.load },
51 | ctx = { error, docs, symbol, actions };
52 | return (
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | );
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/components/doc-member.js:
--------------------------------------------------------------------------------
1 | import assign from 'object-assign';
2 | import { h } from 'preact';
3 |
4 | const NONE = {};
5 |
6 | function getType(type=NONE, nameOnly=false) {
7 | let name = type.expression && type.expression.name || type.name;
8 | if (nameOnly) return name;
9 | if (type.type==='TypeApplication') {
10 | return `${name}<${type.applications.map(a=>a.name).join(', ')}>`;
11 | }
12 | return name;
13 | }
14 |
15 | let normalizeParams = params => params.reduce( (acc, p) => {
16 | let v = acc.map[p.name];
17 | if (!v) acc.params.push( v=acc.map[p.name]={} );
18 | assign(v, p);
19 | return acc;
20 | }, { map:{}, params:[] }).params;
21 |
22 |
23 | export default ({ member:{kind, name, description, params=[], returns} }) => {
24 | let doc = [],
25 | isFunction = kind==='function';
26 |
27 | if (params.length) {
28 | isFunction = true;
29 | doc.push(
30 |
31 |
Parameters
32 | { normalizeParams(params).map( p => (
33 |
34 | )) }
35 |
36 | );
37 | }
38 |
39 | if (Array.isArray(returns)) returns = returns[0];
40 | if (returns) doc.push(
41 |
42 |
Returns
43 |
44 |
45 | );
46 |
47 | return (
48 |
49 |
{ name }{ isFunction ? ({ params.map(p=>p.name).join(', ') }) : null }
50 |
{ description }
51 | { doc }
52 |
53 | );
54 | };
55 |
56 |
57 |
58 | const DocParam = ({ type='argument', param }) => {
59 | let properties = null;
60 | if (param.properties) {
61 | properties = (
62 |
63 |
Properties:
64 |
{ param.properties.map( ({name,...p}) => (
65 |
66 | )) }
67 |
68 | );
69 | }
70 |
71 | let { name } = param;
72 | if (param.type && param.type.type==='OptionalType') {
73 | name = `[${name}${param.default?('='+param.default):''}]`;
74 | }
75 |
76 | return (
77 |
78 | -
79 |
{ getType(param.type) }
{ name }
80 |
81 | - { param.description }{ properties }
82 |
83 | );
84 | };
85 |
--------------------------------------------------------------------------------
/src/components/doc-symbol.js:
--------------------------------------------------------------------------------
1 | import { h } from 'preact';
2 | import { Card } from 'preact-mdl';
3 | import DocMember from './doc-member';
4 |
5 | export default ({ docs, symbol, ...props }) => {
6 | let type = symbol.kind || symbol.type;
7 | return (
8 |
9 |
10 |
11 | { type }
12 | { symbol.name }
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | { Object.keys(symbol.members || {}).map( type => (
22 | symbol.members[type].length ? (
23 |
24 |
{ type }
25 |
{ symbol.members[type].map( member => (
26 |
27 | )) }
28 |
29 | ) : null
30 | )) }
31 |
32 |
33 | );
34 | };
35 |
--------------------------------------------------------------------------------
/src/components/header.js:
--------------------------------------------------------------------------------
1 | import { h } from 'preact';
2 | import { Layout, TextField } from 'preact-mdl';
3 |
4 | export default ({ docs, actions:{ go, load } }) => (
5 |
6 |
7 |
8 | go('/home') }>Docs
9 |
10 |
11 | e.keyCode===13 ? load(e.target.value) : null }
16 | value={ docs && docs.url } />
17 |
18 |
19 | );
20 |
--------------------------------------------------------------------------------
/src/components/main.js:
--------------------------------------------------------------------------------
1 | import { h } from 'preact';
2 | import { Layout, Card, Icon } from 'preact-mdl';
3 | import DocSymbol from './doc-symbol';
4 |
5 | export default ({ error, docs, symbol }) => {
6 | let content = [];
7 |
8 | if (error) {
9 | content.push(
10 |
11 |
12 | Error
13 |
14 |
15 | { String(error) }
16 | { String(error.stack) }
17 |
18 |
19 | );
20 | }
21 | else if (symbol) {
22 | content.push(
23 |
24 | );
25 | }
26 | else {
27 | content.push(
28 |
29 |
30 | Documentation
31 |
32 |
33 |
34 |
35 |
36 | Paste your JSON
documentation URL into the box above to get started.
37 |
38 |
39 |
53 |
54 |
55 |
56 | Made with by developit.
57 | Built with Preact.
58 |
59 |
60 | );
61 | }
62 |
63 | return (
64 |
65 | { content }
66 |
67 | );
68 | };
69 |
--------------------------------------------------------------------------------
/src/components/sidebar.js:
--------------------------------------------------------------------------------
1 | import { h } from 'preact';
2 | import { Layout, Navigation } from 'preact-mdl';
3 |
4 | export default ({ docs=[], actions }) => (
5 |
6 | Symbols
7 | { docs.map( ({ name, kind }) => (
8 | actions.go(name) }>
11 | { name }
12 | { kind }
13 |
14 | ))}
15 |
16 | );
17 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Documentation Viewer
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import './style/index.less';
2 | import { h, render } from 'preact';
3 | import App from './components/app';
4 |
5 | render(, document.body);
6 |
--------------------------------------------------------------------------------
/src/lib/preact-mdl.js:
--------------------------------------------------------------------------------
1 | import { h, Component } from 'preact';
2 | import mdl from 'exports?componentHandler!material-design-lite/material.js';
3 |
4 | // const mdl = window.componentHandler;
5 |
6 | const RIPPLE_CLASS = 'js-ripple-effect';
7 | const MDL_PREFIX = s => `mdl-${s}`;
8 |
9 | let uidCounter = 1;
10 | let uid = () => ++uidCounter;
11 |
12 | let extend = (base, props) => {
13 | for (let i in props) if (props.hasOwnProperty(i)) base[i] = props[i];
14 | return base;
15 | };
16 |
17 | let propMaps = {
18 | disabled({ attributes }) {
19 | if (attributes.hasOwnProperty('disabled') && !attributes.disabled) {
20 | attributes.disabled = null;
21 | }
22 | },
23 | badge({ attributes }) {
24 | attributes['data-badge'] = attributes.badge;
25 | delete attributes.badge;
26 | attributes.class += (attributes.class ? ' ' : '') + 'mdl-badge';
27 | },
28 | active({ attributes }) {
29 | if (attributes.active) {
30 | attributes.class += (attributes.class ? ' ' : '') + 'is-active';
31 | }
32 | },
33 | shadow({ attributes }) {
34 | let d = parseFloat(attributes.shadow)|0,
35 | c = attributes.class.replace(/\smdl-[^ ]+--shadow\b/g,'');
36 | attributes.class = c + (c ? ' ' : '') + `mdl-shadow--${d}dp`;
37 | }
38 | };
39 |
40 | export class MaterialComponent extends Component {
41 | component = 'none';
42 | js = false;
43 | ripple = false;
44 | mdlClasses = null;
45 | upgradedBase = null;
46 |
47 | mdlRender(props) {
48 | return { props.children }
;
49 | }
50 |
51 | render(props, state) {
52 | let r = this.mdlRender(props, state);
53 | if (this.nodeName) r.nodeName = this.nodeName;
54 | if (!r.attributes) r.attributes = {};
55 | r.attributes.class = this.createMdlClasses(props).concat(r.attributes.class || []).join(' ');
56 | for (let i in propMaps) if (propMaps.hasOwnProperty(i)) {
57 | if (props.hasOwnProperty(i)) propMaps[i](r);
58 | }
59 | if (this.base && this.upgradedBase) {
60 | this.preserveMdlDom(this.base, r);
61 | }
62 | return r;
63 | }
64 |
65 | // Copy some transient properties back out of the DOM into VDOM prior to diffing so they don't get overwritten
66 | preserveMdlDom(base, r) {
67 | if (!base || !base.hasAttribute || !r) return;
68 |
69 | let c = base.childNodes,
70 | persist = [
71 | 'mdl-js-ripple-effect--ignore-events',
72 | 'mdl-js-ripple-effect',
73 | 'is-upgraded',
74 | 'is-dirty'
75 | ],
76 | v = base.getAttribute('data-upgraded'),
77 | a = r.attributes,
78 | foundRipple = false;
79 |
80 | if (!a) a = {};
81 |
82 | if (v) {
83 | a['data-upgraded'] = v;
84 | upgradeQueue.add(base);
85 | }
86 |
87 | if (base.hasAttribute('ink-enabled')) {
88 | if (!r.attributes) r.attributes = {};
89 | r.attributes['ink-enabled'] = 'true';
90 | }
91 |
92 | for (let i=0; i
110 |
111 |
112 | ));
113 | foundRipple = true;
114 | }
115 | else if (r && r.children && r.children[i] && typeof r.children[i].nodeName==='string') {
116 | this.preserveMdlDom(c[i], r.children[i]);
117 | }
118 | }
119 | }
120 |
121 | createMdlClasses(props) {
122 | let name = this.component,
123 | c = [name],
124 | js = props.js!==false && (this.js || this.ripple);
125 | if (this.mdlClasses) c.push(...this.mdlClasses);
126 | if (this.ripple && props.ripple!==false) {
127 | c.push(RIPPLE_CLASS);
128 | }
129 | if (js) c.push(`js-${name}`);
130 | for (let i in props) {
131 | if (props.hasOwnProperty(i) && props[i]===true) {
132 | c.push(`${name}--${i}`);
133 | }
134 | }
135 | return c.map(MDL_PREFIX);
136 | }
137 |
138 | componentDidMount() {
139 | if (this.base!==this.upgradedBase) {
140 | if (this.upgradedBase) {
141 | mdl.downgradeElements(this.upgradedBase);
142 | }
143 | this.upgradedBase = null;
144 | if (this.base && this.base.parentElement) {
145 | this.upgradedBase = this.base;
146 | mdl.upgradeElement(this.base);
147 | }
148 | }
149 | }
150 |
151 | componentWillUnmount() {
152 | if (this.upgradedBase) {
153 | mdl.downgradeElements(this.upgradedBase);
154 | this.upgradedBase = null;
155 | }
156 | }
157 | }
158 |
159 |
160 | let upgradeQueue = {
161 | items: [],
162 | add(base) {
163 | if (upgradeQueue.items.push(base)===1) {
164 | requestAnimationFrame(upgradeQueue.process);
165 | }
166 | },
167 | process() {
168 | // console.log(`upgrading ${upgradeQueue.items.length} items`);
169 | let p = upgradeQueue.items;
170 | for (let i=p.length; i--; ) {
171 | let el = p[i],
172 | v = el.getAttribute('data-upgraded'),
173 | u = v && v.split(',');
174 | if (!u) continue;
175 | for (let j=u.length; j--; ) {
176 | let c = u[j],
177 | a = c && el[c];
178 | if (a) {
179 | if (a.updateClasses_) {
180 | a.updateClasses_();
181 | }
182 | if (a.onFocus_ && a.input_ && a.input_.matches && a.input_.matches(':focus')) {
183 | a.onFocus_();
184 | }
185 | // if (a.tabs_) {
186 | // // console.log(a);
187 | // a.tabs_ = el.querySelectorAll('.mdl-tabs__tab-bar > .mdl-tabs__tab');
188 | // console.log(a);
189 | // a.panels_ = [].map.call(a.tabs_, e => {
190 | // console.log(e.querySelector('.mdl-tabs__ripple-container'));
191 | // if (!e.querySelector('.mdl-tabs__ripple-container')) {
192 | // let s = document.createElement('span');
193 | // s.className = 'mdl-tabs__ripple-container mdl-js-ripple-effect';
194 | // s.innerHTML = '';
195 | // e.appendChild(s);
196 | // }
197 | //
198 | // let tab = e.getAttribute('tab');
199 | // if (tab) return el.querySelector(`.mdl-tabs__panel[tab="${tab}"]`);
200 | // return el.querySelector(`.mdl-tabs__panel[id="${e.href.replace(/^#/,'')}"]`);
201 | // });
202 | // console.log(a);
203 | // }
204 | }
205 | // if (a.init) a.init();
206 | }
207 | }
208 | p.length = 0;
209 | }
210 | };
211 |
212 |
213 |
214 | /** Material Icon */
215 | export class Icon extends Component {
216 | render(props) {
217 | let c = props.class || '';
218 | if (typeof c==='string') {
219 | c = 'material-icons ' + c;
220 | }
221 | else {
222 | c['material-icons'] = true;
223 | }
224 | return { props.icon || props.children };
225 | }
226 | }
227 |
228 |
229 |
230 |
231 | /** @prop primary = false
232 | * @prop accent = false
233 | * @prop colored = false
234 | * @prop raised = false
235 | * @prop icon = false
236 | * @prop fab = false
237 | * @prop mini-fab = false
238 | * @prop disabled = false
239 | */
240 | export class Button extends MaterialComponent {
241 | component = 'button';
242 | nodeName = 'button';
243 | js = true;
244 | ripple = true;
245 | }
246 |
247 |
248 |
249 |
250 |
251 |
252 | /** Cards */
253 |
254 | export class Card extends MaterialComponent {
255 | component = 'card';
256 | }
257 |
258 | export class CardTitle extends MaterialComponent {
259 | component = 'card__title';
260 | }
261 |
262 | export class CardTitleText extends MaterialComponent {
263 | component = 'card__title-text';
264 | nodeName = 'h2';
265 | }
266 |
267 | export class CardMedia extends MaterialComponent {
268 | component = 'card__media';
269 | }
270 |
271 | export class CardText extends MaterialComponent {
272 | component = 'card__supporting-text';
273 | }
274 |
275 | export class CardActions extends MaterialComponent {
276 | component = 'card__actions';
277 | // mdlClasses = ['card--border'];
278 | }
279 |
280 | export class CardMenu extends MaterialComponent {
281 | component = 'card__menu';
282 | }
283 |
284 | extend(Card, {
285 | Title: CardTitle,
286 | TitleText: CardTitleText,
287 | Media: CardMedia,
288 | Text: CardText,
289 | Actions: CardActions,
290 | Menu: CardMenu
291 | });
292 |
293 |
294 |
295 |
296 | /** Layouts */
297 |
298 | /** @prop fixed-header = false
299 | * @prop fixed-drawer = false
300 | * @prop overlay-drawer-button = false
301 | * @prop fixed-tabs = false
302 | */
303 | export class Layout extends MaterialComponent {
304 | component = 'layout';
305 | js = true;
306 | }
307 |
308 | /** @prop waterfall = false
309 | * @prop scroll = false
310 | */
311 | export class LayoutHeader extends MaterialComponent {
312 | component = 'layout__header';
313 | nodeName = 'header';
314 | }
315 |
316 | export class LayoutHeaderRow extends MaterialComponent {
317 | component = 'layout__header-row';
318 | }
319 |
320 | export class LayoutTitle extends MaterialComponent {
321 | component = 'layout-title';
322 | nodeName = 'span';
323 | }
324 |
325 | export class LayoutSpacer extends MaterialComponent {
326 | component = 'layout-spacer';
327 | }
328 |
329 | export class LayoutDrawer extends MaterialComponent {
330 | component = 'layout__drawer';
331 | }
332 |
333 | export class LayoutContent extends MaterialComponent {
334 | component = 'layout__content';
335 | nodeName = 'main';
336 | }
337 |
338 | export class LayoutTabBar extends MaterialComponent {
339 | component = 'layout__tab-bar';
340 | js = true;
341 | ripple = false;
342 | }
343 |
344 | /** @prop active */
345 | export class LayoutTab extends MaterialComponent {
346 | component = 'layout__tab';
347 | nodeName = 'a';
348 | }
349 |
350 | /** @prop active */
351 | export class LayoutTabPanel extends MaterialComponent {
352 | component = 'layout__tab-panel';
353 |
354 | mdlRender(props) {
355 | return ;
356 | }
357 | }
358 |
359 | extend(Layout, {
360 | Header: LayoutHeader,
361 | HeaderRow: LayoutHeaderRow,
362 | Title: LayoutTitle,
363 | Spacer: LayoutSpacer,
364 | Drawer: LayoutDrawer,
365 | Content: LayoutContent,
366 | TabBar: LayoutTabBar,
367 | Tab: LayoutTab,
368 | TabPanel: LayoutTabPanel
369 | });
370 |
371 |
372 |
373 | /** @prop large-screen-only = false */
374 | export class Navigation extends MaterialComponent {
375 | component = 'navigation';
376 | nodeName = 'nav';
377 |
378 | mdlRender(props, state) {
379 | let r = super.mdlRender(props, state);
380 | r.children.forEach( item => {
381 | let c = item.attributes.class || '';
382 | if (!c.match(/\bmdl-navigation__link\b/g)) {
383 | item.attributes.class = c + ' mdl-navigation__link';
384 | }
385 | });
386 | return r;
387 | }
388 | }
389 |
390 | export class NavigationLink extends MaterialComponent {
391 | component = 'navigation__link';
392 | nodeName = 'a';
393 |
394 | constructor(...args) {
395 | super(...args);
396 | this.handleClick = this.handleClick.bind(this);
397 | }
398 |
399 | handleClick(e) {
400 | if (typeof this.props.onclick==='function' && this.props.onclick({ type: 'click', target: this })===false) {
401 | }
402 | else if (typeof this.props.route==='function') {
403 | this.props.route(this.props.href);
404 | }
405 | e.preventDefault();
406 | return false;
407 | }
408 |
409 | mdlRender(props, state) {
410 | return { props.children };
411 | }
412 | }
413 |
414 | Navigation.Link = NavigationLink;
415 |
416 |
417 |
418 |
419 | export class Tabs extends MaterialComponent {
420 | component = 'tabs';
421 | js = true;
422 | ripple = false;
423 | }
424 |
425 | export class TabBar extends MaterialComponent {
426 | component = 'tabs__tab-bar';
427 | }
428 |
429 | export class Tab extends MaterialComponent {
430 | component = 'tabs__tab';
431 | nodeName = 'a';
432 | }
433 |
434 | export class TabPanel extends MaterialComponent {
435 | component = 'tabs__panel';
436 | nodeName = 'section';
437 | }
438 |
439 | extend(Tabs, {
440 | TabBar,
441 | Bar: TabBar,
442 | Tab,
443 | TabPanel,
444 | Panel: TabPanel
445 | });
446 |
447 |
448 |
449 | export class MegaFooter extends MaterialComponent {
450 | component = 'mega-footer';
451 | nodeName = 'footer';
452 | }
453 |
454 | export class MegaFooterMiddleSection extends MaterialComponent {
455 | component = 'mega-footer__middle-section';
456 | }
457 |
458 | export class MegaFooterDropDownSection extends MaterialComponent {
459 | component = 'mega-footer__drop-down-section';
460 | }
461 |
462 | export class MegaFooterHeading extends MaterialComponent {
463 | component = 'mega-footer__heading';
464 | nodeName = 'h1';
465 | }
466 |
467 | export class MegaFooterLinkList extends MaterialComponent {
468 | component = 'mega-footer__link-list';
469 | nodeName = 'ul';
470 | }
471 |
472 | export class MegaFooterBottomSection extends MaterialComponent {
473 | component = 'mega-footer__bottom-section';
474 | }
475 |
476 | extend(MegaFooter, {
477 | MiddleSection: MegaFooterMiddleSection,
478 | DropDownSection: MegaFooterDropDownSection,
479 | Heading: MegaFooterHeading,
480 | LinkList: MegaFooterLinkList,
481 | BottomSection: MegaFooterBottomSection
482 | });
483 |
484 |
485 |
486 |
487 | export class MiniFooter extends MaterialComponent {
488 | component = 'mini-footer';
489 | nodeName = 'footer';
490 | }
491 |
492 | export class MiniFooterLeftSection extends MaterialComponent {
493 | component = 'mini-footer__left-section';
494 | }
495 |
496 | export class MiniFooterLinkList extends MaterialComponent {
497 | component = 'mini-footer__link-list';
498 | nodeName = 'ul';
499 | }
500 |
501 | extend(MiniFooter, {
502 | LeftSection: MiniFooterLeftSection,
503 | LinkList: MiniFooterLinkList
504 | });
505 |
506 |
507 |
508 |
509 | /** Responsive Grid
510 | * @prop no-spacing = false
511 | */
512 | export class Grid extends MaterialComponent {
513 | component = 'grid';
514 | }
515 |
516 | export class Cell extends MaterialComponent {
517 | component = 'cell';
518 | }
519 |
520 | Grid.Cell = Cell;
521 |
522 |
523 |
524 |
525 |
526 | /** @prop indeterminate = false */
527 | export class Progress extends MaterialComponent {
528 | component = 'progress';
529 | js = true;
530 |
531 | mdlRender(props) {
532 | return (
533 |
538 | );
539 | }
540 |
541 | componentDidUpdate() {
542 | let api = this.base.MaterialProgress,
543 | p = this.props;
544 | if (p.progress) api.setProgress(p.progress);
545 | if (p.buffer) api.setBuffer(p.buffer);
546 | }
547 | }
548 |
549 |
550 |
551 |
552 |
553 | /** @prop active = false
554 | * @prop single-color = false
555 | */
556 | export class Spinner extends MaterialComponent {
557 | component = 'spinner';
558 | js = true;
559 | }
560 |
561 |
562 |
563 |
564 |
565 | /** @prop bottom-left = true
566 | * @prop bottom-right = false
567 | * @prop top-left = false
568 | * @prop top-right = false
569 | */
570 | export class Menu extends MaterialComponent {
571 | component = 'menu';
572 | js = true;
573 | ripple = true;
574 | }
575 |
576 | /** @prop disabled = false */
577 | export class MenuItem extends MaterialComponent {
578 | component = 'menu__item';
579 | nodeName = 'li';
580 | }
581 |
582 | Menu.Item = MenuItem;
583 |
584 |
585 |
586 |
587 |
588 | /** @prop min = 0
589 | * @prop max = 100
590 | * @prop value = 0
591 | * @prop tabindex = 0
592 | * @prop disabled = false
593 | */
594 | export class Slider extends MaterialComponent {
595 | component = 'slider';
596 | js = true;
597 |
598 | mdlRender(props) {
599 | return ;
600 | }
601 | }
602 |
603 |
604 |
605 |
606 | /** @prop checked = false
607 | * @prop disabled = false
608 | */
609 | export class CheckBox extends MaterialComponent {
610 | component = 'checkbox';
611 | js = true;
612 | ripple = true;
613 |
614 | getValue() {
615 | return this.base.children[0].checked;
616 | }
617 |
618 | mdlRender(props) {
619 | return (
620 |
628 | );
629 | }
630 | }
631 |
632 |
633 |
634 |
635 | /** @prop name (required)
636 | * @prop value (required)
637 | * @prop checked = false
638 | * @prop disabled = false
639 | */
640 | export class Radio extends MaterialComponent {
641 | component = 'radio';
642 | js = true;
643 | ripple = true;
644 |
645 | getValue() {
646 | return this.base.children[0].checked;
647 | }
648 |
649 | mdlRender(props) {
650 | return (
651 |
655 | );
656 | }
657 | }
658 |
659 |
660 |
661 |
662 | /** @prop checked = false
663 | * @prop disabled = false
664 | */
665 | export class IconToggle extends MaterialComponent {
666 | component = 'icon-toggle';
667 | js = true;
668 | ripple = true;
669 |
670 | getValue() {
671 | return this.base.children[0].checked;
672 | }
673 |
674 | mdlRender(props) {
675 | return (
676 |
680 | );
681 | }
682 | }
683 |
684 |
685 |
686 |
687 | /** @prop checked = false
688 | * @prop disabled = false
689 | */
690 | export class Switch extends MaterialComponent {
691 | component = 'switch';
692 | nodeName = 'label';
693 | js = true;
694 | ripple = true;
695 |
696 | getValue() {
697 | return this.base.children[0].checked;
698 | }
699 |
700 | mdlRender(props) {
701 | return (
702 |
706 | );
707 | }
708 | }
709 |
710 |
711 |
712 |
713 | /** @prop selectable = false */
714 | export class Table extends MaterialComponent {
715 | component = 'data-table';
716 | nodeName = 'table';
717 | js = true;
718 | }
719 |
720 | /** @prop non-numeric = false */
721 | export class TableCell extends MaterialComponent {
722 | component = 'data-table__cell';
723 | nodeName = 'td';
724 | }
725 |
726 | Table.Cell = TableCell;
727 |
728 |
729 |
730 |
731 | /** @prop floating-label = false
732 | * @prop multiline = false
733 | * @prop expandable = false
734 | * @prop icon (used with expandable)
735 | */
736 | export class TextField extends MaterialComponent {
737 | component = 'textfield';
738 | js = true;
739 |
740 | constructor(...args) {
741 | super(...args);
742 | this.id = uid();
743 | }
744 |
745 | mdlRender(props={}) {
746 | let id = props.id || this.id,
747 | p = extend({}, props);
748 |
749 | delete p.class;
750 |
751 | let field = (
752 |
753 |
754 |
755 |
756 | );
757 | if (props.multiline) {
758 | field.children[0].nodeName = 'textarea';
759 | field.children[0].children = [props.value];
760 | }
761 | if (props.expandable===true) {
762 | field.class = 'mdl-textfield__expandable-holder';
763 | field = (
764 |
765 |
768 | { field }
769 |
770 | );
771 | }
772 | if (props.class) {
773 | (field.attributes = field.attributes || {}).class = props.class;
774 | }
775 | return field;
776 | }
777 | }
778 |
779 |
780 |
781 |
782 |
783 |
784 | /** @prop for [id]
785 | * @prop large = false
786 | */
787 | export class Tooltip extends MaterialComponent {
788 | component = 'tooltip';
789 | }
790 |
791 |
792 |
793 |
794 | export default {
795 | Icon,
796 | Button,
797 | Card,
798 | Layout,
799 | Navigation,
800 | Tabs,
801 | MegaFooter,
802 | MiniFooter,
803 | Grid,
804 | Cell,
805 | Progress,
806 | Spinner,
807 | Menu,
808 | Slider,
809 | CheckBox,
810 | Radio,
811 | IconToggle,
812 | Switch,
813 | Table,
814 | TextField,
815 | Tooltip
816 | };
817 |
--------------------------------------------------------------------------------
/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Documentation Viewer",
3 | "short_name": "Docs",
4 | "icons": [
5 | {
6 | "src": "/assets/icon-256.png",
7 | "sizes": "256x256",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "/assets/icon-192.png",
12 | "sizes": "192x192",
13 | "type": "image/png"
14 | },
15 | {
16 | "src": "/assets/icon-128.png",
17 | "sizes": "128x128",
18 | "type": "image/png"
19 | }
20 | ],
21 | "start_url": "/",
22 | "display": "standalone",
23 | "theme_color": "aliceblue",
24 | "background_color": "red"
25 | }
26 |
--------------------------------------------------------------------------------
/src/style/index.less:
--------------------------------------------------------------------------------
1 | @import (css) '~normalize.css';
2 | @import (css) '//storage.googleapis.com/code.getmdl.io/1.0.5/material.indigo-pink.min.css';
3 | @import (css) '//fonts.googleapis.com/icon?family=Material+Icons';
4 | @import (css) '//fonts.googleapis.com/css?family=Roboto:300,500,700';
5 |
6 |
7 | html, body {
8 | background: #E0E4E9;
9 | }
10 |
11 | #docs {
12 | position: static;
13 | overflow: visible;
14 | }
15 |
16 | main {
17 | display: block;
18 | text-align: center;
19 | }
20 |
21 | .info {
22 | margin: 0 auto;
23 | padding: 10px;
24 | max-width: 280px;
25 | }
26 |
27 | .symbol {
28 | .symbol-kind {
29 | position: absolute;
30 | left: 20px;
31 | top: 80px;
32 | font-size: 12px;
33 | font-style: italic;
34 | color: #FFF;
35 | }
36 | }
37 |
38 | .mdl-card {
39 | display: inline-block;
40 | text-align: left;
41 | margin: 20px;
42 | padding: 0 0 10px;
43 | width: auto;
44 | &.wide {
45 | max-width: 1000px;
46 | min-width: 600px;
47 | @media (max-width:640px) {
48 | & {
49 | display: block;
50 | min-width: 0;
51 | }
52 | }
53 | }
54 | &.skinny {
55 | max-width: 600px;
56 | min-width: 400px;
57 | @media (max-width:440px) {
58 | & {
59 | display: block;
60 | min-width: 0;
61 | }
62 | }
63 | }
64 | }
65 |
66 | .mdl-card__title.graphic {
67 | height: 100px;
68 | background: url(https://lh3.googleusercontent.com/-WiwrPHajH08/VTpzIfl09SI/AAAAAAAA4S4/062nOW9T-I4/s630-fcrop64=1,00002f44ffffc017/material-design-wallpaper-1.png) center/cover;
69 | .mdl-card__title-text {
70 | color: #FFF;
71 | font-size: 300%;
72 | text-shadow: 0 0 1px #000, 0 0 5px rgba(0,0,0,0.3);
73 | }
74 | }
75 |
76 | .members {
77 | margin: 0 20px;
78 | .member {
79 | padding-left: 5px;
80 | border-left: 2px solid #E6E6E6;
81 | }
82 | h2 {
83 | margin: 5px 0 0;
84 | font-size: 160%;
85 | line-height: 1.21;
86 | color: #888;
87 | }
88 | h3 {
89 | font-size: 120%;
90 | line-height: 1.21;
91 | margin-bottom: 0;
92 |
93 | em {
94 | color: #BBB;
95 | }
96 | }
97 | p {
98 | font-size: 12px;
99 | }
100 | }
101 |
102 | h4 {
103 | font-size: 110%;
104 | line-height: 1.21;
105 | margin: 5px 0;
106 | color: #666;
107 | }
108 | .params {
109 | padding-bottom: 10px;
110 | }
111 | .param {
112 | margin: -1px 10px 0;
113 | padding: 5px;
114 | background: #FFF;
115 | border: 1px solid #DDD;
116 | font-size: 80%;
117 | overflow: hidden;
118 |
119 | .param {
120 | margin: -1px 0 0;
121 | }
122 |
123 | dt {
124 | float: left;
125 | padding-right: 10px;
126 | min-width: 8em;
127 | font-weight: normal;
128 | }
129 | dd {
130 | display: inline-block;
131 | margin: 0;
132 |
133 | h6 {
134 | margin: 0;
135 | pdading: 0;
136 | font-size: 100%;
137 | }
138 | }
139 | }
140 |
141 | .mdl-card__supporting-text,
142 | .mdl-card__supporting-text > p {
143 | font-size: 16px;
144 | width: auto;
145 | }
146 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack'),
2 | ExtractTextPlugin = require("extract-text-webpack-plugin");
3 |
4 | module.exports = {
5 | entry: './src/index.js',
6 | output: {
7 | path: './build',
8 | filename: 'bundle.js'
9 | },
10 | resolve: {
11 | modulesDirectories: [
12 | './src/lib',
13 | 'node_modules'
14 | ]
15 | },
16 | module: {
17 | preLoaders: [
18 | { loader: 'source-map' }
19 | ],
20 | loaders: [
21 | {
22 | test: /\.jsx?$/,
23 | exclude: /node_modules/,
24 | loader: 'babel'
25 | },
26 | {
27 | test: /\.(less|css)$/,
28 | loader: ExtractTextPlugin.extract("style?sourceMap", "css?sourceMap!autoprefixer?browsers=last 2 version!less")
29 | }
30 | ]
31 | },
32 | plugins: ([
33 | new webpack.NoErrorsPlugin(),
34 | new webpack.optimize.DedupePlugin(),
35 | new ExtractTextPlugin('style.css', { allChunks: true })
36 | ]).concat(process.env.WEBPACK_ENV==='dev' ? [] : [
37 | new webpack.optimize.OccurenceOrderPlugin(),
38 | new webpack.optimize.UglifyJsPlugin({
39 | output: { comments: false },
40 | exclude: [/\.min\.js$/gi]
41 | })
42 | ]),
43 | stats: { colors: true },
44 | devtool: 'source-map',
45 | devServer: {
46 | port: process.env.PORT || 8080,
47 | contentBase: './src',
48 | historyApiFallback: true
49 | }
50 | };
51 |
--------------------------------------------------------------------------------