@panneau/core 1.0.1-alpha.0 → 1.0.3-alpha.0

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.
Files changed (80) hide show
  1. package/contexts.js +1 -1
  2. package/es/contexts.js +1740 -0
  3. package/es/hooks.js +1116 -0
  4. package/es/index.js +991 -9
  5. package/es/utils.js +329 -1
  6. package/hooks.js +1 -0
  7. package/lib/contexts.js +1871 -0
  8. package/lib/hooks.js +1167 -0
  9. package/lib/index.js +1003 -44
  10. package/lib/utils.js +371 -12
  11. package/package.json +79 -49
  12. package/utils.js +1 -1
  13. package/components.js +0 -1
  14. package/es/components/Button.js +0 -157
  15. package/es/components/ButtonGroup.js +0 -87
  16. package/es/components/Errors.js +0 -33
  17. package/es/components/Label.js +0 -32
  18. package/es/components/Loading.js +0 -56
  19. package/es/components/index.js +0 -6
  20. package/es/contexts/Components.js +0 -52
  21. package/es/contexts/Definition.js +0 -21
  22. package/es/contexts/UrlGenerator.js +0 -33
  23. package/es/contexts/index.js +0 -3
  24. package/es/lib/ComponentsCollection.js +0 -107
  25. package/es/lib/Definition.js +0 -134
  26. package/es/lib/PropTypes.js +0 -75
  27. package/es/lib/Resource.js +0 -93
  28. package/es/lib/ResourceApi.js +0 -139
  29. package/es/lib/UrlGenerator.js +0 -66
  30. package/es/lib/requests.js +0 -165
  31. package/es/lib/useResourceApi.js +0 -19
  32. package/es/lib/utils.js +0 -19
  33. package/es/requests.js +0 -1
  34. package/lib/components/Button.js +0 -182
  35. package/lib/components/ButtonGroup.js +0 -104
  36. package/lib/components/Errors.js +0 -49
  37. package/lib/components/Label.js +0 -47
  38. package/lib/components/Loading.js +0 -70
  39. package/lib/components/index.js +0 -47
  40. package/lib/contexts/Components.js +0 -78
  41. package/lib/contexts/Definition.js +0 -45
  42. package/lib/contexts/UrlGenerator.js +0 -53
  43. package/lib/contexts/index.js +0 -73
  44. package/lib/lib/ComponentsCollection.js +0 -117
  45. package/lib/lib/Definition.js +0 -145
  46. package/lib/lib/PropTypes.js +0 -152
  47. package/lib/lib/Resource.js +0 -104
  48. package/lib/lib/ResourceApi.js +0 -154
  49. package/lib/lib/UrlGenerator.js +0 -76
  50. package/lib/lib/requests.js +0 -206
  51. package/lib/lib/useResourceApi.js +0 -33
  52. package/lib/lib/utils.js +0 -35
  53. package/lib/requests.js +0 -17
  54. package/requests.js +0 -1
  55. package/src/components/Button.jsx +0 -186
  56. package/src/components/ButtonGroup.jsx +0 -98
  57. package/src/components/Errors.jsx +0 -46
  58. package/src/components/Label.jsx +0 -32
  59. package/src/components/Loading.jsx +0 -51
  60. package/src/components/index.js +0 -7
  61. package/src/contexts/Components.jsx +0 -49
  62. package/src/contexts/Definition.jsx +0 -21
  63. package/src/contexts/UrlGenerator.jsx +0 -35
  64. package/src/contexts/index.js +0 -12
  65. package/src/index.js +0 -8
  66. package/src/lib/ComponentsCollection.js +0 -81
  67. package/src/lib/Definition.js +0 -87
  68. package/src/lib/PropTypes.js +0 -117
  69. package/src/lib/Resource.js +0 -65
  70. package/src/lib/ResourceApi.js +0 -114
  71. package/src/lib/UrlGenerator.js +0 -55
  72. package/src/lib/requests.js +0 -120
  73. package/src/lib/useResourceApi.jsx +0 -20
  74. package/src/lib/utils.js +0 -13
  75. package/src/requests.js +0 -1
  76. package/src/styles/components/button-group.scss +0 -10
  77. package/src/styles/components/errors.scss +0 -5
  78. package/src/styles/components/loading.scss +0 -36
  79. package/src/styles/variables.scss +0 -5
  80. package/src/utils.js +0 -1
@@ -1,87 +0,0 @@
1
- import Resource from './Resource';
2
- import { getLocalizedName } from './utils';
3
-
4
- class Definition {
5
- constructor({ resources = [], ...definition } = {}) {
6
- this.definition = {
7
- ...definition,
8
- resources: resources.map(it => new Resource(it)),
9
- };
10
- }
11
-
12
- allRoutes() {
13
- const { routes = {} } = this.definition;
14
- const resourcesRoutes = this.resources()
15
- .filter(it => it.hasRoutes())
16
- .reduce((routesMap, resource) => {
17
- const resourceRoutes = resource.routes();
18
- return {
19
- ...routesMap,
20
- ...Object.keys(resourceRoutes).reduce(
21
- (mapRoutes, name) => ({
22
- ...mapRoutes,
23
- [`resource.${resource.id()}.${name}`]: resourceRoutes[name],
24
- }),
25
- {},
26
- ),
27
- };
28
- }, {});
29
- return {
30
- ...routes,
31
- ...resourcesRoutes,
32
- };
33
- }
34
-
35
- localizedName(variant = 'default') {
36
- return getLocalizedName(this.definition, variant);
37
- }
38
-
39
- apiEndpoint() {
40
- const { api: { endpoint = null } = {} } = this.definition;
41
- return endpoint;
42
- }
43
-
44
- apiUploadEndpoint() {
45
- const { api: { uploadEndpoint = null } = {} } = this.definition;
46
- return uploadEndpoint;
47
- }
48
-
49
- layout() {
50
- const { layout = {} } = this.definition;
51
- return layout;
52
- }
53
-
54
- locales() {
55
- const { localization: { locales = ['en'] } = {} } = this.definition;
56
- return locales;
57
- }
58
-
59
- resources() {
60
- const { resources = [] } = this.definition;
61
- return resources;
62
- }
63
-
64
- resource(id) {
65
- return this.resources().find(it => it.id() === id) || null;
66
- }
67
-
68
- fields() {
69
- const { fields = [] } = this.definition;
70
- return fields;
71
- }
72
-
73
- field(id) {
74
- return this.fields().find(it => it.id === id) || null;
75
- }
76
-
77
- blocks() {
78
- const { blocks = [] } = this.definition;
79
- return blocks;
80
- }
81
-
82
- block(id) {
83
- return this.blocks().find(it => it.id === id) || null;
84
- }
85
- }
86
-
87
- export default Definition;
@@ -1,117 +0,0 @@
1
- import PropTypes from 'prop-types';
2
- import * as definitions from '@panneau/schemas/prop-types';
3
-
4
- import UrlGenerator from './UrlGenerator';
5
- import ResourceApi from './ResourceApi';
6
- import Definition from './Definition';
7
- import Resource from './Resource';
8
- import ComponentsCollection from './ComponentsCollection';
9
-
10
- /**
11
- * Core
12
- */
13
- export const urlGenerator = PropTypes.instanceOf(UrlGenerator);
14
-
15
- export const history = PropTypes.shape({
16
- push: PropTypes.func.isRequired,
17
- });
18
-
19
- export const intl = PropTypes.shape({
20
- locale: PropTypes.string.isRequired,
21
- formatMessage: PropTypes.func.isRequired,
22
- });
23
-
24
- export const intlMessage = PropTypes.shape({
25
- id: PropTypes.string,
26
- description: PropTypes.string,
27
- defaultMessage: PropTypes.string,
28
- });
29
-
30
- export const componentsCollection = PropTypes.instanceOf(ComponentsCollection);
31
-
32
- export const components = PropTypes.oneOfType([
33
- PropTypes.objectOf(PropTypes.elementType),
34
- PropTypes.instanceOf(ComponentsCollection),
35
- ]);
36
-
37
- export const resourceApi = PropTypes.instanceOf(ResourceApi);
38
-
39
- export const ref = PropTypes.oneOfType([
40
- PropTypes.func,
41
- PropTypes.shape({ current: PropTypes.elementType }),
42
- ]);
43
-
44
- /**
45
- * UI
46
- */
47
- export const message = PropTypes.oneOfType([PropTypes.string, intlMessage]);
48
-
49
- export const label = PropTypes.oneOfType([PropTypes.node, intlMessage]);
50
-
51
- export const button = PropTypes.shape({
52
- id: PropTypes.string,
53
- type: PropTypes.string,
54
- href: PropTypes.string,
55
- external: PropTypes.bool,
56
- label: message,
57
- children: message,
58
- className: PropTypes.string,
59
- onClick: PropTypes.func,
60
- });
61
-
62
- export const buttons = PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.node, button]));
63
-
64
- export const dropdownItem = PropTypes.shape({
65
- id: PropTypes.string,
66
- href: PropTypes.string,
67
- external: PropTypes.bool,
68
- label: message,
69
- className: PropTypes.string,
70
- onClick: PropTypes.func,
71
- });
72
-
73
- export const dropdownItems = PropTypes.arrayOf(dropdownItem);
74
-
75
- export const errors = PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]);
76
-
77
- export const buttonSize = PropTypes.oneOf(['sm', 'md', 'lg']);
78
-
79
- export const buttonStyle = PropTypes.oneOf([
80
- null,
81
- 'primary',
82
- 'secondary',
83
- 'success',
84
- 'danger',
85
- 'warning',
86
- 'info',
87
- 'light',
88
- 'dark',
89
- 'link',
90
- 'outline-primary',
91
- 'outline-secondary',
92
- 'outline-success',
93
- 'outline-danger',
94
- 'outline-warning',
95
- 'outline-info',
96
- 'outline-light',
97
- 'outline-dark',
98
- 'outline-link',
99
- ]);
100
-
101
- /**
102
- * Models
103
- */
104
- export const user = PropTypes.shape({
105
- id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
106
- name: PropTypes.string,
107
- email: PropTypes.string,
108
- });
109
-
110
- /**
111
- * Definitions
112
- */
113
- export const definition = PropTypes.instanceOf(Definition);
114
- export const resource = PropTypes.instanceOf(Resource);
115
- export {
116
- definitions
117
- };
@@ -1,65 +0,0 @@
1
- import get from 'lodash/get';
2
- import { getLocalizedName } from './utils';
3
-
4
- class Resource {
5
- constructor(resource) {
6
- this.resource = resource || {};
7
- }
8
-
9
- id() {
10
- return this.resource.id;
11
- }
12
-
13
- type() {
14
- return this.resource.type || 'default';
15
- }
16
-
17
- types() {
18
- return this.resource.types || [];
19
- }
20
-
21
- localizedName(variant = 'default') {
22
- return getLocalizedName(this.resource, variant);
23
- }
24
-
25
- messages() {
26
- const { messages = {} } = this.resource;
27
- return messages;
28
- }
29
-
30
- message(key, defaultValue) {
31
- return get(this.messages(), key, defaultValue);
32
- }
33
-
34
- routes() {
35
- const { routes = {} } = this.resource;
36
- return routes;
37
- }
38
-
39
- hasRoutes() {
40
- const { routes = null } = this.resource;
41
- return routes !== null;
42
- }
43
-
44
- forms() {
45
- const { forms = {} } = this.resource;
46
- return forms;
47
- }
48
-
49
- form(action) {
50
- const forms = this.forms();
51
- return forms[action] || forms;
52
- }
53
-
54
- lists() {
55
- const { lists = {} } = this.resource;
56
- return lists;
57
- }
58
-
59
- list(action) {
60
- const lists = this.lists();
61
- return lists[action] || lists;
62
- }
63
- }
64
-
65
- export default Resource;
@@ -1,114 +0,0 @@
1
- import trimEnd from 'lodash/trimEnd';
2
- import isEmpty from 'lodash/isEmpty';
3
- import isObject from 'lodash/isObject';
4
- import queryString from 'query-string';
5
- import 'whatwg-fetch';
6
-
7
- import {
8
- getResponseAndDataObject,
9
- throwResponseError,
10
- throwValidationError,
11
- getCSRFHeaders,
12
- } from './requests';
13
-
14
- class ResourceApi {
15
- constructor(resource, urlGenerator, opts) {
16
- this.resource = resource;
17
- this.urlGenerator = urlGenerator;
18
- this.options = {
19
- idParamName: 'id',
20
- host: '/',
21
- ...opts,
22
- };
23
- }
24
-
25
- definition() {
26
- return this.callApi('definition', 'get');
27
- }
28
-
29
- index(params = null) {
30
- const query =
31
- params !== null && isObject(params) ? queryString.stringify(params) : params || '';
32
- const path = `${this.getActionPath('index')}${
33
- !isEmpty(query) ? `?${query.replace(/^\?/, '')}` : ''
34
- }`;
35
- return this.callApi(path, 'get');
36
- }
37
-
38
- create() {
39
- const path = this.getActionPath('create');
40
- return this.callApi(path, 'get');
41
- }
42
-
43
- store(data) {
44
- const path = this.getActionPath('store');
45
- return this.callApi(path, 'post', data);
46
- }
47
-
48
- show(id) {
49
- const path = this.getActionPath('show', id);
50
- return this.callApi(path, 'get');
51
- }
52
-
53
- edit(id) {
54
- const path = this.getActionPath('edit', id);
55
- return this.callApi(path, 'get');
56
- }
57
-
58
- update(id, data) {
59
- const path = this.getActionPath('update', id);
60
- return this.callApi(path, 'put', data);
61
- }
62
-
63
- destroy(id) {
64
- const path = this.getActionPath('destroy', id);
65
- return this.callApi(path, 'delete');
66
- }
67
-
68
- // eslint-disable-next-line class-methods-use-this
69
- callApi(path, method, data = undefined) {
70
- const body = data || null;
71
- const methodUpperCase = method.toUpperCase();
72
- let finalMethod;
73
- let finalBody;
74
- switch (methodUpperCase) {
75
- case 'PUT':
76
- case 'PATCH':
77
- case 'DELETE':
78
- finalMethod = 'POST';
79
- finalBody = {
80
- ...body,
81
- _method: methodUpperCase, // Laravel magic
82
- };
83
- break;
84
- default:
85
- finalMethod = methodUpperCase;
86
- finalBody = body;
87
- break;
88
- }
89
- return fetch(path, {
90
- credentials: 'include',
91
- method: finalMethod,
92
- headers: {
93
- ...getCSRFHeaders(),
94
- 'Content-Type': 'application/json',
95
- Accept: 'application/json',
96
- },
97
- body: finalBody !== null ? JSON.stringify(finalBody) : null,
98
- })
99
- .then(getResponseAndDataObject)
100
- .then(responseObject => throwResponseError(responseObject))
101
- .catch(error => throwValidationError(error));
102
- }
103
-
104
- getActionPath(action, id = undefined) {
105
- const { urlGenerator, resource } = this;
106
- const { idParamName, host } = this.options;
107
- const path = urlGenerator.resource(resource, action, id);
108
- const idPattern = new RegExp(`:${idParamName}([/](.*)?)?$`, 'i');
109
- const fullPath = trimEnd(host, '/') + path;
110
- return fullPath.replace(idPattern, id);
111
- }
112
- }
113
-
114
- export default ResourceApi;
@@ -1,55 +0,0 @@
1
- import reduce from 'lodash/reduce';
2
-
3
- class UrlGenerator {
4
- constructor(routes, opts) {
5
- this.routes = routes;
6
- this.options = {
7
- paramFormat: ':{key}(\\([^\\)]*\\))?', // eslint-disable-line
8
- ...opts,
9
- };
10
- }
11
-
12
- route(key, opts) {
13
- const options = {
14
- withHost: false,
15
- ...this.options,
16
- ...opts,
17
- };
18
- const { withHost, paramFormat, ...params } = options;
19
- const route = this.routes[key] || key;
20
- const url = reduce(
21
- params || {},
22
- (str, v, k) =>
23
- (v || null) !== null
24
- ? str.replace(new RegExp(paramFormat.replace(/\{\s*key\s*\}/gi, k), 'i'), v)
25
- : str,
26
- route,
27
- );
28
-
29
- const host =
30
- typeof window !== 'undefined'
31
- ? `${window.location.protocol}//${window.location.host}`
32
- : '';
33
- const hostPattern = host !== null ? `^${host}` : '^$';
34
- if (typeof withHost !== 'undefined' && withHost === true) {
35
- return !url.match(hostPattern) ? `${host}${url}` : url;
36
- }
37
-
38
- const urlWithoutHost = url.replace(new RegExp(hostPattern, 'i'), '');
39
- return urlWithoutHost === '' ? '/' : urlWithoutHost;
40
- }
41
-
42
- resource(resource, action, id = null) {
43
- const resourceId = resource !== null ? resource.id() : null;
44
- return resource !== null && resource.hasRoutes()
45
- ? this.route(`resource.${resourceId}.${action}`, {
46
- id,
47
- })
48
- : this.route(`resource.${action}`, {
49
- resource: resourceId,
50
- id,
51
- });
52
- }
53
- }
54
-
55
- export default UrlGenerator;
@@ -1,120 +0,0 @@
1
- /* eslint-disable max-classes-per-file */
2
- import Cookies from 'js-cookie';
3
-
4
- export class ResponseError extends Error {
5
- constructor(message, responseData, status) {
6
- super(message);
7
- this.name = 'ResponseError';
8
- this.responseData = responseData;
9
- this.status = status;
10
- }
11
-
12
- getResponseData() {
13
- return this.responseData;
14
- }
15
- }
16
-
17
- export class ValidationError extends ResponseError {
18
- constructor(message, responseData, status) {
19
- super(message, responseData, status);
20
- this.name = 'ValidationError';
21
- }
22
-
23
- getErrors() {
24
- return this.responseData;
25
- }
26
- }
27
-
28
- export const getResponseAndDataObject = response =>
29
- response.json().then(data => ({
30
- data,
31
- response,
32
- }));
33
-
34
- export const getErrorsFromResponseError = error => {
35
- const { name, responseData = {}, message = null } = error;
36
- if (name === 'ValidationError') {
37
- return responseData.errors || responseData;
38
- }
39
- if (name === 'ResponseError') {
40
- return responseData.error || responseData;
41
- }
42
- return message;
43
- };
44
-
45
- export const throwResponseError = responseObject => {
46
- const { response, data } = responseObject;
47
- if (response.status >= 200 && response.status < 300) {
48
- return data;
49
- }
50
- throw new ResponseError(response.statusText, data, response.status);
51
- };
52
-
53
- export const throwValidationError = error => {
54
- if (error.name === 'ResponseError' && error.status === 422) {
55
- throw new ValidationError(error.message, error.responseData, error.status);
56
- }
57
- throw error;
58
- };
59
-
60
- export const getJSON = (url, opts) => {
61
- const { headers, ...options } = opts || {};
62
- return fetch(url, {
63
- method: 'GET',
64
- headers: {
65
- Accept: 'application/json',
66
- ...(headers || null),
67
- },
68
- ...(options || null),
69
- })
70
- .then(getResponseAndDataObject)
71
- .then(throwResponseError);
72
- };
73
-
74
- export const postJSON = (url, data, opts) => {
75
- const { headers, ...options } = opts || {};
76
- return fetch(url, {
77
- method: 'POST',
78
- headers: {
79
- 'Content-Type': 'application/json',
80
- Accept: 'application/json',
81
- ...(headers || null),
82
- },
83
- body: JSON.stringify(data),
84
- ...(options || null),
85
- })
86
- .then(getResponseAndDataObject)
87
- .then(throwResponseError)
88
- .catch(throwValidationError);
89
- };
90
-
91
- export const getXSRFToken = () => {
92
- const cookies = Cookies.get();
93
- return cookies['X-XSRF-TOKEN'] || null;
94
- };
95
-
96
- const getCsrfToken = name => {
97
- const metaName = name || 'csrf-token';
98
- const metas = [].slice.call(document.getElementsByTagName('meta'));
99
- return metas.reduce(
100
- (val, meta) =>
101
- meta.getAttribute('name') === metaName ? meta.getAttribute('content') : val,
102
- null,
103
- );
104
- };
105
-
106
- export const getCSRFHeaders = name => {
107
- const XSRF = getXSRFToken();
108
- if (XSRF !== null) {
109
- return {
110
- 'X-XSRF-TOKEN': XSRF,
111
- };
112
- }
113
- const CSRF = getCsrfToken(name);
114
- if (CSRF !== null) {
115
- return {
116
- 'X-CSRF-TOKEN': CSRF,
117
- };
118
- }
119
- return null;
120
- };
@@ -1,20 +0,0 @@
1
- import { useMemo } from 'react';
2
- import isObject from 'lodash/isObject';
3
-
4
- import ResourceApi from './ResourceApi';
5
- import { useDefinition } from '../contexts/Definition';
6
- import { useUrlGenerator } from '../contexts/UrlGenerator';
7
-
8
- const useResourceApi = resourceId => {
9
- const definition = useDefinition();
10
- const urlGenerator = useUrlGenerator();
11
- const api = useMemo(() => {
12
- const resource = isObject(resourceId) ? resourceId : definition.resource(resourceId);
13
- return new ResourceApi(resource, urlGenerator, {
14
- host: definition.apiEndpoint(),
15
- });
16
- }, [resourceId, definition, urlGenerator]);
17
- return api;
18
- };
19
-
20
- export default useResourceApi;
package/src/lib/utils.js DELETED
@@ -1,13 +0,0 @@
1
- import isString from 'lodash/isString';
2
- import isObject from 'lodash/isObject';
3
-
4
- export const getLocalizedName = (definition, variant = 'default') => {
5
- const { name, messages = {} } = definition;
6
- const { name: nameMessages = {} } = messages;
7
- if (isString(nameMessages)) {
8
- return nameMessages;
9
- }
10
- return nameMessages[variant] || name;
11
- };
12
-
13
- export const isMessage = str => isObject(str) && typeof str.id !== 'undefined';
package/src/requests.js DELETED
@@ -1 +0,0 @@
1
- export * from './lib/requests';
@@ -1,10 +0,0 @@
1
- .container {
2
- &.noWrap {
3
- white-space: nowrap;
4
-
5
- .button {
6
- display: inline-block;
7
- float: none;
8
- }
9
- }
10
- }
@@ -1,5 +0,0 @@
1
- @import '../variables';
2
-
3
- .container {
4
- position: relative;
5
- }
@@ -1,36 +0,0 @@
1
- .component {
2
- .dot {
3
- display: inline-block;
4
- border-radius: 100%;
5
- animation-name: pulse;
6
- animation-duration: .75s;
7
- animation-iteration-count: infinite;
8
- animation-timing-function: cubic-bezier(.2, .68, .18, 1.08);
9
- animation-fill-mode: both;
10
-
11
- &:nth-child(2) {
12
- animation-delay: .12s;
13
- }
14
-
15
- &:nth-child(3) {
16
- animation-delay: .24s;
17
- }
18
- }
19
- }
20
-
21
- @keyframes pulse {
22
- 0% {
23
- transform: scale(1);
24
- opacity: 1;
25
- }
26
-
27
- 45% {
28
- transform: scale(.1);
29
- opacity: .7;
30
- }
31
-
32
- 80% {
33
- transform: scale(1);
34
- opacity: 1;
35
- }
36
- }
@@ -1,5 +0,0 @@
1
- @import '~bootstrap/scss/functions';
2
- @import '~bootstrap/scss/variables';
3
-
4
- $fa-font-path: '~@fortawesome/fontawesome-free/webfonts';
5
- @import '~@fortawesome/fontawesome-free/scss/variables';
package/src/utils.js DELETED
@@ -1 +0,0 @@
1
- export * from './lib/utils';