@wordpress/dataviews 4.22.0 → 5.0.1-next.719a03cbe.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/CHANGELOG.md +39 -0
- package/README.md +146 -32
- package/build/components/dataviews/index.js +71 -37
- package/build/components/dataviews/index.js.map +1 -1
- package/build/components/dataviews-context/index.js +15 -1
- package/build/components/dataviews-context/index.js.map +1 -1
- package/build/components/dataviews-filters/{filter-summary.js → filter.js} +108 -17
- package/build/components/dataviews-filters/filter.js.map +1 -0
- package/build/components/dataviews-filters/index.js +21 -20
- package/build/components/dataviews-filters/index.js.map +1 -1
- package/build/components/dataviews-filters/input-widget.js +76 -0
- package/build/components/dataviews-filters/input-widget.js.map +1 -0
- package/build/components/dataviews-filters/search-widget.js +33 -39
- package/build/components/dataviews-filters/search-widget.js.map +1 -1
- package/build/components/dataviews-filters/utils.js +25 -0
- package/build/components/dataviews-filters/utils.js.map +1 -0
- package/build/components/dataviews-item-actions/index.js +1 -1
- package/build/components/dataviews-item-actions/index.js.map +1 -1
- package/build/components/dataviews-layout/index.js +7 -2
- package/build/components/dataviews-layout/index.js.map +1 -1
- package/build/components/dataviews-pagination/index.js +4 -3
- package/build/components/dataviews-pagination/index.js.map +1 -1
- package/build/components/dataviews-selection-checkbox/index.js.map +1 -1
- package/build/components/dataviews-view-config/index.js +10 -19
- package/build/components/dataviews-view-config/index.js.map +1 -1
- package/build/constants.js +83 -2
- package/build/constants.js.map +1 -1
- package/build/dataform-controls/boolean.js +42 -0
- package/build/dataform-controls/boolean.js.map +1 -0
- package/build/dataform-controls/checkbox.js +44 -0
- package/build/dataform-controls/checkbox.js.map +1 -0
- package/build/dataform-controls/datetime.js +96 -2
- package/build/dataform-controls/datetime.js.map +1 -1
- package/build/dataform-controls/email.js +48 -0
- package/build/dataform-controls/email.js.map +1 -0
- package/build/dataform-controls/index.js +9 -1
- package/build/dataform-controls/index.js.map +1 -1
- package/build/dataform-controls/integer.js +49 -1
- package/build/dataform-controls/integer.js.map +1 -1
- package/build/dataform-controls/select.js +1 -0
- package/build/dataform-controls/select.js.map +1 -1
- package/build/dataform-controls/text.js +3 -1
- package/build/dataform-controls/text.js.map +1 -1
- package/build/dataform-controls/toggle-group.js +52 -0
- package/build/dataform-controls/toggle-group.js.map +1 -0
- package/build/dataforms-layouts/data-form-layout.js +1 -1
- package/build/dataforms-layouts/data-form-layout.js.map +1 -1
- package/build/dataforms-layouts/panel/index.js +14 -5
- package/build/dataforms-layouts/panel/index.js.map +1 -1
- package/build/dataforms-layouts/regular/index.js +23 -4
- package/build/dataforms-layouts/regular/index.js.map +1 -1
- package/build/dataviews-layouts/grid/index.js +31 -25
- package/build/dataviews-layouts/grid/index.js.map +1 -1
- package/build/dataviews-layouts/list/index.js +11 -6
- package/build/dataviews-layouts/list/index.js.map +1 -1
- package/build/dataviews-layouts/table/column-header-menu.js +9 -7
- package/build/dataviews-layouts/table/column-header-menu.js.map +1 -1
- package/build/dataviews-layouts/table/column-primary.js +18 -13
- package/build/dataviews-layouts/table/column-primary.js.map +1 -1
- package/build/dataviews-layouts/table/index.js +46 -14
- package/build/dataviews-layouts/table/index.js.map +1 -1
- package/build/dataviews-layouts/table/use-is-horizontal-scroll-end.js +65 -0
- package/build/dataviews-layouts/table/use-is-horizontal-scroll-end.js.map +1 -0
- package/build/dataviews-layouts/utils/item-click-wrapper.js +77 -0
- package/build/dataviews-layouts/utils/item-click-wrapper.js.map +1 -0
- package/build/field-types/array.js +62 -0
- package/build/field-types/array.js.map +1 -0
- package/build/field-types/boolean.js +71 -0
- package/build/field-types/boolean.js.map +1 -0
- package/build/field-types/datetime.js +19 -1
- package/build/field-types/datetime.js.map +1 -1
- package/build/field-types/email.js +60 -0
- package/build/field-types/email.js.map +1 -0
- package/build/field-types/index.js +38 -1
- package/build/field-types/index.js.map +1 -1
- package/build/field-types/integer.js +23 -1
- package/build/field-types/integer.js.map +1 -1
- package/build/field-types/media.js +31 -0
- package/build/field-types/media.js.map +1 -0
- package/build/field-types/text.js +23 -1
- package/build/field-types/text.js.map +1 -1
- package/build/filter-and-sort-data-view.js +152 -1
- package/build/filter-and-sort-data-view.js.map +1 -1
- package/build/normalize-fields.js +72 -11
- package/build/normalize-fields.js.map +1 -1
- package/build/types.js.map +1 -1
- package/build/utils.js +11 -19
- package/build/utils.js.map +1 -1
- package/build-module/components/dataviews/index.js +74 -40
- package/build-module/components/dataviews/index.js.map +1 -1
- package/build-module/components/dataviews-context/index.js +16 -2
- package/build-module/components/dataviews-context/index.js.map +1 -1
- package/build-module/components/dataviews-filters/filter.js +309 -0
- package/build-module/components/dataviews-filters/filter.js.map +1 -0
- package/build-module/components/dataviews-filters/index.js +22 -21
- package/build-module/components/dataviews-filters/index.js.map +1 -1
- package/build-module/components/dataviews-filters/input-widget.js +69 -0
- package/build-module/components/dataviews-filters/input-widget.js.map +1 -0
- package/build-module/components/dataviews-filters/search-widget.js +31 -37
- package/build-module/components/dataviews-filters/search-widget.js.map +1 -1
- package/build-module/components/dataviews-filters/utils.js +18 -0
- package/build-module/components/dataviews-filters/utils.js.map +1 -0
- package/build-module/components/dataviews-item-actions/index.js +1 -1
- package/build-module/components/dataviews-item-actions/index.js.map +1 -1
- package/build-module/components/dataviews-layout/index.js +7 -2
- package/build-module/components/dataviews-layout/index.js.map +1 -1
- package/build-module/components/dataviews-pagination/index.js +4 -4
- package/build-module/components/dataviews-pagination/index.js.map +1 -1
- package/build-module/components/dataviews-selection-checkbox/index.js.map +1 -1
- package/build-module/components/dataviews-view-config/index.js +9 -20
- package/build-module/components/dataviews-view-config/index.js.map +1 -1
- package/build-module/constants.js +82 -1
- package/build-module/constants.js.map +1 -1
- package/build-module/dataform-controls/boolean.js +35 -0
- package/build-module/dataform-controls/boolean.js.map +1 -0
- package/build-module/dataform-controls/checkbox.js +37 -0
- package/build-module/dataform-controls/checkbox.js.map +1 -0
- package/build-module/dataform-controls/datetime.js +98 -3
- package/build-module/dataform-controls/datetime.js.map +1 -1
- package/build-module/dataform-controls/email.js +41 -0
- package/build-module/dataform-controls/email.js.map +1 -0
- package/build-module/dataform-controls/index.js +9 -1
- package/build-module/dataform-controls/index.js.map +1 -1
- package/build-module/dataform-controls/integer.js +51 -3
- package/build-module/dataform-controls/integer.js.map +1 -1
- package/build-module/dataform-controls/select.js +1 -0
- package/build-module/dataform-controls/select.js.map +1 -1
- package/build-module/dataform-controls/text.js +3 -1
- package/build-module/dataform-controls/text.js.map +1 -1
- package/build-module/dataform-controls/toggle-group.js +45 -0
- package/build-module/dataform-controls/toggle-group.js.map +1 -0
- package/build-module/dataforms-layouts/data-form-layout.js +1 -1
- package/build-module/dataforms-layouts/data-form-layout.js.map +1 -1
- package/build-module/dataforms-layouts/panel/index.js +14 -5
- package/build-module/dataforms-layouts/panel/index.js.map +1 -1
- package/build-module/dataforms-layouts/regular/index.js +23 -4
- package/build-module/dataforms-layouts/regular/index.js.map +1 -1
- package/build-module/dataviews-layouts/grid/index.js +31 -26
- package/build-module/dataviews-layouts/grid/index.js.map +1 -1
- package/build-module/dataviews-layouts/list/index.js +11 -6
- package/build-module/dataviews-layouts/list/index.js.map +1 -1
- package/build-module/dataviews-layouts/table/column-header-menu.js +9 -7
- package/build-module/dataviews-layouts/table/column-header-menu.js.map +1 -1
- package/build-module/dataviews-layouts/table/column-primary.js +18 -12
- package/build-module/dataviews-layouts/table/column-primary.js.map +1 -1
- package/build-module/dataviews-layouts/table/index.js +47 -16
- package/build-module/dataviews-layouts/table/index.js.map +1 -1
- package/build-module/dataviews-layouts/table/use-is-horizontal-scroll-end.js +58 -0
- package/build-module/dataviews-layouts/table/use-is-horizontal-scroll-end.js.map +1 -0
- package/build-module/dataviews-layouts/utils/item-click-wrapper.js +71 -0
- package/build-module/dataviews-layouts/utils/item-click-wrapper.js.map +1 -0
- package/build-module/field-types/array.js +57 -0
- package/build-module/field-types/array.js.map +1 -0
- package/build-module/field-types/boolean.js +65 -0
- package/build-module/field-types/boolean.js.map +1 -0
- package/build-module/field-types/datetime.js +19 -1
- package/build-module/field-types/datetime.js.map +1 -1
- package/build-module/field-types/email.js +54 -0
- package/build-module/field-types/email.js.map +1 -0
- package/build-module/field-types/index.js +38 -1
- package/build-module/field-types/index.js.map +1 -1
- package/build-module/field-types/integer.js +23 -1
- package/build-module/field-types/integer.js.map +1 -1
- package/build-module/field-types/media.js +25 -0
- package/build-module/field-types/media.js.map +1 -0
- package/build-module/field-types/text.js +23 -1
- package/build-module/field-types/text.js.map +1 -1
- package/build-module/filter-and-sort-data-view.js +153 -2
- package/build-module/filter-and-sort-data-view.js.map +1 -1
- package/build-module/normalize-fields.js +72 -11
- package/build-module/normalize-fields.js.map +1 -1
- package/build-module/types.js.map +1 -1
- package/build-module/utils.js +10 -17
- package/build-module/utils.js.map +1 -1
- package/build-style/style-rtl.css +307 -13
- package/build-style/style.css +307 -13
- package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
- package/build-types/components/dataviews/index.d.ts +24 -3
- package/build-types/components/dataviews/index.d.ts.map +1 -1
- package/build-types/components/dataviews/stories/fixtures.d.ts +9 -1
- package/build-types/components/dataviews/stories/fixtures.d.ts.map +1 -1
- package/build-types/components/dataviews/stories/index.story.d.ts +22 -4
- package/build-types/components/dataviews/stories/index.story.d.ts.map +1 -1
- package/build-types/components/dataviews-context/index.d.ts +14 -1
- package/build-types/components/dataviews-context/index.d.ts.map +1 -1
- package/build-types/components/dataviews-filters/filter.d.ts +15 -0
- package/build-types/components/dataviews-filters/filter.d.ts.map +1 -0
- package/build-types/components/dataviews-filters/index.d.ts +3 -8
- package/build-types/components/dataviews-filters/index.d.ts.map +1 -1
- package/build-types/components/dataviews-filters/input-widget.d.ts +13 -0
- package/build-types/components/dataviews-filters/input-widget.d.ts.map +1 -0
- package/build-types/components/dataviews-filters/search-widget.d.ts +4 -5
- package/build-types/components/dataviews-filters/search-widget.d.ts.map +1 -1
- package/build-types/components/dataviews-filters/utils.d.ts +6 -0
- package/build-types/components/dataviews-filters/utils.d.ts.map +1 -0
- package/build-types/components/dataviews-layout/index.d.ts +5 -1
- package/build-types/components/dataviews-layout/index.d.ts.map +1 -1
- package/build-types/components/dataviews-pagination/index.d.ts +1 -1
- package/build-types/components/dataviews-pagination/index.d.ts.map +1 -1
- package/build-types/components/dataviews-selection-checkbox/index.d.ts +2 -2
- package/build-types/components/dataviews-selection-checkbox/index.d.ts.map +1 -1
- package/build-types/components/dataviews-view-config/index.d.ts +3 -4
- package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
- package/build-types/components/stories/index.story.d.ts +59 -0
- package/build-types/components/stories/index.story.d.ts.map +1 -0
- package/build-types/constants.d.ts +20 -3
- package/build-types/constants.d.ts.map +1 -1
- package/build-types/dataform-controls/boolean.d.ts +6 -0
- package/build-types/dataform-controls/boolean.d.ts.map +1 -0
- package/build-types/dataform-controls/checkbox.d.ts +6 -0
- package/build-types/dataform-controls/checkbox.d.ts.map +1 -0
- package/build-types/dataform-controls/datetime.d.ts +1 -1
- package/build-types/dataform-controls/datetime.d.ts.map +1 -1
- package/build-types/dataform-controls/email.d.ts +6 -0
- package/build-types/dataform-controls/email.d.ts.map +1 -0
- package/build-types/dataform-controls/index.d.ts +1 -1
- package/build-types/dataform-controls/index.d.ts.map +1 -1
- package/build-types/dataform-controls/integer.d.ts +1 -4
- package/build-types/dataform-controls/integer.d.ts.map +1 -1
- package/build-types/dataform-controls/select.d.ts.map +1 -1
- package/build-types/dataform-controls/text.d.ts.map +1 -1
- package/build-types/dataform-controls/toggle-group.d.ts +6 -0
- package/build-types/dataform-controls/toggle-group.d.ts.map +1 -0
- package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -1
- package/build-types/dataforms-layouts/regular/index.d.ts.map +1 -1
- package/build-types/dataviews-layouts/grid/index.d.ts +2 -1
- package/build-types/dataviews-layouts/grid/index.d.ts.map +1 -1
- package/build-types/dataviews-layouts/index.d.ts +3 -3
- package/build-types/dataviews-layouts/list/index.d.ts.map +1 -1
- package/build-types/dataviews-layouts/table/column-header-menu.d.ts.map +1 -1
- package/build-types/dataviews-layouts/table/column-primary.d.ts +8 -1
- package/build-types/dataviews-layouts/table/column-primary.d.ts.map +1 -1
- package/build-types/dataviews-layouts/table/index.d.ts +1 -1
- package/build-types/dataviews-layouts/table/index.d.ts.map +1 -1
- package/build-types/dataviews-layouts/table/use-is-horizontal-scroll-end.d.ts +19 -0
- package/build-types/dataviews-layouts/table/use-is-horizontal-scroll-end.d.ts.map +1 -0
- package/build-types/dataviews-layouts/utils/item-click-wrapper.d.ts +15 -0
- package/build-types/dataviews-layouts/utils/item-click-wrapper.d.ts.map +1 -0
- package/build-types/field-types/array.d.ts +7 -0
- package/build-types/field-types/array.d.ts.map +1 -0
- package/build-types/field-types/boolean.d.ts +19 -0
- package/build-types/field-types/boolean.d.ts.map +1 -0
- package/build-types/field-types/datetime.d.ts +7 -1
- package/build-types/field-types/datetime.d.ts.map +1 -1
- package/build-types/field-types/email.d.ts +19 -0
- package/build-types/field-types/email.d.ts.map +1 -0
- package/build-types/field-types/index.d.ts +2 -10
- package/build-types/field-types/index.d.ts.map +1 -1
- package/build-types/field-types/integer.d.ts +7 -1
- package/build-types/field-types/integer.d.ts.map +1 -1
- package/build-types/field-types/media.d.ts +16 -0
- package/build-types/field-types/media.d.ts.map +1 -0
- package/build-types/field-types/text.d.ts +7 -1
- package/build-types/field-types/text.d.ts.map +1 -1
- package/build-types/filter-and-sort-data-view.d.ts.map +1 -1
- package/build-types/normalize-fields.d.ts.map +1 -1
- package/build-types/types.d.ts +70 -8
- package/build-types/types.d.ts.map +1 -1
- package/build-types/utils.d.ts +5 -2
- package/build-types/utils.d.ts.map +1 -1
- package/build-wp/index.js +2545 -994
- package/package.json +18 -12
- package/src/components/dataform/stories/index.story.tsx +41 -20
- package/src/components/dataviews/index.tsx +108 -43
- package/src/components/dataviews/stories/fixtures.tsx +58 -13
- package/src/components/dataviews/stories/index.story.tsx +228 -7
- package/src/components/dataviews/stories/style.css +24 -3
- package/src/components/dataviews/style.scss +27 -0
- package/src/components/dataviews-context/index.ts +30 -2
- package/src/components/dataviews-filters/filter.tsx +603 -0
- package/src/components/dataviews-filters/index.tsx +23 -29
- package/src/components/dataviews-filters/input-widget.tsx +91 -0
- package/src/components/dataviews-filters/search-widget.tsx +51 -48
- package/src/components/dataviews-filters/style.scss +117 -14
- package/src/components/dataviews-filters/utils.ts +25 -0
- package/src/components/dataviews-item-actions/index.tsx +1 -1
- package/src/components/dataviews-layout/index.tsx +8 -1
- package/src/components/dataviews-pagination/index.tsx +4 -4
- package/src/components/dataviews-selection-checkbox/index.tsx +2 -2
- package/src/components/dataviews-view-config/index.tsx +10 -18
- package/src/components/stories/index.story.tsx +351 -0
- package/src/constants.ts +116 -1
- package/src/dataform-controls/boolean.tsx +30 -0
- package/src/dataform-controls/checkbox.tsx +31 -0
- package/src/dataform-controls/datetime.tsx +106 -2
- package/src/dataform-controls/email.tsx +42 -0
- package/src/dataform-controls/index.tsx +8 -0
- package/src/dataform-controls/integer.tsx +75 -1
- package/src/dataform-controls/select.tsx +1 -0
- package/src/dataform-controls/style.scss +5 -0
- package/src/dataform-controls/text.tsx +2 -1
- package/src/dataform-controls/toggle-group.tsx +59 -0
- package/src/dataforms-layouts/data-form-layout.tsx +1 -1
- package/src/dataforms-layouts/panel/index.tsx +19 -7
- package/src/dataforms-layouts/panel/style.scss +8 -1
- package/src/dataforms-layouts/regular/index.tsx +50 -17
- package/src/dataforms-layouts/regular/style.scss +4 -1
- package/src/dataviews-layouts/grid/index.tsx +47 -26
- package/src/dataviews-layouts/list/index.tsx +12 -5
- package/src/dataviews-layouts/table/column-header-menu.tsx +10 -8
- package/src/dataviews-layouts/table/column-primary.tsx +26 -13
- package/src/dataviews-layouts/table/index.tsx +74 -10
- package/src/dataviews-layouts/table/style.scss +37 -1
- package/src/dataviews-layouts/table/use-is-horizontal-scroll-end.ts +82 -0
- package/src/dataviews-layouts/utils/item-click-wrapper.tsx +93 -0
- package/src/field-types/array.tsx +75 -0
- package/src/field-types/boolean.tsx +66 -0
- package/src/field-types/datetime.tsx +46 -2
- package/src/field-types/email.tsx +79 -0
- package/src/field-types/index.tsx +45 -3
- package/src/field-types/integer.tsx +53 -2
- package/src/field-types/media.tsx +28 -0
- package/src/field-types/text.tsx +41 -2
- package/src/filter-and-sort-data-view.ts +243 -1
- package/src/normalize-fields.ts +116 -13
- package/src/test/dataviews.tsx +20 -2
- package/src/test/filter-and-sort-data-view.js +507 -0
- package/src/test/normalize-fields.ts +155 -0
- package/src/types.ts +106 -9
- package/src/utils.ts +10 -33
- package/tsconfig.json +2 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/build/components/dataviews-filters/filter-summary.js.map +0 -1
- package/build/dataviews-layouts/utils/get-clickable-item-props.js +0 -36
- package/build/dataviews-layouts/utils/get-clickable-item-props.js.map +0 -1
- package/build-module/components/dataviews-filters/filter-summary.js +0 -218
- package/build-module/components/dataviews-filters/filter-summary.js.map +0 -1
- package/build-module/dataviews-layouts/utils/get-clickable-item-props.js +0 -30
- package/build-module/dataviews-layouts/utils/get-clickable-item-props.js.map +0 -1
- package/build-types/components/dataviews-filters/filter-summary.d.ts +0 -14
- package/build-types/components/dataviews-filters/filter-summary.d.ts.map +0 -1
- package/build-types/dataviews-layouts/utils/get-clickable-item-props.d.ts +0 -19
- package/build-types/dataviews-layouts/utils/get-clickable-item-props.d.ts.map +0 -1
- package/src/components/dataviews-filters/filter-summary.tsx +0 -338
- package/src/dataviews-layouts/utils/get-clickable-item-props.ts +0 -39
|
@@ -199,13 +199,13 @@ function ListItem< Item >( {
|
|
|
199
199
|
const renderedMediaField =
|
|
200
200
|
showMedia && mediaField?.render ? (
|
|
201
201
|
<div className="dataviews-view-list__media-wrapper">
|
|
202
|
-
<mediaField.render item={ item } />
|
|
202
|
+
<mediaField.render item={ item } field={ mediaField } />
|
|
203
203
|
</div>
|
|
204
204
|
) : null;
|
|
205
205
|
|
|
206
206
|
const renderedTitleField =
|
|
207
207
|
showTitle && titleField?.render ? (
|
|
208
|
-
<titleField.render item={ item } />
|
|
208
|
+
<titleField.render item={ item } field={ titleField } />
|
|
209
209
|
) : null;
|
|
210
210
|
|
|
211
211
|
const usedActions = eligibleActions?.length > 0 && (
|
|
@@ -302,7 +302,10 @@ function ListItem< Item >( {
|
|
|
302
302
|
</HStack>
|
|
303
303
|
{ showDescription && descriptionField?.render && (
|
|
304
304
|
<div className="dataviews-view-list__field">
|
|
305
|
-
<descriptionField.render
|
|
305
|
+
<descriptionField.render
|
|
306
|
+
item={ item }
|
|
307
|
+
field={ descriptionField }
|
|
308
|
+
/>
|
|
306
309
|
</div>
|
|
307
310
|
) }
|
|
308
311
|
<div
|
|
@@ -321,7 +324,10 @@ function ListItem< Item >( {
|
|
|
321
324
|
{ field.label }
|
|
322
325
|
</VisuallyHidden>
|
|
323
326
|
<span className="dataviews-view-list__field-value">
|
|
324
|
-
<field.render
|
|
327
|
+
<field.render
|
|
328
|
+
item={ item }
|
|
329
|
+
field={ field }
|
|
330
|
+
/>
|
|
325
331
|
</span>
|
|
326
332
|
</div>
|
|
327
333
|
) ) }
|
|
@@ -347,6 +353,7 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) {
|
|
|
347
353
|
onChangeSelection,
|
|
348
354
|
selection,
|
|
349
355
|
view,
|
|
356
|
+
className,
|
|
350
357
|
} = props;
|
|
351
358
|
const baseId = useInstanceId( ViewList, 'view-list' );
|
|
352
359
|
|
|
@@ -491,7 +498,7 @@ export default function ViewList< Item >( props: ViewListProps< Item > ) {
|
|
|
491
498
|
<Composite
|
|
492
499
|
id={ baseId }
|
|
493
500
|
render={ <div /> }
|
|
494
|
-
className=
|
|
501
|
+
className={ clsx( 'dataviews-view-list', className ) }
|
|
495
502
|
role="grid"
|
|
496
503
|
activeId={ activeCompositeId }
|
|
497
504
|
setActiveId={ setActiveCompositeId }
|
|
@@ -19,7 +19,6 @@ import { forwardRef, Children, Fragment } from '@wordpress/element';
|
|
|
19
19
|
* Internal dependencies
|
|
20
20
|
*/
|
|
21
21
|
import { unlock } from '../../lock-unlock';
|
|
22
|
-
import { sanitizeOperators } from '../../utils';
|
|
23
22
|
import { SORTING_DIRECTIONS, sortArrows, sortLabels } from '../../constants';
|
|
24
23
|
import type {
|
|
25
24
|
NormalizedField,
|
|
@@ -81,15 +80,18 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
|
|
|
81
80
|
isSortable = field.enableSorting !== false;
|
|
82
81
|
const header = field.header;
|
|
83
82
|
|
|
84
|
-
operators =
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
83
|
+
operators = ( !! field.filterBy && field.filterBy?.operators ) || [];
|
|
84
|
+
|
|
85
|
+
// Filter can be added if:
|
|
86
|
+
//
|
|
87
|
+
// 1. The field is not already part of a view's filters.
|
|
88
|
+
// 2. The field has elements or Edit property.
|
|
89
|
+
// 3. The field does not opt-out of filtering.
|
|
90
|
+
// 4. The filter is not primary (if it is, it is already visible).
|
|
89
91
|
canAddFilter =
|
|
90
92
|
! view.filters?.some( ( _filter ) => fieldId === _filter.field ) &&
|
|
91
|
-
!! field.elements?.length &&
|
|
92
|
-
|
|
93
|
+
!! ( field.elements?.length || field.Edit ) &&
|
|
94
|
+
field.filterBy !== false &&
|
|
93
95
|
! field.filterBy?.isPrimary;
|
|
94
96
|
|
|
95
97
|
return (
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { ComponentProps, ReactElement } from 'react';
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
* WordPress dependencies
|
|
3
8
|
*/
|
|
@@ -10,7 +15,7 @@ import {
|
|
|
10
15
|
* Internal dependencies
|
|
11
16
|
*/
|
|
12
17
|
import type { NormalizedField } from '../../types';
|
|
13
|
-
import
|
|
18
|
+
import { ItemClickWrapper } from '../utils/item-click-wrapper';
|
|
14
19
|
|
|
15
20
|
function ColumnPrimary< Item >( {
|
|
16
21
|
item,
|
|
@@ -19,6 +24,7 @@ function ColumnPrimary< Item >( {
|
|
|
19
24
|
mediaField,
|
|
20
25
|
descriptionField,
|
|
21
26
|
onClickItem,
|
|
27
|
+
renderItemLink,
|
|
22
28
|
isItemClickable,
|
|
23
29
|
}: {
|
|
24
30
|
item: Item;
|
|
@@ -27,35 +33,42 @@ function ColumnPrimary< Item >( {
|
|
|
27
33
|
mediaField?: NormalizedField< Item >;
|
|
28
34
|
descriptionField?: NormalizedField< Item >;
|
|
29
35
|
onClickItem?: ( item: Item ) => void;
|
|
36
|
+
renderItemLink?: (
|
|
37
|
+
props: {
|
|
38
|
+
item: Item;
|
|
39
|
+
} & ComponentProps< 'a' >
|
|
40
|
+
) => ReactElement;
|
|
30
41
|
isItemClickable: ( item: Item ) => boolean;
|
|
31
42
|
} ) {
|
|
32
|
-
const clickableProps = getClickableItemProps( {
|
|
33
|
-
item,
|
|
34
|
-
isItemClickable,
|
|
35
|
-
onClickItem,
|
|
36
|
-
className:
|
|
37
|
-
'dataviews-view-table__cell-content-wrapper dataviews-title-field',
|
|
38
|
-
} );
|
|
39
43
|
return (
|
|
40
44
|
<HStack spacing={ 3 } justify="flex-start">
|
|
41
45
|
{ mediaField && (
|
|
42
46
|
<div className="dataviews-view-table__cell-content-wrapper dataviews-column-primary__media">
|
|
43
|
-
<mediaField.render item={ item } />
|
|
47
|
+
<mediaField.render item={ item } field={ mediaField } />
|
|
44
48
|
</div>
|
|
45
49
|
) }
|
|
46
50
|
<VStack spacing={ 0 }>
|
|
47
51
|
{ titleField && (
|
|
48
|
-
<
|
|
52
|
+
<ItemClickWrapper
|
|
53
|
+
item={ item }
|
|
54
|
+
isItemClickable={ isItemClickable }
|
|
55
|
+
onClickItem={ onClickItem }
|
|
56
|
+
renderItemLink={ renderItemLink }
|
|
57
|
+
className="dataviews-view-table__cell-content-wrapper dataviews-title-field"
|
|
58
|
+
>
|
|
49
59
|
{ level !== undefined && (
|
|
50
60
|
<span className="dataviews-view-table__level">
|
|
51
61
|
{ '—'.repeat( level ) }
|
|
52
62
|
</span>
|
|
53
63
|
) }
|
|
54
|
-
<titleField.render item={ item } />
|
|
55
|
-
</
|
|
64
|
+
<titleField.render item={ item } field={ titleField } />
|
|
65
|
+
</ItemClickWrapper>
|
|
56
66
|
) }
|
|
57
67
|
{ descriptionField && (
|
|
58
|
-
<descriptionField.render
|
|
68
|
+
<descriptionField.render
|
|
69
|
+
item={ item }
|
|
70
|
+
field={ descriptionField }
|
|
71
|
+
/>
|
|
59
72
|
) }
|
|
60
73
|
</VStack>
|
|
61
74
|
</HStack>
|
|
@@ -2,17 +2,25 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
import clsx from 'clsx';
|
|
5
|
+
import type { ComponentProps, ReactElement } from 'react';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* WordPress dependencies
|
|
8
9
|
*/
|
|
9
10
|
import { __ } from '@wordpress/i18n';
|
|
10
11
|
import { Spinner } from '@wordpress/components';
|
|
11
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
useContext,
|
|
14
|
+
useEffect,
|
|
15
|
+
useId,
|
|
16
|
+
useRef,
|
|
17
|
+
useState,
|
|
18
|
+
} from '@wordpress/element';
|
|
12
19
|
|
|
13
20
|
/**
|
|
14
21
|
* Internal dependencies
|
|
15
22
|
*/
|
|
23
|
+
import DataViewsContext from '../../components/dataviews-context';
|
|
16
24
|
import DataViewsSelectionCheckbox from '../../components/dataviews-selection-checkbox';
|
|
17
25
|
import ItemActions from '../../components/dataviews-item-actions';
|
|
18
26
|
import { sortValues } from '../../constants';
|
|
@@ -30,11 +38,13 @@ import type {
|
|
|
30
38
|
import type { SetSelection } from '../../private-types';
|
|
31
39
|
import ColumnHeaderMenu from './column-header-menu';
|
|
32
40
|
import ColumnPrimary from './column-primary';
|
|
41
|
+
import { useIsHorizontalScrollEnd } from './use-is-horizontal-scroll-end';
|
|
33
42
|
|
|
34
43
|
interface TableColumnFieldProps< Item > {
|
|
35
44
|
fields: NormalizedField< Item >[];
|
|
36
45
|
column: string;
|
|
37
46
|
item: Item;
|
|
47
|
+
align?: 'start' | 'center' | 'end';
|
|
38
48
|
}
|
|
39
49
|
|
|
40
50
|
interface TableRowProps< Item > {
|
|
@@ -53,12 +63,19 @@ interface TableRowProps< Item > {
|
|
|
53
63
|
onChangeSelection: SetSelection;
|
|
54
64
|
isItemClickable: ( item: Item ) => boolean;
|
|
55
65
|
onClickItem?: ( item: Item ) => void;
|
|
66
|
+
renderItemLink?: (
|
|
67
|
+
props: {
|
|
68
|
+
item: Item;
|
|
69
|
+
} & ComponentProps< 'a' >
|
|
70
|
+
) => ReactElement;
|
|
71
|
+
isActionsColumnSticky?: boolean;
|
|
56
72
|
}
|
|
57
73
|
|
|
58
74
|
function TableColumnField< Item >( {
|
|
59
75
|
item,
|
|
60
76
|
fields,
|
|
61
77
|
column,
|
|
78
|
+
align,
|
|
62
79
|
}: TableColumnFieldProps< Item > ) {
|
|
63
80
|
const field = fields.find( ( f ) => f.id === column );
|
|
64
81
|
|
|
@@ -66,9 +83,14 @@ function TableColumnField< Item >( {
|
|
|
66
83
|
return null;
|
|
67
84
|
}
|
|
68
85
|
|
|
86
|
+
const className = clsx( 'dataviews-view-table__cell-content-wrapper', {
|
|
87
|
+
'dataviews-view-table__cell-align-end': align === 'end',
|
|
88
|
+
'dataviews-view-table__cell-align-center': align === 'center',
|
|
89
|
+
} );
|
|
90
|
+
|
|
69
91
|
return (
|
|
70
|
-
<div className=
|
|
71
|
-
<field.render {
|
|
92
|
+
<div className={ className }>
|
|
93
|
+
<field.render item={ item } field={ field } />
|
|
72
94
|
</div>
|
|
73
95
|
);
|
|
74
96
|
}
|
|
@@ -88,7 +110,9 @@ function TableRow< Item >( {
|
|
|
88
110
|
getItemId,
|
|
89
111
|
isItemClickable,
|
|
90
112
|
onClickItem,
|
|
113
|
+
renderItemLink,
|
|
91
114
|
onChangeSelection,
|
|
115
|
+
isActionsColumnSticky,
|
|
92
116
|
}: TableRowProps< Item > ) {
|
|
93
117
|
const hasPossibleBulkAction = useHasAPossibleBulkAction( actions, item );
|
|
94
118
|
const isSelected = hasPossibleBulkAction && selection.includes( id );
|
|
@@ -165,20 +189,29 @@ function TableRow< Item >( {
|
|
|
165
189
|
}
|
|
166
190
|
isItemClickable={ isItemClickable }
|
|
167
191
|
onClickItem={ onClickItem }
|
|
192
|
+
renderItemLink={ renderItemLink }
|
|
168
193
|
/>
|
|
169
194
|
</td>
|
|
170
195
|
) }
|
|
171
196
|
{ columns.map( ( column: string ) => {
|
|
172
197
|
// Explicit picks the supported styles.
|
|
173
|
-
const { width, maxWidth, minWidth } =
|
|
198
|
+
const { width, maxWidth, minWidth, align } =
|
|
174
199
|
view.layout?.styles?.[ column ] ?? {};
|
|
175
200
|
|
|
176
201
|
return (
|
|
177
|
-
<td
|
|
202
|
+
<td
|
|
203
|
+
key={ column }
|
|
204
|
+
style={ {
|
|
205
|
+
width,
|
|
206
|
+
maxWidth,
|
|
207
|
+
minWidth,
|
|
208
|
+
} }
|
|
209
|
+
>
|
|
178
210
|
<TableColumnField
|
|
179
211
|
fields={ fields }
|
|
180
212
|
item={ item }
|
|
181
213
|
column={ column }
|
|
214
|
+
align={ align }
|
|
182
215
|
/>
|
|
183
216
|
</td>
|
|
184
217
|
);
|
|
@@ -192,7 +225,11 @@ function TableRow< Item >( {
|
|
|
192
225
|
|
|
193
226
|
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/click-events-have-key-events */
|
|
194
227
|
<td
|
|
195
|
-
className=
|
|
228
|
+
className={ clsx( 'dataviews-view-table__actions-column', {
|
|
229
|
+
'dataviews-view-table__actions-column--sticky': true,
|
|
230
|
+
'dataviews-view-table__actions-column--stuck':
|
|
231
|
+
isActionsColumnSticky,
|
|
232
|
+
} ) }
|
|
196
233
|
onClick={ ( e ) => e.stopPropagation() }
|
|
197
234
|
>
|
|
198
235
|
<ItemActions item={ item } actions={ actions } />
|
|
@@ -216,8 +253,11 @@ function ViewTable< Item >( {
|
|
|
216
253
|
setOpenedFilter,
|
|
217
254
|
onClickItem,
|
|
218
255
|
isItemClickable,
|
|
256
|
+
renderItemLink,
|
|
219
257
|
view,
|
|
258
|
+
className,
|
|
220
259
|
}: ViewTableProps< Item > ) {
|
|
260
|
+
const { containerRef } = useContext( DataViewsContext );
|
|
221
261
|
const headerMenuRefs = useRef<
|
|
222
262
|
Map< string, { node: HTMLButtonElement; fallback: string } >
|
|
223
263
|
>( new Map() );
|
|
@@ -235,6 +275,11 @@ function ViewTable< Item >( {
|
|
|
235
275
|
|
|
236
276
|
const tableNoticeId = useId();
|
|
237
277
|
|
|
278
|
+
const isHorizontalScrollEnd = useIsHorizontalScrollEnd( {
|
|
279
|
+
scrollContainerRef: containerRef,
|
|
280
|
+
enabled: !! actions?.length,
|
|
281
|
+
} );
|
|
282
|
+
|
|
238
283
|
if ( nextHeaderMenuToFocus ) {
|
|
239
284
|
// If we need to force focus, we short-circuit rendering here
|
|
240
285
|
// to prevent any additional work while we handle that.
|
|
@@ -281,7 +326,7 @@ function ViewTable< Item >( {
|
|
|
281
326
|
return (
|
|
282
327
|
<>
|
|
283
328
|
<table
|
|
284
|
-
className={ clsx( 'dataviews-view-table', {
|
|
329
|
+
className={ clsx( 'dataviews-view-table', className, {
|
|
285
330
|
[ `has-${ view.layout?.density }-density` ]:
|
|
286
331
|
view.layout?.density &&
|
|
287
332
|
[ 'compact', 'comfortable' ].includes(
|
|
@@ -328,12 +373,17 @@ function ViewTable< Item >( {
|
|
|
328
373
|
) }
|
|
329
374
|
{ columns.map( ( column, index ) => {
|
|
330
375
|
// Explicit picks the supported styles.
|
|
331
|
-
const { width, maxWidth, minWidth } =
|
|
376
|
+
const { width, maxWidth, minWidth, align } =
|
|
332
377
|
view.layout?.styles?.[ column ] ?? {};
|
|
333
378
|
return (
|
|
334
379
|
<th
|
|
335
380
|
key={ column }
|
|
336
|
-
style={ {
|
|
381
|
+
style={ {
|
|
382
|
+
width,
|
|
383
|
+
maxWidth,
|
|
384
|
+
minWidth,
|
|
385
|
+
textAlign: align,
|
|
386
|
+
} }
|
|
337
387
|
aria-sort={
|
|
338
388
|
view.sort?.direction &&
|
|
339
389
|
view.sort?.field === column
|
|
@@ -355,7 +405,17 @@ function ViewTable< Item >( {
|
|
|
355
405
|
);
|
|
356
406
|
} ) }
|
|
357
407
|
{ !! actions?.length && (
|
|
358
|
-
<th
|
|
408
|
+
<th
|
|
409
|
+
className={ clsx(
|
|
410
|
+
'dataviews-view-table__actions-column',
|
|
411
|
+
{
|
|
412
|
+
'dataviews-view-table__actions-column--sticky':
|
|
413
|
+
true,
|
|
414
|
+
'dataviews-view-table__actions-column--stuck':
|
|
415
|
+
! isHorizontalScrollEnd,
|
|
416
|
+
}
|
|
417
|
+
) }
|
|
418
|
+
>
|
|
359
419
|
<span className="dataviews-view-table-header">
|
|
360
420
|
{ __( 'Actions' ) }
|
|
361
421
|
</span>
|
|
@@ -387,7 +447,11 @@ function ViewTable< Item >( {
|
|
|
387
447
|
getItemId={ getItemId }
|
|
388
448
|
onChangeSelection={ onChangeSelection }
|
|
389
449
|
onClickItem={ onClickItem }
|
|
450
|
+
renderItemLink={ renderItemLink }
|
|
390
451
|
isItemClickable={ isItemClickable }
|
|
452
|
+
isActionsColumnSticky={
|
|
453
|
+
! isHorizontalScrollEnd
|
|
454
|
+
}
|
|
391
455
|
/>
|
|
392
456
|
) ) }
|
|
393
457
|
</tbody>
|
|
@@ -22,6 +22,25 @@
|
|
|
22
22
|
text-align: right;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
&.dataviews-view-table__actions-column--sticky {
|
|
26
|
+
position: sticky;
|
|
27
|
+
right: 0;
|
|
28
|
+
background-color: $white;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&.dataviews-view-table__actions-column--stuck {
|
|
32
|
+
&::after {
|
|
33
|
+
display: block;
|
|
34
|
+
content: "";
|
|
35
|
+
position: absolute;
|
|
36
|
+
top: 0;
|
|
37
|
+
bottom: 0;
|
|
38
|
+
left: 0;
|
|
39
|
+
width: 1px;
|
|
40
|
+
background-color: $gray-100;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
25
44
|
&.dataviews-view-table__checkbox-column {
|
|
26
45
|
padding-right: 0;
|
|
27
46
|
width: 1%;
|
|
@@ -52,7 +71,8 @@
|
|
|
52
71
|
border-bottom: 0;
|
|
53
72
|
}
|
|
54
73
|
|
|
55
|
-
&.is-hovered
|
|
74
|
+
&.is-hovered,
|
|
75
|
+
&.is-hovered .dataviews-view-table__actions-column--sticky {
|
|
56
76
|
background-color: #f8f8f8;
|
|
57
77
|
}
|
|
58
78
|
|
|
@@ -99,6 +119,14 @@
|
|
|
99
119
|
&:hover {
|
|
100
120
|
background-color: rgba(var(--wp-admin-theme-color--rgb), 0.08);
|
|
101
121
|
}
|
|
122
|
+
|
|
123
|
+
.dataviews-view-table__actions-column--sticky {
|
|
124
|
+
background-color: color-mix(in srgb, rgb(var(--wp-admin-theme-color--rgb)) 4%, $white);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
&:hover .dataviews-view-table__actions-column--sticky {
|
|
128
|
+
background-color: color-mix(in srgb, rgb(var(--wp-admin-theme-color--rgb)) 8%, $white);
|
|
129
|
+
}
|
|
102
130
|
}
|
|
103
131
|
}
|
|
104
132
|
thead {
|
|
@@ -131,6 +159,14 @@
|
|
|
131
159
|
min-height: $grid-unit-40;
|
|
132
160
|
display: flex;
|
|
133
161
|
align-items: center;
|
|
162
|
+
|
|
163
|
+
&.dataviews-view-table__cell-align-end {
|
|
164
|
+
justify-content: flex-end;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
&.dataviews-view-table__cell-align-center {
|
|
168
|
+
justify-content: center;
|
|
169
|
+
}
|
|
134
170
|
}
|
|
135
171
|
|
|
136
172
|
.components-v-stack > .dataviews-view-table__cell-content-wrapper:not(:first-child) {
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { MutableRefObject } from 'react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* WordPress dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { useDebounce } from '@wordpress/compose';
|
|
10
|
+
import { useCallback, useEffect, useState } from '@wordpress/element';
|
|
11
|
+
import { isRTL } from '@wordpress/i18n';
|
|
12
|
+
|
|
13
|
+
const isScrolledToEnd = ( element: Element ) => {
|
|
14
|
+
if ( isRTL() ) {
|
|
15
|
+
const scrollLeft = Math.abs( element.scrollLeft );
|
|
16
|
+
return scrollLeft <= 1;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return element.scrollLeft + element.clientWidth >= element.scrollWidth - 1;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A hook to check if a given scroll container has reached the horizontal scroll end.
|
|
24
|
+
*
|
|
25
|
+
* The current way receives "refs" as arguments, but it lacks a mechanism to detect when a ref has changed.
|
|
26
|
+
* As a result, when the "ref" is updated and attached to a new div, the computation should trigger again.
|
|
27
|
+
* However, this isn't possible in the current setup because the hook is unaware that the ref has changed.
|
|
28
|
+
*
|
|
29
|
+
* See https://github.com/Automattic/wp-calypso/pull/103005#discussion_r2077567912.
|
|
30
|
+
*
|
|
31
|
+
* @param {Object} params The parameters for the hook.
|
|
32
|
+
* @param {MutableRefObject<HTMLDivElement | null>} params.scrollContainerRef The ref to the scroll container element.
|
|
33
|
+
* @param {boolean} [params.enabled=false] Whether the hook is enabled.
|
|
34
|
+
* @return {boolean} - Returns true if the scroll container is scrolled to the end or false otherwise.
|
|
35
|
+
*/
|
|
36
|
+
export function useIsHorizontalScrollEnd( {
|
|
37
|
+
scrollContainerRef,
|
|
38
|
+
enabled = false,
|
|
39
|
+
}: {
|
|
40
|
+
scrollContainerRef: React.MutableRefObject< HTMLDivElement | null >;
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
} ): boolean {
|
|
43
|
+
const [ isHorizontalScrollEnd, setIsHorizontalScrollEnd ] =
|
|
44
|
+
useState( false );
|
|
45
|
+
|
|
46
|
+
const handleIsHorizontalScrollEnd = useDebounce(
|
|
47
|
+
useCallback( () => {
|
|
48
|
+
const scrollContainer = scrollContainerRef.current;
|
|
49
|
+
if ( scrollContainer ) {
|
|
50
|
+
setIsHorizontalScrollEnd( isScrolledToEnd( scrollContainer ) );
|
|
51
|
+
}
|
|
52
|
+
}, [ scrollContainerRef, setIsHorizontalScrollEnd ] ),
|
|
53
|
+
200
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
useEffect( () => {
|
|
57
|
+
if (
|
|
58
|
+
typeof window === 'undefined' ||
|
|
59
|
+
! enabled ||
|
|
60
|
+
! scrollContainerRef.current
|
|
61
|
+
) {
|
|
62
|
+
return () => {};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
handleIsHorizontalScrollEnd();
|
|
66
|
+
scrollContainerRef.current.addEventListener(
|
|
67
|
+
'scroll',
|
|
68
|
+
handleIsHorizontalScrollEnd
|
|
69
|
+
);
|
|
70
|
+
window.addEventListener( 'resize', handleIsHorizontalScrollEnd );
|
|
71
|
+
|
|
72
|
+
return () => {
|
|
73
|
+
scrollContainerRef.current?.removeEventListener(
|
|
74
|
+
'scroll',
|
|
75
|
+
handleIsHorizontalScrollEnd
|
|
76
|
+
);
|
|
77
|
+
window.removeEventListener( 'resize', handleIsHorizontalScrollEnd );
|
|
78
|
+
};
|
|
79
|
+
}, [ scrollContainerRef, enabled ] );
|
|
80
|
+
|
|
81
|
+
return isHorizontalScrollEnd;
|
|
82
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { ReactNode, ReactElement, ComponentProps } from 'react';
|
|
5
|
+
|
|
6
|
+
function getClickableItemProps< Item >( {
|
|
7
|
+
item,
|
|
8
|
+
isItemClickable,
|
|
9
|
+
onClickItem,
|
|
10
|
+
className,
|
|
11
|
+
}: {
|
|
12
|
+
item: Item;
|
|
13
|
+
isItemClickable: ( item: Item ) => boolean;
|
|
14
|
+
onClickItem?: ( item: Item ) => void;
|
|
15
|
+
className?: string;
|
|
16
|
+
} ) {
|
|
17
|
+
if ( ! isItemClickable( item ) || ! onClickItem ) {
|
|
18
|
+
return { className };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
className: className
|
|
23
|
+
? `${ className } ${ className }--clickable`
|
|
24
|
+
: undefined,
|
|
25
|
+
role: 'button',
|
|
26
|
+
tabIndex: 0,
|
|
27
|
+
onClick: ( event: React.MouseEvent ) => {
|
|
28
|
+
// Prevents onChangeSelection from triggering.
|
|
29
|
+
event.stopPropagation();
|
|
30
|
+
onClickItem( item );
|
|
31
|
+
},
|
|
32
|
+
onKeyDown: ( event: React.KeyboardEvent ) => {
|
|
33
|
+
if (
|
|
34
|
+
event.key === 'Enter' ||
|
|
35
|
+
event.key === '' ||
|
|
36
|
+
event.key === ' '
|
|
37
|
+
) {
|
|
38
|
+
// Prevents onChangeSelection from triggering.
|
|
39
|
+
event.stopPropagation();
|
|
40
|
+
onClickItem( item );
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function ItemClickWrapper< Item >( {
|
|
47
|
+
item,
|
|
48
|
+
isItemClickable,
|
|
49
|
+
onClickItem,
|
|
50
|
+
renderItemLink,
|
|
51
|
+
className,
|
|
52
|
+
children,
|
|
53
|
+
...extraProps
|
|
54
|
+
}: {
|
|
55
|
+
item: Item;
|
|
56
|
+
isItemClickable: ( item: Item ) => boolean;
|
|
57
|
+
onClickItem?: ( item: Item ) => void;
|
|
58
|
+
renderItemLink?: (
|
|
59
|
+
props: {
|
|
60
|
+
item: Item;
|
|
61
|
+
} & ComponentProps< 'a' >
|
|
62
|
+
) => ReactElement;
|
|
63
|
+
className?: string;
|
|
64
|
+
children: ReactNode;
|
|
65
|
+
} ) {
|
|
66
|
+
if ( ! isItemClickable( item ) ) {
|
|
67
|
+
return children;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// If we have a renderItemLink, use it
|
|
71
|
+
if ( renderItemLink ) {
|
|
72
|
+
return renderItemLink( {
|
|
73
|
+
item,
|
|
74
|
+
className: `${ className } ${ className }--clickable`,
|
|
75
|
+
...extraProps,
|
|
76
|
+
children,
|
|
77
|
+
} );
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Otherwise use the classic click handler approach
|
|
81
|
+
const clickProps = getClickableItemProps( {
|
|
82
|
+
item,
|
|
83
|
+
isItemClickable,
|
|
84
|
+
onClickItem,
|
|
85
|
+
className,
|
|
86
|
+
} );
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<div { ...clickProps } { ...extraProps }>
|
|
90
|
+
{ children }
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type {
|
|
5
|
+
DataViewRenderFieldProps,
|
|
6
|
+
SortDirection,
|
|
7
|
+
ValidationContext,
|
|
8
|
+
FieldTypeDefinition,
|
|
9
|
+
} from '../types';
|
|
10
|
+
import {
|
|
11
|
+
OPERATOR_IS_ALL,
|
|
12
|
+
OPERATOR_IS_ANY,
|
|
13
|
+
OPERATOR_IS_NONE,
|
|
14
|
+
OPERATOR_IS_NOT_ALL,
|
|
15
|
+
} from '../constants';
|
|
16
|
+
|
|
17
|
+
// Sort arrays by length, then alphabetically by joined string
|
|
18
|
+
function sort( valueA: any, valueB: any, direction: SortDirection ) {
|
|
19
|
+
const arrA = Array.isArray( valueA ) ? valueA : [];
|
|
20
|
+
const arrB = Array.isArray( valueB ) ? valueB : [];
|
|
21
|
+
if ( arrA.length !== arrB.length ) {
|
|
22
|
+
return direction === 'asc'
|
|
23
|
+
? arrA.length - arrB.length
|
|
24
|
+
: arrB.length - arrA.length;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const joinedA = arrA.join( ',' );
|
|
28
|
+
const joinedB = arrB.join( ',' );
|
|
29
|
+
return direction === 'asc'
|
|
30
|
+
? joinedA.localeCompare( joinedB )
|
|
31
|
+
: joinedB.localeCompare( joinedA );
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function isValid( value: any, context?: ValidationContext ) {
|
|
35
|
+
if ( ! Array.isArray( value ) ) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Only allow strings for now. Can be extended to other types in the future.
|
|
40
|
+
if ( ! value.every( ( v ) => typeof v === 'string' ) ) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if ( context?.elements ) {
|
|
45
|
+
const validValues = context.elements.map( ( f ) => f.value );
|
|
46
|
+
if ( ! value.every( ( v ) => validValues.includes( v ) ) ) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function render( { item, field }: DataViewRenderFieldProps< any > ) {
|
|
54
|
+
const value = field.getValue( { item } ) || [];
|
|
55
|
+
return value.join( ', ' );
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const arrayFieldType: FieldTypeDefinition< any > = {
|
|
59
|
+
sort,
|
|
60
|
+
isValid,
|
|
61
|
+
Edit: null, // Not implemented yet
|
|
62
|
+
render,
|
|
63
|
+
enableSorting: true,
|
|
64
|
+
filterBy: {
|
|
65
|
+
defaultOperators: [ OPERATOR_IS_ANY, OPERATOR_IS_NONE ],
|
|
66
|
+
validOperators: [
|
|
67
|
+
OPERATOR_IS_ANY,
|
|
68
|
+
OPERATOR_IS_NONE,
|
|
69
|
+
OPERATOR_IS_ALL,
|
|
70
|
+
OPERATOR_IS_NOT_ALL,
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export default arrayFieldType;
|