@plone/volto 18.33.1 → 18.35.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.
- package/.release-it.json +3 -0
- package/CHANGELOG.md +52 -0
- package/README.md +0 -1
- package/locales/af/LC_MESSAGES/volto.po +55 -0
- package/locales/af.json +1 -1
- package/locales/ar/LC_MESSAGES/volto.po +55 -0
- package/locales/ar.json +1 -1
- package/locales/bg/LC_MESSAGES/volto.po +55 -0
- package/locales/bg.json +1 -1
- package/locales/bn/LC_MESSAGES/volto.po +55 -0
- package/locales/bn.json +1 -1
- package/locales/ca/LC_MESSAGES/volto.po +57 -2
- package/locales/ca.json +1 -1
- package/locales/cs/LC_MESSAGES/volto.po +55 -0
- package/locales/cs.json +1 -1
- package/locales/cy/LC_MESSAGES/volto.po +55 -0
- package/locales/cy.json +1 -1
- package/locales/da/LC_MESSAGES/volto.po +55 -0
- package/locales/da.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +59 -4
- package/locales/de.json +1 -1
- package/locales/el/LC_MESSAGES/volto.po +55 -0
- package/locales/el.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +55 -0
- package/locales/en.json +1 -1
- package/locales/en_AU/LC_MESSAGES/volto.po +55 -0
- package/locales/en_AU.json +1 -1
- package/locales/en_GB/LC_MESSAGES/volto.po +55 -0
- package/locales/en_GB.json +1 -1
- package/locales/eo/LC_MESSAGES/volto.po +55 -0
- package/locales/eo.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +73 -18
- package/locales/es.json +1 -1
- package/locales/et/LC_MESSAGES/volto.po +55 -0
- package/locales/et.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +58 -3
- package/locales/eu.json +1 -1
- package/locales/fa/LC_MESSAGES/volto.po +55 -0
- package/locales/fa.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +55 -0
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +56 -1
- package/locales/fr.json +1 -1
- package/locales/fu/LC_MESSAGES/volto.po +55 -0
- package/locales/fu.json +1 -1
- package/locales/gl/LC_MESSAGES/volto.po +60 -5
- package/locales/gl.json +1 -1
- package/locales/he/LC_MESSAGES/volto.po +55 -0
- package/locales/he.json +1 -1
- package/locales/hi/LC_MESSAGES/volto.po +58 -3
- package/locales/hi.json +1 -1
- package/locales/hr/LC_MESSAGES/volto.po +55 -0
- package/locales/hr.json +1 -1
- package/locales/hu/LC_MESSAGES/volto.po +55 -0
- package/locales/hu.json +1 -1
- package/locales/hy/LC_MESSAGES/volto.po +55 -0
- package/locales/hy.json +1 -1
- package/locales/id/LC_MESSAGES/volto.po +55 -0
- package/locales/id.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +56 -1
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +55 -0
- package/locales/ja.json +1 -1
- package/locales/ka/LC_MESSAGES/volto.po +55 -0
- package/locales/ka.json +1 -1
- package/locales/kn/LC_MESSAGES/volto.po +55 -0
- package/locales/kn.json +1 -1
- package/locales/ko/LC_MESSAGES/volto.po +55 -0
- package/locales/ko.json +1 -1
- package/locales/lt/LC_MESSAGES/volto.po +55 -0
- package/locales/lt.json +1 -1
- package/locales/lv/LC_MESSAGES/volto.po +55 -0
- package/locales/lv.json +1 -1
- package/locales/mi/LC_MESSAGES/volto.po +55 -0
- package/locales/mi.json +1 -1
- package/locales/mk/LC_MESSAGES/volto.po +55 -0
- package/locales/mk.json +1 -1
- package/locales/my/LC_MESSAGES/volto.po +55 -0
- package/locales/my.json +1 -1
- package/locales/nb_NO/LC_MESSAGES/volto.po +55 -0
- package/locales/nb_NO.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +56 -1
- package/locales/nl.json +1 -1
- package/locales/nn/LC_MESSAGES/volto.po +55 -0
- package/locales/nn.json +1 -1
- package/locales/pl/LC_MESSAGES/volto.po +55 -0
- package/locales/pl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +55 -0
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +69 -14
- package/locales/pt_BR.json +1 -1
- package/locales/rm/LC_MESSAGES/volto.po +55 -0
- package/locales/rm.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +56 -1
- package/locales/ro.json +1 -1
- package/locales/ru/LC_MESSAGES/volto.po +56 -1
- package/locales/ru.json +1 -1
- package/locales/sk/LC_MESSAGES/volto.po +55 -0
- package/locales/sk.json +1 -1
- package/locales/sl/LC_MESSAGES/volto.po +55 -0
- package/locales/sl.json +1 -1
- package/locales/sm/LC_MESSAGES/volto.po +55 -0
- package/locales/sm.json +1 -1
- package/locales/sq/LC_MESSAGES/volto.po +55 -0
- package/locales/sq.json +1 -1
- package/locales/sr/LC_MESSAGES/volto.po +55 -0
- package/locales/sr.json +1 -1
- package/locales/sr@cyrl/LC_MESSAGES/volto.po +55 -0
- package/locales/sr@cyrl.json +1 -1
- package/locales/sr@latn/LC_MESSAGES/volto.po +55 -0
- package/locales/sr@latn.json +1 -1
- package/locales/sv/LC_MESSAGES/volto.po +55 -0
- package/locales/sv.json +1 -1
- package/locales/ta/LC_MESSAGES/volto.po +56 -1
- package/locales/ta.json +1 -1
- package/locales/te/LC_MESSAGES/volto.po +55 -0
- package/locales/te.json +1 -1
- package/locales/th/LC_MESSAGES/volto.po +55 -0
- package/locales/th.json +1 -1
- package/locales/to/LC_MESSAGES/volto.po +55 -0
- package/locales/to.json +1 -1
- package/locales/tr/LC_MESSAGES/volto.po +55 -0
- package/locales/tr.json +1 -1
- package/locales/uk/LC_MESSAGES/volto.po +55 -0
- package/locales/uk.json +1 -1
- package/locales/vi/LC_MESSAGES/volto.po +55 -0
- package/locales/vi.json +1 -1
- package/locales/volto.pot +56 -1
- package/locales/zh_CN/LC_MESSAGES/volto.po +55 -0
- package/locales/zh_CN.json +1 -1
- package/locales/zh_Hant/LC_MESSAGES/volto.po +55 -0
- package/locales/zh_Hant.json +1 -1
- package/locales/zh_Hant_HK/LC_MESSAGES/volto.po +55 -0
- package/locales/zh_Hant_HK.json +1 -1
- package/news/7308.fix +1 -0
- package/news/8084.fix +1 -0
- package/package.json +19 -19
- package/razzle.config.js +1 -0
- package/src/actions/users/users.js +2 -2
- package/src/components/manage/Blocks/Block/Order/Item.jsx +18 -10
- package/src/components/manage/Blocks/Block/Order/Item.test.jsx +90 -0
- package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +7 -0
- package/src/components/manage/Controlpanels/ContentTypes.jsx +9 -2
- package/src/components/manage/Controlpanels/DatabaseInformation.jsx +9 -0
- package/src/components/manage/Controlpanels/ModerateComments.jsx +8 -0
- package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.test.jsx +3 -0
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +58 -5
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.jsx +624 -0
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +8 -0
- package/src/components/manage/Form/Form.jsx +6 -1
- package/src/components/manage/Form/ModalForm.jsx +165 -87
- package/src/components/manage/Sidebar/Sidebar.jsx +1 -0
- package/src/components/manage/Toast/Toast.jsx +35 -1
- package/src/components/manage/Toast/Toast.test.jsx +8 -5
- package/src/components/manage/Widgets/DatetimeWidget.jsx +92 -58
- package/src/components/manage/Widgets/DatetimeWidget.test.jsx +55 -0
- package/src/components/manage/Widgets/FormFieldWrapper.jsx +7 -5
- package/src/components/manage/Widgets/TextWidget.jsx +4 -0
- package/src/components/manage/Widgets/UrlWidget.jsx +51 -6
- package/src/components/theme/Search/Search.jsx +24 -1
- package/src/components/theme/Unauthorized/Unauthorized.jsx +30 -22
- package/src/components/theme/Unauthorized/Unauthorized.test.jsx +28 -1
- package/src/helpers/FormValidation/validators.ts +15 -2
- package/theme/themes/default/globals/site.variables +2 -2
- package/theme/themes/pastanaga/collections/form.overrides +21 -0
- package/theme/themes/pastanaga/elements/button.overrides +30 -3
- package/theme/themes/pastanaga/extras/main.less +16 -0
- package/theme/themes/pastanaga/globals/site.variables +0 -2
- package/types/components/manage/Blocks/Block/Order/Item.test.d.ts +1 -0
- package/types/components/manage/Controlpanels/Users/UsersControlpanel.d.ts +2 -6
- package/types/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.d.ts +1 -0
- package/types/components/manage/Controlpanels/index.d.ts +1 -1
- package/webpack-plugins/webpack-less-plugin.js +1 -1
|
@@ -19,6 +19,8 @@ const TextWidget = (props) => {
|
|
|
19
19
|
placeholder,
|
|
20
20
|
isDisabled,
|
|
21
21
|
focus,
|
|
22
|
+
required,
|
|
23
|
+
error,
|
|
22
24
|
} = props;
|
|
23
25
|
|
|
24
26
|
const ref = useRef();
|
|
@@ -49,6 +51,8 @@ const TextWidget = (props) => {
|
|
|
49
51
|
onClick={() => onClick()}
|
|
50
52
|
minLength={minLength || null}
|
|
51
53
|
maxLength={maxLength || null}
|
|
54
|
+
aria-required={required ? 'true' : undefined}
|
|
55
|
+
aria-invalid={error?.length > 0 ? 'true' : undefined}
|
|
52
56
|
/>
|
|
53
57
|
{icon && iconAction && (
|
|
54
58
|
<button className={`field-${id}-action-button`} onClick={iconAction}>
|
|
@@ -14,10 +14,30 @@ import {
|
|
|
14
14
|
flattenToAppURL,
|
|
15
15
|
URLUtils,
|
|
16
16
|
} from '@plone/volto/helpers/Url/Url';
|
|
17
|
+
import { defineMessages, useIntl } from 'react-intl';
|
|
17
18
|
import withObjectBrowser from '@plone/volto/components/manage/Sidebar/ObjectBrowser';
|
|
18
19
|
import clearSVG from '@plone/volto/icons/clear.svg';
|
|
19
20
|
import navTreeSVG from '@plone/volto/icons/nav.svg';
|
|
20
21
|
|
|
22
|
+
const messages = defineMessages({
|
|
23
|
+
urlMissing: {
|
|
24
|
+
id: 'URL is missing',
|
|
25
|
+
defaultMessage: 'URL is missing',
|
|
26
|
+
},
|
|
27
|
+
urlInvalid: {
|
|
28
|
+
id: 'URL is invalid',
|
|
29
|
+
defaultMessage: 'URL is invalid',
|
|
30
|
+
},
|
|
31
|
+
clearUrl: {
|
|
32
|
+
id: 'Clear URL',
|
|
33
|
+
defaultMessage: 'Clear URL',
|
|
34
|
+
},
|
|
35
|
+
openUrlBrowser: {
|
|
36
|
+
id: 'Open URL browser',
|
|
37
|
+
defaultMessage: 'Open URL browser',
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
21
41
|
/** Widget to edit urls
|
|
22
42
|
*
|
|
23
43
|
* This is the default widget used for the `remoteUrl` field. You can also use
|
|
@@ -40,9 +60,10 @@ export const UrlWidget = (props) => {
|
|
|
40
60
|
maxLength,
|
|
41
61
|
placeholder,
|
|
42
62
|
isDisabled,
|
|
63
|
+
required,
|
|
43
64
|
} = props;
|
|
44
65
|
const inputId = `field-${id}`;
|
|
45
|
-
|
|
66
|
+
const intl = useIntl();
|
|
46
67
|
const [value, setValue] = useState(flattenToAppURL(props.value));
|
|
47
68
|
const [isInvalid, setIsInvalid] = useState(false);
|
|
48
69
|
/**
|
|
@@ -54,6 +75,7 @@ export const UrlWidget = (props) => {
|
|
|
54
75
|
const clear = () => {
|
|
55
76
|
setValue('');
|
|
56
77
|
onChange(id, undefined);
|
|
78
|
+
setIsInvalid(false);
|
|
57
79
|
};
|
|
58
80
|
|
|
59
81
|
const onChangeValue = (_value) => {
|
|
@@ -83,6 +105,14 @@ export const UrlWidget = (props) => {
|
|
|
83
105
|
onChange(id, newValue === '' ? undefined : newValue);
|
|
84
106
|
};
|
|
85
107
|
|
|
108
|
+
// A11y: if the field is required and the user leaves it empty, we mark it as missing
|
|
109
|
+
const handleBlur = ({ target }) => {
|
|
110
|
+
if (required && (!target.value || target.value === '')) {
|
|
111
|
+
setIsInvalid(true);
|
|
112
|
+
}
|
|
113
|
+
onBlur(id, target.value === '' ? undefined : target.value);
|
|
114
|
+
};
|
|
115
|
+
|
|
86
116
|
return (
|
|
87
117
|
<FormFieldWrapper {...props} className="url wide">
|
|
88
118
|
<div className="wrapper">
|
|
@@ -90,24 +120,38 @@ export const UrlWidget = (props) => {
|
|
|
90
120
|
id={inputId}
|
|
91
121
|
name={id}
|
|
92
122
|
type="url"
|
|
123
|
+
required={required}
|
|
124
|
+
aria-required={required}
|
|
125
|
+
aria-invalid={isInvalid}
|
|
126
|
+
aria-errormessage={isInvalid ? `${inputId}-error` : undefined}
|
|
93
127
|
value={value || ''}
|
|
94
128
|
disabled={isDisabled}
|
|
95
129
|
placeholder={placeholder}
|
|
96
130
|
onChange={({ target }) => onChangeValue(target.value)}
|
|
97
|
-
onBlur={
|
|
98
|
-
onBlur(id, target.value === '' ? undefined : target.value)
|
|
99
|
-
}
|
|
131
|
+
onBlur={handleBlur}
|
|
100
132
|
onClick={() => onClick()}
|
|
101
133
|
minLength={minLength || null}
|
|
102
134
|
maxLength={maxLength || null}
|
|
103
135
|
error={isInvalid}
|
|
104
136
|
/>
|
|
137
|
+
{isInvalid && (
|
|
138
|
+
<span
|
|
139
|
+
id={`${inputId}-error`}
|
|
140
|
+
role="alert"
|
|
141
|
+
className="visually-hidden-volto"
|
|
142
|
+
>
|
|
143
|
+
{value?.length > 0
|
|
144
|
+
? intl.formatMessage(messages.urlInvalid)
|
|
145
|
+
: intl.formatMessage(messages.urlMissing)}
|
|
146
|
+
</span>
|
|
147
|
+
)}
|
|
105
148
|
{value?.length > 0 ? (
|
|
106
149
|
<Button.Group>
|
|
107
150
|
<Button
|
|
151
|
+
type="button"
|
|
108
152
|
basic
|
|
109
153
|
className="cancel"
|
|
110
|
-
aria-label=
|
|
154
|
+
aria-label={intl.formatMessage(messages.clearUrl)}
|
|
111
155
|
onClick={(e) => {
|
|
112
156
|
e.preventDefault();
|
|
113
157
|
e.stopPropagation();
|
|
@@ -120,9 +164,10 @@ export const UrlWidget = (props) => {
|
|
|
120
164
|
) : (
|
|
121
165
|
<Button.Group>
|
|
122
166
|
<Button
|
|
167
|
+
type="button"
|
|
123
168
|
basic
|
|
124
169
|
icon
|
|
125
|
-
aria-label=
|
|
170
|
+
aria-label={intl.formatMessage(messages.openUrlBrowser)}
|
|
126
171
|
onClick={(e) => {
|
|
127
172
|
e.preventDefault();
|
|
128
173
|
e.stopPropagation();
|
|
@@ -85,6 +85,7 @@ class Search extends Component {
|
|
|
85
85
|
componentDidMount() {
|
|
86
86
|
this.doSearch();
|
|
87
87
|
this.setState({ isClient: true });
|
|
88
|
+
this.focusResults();
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
/**
|
|
@@ -97,6 +98,22 @@ class Search extends Component {
|
|
|
97
98
|
if (this.props.location.search !== nextProps.location.search) {
|
|
98
99
|
this.doSearch();
|
|
99
100
|
}
|
|
101
|
+
|
|
102
|
+
if (
|
|
103
|
+
JSON.stringify(this.props.search) !== JSON.stringify(nextProps.search)
|
|
104
|
+
) {
|
|
105
|
+
//on opening results page, move focus on results
|
|
106
|
+
this.focusResults();
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
focusResults = () => {
|
|
111
|
+
//on opening results page, move focus on results
|
|
112
|
+
setTimeout(function () {
|
|
113
|
+
if (document.querySelector('#page-search #search-results')) {
|
|
114
|
+
document.querySelector('#page-search #search-results').focus();
|
|
115
|
+
}
|
|
116
|
+
}, 100);
|
|
100
117
|
};
|
|
101
118
|
|
|
102
119
|
/**
|
|
@@ -162,7 +179,13 @@ class Search extends Component {
|
|
|
162
179
|
return (
|
|
163
180
|
<Container id="page-search">
|
|
164
181
|
<Helmet title={this.props.intl.formatMessage(messages.Search)} />
|
|
165
|
-
<div
|
|
182
|
+
<div
|
|
183
|
+
className="container"
|
|
184
|
+
role="region"
|
|
185
|
+
aria-live="polite"
|
|
186
|
+
id="search-results"
|
|
187
|
+
tabIndex={-1}
|
|
188
|
+
>
|
|
166
189
|
<article id="content">
|
|
167
190
|
<header>
|
|
168
191
|
<h1 className="documentFirstHeading">
|
|
@@ -8,6 +8,7 @@ import { getBaseUrl } from '@plone/volto/helpers/Url/Url';
|
|
|
8
8
|
import BodyClass from '@plone/volto/helpers/BodyClass/BodyClass';
|
|
9
9
|
|
|
10
10
|
const Unauthorized = () => {
|
|
11
|
+
const token = useSelector((state) => state.userSession.token);
|
|
11
12
|
const error_message = useSelector((state) => state.apierror?.message);
|
|
12
13
|
let location = useLocation();
|
|
13
14
|
|
|
@@ -19,28 +20,35 @@ const Unauthorized = () => {
|
|
|
19
20
|
</h1>
|
|
20
21
|
<h3>{error_message}</h3>
|
|
21
22
|
<p className="description">
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
23
|
+
{token ? (
|
|
24
|
+
<FormattedMessage
|
|
25
|
+
id="You are trying to access a protected resource."
|
|
26
|
+
defaultMessage="You are trying to access a protected resource."
|
|
27
|
+
/>
|
|
28
|
+
) : (
|
|
29
|
+
<FormattedMessage
|
|
30
|
+
id="You are trying to access a protected resource, please {login} first."
|
|
31
|
+
defaultMessage="You are trying to access a protected resource, please {login} first."
|
|
32
|
+
values={{
|
|
33
|
+
login: (
|
|
34
|
+
<Link
|
|
35
|
+
to={{
|
|
36
|
+
pathname: `${getBaseUrl(location.pathname)}/login`,
|
|
37
|
+
state: {
|
|
38
|
+
// This is needed to cover the use case of being logged in in
|
|
39
|
+
// another backend (eg. in development), having a token for
|
|
40
|
+
// localhost and try to use it, the login route has to know that
|
|
41
|
+
// it's the same as it comes from a logout
|
|
42
|
+
isLogout: true,
|
|
43
|
+
},
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
<FormattedMessage id="log in" defaultMessage="log in" />
|
|
47
|
+
</Link>
|
|
48
|
+
),
|
|
49
|
+
}}
|
|
50
|
+
/>
|
|
51
|
+
)}
|
|
44
52
|
</p>
|
|
45
53
|
<p>
|
|
46
54
|
<FormattedMessage
|
|
@@ -9,8 +9,35 @@ import Unauthorized from './Unauthorized';
|
|
|
9
9
|
const mockStore = configureStore();
|
|
10
10
|
|
|
11
11
|
describe('Unauthorized', () => {
|
|
12
|
-
it('renders
|
|
12
|
+
it('renders an unauthorized component', () => {
|
|
13
13
|
const store = mockStore({
|
|
14
|
+
userSession: {
|
|
15
|
+
token: null,
|
|
16
|
+
},
|
|
17
|
+
intl: {
|
|
18
|
+
locale: 'en',
|
|
19
|
+
messages: {},
|
|
20
|
+
},
|
|
21
|
+
apierror: {
|
|
22
|
+
message: 'You are not authorized to access this resource',
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
const component = renderer.create(
|
|
26
|
+
<Provider store={store}>
|
|
27
|
+
<MemoryRouter>
|
|
28
|
+
<Unauthorized />
|
|
29
|
+
</MemoryRouter>
|
|
30
|
+
</Provider>,
|
|
31
|
+
);
|
|
32
|
+
const json = component.toJSON();
|
|
33
|
+
expect(json).toMatchSnapshot();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('renders an unauthorized component for authenticated user', () => {
|
|
37
|
+
const store = mockStore({
|
|
38
|
+
userSession: {
|
|
39
|
+
token: '1234',
|
|
40
|
+
},
|
|
14
41
|
intl: {
|
|
15
42
|
locale: 'en',
|
|
16
43
|
messages: {},
|
|
@@ -153,6 +153,15 @@ export const hasUniqueItemsValidator = ({
|
|
|
153
153
|
return !isValid ? formatMessage(messages.uniqueItems) : null;
|
|
154
154
|
};
|
|
155
155
|
|
|
156
|
+
const formatDateValue = (isoString: string) => {
|
|
157
|
+
const date = new Date(isoString);
|
|
158
|
+
if (isNaN(date.getTime())) return isoString;
|
|
159
|
+
return new Intl.DateTimeFormat(undefined, {
|
|
160
|
+
dateStyle: 'medium',
|
|
161
|
+
timeStyle: 'short',
|
|
162
|
+
}).format(date);
|
|
163
|
+
};
|
|
164
|
+
|
|
156
165
|
export const startEventDateRangeValidator = ({
|
|
157
166
|
value,
|
|
158
167
|
field,
|
|
@@ -163,7 +172,9 @@ export const startEventDateRangeValidator = ({
|
|
|
163
172
|
value && formData.end && new Date(value) < new Date(formData.end);
|
|
164
173
|
return !isValid
|
|
165
174
|
? formatMessage(messages.startEventRange, {
|
|
166
|
-
endDateValueOrEndFieldName: formData.end
|
|
175
|
+
endDateValueOrEndFieldName: formData.end
|
|
176
|
+
? formatDateValue(formData.end)
|
|
177
|
+
: 'end',
|
|
167
178
|
})
|
|
168
179
|
: null;
|
|
169
180
|
};
|
|
@@ -178,7 +189,9 @@ export const endEventDateRangeValidator = ({
|
|
|
178
189
|
value && formData.start && new Date(value) > new Date(formData.start);
|
|
179
190
|
return !isValid
|
|
180
191
|
? formatMessage(messages.endEventRange, {
|
|
181
|
-
startDateValueOrStartFieldName: formData.start
|
|
192
|
+
startDateValueOrStartFieldName: formData.start
|
|
193
|
+
? formatDateValue(formData.start)
|
|
194
|
+
: 'start',
|
|
182
195
|
})
|
|
183
196
|
: null;
|
|
184
197
|
};
|
|
@@ -82,8 +82,8 @@
|
|
|
82
82
|
|
|
83
83
|
/* Input Text Color */
|
|
84
84
|
@inputColor: @textColor;
|
|
85
|
-
@inputPlaceholderColor: lighten(@inputColor,
|
|
86
|
-
@inputPlaceholderFocusColor: lighten(@inputColor,
|
|
85
|
+
@inputPlaceholderColor: lighten(@inputColor, 35);
|
|
86
|
+
@inputPlaceholderFocusColor: lighten(@inputColor, 65);
|
|
87
87
|
|
|
88
88
|
/* Line Height Default For Inputs in Browser (Descenders are 17px at 14px base em) */
|
|
89
89
|
@inputLineHeight: unit((17 / 14), em);
|
|
@@ -31,6 +31,27 @@
|
|
|
31
31
|
line-height: initial;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// Restore visible focus for keyboard navigation — overrides Semantic UI's `outline: none` on form inputs
|
|
35
|
+
.ui.form input:not([type]),
|
|
36
|
+
.ui.form input[type='date'],
|
|
37
|
+
.ui.form input[type='datetime-local'],
|
|
38
|
+
.ui.form input[type='email'],
|
|
39
|
+
.ui.form input[type='number'],
|
|
40
|
+
.ui.form input[type='password'],
|
|
41
|
+
.ui.form input[type='search'],
|
|
42
|
+
.ui.form input[type='tel'],
|
|
43
|
+
.ui.form input[type='time'],
|
|
44
|
+
.ui.form input[type='text'],
|
|
45
|
+
.ui.form input[type='file'],
|
|
46
|
+
.ui.form input[type='url'],
|
|
47
|
+
.ui.form textarea {
|
|
48
|
+
padding-left: 5px;
|
|
49
|
+
|
|
50
|
+
&:focus-visible {
|
|
51
|
+
outline: revert;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
34
55
|
.ui.form .ui.input input:not([type]),
|
|
35
56
|
.ui.form .ui.input input[type='date'],
|
|
36
57
|
.ui.form .ui.input input[type='datetime-local'],
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
#main,
|
|
30
|
-
.slate-inline-toolbar.slate-toolbar
|
|
30
|
+
.slate-inline-toolbar.slate-toolbar,
|
|
31
|
+
.contenttype-plone-site .ui.page.modals {
|
|
31
32
|
.ui.basic.buttons .button,
|
|
32
33
|
.ui.basic.button {
|
|
33
34
|
-webkit-box-shadow: 0px 0px 0px @basicBorderSize transparent inset !important;
|
|
@@ -42,11 +43,16 @@
|
|
|
42
43
|
cursor: pointer;
|
|
43
44
|
text-align: initial;
|
|
44
45
|
|
|
45
|
-
&:focus {
|
|
46
|
+
&:focus:not(:focus-visible) {
|
|
46
47
|
outline: none;
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
|
|
51
|
+
.ui.basic.buttons .button:focus-visible,
|
|
52
|
+
.ui.basic.button:focus-visible {
|
|
53
|
+
outline: revert;
|
|
54
|
+
}
|
|
55
|
+
|
|
50
56
|
.ui.basic.primary.button,
|
|
51
57
|
.ui.basic.secondary.button {
|
|
52
58
|
box-shadow: none !important;
|
|
@@ -69,7 +75,7 @@
|
|
|
69
75
|
cursor: pointer;
|
|
70
76
|
text-align: initial;
|
|
71
77
|
|
|
72
|
-
&:focus {
|
|
78
|
+
&:focus:not(:focus-visible) {
|
|
73
79
|
outline: none;
|
|
74
80
|
}
|
|
75
81
|
}
|
|
@@ -85,3 +91,24 @@
|
|
|
85
91
|
margin: 0;
|
|
86
92
|
}
|
|
87
93
|
}
|
|
94
|
+
|
|
95
|
+
.modals {
|
|
96
|
+
.modal {
|
|
97
|
+
.actions {
|
|
98
|
+
display: flex;
|
|
99
|
+
justify-content: flex-end;
|
|
100
|
+
gap: 0.5em;
|
|
101
|
+
|
|
102
|
+
.ui.basic.button {
|
|
103
|
+
display: flex;
|
|
104
|
+
justify-content: center;
|
|
105
|
+
padding: 0.3em;
|
|
106
|
+
margin: 0;
|
|
107
|
+
|
|
108
|
+
svg {
|
|
109
|
+
margin: 0;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -360,6 +360,7 @@ button {
|
|
|
360
360
|
margin-left: 8px;
|
|
361
361
|
|
|
362
362
|
h4 {
|
|
363
|
+
display: inline;
|
|
363
364
|
margin-bottom: 0;
|
|
364
365
|
font-weight: @bold;
|
|
365
366
|
}
|
|
@@ -658,6 +659,21 @@ img.responsive {
|
|
|
658
659
|
margin-top: 20px;
|
|
659
660
|
}
|
|
660
661
|
|
|
662
|
+
// Accessibility
|
|
663
|
+
// This class is used to hide elements visually but keep them accessible for screen readers and assistive technologies.
|
|
664
|
+
// to not interfere with other 'visually-hidden' classes from other CSS frameworks (e.g. Semantic UI or TailwindCSS), we use a specific class name for Volto 18 (only).
|
|
665
|
+
.visually-hidden-volto {
|
|
666
|
+
position: absolute !important;
|
|
667
|
+
overflow: hidden !important;
|
|
668
|
+
width: 1px !important;
|
|
669
|
+
height: 1px !important;
|
|
670
|
+
padding: 0 !important;
|
|
671
|
+
border: 0 !important;
|
|
672
|
+
margin: -1px !important;
|
|
673
|
+
clip-path: inset(50%) !important;
|
|
674
|
+
white-space: nowrap !important;
|
|
675
|
+
}
|
|
676
|
+
|
|
661
677
|
// Deprecated as per https://github.com/plone/volto/issues/1265
|
|
662
678
|
// @import 'utils';
|
|
663
679
|
@import (multiple) '../extras/fonts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,7 +4,7 @@ export declare const RulesControlpanel: import("@loadable/component").LoadableCl
|
|
|
4
4
|
export declare const AddRuleControlpanel: import("@loadable/component").LoadableClassComponent<any>;
|
|
5
5
|
export declare const EditRuleControlpanel: import("@loadable/component").LoadableClassComponent<any>;
|
|
6
6
|
export declare const ConfigureRuleControlpanel: import("@loadable/component").LoadableClassComponent<any>;
|
|
7
|
-
export declare const UsersControlpanel: import("@loadable/component").
|
|
7
|
+
export declare const UsersControlpanel: import("@loadable/component").LoadableClassComponent<any>;
|
|
8
8
|
export declare const RenderUsers: import("@loadable/component").LoadableComponent<any>;
|
|
9
9
|
export declare const UserGroupMembershipControlPanel: import("@loadable/component").LoadableComponent<unknown>;
|
|
10
10
|
export declare const GroupsControlpanel: import("@loadable/component").LoadableClassComponent<any>;
|
|
@@ -143,7 +143,7 @@ module.exports = (userOptions = {}) => ({
|
|
|
143
143
|
/packages\/volto\/theme/,
|
|
144
144
|
/plone\.volto\/theme/,
|
|
145
145
|
/node_modules\/semantic-ui-less/,
|
|
146
|
-
...Object.values(registry.
|
|
146
|
+
...Object.values(registry.packages).map((p) => p.modulePath),
|
|
147
147
|
],
|
|
148
148
|
use: isServer
|
|
149
149
|
? [
|