@wordpress/dataviews 4.7.0 → 4.8.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.
Files changed (98) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +596 -89
  3. package/build/components/dataform-combined-edit/index.js +12 -6
  4. package/build/components/dataform-combined-edit/index.js.map +1 -1
  5. package/build/components/dataviews/index.js +8 -1
  6. package/build/components/dataviews/index.js.map +1 -1
  7. package/build/components/dataviews-context/index.js +2 -0
  8. package/build/components/dataviews-context/index.js.map +1 -1
  9. package/build/components/dataviews-layout/index.js +5 -1
  10. package/build/components/dataviews-layout/index.js.map +1 -1
  11. package/build/components/form-field-visibility/index.js +32 -0
  12. package/build/components/form-field-visibility/index.js.map +1 -0
  13. package/build/dataforms-layouts/panel/index.js +8 -2
  14. package/build/dataforms-layouts/panel/index.js.map +1 -1
  15. package/build/dataforms-layouts/regular/index.js +8 -2
  16. package/build/dataforms-layouts/regular/index.js.map +1 -1
  17. package/build/dataviews-layouts/grid/index.js +14 -3
  18. package/build/dataviews-layouts/grid/index.js.map +1 -1
  19. package/build/dataviews-layouts/table/index.js +22 -5
  20. package/build/dataviews-layouts/table/index.js.map +1 -1
  21. package/build/dataviews-layouts/utils/get-clickable-item-props.js +25 -0
  22. package/build/dataviews-layouts/utils/get-clickable-item-props.js.map +1 -0
  23. package/build/normalize-fields.js +16 -3
  24. package/build/normalize-fields.js.map +1 -1
  25. package/build/types.js.map +1 -1
  26. package/build/validation.js +9 -0
  27. package/build/validation.js.map +1 -1
  28. package/build-module/components/dataform-combined-edit/index.js +12 -6
  29. package/build-module/components/dataform-combined-edit/index.js.map +1 -1
  30. package/build-module/components/dataviews/index.js +8 -1
  31. package/build-module/components/dataviews/index.js.map +1 -1
  32. package/build-module/components/dataviews-context/index.js +2 -0
  33. package/build-module/components/dataviews-context/index.js.map +1 -1
  34. package/build-module/components/dataviews-layout/index.js +5 -1
  35. package/build-module/components/dataviews-layout/index.js.map +1 -1
  36. package/build-module/components/form-field-visibility/index.js +26 -0
  37. package/build-module/components/form-field-visibility/index.js.map +1 -0
  38. package/build-module/dataforms-layouts/panel/index.js +7 -2
  39. package/build-module/dataforms-layouts/panel/index.js.map +1 -1
  40. package/build-module/dataforms-layouts/regular/index.js +7 -2
  41. package/build-module/dataforms-layouts/regular/index.js.map +1 -1
  42. package/build-module/dataviews-layouts/grid/index.js +14 -3
  43. package/build-module/dataviews-layouts/grid/index.js.map +1 -1
  44. package/build-module/dataviews-layouts/table/index.js +22 -5
  45. package/build-module/dataviews-layouts/table/index.js.map +1 -1
  46. package/build-module/dataviews-layouts/utils/get-clickable-item-props.js +19 -0
  47. package/build-module/dataviews-layouts/utils/get-clickable-item-props.js.map +1 -0
  48. package/build-module/normalize-fields.js +15 -3
  49. package/build-module/normalize-fields.js.map +1 -1
  50. package/build-module/types.js.map +1 -1
  51. package/build-module/validation.js +9 -0
  52. package/build-module/validation.js.map +1 -1
  53. package/build-style/style-rtl.css +14 -0
  54. package/build-style/style.css +14 -0
  55. package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
  56. package/build-types/components/dataform-combined-edit/index.d.ts.map +1 -1
  57. package/build-types/components/dataviews/index.d.ts +3 -1
  58. package/build-types/components/dataviews/index.d.ts.map +1 -1
  59. package/build-types/components/dataviews-context/index.d.ts +2 -0
  60. package/build-types/components/dataviews-context/index.d.ts.map +1 -1
  61. package/build-types/components/dataviews-layout/index.d.ts.map +1 -1
  62. package/build-types/components/form-field-visibility/index.d.ts +11 -0
  63. package/build-types/components/form-field-visibility/index.d.ts.map +1 -0
  64. package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -1
  65. package/build-types/dataforms-layouts/regular/index.d.ts.map +1 -1
  66. package/build-types/dataviews-layouts/grid/index.d.ts +1 -1
  67. package/build-types/dataviews-layouts/grid/index.d.ts.map +1 -1
  68. package/build-types/dataviews-layouts/table/index.d.ts +1 -1
  69. package/build-types/dataviews-layouts/table/index.d.ts.map +1 -1
  70. package/build-types/dataviews-layouts/utils/get-clickable-item-props.d.ts +14 -0
  71. package/build-types/dataviews-layouts/utils/get-clickable-item-props.d.ts.map +1 -0
  72. package/build-types/lock-unlock.d.ts +1 -1
  73. package/build-types/lock-unlock.d.ts.map +1 -1
  74. package/build-types/normalize-fields.d.ts.map +1 -1
  75. package/build-types/types.d.ts +6 -0
  76. package/build-types/types.d.ts.map +1 -1
  77. package/build-types/validation.d.ts +9 -0
  78. package/build-types/validation.d.ts.map +1 -1
  79. package/package.json +3 -3
  80. package/src/components/dataform/stories/index.story.tsx +19 -3
  81. package/src/components/dataform-combined-edit/index.tsx +10 -7
  82. package/src/components/dataform-combined-edit/style.scss +4 -0
  83. package/src/components/dataviews/index.tsx +10 -1
  84. package/src/components/dataviews/style.scss +9 -3
  85. package/src/components/dataviews-context/index.ts +4 -0
  86. package/src/components/dataviews-layout/index.tsx +4 -0
  87. package/src/components/form-field-visibility/index.tsx +32 -0
  88. package/src/dataforms-layouts/panel/index.tsx +9 -3
  89. package/src/dataforms-layouts/regular/index.tsx +9 -3
  90. package/src/dataviews-layouts/grid/index.tsx +29 -5
  91. package/src/dataviews-layouts/grid/style.scss +5 -0
  92. package/src/dataviews-layouts/table/index.tsx +34 -3
  93. package/src/dataviews-layouts/utils/get-clickable-item-props.ts +22 -0
  94. package/src/normalize-fields.ts +17 -2
  95. package/src/test/normalize-fields.ts +45 -0
  96. package/src/types.ts +7 -0
  97. package/src/validation.ts +9 -0
  98. package/tsconfig.tsbuildinfo +1 -1
@@ -24,11 +24,14 @@ import SingleSelectionCheckbox from '../../components/dataviews-selection-checkb
24
24
  import { useHasAPossibleBulkAction } from '../../components/dataviews-bulk-actions';
25
25
  import type { Action, NormalizedField, ViewGridProps } from '../../types';
26
26
  import type { SetSelection } from '../../private-types';
27
+ import getClickableItemProps from '../utils/get-clickable-item-props';
27
28
 
28
29
  interface GridItemProps< Item > {
29
30
  selection: string[];
30
31
  onChangeSelection: SetSelection;
31
32
  getItemId: ( item: Item ) => string;
33
+ onClickItem: ( item: Item ) => void;
34
+ isItemClickable: ( item: Item ) => boolean;
32
35
  item: Item;
33
36
  actions: Action< Item >[];
34
37
  mediaField?: NormalizedField< Item >;
@@ -41,6 +44,8 @@ interface GridItemProps< Item > {
41
44
  function GridItem< Item >( {
42
45
  selection,
43
46
  onChangeSelection,
47
+ onClickItem,
48
+ isItemClickable,
44
49
  getItemId,
45
50
  item,
46
51
  actions,
@@ -59,6 +64,21 @@ function GridItem< Item >( {
59
64
  const renderedPrimaryField = primaryField?.render ? (
60
65
  <primaryField.render item={ item } />
61
66
  ) : null;
67
+
68
+ const clickableMediaItemProps = getClickableItemProps(
69
+ item,
70
+ isItemClickable,
71
+ onClickItem,
72
+ 'dataviews-view-grid__media'
73
+ );
74
+
75
+ const clickablePrimaryItemProps = getClickableItemProps(
76
+ item,
77
+ isItemClickable,
78
+ onClickItem,
79
+ 'dataviews-view-grid__primary-field'
80
+ );
81
+
62
82
  return (
63
83
  <VStack
64
84
  spacing={ 0 }
@@ -81,9 +101,7 @@ function GridItem< Item >( {
81
101
  }
82
102
  } }
83
103
  >
84
- <div className="dataviews-view-grid__media">
85
- { renderedMediaField }
86
- </div>
104
+ <div { ...clickableMediaItemProps }>{ renderedMediaField }</div>
87
105
  <SingleSelectionCheckbox
88
106
  item={ item }
89
107
  selection={ selection }
@@ -96,8 +114,10 @@ function GridItem< Item >( {
96
114
  justify="space-between"
97
115
  className="dataviews-view-grid__title-actions"
98
116
  >
99
- <HStack className="dataviews-view-grid__primary-field">
100
- { renderedPrimaryField }
117
+ <HStack>
118
+ <div { ...clickablePrimaryItemProps }>
119
+ { renderedPrimaryField }
120
+ </div>
101
121
  </HStack>
102
122
  <ItemActions item={ item } actions={ actions } isCompact />
103
123
  </HStack>
@@ -170,6 +190,8 @@ export default function ViewGrid< Item >( {
170
190
  getItemId,
171
191
  isLoading,
172
192
  onChangeSelection,
193
+ onClickItem,
194
+ isItemClickable,
173
195
  selection,
174
196
  view,
175
197
  density,
@@ -223,6 +245,8 @@ export default function ViewGrid< Item >( {
223
245
  key={ getItemId( item ) }
224
246
  selection={ selection }
225
247
  onChangeSelection={ onChangeSelection }
248
+ onClickItem={ onClickItem }
249
+ isItemClickable={ isItemClickable }
226
250
  getItemId={ getItemId }
227
251
  item={ item }
228
252
  actions={ actions }
@@ -17,8 +17,13 @@
17
17
 
18
18
  .dataviews-view-grid__primary-field {
19
19
  min-height: $grid-unit-40; // Preserve layout when there is no ellipsis button
20
+
21
+ &--clickable {
22
+ width: fit-content;
23
+ }
20
24
  }
21
25
 
26
+
22
27
  &.is-selected {
23
28
  .dataviews-view-grid__fields .dataviews-view-grid__field .dataviews-view-grid__field-value {
24
29
  color: $gray-900;
@@ -35,11 +35,14 @@ import type {
35
35
  import type { SetSelection } from '../../private-types';
36
36
  import ColumnHeaderMenu from './column-header-menu';
37
37
  import { getVisibleFieldIds } from '../index';
38
+ import getClickableItemProps from '../utils/get-clickable-item-props';
38
39
 
39
40
  interface TableColumnFieldProps< Item > {
40
41
  primaryField?: NormalizedField< Item >;
41
42
  field: NormalizedField< Item >;
42
43
  item: Item;
44
+ isItemClickable: ( item: Item ) => boolean;
45
+ onClickItem: ( item: Item ) => void;
43
46
  }
44
47
 
45
48
  interface TableColumnCombinedProps< Item > {
@@ -48,6 +51,8 @@ interface TableColumnCombinedProps< Item > {
48
51
  field: CombinedField;
49
52
  item: Item;
50
53
  view: ViewTableType;
54
+ isItemClickable: ( item: Item ) => boolean;
55
+ onClickItem: ( item: Item ) => void;
51
56
  }
52
57
 
53
58
  interface TableColumnProps< Item > {
@@ -56,6 +61,8 @@ interface TableColumnProps< Item > {
56
61
  item: Item;
57
62
  column: string;
58
63
  view: ViewTableType;
64
+ isItemClickable: ( item: Item ) => boolean;
65
+ onClickItem: ( item: Item ) => void;
59
66
  }
60
67
 
61
68
  interface TableRowProps< Item > {
@@ -69,6 +76,8 @@ interface TableRowProps< Item > {
69
76
  selection: string[];
70
77
  getItemId: ( item: Item ) => string;
71
78
  onChangeSelection: SetSelection;
79
+ isItemClickable: ( item: Item ) => boolean;
80
+ onClickItem: ( item: Item ) => void;
72
81
  }
73
82
 
74
83
  function TableColumn< Item >( {
@@ -102,15 +111,29 @@ function TableColumnField< Item >( {
102
111
  primaryField,
103
112
  item,
104
113
  field,
114
+ isItemClickable,
115
+ onClickItem,
105
116
  }: TableColumnFieldProps< Item > ) {
117
+ const isPrimaryField = primaryField?.id === field.id;
118
+ const isItemClickableField = ( i: Item ) =>
119
+ isItemClickable( i ) && isPrimaryField;
120
+
121
+ const clickableProps = getClickableItemProps(
122
+ item,
123
+ isItemClickableField,
124
+ onClickItem,
125
+ 'dataviews-view-table__cell-content'
126
+ );
127
+
106
128
  return (
107
129
  <div
108
130
  className={ clsx( 'dataviews-view-table__cell-content-wrapper', {
109
- 'dataviews-view-table__primary-field':
110
- primaryField?.id === field.id,
131
+ 'dataviews-view-table__primary-field': isPrimaryField,
111
132
  } ) }
112
133
  >
113
- <field.render { ...{ item } } />
134
+ <div { ...clickableProps }>
135
+ <field.render { ...{ item } } />
136
+ </div>
114
137
  </div>
115
138
  );
116
139
  }
@@ -139,6 +162,8 @@ function TableRow< Item >( {
139
162
  primaryField,
140
163
  selection,
141
164
  getItemId,
165
+ isItemClickable,
166
+ onClickItem,
142
167
  onChangeSelection,
143
168
  }: TableRowProps< Item > ) {
144
169
  const hasPossibleBulkAction = useHasAPossibleBulkAction( actions, item );
@@ -214,6 +239,8 @@ function TableRow< Item >( {
214
239
  <td key={ column } style={ { width, maxWidth, minWidth } }>
215
240
  <TableColumn
216
241
  primaryField={ primaryField }
242
+ isItemClickable={ isItemClickable }
243
+ onClickItem={ onClickItem }
217
244
  fields={ fields }
218
245
  item={ item }
219
246
  column={ column }
@@ -252,6 +279,8 @@ function ViewTable< Item >( {
252
279
  onChangeSelection,
253
280
  selection,
254
281
  setOpenedFilter,
282
+ onClickItem,
283
+ isItemClickable,
255
284
  view,
256
285
  }: ViewTableProps< Item > ) {
257
286
  const headerMenuRefs = useRef<
@@ -392,6 +421,8 @@ function ViewTable< Item >( {
392
421
  selection={ selection }
393
422
  getItemId={ getItemId }
394
423
  onChangeSelection={ onChangeSelection }
424
+ onClickItem={ onClickItem }
425
+ isItemClickable={ isItemClickable }
395
426
  />
396
427
  ) ) }
397
428
  </tbody>
@@ -0,0 +1,22 @@
1
+ export default function getClickableItemProps< Item >(
2
+ item: Item,
3
+ isItemClickable: ( item: Item ) => boolean,
4
+ onClickItem: ( item: Item ) => void,
5
+ className: string
6
+ ) {
7
+ if ( ! isItemClickable( item ) ) {
8
+ return { className };
9
+ }
10
+
11
+ return {
12
+ className: `${ className } ${ className }--clickable`,
13
+ role: 'button',
14
+ tabIndex: 0,
15
+ onClick: () => onClickItem( item ),
16
+ onKeyDown: ( event: React.KeyboardEvent ) => {
17
+ if ( event.key === 'Enter' || event.key === '' ) {
18
+ onClickItem( item );
19
+ }
20
+ },
21
+ };
22
+ }
@@ -11,6 +11,22 @@ import type {
11
11
  import { getControl } from './dataform-controls';
12
12
  import DataFormCombinedEdit from './components/dataform-combined-edit';
13
13
 
14
+ const getValueFromId =
15
+ ( id: string ) =>
16
+ ( { item }: { item: any } ) => {
17
+ const path = id.split( '.' );
18
+ let value = item;
19
+ for ( const segment of path ) {
20
+ if ( value.hasOwnProperty( segment ) ) {
21
+ value = value[ segment ];
22
+ } else {
23
+ value = undefined;
24
+ }
25
+ }
26
+
27
+ return value;
28
+ };
29
+
14
30
  /**
15
31
  * Apply default values and normalize the fields config.
16
32
  *
@@ -23,8 +39,7 @@ export function normalizeFields< Item >(
23
39
  return fields.map( ( field ) => {
24
40
  const fieldTypeDefinition = getFieldTypeDefinition( field.type );
25
41
 
26
- const getValue =
27
- field.getValue || ( ( { item } ) => ( item as any )[ field.id ] );
42
+ const getValue = field.getValue || getValueFromId( field.id );
28
43
 
29
44
  const sort =
30
45
  field.sort ??
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import { normalizeFields } from '../normalize-fields';
5
+ import type { Field } from '../types';
6
+
7
+ describe( 'normalizeFields: default getValue', () => {
8
+ describe( 'getValue from ID', () => {
9
+ it( 'user', () => {
10
+ const item = { user: 'value' };
11
+ const fields: Field< {} >[] = [
12
+ {
13
+ id: 'user',
14
+ },
15
+ ];
16
+ const normalizedFields = normalizeFields( fields );
17
+ const result = normalizedFields[ 0 ].getValue( { item } );
18
+ expect( result ).toBe( 'value' );
19
+ } );
20
+
21
+ it( 'user.name', () => {
22
+ const item = { user: { name: 'value' } };
23
+ const fields: Field< {} >[] = [
24
+ {
25
+ id: 'user.name',
26
+ },
27
+ ];
28
+ const normalizedFields = normalizeFields( fields );
29
+ const result = normalizedFields[ 0 ].getValue( { item } );
30
+ expect( result ).toBe( 'value' );
31
+ } );
32
+
33
+ it( 'user.name.first', () => {
34
+ const item = { user: { name: { first: 'value' } } };
35
+ const fields: Field< {} >[] = [
36
+ {
37
+ id: 'user.name.first',
38
+ },
39
+ ];
40
+ const normalizedFields = normalizeFields( fields );
41
+ const result = normalizedFields[ 0 ].getValue( { item } );
42
+ expect( result ).toBe( 'value' );
43
+ } );
44
+ } );
45
+ } );
package/src/types.ts CHANGED
@@ -123,6 +123,11 @@ export type Field< Item > = {
123
123
  */
124
124
  isValid?: ( item: Item, context?: ValidationContext ) => boolean;
125
125
 
126
+ /**
127
+ * Callback used to decide if a field should be displayed.
128
+ */
129
+ isVisible?: ( item: Item ) => boolean;
130
+
126
131
  /**
127
132
  * Whether the field is sortable.
128
133
  */
@@ -493,6 +498,8 @@ export interface ViewBaseProps< Item > {
493
498
  onChangeSelection: SetSelection;
494
499
  selection: string[];
495
500
  setOpenedFilter: ( fieldId: string ) => void;
501
+ onClickItem: ( item: Item ) => void;
502
+ isItemClickable: ( item: Item ) => boolean;
496
503
  view: View;
497
504
  density: number;
498
505
  }
package/src/validation.ts CHANGED
@@ -4,6 +4,15 @@
4
4
  import { normalizeFields } from './normalize-fields';
5
5
  import type { Field, Form } from './types';
6
6
 
7
+ /**
8
+ * Whether or not the given item's value is valid according to the fields and form config.
9
+ *
10
+ * @param item The item to validate.
11
+ * @param fields Fields config.
12
+ * @param form Form config.
13
+ *
14
+ * @return A boolean indicating if the item is valid (true) or not (false).
15
+ */
7
16
  export function isItemValid< Item >(
8
17
  item: Item,
9
18
  fields: Field< Item >[],