@wordpress/dataviews 4.4.3 → 4.5.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 (63) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +4 -0
  3. package/build/components/dataform-combined-edit/index.js +67 -0
  4. package/build/components/dataform-combined-edit/index.js.map +1 -0
  5. package/build/components/dataviews-view-config/index.js +49 -38
  6. package/build/components/dataviews-view-config/index.js.map +1 -1
  7. package/build/dataforms-layouts/get-visible-fields.js +21 -0
  8. package/build/dataforms-layouts/get-visible-fields.js.map +1 -0
  9. package/build/dataforms-layouts/panel/index.js +5 -12
  10. package/build/dataforms-layouts/panel/index.js.map +1 -1
  11. package/build/dataforms-layouts/regular/index.js +2 -6
  12. package/build/dataforms-layouts/regular/index.js.map +1 -1
  13. package/build/normalize-fields.js +21 -0
  14. package/build/normalize-fields.js.map +1 -1
  15. package/build/types.js.map +1 -1
  16. package/build/validation.js.map +1 -1
  17. package/build-module/components/dataform-combined-edit/index.js +62 -0
  18. package/build-module/components/dataform-combined-edit/index.js.map +1 -0
  19. package/build-module/components/dataviews-view-config/index.js +50 -39
  20. package/build-module/components/dataviews-view-config/index.js.map +1 -1
  21. package/build-module/dataforms-layouts/get-visible-fields.js +14 -0
  22. package/build-module/dataforms-layouts/get-visible-fields.js.map +1 -0
  23. package/build-module/dataforms-layouts/panel/index.js +5 -12
  24. package/build-module/dataforms-layouts/panel/index.js.map +1 -1
  25. package/build-module/dataforms-layouts/regular/index.js +2 -6
  26. package/build-module/dataforms-layouts/regular/index.js.map +1 -1
  27. package/build-module/normalize-fields.js +20 -0
  28. package/build-module/normalize-fields.js.map +1 -1
  29. package/build-module/types.js.map +1 -1
  30. package/build-module/validation.js.map +1 -1
  31. package/build-style/style-rtl.css +20 -15
  32. package/build-style/style.css +20 -15
  33. package/build-types/components/dataform/stories/index.story.d.ts +23 -0
  34. package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
  35. package/build-types/components/dataform-combined-edit/index.d.ts +7 -0
  36. package/build-types/components/dataform-combined-edit/index.d.ts.map +1 -0
  37. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  38. package/build-types/dataforms-layouts/get-visible-fields.d.ts +3 -0
  39. package/build-types/dataforms-layouts/get-visible-fields.d.ts.map +1 -0
  40. package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -1
  41. package/build-types/dataforms-layouts/regular/index.d.ts.map +1 -1
  42. package/build-types/normalize-fields.d.ts +9 -1
  43. package/build-types/normalize-fields.d.ts.map +1 -1
  44. package/build-types/types.d.ts +27 -8
  45. package/build-types/types.d.ts.map +1 -1
  46. package/build-types/validation.d.ts +1 -1
  47. package/build-types/validation.d.ts.map +1 -1
  48. package/package.json +11 -11
  49. package/src/components/dataform/stories/index.story.tsx +65 -0
  50. package/src/components/dataform-combined-edit/index.tsx +66 -0
  51. package/src/components/dataform-combined-edit/style.scss +12 -0
  52. package/src/components/dataviews-filters/style.scss +0 -1
  53. package/src/components/dataviews-view-config/index.tsx +52 -40
  54. package/src/components/dataviews-view-config/style.scss +5 -8
  55. package/src/dataforms-layouts/get-visible-fields.ts +29 -0
  56. package/src/dataforms-layouts/panel/index.tsx +9 -10
  57. package/src/dataforms-layouts/panel/style.scss +0 -13
  58. package/src/dataforms-layouts/regular/index.tsx +8 -7
  59. package/src/normalize-fields.ts +33 -1
  60. package/src/style.scss +1 -0
  61. package/src/types.ts +29 -9
  62. package/src/validation.ts +1 -1
  63. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,66 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import {
5
+ __experimentalHStack as HStack,
6
+ __experimentalVStack as VStack,
7
+ __experimentalHeading as Heading,
8
+ __experimentalSpacer as Spacer,
9
+ } from '@wordpress/components';
10
+
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import type { DataFormCombinedEditProps, NormalizedField } from '../../types';
15
+
16
+ function Header( { title }: { title: string } ) {
17
+ return (
18
+ <VStack className="dataforms-layouts__dropdown-header" spacing={ 4 }>
19
+ <HStack alignment="center">
20
+ <Heading level={ 2 } size={ 13 }>
21
+ { title }
22
+ </Heading>
23
+ <Spacer />
24
+ </HStack>
25
+ </VStack>
26
+ );
27
+ }
28
+
29
+ function DataFormCombinedEdit< Item >( {
30
+ field,
31
+ data,
32
+ onChange,
33
+ hideLabelFromVision,
34
+ }: DataFormCombinedEditProps< Item > ) {
35
+ const className = 'dataforms-combined-edit';
36
+ const visibleChildren = ( field.children ?? [] )
37
+ .map( ( fieldId ) => field.fields.find( ( { id } ) => id === fieldId ) )
38
+ .filter(
39
+ ( childField ): childField is NormalizedField< Item > =>
40
+ !! childField
41
+ );
42
+ const children = visibleChildren.map( ( child ) => {
43
+ return (
44
+ <div className="dataforms-combined-edit__field" key={ child.id }>
45
+ <child.Edit
46
+ data={ data }
47
+ field={ child }
48
+ onChange={ onChange }
49
+ />
50
+ </div>
51
+ );
52
+ } );
53
+
54
+ const Stack = field.direction === 'horizontal' ? HStack : VStack;
55
+
56
+ return (
57
+ <>
58
+ { ! hideLabelFromVision && <Header title={ field.label } /> }
59
+ <Stack spacing={ 4 } className={ className } as="fieldset">
60
+ { children }
61
+ </Stack>
62
+ </>
63
+ );
64
+ }
65
+
66
+ export default DataFormCombinedEdit;
@@ -0,0 +1,12 @@
1
+ .dataforms-layouts-panel__field-dropdown {
2
+ .dataforms-combined-edit {
3
+ border: none;
4
+ padding: 0;
5
+ }
6
+ }
7
+
8
+ .dataforms-combined-edit {
9
+ &__field {
10
+ flex: 1 1 auto;
11
+ }
12
+ }
@@ -160,7 +160,6 @@
160
160
  }
161
161
 
162
162
  .dataviews-filters__search-widget-listbox {
163
- max-height: $grid-unit * 23;
164
163
  padding: $grid-unit-05;
165
164
  overflow: auto;
166
165
  }
@@ -8,6 +8,7 @@ import type { ChangeEvent } from 'react';
8
8
  */
9
9
  import {
10
10
  Button,
11
+ __experimentalDropdownContentWrapper as DropdownContentWrapper,
11
12
  Dropdown,
12
13
  __experimentalToggleGroupControl as ToggleGroupControl,
13
14
  __experimentalToggleGroupControlOption as ToggleGroupControlOption,
@@ -27,6 +28,7 @@ import { __, _x, sprintf } from '@wordpress/i18n';
27
28
  import { memo, useContext, useMemo } from '@wordpress/element';
28
29
  import { chevronDown, chevronUp, cog, seen, unseen } from '@wordpress/icons';
29
30
  import warning from '@wordpress/warning';
31
+ import { useInstanceId } from '@wordpress/compose';
30
32
 
31
33
  /**
32
34
  * Internal dependencies
@@ -55,6 +57,8 @@ interface ViewTypeMenuProps {
55
57
  defaultLayouts?: SupportedLayouts;
56
58
  }
57
59
 
60
+ const DATAVIEWS_CONFIG_POPOVER_PROPS = { placement: 'bottom-end', offset: 9 };
61
+
58
62
  function ViewTypeMenu( {
59
63
  defaultLayouts = { list: {}, grid: {}, table: {} },
60
64
  }: ViewTypeMenuProps ) {
@@ -510,7 +514,7 @@ function SettingsSection( {
510
514
  );
511
515
  }
512
516
 
513
- function DataviewsViewConfigContent( {
517
+ function DataviewsViewConfigDropdown( {
514
518
  density,
515
519
  setDensity,
516
520
  }: {
@@ -518,25 +522,52 @@ function DataviewsViewConfigContent( {
518
522
  setDensity: React.Dispatch< React.SetStateAction< number > >;
519
523
  } ) {
520
524
  const { view } = useContext( DataViewsContext );
525
+ const popoverId = useInstanceId(
526
+ _DataViewsViewConfig,
527
+ 'dataviews-view-config-dropdown'
528
+ );
529
+
521
530
  return (
522
- <VStack className="dataviews-view-config" spacing={ 6 }>
523
- <SettingsSection title={ __( 'Appearance' ) }>
524
- <HStack expanded className="is-divided-in-two">
525
- <SortFieldControl />
526
- <SortDirectionControl />
527
- </HStack>
528
- { view.type === LAYOUT_GRID && (
529
- <DensityPicker
530
- density={ density }
531
- setDensity={ setDensity }
531
+ <Dropdown
532
+ popoverProps={ {
533
+ ...DATAVIEWS_CONFIG_POPOVER_PROPS,
534
+ id: popoverId,
535
+ } }
536
+ renderToggle={ ( { onToggle, isOpen } ) => {
537
+ return (
538
+ <Button
539
+ size="compact"
540
+ icon={ cog }
541
+ label={ _x( 'View options', 'View is used as a noun' ) }
542
+ onClick={ onToggle }
543
+ aria-expanded={ isOpen ? 'true' : 'false' }
544
+ aria-controls={ popoverId }
532
545
  />
533
- ) }
534
- <ItemsPerPageControl />
535
- </SettingsSection>
536
- <SettingsSection title={ __( 'Properties' ) }>
537
- <FieldControl />
538
- </SettingsSection>
539
- </VStack>
546
+ );
547
+ } }
548
+ renderContent={ () => (
549
+ <DropdownContentWrapper paddingSize="medium">
550
+ <VStack className="dataviews-view-config" spacing={ 6 }>
551
+ <SettingsSection title={ __( 'Appearance' ) }>
552
+ <HStack expanded className="is-divided-in-two">
553
+ <SortFieldControl />
554
+ <SortDirectionControl />
555
+ </HStack>
556
+ { view.type === LAYOUT_GRID && (
557
+ <DensityPicker
558
+ density={ density }
559
+ setDensity={ setDensity }
560
+ />
561
+ ) }
562
+ <ItemsPerPageControl />
563
+ </SettingsSection>
564
+ <SettingsSection title={ __( 'Properties' ) }>
565
+ <FieldControl />
566
+ </SettingsSection>
567
+ </VStack>
568
+ </DropdownContentWrapper>
569
+ ) }
570
+ />
540
571
  );
541
572
  }
542
573
 
@@ -552,28 +583,9 @@ function _DataViewsViewConfig( {
552
583
  return (
553
584
  <>
554
585
  <ViewTypeMenu defaultLayouts={ defaultLayouts } />
555
- <Dropdown
556
- popoverProps={ { placement: 'bottom-end', offset: 9 } }
557
- contentClassName="dataviews-view-config"
558
- renderToggle={ ( { onToggle } ) => {
559
- return (
560
- <Button
561
- size="compact"
562
- icon={ cog }
563
- label={ _x(
564
- 'View options',
565
- 'View is used as a noun'
566
- ) }
567
- onClick={ onToggle }
568
- />
569
- );
570
- } }
571
- renderContent={ () => (
572
- <DataviewsViewConfigContent
573
- density={ density }
574
- setDensity={ setDensity }
575
- />
576
- ) }
586
+ <DataviewsViewConfigDropdown
587
+ density={ density }
588
+ setDensity={ setDensity }
577
589
  />
578
590
  </>
579
591
  );
@@ -1,12 +1,9 @@
1
1
  .dataviews-view-config {
2
- .components-popover__content {
3
- width: 320px;
4
- /* stylelint-disable-next-line property-no-unknown -- the linter needs to be updated to accepted the container-type property */
5
- container-type: inline-size;
6
- padding: $grid-unit-20;
7
- font-size: $default-font-size;
8
- line-height: $default-line-height;
9
- }
2
+ width: 320px;
3
+ /* stylelint-disable-next-line property-no-unknown -- the linter needs to be updated to accepted the container-type property */
4
+ container-type: inline-size;
5
+ font-size: $default-font-size;
6
+ line-height: $default-line-height;
10
7
  }
11
8
 
12
9
  .dataviews-view-config__sort-direction .components-toggle-group-control-option-base {
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import { normalizeCombinedFields } from '../normalize-fields';
5
+ import type {
6
+ Field,
7
+ CombinedFormField,
8
+ NormalizedCombinedFormField,
9
+ } from '../types';
10
+
11
+ export function getVisibleFields< Item >(
12
+ fields: Field< Item >[],
13
+ formFields: string[] = [],
14
+ combinedFields?: CombinedFormField< Item >[]
15
+ ): Field< Item >[] {
16
+ const visibleFields: Array<
17
+ Field< Item > | NormalizedCombinedFormField< Item >
18
+ > = [ ...fields ];
19
+ if ( combinedFields ) {
20
+ visibleFields.push(
21
+ ...normalizeCombinedFields( combinedFields, fields )
22
+ );
23
+ }
24
+ return formFields
25
+ .map( ( fieldId ) =>
26
+ visibleFields.find( ( { id } ) => id === fieldId )
27
+ )
28
+ .filter( ( field ): field is Field< Item > => !! field );
29
+ }
@@ -17,7 +17,8 @@ import { closeSmall } from '@wordpress/icons';
17
17
  * Internal dependencies
18
18
  */
19
19
  import { normalizeFields } from '../../normalize-fields';
20
- import type { DataFormProps, NormalizedField, Field } from '../../types';
20
+ import { getVisibleFields } from '../get-visible-fields';
21
+ import type { DataFormProps, NormalizedField } from '../../types';
21
22
 
22
23
  interface FormFieldProps< Item > {
23
24
  data: Item;
@@ -44,12 +45,10 @@ function DropdownHeader( {
44
45
  <Spacer />
45
46
  { onClose && (
46
47
  <Button
47
- // TODO: Switch to `true` (40px size) if possible
48
- __next40pxDefaultSize={ false }
49
- className="dataforms-layouts-panel__dropdown-header-action"
50
48
  label={ __( 'Close' ) }
51
49
  icon={ closeSmall }
52
50
  onClick={ onClose }
51
+ size="small"
53
52
  />
54
53
  ) }
55
54
  </HStack>
@@ -144,13 +143,13 @@ export default function FormPanel< Item >( {
144
143
  const visibleFields = useMemo(
145
144
  () =>
146
145
  normalizeFields(
147
- ( form.fields ?? [] )
148
- .map( ( fieldId ) =>
149
- fields.find( ( { id } ) => id === fieldId )
150
- )
151
- .filter( ( field ): field is Field< Item > => !! field )
146
+ getVisibleFields< Item >(
147
+ fields,
148
+ form.fields,
149
+ form.combinedFields
150
+ )
152
151
  ),
153
- [ fields, form.fields ]
152
+ [ fields, form.fields, form.combinedFields ]
154
153
  );
155
154
 
156
155
  return (
@@ -44,16 +44,3 @@
44
44
  .dataforms-layouts-panel__dropdown-header {
45
45
  margin-bottom: $grid-unit-20;
46
46
  }
47
-
48
- [class].dataforms-layouts-panel__dropdown-header-action {
49
- height: $icon-size;
50
-
51
- &.has-icon {
52
- min-width: $icon-size;
53
- padding: 0;
54
- }
55
-
56
- &:not(.has-icon) {
57
- text-decoration: underline;
58
- }
59
- }
@@ -8,7 +8,8 @@ import { useMemo } from '@wordpress/element';
8
8
  * Internal dependencies
9
9
  */
10
10
  import { normalizeFields } from '../../normalize-fields';
11
- import type { DataFormProps, Field } from '../../types';
11
+ import { getVisibleFields } from '../get-visible-fields';
12
+ import type { DataFormProps } from '../../types';
12
13
 
13
14
  export default function FormRegular< Item >( {
14
15
  data,
@@ -19,13 +20,13 @@ export default function FormRegular< Item >( {
19
20
  const visibleFields = useMemo(
20
21
  () =>
21
22
  normalizeFields(
22
- ( form.fields ?? [] )
23
- .map( ( fieldId ) =>
24
- fields.find( ( { id } ) => id === fieldId )
25
- )
26
- .filter( ( field ): field is Field< Item > => !! field )
23
+ getVisibleFields< Item >(
24
+ fields,
25
+ form.fields,
26
+ form.combinedFields
27
+ )
27
28
  ),
28
- [ fields, form.fields ]
29
+ [ fields, form.fields, form.combinedFields ]
29
30
  );
30
31
 
31
32
  return (
@@ -2,8 +2,14 @@
2
2
  * Internal dependencies
3
3
  */
4
4
  import getFieldTypeDefinition from './field-types';
5
- import type { Field, NormalizedField } from './types';
5
+ import type {
6
+ CombinedFormField,
7
+ Field,
8
+ NormalizedField,
9
+ NormalizedCombinedFormField,
10
+ } from './types';
6
11
  import { getControl } from './dataform-controls';
12
+ import DataFormCombinedEdit from './components/dataform-combined-edit';
7
13
 
8
14
  /**
9
15
  * Apply default values and normalize the fields config.
@@ -66,3 +72,29 @@ export function normalizeFields< Item >(
66
72
  };
67
73
  } );
68
74
  }
75
+
76
+ /**
77
+ * Apply default values and normalize the fields config.
78
+ *
79
+ * @param combinedFields combined field list.
80
+ * @param fields Fields config.
81
+ * @return Normalized fields config.
82
+ */
83
+ export function normalizeCombinedFields< Item >(
84
+ combinedFields: CombinedFormField< Item >[],
85
+ fields: Field< Item >[]
86
+ ): NormalizedCombinedFormField< Item >[] {
87
+ return combinedFields.map( ( combinedField ) => {
88
+ return {
89
+ ...combinedField,
90
+ Edit: DataFormCombinedEdit,
91
+ fields: normalizeFields(
92
+ combinedField.children
93
+ .map( ( fieldId ) =>
94
+ fields.find( ( { id } ) => id === fieldId )
95
+ )
96
+ .filter( ( field ): field is Field< Item > => !! field )
97
+ ),
98
+ };
99
+ } );
100
+ }
package/src/style.scss CHANGED
@@ -6,6 +6,7 @@
6
6
  @import "./components/dataviews-item-actions/style.scss";
7
7
  @import "./components/dataviews-selection-checkbox/style.scss";
8
8
  @import "./components/dataviews-view-config/style.scss";
9
+ @import "./components/dataform-combined-edit/style.scss";
9
10
 
10
11
  @import "./dataviews-layouts/grid/style.scss";
11
12
  @import "./dataviews-layouts/list/style.scss";
package/src/types.ts CHANGED
@@ -174,14 +174,6 @@ export type Fields< Item > = Field< Item >[];
174
174
 
175
175
  export type Data< Item > = Item[];
176
176
 
177
- /**
178
- * The form configuration.
179
- */
180
- export type Form = {
181
- type?: 'regular' | 'panel';
182
- fields?: string[];
183
- };
184
-
185
177
  export type DataFormControlProps< Item > = {
186
178
  data: Item;
187
179
  field: NormalizedField< Item >;
@@ -524,9 +516,37 @@ export interface SupportedLayouts {
524
516
  table?: Omit< ViewTable, 'type' >;
525
517
  }
526
518
 
519
+ export interface CombinedFormField< Item > extends CombinedField {
520
+ render?: ComponentType< { item: Item } >;
521
+ }
522
+
523
+ export interface DataFormCombinedEditProps< Item > {
524
+ field: NormalizedCombinedFormField< Item >;
525
+ data: Item;
526
+ onChange: ( value: Record< string, any > ) => void;
527
+ hideLabelFromVision?: boolean;
528
+ }
529
+
530
+ export type NormalizedCombinedFormField< Item > = CombinedFormField< Item > & {
531
+ fields: NormalizedField< Item >[];
532
+ Edit?: ComponentType< DataFormCombinedEditProps< Item > >;
533
+ };
534
+
535
+ /**
536
+ * The form configuration.
537
+ */
538
+ export type Form< Item > = {
539
+ type?: 'regular' | 'panel';
540
+ fields?: string[];
541
+ /**
542
+ * The fields to combine.
543
+ */
544
+ combinedFields?: CombinedFormField< Item >[];
545
+ };
546
+
527
547
  export interface DataFormProps< Item > {
528
548
  data: Item;
529
549
  fields: Field< Item >[];
530
- form: Form;
550
+ form: Form< Item >;
531
551
  onChange: ( value: Record< string, any > ) => void;
532
552
  }
package/src/validation.ts CHANGED
@@ -7,7 +7,7 @@ import type { Field, Form } from './types';
7
7
  export function isItemValid< Item >(
8
8
  item: Item,
9
9
  fields: Field< Item >[],
10
- form: Form
10
+ form: Form< Item >
11
11
  ): boolean {
12
12
  const _fields = normalizeFields(
13
13
  fields.filter( ( { id } ) => !! form.fields?.includes( id ) )