@casl/react 0.7.0 → 0.8.1
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.
- package/CHANGELOG.md +47 -3
- package/README.md +16 -7
- package/dist/es5m/index.js +228 -0
- package/dist/es6/index.js +32 -21
- package/dist/umd/index.js +1 -1
- package/index.d.ts +7 -2
- package/package.json +4 -5
- package/index.js +0 -262
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,50 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
# [@casl/react-v0.8.1](https://github.com/stalniy/casl/compare/@casl/react@0.8.0...@casl/react@0.8.1) (2018-11-08)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **react:** moves this.connectToAbility to the setState callback ([#129](https://github.com/stalniy/casl/issues/129)) ([9d0c839](https://github.com/stalniy/casl/commit/9d0c839)), closes [#128](https://github.com/stalniy/casl/issues/128)
|
|
11
|
+
|
|
12
|
+
# [@casl/react-v0.8.0](https://github.com/stalniy/casl/compare/@casl/react@0.7.2...@casl/react@0.8.0) (2018-09-03)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **README:** changes links to [@casl](https://github.com/casl)/ability to point to npm package instead to git root [skip ci] ([a74086b](https://github.com/stalniy/casl/commit/a74086b)), closes [#102](https://github.com/stalniy/casl/issues/102)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* **react:can:** adds `an` alias to `on` prop ([748ea64](https://github.com/stalniy/casl/commit/748ea64))
|
|
23
|
+
* **react:can:** adds `passThrough` option ([045318c](https://github.com/stalniy/casl/commit/045318c)), closes [#105](https://github.com/stalniy/casl/issues/105)
|
|
24
|
+
* **react:can:** adds support for multiple <Can> children ([c022b32](https://github.com/stalniy/casl/commit/c022b32))
|
|
25
|
+
* **react:can:** updates typescript declarations ([70953ed](https://github.com/stalniy/casl/commit/70953ed))
|
|
26
|
+
* **react:can:** updates typescript declarations ([213dcde](https://github.com/stalniy/casl/commit/213dcde))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Performance Improvements
|
|
30
|
+
|
|
31
|
+
* **react:can:** moves prop type checks undef `if`, so they can be removed for production builds ([4bebf0b](https://github.com/stalniy/casl/commit/4bebf0b))
|
|
32
|
+
|
|
33
|
+
# [@casl/react-v0.7.2](https://github.com/stalniy/casl/compare/@casl/react@0.7.1...@casl/react@0.7.2) (2018-07-29)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Bug Fixes
|
|
37
|
+
|
|
38
|
+
* **react:** makes `not` prop to be optional ([8f841bf](https://github.com/stalniy/casl/commit/8f841bf)), closes [#95](https://github.com/stalniy/casl/issues/95)
|
|
39
|
+
|
|
40
|
+
<a name="@casl/react-v0.7.1"></a>
|
|
41
|
+
# [@casl/react-v0.7.1](https://github.com/stalniy/casl/compare/@casl/react@0.7.0...@casl/react@0.7.1) (2018-07-02)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
### Bug Fixes
|
|
45
|
+
|
|
46
|
+
* **package:** changes location of ES5M modules ([2b1ad4e](https://github.com/stalniy/casl/commit/2b1ad4e)), closes [#89](https://github.com/stalniy/casl/issues/89)
|
|
47
|
+
|
|
1
48
|
<a name="@casl/react-v0.7.0"></a>
|
|
2
49
|
# [@casl/react-v0.7.0](https://github.com/stalniy/casl/compare/@casl/react@0.6.0...@casl/react@0.7.0) (2018-06-15)
|
|
3
50
|
|
|
@@ -12,9 +59,6 @@
|
|
|
12
59
|
|
|
13
60
|
* **vue:** adds can component ([42ee540](https://github.com/stalniy/casl/commit/42ee540)), closes [#63](https://github.com/stalniy/casl/issues/63)
|
|
14
61
|
|
|
15
|
-
# Change Log
|
|
16
|
-
|
|
17
|
-
|
|
18
62
|
|
|
19
63
|
<a name="@casl/react-v0.6.0"></a>
|
|
20
64
|
# [@casl/react-v0.6.0](https://github.com/stalniy/casl/compare/@casl/react@0.5.0...@casl/react@0.6.0) (2018-05-28)
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CASL React [](https://badge.fury.io/js/%40casl%2Freact) [](https://www.npmjs.com/package/%40casl%2Freact) [](https://stalniy.github.io/casl/) [](https://gitter.im/stalniy-casl/casl?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
2
2
|
|
|
3
|
-
This package allows to integrate [@casl/ability]
|
|
3
|
+
This package allows to integrate [@casl/ability][casl-ability] into [React][react] application. So, you can show or hide UI elements based on user ability to see them.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -21,7 +21,7 @@ This component accepts children and 4 properties (see [Property names and aliase
|
|
|
21
21
|
|
|
22
22
|
```jsx
|
|
23
23
|
<Can I="create" a="Post" ability={ability}>
|
|
24
|
-
() => <button onClick={this.createPost.bind(this)}>Create Post</button>
|
|
24
|
+
{() => <button onClick={this.createPost.bind(this)}>Create Post</button>}
|
|
25
25
|
</Can>
|
|
26
26
|
```
|
|
27
27
|
|
|
@@ -62,7 +62,7 @@ import Can from './Can'
|
|
|
62
62
|
export function button() {
|
|
63
63
|
return (
|
|
64
64
|
<Can I="create" a="Post">
|
|
65
|
-
() => <button onClick={this.createPost.bind(this)}>Create Post</button>
|
|
65
|
+
{() => <button onClick={this.createPost.bind(this)}>Create Post</button>}
|
|
66
66
|
</Can>
|
|
67
67
|
)
|
|
68
68
|
}
|
|
@@ -108,7 +108,7 @@ export class TodoApp extends Component {
|
|
|
108
108
|
render() {
|
|
109
109
|
return (
|
|
110
110
|
<Can I="create" a="Todo">
|
|
111
|
-
() => <button onClick={this.createTodo.bind(this)}>Create Todo</button>
|
|
111
|
+
{() => <button onClick={this.createTodo.bind(this)}>Create Todo</button>}
|
|
112
112
|
</Can>
|
|
113
113
|
)
|
|
114
114
|
}
|
|
@@ -171,7 +171,7 @@ export class LoginComponent extends Component {
|
|
|
171
171
|
```
|
|
172
172
|
|
|
173
173
|
Obviously, in this case your server API should provide the list of user abilities in `rules` field of the response.
|
|
174
|
-
See [@casl/ability]
|
|
174
|
+
See [@casl/ability][casl-ability] package for more information on how to define abilities.
|
|
175
175
|
|
|
176
176
|
### 3. Property names and aliases
|
|
177
177
|
|
|
@@ -180,13 +180,13 @@ For example, the code below reads as `Can I create a Post`.
|
|
|
180
180
|
|
|
181
181
|
```jsx
|
|
182
182
|
<Can I="create" a="Post">
|
|
183
|
-
() => <button onClick={...}>Create Post</button>
|
|
183
|
+
{() => <button onClick={...}>Create Post</button>}
|
|
184
184
|
</Can>
|
|
185
185
|
```
|
|
186
186
|
|
|
187
187
|
There are several other property aliases which allow to construct a readable question:
|
|
188
188
|
|
|
189
|
-
* use `a` alias when you check by Type
|
|
189
|
+
* use `a` (or `an`) alias when you check by Type
|
|
190
190
|
|
|
191
191
|
```jsx
|
|
192
192
|
<Can I="read" a="Post">...</Can>
|
|
@@ -227,6 +227,14 @@ There are several other property aliases which allow to construct a readable que
|
|
|
227
227
|
<Can not I="read" a="Post">...</Can>
|
|
228
228
|
```
|
|
229
229
|
|
|
230
|
+
* use `passThrough` if you want to customize behavior of `<Can>` component, for example disable button instead of hiding it:
|
|
231
|
+
|
|
232
|
+
```jsx
|
|
233
|
+
<Can I="read" a="Post" passThrough>
|
|
234
|
+
{can => <button disabled={!can}>Save</button>}
|
|
235
|
+
</Can>
|
|
236
|
+
```
|
|
237
|
+
|
|
230
238
|
|
|
231
239
|
## Want to help?
|
|
232
240
|
|
|
@@ -240,3 +248,4 @@ Want to file a bug, contribute some code, or improve documentation? Excellent! R
|
|
|
240
248
|
[react]: https://reactjs.org/
|
|
241
249
|
[casl-react-example]: https://github.com/stalniy/casl-react-example
|
|
242
250
|
[react-ctx-api]: https://medium.com/dailyjs/reacts-%EF%B8%8F-new-context-api-70c9fe01596b
|
|
251
|
+
[casl-ability]: https://www.npmjs.com/package/@casl/ability
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import React, { PureComponent, Fragment, createElement } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { Ability } from '@casl/ability';
|
|
4
|
+
|
|
5
|
+
var classCallCheck = function (instance, Constructor) {
|
|
6
|
+
if (!(instance instanceof Constructor)) {
|
|
7
|
+
throw new TypeError("Cannot call a class as a function");
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
var createClass = function () {
|
|
12
|
+
function defineProperties(target, props) {
|
|
13
|
+
for (var i = 0; i < props.length; i++) {
|
|
14
|
+
var descriptor = props[i];
|
|
15
|
+
descriptor.enumerable = descriptor.enumerable || false;
|
|
16
|
+
descriptor.configurable = true;
|
|
17
|
+
if ("value" in descriptor) descriptor.writable = true;
|
|
18
|
+
Object.defineProperty(target, descriptor.key, descriptor);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return function (Constructor, protoProps, staticProps) {
|
|
23
|
+
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
|
24
|
+
if (staticProps) defineProperties(Constructor, staticProps);
|
|
25
|
+
return Constructor;
|
|
26
|
+
};
|
|
27
|
+
}();
|
|
28
|
+
|
|
29
|
+
var inherits = function (subClass, superClass) {
|
|
30
|
+
if (typeof superClass !== "function" && superClass !== null) {
|
|
31
|
+
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
35
|
+
constructor: {
|
|
36
|
+
value: subClass,
|
|
37
|
+
enumerable: false,
|
|
38
|
+
writable: true,
|
|
39
|
+
configurable: true
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
var possibleConstructorReturn = function (self, call) {
|
|
46
|
+
if (!self) {
|
|
47
|
+
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return call && (typeof call === "object" || typeof call === "function") ? call : self;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
var noop = function noop() {};
|
|
54
|
+
var _renderChildren = Fragment ? function (children) {
|
|
55
|
+
return createElement.apply(null, [Fragment, null].concat(children));
|
|
56
|
+
} : React.Children.only;
|
|
57
|
+
var propTypes = {};
|
|
58
|
+
|
|
59
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
60
|
+
var REQUIRED_OBJECT_OR_STRING = PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired;
|
|
61
|
+
|
|
62
|
+
var alias = function alias(names, validate) {
|
|
63
|
+
return function (props) {
|
|
64
|
+
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
65
|
+
args[_key - 1] = arguments[_key];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// eslint-disable-line
|
|
69
|
+
if (!names.split(' ').some(function (name) {
|
|
70
|
+
return props[name];
|
|
71
|
+
})) {
|
|
72
|
+
return validate.apply(undefined, [props].concat(args));
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
propTypes = {
|
|
78
|
+
I: alias('do', PropTypes.string.isRequired),
|
|
79
|
+
a: alias('on this of an', REQUIRED_OBJECT_OR_STRING),
|
|
80
|
+
an: alias('on this of a', REQUIRED_OBJECT_OR_STRING),
|
|
81
|
+
of: alias('on a this an', REQUIRED_OBJECT_OR_STRING),
|
|
82
|
+
this: alias('on a of an', REQUIRED_OBJECT_OR_STRING),
|
|
83
|
+
do: alias('I', PropTypes.string.isRequired),
|
|
84
|
+
on: alias('this a of an', REQUIRED_OBJECT_OR_STRING),
|
|
85
|
+
not: PropTypes.bool,
|
|
86
|
+
passThrough: PropTypes.bool,
|
|
87
|
+
children: PropTypes.any.isRequired,
|
|
88
|
+
ability: PropTypes.instanceOf(Ability).isRequired
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
var Can = function (_PureComponent) {
|
|
93
|
+
inherits(Can, _PureComponent);
|
|
94
|
+
|
|
95
|
+
function Can() {
|
|
96
|
+
classCallCheck(this, Can);
|
|
97
|
+
|
|
98
|
+
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
99
|
+
args[_key2] = arguments[_key2];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
var _this = possibleConstructorReturn(this, _PureComponent.call.apply(_PureComponent, [this].concat(args)));
|
|
103
|
+
|
|
104
|
+
_this.unsubscribeFromAbility = noop;
|
|
105
|
+
_this.state = {
|
|
106
|
+
ability: _this.props.ability,
|
|
107
|
+
allowed: false
|
|
108
|
+
};
|
|
109
|
+
return _this;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
Can.prototype.componentWillReceiveProps = function componentWillReceiveProps(props) {
|
|
113
|
+
var _this2 = this;
|
|
114
|
+
|
|
115
|
+
if (props.ability && this.state.ability !== props.ability) {
|
|
116
|
+
this.setState({ ability: props.ability }, function () {
|
|
117
|
+
_this2.connectToAbility(_this2.state.ability);
|
|
118
|
+
});
|
|
119
|
+
} else {
|
|
120
|
+
this.recheck(props);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
Can.prototype.componentWillMount = function componentWillMount() {
|
|
125
|
+
this.connectToAbility(this.state.ability);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
Can.prototype.componentWillUnmount = function componentWillUnmount() {
|
|
129
|
+
this.unsubscribeFromAbility();
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
Can.prototype.connectToAbility = function connectToAbility(ability) {
|
|
133
|
+
var _this3 = this;
|
|
134
|
+
|
|
135
|
+
this.unsubscribeFromAbility();
|
|
136
|
+
|
|
137
|
+
if (ability) {
|
|
138
|
+
this.unsubscribeFromAbility = ability.on('updated', function () {
|
|
139
|
+
return _this3.recheck();
|
|
140
|
+
});
|
|
141
|
+
this.recheck();
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
Can.prototype.recheck = function recheck(props) {
|
|
146
|
+
return this.setState({ allowed: this.check(props) });
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
Can.prototype.check = function check() {
|
|
150
|
+
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
151
|
+
|
|
152
|
+
var params = props || this.props;
|
|
153
|
+
|
|
154
|
+
var _split = (params.I || params.do).split(/\s+/),
|
|
155
|
+
action = _split[0],
|
|
156
|
+
field = _split[1];
|
|
157
|
+
|
|
158
|
+
var subject = params.of || params.a || params.this || params.on;
|
|
159
|
+
var can = params.not ? 'cannot' : 'can';
|
|
160
|
+
|
|
161
|
+
return this.state.ability[can](action, subject, field);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
Can.prototype.render = function render() {
|
|
165
|
+
var canRender = this.props.passThrough || this.state.allowed;
|
|
166
|
+
return canRender ? this.renderChildren() : null;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
Can.prototype.renderChildren = function renderChildren() {
|
|
170
|
+
var children = this.props.children;
|
|
171
|
+
|
|
172
|
+
var elements = typeof children === 'function' ? children(this.state.allowed, this.state.ability) : children;
|
|
173
|
+
|
|
174
|
+
return _renderChildren(elements);
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
createClass(Can, [{
|
|
178
|
+
key: 'allowed',
|
|
179
|
+
get: function get$$1() {
|
|
180
|
+
return this.state.allowed;
|
|
181
|
+
}
|
|
182
|
+
}]);
|
|
183
|
+
return Can;
|
|
184
|
+
}(PureComponent);
|
|
185
|
+
|
|
186
|
+
Can.propTypes = propTypes;
|
|
187
|
+
|
|
188
|
+
function createCanBoundTo(ability) {
|
|
189
|
+
var _class, _temp;
|
|
190
|
+
|
|
191
|
+
return _temp = _class = function (_Can) {
|
|
192
|
+
inherits(BoundCan, _Can);
|
|
193
|
+
|
|
194
|
+
function BoundCan() {
|
|
195
|
+
classCallCheck(this, BoundCan);
|
|
196
|
+
|
|
197
|
+
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
|
198
|
+
args[_key] = arguments[_key];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
var _this = possibleConstructorReturn(this, _Can.call.apply(_Can, [this].concat(args)));
|
|
202
|
+
|
|
203
|
+
_this.state.ability = _this.state.ability || ability;
|
|
204
|
+
return _this;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return BoundCan;
|
|
208
|
+
}(Can), _class.propTypes = Object.assign({}, Can.propTypes, {
|
|
209
|
+
ability: PropTypes.instanceOf(Ability)
|
|
210
|
+
}), _temp;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function createContextualCan(Consumer) {
|
|
214
|
+
return function ContextualCan(props) {
|
|
215
|
+
return createElement(Consumer, null, function (ability) {
|
|
216
|
+
return createElement(Can, {
|
|
217
|
+
ability: props.ability || ability,
|
|
218
|
+
I: props.I || props.do,
|
|
219
|
+
a: props.on || props.a || props.an || props.of || props.this,
|
|
220
|
+
not: props.not,
|
|
221
|
+
children: props.children,
|
|
222
|
+
passThrough: props.passThrough
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export { Can, createCanBoundTo, createContextualCan };
|
package/dist/es6/index.js
CHANGED
|
@@ -1,17 +1,34 @@
|
|
|
1
|
-
import React, { PureComponent, createElement } from 'react';
|
|
1
|
+
import React, { PureComponent, Fragment, createElement } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { Ability } from '@casl/ability';
|
|
4
4
|
|
|
5
5
|
const noop = () => {};
|
|
6
|
-
const
|
|
6
|
+
const renderChildren = Fragment ? children => createElement.apply(null, [Fragment, null].concat(children)) : React.Children.only;
|
|
7
|
+
let propTypes = {};
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
10
|
+
const REQUIRED_OBJECT_OR_STRING = PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired;
|
|
11
|
+
|
|
12
|
+
const alias = (names, validate) => (props, ...args) => {
|
|
10
13
|
// eslint-disable-line
|
|
11
14
|
if (!names.split(' ').some(name => props[name])) {
|
|
12
15
|
return validate(props, ...args);
|
|
13
16
|
}
|
|
14
17
|
};
|
|
18
|
+
|
|
19
|
+
propTypes = {
|
|
20
|
+
I: alias('do', PropTypes.string.isRequired),
|
|
21
|
+
a: alias('on this of an', REQUIRED_OBJECT_OR_STRING),
|
|
22
|
+
an: alias('on this of a', REQUIRED_OBJECT_OR_STRING),
|
|
23
|
+
of: alias('on a this an', REQUIRED_OBJECT_OR_STRING),
|
|
24
|
+
this: alias('on a of an', REQUIRED_OBJECT_OR_STRING),
|
|
25
|
+
do: alias('I', PropTypes.string.isRequired),
|
|
26
|
+
on: alias('this a of an', REQUIRED_OBJECT_OR_STRING),
|
|
27
|
+
not: PropTypes.bool,
|
|
28
|
+
passThrough: PropTypes.bool,
|
|
29
|
+
children: PropTypes.any.isRequired,
|
|
30
|
+
ability: PropTypes.instanceOf(Ability).isRequired
|
|
31
|
+
};
|
|
15
32
|
}
|
|
16
33
|
|
|
17
34
|
class Can extends PureComponent {
|
|
@@ -32,8 +49,9 @@ class Can extends PureComponent {
|
|
|
32
49
|
|
|
33
50
|
componentWillReceiveProps(props) {
|
|
34
51
|
if (props.ability && this.state.ability !== props.ability) {
|
|
35
|
-
this.setState({ ability: props.ability })
|
|
36
|
-
|
|
52
|
+
this.setState({ ability: props.ability }, () => {
|
|
53
|
+
this.connectToAbility(this.state.ability);
|
|
54
|
+
});
|
|
37
55
|
} else {
|
|
38
56
|
this.recheck(props);
|
|
39
57
|
}
|
|
@@ -70,26 +88,18 @@ class Can extends PureComponent {
|
|
|
70
88
|
}
|
|
71
89
|
|
|
72
90
|
render() {
|
|
73
|
-
|
|
91
|
+
const canRender = this.props.passThrough || this.state.allowed;
|
|
92
|
+
return canRender ? this.renderChildren() : null;
|
|
74
93
|
}
|
|
75
94
|
|
|
76
95
|
renderChildren() {
|
|
77
96
|
const { children } = this.props;
|
|
97
|
+
const elements = typeof children === 'function' ? children(this.state.allowed, this.state.ability) : children;
|
|
78
98
|
|
|
79
|
-
return
|
|
99
|
+
return renderChildren(elements);
|
|
80
100
|
}
|
|
81
101
|
}
|
|
82
|
-
Can.propTypes =
|
|
83
|
-
I: alias('do', PropTypes.string.isRequired),
|
|
84
|
-
a: alias('on this of', REQUIRED_OBJECT_OR_STRING),
|
|
85
|
-
of: alias('on a this', REQUIRED_OBJECT_OR_STRING),
|
|
86
|
-
this: alias('on a of', REQUIRED_OBJECT_OR_STRING),
|
|
87
|
-
do: alias('I', PropTypes.string.isRequired),
|
|
88
|
-
on: alias('this a of', REQUIRED_OBJECT_OR_STRING),
|
|
89
|
-
not: PropTypes.bool,
|
|
90
|
-
children: PropTypes.any.isRequired,
|
|
91
|
-
ability: PropTypes.instanceOf(Ability).isRequired
|
|
92
|
-
};
|
|
102
|
+
Can.propTypes = propTypes;
|
|
93
103
|
|
|
94
104
|
function createCanBoundTo(ability) {
|
|
95
105
|
var _class, _temp;
|
|
@@ -110,9 +120,10 @@ function createContextualCan(Consumer) {
|
|
|
110
120
|
return createElement(Consumer, null, ability => createElement(Can, {
|
|
111
121
|
ability: props.ability || ability,
|
|
112
122
|
I: props.I || props.do,
|
|
113
|
-
a: props.a || props.
|
|
123
|
+
a: props.on || props.a || props.an || props.of || props.this,
|
|
114
124
|
not: props.not,
|
|
115
|
-
children: props.children
|
|
125
|
+
children: props.children,
|
|
126
|
+
passThrough: props.passThrough
|
|
116
127
|
}));
|
|
117
128
|
};
|
|
118
129
|
}
|
package/dist/umd/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("react"),require("prop-types"),require("@casl/ability")):"function"==typeof define&&define.amd?define(["exports","react","prop-types","@casl/ability"],e):e((t.casl=t.casl||{},t.casl.react={}),t.React,t.React.PropTypes,t.casl)}(this,function(t,n,i,
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("react"),require("prop-types"),require("@casl/ability")):"function"==typeof define&&define.amd?define(["exports","react","prop-types","@casl/ability"],e):e((t.casl=t.casl||{},t.casl.react={}),t.React,t.React.PropTypes,t.casl)}(this,function(t,n,i,o){"use strict";var e="default"in n?n.default:n;i=i&&i.hasOwnProperty("default")?i.default:i;var s=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},a=function(){function i(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(t,e,n){return e&&i(t.prototype,e),n&&i(t,n),t}}(),c=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)},l=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e},u=function(){},p=n.Fragment?function(t){return n.createElement.apply(null,[n.Fragment,null].concat(t))}:e.Children.only,r={};if("production"!==process.env.NODE_ENV){var f=i.oneOfType([i.object,i.string]).isRequired,y=function(o,r){return function(e){for(var t=arguments.length,n=Array(1<t?t-1:0),i=1;i<t;i++)n[i-1]=arguments[i];if(!o.split(" ").some(function(t){return e[t]}))return r.apply(void 0,[e].concat(n))}};r={I:y("do",i.string.isRequired),a:y("on this of an",f),an:y("on this of a",f),of:y("on a this an",f),this:y("on a of an",f),do:y("I",i.string.isRequired),on:y("this a of an",f),not:i.bool,passThrough:i.bool,children:i.any.isRequired,ability:i.instanceOf(o.Ability).isRequired}}var h=function(o){function r(){s(this,r);for(var t=arguments.length,e=Array(t),n=0;n<t;n++)e[n]=arguments[n];var i=l(this,o.call.apply(o,[this].concat(e)));return i.unsubscribeFromAbility=u,i.state={ability:i.props.ability,allowed:!1},i}return c(r,o),r.prototype.componentWillReceiveProps=function(t){var e=this;t.ability&&this.state.ability!==t.ability?this.setState({ability:t.ability},function(){e.connectToAbility(e.state.ability)}):this.recheck(t)},r.prototype.componentWillMount=function(){this.connectToAbility(this.state.ability)},r.prototype.componentWillUnmount=function(){this.unsubscribeFromAbility()},r.prototype.connectToAbility=function(t){var e=this;this.unsubscribeFromAbility(),t&&(this.unsubscribeFromAbility=t.on("updated",function(){return e.recheck()}),this.recheck())},r.prototype.recheck=function(t){return this.setState({allowed:this.check(t)})},r.prototype.check=function(){var t=(0<arguments.length&&void 0!==arguments[0]?arguments[0]:null)||this.props,e=(t.I||t.do).split(/\s+/),n=e[0],i=e[1],o=t.of||t.a||t.this||t.on,r=t.not?"cannot":"can";return this.state.ability[r](n,o,i)},r.prototype.render=function(){return this.props.passThrough||this.state.allowed?this.renderChildren():null},r.prototype.renderChildren=function(){var t=this.props.children,e="function"==typeof t?t(this.state.allowed,this.state.ability):t;return p(e)},a(r,[{key:"allowed",get:function(){return this.state.allowed}}]),r}(n.PureComponent);h.propTypes=r,t.Can=h,t.createCanBoundTo=function(a){var t,e;return e=t=function(o){function r(){s(this,r);for(var t=arguments.length,e=Array(t),n=0;n<t;n++)e[n]=arguments[n];var i=l(this,o.call.apply(o,[this].concat(e)));return i.state.ability=i.state.ability||a,i}return c(r,o),r}(h),t.propTypes=Object.assign({},h.propTypes,{ability:i.instanceOf(o.Ability)}),e},t.createContextualCan=function(t){return function(e){return n.createElement(t,null,function(t){return n.createElement(h,{ability:e.ability||t,I:e.I||e.do,a:e.on||e.a||e.an||e.of||e.this,not:e.not,children:e.children,passThrough:e.passThrough})})}},Object.defineProperty(t,"__esModule",{value:!0})});
|
package/index.d.ts
CHANGED
|
@@ -7,6 +7,9 @@ type BaseProps = {
|
|
|
7
7
|
} | {
|
|
8
8
|
I: string
|
|
9
9
|
a: string
|
|
10
|
+
} | {
|
|
11
|
+
I: string
|
|
12
|
+
an: string
|
|
10
13
|
} | {
|
|
11
14
|
I: string
|
|
12
15
|
of: any
|
|
@@ -17,12 +20,14 @@ type BaseProps = {
|
|
|
17
20
|
|
|
18
21
|
type CanPropsStrict = BaseProps & {
|
|
19
22
|
ability: Ability
|
|
20
|
-
not
|
|
23
|
+
not?: boolean
|
|
24
|
+
passThrough?: boolean
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
type CanProps = BaseProps & {
|
|
24
28
|
ability?: Ability
|
|
25
|
-
not
|
|
29
|
+
not?: boolean
|
|
30
|
+
passThrough?: boolean
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
declare class CanComponent<T> extends PureComponent<T> {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@casl/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "React component for CASL which makes it easy to add permissions in any React application",
|
|
5
5
|
"main": "dist/umd/index.js",
|
|
6
|
-
"module": "index.js",
|
|
6
|
+
"module": "dist/es5m/index.js",
|
|
7
7
|
"es2015": "dist/es6/index.js",
|
|
8
8
|
"typings": "./index.d.ts",
|
|
9
9
|
"repository": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"npm": "^6.0.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@casl/ability": "^2.0.0
|
|
42
|
+
"@casl/ability": "^2.0.0",
|
|
43
43
|
"prop-types": "^15.0.0",
|
|
44
44
|
"react": "^15.0.0 || ^16.0.0"
|
|
45
45
|
},
|
|
@@ -48,7 +48,6 @@
|
|
|
48
48
|
"check-prop-types": "^1.1.2",
|
|
49
49
|
"prop-types": "^15.6.0",
|
|
50
50
|
"react": "^16.3.0",
|
|
51
|
-
"react-test-renderer": "^16.3.0"
|
|
52
|
-
"semantic-release": "^15.5.0"
|
|
51
|
+
"react-test-renderer": "^16.3.0"
|
|
53
52
|
}
|
|
54
53
|
}
|
package/index.js
DELETED
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
import React, { PureComponent, createElement } from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { Ability } from '@casl/ability';
|
|
4
|
-
|
|
5
|
-
var classCallCheck = function (instance, Constructor) {
|
|
6
|
-
if (!(instance instanceof Constructor)) {
|
|
7
|
-
throw new TypeError("Cannot call a class as a function");
|
|
8
|
-
}
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
var createClass = function () {
|
|
12
|
-
function defineProperties(target, props) {
|
|
13
|
-
for (var i = 0; i < props.length; i++) {
|
|
14
|
-
var descriptor = props[i];
|
|
15
|
-
descriptor.enumerable = descriptor.enumerable || false;
|
|
16
|
-
descriptor.configurable = true;
|
|
17
|
-
if ("value" in descriptor) descriptor.writable = true;
|
|
18
|
-
Object.defineProperty(target, descriptor.key, descriptor);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return function (Constructor, protoProps, staticProps) {
|
|
23
|
-
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
|
24
|
-
if (staticProps) defineProperties(Constructor, staticProps);
|
|
25
|
-
return Constructor;
|
|
26
|
-
};
|
|
27
|
-
}();
|
|
28
|
-
|
|
29
|
-
var inherits = function (subClass, superClass) {
|
|
30
|
-
if (typeof superClass !== "function" && superClass !== null) {
|
|
31
|
-
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
35
|
-
constructor: {
|
|
36
|
-
value: subClass,
|
|
37
|
-
enumerable: false,
|
|
38
|
-
writable: true,
|
|
39
|
-
configurable: true
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
var possibleConstructorReturn = function (self, call) {
|
|
46
|
-
if (!self) {
|
|
47
|
-
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return call && (typeof call === "object" || typeof call === "function") ? call : self;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
var slicedToArray = function () {
|
|
54
|
-
function sliceIterator(arr, i) {
|
|
55
|
-
var _arr = [];
|
|
56
|
-
var _n = true;
|
|
57
|
-
var _d = false;
|
|
58
|
-
var _e = undefined;
|
|
59
|
-
|
|
60
|
-
try {
|
|
61
|
-
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
|
|
62
|
-
_arr.push(_s.value);
|
|
63
|
-
|
|
64
|
-
if (i && _arr.length === i) break;
|
|
65
|
-
}
|
|
66
|
-
} catch (err) {
|
|
67
|
-
_d = true;
|
|
68
|
-
_e = err;
|
|
69
|
-
} finally {
|
|
70
|
-
try {
|
|
71
|
-
if (!_n && _i["return"]) _i["return"]();
|
|
72
|
-
} finally {
|
|
73
|
-
if (_d) throw _e;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return _arr;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return function (arr, i) {
|
|
81
|
-
if (Array.isArray(arr)) {
|
|
82
|
-
return arr;
|
|
83
|
-
} else if (Symbol.iterator in Object(arr)) {
|
|
84
|
-
return sliceIterator(arr, i);
|
|
85
|
-
} else {
|
|
86
|
-
throw new TypeError("Invalid attempt to destructure non-iterable instance");
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
}();
|
|
90
|
-
|
|
91
|
-
var noop = function noop() {};
|
|
92
|
-
var REQUIRED_OBJECT_OR_STRING = PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired;
|
|
93
|
-
|
|
94
|
-
function alias(names, validate) {
|
|
95
|
-
return function (props) {
|
|
96
|
-
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
97
|
-
args[_key - 1] = arguments[_key];
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// eslint-disable-line
|
|
101
|
-
if (!names.split(' ').some(function (name) {
|
|
102
|
-
return props[name];
|
|
103
|
-
})) {
|
|
104
|
-
return validate.apply(undefined, [props].concat(args));
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
var Can = function (_PureComponent) {
|
|
110
|
-
inherits(Can, _PureComponent);
|
|
111
|
-
|
|
112
|
-
function Can() {
|
|
113
|
-
var _ref;
|
|
114
|
-
|
|
115
|
-
classCallCheck(this, Can);
|
|
116
|
-
|
|
117
|
-
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
118
|
-
args[_key2] = arguments[_key2];
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
var _this = possibleConstructorReturn(this, (_ref = Can.__proto__ || Object.getPrototypeOf(Can)).call.apply(_ref, [this].concat(args)));
|
|
122
|
-
|
|
123
|
-
_this.unsubscribeFromAbility = noop;
|
|
124
|
-
_this.state = {
|
|
125
|
-
ability: _this.props.ability,
|
|
126
|
-
allowed: false
|
|
127
|
-
};
|
|
128
|
-
return _this;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
createClass(Can, [{
|
|
132
|
-
key: 'componentWillReceiveProps',
|
|
133
|
-
value: function componentWillReceiveProps(props) {
|
|
134
|
-
if (props.ability && this.state.ability !== props.ability) {
|
|
135
|
-
this.setState({ ability: props.ability });
|
|
136
|
-
this.connectToAbility(props.ability);
|
|
137
|
-
} else {
|
|
138
|
-
this.recheck(props);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}, {
|
|
142
|
-
key: 'componentWillMount',
|
|
143
|
-
value: function componentWillMount() {
|
|
144
|
-
this.connectToAbility(this.state.ability);
|
|
145
|
-
}
|
|
146
|
-
}, {
|
|
147
|
-
key: 'componentWillUnmount',
|
|
148
|
-
value: function componentWillUnmount() {
|
|
149
|
-
this.unsubscribeFromAbility();
|
|
150
|
-
}
|
|
151
|
-
}, {
|
|
152
|
-
key: 'connectToAbility',
|
|
153
|
-
value: function connectToAbility(ability) {
|
|
154
|
-
var _this2 = this;
|
|
155
|
-
|
|
156
|
-
this.unsubscribeFromAbility();
|
|
157
|
-
|
|
158
|
-
if (ability) {
|
|
159
|
-
this.unsubscribeFromAbility = ability.on('updated', function () {
|
|
160
|
-
return _this2.recheck();
|
|
161
|
-
});
|
|
162
|
-
this.recheck();
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}, {
|
|
166
|
-
key: 'recheck',
|
|
167
|
-
value: function recheck(props) {
|
|
168
|
-
return this.setState({ allowed: this.check(props) });
|
|
169
|
-
}
|
|
170
|
-
}, {
|
|
171
|
-
key: 'check',
|
|
172
|
-
value: function check() {
|
|
173
|
-
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
174
|
-
|
|
175
|
-
var params = props || this.props;
|
|
176
|
-
|
|
177
|
-
var _split = (params.I || params.do).split(/\s+/),
|
|
178
|
-
_split2 = slicedToArray(_split, 2),
|
|
179
|
-
action = _split2[0],
|
|
180
|
-
field = _split2[1];
|
|
181
|
-
|
|
182
|
-
var subject = params.of || params.a || params.this || params.on;
|
|
183
|
-
var can = params.not ? 'cannot' : 'can';
|
|
184
|
-
|
|
185
|
-
return this.state.ability[can](action, subject, field);
|
|
186
|
-
}
|
|
187
|
-
}, {
|
|
188
|
-
key: 'render',
|
|
189
|
-
value: function render() {
|
|
190
|
-
return this.state.allowed ? this.renderChildren() : null;
|
|
191
|
-
}
|
|
192
|
-
}, {
|
|
193
|
-
key: 'renderChildren',
|
|
194
|
-
value: function renderChildren() {
|
|
195
|
-
var children = this.props.children;
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
return typeof children === 'function' ? children(this.state.ability) : React.Children.only(children);
|
|
199
|
-
}
|
|
200
|
-
}, {
|
|
201
|
-
key: 'allowed',
|
|
202
|
-
get: function get$$1() {
|
|
203
|
-
return this.state.allowed;
|
|
204
|
-
}
|
|
205
|
-
}]);
|
|
206
|
-
return Can;
|
|
207
|
-
}(PureComponent);
|
|
208
|
-
|
|
209
|
-
Can.propTypes = {
|
|
210
|
-
I: alias('do', PropTypes.string.isRequired),
|
|
211
|
-
a: alias('on this of', REQUIRED_OBJECT_OR_STRING),
|
|
212
|
-
of: alias('on a this', REQUIRED_OBJECT_OR_STRING),
|
|
213
|
-
this: alias('on a of', REQUIRED_OBJECT_OR_STRING),
|
|
214
|
-
do: alias('I', PropTypes.string.isRequired),
|
|
215
|
-
on: alias('this a of', REQUIRED_OBJECT_OR_STRING),
|
|
216
|
-
not: PropTypes.bool,
|
|
217
|
-
children: PropTypes.any.isRequired,
|
|
218
|
-
ability: PropTypes.instanceOf(Ability).isRequired
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
function createCanBoundTo(ability) {
|
|
222
|
-
var _class, _temp;
|
|
223
|
-
|
|
224
|
-
return _temp = _class = function (_Can) {
|
|
225
|
-
inherits(BoundCan, _Can);
|
|
226
|
-
|
|
227
|
-
function BoundCan() {
|
|
228
|
-
var _ref;
|
|
229
|
-
|
|
230
|
-
classCallCheck(this, BoundCan);
|
|
231
|
-
|
|
232
|
-
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
|
233
|
-
args[_key] = arguments[_key];
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
var _this = possibleConstructorReturn(this, (_ref = BoundCan.__proto__ || Object.getPrototypeOf(BoundCan)).call.apply(_ref, [this].concat(args)));
|
|
237
|
-
|
|
238
|
-
_this.state.ability = _this.state.ability || ability;
|
|
239
|
-
return _this;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
return BoundCan;
|
|
243
|
-
}(Can), _class.propTypes = Object.assign({}, Can.propTypes, {
|
|
244
|
-
ability: PropTypes.instanceOf(Ability)
|
|
245
|
-
}), _temp;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
function createContextualCan(Consumer) {
|
|
249
|
-
return function ContextualCan(props) {
|
|
250
|
-
return createElement(Consumer, null, function (ability) {
|
|
251
|
-
return createElement(Can, {
|
|
252
|
-
ability: props.ability || ability,
|
|
253
|
-
I: props.I || props.do,
|
|
254
|
-
a: props.a || props.of || props.this || props.on,
|
|
255
|
-
not: props.not,
|
|
256
|
-
children: props.children
|
|
257
|
-
});
|
|
258
|
-
});
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
export { Can, createCanBoundTo, createContextualCan };
|