UNPKG

@shopify/app-bridge-core

Version:

**[Join our team and work on libraries like this one.](https://www.shopify.ca/careers)**

293 lines (290 loc) 9.2 kB
import { getSingleButton } from '../buttonHelper.js'; import { actionWrapper, updateActionFromPayload, getMergedProps } from '../helper.js'; import { ActionSetWithChildren } from '../ActionSet.js'; import { Group, ComponentType } from '../types.js'; import { clickButton } from '../Button/index.js'; var Action; (function (Action) { Action["OPEN"] = "APP::MODAL::OPEN"; Action["CLOSE"] = "APP::MODAL::CLOSE"; Action["UPDATE"] = "APP::MODAL::UPDATE"; Action["UPDATE_CONTENT"] = "APP::MODAL::CONTENT::UPDATE"; Action["FOOTER_BUTTON_CLICK"] = "APP::MODAL::FOOTER::BUTTON::CLICK"; Action["FOOTER_BUTTON_UPDATE"] = "APP::MODAL::FOOTER::BUTTON::UPDATE"; Action["UPDATE_SIZE"] = "APP::MODAL::UPDATE_SIZE"; Action["DATA"] = "APP::MODAL::DATA"; })(Action || (Action = {})); /** * Options available to the Modal `size` param * @public */ var Size; (function (Size) { /** Small modal size */ Size["Small"] = "small"; /** Medium modal size */ Size["Medium"] = "medium"; /** Large modal size (wider than medium) */ Size["Large"] = "large"; /** @deprecated as of 1.6.5 */ Size["Full"] = "full"; /** * @deprecated as of 1.12.x * @remarks * This option has been removed in favour of the `setUpModalAutoSizing` utility. */ Size["Auto"] = "auto"; })(Size || (Size = {})); const FOOTER_BUTTON_PROPS = { group: Group.Modal, subgroups: ['Footer'], type: ComponentType.Button, }; function openModal(modalPayload) { return actionWrapper({ group: Group.Modal, payload: modalPayload, type: Action.OPEN, }); } function closeModal(modalClosePayload) { return actionWrapper({ group: Group.Modal, payload: modalClosePayload, type: Action.CLOSE, }); } /** * Action creator for modal update size action * @internal */ function updateModalSize(updateSizePayload) { return actionWrapper({ group: Group.Modal, payload: updateSizePayload, type: Action.UPDATE_SIZE, }); } function clickFooterButton(id, payload) { const component = { id, ...FOOTER_BUTTON_PROPS }; return clickButton(Group.Modal, component, payload); } function update(payload) { return actionWrapper({ payload, group: Group.Modal, type: Action.UPDATE, }); } function data(payload) { return actionWrapper({ payload, group: Group.Modal, type: Action.DATA, }); } function isIframeModal(options) { return (typeof options.url === 'string' || typeof options.path === 'string'); } function isMessageModal(options) { return typeof options.message === 'string'; } class Modal extends ActionSetWithChildren { title; size = Size.Small; footerPrimary; footerPrimaryOptions; footerSecondary; footerSecondaryOptions; get footer() { if (!this.footerPrimary && !this.footerSecondary) { return undefined; } return { buttons: { primary: this.footerPrimary, secondary: this.footerSecondary, }, }; } get footerOptions() { if (!this.footerPrimaryOptions && !this.footerSecondaryOptions) { return undefined; } return { buttons: { primary: this.footerPrimaryOptions, secondary: this.footerSecondaryOptions, }, }; } close() { this.app.dispatch(closeModal({ id: this.id })); } setFooterPrimaryButton(newOptions, updateCb) { const { subgroups } = FOOTER_BUTTON_PROPS; this.footerPrimaryOptions = this.getChildButton(newOptions, this.footerPrimaryOptions); this.footerPrimary = this.footerPrimaryOptions ? getSingleButton(this, this.footerPrimaryOptions, subgroups, (newPayload) => { this.updatePrimaryFooterButton(newPayload, updateCb); }) : undefined; } setFooterSecondaryButtons(newOptions, updateCb) { const { subgroups } = FOOTER_BUTTON_PROPS; const newButtons = newOptions || []; const currentOptions = (this.footerOptions && this.footerOptions.buttons.secondary) || []; this.footerSecondaryOptions = this.getUpdatedChildActions(newButtons, currentOptions); this.footerSecondary = this.footerSecondaryOptions ? this.footerSecondaryOptions.map((action) => getSingleButton(this, action, subgroups, (newPayload) => { this.updateSecondaryFooterButton(newPayload, updateCb); })) : undefined; } getChildButton(newAction, currentAction) { const newButtons = newAction ? [newAction] : []; const currentButtons = currentAction ? [currentAction] : []; const updatedButton = this.getUpdatedChildActions(newButtons, currentButtons); return updatedButton ? updatedButton[0] : undefined; } updatePrimaryFooterButton(newPayload, updateCb) { if (!this.footer || !this.footer.buttons.primary) { return; } if (updateActionFromPayload(this.footer.buttons.primary, newPayload)) { updateCb(); } } updateSecondaryFooterButton(newPayload, updateCb) { if (!this.footer || !this.footer.buttons || !this.footer.buttons.secondary) { return; } let updated; for (const action of this.footer.buttons.secondary) { updated = updateActionFromPayload(action, newPayload); if (updated) { break; } } if (updated) { updateCb(); } } } class ModalMessage extends Modal { message; constructor(app, options) { super(app, Group.Modal, Group.Modal); this.set(options, false); } get payload() { return { ...this.options, footer: this.footer, id: this.id, }; } get options() { return { footer: this.footerOptions, message: this.message, size: this.size, title: this.title, }; } set(options, shouldUpdate = true) { const mergedOptions = getMergedProps(this.options, options); const { title, footer, message, size } = mergedOptions; this.title = title; this.message = message; this.size = size; this.setFooterPrimaryButton(footer ? footer.buttons.primary : undefined, () => { this.dispatch(Action.UPDATE); }); this.setFooterSecondaryButtons(footer ? footer.buttons.secondary : undefined, () => { this.dispatch(Action.UPDATE); }); if (shouldUpdate) { this.dispatch(Action.UPDATE); } return this; } dispatch(action) { switch (action) { case Action.OPEN: this.app.dispatch(openModal(this.payload)); break; case Action.CLOSE: this.close(); break; case Action.UPDATE: this.app.dispatch(update(this.payload)); break; } return this; } } class ModalIframe extends Modal { url; path; loading; constructor(app, options) { super(app, Group.Modal, Group.Modal); this.set(options, false); } get payload() { return { ...this.options, footer: this.footer, id: this.id, }; } get options() { return { footer: this.footerOptions, path: this.path, size: this.size, title: this.title, url: this.url, loading: this.loading, }; } set(options, shouldUpdate = true) { const mergedOptions = getMergedProps(this.options, options); const { title, footer, path, url, size, loading } = mergedOptions; this.title = title; this.url = url; this.path = path; this.size = size; this.loading = loading; this.setFooterPrimaryButton(footer ? footer.buttons.primary : undefined, () => { this.dispatch(Action.UPDATE); }); this.setFooterSecondaryButtons(footer ? footer.buttons.secondary : undefined, () => { this.dispatch(Action.UPDATE); }); if (shouldUpdate) { this.dispatch(Action.UPDATE); } return this; } dispatch(action, payload) { switch (action) { case Action.OPEN: this.app.dispatch(openModal(this.payload)); break; case Action.CLOSE: this.close(); break; case Action.UPDATE: this.app.dispatch(update(this.payload)); break; case Action.DATA: this.app.dispatch(data(payload || {})); break; } return this; } } export { Action, Modal, ModalIframe, ModalMessage, Size, clickFooterButton, closeModal, data, isIframeModal, isMessageModal, openModal, update, updateModalSize };