react-admin-base-bootstrap 0.9.3 → 0.9.5

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/bun.lockb CHANGED
Binary file
@@ -14,6 +14,7 @@ export interface ApiSelectProps<Option = any> {
14
14
  disabled?: boolean;
15
15
  placeholder?: string;
16
16
  staticOptions?: any[];
17
+ sortable?: boolean;
17
18
  onAddOrEdit?: (item: any) => void;
18
19
  getNewOptionData?: (name: string, elem: React.ReactNode) => any | null;
19
20
  }
@@ -12,6 +12,12 @@ import { RefreshScope, useFetch, useRefresh } from 'react-admin-base';
12
12
  import { FormattedMessage, useIntl } from 'react-intl';
13
13
  import Select, { components } from "react-select";
14
14
  import CreatableSelect from 'react-select/creatable';
15
+ import { SortableContainer, SortableElement, SortableHandle, } from 'react-sortable-hoc';
16
+ function arrayMove(array, from, to) {
17
+ const slicedArray = array.slice();
18
+ slicedArray.splice(to < 0 ? array.length + to : to, 0, slicedArray.splice(from, 1)[0]);
19
+ return slicedArray;
20
+ }
15
21
  function Option(props) {
16
22
  return React.createElement(components.Option, Object.assign({}, props), (props.selectProps.children && props.selectProps.children(props.data)) || (props.data.__isNew__ ? React.createElement(FormattedMessage, { id: "CREATE_VALUE", values: { text: props.children } }) : props.children));
17
23
  }
@@ -47,8 +53,20 @@ function MultiValueRemove(props) {
47
53
  React.createElement(components.MultiValueRemove, Object.assign({}, props)));
48
54
  }
49
55
  const Components = { Option, SingleValue, MultiValue, IndicatorsContainer, MultiValueRemove };
56
+ const SortableMultiValue = SortableElement((props) => {
57
+ const onMouseDown = (e) => {
58
+ e.preventDefault();
59
+ e.stopPropagation();
60
+ };
61
+ const innerProps = Object.assign(Object.assign({}, props.innerProps), { onMouseDown });
62
+ return React.createElement(MultiValue, Object.assign({}, props, { innerProps: innerProps }));
63
+ });
64
+ const SortableMultiValueLabel = SortableHandle((props) => React.createElement(components.MultiValueLabel, Object.assign({}, props)));
65
+ const SortableComponents = { Option, SingleValue, MultiValue: SortableMultiValue, MultiValueLabel: SortableMultiValueLabel, IndicatorsContainer, MultiValueRemove };
66
+ const SortableSelect = SortableContainer(Select);
67
+ const SortableCreateableSelect = SortableContainer(CreatableSelect);
50
68
  export default function ApiSelect(props) {
51
- const { disabled, url, getOptionLabel, getOptionValue, idKey, nameKey, filter, group, onCreateOption, getNewOptionData, isMulti, onChange, value, placeholder, staticOptions } = props;
69
+ const { disabled, url, getOptionLabel, sortable, getOptionValue, idKey, nameKey, filter, group, onCreateOption, getNewOptionData, isMulti, onChange, value, placeholder, staticOptions } = props;
52
70
  const intl = useIntl();
53
71
  const [search, setSearch] = useState('');
54
72
  const params = useMemo(() => ({ query: search }), [search]);
@@ -86,9 +104,13 @@ export default function ApiSelect(props) {
86
104
  const onMenuClose = useCallback(function () {
87
105
  setIsMenuOpen(false);
88
106
  }, [setIsMenuOpen]);
89
- const Component = onCreateOption ? CreatableSelect : Select;
107
+ const onSortEnd = useCallback(({ oldIndex, newIndex }) => {
108
+ const newValue = arrayMove(value, oldIndex, newIndex);
109
+ onChange(newValue);
110
+ }, [value, onChange]);
111
+ const Component = (onCreateOption ? (sortable && isMulti ? SortableCreateableSelect : CreatableSelect) : (sortable && isMulti ? SortableSelect : Select));
90
112
  return React.createElement(RefreshScope, { update: update },
91
- React.createElement(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 })));
113
+ React.createElement(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: (isMulti && sortable ? SortableComponents : 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, axis: "xy", onSortEnd: onSortEnd, distance: 4, getHelperDimensions: ({ node }) => node.getBoundingClientRect() })));
92
114
  }
93
115
  export function CreateSelect(props) {
94
116
  const { Component, onChange, value, isMulti, idKey } = props;
@@ -98,7 +98,7 @@ export function ModalEntityEditor({ entity, title, size, url, onReload, disabled
98
98
  ' ',
99
99
  React.createElement(FormattedMessage, { id: "ENTITY.SAVE" }))),
100
100
  React.createElement(Col, null,
101
- React.createElement(Button, { block: true, outline: true, color: "danger", onClick: (e) => { e.preventDefault(); (url ? setOpen(false) : onReload(null)); } },
101
+ React.createElement(Button, { type: "button", block: true, outline: true, color: "danger", onClick: onClose },
102
102
  React.createElement("i", { className: "fas fa-times-circle" }),
103
103
  ' ',
104
104
  React.createElement(FormattedMessage, { id: "ENTITY.CANCEL" })))))))));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-admin-base-bootstrap",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -38,12 +38,13 @@
38
38
  "modal-cropper": "^1.2.3",
39
39
  "nprogress": "^0.2.0",
40
40
  "prettysize": "^2.0.0",
41
- "react-admin-base": "^0.9.0",
41
+ "react-admin-base": "^0.9.1",
42
42
  "react-dnd": "^16.0.1",
43
43
  "react-dnd-html5-backend": "^16.0.1",
44
44
  "react-password-strength-bar": "^0.4.1",
45
45
  "react-responsive": "^9.0.2",
46
46
  "react-select": "^5.8.0",
47
+ "react-sortable-hoc": "^2.0.0",
47
48
  "reactstrap": "^9.2.2",
48
49
  "sweetalert2": "^11.10.4"
49
50
  },
@@ -5,6 +5,25 @@ import { FormattedMessage, useIntl } from 'react-intl';
5
5
  import Select, { components } from "react-select";
6
6
  import CreatableSelect from 'react-select/creatable';
7
7
 
8
+ import {
9
+ SortableContainer,
10
+ SortableContainerProps,
11
+ SortableElement,
12
+ SortEndHandler,
13
+ SortableHandle,
14
+ } from 'react-sortable-hoc';
15
+
16
+ function arrayMove<T>(array: readonly T[], from: number, to: number) {
17
+ const slicedArray = array.slice();
18
+ slicedArray.splice(
19
+ to < 0 ? array.length + to : to,
20
+ 0,
21
+ slicedArray.splice(from, 1)[0]
22
+ );
23
+ return slicedArray;
24
+ }
25
+
26
+
8
27
  function Option(props) {
9
28
  return <components.Option {...props}>
10
29
  { (props.selectProps.children && props.selectProps.children(props.data)) || (props.data.__isNew__ ? <FormattedMessage
@@ -42,7 +61,7 @@ function EditOrAddIndicator(props) {
42
61
  className
43
62
  )}
44
63
  css={getStyles('clearIndicator', props)}
45
- onMouseDown={e => {
64
+ onMouseDown={e => {
46
65
  e.stopPropagation();
47
66
  e.preventDefault();
48
67
  props.selectProps.onAddOrEdit();
@@ -73,6 +92,26 @@ function MultiValueRemove(props) {
73
92
 
74
93
  const Components = { Option, SingleValue, MultiValue, IndicatorsContainer, MultiValueRemove };
75
94
 
95
+ const SortableMultiValue = SortableElement(
96
+ (props) => {
97
+ const onMouseDown = (e) => {
98
+ e.preventDefault();
99
+ e.stopPropagation();
100
+ };
101
+ const innerProps = { ...props.innerProps, onMouseDown };
102
+ return <MultiValue {...props} innerProps={innerProps} />;
103
+ }
104
+ );
105
+
106
+ const SortableMultiValueLabel = SortableHandle(
107
+ (props) => <components.MultiValueLabel {...props} />
108
+ );
109
+
110
+ const SortableComponents = { Option, SingleValue, MultiValue: SortableMultiValue, MultiValueLabel: SortableMultiValueLabel, IndicatorsContainer, MultiValueRemove };
111
+
112
+ const SortableSelect = SortableContainer(Select);
113
+ const SortableCreateableSelect = SortableContainer(CreatableSelect);
114
+
76
115
  export interface ApiSelectProps<Option = any> {
77
116
  url?: string;
78
117
  value: Option|Option[];
@@ -88,12 +127,14 @@ export interface ApiSelectProps<Option = any> {
88
127
  disabled?: boolean;
89
128
  placeholder?: string;
90
129
  staticOptions?: any[];
130
+ sortable?: boolean;
91
131
  onAddOrEdit?: (item: any) => void;
92
132
  getNewOptionData?: (name: string, elem: React.ReactNode) => any|null;
93
133
  }
94
134
 
135
+
95
136
  export default function ApiSelect<Option = any>(props: ApiSelectProps<Option>) {
96
- const { disabled, url, getOptionLabel, getOptionValue, idKey, nameKey, filter, group, onCreateOption, getNewOptionData, isMulti, onChange, value, placeholder, staticOptions } = props;
137
+ const { disabled, url, getOptionLabel, sortable, getOptionValue, idKey, nameKey, filter, group, onCreateOption, getNewOptionData, isMulti, onChange, value, placeholder, staticOptions } = props;
97
138
  const intl = useIntl();
98
139
  const [ search, setSearch ] = useState('');
99
140
  const params = useMemo(() => ({ query: search }), [search]);
@@ -133,18 +174,23 @@ export default function ApiSelect<Option = any>(props: ApiSelectProps<Option>) {
133
174
  setIsMenuOpen(false);
134
175
  }, [ setIsMenuOpen ]);
135
176
 
136
- const Component = onCreateOption ? CreatableSelect : Select;
177
+ const onSortEnd: SortEndHandler = useCallback(({ oldIndex, newIndex }) => {
178
+ const newValue = arrayMove(value as any, oldIndex, newIndex);
179
+ onChange(newValue as any);
180
+ }, [ value, onChange ]);
181
+
182
+ const Component = (onCreateOption ? (sortable && isMulti ? SortableCreateableSelect : CreatableSelect) : (sortable && isMulti ? SortableSelect : Select)) as any;
137
183
 
138
184
  return <RefreshScope update={update}>
139
185
  <Component
140
186
  {...props}
141
187
  className='react-select-container'
142
188
  classNamePrefix="react-select"
143
- onCreateOption={onCreateOption && handleCreateOption}
189
+ onCreateOption={(onCreateOption && handleCreateOption) as any}
144
190
  getNewOptionData={(onCreateOption && (getNewOptionData || ((inputValue) =>( { [nameKey || 'name']: inputValue, __isNew__: true })))) || undefined}
145
191
  inputValue={search}
146
192
  onInputChange={a => setSearch(a)}
147
- components={Components}
193
+ components={(isMulti && sortable ? SortableComponents : Components) as any}
148
194
  isLoading={!!loading || creating}
149
195
  getOptionLabel={getOptionLabel || ((row:any) => row[nameKey || 'name'])}
150
196
  getOptionValue={getOptionValue || ((row:any) => row[idKey || 'id'])}
@@ -155,6 +201,11 @@ export default function ApiSelect<Option = any>(props: ApiSelectProps<Option>) {
155
201
  options={!options ? [] : ((filter && options.filter(filter)) || options)}
156
202
  onMenuOpen={onMenuOpen}
157
203
  onMenuClose={onMenuClose}
204
+
205
+ axis="xy"
206
+ onSortEnd={onSortEnd}
207
+ distance={4}
208
+ getHelperDimensions={({ node }) => node.getBoundingClientRect()}
158
209
  />
159
210
  </RefreshScope>;
160
211
  }
@@ -97,7 +97,7 @@ export function ModalEntityEditor({ entity, title, size, url, onReload, disabled
97
97
  </LoadingButton>
98
98
  </Col>
99
99
  <Col>
100
- <Button block outline color="danger" onClick={(e) => { e.preventDefault(); (url ? setOpen(false) : onReload(null)); }}>
100
+ <Button type="button" block outline color="danger" onClick={onClose}>
101
101
  <i className="fas fa-times-circle" />{' '}<FormattedMessage id="ENTITY.CANCEL" />
102
102
  </Button>
103
103
  </Col>