react-admin-base-bootstrap 0.8.9 → 0.8.10

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.
@@ -16,6 +16,11 @@ export interface ApiSelectProps<Option = any> {
16
16
  disabled?: boolean;
17
17
  placeholder?: string;
18
18
  staticOptions?: any[];
19
+ onAddOrEdit?: (item: any) => void;
19
20
  getNewOptionData?: (name: string, elem: React.ReactNode) => any | null;
20
21
  }
21
22
  export default function ApiSelect<Option = any>(props: ApiSelectProps<Option>): jsx.JSX.Element;
23
+ export interface CreateSelectProps<Option = any> extends ApiSelectProps<Option> {
24
+ Component: any;
25
+ }
26
+ export declare function CreateSelect(props: CreateSelectProps): jsx.JSX.Element;
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  /** @jsx jsx */
11
11
  import { jsx } from '@emotion/react';
12
- import React, { useCallback, useMemo, useState } from 'react';
13
- import { useFetch } from 'react-admin-base';
12
+ import React, { Fragment, useCallback, useMemo, useState } from 'react';
13
+ import { RefreshScope, useFetch, useRefresh } from 'react-admin-base';
14
14
  import { FormattedMessage, useIntl } from 'react-intl';
15
15
  import Select, { components } from "react-select";
16
16
  import CreatableSelect from 'react-select/creatable';
@@ -21,7 +21,7 @@ function SingleValue(props) {
21
21
  return jsx(components.SingleValue, Object.assign({}, props), (props.selectProps.children && props.selectProps.children(props.data)) || (props.data.__isNew__ ? jsx(FormattedMessage, { id: "CREATE_VALUE", values: { text: props.children } }) : props.children));
22
22
  }
23
23
  function EditOrAddIndicator(props) {
24
- const { className, cx, getStyles, innerProps } = props;
24
+ const { className, cx, getStyles, innerProps, isMulti } = props;
25
25
  return (jsx("div", Object.assign({}, innerProps, { className: cx({
26
26
  indicator: true,
27
27
  'clear-indicator': true
@@ -30,7 +30,7 @@ function EditOrAddIndicator(props) {
30
30
  e.preventDefault();
31
31
  props.selectProps.onAddOrEdit();
32
32
  } }),
33
- jsx("i", { className: "fas " + (props.hasValue ? 'fa-pencil-alt' : 'fa-plus') })));
33
+ jsx("i", { className: "fas " + (props.hasValue && !isMulti ? 'fa-pencil-alt' : 'fa-plus') })));
34
34
  }
35
35
  function IndicatorsContainer(props) {
36
36
  return jsx(components.IndicatorsContainer, Object.assign({}, props),
@@ -39,7 +39,13 @@ function IndicatorsContainer(props) {
39
39
  jsx(components.IndicatorSeparator, Object.assign({}, props))),
40
40
  props.children);
41
41
  }
42
- const Components = { Option, SingleValue, IndicatorsContainer };
42
+ function MultiValueRemove(props) {
43
+ return jsx(Fragment, null,
44
+ props.selectProps.onAddOrEdit && jsx(components.MultiValueRemove, Object.assign({}, props, { innerProps: Object.assign(Object.assign({}, props.innerProps), { onClick: () => props.selectProps.onAddOrEdit(props.data) }) }),
45
+ jsx("i", { className: "fas fa-pencil", style: { fontSize: '.75em' } })),
46
+ jsx(components.MultiValueRemove, Object.assign({}, props)));
47
+ }
48
+ const Components = { Option, SingleValue, IndicatorsContainer, MultiValueRemove };
43
49
  export default function ApiSelect(props) {
44
50
  const { disabled, url, getOptionLabel, getOptionValue, idKey, nameKey, filter, group, onCreateOption, getNewOptionData, isMulti, onChange, value, placeholder, staticOptions } = props;
45
51
  const intl = useIntl();
@@ -47,7 +53,7 @@ export default function ApiSelect(props) {
47
53
  const params = useMemo(() => ({ query: search }), [search]);
48
54
  const [isMenuOpen, setIsMenuOpen] = useState(false);
49
55
  const [hasMenuOpen, setHasMenuOpen] = useState(false);
50
- const [data, loading] = useFetch((hasMenuOpen && url) || false, params);
56
+ const [data, loading, error, update] = useFetch((isMenuOpen && url) || false, params);
51
57
  const [creating, setCreating] = useState(false);
52
58
  let options = staticOptions || (data && data.data) || data;
53
59
  if (group) {
@@ -80,5 +86,20 @@ export default function ApiSelect(props) {
80
86
  setIsMenuOpen(false);
81
87
  }, [setIsMenuOpen]);
82
88
  const Component = onCreateOption ? CreatableSelect : Select;
83
- return jsx(Component, Object.assign({}, props, { className: 'react-select-container', classNamePrefix: "react-select", onCreateOption: onCreateOption && handleCreateOption, getNewOptionData: (onCreateOption && (getNewOptionData || ((inputValue) => ({ [nameKey || 'name']: inputValue, __isNew__: true })))) || undefined, inputValue: search, onInputChange: a => setSearch(a), components: Components, isLoading: !!loading || creating, getOptionLabel: getOptionLabel || ((row) => row[nameKey || 'name']), getOptionValue: getOptionValue || ((row) => row[idKey || 'id']), isDisabled: !!disabled || creating, isClearable: true, isSearchable: true, placeholder: placeholder || intl.formatMessage({ id: 'SELECT' }), options: !options ? [] : ((filter && options.filter(filter)) || options), onMenuOpen: onMenuOpen, onMenuClose: onMenuClose }));
89
+ return jsx(RefreshScope, { update: update },
90
+ jsx(Component, Object.assign({}, props, { className: 'react-select-container', classNamePrefix: "react-select", onCreateOption: onCreateOption && handleCreateOption, getNewOptionData: (onCreateOption && (getNewOptionData || ((inputValue) => ({ [nameKey || 'name']: inputValue, __isNew__: true })))) || undefined, inputValue: search, onInputChange: a => setSearch(a), components: Components, isLoading: !!loading || creating, getOptionLabel: getOptionLabel || ((row) => row[nameKey || 'name']), getOptionValue: getOptionValue || ((row) => row[idKey || 'id']), isDisabled: !!disabled || creating, isClearable: true, isSearchable: true, placeholder: placeholder || intl.formatMessage({ id: 'SELECT' }), options: !options ? [] : ((filter && options.filter(filter)) || options), onMenuOpen: onMenuOpen, onMenuClose: onMenuClose })));
91
+ }
92
+ export function CreateSelect(props) {
93
+ const { Component, onChange, value, isMulti, idKey } = props;
94
+ const update = useRefresh();
95
+ const [isOpen, setIsOpen] = useState(false);
96
+ const isOpenId = isOpen && isOpen[idKey || "id"];
97
+ const onReload = useCallback(function (data) {
98
+ setIsOpen(false);
99
+ data && onChange(isMulti ? isOpenId ? value.map(b => b.id === isOpenId ? data : b) : (value || []).concat([data]) : data);
100
+ update && update();
101
+ }, [value, onChange, isMulti, isOpenId, isOpen, update, setIsOpen]);
102
+ return jsx(Fragment, null,
103
+ isOpen && jsx(Component, { id: isOpenId || (!isMulti && value && value["idKey"]), onReload: onReload }),
104
+ jsx(ApiSelect, Object.assign({}, props, { onAddOrEdit: item => setIsOpen(item || true) })));
84
105
  }
@@ -5,7 +5,7 @@ import ExcelExportButton from './Components/ExcelExportButton';
5
5
  import ExternalLoginButton from './Components/ExternalLoginButton';
6
6
  import GoToTop from "./Components/GoToTop";
7
7
  import { ValidationErrors, Validator, ValueValidator } from "./Components/Validator";
8
- import ApiSelect from "./Components/ApiSelect";
8
+ import ApiSelect, { CreateSelect } from "./Components/ApiSelect";
9
9
  import { Preview, Relative } from './Components/FilePickerCore';
10
10
  import ImagePicker from './Components/ImagePicker';
11
11
  import LoadingButton from './Components/LoadingButton';
@@ -23,4 +23,4 @@ import DefaultValidatorOptions from './Components/DefaultValidatorOptions';
23
23
  import DragAndDropArrow from './Components/DragAndDropArrow';
24
24
  import BootstrapOptionsProvider, { useBootstrapOptions } from './Components/BootstrapOptions';
25
25
  import BootstrapModal from './Components/BootstrapModal';
26
- export { ThemeProvider, useTheme, useAllThemes, useIsMobile, useMenuState, DefaultValidatorOptions, PasswordInput, StepList, StepItem, TopProgressBar, CRUD, ModalEntityEditor, CRUDActions, Relative, ApiSelect, Preview, ExcelExportButton, ExternalLoginButton, SingleFilePicker, MultiFilePicker, ImagePicker, BootstrapTable, EntityEditor, GoToTop, Validator, ValueValidator, ValidationErrors, LoadingButton, BootstrapDataTable, IdColumn, Column, ActionsColumn, Actions, useDataTableContext, RowRenderer, CustomRenderer, LanguageProvider, useLanguage, LanguageSwitcher, ErrorBoundary, CheckBox, DragAndDropArrow, useBootstrapOptions, BootstrapOptionsProvider, BootstrapModal };
26
+ export { ThemeProvider, useTheme, useAllThemes, useIsMobile, useMenuState, DefaultValidatorOptions, PasswordInput, StepList, StepItem, TopProgressBar, CRUD, ModalEntityEditor, CRUDActions, Relative, ApiSelect, Preview, ExcelExportButton, ExternalLoginButton, SingleFilePicker, MultiFilePicker, ImagePicker, BootstrapTable, EntityEditor, GoToTop, Validator, ValueValidator, ValidationErrors, LoadingButton, BootstrapDataTable, IdColumn, Column, ActionsColumn, Actions, useDataTableContext, RowRenderer, CustomRenderer, LanguageProvider, useLanguage, LanguageSwitcher, ErrorBoundary, CheckBox, DragAndDropArrow, useBootstrapOptions, BootstrapOptionsProvider, BootstrapModal, CreateSelect };
package/lib/esm/index.js CHANGED
@@ -5,7 +5,7 @@ import ExcelExportButton from './Components/ExcelExportButton';
5
5
  import ExternalLoginButton from './Components/ExternalLoginButton';
6
6
  import GoToTop from "./Components/GoToTop";
7
7
  import { ValidationErrors, Validator, ValueValidator } from "./Components/Validator";
8
- import ApiSelect from "./Components/ApiSelect";
8
+ import ApiSelect, { CreateSelect } from "./Components/ApiSelect";
9
9
  import { Preview, Relative } from './Components/FilePickerCore';
10
10
  import ImagePicker from './Components/ImagePicker';
11
11
  import LoadingButton from './Components/LoadingButton';
@@ -23,4 +23,4 @@ import DefaultValidatorOptions from './Components/DefaultValidatorOptions';
23
23
  import DragAndDropArrow from './Components/DragAndDropArrow';
24
24
  import BootstrapOptionsProvider, { useBootstrapOptions } from './Components/BootstrapOptions';
25
25
  import BootstrapModal from './Components/BootstrapModal';
26
- export { ThemeProvider, useTheme, useAllThemes, useIsMobile, useMenuState, DefaultValidatorOptions, PasswordInput, StepList, StepItem, TopProgressBar, CRUD, ModalEntityEditor, CRUDActions, Relative, ApiSelect, Preview, ExcelExportButton, ExternalLoginButton, SingleFilePicker, MultiFilePicker, ImagePicker, BootstrapTable, EntityEditor, GoToTop, Validator, ValueValidator, ValidationErrors, LoadingButton, BootstrapDataTable, IdColumn, Column, ActionsColumn, Actions, useDataTableContext, RowRenderer, CustomRenderer, LanguageProvider, useLanguage, LanguageSwitcher, ErrorBoundary, CheckBox, DragAndDropArrow, useBootstrapOptions, BootstrapOptionsProvider, BootstrapModal };
26
+ export { ThemeProvider, useTheme, useAllThemes, useIsMobile, useMenuState, DefaultValidatorOptions, PasswordInput, StepList, StepItem, TopProgressBar, CRUD, ModalEntityEditor, CRUDActions, Relative, ApiSelect, Preview, ExcelExportButton, ExternalLoginButton, SingleFilePicker, MultiFilePicker, ImagePicker, BootstrapTable, EntityEditor, GoToTop, Validator, ValueValidator, ValidationErrors, LoadingButton, BootstrapDataTable, IdColumn, Column, ActionsColumn, Actions, useDataTableContext, RowRenderer, CustomRenderer, LanguageProvider, useLanguage, LanguageSwitcher, ErrorBoundary, CheckBox, DragAndDropArrow, useBootstrapOptions, BootstrapOptionsProvider, BootstrapModal, CreateSelect };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-admin-base-bootstrap",
3
- "version": "0.8.9",
3
+ "version": "0.8.10",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -1,7 +1,7 @@
1
1
  /** @jsx jsx */
2
2
  import { jsx } from '@emotion/react';
3
- import React, { useCallback, useMemo, useState } from 'react';
4
- import { useFetch } from 'react-admin-base';
3
+ import React, {Fragment, useCallback, useMemo, useState} from 'react';
4
+ import {RefreshScope, useFetch, useRefresh} from 'react-admin-base';
5
5
  import { FormattedMessage, useIntl } from 'react-intl';
6
6
  import Select, { components } from "react-select";
7
7
  import CreatableSelect from 'react-select/creatable';
@@ -25,8 +25,7 @@ function SingleValue(props) {
25
25
  }
26
26
 
27
27
  function EditOrAddIndicator(props) {
28
- const { className, cx, getStyles, innerProps } = props;
29
-
28
+ const { className, cx, getStyles, innerProps, isMulti } = props;
30
29
  return (
31
30
  <div
32
31
  {...innerProps}
@@ -44,7 +43,7 @@ function EditOrAddIndicator(props) {
44
43
  props.selectProps.onAddOrEdit();
45
44
  }}
46
45
  >
47
- <i className={"fas " + (props.hasValue ? 'fa-pencil-alt' : 'fa-plus')} />
46
+ <i className={"fas " + (props.hasValue && !isMulti ? 'fa-pencil-alt' : 'fa-plus')} />
48
47
  </div>);
49
48
  }
50
49
 
@@ -58,7 +57,16 @@ function IndicatorsContainer(props) {
58
57
  </components.IndicatorsContainer>;
59
58
  }
60
59
 
61
- const Components = { Option, SingleValue, IndicatorsContainer };
60
+ function MultiValueRemove(props) {
61
+ return <Fragment>
62
+ { props.selectProps.onAddOrEdit && <components.MultiValueRemove {...props} innerProps={{ ...props.innerProps, onClick: () => props.selectProps.onAddOrEdit(props.data) }}>
63
+ <i className="fas fa-pencil" style={{ fontSize: '.75em' }} />
64
+ </components.MultiValueRemove> }
65
+ <components.MultiValueRemove {...props} />
66
+ </Fragment>;
67
+ }
68
+
69
+ const Components = { Option, SingleValue, IndicatorsContainer, MultiValueRemove };
62
70
 
63
71
  export interface ApiSelectProps<Option = any> {
64
72
  url?: string;
@@ -75,6 +83,7 @@ export interface ApiSelectProps<Option = any> {
75
83
  disabled?: boolean;
76
84
  placeholder?: string;
77
85
  staticOptions?: any[];
86
+ onAddOrEdit?: (item: any) => void;
78
87
  getNewOptionData?: (name: string, elem: React.ReactNode) => any|null;
79
88
  }
80
89
 
@@ -85,7 +94,7 @@ export default function ApiSelect<Option = any>(props: ApiSelectProps<Option>) {
85
94
  const params = useMemo(() => ({ query: search }), [search]);
86
95
  const [ isMenuOpen, setIsMenuOpen ] = useState(false);
87
96
  const [ hasMenuOpen, setHasMenuOpen ] = useState(false);
88
- const [ data, loading ] = useFetch((hasMenuOpen && url) || false, params);
97
+ const [ data, loading, error, update ] = useFetch((isMenuOpen && url) || false, params);
89
98
  const [ creating, setCreating ] = useState(false);
90
99
 
91
100
  let options = staticOptions || (data && data.data) || data;
@@ -121,24 +130,49 @@ export default function ApiSelect<Option = any>(props: ApiSelectProps<Option>) {
121
130
 
122
131
  const Component = onCreateOption ? CreatableSelect : Select;
123
132
 
124
- return <Component
125
- {...props}
126
- className='react-select-container'
127
- classNamePrefix="react-select"
128
- onCreateOption={onCreateOption && handleCreateOption}
129
- getNewOptionData={(onCreateOption && (getNewOptionData || ((inputValue) =>( { [nameKey || 'name']: inputValue, __isNew__: true })))) || undefined}
130
- inputValue={search}
131
- onInputChange={a => setSearch(a)}
132
- components={Components}
133
- isLoading={!!loading || creating}
134
- getOptionLabel={getOptionLabel || ((row:any) => row[nameKey || 'name'])}
135
- getOptionValue={getOptionValue || ((row:any) => row[idKey || 'id'])}
136
- isDisabled={!!disabled || creating}
137
- isClearable
138
- isSearchable
139
- placeholder={placeholder || intl.formatMessage({ id: 'SELECT' })}
140
- options={!options ? [] : ((filter && options.filter(filter)) || options)}
141
- onMenuOpen={onMenuOpen}
142
- onMenuClose={onMenuClose}
143
- />;
133
+ return <RefreshScope update={update}>
134
+ <Component
135
+ {...props}
136
+ className='react-select-container'
137
+ classNamePrefix="react-select"
138
+ onCreateOption={onCreateOption && handleCreateOption}
139
+ getNewOptionData={(onCreateOption && (getNewOptionData || ((inputValue) =>( { [nameKey || 'name']: inputValue, __isNew__: true })))) || undefined}
140
+ inputValue={search}
141
+ onInputChange={a => setSearch(a)}
142
+ components={Components}
143
+ isLoading={!!loading || creating}
144
+ getOptionLabel={getOptionLabel || ((row:any) => row[nameKey || 'name'])}
145
+ getOptionValue={getOptionValue || ((row:any) => row[idKey || 'id'])}
146
+ isDisabled={!!disabled || creating}
147
+ isClearable
148
+ isSearchable
149
+ placeholder={placeholder || intl.formatMessage({ id: 'SELECT' })}
150
+ options={!options ? [] : ((filter && options.filter(filter)) || options)}
151
+ onMenuOpen={onMenuOpen}
152
+ onMenuClose={onMenuClose}
153
+ />
154
+ </RefreshScope>;
155
+ }
156
+
157
+ export interface CreateSelectProps<Option = any> extends ApiSelectProps<Option> {
158
+ Component: any;
159
+ }
160
+
161
+ export function CreateSelect(props: CreateSelectProps) {
162
+ const { Component, onChange, value, isMulti, idKey } = props;
163
+
164
+ const update = useRefresh();
165
+ const [ isOpen, setIsOpen ] = useState<any>(false);
166
+ const isOpenId = isOpen && isOpen[idKey || "id"];
167
+
168
+ const onReload = useCallback(function(data) {
169
+ setIsOpen(false);
170
+ data && onChange(isMulti ? isOpenId ? value.map(b => b.id === isOpenId ? data : b) : (value || []).concat([data]) : data);
171
+ update && update();
172
+ }, [value, onChange, isMulti, isOpenId, isOpen, update, setIsOpen]);
173
+
174
+ return <Fragment>
175
+ { isOpen && <Component id={isOpenId || (!isMulti && value && value["idKey"])} onReload={onReload} /> }
176
+ <ApiSelect {...props} onAddOrEdit={item => setIsOpen(item || true)} />
177
+ </Fragment>;
144
178
  }
package/src/index.ts CHANGED
@@ -6,7 +6,7 @@ import ExcelExportButton from './Components/ExcelExportButton';
6
6
  import ExternalLoginButton from './Components/ExternalLoginButton';
7
7
  import GoToTop from "./Components/GoToTop";
8
8
  import { ValidationErrors, Validator, ValueValidator } from "./Components/Validator";
9
- import ApiSelect from "./Components/ApiSelect";
9
+ import ApiSelect, { CreateSelect } from "./Components/ApiSelect";
10
10
  import { Preview, Relative } from './Components/FilePickerCore';
11
11
  import ImagePicker from './Components/ImagePicker';
12
12
  import LoadingButton from './Components/LoadingButton';
@@ -54,5 +54,6 @@ export {
54
54
  DragAndDropArrow,
55
55
  useBootstrapOptions,
56
56
  BootstrapOptionsProvider,
57
- BootstrapModal
57
+ BootstrapModal,
58
+ CreateSelect
58
59
  };