@shopify/app-bridge-host
Advanced tools
Comparing version 1.7.1 to 1.8.0-alpha.0
@@ -6,2 +6,19 @@ # Change Log | ||
# [1.8.0-alpha.0](https://github.com/Shopify/app-bridge/compare/v1.7.1...v1.8.0-alpha.0) (2019-10-15) | ||
### Features | ||
* **host:** allow hosts to provide a navigation context ([225f064](https://github.com/Shopify/app-bridge/commit/225f064)) | ||
* **host:** enable hosts to set the features available ([023be80](https://github.com/Shopify/app-bridge/commit/023be80)) | ||
* **host:** enable hosts to set the features available ([#1224](https://github.com/Shopify/app-bridge/issues/1224)) ([cd7a68a](https://github.com/Shopify/app-bridge/commit/cd7a68a)) | ||
* **host:** handle MainFrame navigation ([9b0242b](https://github.com/Shopify/app-bridge/commit/9b0242b)) | ||
* add loading attribute to ContextualSaveBar actions ([4588633](https://github.com/Shopify/app-bridge/commit/4588633)) | ||
* add loading attribute to ContextualSaveBar actions ([#1258](https://github.com/Shopify/app-bridge/issues/1258)) ([5203fbc](https://github.com/Shopify/app-bridge/commit/5203fbc)) | ||
* **host:** handle MainFrame navigation ([#1262](https://github.com/Shopify/app-bridge/issues/1262)) ([2cffbb4](https://github.com/Shopify/app-bridge/commit/2cffbb4)) | ||
## [1.7.1](https://github.com/Shopify/app-bridge/compare/v1.7.0...v1.7.1) (2019-10-08) | ||
@@ -8,0 +25,0 @@ |
@@ -1,6 +0,21 @@ | ||
/// <reference types="react" /> | ||
import React from 'react'; | ||
import { ComponentProps } from '../types'; | ||
import { WithFeature } from '../store/reducers/embeddedApp/navigation'; | ||
interface ExtraProps { | ||
[key: string]: any; | ||
} | ||
declare type ComposedProps = WithFeature & ExtraProps; | ||
/** | ||
* Renders a Frame component with the Context set to `Main` | ||
* Handles updating the iframe url for all app-related Navigation actions | ||
* @public | ||
* @requires RouterContext | ||
* @requires HostContext | ||
* */ | ||
export default function MainFrame(): JSX.Element | null; | ||
export declare function MainFrame(props: ComposedProps): JSX.Element | null; | ||
declare const _default: (React.ComponentClass<ComponentProps & ExtraProps, any> & Pick<(React.ComponentClass<ComposedProps, any> & typeof MainFrame) | (React.FunctionComponent<ComposedProps> & typeof MainFrame), "defaultProps">) | (React.FunctionComponent<ComponentProps & ExtraProps> & Pick<(React.ComponentClass<ComposedProps, any> & typeof MainFrame) | (React.FunctionComponent<ComposedProps> & typeof MainFrame), "defaultProps">); | ||
/** | ||
* The MainFrame component with the Navigation feature | ||
* @public | ||
* */ | ||
export default _default; |
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) | ||
t[p[i]] = s[p[i]]; | ||
return t; | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
@@ -15,23 +35,93 @@ if (mod && mod.__esModule) return mod; | ||
var app_bridge_1 = require("@shopify/app-bridge"); | ||
var actions_1 = require("@shopify/app-bridge/actions"); | ||
var react_compose_1 = __importDefault(require("@shopify/react-compose")); | ||
var appUrl_1 = require("./utilities/appUrl"); | ||
var error_1 = require("./utilities/error"); | ||
var Frame_1 = __importDefault(require("../Frame")); | ||
var HostProvider_1 = require("../HostProvider"); | ||
var withFeature_1 = __importDefault(require("../withFeature")); | ||
var navigation_1 = require("../store/reducers/embeddedApp/navigation"); | ||
var appBridge_1 = require("../store/reducers/embeddedApp/appBridge"); | ||
var style = { | ||
position: 'relative', | ||
border: 'none', | ||
width: '100%', | ||
flex: '1', | ||
display: 'flex', | ||
}; | ||
/** | ||
* Renders a Frame component with the Context set to `Main` | ||
* Handles updating the iframe url for all app-related Navigation actions | ||
* @public | ||
* @requires RouterContext | ||
* @requires HostContext | ||
* */ | ||
function MainFrame() { | ||
var context = react_1.useContext(HostProvider_1.HostContext); | ||
if (!context) { | ||
function MainFrame(props) { | ||
var hostContext = react_1.useContext(HostProvider_1.HostContext); | ||
var routerContext = react_1.useContext(HostProvider_1.RouterContext); | ||
if (!hostContext) { | ||
error_1.throwMissingHostProvider(); | ||
return null; | ||
} | ||
var app = context.app, config = context.config; | ||
var style = { | ||
position: 'relative', | ||
border: 'none', | ||
width: '100%', | ||
flex: '1', | ||
display: 'flex', | ||
}; | ||
return (react_1.default.createElement(Frame_1.default, { app: app, style: style, title: config.name, context: app_bridge_1.Context.Main, url: config.url })); | ||
if (!routerContext) { | ||
error_1.throwMissingRouterError(); | ||
return null; | ||
} | ||
var app = hostContext.app, config = hostContext.config; | ||
var location = routerContext.location; | ||
var _a = react_1.useState(), iframeUrl = _a[0], setIframeUrl = _a[1]; | ||
var _b = react_1.useState(false), shouldUpdate = _b[0], setShouldUpdate = _b[1]; | ||
var actions = props.actions, updateAction = props.store.updateAction, extraProps = __rest(props, ["actions", "store"]); | ||
function updateIframeUrl(iframe, newUrl) { | ||
if (app.isTransportSubscribed(app_bridge_1.Context.Main, actions_1.Redirect.ActionType.APP)) { | ||
return; | ||
} | ||
if (!iframe || !iframe.contentWindow) { | ||
return; | ||
} | ||
app.dispatch(appBridge_1.reset()); | ||
iframe.contentWindow.location.replace(newUrl); | ||
} | ||
react_1.useEffect(function () { | ||
var pathname = location.pathname; | ||
var apiKey = config.apiKey, handle = config.handle, url = config.url; | ||
setIframeUrl(appUrl_1.buildAppUrl({ handle: handle, apiKey: apiKey, url: url, pathname: pathname })); | ||
}, []); | ||
react_1.useEffect(function () { | ||
if (!updateAction) { | ||
setShouldUpdate(true); | ||
return; | ||
} | ||
var target = updateAction.target, type = updateAction.type; | ||
if (type === actions_1.History.Action.PUSH || | ||
type === actions_1.History.Action.REPLACE || | ||
target !== actions_1.Redirect.Action.APP) { | ||
setShouldUpdate(false); | ||
return; | ||
} | ||
setShouldUpdate(true); | ||
}, [updateAction]); | ||
react_1.useEffect(function () { | ||
if (!shouldUpdate) { | ||
return; | ||
} | ||
var pathname = location.pathname, search = location.search; | ||
var apiKey = config.apiKey, handle = config.handle, url = config.url; | ||
var iframeUrl = appUrl_1.buildAppUrl({ handle: handle, apiKey: apiKey, url: url, pathname: pathname }); | ||
if (app.isTransportSubscribed(app_bridge_1.Context.Main, actions_1.Redirect.ActionType.APP)) { | ||
actions.handleRedirectApp({ path: "" + iframeUrl.pathname + search }); | ||
return; | ||
} | ||
setIframeUrl(iframeUrl); | ||
}, [location]); | ||
if (!iframeUrl) { | ||
return null; | ||
} | ||
return (react_1.default.createElement(Frame_1.default, __assign({}, extraProps, { config: config, style: style, context: app_bridge_1.Context.Main, app: app, title: config.name, url: iframeUrl.href, onUrlChange: updateIframeUrl }))); | ||
} | ||
exports.default = MainFrame; | ||
exports.MainFrame = MainFrame; | ||
/** | ||
* The MainFrame component with the Navigation feature | ||
* @public | ||
* */ | ||
exports.default = react_compose_1.default(withFeature_1.default(navigation_1.feature))(MainFrame); |
@@ -11,4 +11,13 @@ import React, { CSSProperties } from 'react'; | ||
context: Context; | ||
/** The handler called when the `url` prop changes*/ | ||
onUrlChange?: (iframe: HTMLIFrameElement, newUrl: string) => void; | ||
} | ||
export default class Frame extends React.PureComponent<FrameProps, never> { | ||
/** | ||
* Renders an iframe and sets up a `MessageTransport` between | ||
* the iframe and the parent window | ||
* @public | ||
* @remarks The iframe is never updated to prevent duplicated browser history entries | ||
* When a new url is received the `onUrlChange` is called with the iframe and the new url | ||
* */ | ||
export default class Frame extends React.Component<FrameProps, never> { | ||
iframe?: HTMLIFrameElement; | ||
@@ -19,5 +28,7 @@ detach?: Function; | ||
}; | ||
shouldComponentUpdate(): boolean; | ||
componentDidMount(): void; | ||
componentWillUnmount(): void; | ||
UNSAFE_componentWillReceiveProps(nextProps: FrameProps): void; | ||
render(): JSX.Element; | ||
} |
20
Frame.js
@@ -41,2 +41,9 @@ "use strict"; | ||
var app_bridge_1 = require("@shopify/app-bridge"); | ||
/** | ||
* Renders an iframe and sets up a `MessageTransport` between | ||
* the iframe and the parent window | ||
* @public | ||
* @remarks The iframe is never updated to prevent duplicated browser history entries | ||
* When a new url is received the `onUrlChange` is called with the iframe and the new url | ||
* */ | ||
var Frame = /** @class */ (function (_super) { | ||
@@ -47,2 +54,5 @@ __extends(Frame, _super); | ||
} | ||
Frame.prototype.shouldComponentUpdate = function () { | ||
return false; | ||
}; | ||
Frame.prototype.componentDidMount = function () { | ||
@@ -61,5 +71,11 @@ var _a = this.props, context = _a.context, url = _a.url; | ||
}; | ||
Frame.prototype.UNSAFE_componentWillReceiveProps = function (nextProps) { | ||
var url = nextProps.url, onUrlChange = nextProps.onUrlChange; | ||
if (url !== this.props.url && onUrlChange && this.iframe) { | ||
onUrlChange(this.iframe, url); | ||
} | ||
}; | ||
Frame.prototype.render = function () { | ||
var _this = this; | ||
var _a = this.props, app = _a.app, title = _a.title, url = _a.url, style = _a.style, props = __rest(_a, ["app", "title", "url", "style"]); | ||
var _a = this.props, app = _a.app, title = _a.title, url = _a.url, style = _a.style, onUrlChange = _a.onUrlChange, props = __rest(_a, ["app", "title", "url", "style", "onUrlChange"]); | ||
return (react_1.default.createElement("iframe", __assign({ style: style, title: title, src: url }, props, { ref: function (element) { return (element ? (_this.iframe = element) : undefined); } }))); | ||
@@ -71,3 +87,3 @@ }; | ||
return Frame; | ||
}(react_1.default.PureComponent)); | ||
}(react_1.default.Component)); | ||
exports.default = Frame; |
@@ -6,2 +6,24 @@ import React from 'react'; | ||
/** | ||
* The interface for the Navigation Context | ||
* @public | ||
* */ | ||
export interface RouterContext { | ||
/** The `handle` or `apiKey` for the current app */ | ||
appRoot: string; | ||
hostname: string; | ||
/** The router to be to handle router actions */ | ||
history: { | ||
replace(path: string): void; | ||
push(path: string): void; | ||
}; | ||
/** | ||
* The current pathname and query params | ||
* @internal | ||
* */ | ||
location: { | ||
pathname: string; | ||
search?: string; | ||
}; | ||
} | ||
/** | ||
* The interface for the HostProvider | ||
@@ -15,4 +37,8 @@ * @public | ||
dispatchClientEventHandler?: (trackingEventPayload: TrackingEventPayload) => void; | ||
/** Optional initial app state */ | ||
initialState?: Partial<Store>; | ||
/** Required to set the initial app state | ||
* @remarks feature permissions must be specified using the key `features` which will take effect immediately | ||
* other state properties (ex. `loading`, `toast`, etc..) will only be set after the relevant reducer has loaded | ||
*/ | ||
initialState: Partial<Store> & Pick<Store, 'features'>; | ||
router?: RouterContext; | ||
} | ||
@@ -35,2 +61,9 @@ /** | ||
/** | ||
* The context provider for the router. | ||
* Keeps track of the current location and | ||
* handles history push/replace | ||
* @public | ||
* */ | ||
export declare const RouterContext: React.Context<RouterContext | null>; | ||
/** | ||
* A component that creates a dynamic Redux store | ||
@@ -37,0 +70,0 @@ * and renders the Host |
@@ -45,2 +45,9 @@ "use strict"; | ||
/** | ||
* The context provider for the router. | ||
* Keeps track of the current location and | ||
* handles history push/replace | ||
* @public | ||
* */ | ||
exports.RouterContext = react_1.createContext(null); | ||
/** | ||
* A component that creates a dynamic Redux store | ||
@@ -51,3 +58,3 @@ * and renders the Host | ||
function HostProvider(props) { | ||
var config = props.config, dispatchClientEventHandler = props.dispatchClientEventHandler, initialState = props.initialState, hostProps = __rest(props, ["config", "dispatchClientEventHandler", "initialState"]); | ||
var config = props.config, dispatchClientEventHandler = props.dispatchClientEventHandler, initialState = props.initialState, router = props.router, hostProps = __rest(props, ["config", "dispatchClientEventHandler", "initialState", "router"]); | ||
var appBridgeMiddleware = react_1.useMemo(function () { return Middleware_1.buildMiddleware(async_1.APP_BRIDGE_KEY, dispatchClientEventHandler); }, [dispatchClientEventHandler]); | ||
@@ -60,5 +67,9 @@ if (!config) { | ||
} | ||
var store = react_1.useMemo(function () { return async_1.createStore([appBridgeMiddleware]); }, [appBridgeMiddleware]); | ||
var store = react_1.useMemo(function () { | ||
// Only take the features state as features is the only default reducer | ||
var defaultState = initialState.features && { features: initialState.features }; | ||
return async_1.createStore([appBridgeMiddleware], defaultState); | ||
}, [appBridgeMiddleware]); | ||
var hostContext = react_1.useMemo(function () { | ||
var addReducer = async_1.createAddReducer(store); | ||
var addReducer = async_1.createAddReducer(store, initialState); | ||
var app = appBridgeMiddleware.load({ | ||
@@ -70,6 +81,10 @@ config: config, | ||
}, [config]); | ||
var content = (react_1.default.createElement(react_redux_1.Provider, { store: store }, | ||
react_1.default.createElement(Host_1.default, __assign({}, hostProps)))); | ||
if (!router) { | ||
return react_1.default.createElement(exports.HostContext.Provider, { value: hostContext }, content); | ||
} | ||
return (react_1.default.createElement(exports.HostContext.Provider, { value: hostContext }, | ||
react_1.default.createElement(react_redux_1.Provider, { store: store }, | ||
react_1.default.createElement(Host_1.default, __assign({}, hostProps))))); | ||
react_1.default.createElement(exports.RouterContext.Provider, { value: router }, content))); | ||
} | ||
exports.default = HostProvider; |
@@ -10,3 +10,3 @@ export { withApp, WithAppProps } from './decorator'; | ||
export { default as createStore } from './store'; | ||
export { default as HostProvider, HostContext } from './HostProvider'; | ||
export { default as HostProvider, HostContext, RouterContext } from './HostProvider'; | ||
export { default as withFeature } from './withFeature'; |
@@ -26,3 +26,4 @@ "use strict"; | ||
exports.HostContext = HostProvider_1.HostContext; | ||
exports.RouterContext = HostProvider_1.RouterContext; | ||
var withFeature_1 = require("./withFeature"); | ||
exports.withFeature = withFeature_1.default; |
{ | ||
"name": "@shopify/app-bridge-host", | ||
"version": "1.7.1", | ||
"version": "1.8.0-alpha.0", | ||
"types": "index.d.ts", | ||
@@ -65,3 +65,3 @@ "main": "index.js", | ||
"dependencies": { | ||
"@shopify/app-bridge": "^1.7.1", | ||
"@shopify/app-bridge": "^1.8.0-alpha.0", | ||
"@shopify/javascript-utilities": "^2.3.0", | ||
@@ -77,3 +77,3 @@ "@shopify/react-compose": "^1.0.4", | ||
}, | ||
"gitHead": "c48a872deba1e9cf965e28651be904c8f5447090" | ||
"gitHead": "9b7434c8be2aa5aa549da1b8e2235d4b79433f2a" | ||
} |
@@ -78,11 +78,13 @@ import { compose, Middleware as ReduxMiddleware, ReducersMapObject, Reducer, Store as ReduxStore } from 'redux'; | ||
*/ | ||
export declare function createStore(middlewares?: Array<ReturnType<typeof buildMiddleware> | ReduxMiddleware>): ReduxStore<AppBridgeStore, import("redux").AnyAction> & { | ||
export declare function createStore(middlewares?: Array<ReturnType<typeof buildMiddleware> | ReduxMiddleware>, initialState?: Partial<Store>): ReduxStore<AppBridgeStore, import("redux").AnyAction> & { | ||
dispatch: {}; | ||
}; | ||
/** | ||
* Creates a method that when called dynamically, adds a reducer to | ||
* Creates a method that when called, dynamically adds a reducer to | ||
* the provided store | ||
* @internal | ||
* @param store - a Redux store | ||
* @param globalInitialState - custom overrides for resolving the app state when adding a new reducer | ||
* */ | ||
export declare function createAddReducer(store: ReduxStore): <State>({ key, reducer, initialState }: ReducerMap<State>) => void; | ||
export declare function createAddReducer(store: ReduxStore, globalInitialState?: Partial<Store>): <State>({ key, reducer, initialState }: ReducerMap<State>) => void; | ||
export {}; |
@@ -13,5 +13,2 @@ "use strict"; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -21,3 +18,3 @@ var redux_1 = require("redux"); | ||
var helpers_1 = require("./middlewares/mobile/helpers"); | ||
var features_1 = __importDefault(require("./reducers/embeddedApp/features")); | ||
var features_1 = require("./reducers/embeddedApp/features"); | ||
var utilities_1 = require("./reducers/embeddedApp/utilities"); | ||
@@ -41,3 +38,3 @@ /** | ||
return redux_1.combineReducers((_a = {}, | ||
_a[exports.APP_BRIDGE_KEY] = redux_1.combineReducers(utilities_1.wrapReducers(__assign({ features: features_1.default }, stateReducers), utilities_1.resetAppReducer, initialState)), | ||
_a[exports.APP_BRIDGE_KEY] = redux_1.combineReducers(utilities_1.wrapReducers(__assign({ features: features_1.asyncFeaturesReducer }, stateReducers), utilities_1.resetAppReducer, initialState)), | ||
_a)); | ||
@@ -51,6 +48,7 @@ } | ||
*/ | ||
function createStore(middlewares) { | ||
function createStore(middlewares, initialState) { | ||
if (middlewares === void 0) { middlewares = []; } | ||
if (initialState === void 0) { initialState = {}; } | ||
var _a; | ||
var defaultState = (_a = {}, _a[exports.APP_BRIDGE_KEY] = {}, _a); | ||
var defaultState = (_a = {}, _a[exports.APP_BRIDGE_KEY] = initialState, _a); | ||
var composeEnhancers = typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ | ||
@@ -63,11 +61,14 @@ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ name: 'App Bridge' }) | ||
} | ||
return redux_1.createStore(createReducers(), defaultState, composeEnhancers(redux_1.applyMiddleware.apply(void 0, mobileMiddlewares.concat(middlewares)))); | ||
return redux_1.createStore(createReducers({}, initialState), defaultState, composeEnhancers(redux_1.applyMiddleware.apply(void 0, mobileMiddlewares.concat(middlewares)))); | ||
} | ||
exports.createStore = createStore; | ||
/** | ||
* Creates a method that when called dynamically, adds a reducer to | ||
* Creates a method that when called, dynamically adds a reducer to | ||
* the provided store | ||
* @internal | ||
* @param store - a Redux store | ||
* @param globalInitialState - custom overrides for resolving the app state when adding a new reducer | ||
* */ | ||
function createAddReducer(store) { | ||
function createAddReducer(store, globalInitialState) { | ||
if (globalInitialState === void 0) { globalInitialState = {}; } | ||
var asyncReducers = {}; | ||
@@ -82,3 +83,4 @@ return function addReducer(_a) { | ||
var currentState = store.getState()[exports.APP_BRIDGE_KEY]; | ||
var newState = initialState ? __assign({}, currentState, (_b = {}, _b[key] = initialState, _b)) : currentState; | ||
var localState = globalInitialState[key] || initialState; | ||
var newState = localState ? __assign({}, currentState, (_b = {}, _b[key] = localState, _b)) : currentState; | ||
store.replaceReducer(createReducers(asyncReducers, newState)); | ||
@@ -85,0 +87,0 @@ }; |
@@ -6,2 +6,3 @@ import { compose, Middleware as ReduxMiddleware } from 'redux'; | ||
export * from './reducers'; | ||
export { setFeaturesAvailable } from './reducers/embeddedApp/features'; | ||
interface DevToolsOptions { | ||
@@ -8,0 +9,0 @@ name?: string; |
@@ -15,2 +15,4 @@ "use strict"; | ||
__export(require("./reducers")); | ||
var features_1 = require("./reducers/embeddedApp/features"); | ||
exports.setFeaturesAvailable = features_1.setFeaturesAvailable; | ||
function createStore(middlewares) { | ||
@@ -17,0 +19,0 @@ if (middlewares === void 0) { middlewares = []; } |
@@ -14,5 +14,7 @@ import { AnyAction, ActionCreatorsMapObject } from 'redux'; | ||
disabled: boolean; | ||
loading: boolean; | ||
}; | ||
discardAction: { | ||
disabled: boolean; | ||
loading: boolean; | ||
discardConfirmationModal: boolean; | ||
@@ -19,0 +21,0 @@ }; |
@@ -21,8 +21,19 @@ "use strict"; | ||
case actions_1.ContextualSaveBar.ActionType.UPDATE: | ||
var _a = action.payload, id = _a.id, _b = _a.saveAction, saveAction = _b === void 0 ? { disabled: false } : _b, _c = _a.discardAction, discardAction = _c === void 0 ? { disabled: false, discardConfirmationModal: false } : _c; | ||
var _a = action.payload, id = _a.id, _b = _a.saveAction, saveAction = _b === void 0 ? { | ||
disabled: false, | ||
loading: false, | ||
} : _b, _c = _a.discardAction, discardAction = _c === void 0 ? { | ||
disabled: false, | ||
loading: false, | ||
discardConfirmationModal: false, | ||
} : _c; | ||
return { | ||
id: id, | ||
saveAction: { disabled: saveAction.disabled }, | ||
saveAction: { | ||
disabled: saveAction.disabled, | ||
loading: saveAction.loading, | ||
}, | ||
discardAction: { | ||
disabled: discardAction.disabled, | ||
loading: discardAction.loading, | ||
discardConfirmationModal: discardAction.discardConfirmationModal, | ||
@@ -29,0 +40,0 @@ }, |
@@ -1,5 +0,5 @@ | ||
import featuresReducer, { defaultFeaturesStore } from './reducer'; | ||
import featuresReducer, { asyncFeaturesReducer, defaultFeaturesStore, setFeaturesAvailable } from './reducer'; | ||
export default featuresReducer; | ||
export * from './actionCreators'; | ||
export * from './types'; | ||
export { defaultFeaturesStore }; | ||
export { asyncFeaturesReducer, setFeaturesAvailable, defaultFeaturesStore }; |
@@ -14,4 +14,6 @@ "use strict"; | ||
var reducer_1 = __importStar(require("./reducer")); | ||
exports.asyncFeaturesReducer = reducer_1.asyncFeaturesReducer; | ||
exports.defaultFeaturesStore = reducer_1.defaultFeaturesStore; | ||
exports.setFeaturesAvailable = reducer_1.setFeaturesAvailable; | ||
exports.default = reducer_1.default; | ||
__export(require("./actionCreators")); |
@@ -20,1 +20,16 @@ import { FeaturesState, FeaturesAction, FeaturePermission } from '@shopify/app-bridge'; | ||
export default function featuresReducer(state: FeaturesState<Record<Actions.Group, FeaturesAction>> | undefined, action: UpdateAction | LegacyUpdateAction | Actions.AnyAction): FeaturesState; | ||
/** | ||
* Returns the updated feature state | ||
* @param state - the current state | ||
* @param action - the update action with partial features in the payload | ||
* @internal | ||
* */ | ||
export declare function asyncFeaturesReducer(state: FeaturesState<Record<Actions.Group, FeaturesAction>> | undefined, action: UpdateAction | LegacyUpdateAction | Actions.AnyAction): FeaturesState; | ||
/** | ||
* Returns the features state with the provided group(s) enabled | ||
* The permission is set for both Main and Modal context | ||
* according to the default feature permission rules | ||
* @argument keys - the group(s) to enable the feature permission | ||
* @public | ||
* */ | ||
export declare function setFeaturesAvailable(...features: Actions.Group[]): FeaturesState<Record<Actions.Group, FeaturesAction>>; |
@@ -29,2 +29,3 @@ "use strict"; | ||
var validator_1 = require("@shopify/app-bridge/actions/validator"); | ||
var utilities_1 = require("../utilities"); | ||
var APP_REDIRECT_KEY = validator_1.getPermissionKey(Actions.Redirect.ActionType.APP); | ||
@@ -45,2 +46,7 @@ var DEFAULT_FEATURES_STATE = (_a = {}, | ||
_a); | ||
var DEFAULT_ENABLED_GROUPS = [ | ||
Actions.Group.Button, | ||
Actions.Group.ButtonGroup, | ||
Actions.Group.Error, | ||
]; | ||
exports.defaultFeaturesStore = getDefaultFeatures(); | ||
@@ -58,3 +64,3 @@ function getDefaultFeatures() { | ||
_a[app_bridge_1.Context.Modal] = (_b = {}, | ||
_b[Actions.Group.Print] = setFeature(getGroupActionType(Actions.Group.Print), false), | ||
_b[Actions.Group.Print] = setFeature(utilities_1.getGroupActionType(Actions.Group.Print), false), | ||
_b[Actions.Group.Features] = DEFAULT_FEATURES_STATE, | ||
@@ -77,3 +83,3 @@ _b[Actions.Group.Navigation] = (_c = {}, | ||
var castedGroup = group; | ||
return __assign({}, acc, (_a = {}, _a[castedGroup] = setFeature(getGroupActionType(castedGroup), !excludeGroups.includes(castedGroup)), _a)); | ||
return __assign({}, acc, (_a = {}, _a[castedGroup] = setFeature(utilities_1.getGroupActionType(castedGroup), !excludeGroups.includes(castedGroup)), _a)); | ||
}, {}); | ||
@@ -107,12 +113,2 @@ return merge_1.default((_e = {}, | ||
exports.setFeature = setFeature; | ||
function getGroupActionType(group) { | ||
switch (group) { | ||
case Actions.Group.Navigation: | ||
return __assign({}, Actions.History.ActionType, Actions.Redirect.ActionType); | ||
case Actions.Group.ResourcePicker: | ||
return Actions.ResourcePicker.ActionType; | ||
default: | ||
return Actions[group].ActionType; | ||
} | ||
} | ||
/** | ||
@@ -173,1 +169,58 @@ * Returns the updated feature state | ||
} | ||
function getDefaultAsyncFeatures() { | ||
var _a; | ||
var features = Object.keys(Actions.Group) | ||
.map(function (key) { return Actions.Group[key]; }) | ||
.reduce(function (acc, group) { | ||
var _a; | ||
var castedGroup = group; | ||
var permissions = group === Actions.Group.Features | ||
? DEFAULT_FEATURES_STATE | ||
: setFeature(utilities_1.getGroupActionType(castedGroup), DEFAULT_ENABLED_GROUPS.includes(castedGroup)); | ||
return __assign({}, acc, (_a = {}, _a[castedGroup] = permissions, _a)); | ||
}, {}); | ||
return _a = {}, | ||
_a[app_bridge_1.Context.Main] = features, | ||
_a[app_bridge_1.Context.Modal] = features, | ||
_a; | ||
} | ||
var defaultAsyncFeaturesStore = getDefaultAsyncFeatures(); | ||
/** | ||
* Returns the updated feature state | ||
* @param state - the current state | ||
* @param action - the update action with partial features in the payload | ||
* @internal | ||
* */ | ||
function asyncFeaturesReducer(state, action) { | ||
if (state === void 0) { state = defaultAsyncFeaturesStore; } | ||
return featuresReducer(state, action); | ||
} | ||
exports.asyncFeaturesReducer = asyncFeaturesReducer; | ||
/** | ||
* Returns the features state with the provided group(s) enabled | ||
* The permission is set for both Main and Modal context | ||
* according to the default feature permission rules | ||
* @argument keys - the group(s) to enable the feature permission | ||
* @public | ||
* */ | ||
function setFeaturesAvailable() { | ||
var features = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
features[_i] = arguments[_i]; | ||
} | ||
var _a; | ||
var Modal = exports.defaultFeaturesStore.Modal, Main = exports.defaultFeaturesStore.Main; | ||
var modalPermission = features.reduce(function (acc, curr) { | ||
var _a; | ||
return __assign({}, acc, (_a = {}, _a[curr] = Modal && Modal[curr], _a)); | ||
}, {}); | ||
var mainPermission = features.reduce(function (acc, curr) { | ||
var _a; | ||
return __assign({}, acc, (_a = {}, _a[curr] = Main && Main[curr], _a)); | ||
}, {}); | ||
return merge_1.default(defaultAsyncFeaturesStore, (_a = {}, | ||
_a[app_bridge_1.Context.Main] = mainPermission, | ||
_a[app_bridge_1.Context.Modal] = modalPermission, | ||
_a)); | ||
} | ||
exports.setFeaturesAvailable = setFeaturesAvailable; |
@@ -1,3 +0,5 @@ | ||
import navigationReducer, { defaultNavigationStore } from './reducer'; | ||
export default navigationReducer; | ||
import reducer, { defaultNavigationStore } from './reducer'; | ||
import { Feature } from '../../../../withFeature'; | ||
import { NavigationActionCreatorsMap, NavigationStore } from '../..'; | ||
export default reducer; | ||
export * from './actionCreators'; | ||
@@ -7,1 +9,12 @@ export * from './actions'; | ||
export { defaultNavigationStore }; | ||
export interface WithFeature { | ||
actions: NavigationActionCreatorsMap; | ||
store: NavigationStore; | ||
} | ||
/** | ||
* An object containing the key, actions, initial state and reducer of the Navigation feature | ||
* Can be used with the `withFeature` decorator to add the reducer | ||
* and then make its actions and store available to the wrapped component | ||
* @public | ||
* */ | ||
export declare const feature: Feature<WithFeature['store'], WithFeature['actions']>; |
@@ -15,4 +15,18 @@ "use strict"; | ||
exports.defaultNavigationStore = reducer_1.defaultNavigationStore; | ||
var utilities_1 = require("../utilities"); | ||
var actionCreators_1 = require("./actionCreators"); | ||
exports.default = reducer_1.default; | ||
__export(require("./actionCreators")); | ||
__export(require("./actions")); | ||
/** | ||
* An object containing the key, actions, initial state and reducer of the Navigation feature | ||
* Can be used with the `withFeature` decorator to add the reducer | ||
* and then make its actions and store available to the wrapped component | ||
* @public | ||
* */ | ||
exports.feature = { | ||
actions: actionCreators_1.navigationActionCreatorsMap, | ||
key: 'navigation', | ||
initialState: reducer_1.defaultNavigationStore, | ||
reducer: utilities_1.resetStateReducer(reducer_1.default), | ||
}; |
import { Reducer } from 'redux'; | ||
import * as Actions from '@shopify/app-bridge/actions'; | ||
export interface ReducerMap { | ||
@@ -38,1 +39,14 @@ [key: string]: Reducer; | ||
export declare function wrapReducers<T extends ReducerMap>(reducers: T, wrapper: (reducer: Reducer, initialState?: InitialStateMap) => Reducer, initialState?: InitialStateMap): T; | ||
/** | ||
* Return the full action type given a group name | ||
* @internal | ||
*/ | ||
export declare function getGroupActionType(group: Actions.Group): typeof Actions.Error.ActionType | typeof Actions.Flash.ActionType | typeof Actions.Modal.ActionType | typeof Actions.ResourcePicker.ActionType | typeof Actions.Features.ActionType | typeof Actions.Button.ActionType | typeof Actions.ButtonGroup.ActionType | typeof Actions.Cart.ActionType | typeof Actions.Fullscreen.ActionType | typeof Actions.Loading.ActionType | typeof Actions.Print.ActionType | typeof Actions.Scanner.ActionType | typeof Actions.TitleBar.ActionType | typeof Actions.ContextualSaveBar.ActionType | typeof Actions.Share.ActionType | { | ||
[x: number]: string; | ||
ADMIN_SECTION: Actions.Redirect.ActionType.ADMIN_SECTION; | ||
ADMIN_PATH: Actions.Redirect.ActionType.ADMIN_PATH; | ||
REMOTE: Actions.Redirect.ActionType.REMOTE; | ||
APP: Actions.Redirect.ActionType.APP; | ||
PUSH: Actions.History.ActionType.PUSH; | ||
REPLACE: Actions.History.ActionType.REPLACE; | ||
}; |
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | ||
result["default"] = mod; | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var Actions = __importStar(require("@shopify/app-bridge/actions")); | ||
var actions_1 = require("../../../actions"); | ||
@@ -58,1 +77,16 @@ var actions_2 = require("./appBridge/actions"); | ||
exports.wrapReducers = wrapReducers; | ||
/** | ||
* Return the full action type given a group name | ||
* @internal | ||
*/ | ||
function getGroupActionType(group) { | ||
switch (group) { | ||
case Actions.Group.Navigation: | ||
return __assign({}, Actions.History.ActionType, Actions.Redirect.ActionType); | ||
case Actions.Group.ResourcePicker: | ||
return Actions.ResourcePicker.ActionType; | ||
default: | ||
return Actions[group].ActionType; | ||
} | ||
} | ||
exports.getGroupActionType = getGroupActionType; |
@@ -21,2 +21,3 @@ import { AnyAction, Dispatch, Unsubscribe } from '@shopify/app-bridge/actions/types'; | ||
url: string; | ||
handle: string; | ||
} | ||
@@ -23,0 +24,0 @@ export declare type ApiClientConfig = PrivilegedAppConfig; |
@@ -32,2 +32,3 @@ "use strict"; | ||
var redux_1 = require("redux"); | ||
var error_1 = require("./components/utilities/error"); | ||
var HostProvider_1 = require("./HostProvider"); | ||
@@ -46,3 +47,3 @@ /** | ||
if (!context) { | ||
return; | ||
return error_1.throwMissingHostProvider(); | ||
} | ||
@@ -49,0 +50,0 @@ var app = context.app, addReducer = context.addReducer; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
193623
178
4283
2