@plone/volto 19.0.0-alpha.31 → 19.0.0-alpha.33
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/AGENTS.md +47 -0
- package/CHANGELOG.md +27 -0
- package/README.md +0 -1
- package/package.json +11 -14
- package/src/actions/controlpanels/controlpanels.js +7 -12
- package/src/actions/controlpanels/controlpanels.test.js +2 -3
- package/src/components/manage/Contents/Contents.jsx +410 -323
- package/src/components/manage/Contents/Contents.test.jsx +1 -1
- package/src/components/manage/Contents/ContentsIndexHeader.jsx +47 -81
- package/src/components/manage/Contents/ContentsIndexHeader.test.jsx +10 -3
- package/src/components/manage/Contents/ContentsItem.jsx +226 -278
- package/src/components/manage/Contents/ContentsItem.test.jsx +10 -6
- package/src/components/manage/Controlpanels/ContentType.jsx +131 -222
- package/src/components/manage/Controlpanels/Controlpanel.jsx +122 -218
- package/src/components/manage/Controlpanels/Controlpanel.test.jsx +1 -29
- package/src/components/manage/Form/Field.jsx +1 -69
- package/src/components/manage/Form/Form.jsx +8 -0
- package/src/components/manage/Form/Form.test.jsx +130 -1
- package/src/components/manage/Widgets/ArrayWidget.jsx +111 -88
- package/src/components/manage/Widgets/ArrayWidget.test.jsx +0 -6
- package/src/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthIndexField.jsx +56 -50
- package/src/components/manage/Widgets/SelectStyling.jsx +52 -20
- package/src/config/Loadables.jsx +1 -5
- package/src/config/index.js +3 -0
- package/src/helpers/Utils/withSaveAsDraft.jsx +33 -9
- package/src/server.jsx +7 -1
- package/theme/themes/pastanaga/extras/contents.less +0 -4
- package/types/components/manage/Contents/Contents.d.ts +1 -1
- package/types/components/manage/Contents/ContentsIndexHeader.d.ts +6 -11
- package/types/components/manage/Contents/ContentsItem.d.ts +3 -10
- package/types/components/manage/Controlpanels/ContentType.d.ts +2 -2
- package/types/components/manage/Controlpanels/Controlpanel.d.ts +2 -5
- package/types/components/manage/Controlpanels/index.d.ts +2 -2
- package/types/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthIndexField.d.ts +22 -5
- package/types/components/manage/Widgets/SelectStyling.d.ts +1 -0
|
@@ -4,14 +4,47 @@ import configureStore from 'redux-mock-store';
|
|
|
4
4
|
import { Provider } from 'react-intl-redux';
|
|
5
5
|
import { MemoryRouter } from 'react-router-dom';
|
|
6
6
|
import Form from './Form';
|
|
7
|
+
import config from '@plone/volto/registry';
|
|
7
8
|
|
|
8
9
|
const mockStore = configureStore();
|
|
9
10
|
const errorMessage =
|
|
10
11
|
"[{'message': 'The specified email is not valid.', 'field': 'contact_email', 'error': 'ValidationError'}";
|
|
11
12
|
|
|
12
13
|
vi.mock('@plone/volto/components/manage/Form');
|
|
14
|
+
vi.mock('@plone/volto/helpers/Utils/withSaveAsDraft', async () => {
|
|
15
|
+
const React = await import('react');
|
|
16
|
+
const { default: config } = await import('@plone/volto/registry');
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
default: () => (WrappedComponent) =>
|
|
20
|
+
React.forwardRef((props, ref) =>
|
|
21
|
+
config.experimental?.saveAsDraft?.enabled ? (
|
|
22
|
+
<div data-autosave-wrapper="true">
|
|
23
|
+
<WrappedComponent
|
|
24
|
+
{...props}
|
|
25
|
+
checkSavedDraft={vi.fn()}
|
|
26
|
+
onSaveDraft={vi.fn()}
|
|
27
|
+
onCancelDraft={vi.fn()}
|
|
28
|
+
ref={ref}
|
|
29
|
+
/>
|
|
30
|
+
</div>
|
|
31
|
+
) : (
|
|
32
|
+
<WrappedComponent {...props} ref={ref} />
|
|
33
|
+
),
|
|
34
|
+
),
|
|
35
|
+
};
|
|
36
|
+
});
|
|
13
37
|
|
|
14
38
|
describe('Form', () => {
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
config.experimental = {
|
|
41
|
+
...(config.experimental || {}),
|
|
42
|
+
saveAsDraft: {
|
|
43
|
+
enabled: false,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
|
|
15
48
|
it('renders a form component', () => {
|
|
16
49
|
const store = mockStore({
|
|
17
50
|
intl: {
|
|
@@ -49,10 +82,106 @@ describe('Form', () => {
|
|
|
49
82
|
onCancel={() => {}}
|
|
50
83
|
/>
|
|
51
84
|
</MemoryRouter>
|
|
52
|
-
,
|
|
53
85
|
</Provider>,
|
|
54
86
|
);
|
|
55
87
|
const json = component.toJSON();
|
|
56
88
|
expect(json).toMatchSnapshot();
|
|
57
89
|
});
|
|
90
|
+
|
|
91
|
+
it('does not wrap the form with autosave when the experimental flag is disabled', () => {
|
|
92
|
+
const store = mockStore({
|
|
93
|
+
intl: {
|
|
94
|
+
locale: 'en',
|
|
95
|
+
messages: {},
|
|
96
|
+
},
|
|
97
|
+
content: {
|
|
98
|
+
data: {},
|
|
99
|
+
create: {
|
|
100
|
+
loading: false,
|
|
101
|
+
loaded: true,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const component = renderer.create(
|
|
107
|
+
<Provider store={store}>
|
|
108
|
+
<MemoryRouter initialEntries={['/some-route']}>
|
|
109
|
+
<Form
|
|
110
|
+
schema={{
|
|
111
|
+
fieldsets: [
|
|
112
|
+
{
|
|
113
|
+
id: 'default',
|
|
114
|
+
title: 'Default',
|
|
115
|
+
fields: ['title'],
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
properties: {
|
|
119
|
+
title: {},
|
|
120
|
+
},
|
|
121
|
+
required: [],
|
|
122
|
+
}}
|
|
123
|
+
requestError={errorMessage}
|
|
124
|
+
onSubmit={() => {}}
|
|
125
|
+
onCancel={() => {}}
|
|
126
|
+
/>
|
|
127
|
+
</MemoryRouter>
|
|
128
|
+
</Provider>,
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
expect(
|
|
132
|
+
component.root.findAllByProps({ 'data-autosave-wrapper': 'true' }),
|
|
133
|
+
).toHaveLength(0);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('wraps the form with autosave when the experimental flag is enabled', () => {
|
|
137
|
+
config.experimental = {
|
|
138
|
+
...config.experimental,
|
|
139
|
+
saveAsDraft: {
|
|
140
|
+
enabled: true,
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const store = mockStore({
|
|
145
|
+
intl: {
|
|
146
|
+
locale: 'en',
|
|
147
|
+
messages: {},
|
|
148
|
+
},
|
|
149
|
+
content: {
|
|
150
|
+
data: {},
|
|
151
|
+
create: {
|
|
152
|
+
loading: false,
|
|
153
|
+
loaded: true,
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const component = renderer.create(
|
|
159
|
+
<Provider store={store}>
|
|
160
|
+
<MemoryRouter initialEntries={['/some-route']}>
|
|
161
|
+
<Form
|
|
162
|
+
schema={{
|
|
163
|
+
fieldsets: [
|
|
164
|
+
{
|
|
165
|
+
id: 'default',
|
|
166
|
+
title: 'Default',
|
|
167
|
+
fields: ['title'],
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
properties: {
|
|
171
|
+
title: {},
|
|
172
|
+
},
|
|
173
|
+
required: [],
|
|
174
|
+
}}
|
|
175
|
+
requestError={errorMessage}
|
|
176
|
+
onSubmit={() => {}}
|
|
177
|
+
onCancel={() => {}}
|
|
178
|
+
/>
|
|
179
|
+
</MemoryRouter>
|
|
180
|
+
</Provider>,
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
expect(
|
|
184
|
+
component.root.findAllByProps({ 'data-autosave-wrapper': 'true' }),
|
|
185
|
+
).toHaveLength(1);
|
|
186
|
+
});
|
|
58
187
|
});
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
SortableMultiValue,
|
|
30
30
|
SortableMultiValueLabel,
|
|
31
31
|
MultiValueContainer,
|
|
32
|
+
MultiValueRemove,
|
|
32
33
|
} from '@plone/volto/components/manage/Widgets/SelectStyling';
|
|
33
34
|
|
|
34
35
|
import FormFieldWrapper from '@plone/volto/components/manage/Widgets/FormFieldWrapper';
|
|
@@ -276,11 +277,11 @@ class ArrayWidget extends Component {
|
|
|
276
277
|
render() {
|
|
277
278
|
const choices = normalizeChoices(this.props?.choices || []);
|
|
278
279
|
const selectedOption = normalizeArrayValue(choices, this.props.value);
|
|
280
|
+
const selectedIds = selectedOption.map((option) => option.value);
|
|
279
281
|
|
|
280
282
|
const CreatableSelect = this.props.reactSelectCreateable.default;
|
|
281
|
-
const { SortableContainer } = this.props.reactSortableHOC;
|
|
282
283
|
const Select = this.props.reactSelect.default;
|
|
283
|
-
const
|
|
284
|
+
const SelectComponent =
|
|
284
285
|
// It will be only creatable if the named vocabulary is in the widget definition
|
|
285
286
|
// (hint) like:
|
|
286
287
|
// list_field_voc_unconstrained = schema.List(
|
|
@@ -298,95 +299,112 @@ class ArrayWidget extends Component {
|
|
|
298
299
|
this.props?.choices &&
|
|
299
300
|
!getVocabFromHint(this.props) &&
|
|
300
301
|
!this.props.creatable
|
|
301
|
-
?
|
|
302
|
-
:
|
|
302
|
+
? Select
|
|
303
|
+
: CreatableSelect;
|
|
304
|
+
const { DndContext, closestCenter } = this.props.dndKitCore;
|
|
305
|
+
const { SortableContext, horizontalListSortingStrategy } =
|
|
306
|
+
this.props.dndKitSortable;
|
|
303
307
|
|
|
304
308
|
return (
|
|
305
309
|
<FormFieldWrapper {...this.props}>
|
|
306
|
-
<
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
aria-labelledby={`fieldset-${this.props.fieldSet}-field-label-${this.props.id}`}
|
|
319
|
-
key={this.props.id}
|
|
320
|
-
isDisabled={this.props.disabled || this.props.isDisabled}
|
|
321
|
-
className="react-select-container"
|
|
322
|
-
classNamePrefix="react-select"
|
|
323
|
-
/* eslint-disable jsx-a11y/no-autofocus */
|
|
324
|
-
autoFocus={this.props.focus}
|
|
325
|
-
/* eslint-enable jsx-a11y/no-autofocus */
|
|
326
|
-
options={
|
|
327
|
-
this.props.vocabBaseUrl
|
|
328
|
-
? choices
|
|
329
|
-
: this.props.choices
|
|
330
|
-
? [
|
|
331
|
-
...choices,
|
|
332
|
-
...(this.props.noValueOption &&
|
|
333
|
-
(this.props.default === undefined ||
|
|
334
|
-
this.props.default === null)
|
|
335
|
-
? [
|
|
336
|
-
{
|
|
337
|
-
label: this.props.intl.formatMessage(
|
|
338
|
-
messages.no_value,
|
|
339
|
-
),
|
|
340
|
-
value: 'no-value',
|
|
341
|
-
},
|
|
342
|
-
]
|
|
343
|
-
: []),
|
|
344
|
-
]
|
|
345
|
-
: [
|
|
346
|
-
{
|
|
347
|
-
label: this.props.intl.formatMessage(messages.no_value),
|
|
348
|
-
value: 'no-value',
|
|
349
|
-
},
|
|
350
|
-
]
|
|
351
|
-
}
|
|
352
|
-
styles={customSelectStyles}
|
|
353
|
-
theme={selectTheme}
|
|
354
|
-
components={{
|
|
355
|
-
...(this.props.choices?.length > 25 && {
|
|
356
|
-
MenuList,
|
|
357
|
-
}),
|
|
358
|
-
MultiValueContainer,
|
|
359
|
-
MultiValue: SortableMultiValue,
|
|
360
|
-
MultiValueLabel: SortableMultiValueLabel,
|
|
361
|
-
DropdownIndicator,
|
|
362
|
-
ClearIndicator,
|
|
363
|
-
Option,
|
|
310
|
+
<DndContext
|
|
311
|
+
collisionDetection={closestCenter}
|
|
312
|
+
onDragEnd={({ active, over }) => {
|
|
313
|
+
if (!over || active.id === over.id) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const oldIndex = selectedIds.indexOf(active.id);
|
|
317
|
+
const newIndex = selectedIds.indexOf(over.id);
|
|
318
|
+
if (oldIndex < 0 || newIndex < 0) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
this.onSortEnd(selectedOption, { oldIndex, newIndex });
|
|
364
322
|
}}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
323
|
+
>
|
|
324
|
+
<SortableContext
|
|
325
|
+
items={selectedIds}
|
|
326
|
+
strategy={horizontalListSortingStrategy}
|
|
327
|
+
>
|
|
328
|
+
<SelectComponent
|
|
329
|
+
menuShouldScrollIntoView={false}
|
|
330
|
+
id={`field-${this.props.id}`}
|
|
331
|
+
aria-labelledby={`fieldset-${this.props.fieldSet}-field-label-${this.props.id}`}
|
|
332
|
+
key={this.props.id}
|
|
333
|
+
isDisabled={this.props.disabled || this.props.isDisabled}
|
|
334
|
+
className="react-select-container"
|
|
335
|
+
classNamePrefix="react-select"
|
|
336
|
+
/* eslint-disable jsx-a11y/no-autofocus */
|
|
337
|
+
autoFocus={this.props.focus}
|
|
338
|
+
/* eslint-enable jsx-a11y/no-autofocus */
|
|
339
|
+
options={
|
|
340
|
+
this.props.vocabBaseUrl
|
|
341
|
+
? choices
|
|
342
|
+
: this.props.choices
|
|
343
|
+
? [
|
|
344
|
+
...choices,
|
|
345
|
+
...(this.props.noValueOption &&
|
|
346
|
+
(this.props.default === undefined ||
|
|
347
|
+
this.props.default === null)
|
|
348
|
+
? [
|
|
349
|
+
{
|
|
350
|
+
label: this.props.intl.formatMessage(
|
|
351
|
+
messages.no_value,
|
|
352
|
+
),
|
|
353
|
+
value: 'no-value',
|
|
354
|
+
},
|
|
355
|
+
]
|
|
356
|
+
: []),
|
|
357
|
+
]
|
|
358
|
+
: [
|
|
359
|
+
{
|
|
360
|
+
label: this.props.intl.formatMessage(
|
|
361
|
+
messages.no_value,
|
|
362
|
+
),
|
|
363
|
+
value: 'no-value',
|
|
364
|
+
},
|
|
365
|
+
]
|
|
366
|
+
}
|
|
367
|
+
styles={customSelectStyles}
|
|
368
|
+
theme={selectTheme}
|
|
369
|
+
components={{
|
|
370
|
+
...(this.props.choices?.length > 25 && {
|
|
371
|
+
MenuList,
|
|
372
|
+
}),
|
|
373
|
+
MultiValueContainer,
|
|
374
|
+
MultiValue: SortableMultiValue,
|
|
375
|
+
MultiValueLabel: SortableMultiValueLabel,
|
|
376
|
+
MultiValueRemove,
|
|
377
|
+
DropdownIndicator,
|
|
378
|
+
ClearIndicator,
|
|
379
|
+
Option,
|
|
380
|
+
}}
|
|
381
|
+
value={selectedOption || []}
|
|
382
|
+
placeholder={
|
|
383
|
+
this.props.placeholder ??
|
|
384
|
+
this.props.intl.formatMessage(messages.select)
|
|
385
|
+
}
|
|
386
|
+
onChange={this.handleChange}
|
|
387
|
+
isValidNewOption={(
|
|
388
|
+
inputValue,
|
|
389
|
+
selectValue,
|
|
390
|
+
selectOptions,
|
|
391
|
+
accessors,
|
|
392
|
+
) =>
|
|
393
|
+
!(
|
|
394
|
+
!inputValue ||
|
|
395
|
+
selectValue.some((option) =>
|
|
396
|
+
compareOption(inputValue, option, accessors),
|
|
397
|
+
) ||
|
|
398
|
+
selectOptions.some((option) =>
|
|
399
|
+
compareOption(inputValue, option, accessors),
|
|
400
|
+
)
|
|
401
|
+
)
|
|
402
|
+
}
|
|
403
|
+
isClearable
|
|
404
|
+
isMulti
|
|
405
|
+
/>
|
|
406
|
+
</SortableContext>
|
|
407
|
+
</DndContext>
|
|
390
408
|
</FormFieldWrapper>
|
|
391
409
|
);
|
|
392
410
|
}
|
|
@@ -396,7 +414,12 @@ export const ArrayWidgetComponent = injectIntl(ArrayWidget);
|
|
|
396
414
|
|
|
397
415
|
export default compose(
|
|
398
416
|
injectIntl,
|
|
399
|
-
injectLazyLibs([
|
|
417
|
+
injectLazyLibs([
|
|
418
|
+
'reactSelect',
|
|
419
|
+
'reactSelectCreateable',
|
|
420
|
+
'dndKitCore',
|
|
421
|
+
'dndKitSortable',
|
|
422
|
+
]),
|
|
400
423
|
connect(
|
|
401
424
|
(state, props) => {
|
|
402
425
|
const vocabBaseUrl =
|
|
@@ -9,12 +9,6 @@ import ArrayWidget from './ArrayWidget';
|
|
|
9
9
|
const mockStore = configureStore();
|
|
10
10
|
|
|
11
11
|
vi.mock('@plone/volto/helpers/Loadable/Loadable');
|
|
12
|
-
// Mock react-sortable-hoc to prevent the container error
|
|
13
|
-
vi.mock('react-sortable-hoc', () => ({
|
|
14
|
-
...vi.importActual('react-sortable-hoc'),
|
|
15
|
-
SortableContainer: (component) => component,
|
|
16
|
-
SortableElement: (component) => component,
|
|
17
|
-
}));
|
|
18
12
|
|
|
19
13
|
beforeAll(async () => {
|
|
20
14
|
const { __setLoadables } = await import(
|
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
* @module components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthIndexField
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React
|
|
6
|
+
import React from 'react';
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
|
-
import { defineMessages,
|
|
8
|
+
import { defineMessages, useIntl } from 'react-intl';
|
|
9
9
|
import map from 'lodash/map';
|
|
10
10
|
import { Form } from 'semantic-ui-react';
|
|
11
11
|
import SelectInput from './SelectInput';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* WeekdayOfTheMonthIndexField component
|
|
14
|
+
* WeekdayOfTheMonthIndexField component.
|
|
15
15
|
* @function WeekdayOfTheMonthIndexField
|
|
16
|
-
* @returns {
|
|
16
|
+
* @returns {JSX.Element} Markup of the component.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
const messages = defineMessages({
|
|
@@ -34,53 +34,59 @@ const ORDINAL_NUMBERS = {
|
|
|
34
34
|
'-1': 'last',
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
37
|
+
const WeekdayOfTheMonthIndexField = ({
|
|
38
|
+
disabled,
|
|
39
|
+
value,
|
|
40
|
+
onChange,
|
|
41
|
+
...otherProps
|
|
42
|
+
}) => {
|
|
43
|
+
const intl = useIntl();
|
|
44
|
+
const weekdayOfTheMonthIndexList = [
|
|
45
|
+
...map(Object.keys(ORDINAL_NUMBERS), (option) => ({
|
|
46
|
+
value: parseInt(option),
|
|
47
|
+
label: intl.formatMessage(messages[ORDINAL_NUMBERS[option]]),
|
|
48
|
+
})),
|
|
49
|
+
];
|
|
50
|
+
return (
|
|
51
|
+
<>
|
|
52
|
+
<Form.Field disabled={disabled}>
|
|
53
|
+
{intl.formatMessage(messages.bymonthDayNumber)}
|
|
54
|
+
</Form.Field>
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
<Form.Field disabled={disabled}>
|
|
57
|
+
<SelectInput
|
|
58
|
+
name="weekdayOfTheMonthIndex"
|
|
59
|
+
options={weekdayOfTheMonthIndexList}
|
|
60
|
+
disabled={disabled}
|
|
61
|
+
value={value}
|
|
62
|
+
onChange={onChange}
|
|
63
|
+
{...otherProps}
|
|
64
|
+
/>
|
|
65
|
+
</Form.Field>
|
|
66
|
+
</>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
59
69
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
<Form.Field disabled={disabled}>
|
|
71
|
-
{intl.formatMessage(messages.bymonthDayNumber)}
|
|
72
|
-
</Form.Field>
|
|
70
|
+
/**
|
|
71
|
+
* Property types.
|
|
72
|
+
* @property {Object} propTypes
|
|
73
|
+
* @static
|
|
74
|
+
*/
|
|
75
|
+
WeekdayOfTheMonthIndexField.propTypes = {
|
|
76
|
+
disabled: PropTypes.bool,
|
|
77
|
+
value: PropTypes.any,
|
|
78
|
+
onChange: PropTypes.func,
|
|
79
|
+
};
|
|
73
80
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
81
|
+
/**
|
|
82
|
+
* Default properties.
|
|
83
|
+
* @property {Object} defaultProps
|
|
84
|
+
* @static
|
|
85
|
+
*/
|
|
86
|
+
WeekdayOfTheMonthIndexField.defaultProps = {
|
|
87
|
+
disabled: false,
|
|
88
|
+
value: null,
|
|
89
|
+
onChange: null,
|
|
90
|
+
};
|
|
85
91
|
|
|
86
|
-
export default
|
|
92
|
+
export default WeekdayOfTheMonthIndexField;
|
|
@@ -14,33 +14,52 @@ export const MenuList = ({ children }) => {
|
|
|
14
14
|
return <DynamicHeightList>{children}</DynamicHeightList>;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
+
// this prevents the menu from being opened/closed when the user clicks
|
|
18
|
+
// on a value to begin dragging it. ideally, detecting a click (instead of
|
|
19
|
+
// a drag) would still focus the control and toggle the menu, but that
|
|
20
|
+
// requires some magic with refs that are out of scope for this example
|
|
21
|
+
const onMouseDown = (e) => {
|
|
22
|
+
e.preventDefault();
|
|
23
|
+
e.stopPropagation();
|
|
24
|
+
};
|
|
25
|
+
|
|
17
26
|
export const SortableMultiValue = injectLazyLibs([
|
|
18
27
|
'reactSelect',
|
|
19
|
-
'
|
|
28
|
+
'dndKitSortable',
|
|
29
|
+
'dndKitUtilities',
|
|
20
30
|
])((props) => {
|
|
21
31
|
const { MultiValue } = props.reactSelect.components;
|
|
22
|
-
const {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
const { useSortable } = props.dndKitSortable;
|
|
33
|
+
const { CSS } = props.dndKitUtilities;
|
|
34
|
+
const { attributes, listeners, setNodeRef, transform, transition } =
|
|
35
|
+
useSortable({
|
|
36
|
+
id: props.data.value,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
41
|
+
<div
|
|
42
|
+
ref={setNodeRef}
|
|
43
|
+
style={{
|
|
44
|
+
transform: CSS.Transform.toString(transform),
|
|
45
|
+
transition,
|
|
46
|
+
}}
|
|
47
|
+
{...attributes}
|
|
48
|
+
{...listeners}
|
|
49
|
+
>
|
|
50
|
+
<MultiValue
|
|
51
|
+
{...props}
|
|
52
|
+
innerProps={{ ...props.innerProps, onMouseDown }}
|
|
53
|
+
/>
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
34
56
|
});
|
|
35
57
|
|
|
36
|
-
export const SortableMultiValueLabel = injectLazyLibs([
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
])((props) => {
|
|
58
|
+
export const SortableMultiValueLabel = injectLazyLibs(['reactSelect'])((
|
|
59
|
+
props,
|
|
60
|
+
) => {
|
|
40
61
|
const { MultiValueLabel } = props.reactSelect.components;
|
|
41
|
-
|
|
42
|
-
const SortableComponent = SortableHandle(MultiValueLabel);
|
|
43
|
-
return <SortableComponent {...props} />;
|
|
62
|
+
return <MultiValueLabel {...props} />;
|
|
44
63
|
});
|
|
45
64
|
|
|
46
65
|
export const MultiValueContainer = injectLazyLibs('reactSelect')((props) => {
|
|
@@ -57,6 +76,19 @@ export const MultiValueContainer = injectLazyLibs('reactSelect')((props) => {
|
|
|
57
76
|
);
|
|
58
77
|
});
|
|
59
78
|
|
|
79
|
+
export const MultiValueRemove = injectLazyLibs(['reactSelect'])((props) => {
|
|
80
|
+
const { MultiValueRemove } = props.reactSelect.components;
|
|
81
|
+
return (
|
|
82
|
+
<MultiValueRemove
|
|
83
|
+
{...props}
|
|
84
|
+
innerProps={{
|
|
85
|
+
...props.innerProps,
|
|
86
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
87
|
+
}}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
|
|
60
92
|
export const Option = injectLazyLibs('reactSelect')((props) => {
|
|
61
93
|
const { Option } = props.reactSelect.components;
|
|
62
94
|
const color = props.isFocused && !props.isSelected ? '#b8c6c8' : '#007bc1';
|
package/src/config/Loadables.jsx
CHANGED
|
@@ -24,9 +24,6 @@ export const loadables = {
|
|
|
24
24
|
reactVirtualized: loadable.lib(() => import('react-virtualized'), {
|
|
25
25
|
ssr: false,
|
|
26
26
|
}),
|
|
27
|
-
reactSortableHOC: loadable.lib(() => import('react-sortable-hoc'), {
|
|
28
|
-
ssr: false,
|
|
29
|
-
}),
|
|
30
27
|
reactSelectAsyncPaginate: loadable.lib(
|
|
31
28
|
() => import('react-select-async-paginate'),
|
|
32
29
|
{ ssr: false },
|
|
@@ -46,11 +43,10 @@ export const loadables = {
|
|
|
46
43
|
diffLib: loadable.lib(() => import('diff')),
|
|
47
44
|
moment: loadable.lib(() => import('moment')),
|
|
48
45
|
reactDates: loadable.lib(() => import('react-dates')),
|
|
49
|
-
reactDnd: loadable.lib(() => import('react-dnd')),
|
|
50
|
-
reactDndHtml5Backend: loadable.lib(() => import('react-dnd-html5-backend')),
|
|
51
46
|
reactBeautifulDnd: loadable.lib(() => import('react-beautiful-dnd')),
|
|
52
47
|
rrule: loadable.lib(() => import('rrule')),
|
|
53
48
|
dndKitCore: loadable.lib(() => import('@dnd-kit/core')),
|
|
49
|
+
dndKitModifiers: loadable.lib(() => import('@dnd-kit/modifiers')),
|
|
54
50
|
dndKitSortable: loadable.lib(() => import('@dnd-kit/sortable')),
|
|
55
51
|
dndKitUtilities: loadable.lib(() => import('@dnd-kit/utilities')),
|
|
56
52
|
};
|