UNPKG

@carbon/ibm-products

Version:
149 lines (147 loc) 5.75 kB
/** * Copyright IBM Corp. 2020, 2026 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ const require_runtime = require("../../_virtual/_rolldown/runtime.js"); const require_props_helper = require("../../global/js/utils/props-helper.js"); let react = require("react"); react = require_runtime.__toESM(react); let prop_types = require("prop-types"); prop_types = require_runtime.__toESM(prop_types); let _carbon_feature_flags = require("@carbon/feature-flags"); //#region src/components/FeatureFlags/index.tsx /** * Copyright IBM Corp. 2024, 2025 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ _carbon_feature_flags.FeatureFlags.merge({ "default-portal-target-body": true, "enable-datagrid-useInlineEdit": false, "enable-datagrid-useEditableCell": false, "enable-datagrid-useCustomizeColumns": false, "ExampleComponent.secondaryIcon": false, "ExampleComponent.useExample": false, "enable-test-flag-a": false, "enable-test-flag-b": true, enableSidepanelResizer: false }); /** * Our FeatureFlagContext is used alongside the FeatureFlags component to enable * or disable feature flags in a given React tree */ const FeatureFlagContext = (0, react.createContext)(_carbon_feature_flags.FeatureFlags); /** * Supports an object of feature flag values with the `flags` prop, merging them * along with the current `FeatureFlagContext` to provide consumers to check if * a feature flag is enabled or disabled in a given React tree */ function FeatureFlags({ children, flags = {}, defaultPortalTargetBody = true, enableDatagridUseInlineEdit = false, enableDatagridUseEditableCell = false, enableDatagridUseCustomizeColumns = false, enableSidepanelResizer = false, enableTestFlagA = false, enableTestFlagB = false }) { const parentScope = (0, react.useContext)(FeatureFlagContext); const [prevParentScope, setPrevParentScope] = (0, react.useState)(parentScope); const combinedFlags = { "default-portal-target-body": defaultPortalTargetBody, "enable-datagrid-useInlineEdit": enableDatagridUseInlineEdit, "enable-datagrid-useEditableCell": enableDatagridUseEditableCell, "enable-datagrid-useCustomizeColumns": enableDatagridUseCustomizeColumns, enableSidepanelResizer, "enable-test-flag-a": enableTestFlagA, "enable-test-flag-b": enableTestFlagB, ...flags }; const [scope, updateScope] = (0, react.useState)(() => { const scope = (0, _carbon_feature_flags.createScope)(combinedFlags); scope.mergeWithScope(parentScope); return scope; }); if (parentScope !== prevParentScope) { const scope = (0, _carbon_feature_flags.createScope)(combinedFlags); scope.mergeWithScope(parentScope); updateScope(scope); setPrevParentScope(parentScope); } useChangedValue(combinedFlags, isEqual, (changedFlags) => { const scope = (0, _carbon_feature_flags.createScope)(changedFlags); scope.mergeWithScope(parentScope); updateScope(scope); }); return /* @__PURE__ */ react.default.createElement(FeatureFlagContext.Provider, { value: scope }, children); } FeatureFlags.propTypes = { children: prop_types.default.node, /** * Provide the feature flags to enabled or disabled in the current React tree */ defaultPortalTargetBody: prop_types.default.bool, enableDatagridUseCustomizeColumns: prop_types.default.bool, enableDatagridUseEditableCell: prop_types.default.bool, enableDatagridUseInlineEdit: prop_types.default.bool, enableSidepanelResizer: prop_types.default.bool, enableTestFlagA: prop_types.default.bool, enableTestFlagB: prop_types.default.bool, flags: require_props_helper.deprecateProp(prop_types.default.objectOf(prop_types.default.bool), "The `flags` prop for `FeatureFlag` has been deprecated. Please pass the flags directly as props in camelCase") }; /** * This hook will store previous versions of the given `value` and compare the * current value to the previous one using the `compare` function. If the * compare function returns true, then the given `callback` is invoked in an * effect. * * @param {any} value * @param {Function} compare * @param {Function} callback */ function useChangedValue(value, compare, callback) { const initialRender = (0, react.useRef)(false); const savedCallback = (0, react.useRef)(callback); const [prevValue, setPrevValue] = (0, react.useState)(value); if (!compare(prevValue, value)) setPrevValue(value); (0, react.useEffect)(() => { savedCallback.current = callback; }); (0, react.useEffect)(() => { if (initialRender.current) savedCallback.current(prevValue); }, [prevValue]); (0, react.useEffect)(() => { initialRender.current = true; }, []); } /** * Access whether a given flag is enabled or disabled in a given * FeatureFlagContext * * @returns {boolean} */ function useFeatureFlag(flag) { return (0, react.useContext)(FeatureFlagContext).enabled(flag); } /** * Access all feature flag information for the given FeatureFlagContext * * @returns {FeatureFlagScope} */ function useFeatureFlags() { return (0, react.useContext)(FeatureFlagContext); } /** * Compare two objects and determine if they are equal. This is a shallow * comparison since the objects we are comparing are objects with boolean flags * from the flags prop in the `FeatureFlags` component * * @param {object} a * @param {object} b * @returns {boolean} */ function isEqual(a, b) { if (a === b) return true; for (const key of Object.keys(a)) if (a[key] !== b[key]) return false; for (const key of Object.keys(b)) if (b[key] !== a[key]) return false; return true; } //#endregion exports.FeatureFlags = FeatureFlags; exports.useFeatureFlag = useFeatureFlag; exports.useFeatureFlags = useFeatureFlags;