@plone/volto 17.21.0 → 17.22.1

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.
Binary file
package/CHANGELOG.md CHANGED
@@ -17,6 +17,23 @@ myst:
17
17
 
18
18
  <!-- towncrier release notes start -->
19
19
 
20
+ ## 17.22.1 (2025-08-25)
21
+
22
+ ### Bugfix
23
+
24
+ - fix(fetchContent): correctly handle undefined blocksType in async fetchContent @nileshgulia1 [#7112](https://github.com/plone/volto/issues/7112)
25
+ - Fix corner case in devproxy when pathname is null. @sneridagh [#7276](https://github.com/plone/volto/issues/7276)
26
+
27
+ ## 17.22.0 (2025-05-20)
28
+
29
+ ### Feature
30
+
31
+ - Use table sorting icons from pastanaga `icons.woff` instead of assuming we have Font Awesome icons. Improve accessibility for sortable table headers in table block. @ichim-david @kreafox [#7091](https://github.com/plone/volto/issues/7091)
32
+
33
+ ### Bugfix
34
+
35
+ - Added an `aria-label` to `CreatableSelect` inside `TokenWidget` to improve the component’s accessibility. @Wagner3UB [#6786](https://github.com/plone/volto/issues/6786)
36
+
20
37
  ## 17.21.0 (2025-03-05)
21
38
 
22
39
  ### Feature
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  }
10
10
  ],
11
11
  "license": "MIT",
12
- "version": "17.21.0",
12
+ "version": "17.22.1",
13
13
  "repository": {
14
14
  "type": "git",
15
15
  "url": "git@github.com:plone/volto.git"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plone/volto-slate",
3
- "version": "17.21.0",
3
+ "version": "17.22.1",
4
4
  "description": "Slate.js integration with Volto",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -71,6 +71,19 @@ const View = ({ data }) => {
71
71
  });
72
72
  }, [state, rows]);
73
73
 
74
+ const handleSort = (index) => {
75
+ if (!data.table.sortable) return;
76
+ setState({
77
+ column: index,
78
+ direction:
79
+ state.column !== index
80
+ ? 'ascending'
81
+ : state.direction === 'ascending'
82
+ ? 'descending'
83
+ : 'ascending',
84
+ });
85
+ };
86
+
74
87
  return (
75
88
  <>
76
89
  {data && data.table && (
@@ -92,19 +105,20 @@ const View = ({ data }) => {
92
105
  key={cell.key}
93
106
  textAlign="left"
94
107
  verticalAlign="middle"
108
+ tabIndex={data.table.sortable ? '0' : '-1'}
95
109
  sorted={state.column === index ? state.direction : null}
96
110
  onClick={() => {
97
- if (!data.table.sortable) return;
98
- setState({
99
- column: index,
100
- direction:
101
- state.column !== index
102
- ? 'ascending'
103
- : state.direction === 'ascending'
104
- ? 'descending'
105
- : 'ascending',
106
- });
111
+ handleSort(index);
112
+ }}
113
+ onKeyDown={(e) => {
114
+ if (e.key === 'Enter' || e.key === ' ') {
115
+ e.preventDefault();
116
+ handleSort(index);
117
+ }
107
118
  }}
119
+ aria-sort={
120
+ state.column === index ? state.direction : 'none'
121
+ }
108
122
  >
109
123
  {cell.value &&
110
124
  Node.string({ children: cell.value }).length > 0
@@ -173,6 +173,7 @@ class TokenWidget extends Component {
173
173
  <FormFieldWrapper {...this.props}>
174
174
  <CreatableSelect
175
175
  id={`field-${this.props.id}`}
176
+ aria-labelledby={`fieldset-${this.props.fieldSet}-field-label-${this.props.id}`}
176
177
  key={this.props.id}
177
178
  menuShouldScrollIntoView={false}
178
179
  isDisabled={this.props.isDisabled}
@@ -232,7 +232,9 @@ export const fetchContent = async ({ store, location }) => {
232
232
 
233
233
  const visitor = ([id, data]) => {
234
234
  const blockType = data['@type'];
235
- const { getAsyncData } = blocksConfig[blockType];
235
+ const block = blocksConfig[blockType];
236
+ if (!block) return;
237
+ const { getAsyncData } = block;
236
238
  if (getAsyncData) {
237
239
  const p = getAsyncData({
238
240
  store,
@@ -10,8 +10,13 @@ import querystring from 'querystring';
10
10
  import { parse as parseUrl } from 'url';
11
11
 
12
12
  const filter = function (pathname, req) {
13
- // This is the proxy to the API in case the accept header is 'application/json'
14
- return config.settings.devProxyToApiPath && pathname.startsWith('/++api++');
13
+ // Check if pathname is defined, there are some corner cases that pathname is null
14
+ if (pathname) {
15
+ // This is the proxy to the API in case the accept header is 'application/json'
16
+ return config.settings.devProxyToApiPath && pathname.startsWith('/++api++');
17
+ } else {
18
+ return false;
19
+ }
15
20
  };
16
21
 
17
22
  let _env = null;
@@ -19,6 +19,15 @@
19
19
  vertical-align: @headerVerticalAlign;
20
20
  }
21
21
 
22
+ // use sorting icons from icons.woff instead of assuming it's font awesome
23
+ .ui.sortable.table thead th.ascending::after {
24
+ content: '\E9EC';
25
+ }
26
+
27
+ .ui.sortable.table thead th.descending::after {
28
+ content: '\E9EB';
29
+ }
30
+
22
31
  .ui.table tr > th:first-child {
23
32
  border-left: none;
24
33
  }