@wordpress/dataviews 10.3.1-next.2f1c7c01b.0 → 10.4.1-next.dc3f6d3c1.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 (149) hide show
  1. package/CHANGELOG.md +23 -5
  2. package/README.md +413 -148
  3. package/build/components/dataviews-filters/filter.js +11 -1
  4. package/build/components/dataviews-filters/filter.js.map +2 -2
  5. package/build/components/dataviews-view-config/index.js +11 -396
  6. package/build/components/dataviews-view-config/index.js.map +3 -3
  7. package/build/components/dataviews-view-config/properties-section.js +177 -0
  8. package/build/components/dataviews-view-config/properties-section.js.map +7 -0
  9. package/build/constants.js +3 -0
  10. package/build/constants.js.map +2 -2
  11. package/build/dataform-controls/date.js +23 -7
  12. package/build/dataform-controls/date.js.map +2 -2
  13. package/build/dataform-controls/email.js +1 -1
  14. package/build/dataform-controls/email.js.map +1 -1
  15. package/build/dataform-layouts/details/index.js +78 -0
  16. package/build/dataform-layouts/details/index.js.map +7 -0
  17. package/build/dataform-layouts/index.js +5 -0
  18. package/build/dataform-layouts/index.js.map +3 -3
  19. package/build/dataform-layouts/normalize-form.js +5 -0
  20. package/build/dataform-layouts/normalize-form.js.map +2 -2
  21. package/build/dataviews-layouts/index.js +9 -0
  22. package/build/dataviews-layouts/index.js.map +3 -3
  23. package/build/dataviews-layouts/picker-table/index.js +422 -0
  24. package/build/dataviews-layouts/picker-table/index.js.map +7 -0
  25. package/build/dataviews-layouts/table/column-header-menu.js.map +2 -2
  26. package/build/dataviews-layouts/table/column-primary.js +1 -6
  27. package/build/dataviews-layouts/table/column-primary.js.map +2 -2
  28. package/build/dataviews-layouts/table/index.js +47 -2
  29. package/build/dataviews-layouts/table/index.js.map +2 -2
  30. package/build/field-types/date.js +4 -2
  31. package/build/field-types/date.js.map +2 -2
  32. package/build/types/dataform.js.map +1 -1
  33. package/build/types/dataviews.js.map +1 -1
  34. package/build/types/field-api.js.map +1 -1
  35. package/build/utils/normalize-fields.js +23 -3
  36. package/build/utils/normalize-fields.js.map +2 -2
  37. package/build/utils/week-starts-on.js +59 -0
  38. package/build/utils/week-starts-on.js.map +7 -0
  39. package/build-module/components/dataviews-filters/filter.js +11 -1
  40. package/build-module/components/dataviews-filters/filter.js.map +2 -2
  41. package/build-module/components/dataviews-view-config/index.js +15 -412
  42. package/build-module/components/dataviews-view-config/index.js.map +2 -2
  43. package/build-module/components/dataviews-view-config/properties-section.js +149 -0
  44. package/build-module/components/dataviews-view-config/properties-section.js.map +7 -0
  45. package/build-module/constants.js +2 -0
  46. package/build-module/constants.js.map +2 -2
  47. package/build-module/dataform-controls/date.js +23 -7
  48. package/build-module/dataform-controls/date.js.map +2 -2
  49. package/build-module/dataform-controls/email.js +2 -2
  50. package/build-module/dataform-controls/email.js.map +1 -1
  51. package/build-module/dataform-layouts/details/index.js +47 -0
  52. package/build-module/dataform-layouts/details/index.js.map +7 -0
  53. package/build-module/dataform-layouts/index.js +5 -0
  54. package/build-module/dataform-layouts/index.js.map +2 -2
  55. package/build-module/dataform-layouts/normalize-form.js +5 -0
  56. package/build-module/dataform-layouts/normalize-form.js.map +2 -2
  57. package/build-module/dataviews-layouts/index.js +11 -1
  58. package/build-module/dataviews-layouts/index.js.map +2 -2
  59. package/build-module/dataviews-layouts/picker-table/index.js +397 -0
  60. package/build-module/dataviews-layouts/picker-table/index.js.map +7 -0
  61. package/build-module/dataviews-layouts/table/column-header-menu.js.map +2 -2
  62. package/build-module/dataviews-layouts/table/column-primary.js +1 -6
  63. package/build-module/dataviews-layouts/table/column-primary.js.map +2 -2
  64. package/build-module/dataviews-layouts/table/index.js +48 -3
  65. package/build-module/dataviews-layouts/table/index.js.map +2 -2
  66. package/build-module/field-types/date.js +5 -3
  67. package/build-module/field-types/date.js.map +2 -2
  68. package/build-module/utils/normalize-fields.js +23 -3
  69. package/build-module/utils/normalize-fields.js.map +2 -2
  70. package/build-module/utils/week-starts-on.js +32 -0
  71. package/build-module/utils/week-starts-on.js.map +7 -0
  72. package/build-style/style-rtl.css +58 -54
  73. package/build-style/style.css +58 -54
  74. package/build-types/components/dataviews-filters/filter.d.ts.map +1 -1
  75. package/build-types/components/dataviews-filters/utils.d.ts.map +1 -1
  76. package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
  77. package/build-types/components/dataviews-view-config/properties-section.d.ts +4 -0
  78. package/build-types/components/dataviews-view-config/properties-section.d.ts.map +1 -0
  79. package/build-types/constants.d.ts +1 -0
  80. package/build-types/constants.d.ts.map +1 -1
  81. package/build-types/dataform-controls/date.d.ts.map +1 -1
  82. package/build-types/dataform-layouts/details/index.d.ts +6 -0
  83. package/build-types/dataform-layouts/details/index.d.ts.map +1 -0
  84. package/build-types/dataform-layouts/get-summary-fields.d.ts.map +1 -1
  85. package/build-types/dataform-layouts/index.d.ts +5 -0
  86. package/build-types/dataform-layouts/index.d.ts.map +1 -1
  87. package/build-types/dataform-layouts/normalize-form.d.ts.map +1 -1
  88. package/build-types/dataviews-layouts/index.d.ts +8 -0
  89. package/build-types/dataviews-layouts/index.d.ts.map +1 -1
  90. package/build-types/dataviews-layouts/picker-table/index.d.ts +4 -0
  91. package/build-types/dataviews-layouts/picker-table/index.d.ts.map +1 -0
  92. package/build-types/dataviews-layouts/table/column-header-menu.d.ts +3 -3
  93. package/build-types/dataviews-layouts/table/column-header-menu.d.ts.map +1 -1
  94. package/build-types/dataviews-layouts/table/column-primary.d.ts.map +1 -1
  95. package/build-types/dataviews-layouts/table/index.d.ts.map +1 -1
  96. package/build-types/field-types/date.d.ts.map +1 -1
  97. package/build-types/stories/dataform.story.d.ts +3 -0
  98. package/build-types/stories/dataform.story.d.ts.map +1 -1
  99. package/build-types/stories/dataviews-picker.story.d.ts +2 -0
  100. package/build-types/stories/dataviews-picker.story.d.ts.map +1 -1
  101. package/build-types/stories/dataviews.story.d.ts +7 -1
  102. package/build-types/stories/dataviews.story.d.ts.map +1 -1
  103. package/build-types/stories/field-types.story.d.ts +27 -1
  104. package/build-types/stories/field-types.story.d.ts.map +1 -1
  105. package/build-types/types/dataform.d.ts +11 -3
  106. package/build-types/types/dataform.d.ts.map +1 -1
  107. package/build-types/types/dataviews.d.ts +23 -2
  108. package/build-types/types/dataviews.d.ts.map +1 -1
  109. package/build-types/types/field-api.d.ts +28 -1
  110. package/build-types/types/field-api.d.ts.map +1 -1
  111. package/build-types/utils/normalize-fields.d.ts.map +1 -1
  112. package/build-types/utils/week-starts-on.d.ts +20 -0
  113. package/build-types/utils/week-starts-on.d.ts.map +1 -0
  114. package/build-wp/index.js +1497 -1188
  115. package/package.json +15 -15
  116. package/src/components/dataviews/style.scss +2 -0
  117. package/src/components/dataviews-filters/filter.tsx +11 -1
  118. package/src/components/dataviews-footer/style.scss +1 -1
  119. package/src/components/dataviews-view-config/index.tsx +8 -504
  120. package/src/components/dataviews-view-config/properties-section.tsx +201 -0
  121. package/src/components/dataviews-view-config/style.scss +2 -39
  122. package/src/constants.ts +1 -0
  123. package/src/dataform-controls/date.tsx +24 -6
  124. package/src/dataform-controls/email.tsx +2 -2
  125. package/src/dataform-layouts/details/index.tsx +71 -0
  126. package/src/dataform-layouts/details/style.scss +5 -0
  127. package/src/dataform-layouts/index.tsx +5 -0
  128. package/src/dataform-layouts/normalize-form.ts +6 -0
  129. package/src/dataviews-layouts/index.ts +10 -0
  130. package/src/dataviews-layouts/list/style.scss +1 -0
  131. package/src/dataviews-layouts/picker-table/index.tsx +487 -0
  132. package/src/dataviews-layouts/picker-table/style.scss +47 -0
  133. package/src/dataviews-layouts/table/column-header-menu.tsx +3 -2
  134. package/src/dataviews-layouts/table/column-primary.tsx +4 -7
  135. package/src/dataviews-layouts/table/index.tsx +55 -2
  136. package/src/dataviews-layouts/table/style.scss +36 -19
  137. package/src/field-types/date.tsx +11 -5
  138. package/src/stories/dataform.story.tsx +84 -0
  139. package/src/stories/dataviews-picker.story.tsx +11 -6
  140. package/src/stories/dataviews.story.tsx +10 -2
  141. package/src/stories/field-types.story.tsx +67 -2
  142. package/src/style.scss +2 -0
  143. package/src/test/normalize-fields.ts +53 -0
  144. package/src/types/dataform.ts +18 -3
  145. package/src/types/dataviews.ts +36 -2
  146. package/src/types/field-api.ts +42 -1
  147. package/src/utils/normalize-fields.ts +51 -2
  148. package/src/utils/week-starts-on.ts +46 -0
  149. package/tsconfig.tsbuildinfo +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/dataviews",
3
- "version": "10.3.1-next.2f1c7c01b.0",
3
+ "version": "10.4.1-next.dc3f6d3c1.0",
4
4
  "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -44,19 +44,19 @@
44
44
  "sideEffects": false,
45
45
  "dependencies": {
46
46
  "@ariakit/react": "^0.4.15",
47
- "@wordpress/base-styles": "^6.10.1-next.2f1c7c01b.0",
48
- "@wordpress/components": "^30.7.2-next.2f1c7c01b.0",
49
- "@wordpress/compose": "^7.34.1-next.2f1c7c01b.0",
50
- "@wordpress/data": "^10.34.1-next.2f1c7c01b.0",
51
- "@wordpress/date": "^5.34.1-next.2f1c7c01b.0",
52
- "@wordpress/element": "^6.34.1-next.2f1c7c01b.0",
53
- "@wordpress/i18n": "^6.7.1-next.2f1c7c01b.0",
54
- "@wordpress/icons": "^11.1.1-next.2f1c7c01b.0",
55
- "@wordpress/keycodes": "^4.34.1-next.2f1c7c01b.0",
56
- "@wordpress/primitives": "^4.34.1-next.2f1c7c01b.0",
57
- "@wordpress/private-apis": "^1.34.1-next.2f1c7c01b.0",
58
- "@wordpress/url": "^4.34.1-next.2f1c7c01b.0",
59
- "@wordpress/warning": "^3.34.1-next.2f1c7c01b.0",
47
+ "@wordpress/base-styles": "^6.11.1-next.dc3f6d3c1.0",
48
+ "@wordpress/components": "^30.8.2-next.dc3f6d3c1.0",
49
+ "@wordpress/compose": "^7.35.1-next.dc3f6d3c1.0",
50
+ "@wordpress/data": "^10.35.1-next.dc3f6d3c1.0",
51
+ "@wordpress/date": "^5.35.1-next.dc3f6d3c1.0",
52
+ "@wordpress/element": "^6.35.1-next.dc3f6d3c1.0",
53
+ "@wordpress/i18n": "^6.8.1-next.dc3f6d3c1.0",
54
+ "@wordpress/icons": "^11.2.1-next.dc3f6d3c1.0",
55
+ "@wordpress/keycodes": "^4.35.1-next.dc3f6d3c1.0",
56
+ "@wordpress/primitives": "^4.35.1-next.dc3f6d3c1.0",
57
+ "@wordpress/private-apis": "^1.35.1-next.dc3f6d3c1.0",
58
+ "@wordpress/url": "^4.35.1-next.dc3f6d3c1.0",
59
+ "@wordpress/warning": "^3.35.1-next.dc3f6d3c1.0",
60
60
  "clsx": "^2.1.1",
61
61
  "colord": "^2.7.0",
62
62
  "date-fns": "^4.1.0",
@@ -74,5 +74,5 @@
74
74
  "scripts": {
75
75
  "build:wp": "node build"
76
76
  },
77
- "gitHead": "c6ddcdf455bc02567a2c9e03de6862a2061b85e8"
77
+ "gitHead": "f73b5e69b34fbaccfb8c47783f4f993059ff1a41"
78
78
  }
@@ -14,6 +14,7 @@
14
14
  flex-direction: column;
15
15
  font-size: $default-font-size;
16
16
  line-height: $default-line-height;
17
+ background-color: inherit;
17
18
  }
18
19
 
19
20
  .dataviews__view-actions,
@@ -23,6 +24,7 @@
23
24
  flex-shrink: 0;
24
25
  position: sticky;
25
26
  left: 0;
27
+ background-color: inherit;
26
28
 
27
29
  @media not (prefers-reduced-motion) {
28
30
  transition: padding ease-out 0.1s;
@@ -19,6 +19,7 @@ import {
19
19
  import { __, sprintf } from '@wordpress/i18n';
20
20
  import { useRef, createInterpolateElement } from '@wordpress/element';
21
21
  import { closeSmall } from '@wordpress/icons';
22
+ import { dateI18n, getDate } from '@wordpress/date';
22
23
 
23
24
  const ENTER = 'Enter';
24
25
  const SPACE = ' ';
@@ -498,7 +499,16 @@ export default function Filter( {
498
499
  const field = fields.find( ( f ) => f.id === filter.field );
499
500
  let label = filterInView.value;
500
501
 
501
- if ( field?.type === 'datetime' && typeof label === 'string' ) {
502
+ if ( field?.type === 'date' && typeof label === 'string' ) {
503
+ try {
504
+ const dateValue = parseDateTime( label );
505
+ if ( dateValue !== null ) {
506
+ label = dateI18n( field.format.date, getDate( label ) );
507
+ }
508
+ } catch ( e ) {
509
+ label = filterInView.value;
510
+ }
511
+ } else if ( field?.type === 'datetime' && typeof label === 'string' ) {
502
512
  try {
503
513
  const dateValue = parseDateTime( label );
504
514
  if ( dateValue !== null ) {
@@ -6,7 +6,7 @@
6
6
  position: sticky;
7
7
  bottom: 0;
8
8
  left: 0;
9
- background-color: $white;
9
+ background-color: inherit;
10
10
  padding: $grid-unit-15 $grid-unit-60;
11
11
  border-top: $border-width solid $gray-100;
12
12
  flex-shrink: 0;
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import type { ChangeEvent, ReactNode } from 'react';
5
- import clsx from 'clsx';
4
+ import type { ChangeEvent } from 'react';
6
5
 
7
6
  /**
8
7
  * WordPress dependencies
@@ -15,28 +14,16 @@ import {
15
14
  __experimentalToggleGroupControlOption as ToggleGroupControlOption,
16
15
  __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon,
17
16
  SelectControl,
18
- __experimentalItemGroup as ItemGroup,
19
- __experimentalItem as Item,
20
17
  __experimentalGrid as Grid,
21
18
  __experimentalVStack as VStack,
22
19
  __experimentalHStack as HStack,
23
20
  __experimentalHeading as Heading,
24
21
  __experimentalText as Text,
25
22
  privateApis as componentsPrivateApis,
26
- BaseControl,
27
- Icon,
28
23
  } from '@wordpress/components';
29
- import { __, _x, sprintf } from '@wordpress/i18n';
30
- import { memo, useContext, useMemo, useState } from '@wordpress/element';
31
- import {
32
- chevronDown,
33
- chevronUp,
34
- cog,
35
- seen,
36
- unseen,
37
- lock,
38
- moreVertical,
39
- } from '@wordpress/icons';
24
+ import { __, _x } from '@wordpress/i18n';
25
+ import { memo, useContext, useMemo } from '@wordpress/element';
26
+ import { cog } from '@wordpress/icons';
40
27
  import warning from '@wordpress/warning';
41
28
  import { useInstanceId } from '@wordpress/compose';
42
29
 
@@ -45,9 +32,10 @@ import { useInstanceId } from '@wordpress/compose';
45
32
  */
46
33
  import { SORTING_DIRECTIONS, sortIcons, sortLabels } from '../../constants';
47
34
  import { VIEW_LAYOUTS } from '../../dataviews-layouts';
48
- import type { NormalizedField, View } from '../../types';
35
+ import type { View } from '../../types';
49
36
  import DataViewsContext from '../dataviews-context';
50
37
  import InfiniteScrollToggle from './infinite-scroll-toggle';
38
+ import { PropertiesSection } from './properties-section';
51
39
  import { unlock } from '../../lock-unlock';
52
40
 
53
41
  const { Menu } = unlock( componentsPrivateApis );
@@ -100,6 +88,7 @@ export function ViewTypeMenu() {
100
88
  case 'grid':
101
89
  case 'table':
102
90
  case 'pickerGrid':
91
+ case 'pickerTable':
103
92
  const viewWithoutLayout = { ...view };
104
93
  if ( 'layout' in viewWithoutLayout ) {
105
94
  delete viewWithoutLayout.layout;
@@ -261,489 +250,6 @@ function ItemsPerPageControl() {
261
250
  );
262
251
  }
263
252
 
264
- function PreviewOptions( {
265
- previewOptions,
266
- onChangePreviewOption,
267
- onMenuOpenChange,
268
- activeOption,
269
- }: {
270
- previewOptions?: Array< { label: string; id: string } >;
271
- onChangePreviewOption?: ( newPreviewOption: string ) => void;
272
- onMenuOpenChange: ( isOpen: boolean ) => void;
273
- activeOption?: string;
274
- } ) {
275
- const focusPreviewOptionsField = ( id: string ) => {
276
- // Focus the visibility button to avoid focus loss.
277
- // Our code is safe against the component being unmounted, so we don't need to worry about cleaning the timeout.
278
- // eslint-disable-next-line @wordpress/react-no-unsafe-timeout
279
- setTimeout( () => {
280
- const element = document.querySelector(
281
- `.dataviews-field-control__field-${ id } .dataviews-field-control__field-preview-options-button`
282
- );
283
- if ( element instanceof HTMLElement ) {
284
- element.focus();
285
- }
286
- }, 50 );
287
- };
288
- return (
289
- <Menu onOpenChange={ onMenuOpenChange }>
290
- <Menu.TriggerButton
291
- render={
292
- <Button
293
- className="dataviews-field-control__field-preview-options-button"
294
- size="compact"
295
- icon={ moreVertical }
296
- label={ __( 'Preview' ) }
297
- />
298
- }
299
- />
300
- <Menu.Popover>
301
- { previewOptions?.map( ( { id, label } ) => {
302
- return (
303
- <Menu.RadioItem
304
- key={ id }
305
- value={ id }
306
- checked={ id === activeOption }
307
- onChange={ () => {
308
- onChangePreviewOption?.( id );
309
- focusPreviewOptionsField( id );
310
- } }
311
- >
312
- <Menu.ItemLabel>{ label }</Menu.ItemLabel>
313
- </Menu.RadioItem>
314
- );
315
- } ) }
316
- </Menu.Popover>
317
- </Menu>
318
- );
319
- }
320
- function FieldItem( {
321
- field,
322
- label,
323
- description,
324
- isVisible,
325
- isFirst,
326
- isLast,
327
- canMove = true,
328
- onToggleVisibility,
329
- onMoveUp,
330
- onMoveDown,
331
- previewOptions,
332
- onChangePreviewOption,
333
- }: {
334
- field: NormalizedField< any >;
335
- label?: string;
336
- description?: string;
337
- isVisible: boolean;
338
- isFirst?: boolean;
339
- isLast?: boolean;
340
- canMove?: boolean;
341
- onToggleVisibility?: () => void;
342
- onMoveUp?: () => void;
343
- onMoveDown?: () => void;
344
- previewOptions?: Array< { label: string; id: string } >;
345
- onChangePreviewOption?: ( newPreviewOption: string ) => void;
346
- } ) {
347
- const [ isChangingPreviewOption, setIsChangingPreviewOption ] =
348
- useState< boolean >( false );
349
-
350
- const focusVisibilityField = () => {
351
- // Focus the visibility button to avoid focus loss.
352
- // Our code is safe against the component being unmounted, so we don't need to worry about cleaning the timeout.
353
- // eslint-disable-next-line @wordpress/react-no-unsafe-timeout
354
- setTimeout( () => {
355
- const element = document.querySelector(
356
- `.dataviews-field-control__field-${ field.id } .dataviews-field-control__field-visibility-button`
357
- );
358
- if ( element instanceof HTMLElement ) {
359
- element.focus();
360
- }
361
- }, 50 );
362
- };
363
-
364
- return (
365
- <Item>
366
- <HStack
367
- expanded
368
- className={ clsx(
369
- 'dataviews-field-control__field',
370
- `dataviews-field-control__field-${ field.id }`,
371
- // The actions are hidden when the mouse is not hovering the item, or focus
372
- // is outside the item.
373
- // For actions that require a popover, a menu etc, that would mean that when the interactive element
374
- // opens and the focus goes there the actions would be hidden.
375
- // To avoid that we add a class to the item, that makes sure actions are visible while there is some
376
- // interaction with the item.
377
- { 'is-interacting': isChangingPreviewOption }
378
- ) }
379
- justify="flex-start"
380
- >
381
- <span className="dataviews-field-control__icon">
382
- { ! canMove && ! field.enableHiding && (
383
- <Icon icon={ lock } />
384
- ) }
385
- </span>
386
- <span className="dataviews-field-control__label-sub-label-container">
387
- <span className="dataviews-field-control__label">
388
- { label || field.label }
389
- </span>
390
- { description && (
391
- <span className="dataviews-field-control__sub-label">
392
- { description }
393
- </span>
394
- ) }
395
- </span>
396
- <HStack
397
- justify="flex-end"
398
- expanded={ false }
399
- className="dataviews-field-control__actions"
400
- >
401
- { isVisible && (
402
- <>
403
- <Button
404
- disabled={ isFirst || ! canMove }
405
- accessibleWhenDisabled
406
- size="compact"
407
- onClick={ onMoveUp }
408
- icon={ chevronUp }
409
- label={
410
- isFirst || ! canMove
411
- ? __( "This field can't be moved up" )
412
- : sprintf(
413
- /* translators: %s: field label */
414
- __( 'Move %s up' ),
415
- field.label
416
- )
417
- }
418
- />
419
- <Button
420
- disabled={ isLast || ! canMove }
421
- accessibleWhenDisabled
422
- size="compact"
423
- onClick={ onMoveDown }
424
- icon={ chevronDown }
425
- label={
426
- isLast || ! canMove
427
- ? __( "This field can't be moved down" )
428
- : sprintf(
429
- /* translators: %s: field label */
430
- __( 'Move %s down' ),
431
- field.label
432
- )
433
- }
434
- />
435
- </>
436
- ) }
437
- { onToggleVisibility && (
438
- <Button
439
- className="dataviews-field-control__field-visibility-button"
440
- disabled={ ! field.enableHiding }
441
- accessibleWhenDisabled
442
- size="compact"
443
- onClick={ () => {
444
- onToggleVisibility();
445
- focusVisibilityField();
446
- } }
447
- icon={ isVisible ? unseen : seen }
448
- label={
449
- isVisible
450
- ? sprintf(
451
- /* translators: %s: field label */
452
- _x( 'Hide %s', 'field' ),
453
- field.label
454
- )
455
- : sprintf(
456
- /* translators: %s: field label */
457
- _x( 'Show %s', 'field' ),
458
- field.label
459
- )
460
- }
461
- />
462
- ) }
463
- { previewOptions && (
464
- <PreviewOptions
465
- previewOptions={ previewOptions }
466
- onChangePreviewOption={ onChangePreviewOption }
467
- onMenuOpenChange={ setIsChangingPreviewOption }
468
- activeOption={ field.id }
469
- />
470
- ) }
471
- </HStack>
472
- </HStack>
473
- </Item>
474
- );
475
- }
476
-
477
- function RegularFieldItem( {
478
- index,
479
- field,
480
- view,
481
- onChangeView,
482
- }: {
483
- index?: number;
484
- field: NormalizedField< any >;
485
- view: View;
486
- onChangeView: ( view: View ) => void;
487
- } ) {
488
- const visibleFieldIds = view.fields ?? [];
489
- const isVisible =
490
- index !== undefined && visibleFieldIds.includes( field.id );
491
-
492
- return (
493
- <FieldItem
494
- field={ field }
495
- isVisible={ isVisible }
496
- isFirst={ index !== undefined && index < 1 }
497
- isLast={
498
- index !== undefined && index === visibleFieldIds.length - 1
499
- }
500
- onToggleVisibility={ () => {
501
- onChangeView( {
502
- ...view,
503
- fields: isVisible
504
- ? visibleFieldIds.filter(
505
- ( fieldId ) => fieldId !== field.id
506
- )
507
- : [ ...visibleFieldIds, field.id ],
508
- } );
509
- } }
510
- onMoveUp={
511
- index !== undefined
512
- ? () => {
513
- onChangeView( {
514
- ...view,
515
- fields: [
516
- ...( visibleFieldIds.slice(
517
- 0,
518
- index - 1
519
- ) ?? [] ),
520
- field.id,
521
- visibleFieldIds[ index - 1 ],
522
- ...visibleFieldIds.slice( index + 1 ),
523
- ],
524
- } );
525
- }
526
- : undefined
527
- }
528
- onMoveDown={
529
- index !== undefined
530
- ? () => {
531
- onChangeView( {
532
- ...view,
533
- fields: [
534
- ...( visibleFieldIds.slice( 0, index ) ??
535
- [] ),
536
- visibleFieldIds[ index + 1 ],
537
- field.id,
538
- ...visibleFieldIds.slice( index + 2 ),
539
- ],
540
- } );
541
- }
542
- : undefined
543
- }
544
- />
545
- );
546
- }
547
-
548
- function isDefined< T >( item: T | undefined ): item is T {
549
- return !! item;
550
- }
551
-
552
- function FieldControl() {
553
- const { view, fields, onChangeView } = useContext( DataViewsContext );
554
-
555
- const togglableFields = [
556
- view?.titleField,
557
- view?.mediaField,
558
- view?.descriptionField,
559
- ].filter( Boolean );
560
- const visibleFieldIds = view.fields ?? [];
561
- const hiddenFields = fields.filter(
562
- ( f ) =>
563
- ! visibleFieldIds.includes( f.id ) &&
564
- ! togglableFields.includes( f.id ) &&
565
- f.type !== 'media' &&
566
- f.enableHiding !== false
567
- );
568
- let visibleFields = visibleFieldIds
569
- .map( ( fieldId ) => fields.find( ( f ) => f.id === fieldId ) )
570
- .filter( isDefined );
571
-
572
- if ( ! visibleFields?.length && ! hiddenFields?.length ) {
573
- return null;
574
- }
575
- const titleField = fields.find( ( f ) => f.id === view.titleField );
576
- const previewField = fields.find( ( f ) => f.id === view.mediaField );
577
- const descriptionField = fields.find(
578
- ( f ) => f.id === view.descriptionField
579
- );
580
-
581
- const previewFields = fields.filter( ( f ) => f.type === 'media' );
582
-
583
- let previewFieldUI;
584
- if ( previewFields.length > 1 ) {
585
- const isPreviewFieldVisible =
586
- isDefined( previewField ) && ( view.showMedia ?? true );
587
- previewFieldUI = isDefined( previewField ) && (
588
- <FieldItem
589
- key={ previewField.id }
590
- field={ previewField }
591
- label={ __( 'Preview' ) }
592
- description={ previewField.label }
593
- isVisible={ isPreviewFieldVisible }
594
- onToggleVisibility={ () => {
595
- onChangeView( {
596
- ...view,
597
- showMedia: ! isPreviewFieldVisible,
598
- } );
599
- } }
600
- canMove={ false }
601
- previewOptions={ previewFields.map( ( field ) => ( {
602
- label: field.label,
603
- id: field.id,
604
- } ) ) }
605
- onChangePreviewOption={ ( newPreviewId ) =>
606
- onChangeView( { ...view, mediaField: newPreviewId } )
607
- }
608
- />
609
- );
610
- }
611
- const lockedFields = [
612
- {
613
- field: titleField,
614
- isVisibleFlag: 'showTitle',
615
- },
616
- {
617
- field: previewField,
618
- isVisibleFlag: 'showMedia',
619
- ui: previewFieldUI,
620
- },
621
- {
622
- field: descriptionField,
623
- isVisibleFlag: 'showDescription',
624
- },
625
- ].filter( ( { field } ) => isDefined( field ) );
626
- let visibleLockedFields = lockedFields.filter(
627
- ( { field, isVisibleFlag } ) =>
628
- // @ts-expect-error
629
- isDefined( field ) && ( view[ isVisibleFlag ] ?? true )
630
- ) as Array< {
631
- field: NormalizedField< any >;
632
- isVisibleFlag: string;
633
- ui?: ReactNode;
634
- } >;
635
-
636
- // If only one locked field is visible, prevent it from being hidden.
637
- if ( visibleLockedFields.length === 1 ) {
638
- visibleLockedFields = visibleLockedFields.map( ( locked ) => ( {
639
- ...locked,
640
- field: { ...locked.field, enableHiding: false },
641
- } ) );
642
- }
643
-
644
- // If no locked fields are visible but there are visibleFields, lock the last visible field.
645
- if ( visibleLockedFields.length === 0 && visibleFields.length === 1 ) {
646
- visibleFields = [ { ...visibleFields[ 0 ], enableHiding: false } ];
647
- }
648
-
649
- const hiddenLockedFields = lockedFields.filter(
650
- ( { field, isVisibleFlag } ) =>
651
- // @ts-expect-error
652
- isDefined( field ) && ! ( view[ isVisibleFlag ] ?? true )
653
- ) as Array< {
654
- field: NormalizedField< any >;
655
- isVisibleFlag: string;
656
- ui?: ReactNode;
657
- } >;
658
-
659
- return (
660
- <VStack className="dataviews-field-control" spacing={ 6 }>
661
- <VStack className="dataviews-view-config__properties" spacing={ 0 }>
662
- { ( visibleLockedFields.length > 0 ||
663
- !! visibleFields?.length ) && (
664
- <ItemGroup isBordered isSeparated>
665
- { visibleLockedFields.map(
666
- ( { field, isVisibleFlag, ui } ) => {
667
- return (
668
- ui ?? (
669
- <FieldItem
670
- key={ field.id }
671
- field={ field }
672
- isVisible
673
- onToggleVisibility={ () => {
674
- onChangeView( {
675
- ...view,
676
- [ isVisibleFlag ]: false,
677
- } );
678
- } }
679
- canMove={ false }
680
- />
681
- )
682
- );
683
- }
684
- ) }
685
-
686
- { visibleFields.map( ( field, index ) => (
687
- <RegularFieldItem
688
- key={ field.id }
689
- field={ field }
690
- view={ view }
691
- onChangeView={ onChangeView }
692
- index={ index }
693
- />
694
- ) ) }
695
- </ItemGroup>
696
- ) }
697
- </VStack>
698
-
699
- { ( !! hiddenFields?.length || !! hiddenLockedFields.length ) && (
700
- <VStack spacing={ 4 }>
701
- <BaseControl.VisualLabel style={ { margin: 0 } }>
702
- { __( 'Hidden' ) }
703
- </BaseControl.VisualLabel>
704
- <VStack
705
- className="dataviews-view-config__properties"
706
- spacing={ 0 }
707
- >
708
- <ItemGroup isBordered isSeparated>
709
- { hiddenLockedFields.length > 0 &&
710
- hiddenLockedFields.map(
711
- ( { field, isVisibleFlag, ui } ) => {
712
- return (
713
- ui ?? (
714
- <FieldItem
715
- key={ field.id }
716
- field={ field }
717
- isVisible={ false }
718
- onToggleVisibility={ () => {
719
- onChangeView( {
720
- ...view,
721
- [ isVisibleFlag ]:
722
- true,
723
- } );
724
- } }
725
- canMove={ false }
726
- />
727
- )
728
- );
729
- }
730
- ) }
731
- { hiddenFields.map( ( field ) => (
732
- <RegularFieldItem
733
- key={ field.id }
734
- field={ field }
735
- view={ view }
736
- onChangeView={ onChangeView }
737
- />
738
- ) ) }
739
- </ItemGroup>
740
- </VStack>
741
- </VStack>
742
- ) }
743
- </VStack>
744
- );
745
- }
746
-
747
253
  function SettingsSection( {
748
254
  title,
749
255
  description,
@@ -826,9 +332,7 @@ export function DataviewsViewConfigDropdown() {
826
332
  ) }
827
333
  <InfiniteScrollToggle />
828
334
  <ItemsPerPageControl />
829
- </SettingsSection>
830
- <SettingsSection title={ __( 'Properties' ) }>
831
- <FieldControl />
335
+ <PropertiesSection />
832
336
  </SettingsSection>
833
337
  </VStack>
834
338
  </DropdownContentWrapper>