| import '@testing-library/jest-dom/extend-expect'; |
| import '@testing-library/jest-dom/extend-expect'; |
| import '@testing-library/jest-dom/extend-expect'; |
@@ -21,3 +21,3 @@ 'use strict'; | ||
| function useFeature(name) { | ||
| function useFeatures() { | ||
| var features = React.useContext(FeatureFlagsContext); | ||
@@ -29,3 +29,14 @@ | ||
| return Array.isArray(features) ? features.includes(name) : features[name]; | ||
| return features; | ||
| } // Custom Hook API | ||
| function useFeature(name) { | ||
| var features = useFeatures(); | ||
| if (Array.isArray(features)) return features.includes(name); | ||
| if (typeof features[name] === 'boolean') return features[name]; | ||
| return name.split('/').reduce(function (featureGroup, featureName) { | ||
| if (typeof featureGroup === 'boolean') return featureGroup; | ||
| if (featureGroup[featureName] === undefined) return false; | ||
| return featureGroup[featureName]; | ||
| }, features); | ||
| } // High Order Component API | ||
@@ -57,3 +68,4 @@ | ||
| exports.useFeature = useFeature; | ||
| exports.useFeatures = useFeatures; | ||
| exports.withFeature = withFeature; | ||
| //# sourceMappingURL=flagged.cjs.development.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"flagged.cjs.development.js","sources":["../src/index.tsx"],"sourcesContent":["import * as React from 'react';\n\nexport type FeatureFlags =\n | string[]\n | {\n [featureName: string]: boolean;\n }\n | null;\n\nconst FeatureFlagsContext = React.createContext<FeatureFlags>(null);\n\nexport function FlagsProvider({\n features,\n children,\n}: {\n features?: FeatureFlags;\n children: React.ReactChild;\n}) {\n if (!features || features === null || typeof features !== 'object') {\n throw new TypeError('The features prop must be an object or an array.');\n }\n return (\n <FeatureFlagsContext.Provider value={features}>\n {children}\n </FeatureFlagsContext.Provider>\n );\n}\n\n// Custom Hook API\nexport function useFeature(name: string): boolean {\n const features = React.useContext(FeatureFlagsContext);\n if (features === null) {\n throw new Error('You must wrap your components in a FlagsProvider.');\n }\n return Array.isArray(features) ? features.includes(name) : features[name];\n}\n\n// High Order Component API\nexport function withFeature(featureName: string) {\n return (Component: Function) => (props: React.ComponentProps<any>) => {\n const hasFeature = useFeature(featureName);\n if (!hasFeature) return null;\n return <Component {...props} />;\n };\n}\n\n// Render Prop API\nexport function Feature({\n name,\n children,\n render = children,\n}: {\n name: string;\n children?: React.ReactChild | Function;\n render?: React.ReactChild | Function;\n}) {\n const hasFeature = useFeature(name);\n if (typeof render === 'function') return render(hasFeature);\n if (!hasFeature) return null;\n return render;\n}\n"],"names":["FeatureFlagsContext","React","FlagsProvider","features","children","TypeError","Provider","value","useFeature","name","Error","Array","isArray","includes","withFeature","featureName","Component","props","hasFeature","Object","assign","Feature","render"],"mappings":";;;;AASA,IAAMA,mBAAmB;;AAAGC,mBAAA,CAAkC,IAAlC,CAA5B;AAEA,AAAM,SAAUC,aAAV,OAML;MALCC,QAKD,QALCA,QAKD;MAJCC,QAID,QAJCA,QAID;;MACK,CAACD,QAAD,IAAaA,QAAQ,KAAK,IAA1B,IAAkC,OAAOA,QAAP,KAAoB,UAAU;UAC5D,IAAIE,SAAJ,CAAc,kDAAd;;;SAGNJ,mBAAA,CAACD,mBAAmB,CAACM,QAArB,EAA6B;IAACC,KAAK,EAAEJ;GAArC,EACGC,QADH;;;AAOJ,AAAM,SAAUI,UAAV,CAAqBC,IAArB,EAAiC;MAC/BN,QAAQ,GAAGF,gBAAA,CAAiBD,mBAAjB;;MACbG,QAAQ,KAAK,MAAM;UACf,IAAIO,KAAJ,CAAU,mDAAV;;;SAEDC,KAAK,CAACC,OAAN,CAAcT,QAAd,IAA0BA,QAAQ,CAACU,QAAT,CAAkBJ,IAAlB,CAA1B,GAAoDN,QAAQ,CAACM,IAAD;;;AAIrE,AAAM,SAAUK,WAAV,CAAsBC,WAAtB,EAAyC;SACrC,UAAAC,SAAD;WAA0B,UAAAC,KAAD,EAAqC;UAC7DC,UAAU,GAAGV,UAAU,CAACO,WAAD;UACzB,CAACG,YAAY,OAAO,IAAP;aACVjB,mBAAA,CAACe,SAAD,EAAUG,MAAA,CAAAC,MAAA,CAAA,EAAA,EAAKH,KAAL,CAAV;KAHF;;;;AAQT,AAAM,SAAUI,OAAV,QAQL;MAPCZ,IAOD,SAPCA,IAOD;MANCL,QAMD,SANCA,QAMD;2BALCkB,MAKD;MALCA,MAKD,6BALUlB,QAKV;MACOc,UAAU,GAAGV,UAAU,CAACC,IAAD;MACzB,OAAOa,MAAP,KAAkB,YAAY,OAAOA,MAAM,CAACJ,UAAD,CAAb;MAC9B,CAACA,YAAY,OAAO,IAAP;SACVI;;;;;;;;"} | ||
| {"version":3,"file":"flagged.cjs.development.js","sources":["../src/index.tsx"],"sourcesContent":["import * as React from 'react';\n\ntype FeatureGroup = {\n [featureName: string]: boolean | FeatureGroup;\n};\n\nexport type FeatureFlags = string[] | FeatureGroup;\n\nconst FeatureFlagsContext = React.createContext<FeatureFlags | null>(null);\n\nexport function FlagsProvider({\n features,\n children,\n}: {\n features?: FeatureFlags;\n children: React.ReactChild;\n}) {\n if (!features || features === null || typeof features !== 'object') {\n throw new TypeError('The features prop must be an object or an array.');\n }\n return (\n <FeatureFlagsContext.Provider value={features}>\n {children}\n </FeatureFlagsContext.Provider>\n );\n}\n\n// Custom Hook API\nexport function useFeatures(): FeatureFlags {\n const features = React.useContext(FeatureFlagsContext);\n if (features === null) {\n throw new Error('You must wrap your components in a FlagsProvider.');\n }\n return features;\n}\n\n// Custom Hook API\nexport function useFeature(name: string): boolean | FeatureFlags {\n const features = useFeatures();\n if (Array.isArray(features)) return features.includes(name);\n if (typeof features[name] === 'boolean') return features[name];\n return name\n .split('/')\n .reduce<FeatureGroup | boolean>((featureGroup, featureName: string) => {\n if (typeof featureGroup === 'boolean') return featureGroup;\n if (featureGroup[featureName] === undefined) return false;\n return featureGroup[featureName];\n }, features);\n}\n\n// High Order Component API\nexport function withFeature(featureName: string) {\n return (Component: Function) => (props: React.ComponentProps<any>) => {\n const hasFeature = useFeature(featureName);\n if (!hasFeature) return null;\n return <Component {...props} />;\n };\n}\n\n// Render Prop API\nexport function Feature({\n name,\n children,\n render = children,\n}: {\n name: string;\n children?: React.ReactChild | Function;\n render?: React.ReactChild | Function;\n}) {\n const hasFeature = useFeature(name);\n if (typeof render === 'function') return render(hasFeature);\n if (!hasFeature) return null;\n return render;\n}\n"],"names":["FeatureFlagsContext","React","FlagsProvider","features","children","TypeError","Provider","value","useFeatures","Error","useFeature","name","Array","isArray","includes","split","reduce","featureGroup","featureName","undefined","withFeature","Component","props","hasFeature","Feature","render"],"mappings":";;;;AAQA,IAAMA,mBAAmB;;AAAGC,mBAAA,CAAyC,IAAzC,CAA5B;AAEA,SAAgBC;MACdC,gBAAAA;MACAC,gBAAAA;;MAKI,CAACD,QAAD,IAAaA,QAAQ,KAAK,IAA1B,IAAkC,OAAOA,QAAP,KAAoB,QAA1D,EAAoE;UAC5D,IAAIE,SAAJ,CAAc,kDAAd,CAAN;;;SAGAJ,mBAAA,CAACD,mBAAmB,CAACM,QAArB;IAA8BC,KAAK,EAAEJ;GAArC,EACGC,QADH,CADF;;;AAQF,SAAgBI;MACRL,QAAQ,GAAGF,gBAAA,CAAiBD,mBAAjB,CAAjB;;MACIG,QAAQ,KAAK,IAAjB,EAAuB;UACf,IAAIM,KAAJ,CAAU,mDAAV,CAAN;;;SAEKN,QAAP;;;AAIF,SAAgBO,WAAWC;MACnBR,QAAQ,GAAGK,WAAW,EAA5B;MACII,KAAK,CAACC,OAAN,CAAcV,QAAd,CAAJ,EAA6B,OAAOA,QAAQ,CAACW,QAAT,CAAkBH,IAAlB,CAAP;MACzB,OAAOR,QAAQ,CAACQ,IAAD,CAAf,KAA0B,SAA9B,EAAyC,OAAOR,QAAQ,CAACQ,IAAD,CAAf;SAClCA,IAAI,CACRI,KADI,CACE,GADF,EAEJC,MAFI,CAE2B,UAACC,YAAD,EAAeC,WAAf;QAC1B,OAAOD,YAAP,KAAwB,SAA5B,EAAuC,OAAOA,YAAP;QACnCA,YAAY,CAACC,WAAD,CAAZ,KAA8BC,SAAlC,EAA6C,OAAO,KAAP;WACtCF,YAAY,CAACC,WAAD,CAAnB;GALG,EAMFf,QANE,CAAP;;;AAUF,SAAgBiB,YAAYF;SACnB,UAACG,SAAD;WAAyB,UAACC,KAAD;UACxBC,UAAU,GAAGb,UAAU,CAACQ,WAAD,CAA7B;UACI,CAACK,UAAL,EAAiB,OAAO,IAAP;aACVtB,mBAAA,CAACoB,SAAD,oBAAeC,MAAf,CAAP;KAHK;GAAP;;;AAQF,SAAgBE;MACdb,aAAAA;MACAP,iBAAAA;2BACAqB;MAAAA,mCAASrB;MAMHmB,UAAU,GAAGb,UAAU,CAACC,IAAD,CAA7B;MACI,OAAOc,MAAP,KAAkB,UAAtB,EAAkC,OAAOA,MAAM,CAACF,UAAD,CAAb;MAC9B,CAACA,UAAL,EAAiB,OAAO,IAAP;SACVE,MAAP;;;;;;;;;"} |
@@ -1,2 +0,2 @@ | ||
| "use strict";var r=require("react"),e=r.createContext(null);function t(t){var n=r.useContext(e);if(null===n)throw new Error("You must wrap your components in a FlagsProvider.");return Array.isArray(n)?n.includes(t):n[t]}exports.Feature=function(r){var e=r.render,n=void 0===e?r.children:e,u=t(r.name);return"function"==typeof n?n(u):u?n:null},exports.FlagsProvider=function(t){var n=t.features,u=t.children;if(!n||null===n||"object"!=typeof n)throw new TypeError("The features prop must be an object or an array.");return r.createElement(e.Provider,{value:n},u)},exports.useFeature=t,exports.withFeature=function(e){return function(n){return function(u){return t(e)?r.createElement(n,Object.assign({},u)):null}}}; | ||
| "use strict";var e=require("react"),r=e.createContext(null);function t(){var t=e.useContext(r);if(null===t)throw new Error("You must wrap your components in a FlagsProvider.");return t}function n(e){var r=t();return Array.isArray(r)?r.includes(e):"boolean"==typeof r[e]?r[e]:e.split("/").reduce((function(e,r){return"boolean"==typeof e?e:void 0!==e[r]&&e[r]}),r)}exports.Feature=function(e){var r=e.render,t=void 0===r?e.children:r,o=n(e.name);return"function"==typeof t?t(o):o?t:null},exports.FlagsProvider=function(t){var n=t.features,o=t.children;if(!n||null===n||"object"!=typeof n)throw new TypeError("The features prop must be an object or an array.");return e.createElement(r.Provider,{value:n},o)},exports.useFeature=n,exports.useFeatures=t,exports.withFeature=function(r){return function(t){return function(o){return n(r)?e.createElement(t,Object.assign({},o)):null}}}; | ||
| //# sourceMappingURL=flagged.cjs.production.min.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"flagged.cjs.production.min.js","sources":["../src/index.tsx"],"sourcesContent":["import * as React from 'react';\n\nexport type FeatureFlags =\n | string[]\n | {\n [featureName: string]: boolean;\n }\n | null;\n\nconst FeatureFlagsContext = React.createContext<FeatureFlags>(null);\n\nexport function FlagsProvider({\n features,\n children,\n}: {\n features?: FeatureFlags;\n children: React.ReactChild;\n}) {\n if (!features || features === null || typeof features !== 'object') {\n throw new TypeError('The features prop must be an object or an array.');\n }\n return (\n <FeatureFlagsContext.Provider value={features}>\n {children}\n </FeatureFlagsContext.Provider>\n );\n}\n\n// Custom Hook API\nexport function useFeature(name: string): boolean {\n const features = React.useContext(FeatureFlagsContext);\n if (features === null) {\n throw new Error('You must wrap your components in a FlagsProvider.');\n }\n return Array.isArray(features) ? features.includes(name) : features[name];\n}\n\n// High Order Component API\nexport function withFeature(featureName: string) {\n return (Component: Function) => (props: React.ComponentProps<any>) => {\n const hasFeature = useFeature(featureName);\n if (!hasFeature) return null;\n return <Component {...props} />;\n };\n}\n\n// Render Prop API\nexport function Feature({\n name,\n children,\n render = children,\n}: {\n name: string;\n children?: React.ReactChild | Function;\n render?: React.ReactChild | Function;\n}) {\n const hasFeature = useFeature(name);\n if (typeof render === 'function') return render(hasFeature);\n if (!hasFeature) return null;\n return render;\n}\n"],"names":["FeatureFlagsContext","React","useFeature","name","features","Error","Array","isArray","includes","render","children","hasFeature","TypeError","Provider","value","featureName","Component","props","Object","assign"],"mappings":"oCASMA,EAAsBC,gBAAkC,MAoBxD,SAAUC,EAAWC,OACnBC,EAAWH,aAAiBD,MACjB,OAAbI,QACI,IAAIC,MAAM,4DAEXC,MAAMC,QAAQH,GAAYA,EAASI,SAASL,GAAQC,EAASD,mBAahE,oBAGJM,OAAAA,eADAC,WAOMC,EAAaT,IARnBC,YASsB,mBAAXM,EAA8BA,EAAOE,GAC3CA,EACEF,EADiB,4BA/CpB,gBACJL,IAAAA,SACAM,IAAAA,aAKKN,GAAyB,OAAbA,GAAyC,iBAAbA,QACrC,IAAIQ,UAAU,2DAGpBX,gBAACD,EAAoBa,SAAQ,CAACC,MAAOV,GAClCM,6CAeD,SAAsBK,UAClB,SAAAC,UAAyB,SAAAC,UACZf,EAAWa,GAEvBd,gBAACe,EAASE,OAAAC,OAAA,GAAKF,IADE"} | ||
| {"version":3,"file":"flagged.cjs.production.min.js","sources":["../src/index.tsx"],"sourcesContent":["import * as React from 'react';\n\ntype FeatureGroup = {\n [featureName: string]: boolean | FeatureGroup;\n};\n\nexport type FeatureFlags = string[] | FeatureGroup;\n\nconst FeatureFlagsContext = React.createContext<FeatureFlags | null>(null);\n\nexport function FlagsProvider({\n features,\n children,\n}: {\n features?: FeatureFlags;\n children: React.ReactChild;\n}) {\n if (!features || features === null || typeof features !== 'object') {\n throw new TypeError('The features prop must be an object or an array.');\n }\n return (\n <FeatureFlagsContext.Provider value={features}>\n {children}\n </FeatureFlagsContext.Provider>\n );\n}\n\n// Custom Hook API\nexport function useFeatures(): FeatureFlags {\n const features = React.useContext(FeatureFlagsContext);\n if (features === null) {\n throw new Error('You must wrap your components in a FlagsProvider.');\n }\n return features;\n}\n\n// Custom Hook API\nexport function useFeature(name: string): boolean | FeatureFlags {\n const features = useFeatures();\n if (Array.isArray(features)) return features.includes(name);\n if (typeof features[name] === 'boolean') return features[name];\n return name\n .split('/')\n .reduce<FeatureGroup | boolean>((featureGroup, featureName: string) => {\n if (typeof featureGroup === 'boolean') return featureGroup;\n if (featureGroup[featureName] === undefined) return false;\n return featureGroup[featureName];\n }, features);\n}\n\n// High Order Component API\nexport function withFeature(featureName: string) {\n return (Component: Function) => (props: React.ComponentProps<any>) => {\n const hasFeature = useFeature(featureName);\n if (!hasFeature) return null;\n return <Component {...props} />;\n };\n}\n\n// Render Prop API\nexport function Feature({\n name,\n children,\n render = children,\n}: {\n name: string;\n children?: React.ReactChild | Function;\n render?: React.ReactChild | Function;\n}) {\n const hasFeature = useFeature(name);\n if (typeof render === 'function') return render(hasFeature);\n if (!hasFeature) return null;\n return render;\n}\n"],"names":["FeatureFlagsContext","React","useFeatures","features","Error","useFeature","name","Array","isArray","includes","split","reduce","featureGroup","featureName","undefined","render","children","hasFeature","TypeError","Provider","value","Component","props"],"mappings":"oCAQMA,EAAsBC,gBAAyC,MAoBrE,SAAgBC,QACRC,EAAWF,aAAiBD,MACjB,OAAbG,QACI,IAAIC,MAAM,4DAEXD,WAIOE,EAAWC,OACnBH,EAAWD,WACbK,MAAMC,QAAQL,GAAkBA,EAASM,SAASH,GACxB,kBAAnBH,EAASG,GAA4BH,EAASG,GAClDA,EACJI,MAAM,KACNC,QAA+B,SAACC,EAAcC,SACjB,kBAAjBD,EAAmCA,OACZE,IAA9BF,EAAaC,IACVD,EAAaC,KACnBV,uCAgBLY,OAAAA,eADAC,WAOMC,EAAaZ,IARnBC,YASsB,mBAAXS,EAA8BA,EAAOE,GAC3CA,EACEF,EADiB,4CA5DxBZ,IAAAA,SACAa,IAAAA,aAKKb,GAAyB,OAAbA,GAAyC,iBAAbA,QACrC,IAAIe,UAAU,2DAGpBjB,gBAACD,EAAoBmB,UAASC,MAAOjB,GAClCa,4EA6BqBH,UACnB,SAACQ,UAAwB,SAACC,UACZjB,EAAWQ,GAEvBZ,gBAACoB,mBAAcC,IADE"} |
+14
-3
@@ -19,3 +19,3 @@ import { createElement, useContext, createContext } from 'react'; | ||
| function useFeature(name) { | ||
| function useFeatures() { | ||
| var features = useContext(FeatureFlagsContext); | ||
@@ -27,3 +27,14 @@ | ||
| return Array.isArray(features) ? features.includes(name) : features[name]; | ||
| return features; | ||
| } // Custom Hook API | ||
| function useFeature(name) { | ||
| var features = useFeatures(); | ||
| if (Array.isArray(features)) return features.includes(name); | ||
| if (typeof features[name] === 'boolean') return features[name]; | ||
| return name.split('/').reduce(function (featureGroup, featureName) { | ||
| if (typeof featureGroup === 'boolean') return featureGroup; | ||
| if (featureGroup[featureName] === undefined) return false; | ||
| return featureGroup[featureName]; | ||
| }, features); | ||
| } // High Order Component API | ||
@@ -52,3 +63,3 @@ | ||
| export { Feature, FlagsProvider, useFeature, withFeature }; | ||
| export { Feature, FlagsProvider, useFeature, useFeatures, withFeature }; | ||
| //# sourceMappingURL=flagged.esm.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"flagged.esm.js","sources":["../src/index.tsx"],"sourcesContent":["import * as React from 'react';\n\nexport type FeatureFlags =\n | string[]\n | {\n [featureName: string]: boolean;\n }\n | null;\n\nconst FeatureFlagsContext = React.createContext<FeatureFlags>(null);\n\nexport function FlagsProvider({\n features,\n children,\n}: {\n features?: FeatureFlags;\n children: React.ReactChild;\n}) {\n if (!features || features === null || typeof features !== 'object') {\n throw new TypeError('The features prop must be an object or an array.');\n }\n return (\n <FeatureFlagsContext.Provider value={features}>\n {children}\n </FeatureFlagsContext.Provider>\n );\n}\n\n// Custom Hook API\nexport function useFeature(name: string): boolean {\n const features = React.useContext(FeatureFlagsContext);\n if (features === null) {\n throw new Error('You must wrap your components in a FlagsProvider.');\n }\n return Array.isArray(features) ? features.includes(name) : features[name];\n}\n\n// High Order Component API\nexport function withFeature(featureName: string) {\n return (Component: Function) => (props: React.ComponentProps<any>) => {\n const hasFeature = useFeature(featureName);\n if (!hasFeature) return null;\n return <Component {...props} />;\n };\n}\n\n// Render Prop API\nexport function Feature({\n name,\n children,\n render = children,\n}: {\n name: string;\n children?: React.ReactChild | Function;\n render?: React.ReactChild | Function;\n}) {\n const hasFeature = useFeature(name);\n if (typeof render === 'function') return render(hasFeature);\n if (!hasFeature) return null;\n return render;\n}\n"],"names":["FeatureFlagsContext","React","FlagsProvider","features","children","TypeError","Provider","value","useFeature","name","Error","Array","isArray","includes","withFeature","featureName","Component","props","hasFeature","Object","assign","Feature","render"],"mappings":";;AASA,IAAMA,mBAAmB;;AAAGC,aAAA,CAAkC,IAAlC,CAA5B;AAEA,AAAM,SAAUC,aAAV,OAML;MALCC,QAKD,QALCA,QAKD;MAJCC,QAID,QAJCA,QAID;;MACK,CAACD,QAAD,IAAaA,QAAQ,KAAK,IAA1B,IAAkC,OAAOA,QAAP,KAAoB,UAAU;UAC5D,IAAIE,SAAJ,CAAc,kDAAd;;;SAGNJ,aAAA,CAACD,mBAAmB,CAACM,QAArB,EAA6B;IAACC,KAAK,EAAEJ;GAArC,EACGC,QADH;;;AAOJ,AAAM,SAAUI,UAAV,CAAqBC,IAArB,EAAiC;MAC/BN,QAAQ,GAAGF,UAAA,CAAiBD,mBAAjB;;MACbG,QAAQ,KAAK,MAAM;UACf,IAAIO,KAAJ,CAAU,mDAAV;;;SAEDC,KAAK,CAACC,OAAN,CAAcT,QAAd,IAA0BA,QAAQ,CAACU,QAAT,CAAkBJ,IAAlB,CAA1B,GAAoDN,QAAQ,CAACM,IAAD;;;AAIrE,AAAM,SAAUK,WAAV,CAAsBC,WAAtB,EAAyC;SACrC,UAAAC,SAAD;WAA0B,UAAAC,KAAD,EAAqC;UAC7DC,UAAU,GAAGV,UAAU,CAACO,WAAD;UACzB,CAACG,YAAY,OAAO,IAAP;aACVjB,aAAA,CAACe,SAAD,EAAUG,MAAA,CAAAC,MAAA,CAAA,EAAA,EAAKH,KAAL,CAAV;KAHF;;;;AAQT,AAAM,SAAUI,OAAV,QAQL;MAPCZ,IAOD,SAPCA,IAOD;MANCL,QAMD,SANCA,QAMD;2BALCkB,MAKD;MALCA,MAKD,6BALUlB,QAKV;MACOc,UAAU,GAAGV,UAAU,CAACC,IAAD;MACzB,OAAOa,MAAP,KAAkB,YAAY,OAAOA,MAAM,CAACJ,UAAD,CAAb;MAC9B,CAACA,YAAY,OAAO,IAAP;SACVI;;;;;"} | ||
| {"version":3,"file":"flagged.esm.js","sources":["../src/index.tsx"],"sourcesContent":["import * as React from 'react';\n\ntype FeatureGroup = {\n [featureName: string]: boolean | FeatureGroup;\n};\n\nexport type FeatureFlags = string[] | FeatureGroup;\n\nconst FeatureFlagsContext = React.createContext<FeatureFlags | null>(null);\n\nexport function FlagsProvider({\n features,\n children,\n}: {\n features?: FeatureFlags;\n children: React.ReactChild;\n}) {\n if (!features || features === null || typeof features !== 'object') {\n throw new TypeError('The features prop must be an object or an array.');\n }\n return (\n <FeatureFlagsContext.Provider value={features}>\n {children}\n </FeatureFlagsContext.Provider>\n );\n}\n\n// Custom Hook API\nexport function useFeatures(): FeatureFlags {\n const features = React.useContext(FeatureFlagsContext);\n if (features === null) {\n throw new Error('You must wrap your components in a FlagsProvider.');\n }\n return features;\n}\n\n// Custom Hook API\nexport function useFeature(name: string): boolean | FeatureFlags {\n const features = useFeatures();\n if (Array.isArray(features)) return features.includes(name);\n if (typeof features[name] === 'boolean') return features[name];\n return name\n .split('/')\n .reduce<FeatureGroup | boolean>((featureGroup, featureName: string) => {\n if (typeof featureGroup === 'boolean') return featureGroup;\n if (featureGroup[featureName] === undefined) return false;\n return featureGroup[featureName];\n }, features);\n}\n\n// High Order Component API\nexport function withFeature(featureName: string) {\n return (Component: Function) => (props: React.ComponentProps<any>) => {\n const hasFeature = useFeature(featureName);\n if (!hasFeature) return null;\n return <Component {...props} />;\n };\n}\n\n// Render Prop API\nexport function Feature({\n name,\n children,\n render = children,\n}: {\n name: string;\n children?: React.ReactChild | Function;\n render?: React.ReactChild | Function;\n}) {\n const hasFeature = useFeature(name);\n if (typeof render === 'function') return render(hasFeature);\n if (!hasFeature) return null;\n return render;\n}\n"],"names":["FeatureFlagsContext","React","FlagsProvider","features","children","TypeError","Provider","value","useFeatures","Error","useFeature","name","Array","isArray","includes","split","reduce","featureGroup","featureName","undefined","withFeature","Component","props","hasFeature","Feature","render"],"mappings":";;AAQA,IAAMA,mBAAmB;;AAAGC,aAAA,CAAyC,IAAzC,CAA5B;AAEA,SAAgBC;MACdC,gBAAAA;MACAC,gBAAAA;;MAKI,CAACD,QAAD,IAAaA,QAAQ,KAAK,IAA1B,IAAkC,OAAOA,QAAP,KAAoB,QAA1D,EAAoE;UAC5D,IAAIE,SAAJ,CAAc,kDAAd,CAAN;;;SAGAJ,aAAA,CAACD,mBAAmB,CAACM,QAArB;IAA8BC,KAAK,EAAEJ;GAArC,EACGC,QADH,CADF;;;AAQF,SAAgBI;MACRL,QAAQ,GAAGF,UAAA,CAAiBD,mBAAjB,CAAjB;;MACIG,QAAQ,KAAK,IAAjB,EAAuB;UACf,IAAIM,KAAJ,CAAU,mDAAV,CAAN;;;SAEKN,QAAP;;;AAIF,SAAgBO,WAAWC;MACnBR,QAAQ,GAAGK,WAAW,EAA5B;MACII,KAAK,CAACC,OAAN,CAAcV,QAAd,CAAJ,EAA6B,OAAOA,QAAQ,CAACW,QAAT,CAAkBH,IAAlB,CAAP;MACzB,OAAOR,QAAQ,CAACQ,IAAD,CAAf,KAA0B,SAA9B,EAAyC,OAAOR,QAAQ,CAACQ,IAAD,CAAf;SAClCA,IAAI,CACRI,KADI,CACE,GADF,EAEJC,MAFI,CAE2B,UAACC,YAAD,EAAeC,WAAf;QAC1B,OAAOD,YAAP,KAAwB,SAA5B,EAAuC,OAAOA,YAAP;QACnCA,YAAY,CAACC,WAAD,CAAZ,KAA8BC,SAAlC,EAA6C,OAAO,KAAP;WACtCF,YAAY,CAACC,WAAD,CAAnB;GALG,EAMFf,QANE,CAAP;;;AAUF,SAAgBiB,YAAYF;SACnB,UAACG,SAAD;WAAyB,UAACC,KAAD;UACxBC,UAAU,GAAGb,UAAU,CAACQ,WAAD,CAA7B;UACI,CAACK,UAAL,EAAiB,OAAO,IAAP;aACVtB,aAAA,CAACoB,SAAD,oBAAeC,MAAf,CAAP;KAHK;GAAP;;;AAQF,SAAgBE;MACdb,aAAAA;MACAP,iBAAAA;2BACAqB;MAAAA,mCAASrB;MAMHmB,UAAU,GAAGb,UAAU,CAACC,IAAD,CAA7B;MACI,OAAOc,MAAP,KAAkB,UAAtB,EAAkC,OAAOA,MAAM,CAACF,UAAD,CAAb;MAC9B,CAACA,UAAL,EAAiB,OAAO,IAAP;SACVE,MAAP;;;;;"} |
+8
-5
@@ -1,5 +0,6 @@ | ||
| import * as React from "react"; | ||
| export declare type FeatureFlags = string[] | { | ||
| [featureName: string]: boolean; | ||
| } | null; | ||
| import * as React from 'react'; | ||
| declare type FeatureGroup = { | ||
| [featureName: string]: boolean | FeatureGroup; | ||
| }; | ||
| export declare type FeatureFlags = string[] | FeatureGroup; | ||
| export declare function FlagsProvider({ features, children, }: { | ||
@@ -9,3 +10,4 @@ features?: FeatureFlags; | ||
| }): JSX.Element; | ||
| export declare function useFeature(name: string): boolean; | ||
| export declare function useFeatures(): FeatureFlags; | ||
| export declare function useFeature(name: string): boolean | FeatureFlags; | ||
| export declare function withFeature(featureName: string): (Component: Function) => (props: any) => JSX.Element | null; | ||
@@ -17,1 +19,2 @@ export declare function Feature({ name, children, render, }: { | ||
| }): any; | ||
| export {}; |
+3
-3
| { | ||
| "name": "flagged", | ||
| "description": "Feature flags for React made easy with hooks, HOC and Render Props", | ||
| "version": "1.0.1", | ||
| "version": "1.1.0", | ||
| "license": "MIT", | ||
@@ -36,3 +36,3 @@ "repository": "https://github.com/sergiodxa/flagged.git", | ||
| "scripts": { | ||
| "prepare": "tsdx build", | ||
| "prepublishOnly": "tsdx build", | ||
| "start": "tsdx watch", | ||
@@ -66,3 +66,3 @@ "build": "tsdx build", | ||
| "react-dom": "^16.11.0", | ||
| "tsdx": "^0.10.5", | ||
| "tsdx": "^0.11.0", | ||
| "tslib": "^1.10.0", | ||
@@ -69,0 +69,0 @@ "typescript": "^3.6.4" |
+58
-0
@@ -22,2 +22,3 @@ # Flagged | ||
| - Zero Dependencies | ||
| - Nested Flags | ||
@@ -52,2 +53,40 @@ ## How to Use It | ||
| ### Features Valid Values | ||
| The features prop you pass to `FlagsProvider` could be an array of strings or an object, if you decide to use an object you could also pass nested objects to group feature flags together. | ||
| **Using an Array** | ||
| ```tsx | ||
| ReactDOM.render( | ||
| <FlagsProvider features={['v2', 'moderate']}> | ||
| <App /> | ||
| </FlagsProvider>, | ||
| document.querySelector('root') | ||
| ); | ||
| ``` | ||
| **Using an Object** | ||
| ```tsx | ||
| ReactDOM.render( | ||
| <FlagsProvider features={{ v2: true, moderate: false }}> | ||
| <App /> | ||
| </FlagsProvider>, | ||
| document.querySelector('root') | ||
| ); | ||
| ``` | ||
| **Using Nested Objects** | ||
| ```tsx | ||
| ReactDOM.render( | ||
| <FlagsProvider | ||
| features={{ v2: true, content: { moderate: true, admin: false } }} | ||
| > | ||
| <App /> | ||
| </FlagsProvider>, | ||
| document.querySelector('root') | ||
| ); | ||
| ``` | ||
| If you use nested objects you will need to either use the `useFeatures` hook or pass a string separated by `/`, e.g. `content/moderate` to read nested flags, if you don't pass the whole path you will get an object so `content` will return `{ moderate: false }` when reading it. | ||
| ### `useFeature` Custom Hook | ||
@@ -165,1 +204,20 @@ | ||
| ``` | ||
| ### `useFeatures` Custom Hook | ||
| The `useFeatures` custom hook is the base for the `useFeature` custom hook, it gives you the entire feature flags object or array you sent to `FlagsProvider` so you could use it however you want. | ||
| ```tsx | ||
| import * as React from 'react'; | ||
| import { useFeature } from 'flagged'; | ||
| function Header() { | ||
| const features = useFeatures(); | ||
| return ( | ||
| <header>{features.v2 ? <h1>My App v2</h1> : <h1>My App v1</h1>}</header> | ||
| ); | ||
| } | ||
| export default Header; | ||
| ``` |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
25361
25.82%14
27.27%141
24.78%221
35.58%