@casl/react
Version:
React component for CASL which makes it easy to add permissions in any React application
1 lines • 4.12 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","names":["React"],"sources":["../../src/hooks/useAbility.ts","../../src/Can.ts"],"sourcesContent":["import { createElement, useContext, useCallback, useSyncExternalStore, createContext } from 'react';\nimport type { AnyAbility } from '@casl/ability';\n\nconst AbilityContext = createContext<AnyAbility | null>(null);\nconst EMPTY_RULES: any[] = [];\nconst noop = () => {};\n\nexport function AbilityProvider<T extends AnyAbility>({\n children,\n value,\n}: {\n children: React.ReactNode;\n value: T;\n}) {\n return createElement(AbilityContext.Provider, { value }, children);\n}\n\nexport function useAbility<T extends AnyAbility>(): T {\n const ability = useContext(AbilityContext);\n const subscribe = useCallback(\n (callback: () => void) => ability?.on('updated', callback) || noop,\n [ability],\n );\n const getSnapshot = useCallback(() => ability?.rules || EMPTY_RULES, [ability]);\n\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n if (!ability) {\n throw new Error('AbilityContext is not provided. Please make sure to wrap your component tree with <AbilityProvider>.');\n }\n\n return ability as T;\n}\n","import React, { ReactNode } from 'react';\nimport {\n AbilityTuple,\n SubjectType,\n AnyAbility,\n Generics,\n Abilities,\n IfString,\n} from '@casl/ability';\nimport { useAbility } from './hooks/useAbility';\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 children: ReactNode | ((exposes: {\n isAllowed: boolean;\n ability: T;\n reason: string | undefined;\n }) => ReactNode)\n}\n\nexport type CanProps<T extends AnyAbility> =\n AbilityCanProps<Generics<T>['abilities']> & CanExtraProps<T>;\n\nfunction CanComponent<T extends AnyAbility>(props: CanProps<T>) {\n const ability = useAbility();\n const propsWithAliases = props as CanProps<T> & {\n of?: unknown\n a?: unknown\n an?: unknown\n this?: unknown\n on?: unknown\n I?: unknown\n do?: unknown\n field?: string\n };\n const subject =\n propsWithAliases.of ||\n propsWithAliases.a ||\n propsWithAliases.an ||\n propsWithAliases.this ||\n propsWithAliases.on;\n const action = propsWithAliases.I || propsWithAliases.do;\n const field = propsWithAliases.field;\n const rule = React.useMemo(() => {\n return ability.relevantRuleFor(action, subject, field);\n }, [ability, ability.rules, action, subject, field]);\n let isAllowed = !!rule && !rule.inverted;\n if (props.not) isAllowed = !isAllowed;\n\n const elements = typeof props.children === 'function'\n ? props.children({ isAllowed, ability: ability as T, reason: rule?.reason })\n : props.children;\n\n return props.passThrough || isAllowed ? elements as ReactNode : null;\n}\n\nexport const Can = React.memo(CanComponent) as typeof CanComponent;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAGA,MAAM,KAAA,GAAA,EAAA,eAAkD,OAClD,IAAqB,IACrB,IAAA;;AAYN,SAAgB;IACd,MAAM,KAAA,GAAA,EAAA,YAAqB,IACrB,KAAA,GAAA,EAAA,aACH,KAAyB,GAAS,GAAG,WAAW,MAAa,GAC9D,EAAC,MAEG,KAAA;IAAA,EAAA,aAAA,MAAgC,GAAS,SAAS,GAAa,EAAC;IAItE,KAFA,GAAA,EAAA,sBAAqB,GAAW,GAAa,KAExC,GACH,MAAM,IAAI,MAAM;IAGlB,OAAO;;;ACuCT,MAAa,IAAMA,EAAAA,QAAM,KAjCzB,SAA4C;IAC1C,MAAM,IAAU,KACV,IAAmB,GAUnB,IACJ,EAAiB,MACjB,EAAiB,KACjB,EAAiB,MACjB,EAAiB,QACjB,EAAiB,IACb,IAAS,EAAiB,KAAK,EAAiB,IAChD,IAAQ,EAAiB,OACzB,IAAOA,EAAAA,QAAM,QAAA,MACV,EAAQ,gBAAgB,GAAQ,GAAS,IAC/C,EAAC,GAAS,EAAQ,OAAO,GAAQ,GAAS;IAC7C,IAAI,MAAc,MAAS,EAAK;IAC5B,EAAM,QAAK,KAAa;IAE5B,MAAM,IAAqC,qBAAnB,EAAM,WAC1B,EAAM,SAAS;QAAE;QAAoB;QAAc,QAAQ,GAAM;SACjE,EAAM;IAEV,OAAO,EAAM,eAAe,IAAY,IAAwB;;;0BD5DlE,UAAsD,UACpD,GAAA,OACA;IAKA,QAAA,GAAA,EAAA,eAAqB,EAAe,UAAU;QAAE;OAAS"}