@shopify/app-bridge-react 2.0.23 → 2.0.26

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.
@@ -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,108 @@
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");
6
+ var ButtonGroup_1 = require("@shopify/app-bridge/actions/ButtonGroup");
23
7
  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;
8
+ var useAppBridge_1 = require("../../useAppBridge");
9
+ function TitleBar(props) {
10
+ var title = props.title;
11
+ var app = useAppBridge_1.useAppBridge();
12
+ var currentProps = react_1.useRef({ title: title });
13
+ var titleBar = react_1.useMemo(function () {
14
+ /**
15
+ * We purposely don't pass buttons here as they will be replaced
16
+ * by the subsequent useEffect to call `set` to update the options.
17
+ * If we pass them in here button subscriptions will be created without
18
+ * being cleaned up.
19
+ */
20
+ return TitleBar_1.create(app, {});
21
+ }, [app]);
22
+ /**
23
+ * All option updates are handled in this useEffect so they can be cleaned up.
24
+ */
25
+ react_1.useEffect(function () {
26
+ var _a;
27
+ var propsChanged = JSON.stringify(currentProps.current) !== JSON.stringify(props);
28
+ currentProps.current = props;
29
+ if (propsChanged) {
30
+ titleBar.set(transformProps(app, props));
62
31
  }
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);
32
+ else {
33
+ /**
34
+ * We manually update the button callbacks when no props have changed aside from the
35
+ * callbacks to avoid sending an unnecessary UPDATE action to the host
36
+ */
37
+ var primaryAction = props.primaryAction, secondaryActions = props.secondaryActions, actionGroups = props.actionGroups, breadcrumbs = props.breadcrumbs;
38
+ var breadcrumb = Array.isArray(breadcrumbs)
39
+ ? breadcrumbs[breadcrumbs.length - 1]
40
+ : breadcrumbs;
41
+ updateButton(breadcrumb, titleBar.options.breadcrumbs);
42
+ updateButton(primaryAction, (_a = titleBar.options.buttons) === null || _a === void 0 ? void 0 : _a.primary);
43
+ updateSecondaryActions(titleBar, secondaryActions);
44
+ updateActionGroups(titleBar, actionGroups);
71
45
  }
72
- if (onAction != null) {
73
- button.subscribe(actions_1.Button.Action.CLICK, onAction);
46
+ return function () {
47
+ titleBar.unsubscribe();
48
+ };
49
+ }, [titleBar, props]);
50
+ return null;
51
+ }
52
+ exports.default = TitleBar;
53
+ function updateSecondaryActions(titleBar, secondaryActions) {
54
+ var _a, _b;
55
+ var secondaryButtons = ((_b = (_a = titleBar.options.buttons) === null || _a === void 0 ? void 0 : _a.secondary) === null || _b === void 0 ? void 0 : _b.filter(function (button) { return !ButtonGroup_1.isGroupedButton(button); })) || [];
56
+ secondaryButtons === null || secondaryButtons === void 0 ? void 0 : secondaryButtons.forEach(function (secondaryButton, index) {
57
+ return updateButton(secondaryActions === null || secondaryActions === void 0 ? void 0 : secondaryActions[index],
58
+ // This needs to be casted as the React TitleBar component doesn't accept button groups for secondary actions
59
+ secondaryButton);
60
+ });
61
+ }
62
+ function updateActionGroups(titleBar, actionGroups) {
63
+ var _a, _b;
64
+ var actionGroupButtons = ((_b = (_a = titleBar.options.buttons) === null || _a === void 0 ? void 0 : _a.secondary) === null || _b === void 0 ? void 0 : _b.filter(ButtonGroup_1.isGroupedButton)) ||
65
+ [];
66
+ actionGroupButtons === null || actionGroupButtons === void 0 ? void 0 : actionGroupButtons.forEach(function (actionBroupButton, index) {
67
+ var actionGroup = actionGroups === null || actionGroups === void 0 ? void 0 : actionGroups[index];
68
+ if (!actionGroup) {
69
+ return;
74
70
  }
75
- return button;
71
+ actionBroupButton.options.buttons.forEach(function (nestedButton, nestedIndex) {
72
+ return updateButton(actionGroup.actions[nestedIndex], nestedButton);
73
+ });
74
+ });
75
+ }
76
+ function transformProps(app, _a) {
77
+ var actionGroups = _a.actionGroups, breadcrumbs = _a.breadcrumbs, primaryAction = _a.primaryAction, secondaryActions = _a.secondaryActions, title = _a.title;
78
+ var breadcrumb = Array.isArray(breadcrumbs) ? breadcrumbs[breadcrumbs.length - 1] : breadcrumbs;
79
+ return {
80
+ title: title,
81
+ buttons: transformers_1.transformActions(app, {
82
+ primaryAction: primaryAction,
83
+ secondaryActions: secondaryActions,
84
+ actionGroups: actionGroups,
85
+ }),
86
+ breadcrumbs: breadcrumb ? transformBreadcrumb(app, breadcrumb) : undefined,
76
87
  };
77
- TitleBar.contextType = context_1.AppBridgeContext;
78
- return TitleBar;
79
- }(react_1.default.PureComponent));
80
- exports.default = TitleBar;
88
+ }
89
+ function transformBreadcrumb(app, breadcrumb, updateBreadcrumb) {
90
+ var button = updateBreadcrumb ||
91
+ Button_1.create(app, {
92
+ label: breadcrumb.content || '',
93
+ });
94
+ updateButton(breadcrumb, button);
95
+ return button;
96
+ }
97
+ function updateButton(actionProps, button) {
98
+ if (!actionProps || !button) {
99
+ return;
100
+ }
101
+ var redirect = transformers_1.generateRedirect(button.app, actionProps.url, actionProps.target);
102
+ if (redirect) {
103
+ button.subscribe(Button_1.Action.CLICK, redirect, button);
104
+ }
105
+ if (actionProps === null || actionProps === void 0 ? void 0 : actionProps.onAction) {
106
+ button.subscribe(Button_1.Action.CLICK, actionProps.onAction, button);
107
+ }
108
+ }
package/hooks/index.d.ts CHANGED
@@ -1,4 +1,8 @@
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';
8
+ export { useNavigate } from './useNavigate';
package/hooks/index.js CHANGED
@@ -1,11 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- 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");
9
13
  Object.defineProperty(exports, "useToast", { enumerable: true, get: function () { return useToast_1.useToast; } });
10
14
  var useAppBridgeState_1 = require("./useAppBridgeState");
11
15
  Object.defineProperty(exports, "useAppBridgeState", { enumerable: true, get: function () { return useAppBridgeState_1.useAppBridgeState; } });
16
+ var useNavigate_1 = require("./useNavigate");
17
+ Object.defineProperty(exports, "useNavigate", { enumerable: true, get: function () { return useNavigate_1.useNavigate; } });
@@ -42,8 +42,9 @@ var useAppBridge_1 = require("../../useAppBridge");
42
42
  var useAppBridgeState = function (query) {
43
43
  var app = useAppBridge_1.useAppBridge();
44
44
  var _a = react_1.useState(), state = _a[0], setState = _a[1];
45
+ var isUnmounted = react_1.useRef(false);
45
46
  var refresh = react_1.useCallback(function () { return __awaiter(void 0, void 0, void 0, function () {
46
- var state, _a;
47
+ var newState, _a;
47
48
  return __generator(this, function (_b) {
48
49
  switch (_b.label) {
49
50
  case 0:
@@ -57,9 +58,17 @@ var useAppBridgeState = function (query) {
57
58
  _a = _b.sent();
58
59
  _b.label = 4;
59
60
  case 4:
60
- state = _a;
61
- setState(state);
62
- return [2 /*return*/, state];
61
+ newState = _a;
62
+ if (isUnmounted.current) {
63
+ return [2 /*return*/];
64
+ }
65
+ setState(function (currentState) {
66
+ if (JSON.stringify(newState) === JSON.stringify(currentState)) {
67
+ return currentState;
68
+ }
69
+ return newState;
70
+ });
71
+ return [2 /*return*/];
63
72
  }
64
73
  });
65
74
  }); }, [app, query]);
@@ -70,6 +79,11 @@ var useAppBridgeState = function (query) {
70
79
  refresh();
71
80
  });
72
81
  }, [app, refresh]);
82
+ react_1.useEffect(function () {
83
+ return function () {
84
+ isUnmounted.current = true;
85
+ };
86
+ }, [app]);
73
87
  return state;
74
88
  };
75
89
  exports.useAppBridgeState = useAppBridgeState;
@@ -0,0 +1 @@
1
+ export * from './useFeatureRequest';
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ __exportStar(require("./useFeatureRequest"), exports);
@@ -0,0 +1,13 @@
1
+ import type { FeaturePermission, FeaturesAction } from '@shopify/app-bridge';
2
+ import { Group } from '@shopify/app-bridge/actions';
3
+ /**
4
+ * useFeatureRequest hook
5
+ *
6
+ * @public
7
+ * @remarks
8
+ * React hook performs a feature request and then returns
9
+ * the requested feature when permissions has been updated
10
+ * @param {Group} group - The requested group enum
11
+ * @param {string} action - The requested action. This param is optional
12
+ */
13
+ export declare function useFeatureRequest(group: Group, action?: string): FeaturesAction | FeaturePermission | undefined;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useFeatureRequest = void 0;
4
+ var react_1 = require("react");
5
+ var Features_1 = require("@shopify/app-bridge/actions/Features");
6
+ var useAppBridge_1 = require("../../useAppBridge");
7
+ var useFeaturesAvailable_1 = require("../useFeaturesAvailable");
8
+ /**
9
+ * useFeatureRequest hook
10
+ *
11
+ * @public
12
+ * @remarks
13
+ * React hook performs a feature request and then returns
14
+ * the requested feature when permissions has been updated
15
+ * @param {Group} group - The requested group enum
16
+ * @param {string} action - The requested action. This param is optional
17
+ */
18
+ function useFeatureRequest(group, action) {
19
+ var app = useAppBridge_1.useAppBridge();
20
+ var featuresAvailable = useFeaturesAvailable_1.useFeaturesAvailable();
21
+ var _a = react_1.useState(), feature = _a[0], setFeature = _a[1];
22
+ var handleFeatureUpdate = react_1.useCallback(function (featuresAvailable) {
23
+ var updatedFeatures = featuresAvailable === null || featuresAvailable === void 0 ? void 0 : featuresAvailable[group];
24
+ if (action && (updatedFeatures === null || updatedFeatures === void 0 ? void 0 : updatedFeatures[action])) {
25
+ var actionPermission_1 = updatedFeatures === null || updatedFeatures === void 0 ? void 0 : updatedFeatures[action];
26
+ setFeature(function (currentState) {
27
+ if (JSON.stringify(actionPermission_1) !== JSON.stringify(currentState)) {
28
+ return actionPermission_1;
29
+ }
30
+ return currentState;
31
+ });
32
+ return;
33
+ }
34
+ setFeature(function (currentState) {
35
+ if (JSON.stringify(updatedFeatures) !== JSON.stringify(currentState)) {
36
+ return updatedFeatures;
37
+ }
38
+ return currentState;
39
+ });
40
+ }, [group, action]);
41
+ react_1.useEffect(function () {
42
+ Features_1.create(app).dispatch(Features_1.Action.REQUEST, { feature: group, action: action });
43
+ }, [app, group, action]);
44
+ react_1.useEffect(function () {
45
+ handleFeatureUpdate(featuresAvailable);
46
+ }, [featuresAvailable, handleFeatureUpdate]);
47
+ return feature;
48
+ }
49
+ exports.useFeatureRequest = useFeatureRequest;
@@ -0,0 +1,2 @@
1
+ export type { FeaturesAvailable } from './useFeaturesAvailable';
2
+ export { useFeaturesAvailable } from './useFeaturesAvailable';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useFeaturesAvailable = void 0;
4
+ var useFeaturesAvailable_1 = require("./useFeaturesAvailable");
5
+ Object.defineProperty(exports, "useFeaturesAvailable", { enumerable: true, get: function () { return useFeaturesAvailable_1.useFeaturesAvailable; } });
@@ -0,0 +1,12 @@
1
+ import { Group } from '@shopify/app-bridge/actions/types';
2
+ import { AppBridgeState } from '@shopify/app-bridge/client';
3
+ export declare type FeaturesAvailable = AppBridgeState['features'];
4
+ /**
5
+ * useFeaturesAvailable hook
6
+ *
7
+ * @remarks
8
+ * React hook that wraps the Shopify App Bridge getFeaturesAvailable method.
9
+ *
10
+ * @public
11
+ */
12
+ export declare function useFeaturesAvailable(...query: Group[]): import("@shopify/app-bridge/client").FeaturesAvailable<Group> | undefined;