UNPKG

survey-creator-react

Version:

Use SurveyJS Creator to create or edit JSON for SurveyJS Form Library.

1,093 lines (1,068 loc) 139 kB
/*! * SurveyJS Creator React v2.3.1 * (c) 2015-2025 Devsoft Baltic OÜ - http://surveyjs.io/ * Github: https://github.com/surveyjs/survey-creator * License: https://surveyjs.io/Licenses#SurveyCreator */ import * as React from 'react'; import { createElement, Fragment } from 'react'; import { ReactElementFactory, SurveyElementBase, attachKey2click, SvgIcon, Survey, ReactQuestionFactory, SurveyLocStringViewer, SvgBundleComponent, PopupModal, SurveyActionBar, NotifierComponent, TitleElement, ReactSurveyElementsWrapper, LoadingIndicatorComponent, SurveyPage, Popup, LogoImage, SurveyQuestionElementBase, SurveyQuestion, Scroll, CharacterCounterComponent, SurveyQuestionDropdown, SurveyHeader, List, SurveyQuestionText } from 'survey-react-ui'; import { SurveyCreatorModel, assign, RowViewModel, QuestionAdornerViewModel, QuestionDropdownAdornerViewModel, QuestionImageAdornerViewModel, QuestionRatingAdornerViewModel, PageAdorner, LogoImageViewModel, editorLocalization, ItemValueWrapperViewModel, ImageItemValueWrapperViewModel, MatrixCellWrapperViewModel, SurveyResultsModel, ToolboxToolViewModel, editableStringRendererName, StringEditorViewModelBase, initLogicOperator, PageNavigatorViewModel } from 'survey-creator-core'; export { PropertyGridEditorCollection, SurveyLogic, SurveyLogicUI, SurveyQuestionEditorDefinition, ToolboxToolViewModel, editorLocalization, localization, settings, svgBundle } from 'survey-creator-core'; import * as ReactDOM from 'react-dom'; import { CssClassBuilder, settings, RendererFactory, unwrap, checkLibraryVersion } from 'survey-core'; class TabbedMenuComponent extends SurveyElementBase { get model() { return this.props.model; } getStateElement() { return this.model; } constructor(props) { super(props); this.rootRef = React.createRef(); } renderElement() { const items = this.model.renderedActions.map((item) => React.createElement(TabbedMenuItemWrapper, { item: item, key: item.renderedId })); return (React.createElement("div", { ref: this.rootRef, className: "svc-tabbed-menu", role: "tablist", style: this.model.getRootStyle() }, items)); } componentDidUpdate(prevProps, prevState) { super.componentDidUpdate(prevProps, prevState); const container = this.rootRef.current; if (!container) return; this.model.initResponsivityManager(container); } componentDidMount() { super.componentDidMount(); const container = this.rootRef.current; if (!container) return; this.model.initResponsivityManager(container); } componentWillUnmount() { this.model.resetResponsivityManager(); super.componentWillUnmount(); } } class TabbedMenuItemWrapper extends SurveyElementBase { constructor(props) { super(props); this.ref = React.createRef(); } get item() { return this.props.item; } getStateElement() { return this.item; } renderElement() { let css = "svc-tabbed-menu-item-container"; if (this.item.css) { css += " " + this.item.css; } css += (!this.item.isVisible ? " sv-action--hidden" : ""); const component = ReactElementFactory.Instance.createElement(this.item.component || "svc-tabbed-menu-item", { item: this.item }); return (React.createElement("span", { key: this.item.id, className: css, ref: this.ref }, React.createElement("div", { className: "sv-action__content" }, component))); } componentDidMount() { super.componentDidMount(); this.item.updateModeCallback = (mode, callback) => { queueMicrotask(() => { if (ReactDOM["flushSync"]) { ReactDOM["flushSync"](() => { this.item.mode = mode; }); } else { this.item.mode = mode; } queueMicrotask(() => { callback(mode, this.ref.current); }); }); }; this.item.afterRender(); } componentWillUnmount() { super.componentWillUnmount(); this.item.updateModeCallback = undefined; } } class TabbedMenuItemComponent extends SurveyElementBase { get item() { return this.props.item; } getStateElement() { return this.item; } render() { const item = this.item; return (attachKey2click(React.createElement("div", { role: "tab", id: "tab-" + item.id, "aria-selected": item.active, "aria-controls": "scrollableDiv-" + item.id, className: item.getRootCss(), onClick: () => item.action(item) }, item.hasTitle ? React.createElement("span", { className: item.getTitleCss() }, item.title) : null, item.hasIcon ? React.createElement(SvgIcon, { iconName: item.iconName, className: item.getIconCss(), size: "auto", title: item.tooltip || item.title }) : null))); } } ReactElementFactory.Instance.registerElement("svc-tabbed-menu-item", (props) => { return React.createElement(TabbedMenuItemComponent, props); }); class SurveyCreatorComponent extends SurveyElementBase { constructor(props) { super(props); this.rootNode = React.createRef(); } get creator() { return this.props.creator; } getStateElement() { return this.creator; } get style() { return this.props.style; } componentDidUpdate(prevProps, prevState) { super.componentDidUpdate(prevProps, prevState); if (this.creator !== prevProps.creator) { if (prevProps.creator) { prevProps.creator.unsubscribeRootElement(); } if (this.creator && this.rootNode.current) { this.creator.setRootElement(this.rootNode.current); } } } componentDidMount() { super.componentDidMount(); this.creator.setRootElement(this.rootNode.current); } componentWillUnmount() { super.componentWillUnmount(); this.creator.unsubscribeRootElement(); } renderElement() { const creator = this.props.creator; if (creator.isCreatorDisposed) return null; const areaClassName = "svc-full-container svc-creator__area svc-flex-column" + (this.props.creator.haveCommercialLicense ? "" : " svc-creator__area--with-banner"); const contentWrapperClassName = "svc-creator__content-wrapper svc-flex-row" + (this.props.creator.isMobileView ? " svc-creator__content-wrapper--footer-toolbar" : ""); const fullContainerClassName = "svc-flex-row svc-full-container" + (" svc-creator__side-bar--" + this.creator.sidebarLocation); const creatorStyles = {}; assign(creatorStyles, this.style, this.props.creator.themeVariables); let licenseBanner = null; if (!this.props.creator.haveCommercialLicense) { const htmlValue = { __html: this.props.creator.licenseText }; licenseBanner = (React.createElement("div", { className: "svc-creator__banner" }, React.createElement("span", { className: "svc-creator__non-commercial-text", dangerouslySetInnerHTML: htmlValue }))); } //AM: width unrecognized by react return (React.createElement("div", { className: this.creator.getRootCss(), ref: this.rootNode, style: creatorStyles }, React.createElement(SvgBundleComponent, null), React.createElement(PopupModal, null), React.createElement("div", { className: areaClassName }, React.createElement("div", { className: fullContainerClassName }, React.createElement("div", { className: "svc-flex-column svc-flex-row__element svc-flex-row__element--growing" }, React.createElement("div", { className: "svc-top-bar" }, (creator.showTabs ? React.createElement("div", { className: "svc-tabbed-menu-wrapper" }, React.createElement(TabbedMenuComponent, { model: creator.tabbedMenu })) : null), (creator.showToolbar ? React.createElement("div", { className: "svc-toolbar-wrapper" }, React.createElement(SurveyActionBar, { model: creator.toolbar })) : null)), React.createElement("div", { className: contentWrapperClassName }, React.createElement("div", { className: "svc-creator__content-holder svc-flex-column" }, this.renderActiveTab())), React.createElement("div", { className: "svc-footer-bar" }, (creator.isMobileView ? React.createElement("div", { className: "svc-toolbar-wrapper" }, React.createElement(SurveyActionBar, { model: creator.footerToolbar })) : null))), this.renderSidebar()), licenseBanner, React.createElement(NotifierComponent, { notifier: creator.notifier })))); } renderActiveTab() { const creator = this.props.creator; for (var i = 0; i < creator.tabs.length; i++) { if (creator.tabs[i].id === creator.activeTab) { return this.renderCreatorTab(creator.tabs[i]); } } return null; } renderCreatorTab(tab) { if (tab.visible === false) { return null; } const creator = this.props.creator; const component = !!tab.renderTab ? tab.renderTab() : ReactElementFactory.Instance.createElement(tab.componentContent, { creator: creator, survey: creator.survey, data: tab.data.model }); const className = "svc-creator-tab" + (creator.toolboxLocation == "right" ? " svc-creator__toolbox--right" : ""); return (React.createElement("div", { role: "tabpanel", key: tab.id, id: "scrollableDiv-" + tab.id, "aria-labelledby": "tab-" + tab.id, className: className }, component)); } renderSidebar() { if (!!this.creator.sidebar) { return ReactElementFactory.Instance.createElement("svc-side-bar", { model: this.creator.sidebar }); } else { return null; } } } class SurveyCreator extends SurveyCreatorModel { constructor(options = {}, options2) { super(options, options2); } render(target) { // eslint-disable-next-line no-console console.error("The render method is deprecated. Use SurveyCreatorComponent instead."); } //ISurveyCreator createQuestionElement(question) { return ReactQuestionFactory.Instance.createQuestion(question.isDefaultRendering() ? question.getTemplate() : question.getComponentName(), { question: question, isDisplayMode: question.isReadOnly, creator: this }); } renderError(key, error, cssClasses) { return (React.createElement("div", { key: key }, React.createElement("span", { className: cssClasses.error.icon, "aria-hidden": "true" }), React.createElement("span", { className: cssClasses.error.item }, React.createElement(SurveyLocStringViewer, { locStr: error.locText })))); } questionTitleLocation() { return this.survey.questionTitleLocation; } questionErrorLocation() { return this.survey.questionErrorLocation; } } ReactElementFactory.Instance.registerElement("survey-widget", (props) => { return React.createElement(Survey, props); }); class CreatorModelElement extends SurveyElementBase { constructor(props) { super(props); this.createModel(props); } shouldComponentUpdate(nextProps, nextState) { const result = super.shouldComponentUpdate(nextProps, nextState); if (result) { if (this.needUpdateModel(nextProps)) { this.createModel(nextProps); } } return result; } createModel(props) { } needUpdateModel(nextProps) { const names = this.getUpdatedModelProps(); if (!Array.isArray(names)) return true; for (var i = 0; i < names.length; i++) { const key = names[i]; if (this.props[key] !== nextProps[key]) return true; } return false; } getUpdatedModelProps() { return undefined; } } class RowWrapper extends CreatorModelElement { constructor(props) { super(props); } createModel(props) { if (!!this.model) { this.model.dispose(); } this.model = new RowViewModel(props.componentData.creator, props.row, null); } getUpdatedModelProps() { return ["row", "componentData"]; } getStateElement() { return this.model; } componentDidMount() { super.componentDidMount(); this.model.subscribeElementChanges(); } componentWillUnmount() { this.model.unsubscribeElementChanges(); super.componentWillUnmount(); } render() { return (React.createElement("div", { key: "svc-row-" + this.props.row.id, className: this.model.cssClasses }, React.createElement("div", { className: "svc-row__drop-indicator svc-row__drop-indicator--top" }), React.createElement("div", { className: "svc-row__drop-indicator svc-row__drop-indicator--bottom" }), this.props.element)); } } ReactElementFactory.Instance.registerElement("svc-row", (props) => { return React.createElement(RowWrapper, props); }); class ReactMouseEvent { constructor(event) { this.event = event; } stopPropagation() { this.event.stopPropagation(); //this.event.nativeEvent.stopPropagation(); //this.event.nativeEvent.stopImmediatePropagation(); } preventDefault() { this.event.preventDefault(); //this.event.nativeEvent.preventDefault(); } get cancelBubble() { //return this.event.cancelBubble; return false; } set cancelBubble(value) { //this.event.cancelBubble = value; } get target() { return this.event.target; } get currentTarget() { return this.event.currentTarget; } get clientX() { return this.event.clientX; } get clientY() { return this.event.clientY; } get offsetX() { return this.event.nativeEvent.offsetX; } get offsetY() { return this.event.nativeEvent.offsetY; } } class ReactDragEvent extends ReactMouseEvent { constructor(event) { super(event); this.event = event; } get dataTransfer() { return this.event.dataTransfer; } } function QuestionElementContentFunc(props) { return props.element; } const QuestionElementContent = React.memo(QuestionElementContentFunc); QuestionElementContent.displayName = "QuestionElementContent"; class QuestionAdornerComponent extends CreatorModelElement { constructor(props) { super(props); this.rootRef = React.createRef(); } createModel(props) { if (this.model) { this.model.attachToUI(props.question, this.rootRef.current); } else { this.modelValue = this.createQuestionViewModel(props); } } createQuestionViewModel(props) { return new QuestionAdornerViewModel(props.componentData, props.question, null); } getUpdatedModelProps() { return ["question", "componentData"]; } get model() { return this.modelValue; } getStateElement() { return this.model; } renderElement() { const allowInteractions = this.model.element .isInteractiveDesignElement; const titleForCollapsedState = this.renderQuestionTitle(); const content = this.renderContent(allowInteractions); return (React.createElement("div", { ref: this.rootRef, "data-sv-drop-target-survey-element": this.model.element.name || null, className: this.model.rootCss(), onDoubleClick: e => { allowInteractions && this.model.dblclick(e.nativeEvent); e.stopPropagation(); }, onMouseLeave: e => allowInteractions && this.model.hover(e.nativeEvent, e.currentTarget), onMouseOver: e => allowInteractions && this.model.hover(e.nativeEvent, e.currentTarget) }, titleForCollapsedState, content)); } disableTabStop() { return true; } renderContent(allowInteractions) { var content = this.model.needToRenderContent ? this.renderElementContent() : null; //if (!allowInteractions) return <>{content}{this.renderFooter()}</>; return attachKey2click(React.createElement("div", { className: this.model.css(), onClick: (e) => this.model.select(this.model, new ReactMouseEvent(e)) }, React.createElement("div", { className: "svc-question__drop-indicator svc-question__drop-indicator--left" }), React.createElement("div", { className: "svc-question__drop-indicator svc-question__drop-indicator--right" }), React.createElement("div", { className: "svc-question__drop-indicator svc-question__drop-indicator--top" }), React.createElement("div", { className: "svc-question__drop-indicator svc-question__drop-indicator--bottom" }), allowInteractions ? this.renderHeader() : null, content, this.model.needToRenderContent ? this.renderFooter() : null), undefined, { disableTabStop: this.disableTabStop() }); } renderHeader() { return ReactElementFactory.Instance.createElement("svc-question-header", { model: this.model }); } renderFooter() { const allowInteractions = this.model.element .isInteractiveDesignElement; return allowInteractions ? ReactElementFactory.Instance.createElement("svc-question-footer", { className: "svc-question__content-actions", model: this.model }) : null; } renderCarryForwardBanner() { if (!this.model.isBannerShowing) return null; return ReactElementFactory.Instance.createElement("svc-question-banner", this.model.createBannerParams()); } renderQuestionTitle() { if (!this.model.showHiddenTitle) return null; const element = this.model.element; return (React.createElement("div", { ref: node => node && (!this.model.renderedCollapsed ? node.setAttribute("inert", "") : node.removeAttribute("inert")), className: this.model.cssCollapsedHiddenHeader }, (element.hasTitle ? React.createElement(TitleElement, { element: element }) : React.createElement("div", { className: this.model.cssCollapsedHiddenTitle }, React.createElement("span", { className: "svc-fake-title" }, element.name))))); } renderElementContent() { return (React.createElement(React.Fragment, null, React.createElement(QuestionElementContent, { element: this.props.element }), this.renderElementPlaceholder(), this.renderCarryForwardBanner())); } componentDidMount() { super.componentDidMount(); this.model.attachToUI(this.props.question, this.rootRef.current); } renderElementPlaceholder() { if (!this.model.isEmptyElement) { return null; } return (React.createElement("div", { className: "svc-panel__placeholder_frame-wrapper" }, React.createElement("div", { className: "svc-panel__placeholder_frame" }, React.createElement("div", { className: "svc-panel__placeholder" }, this.model.placeholderText)))); } componentWillUnmount() { super.componentWillUnmount(); this.model.detachFromUI(); } } ReactElementFactory.Instance.registerElement("svc-question", (props) => { return React.createElement(QuestionAdornerComponent, props); }); class QuestionWrapperHeader extends React.Component { render() { if (!this.props.model.allowDragging) return null; return (React.createElement("div", { className: "svc-question__drag-area", onPointerDown: (event) => this.props.model.onPointerDown(event) }, React.createElement(SvgIcon, { className: "svc-question__drag-element", size: "auto", iconName: "icon-drag-area-indicator_24x16" }), React.createElement("div", { className: "svc-question__top-actions" }, React.createElement(SurveyActionBar, { model: this.props.model.topActionContainer, handleClick: false })))); } } ReactElementFactory.Instance.registerElement("svc-question-header", (props) => { return React.createElement(QuestionWrapperHeader, props); }); class QuestionWrapperFooter extends React.Component { render() { return (React.createElement("div", { className: this.props.className, onFocus: (e) => this.props.model.select(this.props.model, new ReactMouseEvent(e)) }, React.createElement(SurveyActionBar, { model: this.props.model.actionContainer, handleClick: false }))); } } ReactElementFactory.Instance.registerElement("svc-question-footer", (props) => { return React.createElement(QuestionWrapperFooter, props); }); class ActionButton extends SurveyElementBase { renderElement() { const classes = new CssClassBuilder() .append(this.props.classes) .append("svc-action-button") .append("svc-action-button--selected", !!this.props.selected) .append("svc-action-button--disabled", !!this.props.disabled) .toString(); if (this.props.iconName) { return this.renderIcon(classes); } return this.renderButtonText(classes); } renderButtonText(classes) { if (this.props.disabled) { return React.createElement("span", { className: classes }, this.props.text); } return (React.createElement(React.Fragment, null, attachKey2click(React.createElement("span", { role: "button", className: classes, onClick: (e) => { if (!this.props.allowBubble) { e.stopPropagation(); } this.props.click(); }, title: this.props.title }, this.props.text)))); } renderIcon(classes) { classes += " svc-action-button--icon"; if (this.props.disabled) { return React.createElement("span", { className: classes }, React.createElement(SvgIcon, { size: "auto", iconName: this.props.iconName })); } return (React.createElement(React.Fragment, null, attachKey2click(React.createElement("span", { className: classes, onClick: (e) => { if (!this.props.allowBubble) { e.stopPropagation(); } this.props.click(); }, title: this.props.title }, React.createElement(SvgIcon, { size: "auto", iconName: this.props.iconName }))))); } } ReactElementFactory.Instance.registerElement("svc-action-button", (props) => { return React.createElement(ActionButton, props); }); class QuestionBanner extends React.Component { render() { return (React.createElement("div", { className: "svc-carry-forward-panel-wrapper" }, React.createElement("div", { className: "svc-carry-forward-panel" }, React.createElement("span", null, this.props.text, " "), React.createElement("span", { className: "svc-carry-forward-panel__link" }, React.createElement(ActionButton, { click: () => this.props.onClick(), text: this.props.actionText }))))); } } ReactElementFactory.Instance.registerElement("svc-question-banner", (props) => { return React.createElement(QuestionBanner, props); }); class QuestionDropdownAdornerComponent extends QuestionAdornerComponent { constructor(props) { super(props); } createQuestionViewModel(props) { return new QuestionDropdownAdornerViewModel(props.componentData, props.question, null); } get dropdownModel() { return this.model; } get question() { return this.dropdownModel.question; } renderElementPlaceholder() { const textStyle = this.question.textStyle; return (React.createElement("div", { className: "svc-question__dropdown-choices--wrapper" }, React.createElement("div", null, React.createElement("div", { className: "svc-question__dropdown-choices" }, (this.dropdownModel.getRenderedItems() || []).map((item, index) => (React.createElement("div", { className: this.dropdownModel.getChoiceCss(), key: `editable_choice_${index}` }, ReactSurveyElementsWrapper.wrapItemValue(this.question.survey, ReactElementFactory.Instance.createElement(this.dropdownModel.itemComponent, { key: item.value, question: this.question, cssClasses: this.question.cssClasses, isDisplayMode: true, item: item, textStyle: textStyle, index: index, isChecked: this.question.value === item.value }), this.question, item))))), this.dropdownModel.needToCollapse ? React.createElement(ActionButton, { click: this.dropdownModel.switchCollapse, text: this.dropdownModel.getButtonText(), allowBubble: true }) : null))); } } ReactElementFactory.Instance.registerElement("svc-dropdown-question", (props) => { return React.createElement(QuestionDropdownAdornerComponent, props); }); class QuestionImageAdornerComponent extends QuestionAdornerComponent { createQuestionViewModel(props) { return new QuestionImageAdornerViewModel(props.componentData, props.question, null); } get imageModel() { return this.model; } renderHeader() { return (React.createElement(React.Fragment, null, React.createElement("input", { type: "file", "aria-hidden": "true", tabIndex: -1, accept: this.imageModel.acceptedTypes, className: "svc-choose-file-input", style: { position: "absolute", opacity: 0, width: "1px", height: "1px", overflow: "hidden" } }), super.renderHeader())); } renderLoadingPlaceholder() { return (React.createElement("div", { className: "svc-image-question__loading-placeholder" }, React.createElement("div", { className: "svc-image-question__loading" }, React.createElement(LoadingIndicatorComponent, null)))); } renderChooseButton() { return (React.createElement("div", { className: "svc-image-question-controls" }, this.model.allowEdit ? attachKey2click(React.createElement("span", { className: "svc-context-button", onClick: () => this.imageModel.chooseFile(this.imageModel) }, React.createElement(SvgIcon, { size: "auto", iconName: "icon-choosefile" }))) : null)); } renderElementPlaceholder() { return this.imageModel.isUploading ? this.renderLoadingPlaceholder() : this.renderChooseButton(); } getStateElements() { return [this.model, this.imageModel.filePresentationModel]; } renderElementContent() { if (this.imageModel.isEmptyImageLink) { const fileQuestion = ReactQuestionFactory.Instance.createQuestion("file", { creator: this.imageModel.question.survey, isDisplayMode: false, question: this.imageModel.filePresentationModel }); return (React.createElement(React.Fragment, null, fileQuestion)); } else { return (React.createElement(React.Fragment, null, this.props.element, this.renderElementPlaceholder())); } } } ReactElementFactory.Instance.registerElement("svc-image-question", (props) => { return React.createElement(QuestionImageAdornerComponent, props); }); class QuestionRatingAdornerComponent extends CreatorModelElement { createModel(props) { this.modelValue = this.createQuestionViewModel(props); } createQuestionViewModel(props) { return new QuestionRatingAdornerViewModel(props.componentData, props.question, null); } getUpdatedModelProps() { return ["question", "componentData"]; } get ratingModel() { return this.model; } get model() { return this.modelValue; } getStateElement() { return this.model; } renderElement() { const model = this.ratingModel; return (React.createElement(React.Fragment, null, React.createElement("div", { className: "svc-rating-question-content" }, React.createElement("div", { className: model.controlsClassNames }, model.allowRemove ? attachKey2click(React.createElement("span", { role: "button", className: model.removeClassNames, "aria-label": model.removeTooltip, onClick: () => model.removeItem(model) }, React.createElement(SvgIcon, { size: "auto", iconName: "icon-remove_16x16", title: model.removeTooltip }))) : null, model.allowAdd ? attachKey2click(React.createElement("span", { role: "button", className: model.addClassNames, "aria-label": model.addTooltip, onClick: () => model.addItem(model) }, React.createElement(SvgIcon, { size: "auto", iconName: "icon-add_16x16", title: model.addTooltip }))) : null), this.props.element))); } } ReactElementFactory.Instance.registerElement("svc-rating-question", (props) => { return React.createElement(QuestionRatingAdornerComponent, props); }); ReactElementFactory.Instance.registerElement("svc-rating-question-content", (props) => { return React.createElement(QuestionRatingAdornerComponent, props); }); class QuestionWidgetAdornerComponent extends QuestionAdornerComponent { createQuestionViewModel(props) { return new QuestionAdornerViewModel(props.componentData, props.question, null); } get widgetModel() { return this.model; } renderElementContent() { return (React.createElement("div", { className: "svc-widget__content" }, this.props.element)); } } ReactElementFactory.Instance.registerElement("svc-widget-question", (props) => { return React.createElement(QuestionWidgetAdornerComponent, props); }); class CellQuestionAdornerComponent extends CreatorModelElement { createModel(props) { this.model = new QuestionAdornerViewModel(props.componentData, props.question, null); } getStateElement() { return this.model; } getUpdatedModelProps() { return ["question", "componentData"]; } render() { return (React.createElement(React.Fragment, null, React.createElement("div", { "data-sv-drop-target-survey-element": this.model.element.name, className: "svc-question__adorner" }, React.createElement("div", { className: " svc-question__content--in-popup svc-question__content" }, this.props.element)))); } } ReactElementFactory.Instance.registerElement("svc-cell-question", (props) => { return React.createElement(CellQuestionAdornerComponent, props); }); class CellQuestionDropdownAdornerComponent extends CreatorModelElement { createModel(props) { this.model = new QuestionAdornerViewModel(props.componentData, props.question, null); } getUpdatedModelProps() { return ["question", "componentData"]; } getStateElement() { return this.model; } render() { const question = this.props.question; const textStyle = this.props.question.textStyle; return (React.createElement(React.Fragment, null, React.createElement("div", { "data-sv-drop-target-survey-element": this.model.element.name, className: "svc-question__adorner" }, React.createElement("div", { className: " svc-question__content--in-popup svc-question__content" }, this.props.element, React.createElement("div", { className: "svc-question__dropdown-choices" }, question.visibleChoices.map((item, index) => (React.createElement("div", { className: "svc-question__dropdown-choice", key: `editable_choice_${index}` }, ReactSurveyElementsWrapper.wrapItemValue(question.survey, ReactElementFactory.Instance.createElement("survey-radiogroup-item", { question: question, cssClasses: question.cssClasses, isDisplayMode: true, item: item, textStyle: textStyle, index: index, isChecked: question.value === item.value }), question, item))))))))); } } ReactElementFactory.Instance.registerElement("svc-cell-dropdown-question", (props) => { return React.createElement(CellQuestionDropdownAdornerComponent, props); }); const PageElementContent = React.memo(({ page, survey, creator }) => { return React.createElement(SurveyPage, { page: page, survey: survey, creator: creator }); }); PageElementContent.displayName = "PageElementContent"; class CreatorSurveyPageComponent extends CreatorModelElement { constructor(props) { super(props); this.rootRef = React.createRef(); } createModel(props) { if (this.model) { this.model.attachToUI(props.page, this.rootRef.current); } this.model = this.createPageAdorner(props.creator, props.page); this.model.isGhost = this.props.isGhost; } createPageAdorner(creator, page) { return new PageAdorner(creator, page); } shouldComponentUpdate(nextProps, nextState) { const res = super.shouldComponentUpdate(nextProps, nextState); if (this.model) { this.model.isGhost = this.props.isGhost; } return res; } componentDidUpdate(prevProps, prevState) { super.componentDidUpdate(prevProps, prevState); } getUpdatedModelProps() { return ["creator", "page"]; } getStateElement() { return this.model; } componentDidMount() { super.componentDidMount(); this.model.attachToUI(this.props.page, this.rootRef.current); this.model.isGhost = this.props.isGhost; } componentWillUnmount() { super.componentWillUnmount(); this.model.detachFromUI(); } canRender() { return super.canRender(); } renderElement() { if (!this.props.page) return null; return (attachKey2click(React.createElement("div", { ref: this.rootRef, id: this.props.page.id, "data-sv-drop-target-survey-page": this.model.dropTargetName, className: "svc-page__content " + this.model.css, onClick: (e) => { return this.model.select(this.model, new ReactMouseEvent(e)); }, onDoubleClick: e => this.model.dblclick(e.nativeEvent), onMouseLeave: (e) => this.model.hover(e.nativeEvent, e.currentTarget), onMouseOver: (e) => this.model.hover(e.nativeEvent, e.currentTarget) }, React.createElement("div", { className: "svc-question__drop-indicator svc-question__drop-indicator--top" }), React.createElement("div", { className: "svc-question__drop-indicator svc-question__drop-indicator--bottom" }), this.renderContent(), this.renderPlaceholder(), this.renderHeader(), this.renderFooter()))); } renderPlaceholder() { if (!this.model.showPlaceholder) return null; return (React.createElement("div", { className: "svc-page__placeholder_frame" }, React.createElement("div", { className: "svc-panel__placeholder_frame" }, React.createElement("div", { className: "svc-panel__placeholder" }, this.model.placeholderText)))); } renderContent() { if (!this.model.needRenderContent) { return React.createElement("div", { className: "svc-page__loading-content" }, React.createElement(LoadingIndicatorComponent, null)); } return (React.createElement(PageElementContent, { page: this.props.page, survey: this.props.survey, creator: this.props.creator })); } renderHeader() { const actions = (React.createElement("div", { className: "svc-page__content-actions" }, React.createElement(SurveyActionBar, { model: this.model.actionContainer }), (this.model.topActionContainer.hasActions ? React.createElement(SurveyActionBar, { model: this.model.topActionContainer }) : null))); if (this.model.isGhost || !this.model.allowDragging) { return actions; } return (React.createElement("div", { className: "svc-question__drag-area", onPointerDown: (event) => this.model.onPointerDown(event) }, React.createElement(SvgIcon, { className: "svc-question__drag-element", size: "auto", iconName: "icon-drag-area-indicator_24x16" }), actions)); } renderFooter() { return React.createElement(SurveyActionBar, { model: this.model.footerActionsBar }); } } ReactElementFactory.Instance.registerElement("svc-page", (props) => { return React.createElement(CreatorSurveyPageComponent, props); }); class AddQuestionButtonComponent extends SurveyElementBase { get model() { return this.props.item.data; } renderTypeSelector() { const questionTypeSelectorModel = this.model.questionTypeSelectorModel; return attachKey2click(React.createElement("button", { type: "button", onClick: (e) => { e.stopPropagation(); questionTypeSelectorModel.action(); }, className: "svc-element__question-type-selector", title: this.model.addNewQuestionText, role: "button" }, React.createElement("span", { className: "svc-element__question-type-selector-icon" }, React.createElement(SvgIcon, { iconName: questionTypeSelectorModel.iconName, size: "auto", title: this.model.addNewQuestionText })), this.props.renderPopup === undefined || this.props.renderPopup ? React.createElement(Popup, { model: questionTypeSelectorModel.popupModel }) : null)); } renderElement() { const addButtonClass = this.props.buttonClass || "svc-btn"; return React.createElement(React.Fragment, null, attachKey2click(React.createElement("div", { className: "svc-element__add-new-question " + addButtonClass, onClick: (e) => { e.stopPropagation(); this.model.addNewQuestion(this.model, new ReactMouseEvent(e)); }, onMouseOver: (e) => this.model.hoverStopper && this.model.hoverStopper(e.nativeEvent, e.currentTarget) }, React.createElement(SvgIcon, { className: "svc-panel__add-new-question-icon", iconName: "icon-add_24x24", size: "auto" }), React.createElement("span", { className: "svc-add-new-item-button__text" }, this.model.addNewQuestionText), this.props.renderPopup !== false ? this.renderTypeSelector() : null)), this.props.renderPopup === false ? this.renderTypeSelector() : null); } } ReactElementFactory.Instance.registerElement("svc-add-new-question-btn", (props) => { return React.createElement(AddQuestionButtonComponent, props); }); class PanelAdornerComponent extends QuestionAdornerComponent { renderElementPlaceholder() { if (!this.model.isEmptyElement) { return null; } return (React.createElement("div", { className: "svc-panel__placeholder_frame-wrapper" }, React.createElement("div", { className: "svc-panel__placeholder_frame" }, React.createElement("div", { className: "svc-panel__placeholder" }, this.model.placeholderText), this.model.showAddQuestionButton ? attachKey2click(React.createElement("div", { className: "svc-panel__add-new-question svc-action-button", onClick: (e) => { e.stopPropagation(); this.model.addNewQuestion(); } }, React.createElement(SvgIcon, { className: "svc-panel__add-new-question-icon", iconName: "icon-add_24x24", size: "auto" }), React.createElement("span", { className: "svc-add-new-item-button__text" }, this.model.addNewQuestionText))) : null))); } disableTabStop() { return true; } renderFooter() { return (React.createElement(React.Fragment, null, !this.model.isEmptyElement && this.model.element.isPanel && this.model.showAddQuestionButton ? (React.createElement("div", { className: "svc-panel__add-new-question-container" }, React.createElement("div", { className: "svc-panel__question-type-selector-popup" }, React.createElement(Popup, { model: this.model.questionTypeSelectorModel.popupModel })), React.createElement("div", { className: "svc-panel__add-new-question-wrapper" }, React.createElement(AddQuestionButtonComponent, { item: { data: this.model }, buttonClass: "svc-action-button", renderPopup: false })))) : null, super.renderFooter())); } } ReactElementFactory.Instance.registerElement("svc-panel", (props) => { return React.createElement(PanelAdornerComponent, props); }); class LogoImageComponent extends CreatorModelElement { constructor(props) { super(props); this.rootRef = React.createRef(); } createModel(props) { let prevRoot = null; if (!!this.model) { prevRoot = this.model.root; } this.model = new LogoImageViewModel(props.data, prevRoot); } getUpdatedModelProps() { return ["data"]; } getStateElement() { return this.model; } componentDidMount() { super.componentDidMount(); this.model.root = this.rootRef.current; } renderChooseButton() { return attachKey2click(React.createElement("span", { className: "svc-context-button", onClick: () => this.model.chooseFile(this.model) }, React.createElement(SvgIcon, { size: "auto", iconName: "icon-choosefile" }))); } renderClearButton() { return attachKey2click(React.createElement("span", { className: "svc-context-button svc-context-button--danger", onClick: () => this.model.remove(this.model) }, React.createElement(SvgIcon, { size: "auto", iconName: "icon-clear" }))); } renderButtons() { return (React.createElement("div", { className: "svc-context-container svc-logo-image-controls" }, this.renderChooseButton(), this.renderClearButton())); } renderImage() { return React.createElement("div", { className: this.model.containerCss }, this.renderButtons(), React.createElement(LogoImage, { data: this.props.data.survey })); } renderPlaceHolder() { return this.model.allowEdit && !this.model.isUploading ? attachKey2click(React.createElement("div", { className: "svc-logo-image-placeholder", onClick: () => this.model.chooseFile(this.model) }, React.createElement("svg", null, React.createElement("use", { xlinkHref: "#icon-image-48x48" })))) : null; } renderInput() { return React.createElement("input", { "aria-hidden": "true", type: "file", tabIndex: -1, accept: this.model.acceptedTypes, className: "svc-choose-file-input" }); } renderLoadingIndicator() { return React.createElement("div", { className: "svc-logo-image__loading" }, React.createElement(LoadingIndicatorComponent, null)); } render() { let content = null; if (this.model.survey.locLogo.renderedHtml && !this.model.isUploading) { content = this.renderImage(); } else if (this.model.isUploading) { content = this.renderLoadingIndicator(); } else { content = this.renderPlaceHolder(); } return (React.createElement("div", { ref: this.rootRef, className: "svc-logo-image" }, this.renderInput(), content)); } } ReactElementFactory.Instance.registerElement("svc-logo-image", (props) => { return React.createElement(LogoImageComponent, props); }); class SurveyQuestionLinkValue extends SurveyQuestionElementBase { get question() { return this.questionBase; } renderClear() { const showClear = this.questionBase.showClear; if (!this.questionBase.isReadOnly && showClear) { return (React.createElement(ActionButton, { classes: this.question.linkClearButtonCssClasses, click: () => this.question.doClearClick(), text: editorLocalization.getString("pe.clear") })); } else { return null; } } renderElement() { return (React.createElement(React.Fragment, null, React.createElement(ActionButton, { classes: this.question.linkSetButtonCssClasses, click: () => this.question.doLinkClick(), selected: this.question.isSelected, disabled: !this.question.isClickable, text: this.question.linkValueText, title: this.question.tooltip, iconName: this.question.iconName }), this.renderClear())); } } ReactQuestionFactory.Instance.registerQuestion("linkvalue", (props) => { return React.createElement(SurveyQuestionLinkValue, props); }); class SurveyElementEmbeddedSurvey extends SurveyQuestionElementBase { get embeddedSurvey() { return (this.props.element || this.props.question); } get creator() { return this.props.creator; } render() { if (!this.embeddedSurvey) return null; const survey = this.embeddedSurvey.embeddedSurvey; if (!survey || !survey.currentPage) return null; return React.createElement(SurveyPage, { survey: survey, page: survey.currentPage, css: survey.css, creator: this.creator }); } } ReactQuestionFactory.Instance.registerQuestion("embeddedsurvey", (props) => { return React.createElement(SurveyElementEmbeddedSurvey, props); }); class QuestionEditorContentComponent extends React.Component { get survey() { return this.props.survey; } createQuestionElement(question) { return ReactQuestionFactory.Instance.createQuestion(!question.isDefaultRendering || question.isDefaultRendering() ? question.getTemplate() : question.getComponentName(), { question: question, isDisplayMode: question.isInputReadOnly, creator: this, }); } questionTitleLocation() { return this.survey.questionTitleLocation; } questionErrorLocation() { return this.survey.questionErrorLocation; } renderError(key, error, cssClasses) { return null; } render() { const question = this.survey.getAllQuestions()[0]; return (React.createElement("div", { style: this.props.style }, React.createElement(SurveyQuestion, { creator: this, element: question }))); } } ReactElementFactory.Instance.registerElement("svc-question-editor-content", (props) => { return React.createElement(QuestionEditorContentComponent, props); }); class ItemValueAdornerComponent extends CreatorModelElement { constructor(props) { super(props); this.onBlur = (event) => { this.model.onFocusOut(event.nativeEvent); }; this.rootRef = React.createRef(); } createModel(props) { this.model = new ItemValueWrapperViewModel(props.componentData.creator, props.question, props.item); } getUpdatedModelProps() { return ["question", "item"]; } getStateElement() { return this.model; } componentDidUpdate(prevProps, prevState) { super.componentDidUpdate(prevProps, prevState); this.props.item.setRootElement(this.rootRef.current); if (prevProps.item !== this.props.item && prevProps.item) { prevProps.item.setRootElement(undefined); } } componentDidMount() { super.componentDidMount(); this.props.item.setRootElement(this.rootRef.current); } componentWillUnmount() { super.componentWillUnmount(); this.props.item.setRootElement(undefined); } render() { this.model.item = this.props.item; const button = this.model.allowAdd ? (attachKey2click(React.createElement("span", { role: "button", className: "svc-item-value-controls__button svc-item-value-controls__add", "aria-label": this.model.tooltip, onClick: () => { this.model.add(this.model); this.model.isNew = false; } }, React.createElement(SvgIcon, { size: "auto", iconName: "icon-add_16x16", title: this.model.tooltip })))) : (React.createElement(React.Fragment, null, " ", this.model.isDraggable ? (React.createElement("span", { className: "svc-item-value-controls__button svc-item-value-controls__drag" }, React.createElement(SvgIcon, { className: "svc-item-value-controls__drag-icon", size: "auto", iconName: "icon-drag-24x24", title: this.model.dragTooltip }))) : null