@shopify/app-bridge-react 2.0.24 → 2.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,26 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [2.0.25](https://github.com/Shopify/app-bridge/compare/v2.0.24...v2.0.25) (2022-04-20)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **app-bridge-react:** prevent Resource Picker from sending unecessary updates ([62abe7f](https://github.com/Shopify/app-bridge/commit/62abe7f4116bf4c78934b8eb86e9a74fc0ea03d5))
12
+ * refactor useFeaturesAvailable to always return state ([2634016](https://github.com/Shopify/app-bridge/commit/2634016ccc9b883dd979c82585833b0fdf73d6d0))
13
+ * **app-bridge-react:** ensure useAppState only modifies the state when it has actually changed ([0a2f017](https://github.com/Shopify/app-bridge/commit/0a2f017c35e7d5dda8642eb68801d25158cb7539))
14
+
15
+
16
+ ### Features
17
+
18
+ * Add optional router prop to Provider ([4d032b1](https://github.com/Shopify/app-bridge/commit/4d032b1e0cc940ab02a07339ed48cc23e21e26ae))
19
+ * **app-bridge-react:** add useFeatureRequest hook ([adc03c9](https://github.com/Shopify/app-bridge/commit/adc03c9c4d1b2b9e3a2ea44a9ed2eaf4b75b99bf))
20
+ * useFeature hook, refactor React playground ([e1b7c71](https://github.com/Shopify/app-bridge/commit/e1b7c71a4e3f3fb3a6b0373ea6aedc05a34baaea))
21
+
22
+
23
+
24
+
25
+
6
26
  ## [2.0.24](https://github.com/Shopify/app-bridge/compare/v2.0.23...v2.0.24) (2022-04-08)
7
27
 
8
28
 
@@ -1,5 +1,7 @@
1
- import React from 'react';
1
+ import React, { PropsWithChildren } from 'react';
2
2
  import type { AppConfigV2, DispatchActionHook } from '@shopify/app-bridge/client';
3
+ import type { History } from '../ClientRouter';
4
+ import type { LocationOrHref } from '../RoutePropagator';
3
5
  /**
4
6
  * Provider props
5
7
  *
@@ -10,26 +12,70 @@ export interface Props {
10
12
  config: AppConfigV2;
11
13
  /** The child elements to render. */
12
14
  children?: React.ReactNode;
15
+ /**
16
+ * Option to set up client routing and route propagation automatically.
17
+ * Passing in a router will allow you to bypass setting these
18
+ * utilities up yourself.
19
+ *
20
+ * If you are using React Router, ensure that the Provider is a child
21
+ * of the router component. For example:
22
+ *
23
+ * import {useMemo} from 'react';
24
+ * import {useLocation, useNavigate, BrowserRouter} from 'react-router-dom';
25
+ * import {Provider} from '@shopify/app-bridge-react';
26
+ * import Routes from './Routes';
27
+ *
28
+ * export function App() {
29
+ * const navigate = useNavigate();
30
+ * const location = useLocation();
31
+ * const history = useMemo(
32
+ * () => ({replace: (path: string) => navigate(path, {replace: true})}),
33
+ * [navigate],
34
+ * );
35
+ * const router = useMemo(
36
+ * () => ({
37
+ * location,
38
+ * history,
39
+ * }),
40
+ * [location, navigate],
41
+ * );
42
+ * return (
43
+ * <Provider
44
+ * apiKey={{
45
+ * apiKey: 'API key from Shopify Partner Dashboard',
46
+ * host: host,
47
+ * }}
48
+ * router={router}
49
+ * >
50
+ * <Routes />
51
+ * </Provider>
52
+ * );
53
+ * }
54
+ *
55
+ * export default function AppWrapper() {
56
+ * return (
57
+ * <BrowserRouter>
58
+ * <App />
59
+ * </BrowserRouter>
60
+ * );
61
+ * }
62
+ */
63
+ router?: {
64
+ location: LocationOrHref;
65
+ history: History;
66
+ };
13
67
  }
14
68
  /**
15
69
  * Create an App Bridge client application from a config and pass it as the
16
70
  * value to the context provider.
17
71
  *
18
- * @remarks
19
- * You'll probably want something a little more robust than storing the current
20
- * app instance in a module-level global.
21
- *
22
72
  * @public
23
73
  */
24
- declare class Provider extends React.Component<Props> {
25
- private app;
26
- private get appInstance();
27
- render(): JSX.Element;
28
- }
29
- export default Provider;
74
+ declare function Provider({ config, router, children }: PropsWithChildren<Props>): JSX.Element;
30
75
  /**
31
76
  * Augment actions with clientInterface metadata, identifying use of this library
32
77
  *
33
78
  * @internal
34
79
  */
35
80
  export declare const setClientInterfaceHook: DispatchActionHook;
81
+ export default Provider;
@@ -1,19 +1,4 @@
1
1
  "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- if (typeof b !== "function" && b !== null)
11
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
- extendStatics(d, b);
13
- function __() { this.constructor = d; }
14
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
- };
16
- })();
17
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
3
  if (k2 === undefined) k2 = k;
19
4
  Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
@@ -33,52 +18,34 @@ var __importStar = (this && this.__importStar) || function (mod) {
33
18
  __setModuleDefault(result, mod);
34
19
  return result;
35
20
  };
36
- var __importDefault = (this && this.__importDefault) || function (mod) {
37
- return (mod && mod.__esModule) ? mod : { "default": mod };
38
- };
39
21
  Object.defineProperty(exports, "__esModule", { value: true });
40
22
  exports.setClientInterfaceHook = void 0;
41
- var react_1 = __importDefault(require("react"));
23
+ var react_1 = __importStar(require("react"));
42
24
  var app_bridge_1 = __importStar(require("@shopify/app-bridge"));
43
25
  var context_1 = require("../../context");
26
+ var ClientRouter_1 = require("../ClientRouter");
27
+ var RoutePropagator_1 = require("../RoutePropagator");
44
28
  // eslint-disable-next-line @typescript-eslint/no-var-requires
45
29
  var packageJson = require('../../package.json');
46
30
  /**
47
31
  * Create an App Bridge client application from a config and pass it as the
48
32
  * value to the context provider.
49
33
  *
50
- * @remarks
51
- * You'll probably want something a little more robust than storing the current
52
- * app instance in a module-level global.
53
- *
54
34
  * @public
55
35
  */
56
- var Provider = /** @class */ (function (_super) {
57
- __extends(Provider, _super);
58
- function Provider() {
59
- var _this = _super !== null && _super.apply(this, arguments) || this;
60
- _this.app = _this.appInstance;
61
- return _this;
62
- }
63
- Object.defineProperty(Provider.prototype, "appInstance", {
64
- get: function () {
65
- if (!this.app) {
66
- this.app = app_bridge_1.default(this.props.config);
67
- if (this.app && this.app.hooks) {
68
- this.app.hooks.set(app_bridge_1.LifecycleHook.DispatchAction, exports.setClientInterfaceHook);
69
- }
70
- }
71
- return this.app;
72
- },
73
- enumerable: false,
74
- configurable: true
75
- });
76
- Provider.prototype.render = function () {
77
- return (react_1.default.createElement(context_1.AppBridgeContext.Provider, { value: this.appInstance }, this.props.children));
78
- };
79
- return Provider;
80
- }(react_1.default.Component));
81
- exports.default = Provider;
36
+ function Provider(_a) {
37
+ var config = _a.config, router = _a.router, children = _a.children;
38
+ var app = react_1.useMemo(function () { return app_bridge_1.default(config); }, [JSON.stringify(config)]);
39
+ react_1.useEffect(function () {
40
+ if (app === null || app === void 0 ? void 0 : app.hooks) {
41
+ app.hooks.set(app_bridge_1.LifecycleHook.DispatchAction, exports.setClientInterfaceHook);
42
+ }
43
+ }, [app]);
44
+ var routerMarkup = (router === null || router === void 0 ? void 0 : router.history) && (router === null || router === void 0 ? void 0 : router.location) ? (react_1.default.createElement(Router, { history: router.history, location: router.location })) : null;
45
+ return (react_1.default.createElement(context_1.AppBridgeContext.Provider, { value: app },
46
+ routerMarkup,
47
+ children));
48
+ }
82
49
  /**
83
50
  * Augment actions with clientInterface metadata, identifying use of this library
84
51
  *
@@ -94,3 +61,10 @@ var setClientInterfaceHook = function (next) {
94
61
  };
95
62
  };
96
63
  exports.setClientInterfaceHook = setClientInterfaceHook;
64
+ function Router(_a) {
65
+ var history = _a.history, location = _a.location;
66
+ ClientRouter_1.useClientRouting(history);
67
+ RoutePropagator_1.useRoutePropagation(location);
68
+ return null;
69
+ }
70
+ exports.default = Provider;
@@ -1,11 +1,10 @@
1
- import React from 'react';
2
- import { ResourcePicker as AppBridgeResourcePicker } from '@shopify/app-bridge/actions';
3
- import { BaseResource } from '@shopify/app-bridge/actions/ResourcePicker';
1
+ import { ActionVerb, ResourceType } from '@shopify/app-bridge/actions/ResourcePicker';
2
+ import type { BaseResource, Options, ResourceSelection, ProductOptions } from '@shopify/app-bridge/actions/ResourcePicker';
4
3
  export interface SelectPayload {
5
4
  /** The selected resources
6
5
  * @see {@link https://help.shopify.com/en/api/embedded-apps/app-bridge/actions/resourcepicker|resource picker documentation} for more information
7
6
  */
8
- selection: AppBridgeResourcePicker.ResourceSelection[];
7
+ selection: ResourceSelection[];
9
8
  }
10
9
  interface BaseProps {
11
10
  /** Whether the picker is open or not */
@@ -26,7 +25,7 @@ interface BaseProps {
26
25
  /** Whether to allow selection of multiple items, or the maximum number of selected items */
27
26
  selectMultiple?: boolean | number;
28
27
  /** Override default action verb `Add`. The actionVerb appears in the title `<actionVerb>` `<resourceType>` and as the primary action of the resource picker. */
29
- actionVerb?: AppBridgeResourcePicker.ActionVerb;
28
+ actionVerb?: ActionVerb;
30
29
  /** Callback when a selection has been made */
31
30
  onSelection?(selectPayload: SelectPayload): void;
32
31
  /** Callback when the picker is closed without selection */
@@ -63,15 +62,7 @@ export declare type Props = ProductPickerProps | ProductVariantProps | Collectio
63
62
  *
64
63
  * @public
65
64
  */
66
- declare class ResourcePicker extends React.PureComponent<Props, never> {
67
- static contextType: React.Context<import("../../context").IAppBridgeContext>;
68
- static ActionVerb: typeof AppBridgeResourcePicker.ActionVerb;
69
- private focusReturnPoint;
70
- private picker;
71
- componentDidMount(): void;
72
- componentDidUpdate(prevProps: Props): void;
73
- componentWillUnmount(): void;
74
- render(): null;
75
- getActionOptions(): AppBridgeResourcePicker.Options | AppBridgeResourcePicker.ProductOptions;
76
- }
65
+ declare function ResourcePicker(props: Props): null;
77
66
  export default ResourcePicker;
67
+ export type { BaseResource, Options, ProductOptions };
68
+ export { ActionVerb, ResourceType };
@@ -1,19 +1,4 @@
1
1
  "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- if (typeof b !== "function" && b !== null)
11
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
- extendStatics(d, b);
13
- function __() { this.constructor = d; }
14
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
- };
16
- })();
17
2
  var __assign = (this && this.__assign) || function () {
18
3
  __assign = Object.assign || function(t) {
19
4
  for (var s, i = 1, n = arguments.length; i < n; i++) {
@@ -25,13 +10,13 @@ var __assign = (this && this.__assign) || function () {
25
10
  };
26
11
  return __assign.apply(this, arguments);
27
12
  };
28
- var __importDefault = (this && this.__importDefault) || function (mod) {
29
- return (mod && mod.__esModule) ? mod : { "default": mod };
30
- };
31
13
  Object.defineProperty(exports, "__esModule", { value: true });
32
- var react_1 = __importDefault(require("react"));
33
- var actions_1 = require("@shopify/app-bridge/actions");
34
- var context_1 = require("../../context");
14
+ exports.ResourceType = exports.ActionVerb = void 0;
15
+ var react_1 = require("react");
16
+ var ResourcePicker_1 = require("@shopify/app-bridge/actions/ResourcePicker");
17
+ Object.defineProperty(exports, "ActionVerb", { enumerable: true, get: function () { return ResourcePicker_1.ActionVerb; } });
18
+ Object.defineProperty(exports, "ResourceType", { enumerable: true, get: function () { return ResourcePicker_1.ResourceType; } });
19
+ var useAppBridge_1 = require("../../useAppBridge");
35
20
  /**
36
21
  * ResourcePicker component
37
22
  *
@@ -40,92 +25,90 @@ var context_1 = require("../../context");
40
25
  *
41
26
  * @public
42
27
  */
43
- var ResourcePicker = /** @class */ (function (_super) {
44
- __extends(ResourcePicker, _super);
45
- function ResourcePicker() {
46
- var _this = _super !== null && _super.apply(this, arguments) || this;
47
- _this.focusReturnPoint = null;
48
- return _this;
49
- }
50
- ResourcePicker.prototype.componentDidMount = function () {
51
- var _a = this.props, open = _a.open, resourceType = _a.resourceType, onSelection = _a.onSelection, onCancel = _a.onCancel;
52
- var app = this.context;
53
- this.picker = actions_1.ResourcePicker.create(app, {
54
- resourceType: actions_1.ResourcePicker.ResourceType[resourceType],
55
- options: this.getActionOptions(),
28
+ function ResourcePicker(props) {
29
+ var app = useAppBridge_1.useAppBridge();
30
+ var focusReturnPoint = react_1.useRef(null);
31
+ var resourceType = props.resourceType, onSelection = props.onSelection, onCancel = props.onCancel, open = props.open;
32
+ // Initialize with open: false so the open action will dispatch on initial load
33
+ var prevProps = react_1.useRef({ open: false });
34
+ var picker = react_1.useMemo(function () {
35
+ return ResourcePicker_1.create(app, {
36
+ resourceType: ResourcePicker_1.ResourceType[resourceType],
37
+ options: getActionOptions(props),
56
38
  });
57
- if (onSelection != null) {
58
- this.picker.subscribe(actions_1.ResourcePicker.Action.SELECT, onSelection);
59
- }
60
- if (onCancel != null) {
61
- this.picker.subscribe(actions_1.ResourcePicker.Action.CANCEL, onCancel);
62
- }
63
- if (open) {
64
- this.focusReturnPoint = document.activeElement;
65
- this.picker.dispatch(actions_1.ResourcePicker.Action.OPEN);
66
- }
67
- };
68
- ResourcePicker.prototype.componentDidUpdate = function (prevProps) {
69
- var wasOpen = prevProps.open;
70
- var _a = this.props, open = _a.open, onCancel = _a.onCancel, onSelection = _a.onSelection;
71
- this.picker.unsubscribe();
72
- this.picker.set(this.getActionOptions());
73
- if (onSelection != null) {
74
- this.picker.subscribe(actions_1.ResourcePicker.Action.SELECT, onSelection);
75
- }
76
- if (onCancel != null) {
77
- this.picker.subscribe(actions_1.ResourcePicker.Action.CANCEL, onCancel);
78
- }
39
+ // We purposely want to reuse the same picker instance
40
+ // and use a useEffect to call `picker.set` when needed
41
+ }, [app]);
42
+ react_1.useEffect(function () {
43
+ var _a;
44
+ var wasOpen = (_a = prevProps.current) === null || _a === void 0 ? void 0 : _a.open;
79
45
  if (wasOpen !== open) {
80
46
  if (open) {
81
- this.picker.dispatch(actions_1.ResourcePicker.Action.OPEN);
47
+ picker.dispatch(ResourcePicker_1.Action.OPEN);
82
48
  }
83
49
  else {
84
- this.picker.dispatch(actions_1.ResourcePicker.Action.CLOSE);
50
+ picker.dispatch(ResourcePicker_1.Action.CLOSE);
85
51
  }
86
52
  }
87
53
  if (!wasOpen && open) {
88
- this.focusReturnPoint = document.activeElement;
54
+ focusReturnPoint.current = document.activeElement;
89
55
  }
90
56
  else if (wasOpen &&
91
57
  !open &&
92
- this.focusReturnPoint != null &&
93
- document.contains(this.focusReturnPoint)) {
94
- this.focusReturnPoint.focus();
95
- this.focusReturnPoint = null;
58
+ focusReturnPoint.current != null &&
59
+ document.contains(focusReturnPoint.current)) {
60
+ focusReturnPoint.current.focus();
61
+ focusReturnPoint.current = null;
96
62
  }
97
- };
98
- ResourcePicker.prototype.componentWillUnmount = function () {
99
- this.picker.unsubscribe();
100
- };
101
- ResourcePicker.prototype.render = function () {
102
- return null;
103
- };
104
- ResourcePicker.prototype.getActionOptions = function () {
105
- var _a = this.props, initialQuery = _a.initialQuery, initialSelectionIds = _a.initialSelectionIds, showHidden = _a.showHidden, allowMultiple = _a.allowMultiple, selectMultiple = _a.selectMultiple, actionVerb = _a.actionVerb;
106
- var sharedOptions = {
107
- initialQuery: initialQuery,
108
- initialSelectionIds: initialSelectionIds,
109
- showHidden: showHidden,
110
- selectMultiple: selectMultiple !== null && selectMultiple !== void 0 ? selectMultiple : allowMultiple,
111
- actionVerb: actionVerb,
63
+ }, [open]);
64
+ react_1.useEffect(function () {
65
+ var unsubscribeList = [];
66
+ if (onSelection != null) {
67
+ unsubscribeList.push(picker.subscribe(ResourcePicker_1.Action.SELECT, onSelection));
68
+ }
69
+ if (onCancel != null) {
70
+ unsubscribeList.push(picker.subscribe(ResourcePicker_1.Action.CANCEL, onCancel));
71
+ }
72
+ return function () {
73
+ var unsubscribe = unsubscribeList.pop();
74
+ while (unsubscribe) {
75
+ unsubscribe();
76
+ unsubscribe = unsubscribeList.pop();
77
+ }
112
78
  };
113
- var result = sharedOptions;
114
- if (this.props.resourceType === 'Product') {
115
- var _b = this.props, showVariants = _b.showVariants, showDraft = _b.showDraft, showArchived = _b.showArchived, showDraftBadge = _b.showDraftBadge, showArchivedBadge = _b.showArchivedBadge;
116
- var productSpecificOptions = {
117
- showVariants: showVariants,
118
- showDraft: showDraft,
119
- showArchived: showArchived,
120
- showDraftBadge: showDraftBadge,
121
- showArchivedBadge: showArchivedBadge,
122
- };
123
- result = __assign(__assign({}, sharedOptions), productSpecificOptions);
79
+ }, [onSelection, onCancel]);
80
+ react_1.useEffect(function () {
81
+ var shouldUpdate = JSON.stringify(__assign(__assign({}, prevProps.current), { open: undefined })) !==
82
+ JSON.stringify(__assign(__assign({}, props), { open: undefined }));
83
+ if (!shouldUpdate) {
84
+ return;
124
85
  }
125
- return result;
86
+ picker.set(getActionOptions(props));
87
+ prevProps.current = props;
88
+ }, [props]);
89
+ return null;
90
+ }
91
+ function getActionOptions(props) {
92
+ var initialQuery = props.initialQuery, initialSelectionIds = props.initialSelectionIds, showHidden = props.showHidden, allowMultiple = props.allowMultiple, selectMultiple = props.selectMultiple, actionVerb = props.actionVerb;
93
+ var sharedOptions = {
94
+ initialQuery: initialQuery,
95
+ initialSelectionIds: initialSelectionIds,
96
+ showHidden: showHidden,
97
+ selectMultiple: selectMultiple !== null && selectMultiple !== void 0 ? selectMultiple : allowMultiple,
98
+ actionVerb: actionVerb,
126
99
  };
127
- ResourcePicker.contextType = context_1.AppBridgeContext;
128
- ResourcePicker.ActionVerb = actions_1.ResourcePicker.ActionVerb;
129
- return ResourcePicker;
130
- }(react_1.default.PureComponent));
100
+ var result = sharedOptions;
101
+ if (props.resourceType === 'Product') {
102
+ var showVariants = props.showVariants, showDraft = props.showDraft, showArchived = props.showArchived, showDraftBadge = props.showDraftBadge, showArchivedBadge = props.showArchivedBadge;
103
+ var productSpecificOptions = {
104
+ showVariants: showVariants,
105
+ showDraft: showDraft,
106
+ showArchived: showArchived,
107
+ showDraftBadge: showDraftBadge,
108
+ showArchivedBadge: showArchivedBadge,
109
+ };
110
+ result = __assign(__assign({}, sharedOptions), productSpecificOptions);
111
+ }
112
+ return result;
113
+ }
131
114
  exports.default = ResourcePicker;
@@ -1,4 +1,3 @@
1
- import React from 'react';
2
1
  import { ActionProps, ActionGroupProps, Target } from '../../types';
3
2
  export interface Breadcrumb {
4
3
  /** Content the action displays */
@@ -16,8 +15,8 @@ export interface Breadcrumb {
16
15
  export interface Props {
17
16
  /** TitleBar title */
18
17
  title: string;
19
- /** Collection of breadcrumbs */
20
- breadcrumbs?: Breadcrumb[];
18
+ /** The current breadcrumb; only displays the last item in array */
19
+ breadcrumbs?: Breadcrumb | Breadcrumb[];
21
20
  /** Primary TitleBar action */
22
21
  primaryAction?: ActionProps;
23
22
  /** Collection of secondary TitleBar actions */
@@ -25,14 +24,4 @@ export interface Props {
25
24
  /** Collection of TitleBar groups of secondary actions */
26
25
  actionGroups?: ActionGroupProps[];
27
26
  }
28
- declare class TitleBar extends React.PureComponent<Props, never> {
29
- static contextType: React.Context<import("../../context").IAppBridgeContext>;
30
- private titleBar;
31
- componentDidMount(): void;
32
- componentDidUpdate(): void;
33
- componentWillUnmount(): void;
34
- render(): null;
35
- private transformProps;
36
- private transformBreadcrumbs;
37
- }
38
- export default TitleBar;
27
+ export default function TitleBar(props: Props): null;
@@ -1,80 +1,55 @@
1
1
  "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- if (typeof b !== "function" && b !== null)
11
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
- extendStatics(d, b);
13
- function __() { this.constructor = d; }
14
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
- };
16
- })();
17
- var __importDefault = (this && this.__importDefault) || function (mod) {
18
- return (mod && mod.__esModule) ? mod : { "default": mod };
19
- };
20
2
  Object.defineProperty(exports, "__esModule", { value: true });
21
- var react_1 = __importDefault(require("react"));
22
- var actions_1 = require("@shopify/app-bridge/actions");
3
+ var react_1 = require("react");
4
+ var Button_1 = require("@shopify/app-bridge/actions/Button");
5
+ var TitleBar_1 = require("@shopify/app-bridge/actions/TitleBar");
23
6
  var transformers_1 = require("../../utilities/transformers");
24
- var context_1 = require("../../context");
25
- var TitleBar = /** @class */ (function (_super) {
26
- __extends(TitleBar, _super);
27
- function TitleBar() {
28
- return _super !== null && _super.apply(this, arguments) || this;
29
- }
30
- TitleBar.prototype.componentDidMount = function () {
31
- var app = this.context;
32
- this.titleBar = actions_1.TitleBar.create(app, this.transformProps());
33
- };
34
- TitleBar.prototype.componentDidUpdate = function () {
35
- this.titleBar.unsubscribe();
36
- this.titleBar.set(this.transformProps());
37
- };
38
- TitleBar.prototype.componentWillUnmount = function () {
39
- this.titleBar.unsubscribe();
40
- };
41
- TitleBar.prototype.render = function () {
42
- return null;
43
- };
44
- TitleBar.prototype.transformProps = function () {
45
- var app = this.context;
46
- var _a = this.props, title = _a.title, primaryAction = _a.primaryAction, secondaryActions = _a.secondaryActions, actionGroups = _a.actionGroups;
47
- return {
48
- title: title,
49
- buttons: transformers_1.transformActions(app, {
50
- primaryAction: primaryAction,
51
- secondaryActions: secondaryActions,
52
- actionGroups: actionGroups,
53
- }),
54
- breadcrumbs: this.transformBreadcrumbs(),
55
- };
56
- };
57
- TitleBar.prototype.transformBreadcrumbs = function () {
58
- var app = this.context;
59
- var breadcrumbs = this.props.breadcrumbs;
60
- if (breadcrumbs == null || breadcrumbs.length === 0) {
61
- return undefined;
62
- }
63
- var breadcrumb = breadcrumbs[breadcrumbs.length - 1];
64
- var url = breadcrumb.url, onAction = breadcrumb.onAction, target = breadcrumb.target, content = breadcrumb.content;
65
- var button = actions_1.Button.create(app, {
66
- label: content || '',
67
- });
68
- var redirect = transformers_1.generateRedirect(app, url, target);
69
- if (redirect != null) {
70
- button.subscribe(actions_1.Button.Action.CLICK, redirect);
7
+ var useAppBridge_1 = require("../../useAppBridge");
8
+ function TitleBar(props) {
9
+ var app = useAppBridge_1.useAppBridge();
10
+ var titleBar = react_1.useMemo(function () {
11
+ return TitleBar_1.create(app, transformProps(app, props));
12
+ }, [app]);
13
+ var currentProps = react_1.useRef(props);
14
+ react_1.useEffect(function () {
15
+ var propsChanged = JSON.stringify(currentProps.current) !== JSON.stringify(props);
16
+ if (propsChanged) {
17
+ currentProps.current = props;
71
18
  }
72
- if (onAction != null) {
73
- button.subscribe(actions_1.Button.Action.CLICK, onAction);
74
- }
75
- return button;
76
- };
77
- TitleBar.contextType = context_1.AppBridgeContext;
78
- return TitleBar;
79
- }(react_1.default.PureComponent));
19
+ titleBar.set(transformProps(app, props), propsChanged);
20
+ }, [titleBar, props]);
21
+ react_1.useEffect(function () {
22
+ return function () {
23
+ titleBar.unsubscribe();
24
+ };
25
+ }, [titleBar]);
26
+ return null;
27
+ }
80
28
  exports.default = TitleBar;
29
+ function transformProps(app, _a) {
30
+ var actionGroups = _a.actionGroups, breadcrumbs = _a.breadcrumbs, primaryAction = _a.primaryAction, secondaryActions = _a.secondaryActions, title = _a.title;
31
+ var breadcrumb = Array.isArray(breadcrumbs) ? breadcrumbs[breadcrumbs.length - 1] : breadcrumbs;
32
+ return {
33
+ title: title,
34
+ buttons: transformers_1.transformActions(app, {
35
+ primaryAction: primaryAction,
36
+ secondaryActions: secondaryActions,
37
+ actionGroups: actionGroups,
38
+ }),
39
+ breadcrumbs: breadcrumb ? transformBreadcrumb(app, breadcrumb) : undefined,
40
+ };
41
+ }
42
+ function transformBreadcrumb(app, breadcrumb) {
43
+ var url = breadcrumb.url, onAction = breadcrumb.onAction, target = breadcrumb.target, content = breadcrumb.content;
44
+ var button = Button_1.create(app, {
45
+ label: content || '',
46
+ });
47
+ var redirect = transformers_1.generateRedirect(app, url, target);
48
+ if (redirect) {
49
+ button.subscribe(Button_1.Action.CLICK, redirect);
50
+ }
51
+ if (onAction) {
52
+ button.subscribe(Button_1.Action.CLICK, onAction);
53
+ }
54
+ return button;
55
+ }
package/hooks/index.d.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  export { useContextualSaveBar } from './useContextualSaveBar';
2
+ export { useFeaturesAvailable } from './useFeaturesAvailable';
3
+ export { useFeatureRequest } from './useFeatureRequest';
4
+ export type { FeaturesAvailable } from './useFeaturesAvailable';
2
5
  export { useNavigationHistory } from './useNavigationHistory';
3
6
  export { useToast } from './useToast';
4
7
  export { useAppBridgeState } from './useAppBridgeState';
package/hooks/index.js CHANGED
@@ -1,8 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useNavigate = exports.useAppBridgeState = exports.useToast = exports.useNavigationHistory = exports.useContextualSaveBar = void 0;
3
+ exports.useNavigate = exports.useAppBridgeState = exports.useToast = exports.useNavigationHistory = exports.useFeatureRequest = exports.useFeaturesAvailable = exports.useContextualSaveBar = void 0;
4
4
  var useContextualSaveBar_1 = require("./useContextualSaveBar");
5
5
  Object.defineProperty(exports, "useContextualSaveBar", { enumerable: true, get: function () { return useContextualSaveBar_1.useContextualSaveBar; } });
6
+ var useFeaturesAvailable_1 = require("./useFeaturesAvailable");
7
+ Object.defineProperty(exports, "useFeaturesAvailable", { enumerable: true, get: function () { return useFeaturesAvailable_1.useFeaturesAvailable; } });
8
+ var useFeatureRequest_1 = require("./useFeatureRequest");
9
+ Object.defineProperty(exports, "useFeatureRequest", { enumerable: true, get: function () { return useFeatureRequest_1.useFeatureRequest; } });
6
10
  var useNavigationHistory_1 = require("./useNavigationHistory");
7
11
  Object.defineProperty(exports, "useNavigationHistory", { enumerable: true, get: function () { return useNavigationHistory_1.useNavigationHistory; } });
8
12
  var useToast_1 = require("./useToast");