@casl/react
Version:
React component for CASL which makes it easy to add permissions in any React application
1 lines • 5.47 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","sources":["../../src/Can.ts","../../src/factory.ts","../../src/hooks/useAbility.ts"],"sourcesContent":["import { PureComponent, ReactNode } from 'react';\nimport {\n Unsubscribe,\n AbilityTuple,\n SubjectType,\n AnyAbility,\n Generics,\n Abilities,\n IfString,\n} from '@casl/ability';\n\nconst noop = () => {};\n\ntype AbilityCanProps<\n T extends Abilities,\n Else = IfString<T, { do: T } | { I: T }>\n> = T extends AbilityTuple\n ? { do: T[0], on: T[1], field?: string } |\n { I: T[0], a: Extract<T[1], SubjectType>, field?: string } |\n { I: T[0], an: Extract<T[1], SubjectType>, field?: string } |\n { I: T[0], this: Exclude<T[1], SubjectType>, field?: string }\n : Else;\n\ninterface ExtraProps {\n not?: boolean\n passThrough?: boolean\n}\n\ninterface CanExtraProps<T extends AnyAbility> extends ExtraProps {\n ability: T\n children: ReactNode | ((isAllowed: boolean, ability: T) => ReactNode)\n}\n\ninterface BoundCanExtraProps<T extends AnyAbility> extends ExtraProps {\n ability?: T\n children: ReactNode | ((isAllowed: boolean, ability: T) => ReactNode)\n}\n\nexport type CanProps<T extends AnyAbility> =\n AbilityCanProps<Generics<T>['abilities']> & CanExtraProps<T>;\nexport type BoundCanProps<T extends AnyAbility> =\n AbilityCanProps<Generics<T>['abilities']> & BoundCanExtraProps<T>;\n\nexport class Can<T extends AnyAbility> extends PureComponent<CanProps<T>, { t: boolean }> {\n private _isAllowed = false;\n private _ability: T | null = null;\n private _unsubscribeFromAbility: Unsubscribe = noop;\n state = { t: true }\n\n componentWillUnmount() {\n this._unsubscribeFromAbility();\n }\n\n private _connectToAbility(ability?: T) {\n if (ability === this._ability) {\n return;\n }\n\n this._unsubscribeFromAbility();\n this._ability = null;\n\n if (ability) {\n this._ability = ability;\n this._unsubscribeFromAbility = ability.on('updated', () => this.setState({ t: !this.state.t }));\n }\n }\n\n get allowed() {\n return this._isAllowed;\n }\n\n private _canRender(): boolean {\n const props: any = this.props;\n const subject = props.of || props.a || props.an || props.this || props.on;\n const can = props.not ? 'cannot' : 'can';\n\n return props.ability[can](props.I || props.do, subject, props.field);\n }\n\n render() {\n this._connectToAbility(this.props.ability);\n this._isAllowed = this._canRender();\n return this.props.passThrough || this._isAllowed ? this._renderChildren() : null;\n }\n\n private _renderChildren() {\n const { children, ability } = this.props;\n const elements = typeof children === 'function'\n ? children(this._isAllowed, ability as any)\n : children;\n\n return elements as ReactNode;\n }\n}\n","import { AnyAbility } from '@casl/ability';\nimport { Consumer, FunctionComponent, createElement } from 'react';\nimport { BoundCanProps, Can } from './Can';\n\nexport function createContextualCan<T extends AnyAbility>(\n Getter: Consumer<T>\n): FunctionComponent<BoundCanProps<T>> {\n return (props: BoundCanProps<T>) => createElement(Getter, {\n children: (ability: T) => \n createElement(Can, { ...props, ability: props.ability || ability } as any),\n });\n}\n","import React from 'react';\nimport { AnyAbility } from '@casl/ability';\n\nexport function useAbility<T extends AnyAbility>(context: React.Context<T>): T {\n const ability = React.useContext<T>(context);\n const [rules, setRules] = React.useState<T['rules']>();\n\n React.useEffect(() => ability.on('updated', (event) => {\n if (event.rules !== rules) {\n setRules(event.rules);\n }\n }), []);\n\n return ability;\n}\n"],"names":["noop","Can","PureComponent","constructor","args","super","this","_isAllowed","_ability","_unsubscribeFromAbility","state","t","componentWillUnmount","_connectToAbility","ability","on","setState","allowed","_canRender","props","subject","of","a","an","can","not","I","do","field","render","passThrough","_renderChildren","children","elements","createContextualCan","Getter","createElement","Object","assign","useAbility","context","React","useContext","rules","setRules","useState","useEffect","event"],"mappings":"4DAWA,MAAMA,EAAOA,OAgCN,MAAMC,UAAkCC,EAA2CC,WAAAA,IAAAC,GAAAC,SAAAD,GAAAE,KAChFC,EAAa,MAAKD,KAClBE,EAAqB,KAAIF,KACzBG,EAAuCT,EAAIM,KACnDI,MAAQ,CAAEC,EAAG,KAAM,CAEnBC,oBAAAA,GACEN,KAAKG,GACP,CAEQI,CAAAA,CAAkBC,GACxB,GAAIA,IAAYR,KAAKE,EACnB,OAGFF,KAAKG,IACLH,KAAKE,EAAW,KAEhB,GAAIM,EAAS,CACXR,KAAKE,EAAWM,EAChBR,KAAKG,EAA0BK,EAAQC,GAAG,WAAW,IAAMT,KAAKU,SAAS,CAAEL,GAAIL,KAAKI,MAAMC,KAC5F,CACF,CAEA,WAAIM,GACF,OAAOX,KAAKC,CACd,CAEQW,CAAAA,GACN,MAAMC,EAAab,KAAKa,MACxB,MAAMC,EAAUD,EAAME,IAAMF,EAAMG,GAAKH,EAAMI,IAAMJ,EAAMb,MAAQa,EAAMJ,GACvE,MAAMS,EAAML,EAAMM,IAAM,SAAW,MAEnC,OAAON,EAAML,QAAQU,GAAKL,EAAMO,GAAKP,EAAMQ,GAAIP,EAASD,EAAMS,MAChE,CAEAC,MAAAA,GACEvB,KAAKO,EAAkBP,KAAKa,MAAML,SAClCR,KAAKC,EAAaD,KAAKY,IACvB,OAAOZ,KAAKa,MAAMW,aAAexB,KAAKC,EAAaD,KAAKyB,IAAoB,IAC9E,CAEQA,CAAAA,GACN,MAAMC,SAAEA,EAAQlB,QAAEA,GAAYR,KAAKa,MACnC,MAAMc,SAAkBD,IAAa,WACjCA,EAAS1B,KAAKC,EAAYO,GAC1BkB,EAEJ,OAAOC,CACT,ECxFK,SAASC,EACdC,GAEA,OAAQhB,GAA4BiB,EAAcD,EAAQ,CACxDH,SAAWlB,GACTsB,EAAcnC,EAAGoC,OAAAC,OAAA,CAAA,EAAOnB,EAAK,CAAEL,QAASK,EAAML,SAAWA,MAE/D,CCRO,SAASyB,WAAiCC,GAC/C,MAAM1B,EAAU2B,EAAMC,WAAcF,GACpC,MAAOG,EAAOC,GAAYH,EAAMI,WAEhCJ,EAAMK,WAAU,IAAMhC,EAAQC,GAAG,WAAYgC,IAC3C,GAAIA,EAAMJ,QAAUA,EAClBC,EAASG,EAAMJ,MACjB,KACE,IAEJ,OAAO7B,CACT"}