import { __assign, __extends } from 'tslib';
import { BuilderBlocks, BuilderBlockComponent, BuilderStoreContext, stringToFunction, BuilderAsyncRequestsContext, Builder, withBuilder } from '@builder.io/react';
import React from 'react';
import Slider from 'react-slick';
import Masonry from 'react-masonry-component';

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/**
 * Gets the last element of `array`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Array
 * @param {Array} array The array to query.
 * @returns {*} Returns the last element of `array`.
 * @example
 *
 * _.last([1, 2, 3]);
 * // => 3
 */
function last(array) {
  var length = array == null ? 0 : array.length;
  return length ? array[length - 1] : undefined;
}

var defaultElement = {
    '@type': '@builder.io/sdk:Element',
    responsiveStyles: {
        large: {
            // TODO: always apply these if not given
            position: 'relative',
            display: 'flex',
            alignItems: 'stretch',
            flexDirection: 'column',
            height: '400px'
        }
    },
    children: [
        {
            '@type': '@builder.io/sdk:Element',
            responsiveStyles: {
                large: {
                    marginTop: '50px',
                    textAlign: 'center',
                    display: 'flex',
                    flexDirection: 'column'
                }
            },
            component: {
                name: 'Text',
                options: {
                    text: 'I am a slide'
                }
            }
        }
    ]
};
var defaultButton = {
    '@type': '@builder.io/sdk:Element',
    responsiveStyles: {
        large: {
            position: 'relative',
            display: 'flex',
            alignItems: 'stretch',
            flexDirection: 'column',
            height: '30px'
        }
    }
};
// TODO: change to slick grid
var BuilderCarouselComponent = /** @class */ (function (_super) {
    __extends(BuilderCarouselComponent, _super);
    function BuilderCarouselComponent() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.divRef = null;
        _this.sliderRef = null;
        return _this;
    }
    BuilderCarouselComponent.prototype.componentDidMount = function () {
        var _this = this;
        setTimeout(function () {
            if (_this.divRef) {
                _this.divRef.dispatchEvent(new CustomEvent('builder:carousel:load', {
                    bubbles: true,
                    cancelable: false,
                    detail: {
                        block: _this.props.builderBlock,
                        carousel: _this.sliderRef
                    }
                }));
            }
        });
    };
    BuilderCarouselComponent.prototype.render = function () {
        var _this = this;
        var slides = this.props.slides;
        if (slides && !Builder.isBrowser) {
            slides = slides.slice(0, 1);
        }
        return (React.createElement(BuilderAsyncRequestsContext.Consumer, null, function (value) {
            _this._errors = value && value.errors;
            _this._logs = value && value.logs;
            return (React.createElement(BuilderStoreContext.Consumer, null, function (state) { return (React.createElement("div", { ref: function (ref) { return (_this.divRef = ref); }, className: "builder-carousel" },
                Builder.isServer ? (React.createElement("style", { type: "text/css", dangerouslySetInnerHTML: { __html: slickStyles } })) : (React.createElement("style", { type: "text/css" }, slickStyles)),
                React.createElement(Slider, __assign({ responsive: _this.props.responsive, ref: function (ref) { return (_this.sliderRef = ref); }, afterChange: function (slide) {
                        // TODO; callbacks
                        if (_this.divRef) {
                            _this.divRef.dispatchEvent(new CustomEvent('builder:carousel:change', {
                                bubbles: true,
                                cancelable: false,
                                detail: {
                                    slide: slide,
                                    block: _this.props.builderBlock,
                                    carousel: _this.sliderRef
                                }
                            }));
                        }
                    }, autoplay: _this.props.autoplay, autoplaySpeed: _this.props.autoplaySpeed
                        ? _this.props.autoplaySpeed * 1000
                        : undefined, dots: !_this.props.hideDots, 
                    // TODO: on change emit event on element?
                    // renderBottomCenterControls={this.props.hideDots ? () => null : undefined}
                    // OOF!!
                    nextArrow: React.createElement("div", null,
                        React.createElement(BuilderBlocks, { parentElementId: _this.props.builderBlock.id, dataPath: "component.options.prevButton", blocks: _this.props.prevButton })), 
                    // OOF!!
                    prevArrow: React.createElement("div", null,
                        React.createElement(BuilderBlocks, { parentElementId: _this.props.builderBlock.id, dataPath: "component.options.nextButton", blocks: _this.props.nextButton })) }, _this.props.slickProps), _this.props.useChildrenForSlides
                    ? _this.props.builderBlock &&
                        _this.props.builderBlock.children &&
                        _this.props.builderBlock.children.map(function (block, index) {
                            if (block.repeat && block.repeat.collection) {
                                var collectionPath = block.repeat.collection;
                                var collectionName = last((collectionPath || '')
                                    .split(/\.\w+\(/)[0]
                                    .trim()
                                    .split('.'));
                                var itemName_1 = block.repeat.itemName ||
                                    (collectionName
                                        ? collectionName + 'Item'
                                        : 'item');
                                var array = stringToFunction(collectionPath, true, _this._errors, _this._logs)(state.state);
                                if (isArray(array)) {
                                    if (!Builder.isBrowser) {
                                        array = array.slice(0, 1);
                                    }
                                    return array.map(function (data, index) {
                                        var _a;
                                        // TODO: Builder state produce the data
                                        var childState = __assign(__assign({}, state.state), (_a = { $index: index, $item: data }, _a[itemName_1] = data, _a));
                                        return (React.createElement(BuilderStoreContext.Provider, { key: block.id, value: __assign(__assign({}, state), { state: childState }) },
                                            React.createElement(BuilderBlockComponent, { block: __assign(__assign({}, block), { repeat: null }), index: index, child: true })));
                                    });
                                }
                            }
                            return (React.createElement(BuilderBlockComponent, { key: block.id, block: block, index: index, child: true }));
                        })
                    : _this.props.slides &&
                        _this.props.slides.map(function (slide, index) { return (
                        // TODO: how make react compatible with plain react components
                        // slides: <Foo><Bar> <- builder blocks if passed react nodes as blocks just forward them
                        React.createElement(BuilderBlocks, { key: index, parentElementId: _this.props.builderBlock &&
                                _this.props.builderBlock.id, dataPath: "component.options.slides." + index + ".content", child: true, blocks: slide.content || slide })); })))); }));
        }));
    };
    return BuilderCarouselComponent;
}(React.Component));
var slickStyles = "@charset 'UTF-8';\n  .slick-list,.slick-slider,.slick-track{position:relative;display:block}.slick-loading .slick-slide,.slick-loading .slick-track{visibility:hidden}.slick-slider{box-sizing:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-khtml-user-select:none;-ms-touch-action:pan-y;touch-action:pan-y;-webkit-tap-highlight-color:transparent}.slick-list{overflow:hidden;margin:0;padding:0}.slick-list:focus{outline:0}.slick-list.dragging{cursor:pointer;cursor:hand}.slick-slider .slick-list,.slick-slider .slick-track{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.slick-track{top:0;left:0}.slick-track:after,.slick-track:before{display:table;content:''}.slick-track:after{clear:both}.slick-slide{display:none;float:left;height:auto;min-height:1px}[dir=rtl] .slick-slide{float:right}.slick-slide img{display:block}.slick-slide.slick-loading img{display:none}.slick-slide.dragging img{pointer-events:none}.slick-initialized .slick-slide{display:block}.slick-vertical .slick-slide{display:block;height:auto;border:1px solid transparent}.slick-arrow.slick-hidden{display:none}\n  .slick-dots,.slick-next,.slick-prev{position:absolute;display:block;padding:0}.slick-dots li button:before,.slick-next:before,.slick-prev:before{font-family:slick;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.slick-loading .slick-list{background:url(ajax-loader.gif) center center no-repeat #fff}@font-face{font-display:swap;font-family:slick;font-weight:400;font-style:normal;src:url(https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/fonts/slick.eot);src:local(\"slick\"),url(https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/fonts/slick.eot?#iefix) format('embedded-opentype'),url(https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/fonts/slick.woff) format('woff'),url(https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/fonts/slick.ttf) format('truetype'),url(https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/fonts/slick.svg#slick) format('svg')}.slick-next,.slick-prev{font-size:0;line-height:0;top:50%;width:20px;height:20px;-webkit-transform:translate(0,-50%);-ms-transform:translate(0,-50%);transform:translate(0,-50%);cursor:pointer;color:transparent;border:none;outline:0;background:0 0}.slick-next:focus,.slick-next:hover,.slick-prev:focus,.slick-prev:hover{color:transparent;outline:0;background:0 0}.slick-next:focus:before,.slick-next:hover:before,.slick-prev:focus:before,.slick-prev:hover:before{opacity:1}.slick-next.slick-disabled:before,.slick-prev.slick-disabled:before{opacity:.25}.slick-next:before,.slick-prev:before{font-size:20px;line-height:1;opacity:.75;color:#fff}.slick-prev{left:-25px}[dir=rtl] .slick-prev{right:-25px;left:auto}.slick-prev:before{content:''}.slick-next:before,[dir=rtl] .slick-prev:before{content:''}.slick-next{right:-25px}[dir=rtl] .slick-next{right:auto;left:-25px}[dir=rtl] .slick-next:before{content:'\u2022\u0090'}.slick-dotted.slick-slider{margin-bottom:30px}.slick-dots{bottom:-25px;width:100%;margin:0;list-style:none;text-align:center}.slick-dots li{position:relative;display:inline-block;width:20px;height:20px;margin:0 5px;padding:0;cursor:pointer}.slick-dots li button{font-size:0;line-height:0;display:block;width:20px;height:20px;padding:5px;cursor:pointer;color:transparent;border:0;outline:0;background:0 0}.slick-dots li button:focus,.slick-dots li button:hover{outline:0}.slick-dots li button:focus:before,.slick-dots li button:hover:before{opacity:1}.slick-dots li button:before{font-size:6px;line-height:20px;position:absolute;top:0;left:0;width:20px;height:20px;content:'\u2022';text-align:center;opacity:.25;color:#000}.slick-dots li.slick-active button:before{opacity:.75;color:#000}\n";
var BuilderCarousel = withBuilder(BuilderCarouselComponent, {
    name: 'Builder:Carousel',
    // TODO: default children
    canHaveChildren: true,
    defaultStyles: {
        paddingLeft: '30px',
        paddingRight: '30px',
        paddingBottom: '30px'
    },
    inputs: [
        {
            name: 'slides',
            type: 'list',
            subFields: [
                {
                    name: 'content',
                    type: 'uiBlocks',
                    hideFromUI: true,
                    defaultValue: [defaultElement]
                }
            ],
            defaultValue: [
                {
                    content: [defaultElement]
                },
                {
                    content: [defaultElement]
                }
            ],
            // showIf: options => !options.get('useChildrenForSlides'),
            showIf: function (options) { return !options.get('useChildrenForSlides'); }
        },
        {
            name: 'hideDots',
            helperText: 'Show pagination dots',
            type: 'boolean',
            defaultValue: false
        },
        {
            name: 'autoplay',
            helperText: 'Automatically rotate to the next slide every few seconds',
            type: 'boolean',
            defaultValue: false
        },
        {
            name: 'autoplaySpeed',
            type: 'number',
            defaultValue: 5,
            helperText: 'If auto play is on, how many seconds to wait before automatically changing each slide',
            // TODO: showIf option
            // showIf: options => options.get('autoplay'),
            // TODO: why fn not working?
            showIf: function (options) { return options.get('autoplay'); }
            // showIf: (options) => options.get('autoPlay')
        },
        // TODO: on add new duplicate the prior or expect use templates
        // onChange:
        {
            name: 'prevButton',
            type: 'uiBlocks',
            hideFromUI: true,
            defaultValue: [
                __assign(__assign({}, defaultButton), { component: {
                        name: 'Image',
                        options: {
                            image: 'https://cdn.builder.io/api/v1/image/assets%2FagZ9n5CUKRfbL9t6CaJOyVSK4Es2%2Fd909a5b91650499c9e0524cc904eeb77'
                        }
                    } })
            ]
        },
        {
            name: 'nextButton',
            type: 'uiBlocks',
            hideFromUI: true,
            defaultValue: [
                __assign(__assign({}, defaultButton), { component: {
                        name: 'Image',
                        options: {
                            image: 'https://cdn.builder.io/api/v1/image/assets%2FagZ9n5CUKRfbL9t6CaJOyVSK4Es2%2Fdb2a9827561249aea3817b539aacdcdc'
                        }
                    } })
            ]
        },
        {
            name: 'useChildrenForSlides',
            type: 'boolean',
            helperText: 'Use child elements for each slide, instead of the array. Useful for dynamically repeating slides',
            advanced: true,
            defaultValue: false,
            onChange: function (options) {
                if (options.get('useChildrenForSlides') === true) {
                    options.set('slides', []);
                }
            }
        },
        {
            name: 'responsive',
            type: 'array',
            helperText: 'Responsive settings - e.g. see https://kenwheeler.github.io/slick/',
            advanced: true,
            defaultValue: [
                {
                    width: 3000,
                    slidesToShow: 2,
                    slidesToScroll: 2
                },
                {
                    width: 400,
                    slidesToShow: 1,
                    slidesToScroll: 1
                }
            ],
            subFields: [
                {
                    name: 'breakpoint',
                    type: 'number',
                    defaultValue: 400,
                    required: true
                },
                {
                    name: 'settings',
                    type: 'object',
                    defaultValue: {
                        slidesToShow: 2,
                        slidesToScroll: 2
                    },
                    subFields: [
                        {
                            name: 'slidesToShow',
                            type: 'number',
                            defaultValue: 2
                        },
                        {
                            name: 'slidesToScroll',
                            type: 'number',
                            defaultValue: 2
                        },
                        {
                            name: 'infinite',
                            type: 'boolean',
                            defaultValue: true
                        },
                        {
                            name: 'dots',
                            type: 'boolean',
                            defaultValue: true
                        }
                    ]
                }
            ]
        }
    ]
});

var defaultTab = {
    '@type': '@builder.io/sdk:Element',
    responsiveStyles: {
        large: {
            paddingLeft: '20px',
            paddingRight: '20px',
            paddingTop: '10px',
            paddingBottom: '10px',
            minWidth: '100px',
            textAlign: 'center',
            // TODO: add to all
            display: 'flex',
            flexDirection: 'column',
            cursor: 'pointer',
            userSelect: 'none'
        }
    },
    component: {
        // Builder:text
        name: 'Text',
        options: {
            text: 'New tab'
        }
    }
};
var defaultElement$1 = {
    '@type': '@builder.io/sdk:Element',
    responsiveStyles: {
        large: {
            height: '200px',
            display: 'flex',
            marginTop: '20px',
            flexDirection: 'column'
        }
    },
    component: {
        name: 'Text',
        options: {
            text: 'New tab content '
        }
    }
};
var TabsComponent = /** @class */ (function (_super) {
    __extends(TabsComponent, _super);
    function TabsComponent() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.state = {
            activeTab: 0
        };
        return _this;
    }
    Object.defineProperty(TabsComponent.prototype, "activeTabSpec", {
        get: function () {
            return this.props.tabs && this.props.tabs[this.state.activeTab];
        },
        enumerable: true,
        configurable: true
    });
    TabsComponent.prototype.componentWillMount = function () {
        if (this.props.defaultActiveTab) {
            this.activeTab = this.props.defaultActiveTab - 1;
        }
    };
    Object.defineProperty(TabsComponent.prototype, "activeTab", {
        get: function () {
            return this.state.activeTab;
        },
        set: function (tab) {
            this.setState(__assign(__assign({}, this.state), { activeTab: tab }));
        },
        enumerable: true,
        configurable: true
    });
    TabsComponent.prototype.render = function () {
        var _this = this;
        return (React.createElement("span", null,
            React.createElement("span", { style: {
                    display: 'flex',
                    flexDirection: 'row',
                    justifyContent: this.props.tabHeaderLayout,
                    overflow: 'auto',
                    WebkitOverflowScrolling: 'touch'
                }, className: "builder-tabs-wrap" }, this.props.tabs &&
                this.props.tabs.map(function (item, index) { return (React.createElement("span", { key: index, className: 'builder-tab-wrap ' +
                        (_this.activeTabSpec === item ? 'builder-tab-active' : ''), style: __assign({}, ((_this.activeTabSpec === item &&
                        _this.props.activeTabStyle) ||
                        undefined)), onClick: function () {
                        if (index === _this.activeTab && _this.props.collapsible) {
                            _this.activeTab = -1;
                        }
                        else {
                            _this.activeTab = index;
                        }
                    } },
                    React.createElement(BuilderBlocks
                    // TODO: parent={this.props.builderBlock}
                    , { 
                        // TODO: parent={this.props.builderBlock}
                        parentElementId: _this.props.builderBlock.id, 
                        // TODO: start with just "tabs." when bump react version
                        dataPath: "component.options.tabs." + _this.state.activeTab + ".label", blocks: item.label }))); })),
            this.activeTabSpec && (React.createElement(BuilderBlocks, { parentElementId: this.props.builderBlock.id, dataPath: "component.options.tabs." + this.state.activeTab + ".content", blocks: this.activeTabSpec.content }))));
    };
    return TabsComponent;
}(React.Component));
var Tabs = withBuilder(TabsComponent, {
    name: 'Builder: Tabs',
    inputs: [
        {
            name: 'tabs',
            type: 'list',
            subFields: [
                {
                    name: 'label',
                    type: 'uiBlocks',
                    hideFromUI: true,
                    defaultValue: [defaultTab]
                },
                {
                    name: 'content',
                    type: 'uiBlocks',
                    hideFromUI: true,
                    defaultValue: [defaultElement$1]
                }
            ],
            defaultValue: [
                {
                    label: [
                        __assign(__assign({}, defaultTab), { component: {
                                name: 'Text',
                                options: {
                                    text: 'Tab 1'
                                }
                            } })
                    ],
                    content: [
                        __assign(__assign({}, defaultElement$1), { component: {
                                name: 'Text',
                                options: {
                                    text: 'Tab 1 content'
                                }
                            } })
                    ]
                },
                {
                    label: [
                        __assign(__assign({}, defaultTab), { component: {
                                name: 'Text',
                                options: {
                                    text: 'Tab 2'
                                }
                            } })
                    ],
                    content: [
                        __assign(__assign({}, defaultElement$1), { component: {
                                name: 'Text',
                                options: {
                                    text: 'Tab 2 content'
                                }
                            } })
                    ]
                }
            ]
        },
        {
            name: 'activeTabStyle',
            type: 'uiStyle',
            helperText: 'CSS styles for the active tab',
            defaultValue: {
                backgroundColor: 'rgba(0, 0, 0, 0.1)'
            }
        },
        {
            name: 'defaultActiveTab',
            type: 'number',
            helperText: 'Deafult tab to open to. Set to "1" for the first tab, "2" for the second, or choose "0" for none',
            defaultValue: 1,
            advanced: true
        },
        {
            name: 'collapsible',
            type: 'boolean',
            helperText: 'If on, clicking an open tab closes it so no tabs are active',
            defaultValue: false,
            advanced: true
        },
        {
            name: 'tabHeaderLayout',
            type: 'enum',
            helperText: 'Change the layout of the tab headers (uses justify-content)',
            defaultValue: 'flex-start',
            enum: [
                { label: 'Center', value: 'center' },
                { label: 'Space between', value: 'space-between' },
                { label: 'Space around', value: 'space-around' },
                { label: 'Left', value: 'flex-start' },
                { label: 'Right', value: 'flex-end' }
            ]
        }
    ]
});

// import { get, isArray, last } from 'lodash';
var defaultTitle = {
    '@type': '@builder.io/sdk:Element',
    layerName: 'Accordion item title',
    responsiveStyles: {
        large: {
            marginTop: '10px',
            position: 'relative',
            display: 'flex',
            alignItems: 'stretch',
            flexDirection: 'column',
            paddingBottom: '10px'
        }
    },
    children: [
        {
            '@type': '@builder.io/sdk:Element',
            responsiveStyles: {
                large: {
                    textAlign: 'left',
                    display: 'flex',
                    flexDirection: 'column'
                }
            },
            component: {
                name: 'Text',
                options: {
                    text: 'I am an accordion title. Click me!'
                }
            }
        }
    ]
};
var defaultDetail = {
    '@type': '@builder.io/sdk:Element',
    layerName: 'Accordion item detail',
    responsiveStyles: {
        large: {
            position: 'relative',
            display: 'flex',
            alignItems: 'stretch',
            flexDirection: 'column',
            marginTop: '10px',
            paddingBottom: '10px'
        }
    },
    children: [
        {
            '@type': '@builder.io/sdk:Element',
            responsiveStyles: {
                large: {
                    paddingTop: '50px',
                    textAlign: 'left',
                    display: 'flex',
                    flexDirection: 'column',
                    paddingBottom: '50px'
                }
            },
            component: {
                name: 'Text',
                options: {
                    text: 'I am an accordion detail, hello!'
                }
            }
        }
    ]
};
// TODO: change to slick grid
var BuilderAccordionComponent = /** @class */ (function (_super) {
    __extends(BuilderAccordionComponent, _super);
    function BuilderAccordionComponent() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.divRef = null;
        _this.state = {
            open: []
        };
        return _this;
    }
    BuilderAccordionComponent.prototype.componentDidMount = function () {
        var _this = this;
        setTimeout(function () {
            if (_this.divRef) {
                _this.divRef.dispatchEvent(new CustomEvent('builder:accordion:load', {
                    bubbles: true,
                    cancelable: false,
                    detail: {
                        ref: _this
                    }
                }));
            }
        });
    };
    BuilderAccordionComponent.prototype.getAccordionItem = function (titleBlocks, detailBlocks, index, openGridItemOrder, onlyOneAtATime, fromChildren) {
        var _this = this;
        if (fromChildren === void 0) { fromChildren = false; }
        var open = this.state.open.indexOf(index) !== -1;
        var grid = this.props.grid;
        return (
        // This will not work as expected with react 15
        // Did preact get the span replacmenet too?
        React.createElement("span", { key: index },
            React.createElement("div", { className: "builder-accordion-title builder-accordion-title-" + (open ? 'open' : 'closed'), style: __assign({ cursor: 'pointer', display: 'flex', flexDirection: 'column', alignItems: 'stretch' }, (grid && __assign({ width: this.props.gridRowWidth }, (typeof openGridItemOrder === 'number' && {
                    order: index < openGridItemOrder ? index : index + 1
                })))), "data-index": index, onClick: function () {
                    if (open) {
                        _this.setState(__assign(__assign({}, _this.state), { open: onlyOneAtATime ? [] : _this.state.open.filter(function (item) { return item !== index; }) }));
                    }
                    else {
                        _this.setState(__assign(__assign({}, _this.state), { open: onlyOneAtATime ? [index] : _this.state.open.concat(index) }));
                    }
                } }, fromChildren ? (titleBlocks.map(function (block, index) { return (React.createElement(BuilderBlockComponent, { key: index, block: __assign(__assign({}, block), { repeat: null }), index: index, child: true })); })) : (React.createElement(BuilderBlocks, { blocks: titleBlocks, dataPath: "items." + index + ".title" }))),
            open && (React.createElement("div", { className: "builder-accordion-detail builder-accordion-detail-" + (open ? 'open' : 'closed'), style: __assign({ order: typeof openGridItemOrder === 'number' ? openGridItemOrder : undefined, maxHeight: this.props.animate ? (open ? '100vh' : 0) : undefined, transition: this.props.animate ? 'max-height 0.5s' : undefined }, (grid && {
                    width: '100%'
                })) }, open &&
                (fromChildren ? (detailBlocks.map(function (block, index) { return (React.createElement(BuilderBlockComponent, { key: index, block: __assign(__assign({}, block), { repeat: null }), index: index, child: true })); })) : (React.createElement(BuilderBlocks, { blocks: detailBlocks, dataPath: "items." + index + ".detail" })))))));
    };
    BuilderAccordionComponent.prototype.render = function () {
        var _this = this;
        var _a = this.props, grid = _a.grid, oneAtATime = _a.oneAtATime;
        var onlyOneAtATime = Boolean(grid || oneAtATime);
        var getOpenGridItemPosition = grid && this.state.open.length;
        var openGridItemOrder = null;
        if (getOpenGridItemPosition && this.divRef) {
            var openItemIndex = this.state.open[0];
            var openItem = this.divRef.querySelector(".builder-accordion-title[data-index=\"" + openItemIndex + "\"]");
            var subjectItem = openItem;
            openGridItemOrder = openItemIndex;
            if (subjectItem) {
                var prevItemRect = subjectItem.getBoundingClientRect();
                while ((subjectItem = subjectItem && subjectItem.nextElementSibling)) {
                    if (subjectItem) {
                        if (subjectItem.classList.contains('builder-accordion-detail')) {
                            continue;
                        }
                        var subjectItemRect = subjectItem.getBoundingClientRect();
                        if (subjectItemRect.left > prevItemRect.left) {
                            var index = parseInt(subjectItem.getAttribute('data-index') || '', 10);
                            if (!isNaN(index)) {
                                prevItemRect = subjectItemRect;
                                openGridItemOrder = index;
                            }
                        }
                        else {
                            break;
                        }
                    }
                }
            }
        }
        if (typeof openGridItemOrder === 'number') {
            openGridItemOrder = openGridItemOrder + 1;
        }
        return (React.createElement(BuilderAsyncRequestsContext.Consumer, null, function (value) {
            _this._errors = value && value.errors;
            _this._logs = value && value.logs;
            return (React.createElement(BuilderStoreContext.Consumer, null, function (state) { return (React.createElement("div", { ref: function (ref) { return (_this.divRef = ref); }, className: "builder-accordion", style: __assign({ display: 'flex', alignItems: 'stretch', flexDirection: 'column' }, (grid && {
                    flexDirection: 'row',
                    alignItems: 'flex-start',
                    flexWrap: 'wrap'
                })) }, _this.props.useChildrenForItems
                ? _this.props.builderBlock &&
                    _this.props.builderBlock.children &&
                    _this.props.builderBlock.children.map(function (block, index) {
                        if (block.repeat && block.repeat.collection) {
                            var collectionPath = block.repeat.collection;
                            var collectionName = last((collectionPath || '')
                                .split(/\.\w+\(/)[0]
                                .trim()
                                .split('.'));
                            var itemName_1 = block.repeat.itemName ||
                                (collectionName ? collectionName + 'Item' : 'item');
                            var array = stringToFunction(collectionPath, true, _this._errors, _this._logs)(state.state);
                            if (isArray(array)) {
                                return array.map(function (data, index) {
                                    var _a;
                                    // TODO: Builder state produce the data
                                    var childState = __assign(__assign({}, state.state), (_a = { $index: index, $item: data }, _a[itemName_1] = data, _a));
                                    return (React.createElement(BuilderStoreContext.Provider, { key: block.id, value: __assign(__assign({}, state), { state: childState }) }, _this.getAccordionItem(block.children ? [block.children[0]] : [], block.children ? [block.children[1]] : [], index, openGridItemOrder, onlyOneAtATime, true)));
                                });
                            }
                        }
                        return _this.getAccordionItem(block.children ? [block.children[0]] : [], block.children ? [block.children[1]] : [], index, openGridItemOrder, onlyOneAtATime, true);
                    })
                : _this.props.items &&
                    _this.props.items.map(function (item, index) {
                        return _this.getAccordionItem(item.title, item.detail, index, openGridItemOrder, onlyOneAtATime);
                    }))); }));
        }));
    };
    return BuilderAccordionComponent;
}(React.Component));
var BuilderAccordion = withBuilder(BuilderAccordionComponent, {
    name: 'Builder:Accordion',
    canHaveChildren: true,
    image: 'https://cdn.builder.io/api/v1/image/assets%2FagZ9n5CUKRfbL9t6CaJOyVSK4Es2%2Ffab6c1fd3fe542408cbdec078bca7f35',
    defaultStyles: {
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'stretch'
    },
    inputs: [
        {
            name: 'items',
            type: 'list',
            subFields: [
                {
                    name: 'title',
                    type: 'uiBlocks',
                    hideFromUI: true,
                    defaultValue: [defaultTitle]
                },
                {
                    name: 'detail',
                    type: 'uiBlocks',
                    hideFromUI: true,
                    defaultValue: [defaultDetail]
                }
            ],
            defaultValue: [
                {
                    title: [defaultTitle],
                    detail: [defaultDetail]
                },
                {
                    title: [defaultTitle],
                    detail: [defaultDetail]
                }
            ],
            showIf: function (options) { return !options.get('useChildrenForItems'); }
        },
        {
            name: 'oneAtATime',
            helperText: 'Only allow opening one at a time (collapse all others when new item openned)',
            type: 'boolean',
            defaultValue: false
        },
        {
            name: 'animate',
            helperText: 'Animate openning and closing',
            type: 'boolean',
            defaultValue: true
        },
        {
            name: 'grid',
            helperText: 'Display as a grid',
            type: 'boolean',
            defaultValue: false
        },
        {
            name: 'gridRowWidth',
            helperText: 'Display as a grid',
            type: 'string',
            showIf: function (options) { return options.get('grid'); },
            defaultValue: '25%'
        },
        {
            name: 'useChildrenForItems',
            type: 'boolean',
            helperText: 'Use child elements for each slide, instead of the array. Useful for dynamically repeating items',
            advanced: true,
            defaultValue: false,
            onChange: function (options) {
                if (options.get('useChildrenForItems') === true) {
                    options.set('items', []);
                }
            }
        }
        // TODO: best way to do this? how multiple, comma? All with "*"? Have as a per item option?
        // {
        //   name: 'defaultOpen',
        //   helperText: 'Number of the accordion item to have open default (e.g. choose 1 for the first)',
        // }
    ]
});

var defaultTile = {
    '@type': '@builder.io/sdk:Element',
    responsiveStyles: {
        large: {
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'stretch',
            position: 'relative',
            flexShrink: '0',
            boxSizing: 'border-box',
            marginTop: '20px',
            minHeight: '20px',
            minWidth: '20px',
            overflow: 'hidden',
            marginLeft: '20px'
        }
    },
    component: {
        name: 'Image',
        options: {
            image: 'https://builder.io/api/v1/image/assets%2Fpwgjf0RoYWbdnJSbpBAjXNRMe9F2%2Ffb27a7c790324294af8be1c35fe30f4d?width=2000&height=1200',
            backgroundSize: 'cover',
            backgroundPosition: 'center',
            aspectRatio: 0.7041
        }
    }
};
var getRandomAspectTile = function () { return (__assign(__assign({}, defaultTile), { component: __assign(__assign({}, defaultTile.component), { options: __assign(__assign({}, defaultTile.component.options), { 
            // range from 0.5 to 2, rounded to 2 decimal points
            aspectRatio: Math.round((Math.random() * 1.5 + 0.5) * 100) / 100 }) }) })); };
// TODO: column with, gutter, etc options
var BuilderMasonryComponent = /** @class */ (function (_super) {
    __extends(BuilderMasonryComponent, _super);
    function BuilderMasonryComponent() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.divRef = null;
        _this.masonryRef = null;
        _this.state = {
            layoutComplete: false
        };
        return _this;
    }
    BuilderMasonryComponent.prototype.componentDidMount = function () {
        var _this = this;
        setTimeout(function () {
            if (_this.divRef) {
                _this.divRef.dispatchEvent(new CustomEvent('builder:masonry:load', {
                    bubbles: true,
                    cancelable: false,
                    detail: {
                        block: _this.props.builderBlock,
                        ref: _this.divRef,
                        masonry: _this.masonryRef
                    }
                }));
            }
            if (Builder.isEditing) ;
        });
    };
    BuilderMasonryComponent.prototype.render = function () {
        var _this = this;
        var slides = this.props.tiles;
        // if (slides && !Builder.isBrowser) {
        //   slides = slides.slice(0, 1)
        // }
        var itemStyle = {
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'stretch',
            width: this.props.columnWidth
        };
        return (React.createElement("div", { style: {
                opacity: Builder.isBrowser && this.state.layoutComplete ? 1 : 0,
                transition: 'opacity 0.2s'
            } },
            React.createElement(BuilderAsyncRequestsContext.Consumer, null, function (value) {
                _this._errors = value && value.errors;
                _this._logs = value && value.logs;
                return (React.createElement(BuilderStoreContext.Consumer, null, function (state) { return (React.createElement("div", { ref: function (ref) { return (_this.divRef = ref); }, className: "builder-masonry" },
                    React.createElement(Masonry, { onLayoutComplete: function () {
                            if (!_this.state.layoutComplete) {
                                _this.setState(__assign(__assign({}, _this.state), { layoutComplete: true }));
                            }
                        }, options: {
                            gutter: _this.props.gutterSize,
                            // Maybe us this
                            fitWidth: _this.props.columnWidth && _this.props.columnWidth.endsWith('%')
                                ? false
                                : true,
                            percentPosition: 
                            // TODO: option to override this too
                            (_this.props.columnWidth &&
                                (_this.props.columnWidth.endsWith('%') ||
                                    _this.props.columnWidth.startsWith('.'))) ||
                                false
                        }, ref: function (ref) { return (_this.masonryRef = ref); } }, _this.props.useChildrenForTiles
                        ? _this.props.builderBlock &&
                            _this.props.builderBlock.children &&
                            _this.props.builderBlock.children.map(function (block, index) {
                                if (block.repeat && block.repeat.collection) {
                                    var collectionPath = block.repeat.collection;
                                    var collectionName = last((collectionPath || '')
                                        .split(/\.\w+\(/)[0]
                                        .trim()
                                        .split('.'));
                                    var itemName_1 = block.repeat.itemName ||
                                        (collectionName ? collectionName + 'Item' : 'item');
                                    var array = stringToFunction(collectionPath, true, _this._errors, _this._logs)(state.state);
                                    if (isArray(array)) {
                                        if (!Builder.isBrowser) {
                                            array = array.slice(0, 1);
                                        }
                                        return array.map(function (data, index) {
                                            var _a;
                                            // TODO: Builder state produce the data
                                            var childState = __assign(__assign({}, state.state), (_a = { $index: index, $item: data }, _a[itemName_1] = data, _a));
                                            return (React.createElement("div", { className: "masonry-item", style: itemStyle },
                                                React.createElement(BuilderStoreContext.Provider, { key: block.id, value: __assign(__assign({}, state), { state: childState }) },
                                                    React.createElement(BuilderBlockComponent, { block: __assign(__assign({}, block), { repeat: null }), index: index, child: true }))));
                                        });
                                    }
                                }
                                return (React.createElement("div", { style: itemStyle, className: "masonry-item" },
                                    React.createElement(BuilderBlockComponent, { key: block.id, block: block, index: index, child: true })));
                            })
                        : _this.props.tiles &&
                            _this.props.tiles.map(function (tile, index) { return (
                            // TODO: how make react compatible with plain react components
                            // tiles: <Foo><Bar> <- builder blocks if passed react nodes as blocks just forward them
                            React.createElement("div", { style: itemStyle, className: "masonry-item" },
                                React.createElement(BuilderBlocks, { key: index, parentElementId: _this.props.builderBlock && _this.props.builderBlock.id, dataPath: "component.options.tiles." + index + ".content", child: true, blocks: tile.content || tile }))); })))); }));
            })));
    };
    return BuilderMasonryComponent;
}(React.Component));
var BuilderMasonry = withBuilder(BuilderMasonryComponent, {
    name: 'Builder:Masonry',
    // TODO: default children
    image: 'https://cdn.builder.io/api/v1/image/assets%2FBvYIl5jKN9QpChUB3PVzsTe2ZSI2%2F7ed6bd8129d148608ecec09300786d71?width=2000&height=1200',
    canHaveChildren: true,
    defaultStyles: {
        paddingLeft: '20px',
        paddingRight: '20px',
        paddingBottom: '20px'
    },
    defaultChildren: [
        getRandomAspectTile(),
        getRandomAspectTile(),
        getRandomAspectTile(),
        getRandomAspectTile(),
        getRandomAspectTile(),
        getRandomAspectTile(),
        getRandomAspectTile(),
        getRandomAspectTile(),
        getRandomAspectTile()
    ],
    inputs: [
        {
            name: 'columnWidth',
            // TODO: type: 'styleNumber'
            type: 'string',
            helperText: 'Width of each tile, as a CSS value. E.g. "200px" or "50%"',
            defaultValue: '200px'
        },
        {
            name: 'gutterSize',
            type: 'number',
            helperText: 'Horizontal space between tiles in pixels, e.g. "20" for 20 pixels wide',
            defaultValue: 0,
            advanced: true
        },
        {
            name: 'tiles',
            type: 'list',
            subFields: [
                {
                    name: 'content',
                    type: 'uiBlocks',
                    hideFromUI: true,
                    defaultValue: [defaultTile]
                }
            ],
            defaultValue: [],
            showIf: function (options) { return !options.get('useChildrenForTiles'); }
        },
        {
            name: 'useChildrenForTiles',
            type: 'boolean',
            helperText: 'Use child elements for each slide, instead of the array. Useful for dynamically repeating tiles',
            advanced: true,
            defaultValue: true,
            onChange: function (options) {
                if (options.get('useChildrenForTiles') === true) {
                    options.set('tiles', []);
                }
            }
        }
    ]
});

export { BuilderCarousel, Tabs, BuilderAccordion, BuilderMasonryComponent, BuilderMasonry };
//# sourceMappingURL=15.esm.js.map
