src/Collapsible.ts

   1/**

   2 * # Collapsible Widget

   3 * returns a Vnode that can be toggled to expand and contract by clicking on the first `component`.

   4 * 

   5 * ### Invocation

   6 * invoked as 

   7 * ```

   8 * m(Collapsible, { css:, isExpanded:true, components:[

   9 *     m('div''the title'),

  10 *     ['body item1''body item2''body item3']

  11 * ]})

  12 * ```

  13 * 

  14 * ### Attributes (node.attrs):

  15 * - `css`: optional; the css class to assign to the entire Collapsible div

  16 * - `isExpanded`: optional; boolean indicating if the Collapsible is initially expanded

  17 * - `components`: array of two components: 

  18 *     - `component[0]` is the title of the Collapsible. This will remain visible and can be clicked 

  19 *       on to expand or contract the remaining components

  20 *     - `component[1]` an array of Vnodes that will be collapsed or expanded.

  21 * 

  22 * ### Example

  23 * 

  24 * 'script.js'>

  25 * m.mount(root, {view: () => m('.hs-white', [

  26 *    m(hsWidget.Collapsible, { css:'.myExample', components: [

  27 *       m('.myTitle''click me to toggle'), [

  28 *          m('.myItem''body item1'), 

  29 *          m('.myItem''body item2'), 

  30 *          m('.myItem''body item3')

  31 *       ]

  32 *    ]}),

  33 *    m('''This is a background text that will be pushed down by the Collapsible')

  34 * ])});

  35 * 

  36 * 'style.css'>

  37 * div { margin-top: 5px; }

  38 * .myTitle {

  39 *    display: inline-block;

  40 *    border-radius: 0px 4px;

  41 *    padding: 1px;

  42 *    border-bottom: 1px solid blue;

  43 *    width: auto;

  44 * }

  45 * 

  46 * 

  47 */

  48

  49 /** */

  50import { m, Vnode } from 'hslayout';

  51

  52export class Collapsible {

  53    oninit(node:Vnode) {

  54        node.state.intial = true;

  55        node.state.expanded = false;

  56        node.state.toggle = () => {

  57            node.state.expanded = !node.state.expanded;

  58            node.state.initial = false;

  59        };

  60    }

  61    view(node:Vnode) {

  62        const css        = node.attrs.css;

  63        const components = node.attrs.components;

  64        const preArrow   = node.attrs.preArrow;

  65        const postArrow  = node.attrs.postArrow;

  66        if (node.state.initial && node.attrs.isExpanded!==undefined) {

  67            node.state.expanded = node.attrs.isExpanded;

  68        }

  69        const expCSS = node.state.expanded?'hs-collapsible-expanded':'';

  70        return m(`.hs-collapsible ${css}`, [

  71            m('.hs-collapsible-title', { onclick:node.state.toggle}, [

  72                !preArrow? m('') : m(`.hs-collapsible-pre .hs-collapsible-arrow-${node.state.expanded?'down' : 'right'}`),

  73                components[0],

  74                !postArrow? m('') : m(`.hs-collapsible-post .hs-collapsible-arrow-${node.state.expanded?'down' : 'left'}`),

  75            ]),

  76            components[1]? m(`.hs-collapsible-content ${expCSS}`, components[1].map((c:any) =>m('',c))) : undefined

  77        ]);

  78    }

  79}

  80