fix: prevent asset conflicts between React and Grid.js versions

Add coexistence checks to all enqueue methods to prevent loading
both React and Grid.js assets simultaneously.

Changes:
- ReactAdmin.php: Only enqueue React assets when ?react=1
- Init.php: Skip Grid.js when React active on admin pages
- Form.php, Coupon.php, Access.php: Restore classic assets when ?react=0
- Customer.php, Product.php, License.php: Add coexistence checks

Now the toggle between Classic and React versions works correctly.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
dwindown
2026-04-18 17:02:14 +07:00
parent bd9cdac02e
commit e8fbfb14c1
74973 changed files with 6658406 additions and 71 deletions

View File

@@ -0,0 +1,27 @@
import { createElement } from "react";
/**
* Internal dependencies
*/
import { buildTermsTree } from './terms';
import TreeSelect from '../tree-select';
export default function AuthorSelect({
__next40pxDefaultSize,
label,
noOptionLabel,
authorList,
selectedAuthorId,
onChange: onChangeProp
}) {
if (!authorList) return null;
const termsTree = buildTermsTree(authorList);
return createElement(TreeSelect, {
label,
noOptionLabel,
onChange: onChangeProp,
tree: termsTree,
selectedId: selectedAuthorId !== undefined ? String(selectedAuthorId) : undefined,
__nextHasNoMarginBottom: true,
__next40pxDefaultSize: __next40pxDefaultSize
});
}
//# sourceMappingURL=author-select.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["buildTermsTree","TreeSelect","AuthorSelect","__next40pxDefaultSize","label","noOptionLabel","authorList","selectedAuthorId","onChange","onChangeProp","termsTree","createElement","tree","selectedId","undefined","String","__nextHasNoMarginBottom"],"sources":["@wordpress/components/src/query-controls/author-select.tsx"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport { buildTermsTree } from './terms';\nimport TreeSelect from '../tree-select';\nimport type { AuthorSelectProps } from './types';\n\nexport default function AuthorSelect( {\n\t__next40pxDefaultSize,\n\tlabel,\n\tnoOptionLabel,\n\tauthorList,\n\tselectedAuthorId,\n\tonChange: onChangeProp,\n}: AuthorSelectProps ) {\n\tif ( ! authorList ) return null;\n\tconst termsTree = buildTermsTree( authorList );\n\treturn (\n\t\t<TreeSelect\n\t\t\t{ ...{\n\t\t\t\tlabel,\n\t\t\t\tnoOptionLabel,\n\t\t\t\tonChange: onChangeProp,\n\t\t\t} }\n\t\t\ttree={ termsTree }\n\t\t\tselectedId={\n\t\t\t\tselectedAuthorId !== undefined\n\t\t\t\t\t? String( selectedAuthorId )\n\t\t\t\t\t: undefined\n\t\t\t}\n\t\t\t__nextHasNoMarginBottom\n\t\t\t__next40pxDefaultSize={ __next40pxDefaultSize }\n\t\t/>\n\t);\n}\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,cAAc,QAAQ,SAAS;AACxC,OAAOC,UAAU,MAAM,gBAAgB;AAGvC,eAAe,SAASC,YAAYA,CAAE;EACrCC,qBAAqB;EACrBC,KAAK;EACLC,aAAa;EACbC,UAAU;EACVC,gBAAgB;EAChBC,QAAQ,EAAEC;AACQ,CAAC,EAAG;EACtB,IAAK,CAAEH,UAAU,EAAG,OAAO,IAAI;EAC/B,MAAMI,SAAS,GAAGV,cAAc,CAAEM,UAAW,CAAC;EAC9C,OACCK,aAAA,CAACV,UAAU;IAETG,KAAK;IACLC,aAAa;IACbG,QAAQ,EAAEC,YAAY;IAEvBG,IAAI,EAAGF,SAAW;IAClBG,UAAU,EACTN,gBAAgB,KAAKO,SAAS,GAC3BC,MAAM,CAAER,gBAAiB,CAAC,GAC1BO,SACH;IACDE,uBAAuB;IACvBb,qBAAqB,EAAGA;EAAuB,CAC/C,CAAC;AAEJ"}

View File

@@ -0,0 +1,35 @@
import { createElement } from "react";
/**
* Internal dependencies
*/
import { buildTermsTree } from './terms';
import TreeSelect from '../tree-select';
/**
* WordPress dependencies
*/
import { useMemo } from '@wordpress/element';
export default function CategorySelect({
__next40pxDefaultSize,
label,
noOptionLabel,
categoriesList,
selectedCategoryId,
onChange: onChangeProp,
...props
}) {
const termsTree = useMemo(() => {
return buildTermsTree(categoriesList);
}, [categoriesList]);
return createElement(TreeSelect, {
label,
noOptionLabel,
onChange: onChangeProp,
tree: termsTree,
selectedId: selectedCategoryId !== undefined ? String(selectedCategoryId) : undefined,
...props,
__nextHasNoMarginBottom: true,
__next40pxDefaultSize: __next40pxDefaultSize
});
}
//# sourceMappingURL=category-select.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["buildTermsTree","TreeSelect","useMemo","CategorySelect","__next40pxDefaultSize","label","noOptionLabel","categoriesList","selectedCategoryId","onChange","onChangeProp","props","termsTree","createElement","tree","selectedId","undefined","String","__nextHasNoMarginBottom"],"sources":["@wordpress/components/src/query-controls/category-select.tsx"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport { buildTermsTree } from './terms';\nimport TreeSelect from '../tree-select';\n\n/**\n * WordPress dependencies\n */\nimport { useMemo } from '@wordpress/element';\nimport type { CategorySelectProps } from './types';\n\nexport default function CategorySelect( {\n\t__next40pxDefaultSize,\n\tlabel,\n\tnoOptionLabel,\n\tcategoriesList,\n\tselectedCategoryId,\n\tonChange: onChangeProp,\n\t...props\n}: CategorySelectProps ) {\n\tconst termsTree = useMemo( () => {\n\t\treturn buildTermsTree( categoriesList );\n\t}, [ categoriesList ] );\n\n\treturn (\n\t\t<TreeSelect\n\t\t\t{ ...{\n\t\t\t\tlabel,\n\t\t\t\tnoOptionLabel,\n\t\t\t\tonChange: onChangeProp,\n\t\t\t} }\n\t\t\ttree={ termsTree }\n\t\t\tselectedId={\n\t\t\t\tselectedCategoryId !== undefined\n\t\t\t\t\t? String( selectedCategoryId )\n\t\t\t\t\t: undefined\n\t\t\t}\n\t\t\t{ ...props }\n\t\t\t__nextHasNoMarginBottom\n\t\t\t__next40pxDefaultSize={ __next40pxDefaultSize }\n\t\t/>\n\t);\n}\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,cAAc,QAAQ,SAAS;AACxC,OAAOC,UAAU,MAAM,gBAAgB;;AAEvC;AACA;AACA;AACA,SAASC,OAAO,QAAQ,oBAAoB;AAG5C,eAAe,SAASC,cAAcA,CAAE;EACvCC,qBAAqB;EACrBC,KAAK;EACLC,aAAa;EACbC,cAAc;EACdC,kBAAkB;EAClBC,QAAQ,EAAEC,YAAY;EACtB,GAAGC;AACiB,CAAC,EAAG;EACxB,MAAMC,SAAS,GAAGV,OAAO,CAAE,MAAM;IAChC,OAAOF,cAAc,CAAEO,cAAe,CAAC;EACxC,CAAC,EAAE,CAAEA,cAAc,CAAG,CAAC;EAEvB,OACCM,aAAA,CAACZ,UAAU;IAETI,KAAK;IACLC,aAAa;IACbG,QAAQ,EAAEC,YAAY;IAEvBI,IAAI,EAAGF,SAAW;IAClBG,UAAU,EACTP,kBAAkB,KAAKQ,SAAS,GAC7BC,MAAM,CAAET,kBAAmB,CAAC,GAC5BQ,SACH;IAAA,GACIL,KAAK;IACVO,uBAAuB;IACvBd,qBAAqB,EAAGA;EAAuB,CAC/C,CAAC;AAEJ"}

View File

@@ -0,0 +1,149 @@
import { createElement } from "react";
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import AuthorSelect from './author-select';
import CategorySelect from './category-select';
import FormTokenField from '../form-token-field';
import RangeControl from '../range-control';
import SelectControl from '../select-control';
import { VStack } from '../v-stack';
const DEFAULT_MIN_ITEMS = 1;
const DEFAULT_MAX_ITEMS = 100;
const MAX_CATEGORIES_SUGGESTIONS = 20;
function isSingleCategorySelection(props) {
return 'categoriesList' in props;
}
function isMultipleCategorySelection(props) {
return 'categorySuggestions' in props;
}
/**
* Controls to query for posts.
*
* ```jsx
* const MyQueryControls = () => (
* <QueryControls
* { ...{ maxItems, minItems, numberOfItems, order, orderBy } }
* onOrderByChange={ ( newOrderBy ) => {
* updateQuery( { orderBy: newOrderBy } )
* }
* onOrderChange={ ( newOrder ) => {
* updateQuery( { order: newOrder } )
* }
* categoriesList={ categories }
* selectedCategoryId={ category }
* onCategoryChange={ ( newCategory ) => {
* updateQuery( { category: newCategory } )
* }
* onNumberOfItemsChange={ ( newNumberOfItems ) => {
* updateQuery( { numberOfItems: newNumberOfItems } )
* } }
* />
* );
* ```
*/
export function QueryControls({
__next40pxDefaultSize = false,
authorList,
selectedAuthorId,
numberOfItems,
order,
orderBy,
maxItems = DEFAULT_MAX_ITEMS,
minItems = DEFAULT_MIN_ITEMS,
onAuthorChange,
onNumberOfItemsChange,
onOrderChange,
onOrderByChange,
// Props for single OR multiple category selection are not destructured here,
// but instead are destructured inline where necessary.
...props
}) {
return createElement(VStack, {
spacing: "4",
className: "components-query-controls"
}, [onOrderChange && onOrderByChange && createElement(SelectControl, {
__nextHasNoMarginBottom: true,
__next40pxDefaultSize: __next40pxDefaultSize,
key: "query-controls-order-select",
label: __('Order by'),
value: `${orderBy}/${order}`,
options: [{
label: __('Newest to oldest'),
value: 'date/desc'
}, {
label: __('Oldest to newest'),
value: 'date/asc'
}, {
/* translators: label for ordering posts by title in ascending order */
label: __('A → Z'),
value: 'title/asc'
}, {
/* translators: label for ordering posts by title in descending order */
label: __('Z → A'),
value: 'title/desc'
}],
onChange: value => {
if (typeof value !== 'string') {
return;
}
const [newOrderBy, newOrder] = value.split('/');
if (newOrder !== order) {
onOrderChange(newOrder);
}
if (newOrderBy !== orderBy) {
onOrderByChange(newOrderBy);
}
}
}), isSingleCategorySelection(props) && props.categoriesList && props.onCategoryChange && createElement(CategorySelect, {
__next40pxDefaultSize: __next40pxDefaultSize,
key: "query-controls-category-select",
categoriesList: props.categoriesList,
label: __('Category'),
noOptionLabel: __('All'),
selectedCategoryId: props.selectedCategoryId,
onChange: props.onCategoryChange
}), isMultipleCategorySelection(props) && props.categorySuggestions && props.onCategoryChange && createElement(FormTokenField, {
__next40pxDefaultSize: __next40pxDefaultSize,
__nextHasNoMarginBottom: true,
key: "query-controls-categories-select",
label: __('Categories'),
value: props.selectedCategories && props.selectedCategories.map(item => ({
id: item.id,
// Keeping the fallback to `item.value` for legacy reasons,
// even if items of `selectedCategories` should not have a
// `value` property.
// @ts-expect-error
value: item.name || item.value
})),
suggestions: Object.keys(props.categorySuggestions),
onChange: props.onCategoryChange,
maxSuggestions: MAX_CATEGORIES_SUGGESTIONS
}), onAuthorChange && createElement(AuthorSelect, {
__next40pxDefaultSize: __next40pxDefaultSize,
key: "query-controls-author-select",
authorList: authorList,
label: __('Author'),
noOptionLabel: __('All'),
selectedAuthorId: selectedAuthorId,
onChange: onAuthorChange
}), onNumberOfItemsChange && createElement(RangeControl, {
__nextHasNoMarginBottom: true,
__next40pxDefaultSize: __next40pxDefaultSize,
key: "query-controls-range-control",
label: __('Number of items'),
value: numberOfItems,
onChange: onNumberOfItemsChange,
min: minItems,
max: maxItems,
required: true
})]);
}
export default QueryControls;
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,76 @@
import { createElement, Fragment } from "react";
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { useCallback, memo } from '@wordpress/element';
/**
* Internal dependencies
*/
import { RangeControl, SelectControl } from '../';
import CategorySelect from './category-select';
const DEFAULT_MIN_ITEMS = 1;
const DEFAULT_MAX_ITEMS = 100;
const options = [{
label: __('Newest to oldest'),
value: 'date/desc'
}, {
label: __('Oldest to newest'),
value: 'date/asc'
}, {
/* translators: label for ordering posts by title in ascending order */
label: __('A → Z'),
value: 'title/asc'
}, {
/* translators: label for ordering posts by title in descending order */
label: __('Z → A'),
value: 'title/desc'
}];
const QueryControls = memo(({
categoriesList,
selectedCategoryId,
numberOfItems,
order,
orderBy,
maxItems = DEFAULT_MAX_ITEMS,
minItems = DEFAULT_MIN_ITEMS,
onCategoryChange,
onNumberOfItemsChange,
onOrderChange,
onOrderByChange
}) => {
const onChange = useCallback(value => {
const [newOrderBy, newOrder] = value.split('/');
if (newOrder !== order) {
onOrderChange(newOrder);
}
if (newOrderBy !== orderBy) {
onOrderByChange(newOrderBy);
}
}, [order, orderBy, onOrderByChange, onOrderChange]);
return createElement(Fragment, null, onOrderChange && onOrderByChange && createElement(SelectControl, {
label: __('Order by'),
value: `${orderBy}/${order}`,
options: options,
onChange: onChange,
hideCancelButton: true
}), onCategoryChange && createElement(CategorySelect, {
categoriesList: categoriesList,
label: __('Category'),
noOptionLabel: __('All'),
selectedCategoryId: selectedCategoryId,
onChange: onCategoryChange,
hideCancelButton: true
}), onNumberOfItemsChange && createElement(RangeControl, {
__next40pxDefaultSize: true,
label: __('Number of items'),
value: numberOfItems,
onChange: onNumberOfItemsChange,
min: minItems,
max: maxItems,
required: true
}));
});
export default QueryControls;
//# sourceMappingURL=index.native.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["__","useCallback","memo","RangeControl","SelectControl","CategorySelect","DEFAULT_MIN_ITEMS","DEFAULT_MAX_ITEMS","options","label","value","QueryControls","categoriesList","selectedCategoryId","numberOfItems","order","orderBy","maxItems","minItems","onCategoryChange","onNumberOfItemsChange","onOrderChange","onOrderByChange","onChange","newOrderBy","newOrder","split","createElement","Fragment","hideCancelButton","noOptionLabel","__next40pxDefaultSize","min","max","required"],"sources":["@wordpress/components/src/query-controls/index.native.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { useCallback, memo } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport { RangeControl, SelectControl } from '../';\nimport CategorySelect from './category-select';\n\nconst DEFAULT_MIN_ITEMS = 1;\nconst DEFAULT_MAX_ITEMS = 100;\n\nconst options = [\n\t{\n\t\tlabel: __( 'Newest to oldest' ),\n\t\tvalue: 'date/desc',\n\t},\n\t{\n\t\tlabel: __( 'Oldest to newest' ),\n\t\tvalue: 'date/asc',\n\t},\n\t{\n\t\t/* translators: label for ordering posts by title in ascending order */\n\t\tlabel: __( 'A → Z' ),\n\t\tvalue: 'title/asc',\n\t},\n\t{\n\t\t/* translators: label for ordering posts by title in descending order */\n\t\tlabel: __( 'Z → A' ),\n\t\tvalue: 'title/desc',\n\t},\n];\n\nconst QueryControls = memo(\n\t( {\n\t\tcategoriesList,\n\t\tselectedCategoryId,\n\t\tnumberOfItems,\n\t\torder,\n\t\torderBy,\n\t\tmaxItems = DEFAULT_MAX_ITEMS,\n\t\tminItems = DEFAULT_MIN_ITEMS,\n\t\tonCategoryChange,\n\t\tonNumberOfItemsChange,\n\t\tonOrderChange,\n\t\tonOrderByChange,\n\t} ) => {\n\t\tconst onChange = useCallback(\n\t\t\t( value ) => {\n\t\t\t\tconst [ newOrderBy, newOrder ] = value.split( '/' );\n\t\t\t\tif ( newOrder !== order ) {\n\t\t\t\t\tonOrderChange( newOrder );\n\t\t\t\t}\n\t\t\t\tif ( newOrderBy !== orderBy ) {\n\t\t\t\t\tonOrderByChange( newOrderBy );\n\t\t\t\t}\n\t\t\t},\n\t\t\t[ order, orderBy, onOrderByChange, onOrderChange ]\n\t\t);\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{ onOrderChange && onOrderByChange && (\n\t\t\t\t\t<SelectControl\n\t\t\t\t\t\tlabel={ __( 'Order by' ) }\n\t\t\t\t\t\tvalue={ `${ orderBy }/${ order }` }\n\t\t\t\t\t\toptions={ options }\n\t\t\t\t\t\tonChange={ onChange }\n\t\t\t\t\t\thideCancelButton={ true }\n\t\t\t\t\t/>\n\t\t\t\t) }\n\t\t\t\t{ onCategoryChange && (\n\t\t\t\t\t<CategorySelect\n\t\t\t\t\t\tcategoriesList={ categoriesList }\n\t\t\t\t\t\tlabel={ __( 'Category' ) }\n\t\t\t\t\t\tnoOptionLabel={ __( 'All' ) }\n\t\t\t\t\t\tselectedCategoryId={ selectedCategoryId }\n\t\t\t\t\t\tonChange={ onCategoryChange }\n\t\t\t\t\t\thideCancelButton={ true }\n\t\t\t\t\t/>\n\t\t\t\t) }\n\t\t\t\t{ onNumberOfItemsChange && (\n\t\t\t\t\t<RangeControl\n\t\t\t\t\t\t__next40pxDefaultSize\n\t\t\t\t\t\tlabel={ __( 'Number of items' ) }\n\t\t\t\t\t\tvalue={ numberOfItems }\n\t\t\t\t\t\tonChange={ onNumberOfItemsChange }\n\t\t\t\t\t\tmin={ minItems }\n\t\t\t\t\t\tmax={ maxItems }\n\t\t\t\t\t\trequired\n\t\t\t\t\t/>\n\t\t\t\t) }\n\t\t\t</>\n\t\t);\n\t}\n);\n\nexport default QueryControls;\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,EAAE,QAAQ,iBAAiB;AACpC,SAASC,WAAW,EAAEC,IAAI,QAAQ,oBAAoB;;AAEtD;AACA;AACA;AACA,SAASC,YAAY,EAAEC,aAAa,QAAQ,KAAK;AACjD,OAAOC,cAAc,MAAM,mBAAmB;AAE9C,MAAMC,iBAAiB,GAAG,CAAC;AAC3B,MAAMC,iBAAiB,GAAG,GAAG;AAE7B,MAAMC,OAAO,GAAG,CACf;EACCC,KAAK,EAAET,EAAE,CAAE,kBAAmB,CAAC;EAC/BU,KAAK,EAAE;AACR,CAAC,EACD;EACCD,KAAK,EAAET,EAAE,CAAE,kBAAmB,CAAC;EAC/BU,KAAK,EAAE;AACR,CAAC,EACD;EACC;EACAD,KAAK,EAAET,EAAE,CAAE,OAAQ,CAAC;EACpBU,KAAK,EAAE;AACR,CAAC,EACD;EACC;EACAD,KAAK,EAAET,EAAE,CAAE,OAAQ,CAAC;EACpBU,KAAK,EAAE;AACR,CAAC,CACD;AAED,MAAMC,aAAa,GAAGT,IAAI,CACzB,CAAE;EACDU,cAAc;EACdC,kBAAkB;EAClBC,aAAa;EACbC,KAAK;EACLC,OAAO;EACPC,QAAQ,GAAGV,iBAAiB;EAC5BW,QAAQ,GAAGZ,iBAAiB;EAC5Ba,gBAAgB;EAChBC,qBAAqB;EACrBC,aAAa;EACbC;AACD,CAAC,KAAM;EACN,MAAMC,QAAQ,GAAGtB,WAAW,CACzBS,KAAK,IAAM;IACZ,MAAM,CAAEc,UAAU,EAAEC,QAAQ,CAAE,GAAGf,KAAK,CAACgB,KAAK,CAAE,GAAI,CAAC;IACnD,IAAKD,QAAQ,KAAKV,KAAK,EAAG;MACzBM,aAAa,CAAEI,QAAS,CAAC;IAC1B;IACA,IAAKD,UAAU,KAAKR,OAAO,EAAG;MAC7BM,eAAe,CAAEE,UAAW,CAAC;IAC9B;EACD,CAAC,EACD,CAAET,KAAK,EAAEC,OAAO,EAAEM,eAAe,EAAED,aAAa,CACjD,CAAC;EAED,OACCM,aAAA,CAAAC,QAAA,QACGP,aAAa,IAAIC,eAAe,IACjCK,aAAA,CAACvB,aAAa;IACbK,KAAK,EAAGT,EAAE,CAAE,UAAW,CAAG;IAC1BU,KAAK,EAAI,GAAGM,OAAS,IAAID,KAAO,EAAG;IACnCP,OAAO,EAAGA,OAAS;IACnBe,QAAQ,EAAGA,QAAU;IACrBM,gBAAgB,EAAG;EAAM,CACzB,CACD,EACCV,gBAAgB,IACjBQ,aAAA,CAACtB,cAAc;IACdO,cAAc,EAAGA,cAAgB;IACjCH,KAAK,EAAGT,EAAE,CAAE,UAAW,CAAG;IAC1B8B,aAAa,EAAG9B,EAAE,CAAE,KAAM,CAAG;IAC7Ba,kBAAkB,EAAGA,kBAAoB;IACzCU,QAAQ,EAAGJ,gBAAkB;IAC7BU,gBAAgB,EAAG;EAAM,CACzB,CACD,EACCT,qBAAqB,IACtBO,aAAA,CAACxB,YAAY;IACZ4B,qBAAqB;IACrBtB,KAAK,EAAGT,EAAE,CAAE,iBAAkB,CAAG;IACjCU,KAAK,EAAGI,aAAe;IACvBS,QAAQ,EAAGH,qBAAuB;IAClCY,GAAG,EAAGd,QAAU;IAChBe,GAAG,EAAGhB,QAAU;IAChBiB,QAAQ;EAAA,CACR,CAED,CAAC;AAEL,CACD,CAAC;AAED,eAAevB,aAAa"}

View File

@@ -0,0 +1,51 @@
/**
* Internal dependencies
*/
const ensureParentsAreDefined = terms => {
return terms.every(term => term.parent !== null);
};
/**
* Returns terms in a tree form.
*
* @param flatTerms Array of terms in flat format.
*
* @return Terms in tree format.
*/
export function buildTermsTree(flatTerms) {
const flatTermsWithParentAndChildren = flatTerms.map(term => ({
children: [],
parent: null,
...term,
id: String(term.id)
}));
// We use a custom type guard here to ensure that the parent property is
// defined on all terms. The type of the `parent` property is `number | null`
// and we need to ensure that it is `number`. This is because we use the
// `parent` property as a key in the `termsByParent` object.
if (!ensureParentsAreDefined(flatTermsWithParentAndChildren)) {
return flatTermsWithParentAndChildren;
}
const termsByParent = flatTermsWithParentAndChildren.reduce((acc, term) => {
const {
parent
} = term;
if (!acc[parent]) {
acc[parent] = [];
}
acc[parent].push(term);
return acc;
}, {});
const fillWithChildren = terms => {
return terms.map(term => {
const children = termsByParent[term.id];
return {
...term,
children: children && children.length ? fillWithChildren(children) : []
};
});
};
return fillWithChildren(termsByParent['0'] || []);
}
//# sourceMappingURL=terms.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["ensureParentsAreDefined","terms","every","term","parent","buildTermsTree","flatTerms","flatTermsWithParentAndChildren","map","children","id","String","termsByParent","reduce","acc","push","fillWithChildren","length"],"sources":["@wordpress/components/src/query-controls/terms.ts"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport type {\n\tAuthor,\n\tCategory,\n\tTermWithParentAndChildren,\n\tTermsByParent,\n} from './types';\n\nconst ensureParentsAreDefined = (\n\tterms: TermWithParentAndChildren[]\n): terms is ( TermWithParentAndChildren & { parent: number } )[] => {\n\treturn terms.every( ( term ) => term.parent !== null );\n};\n/**\n * Returns terms in a tree form.\n *\n * @param flatTerms Array of terms in flat format.\n *\n * @return Terms in tree format.\n */\nexport function buildTermsTree( flatTerms: readonly ( Author | Category )[] ) {\n\tconst flatTermsWithParentAndChildren: TermWithParentAndChildren[] =\n\t\tflatTerms.map( ( term ) => ( {\n\t\t\tchildren: [],\n\t\t\tparent: null,\n\t\t\t...term,\n\t\t\tid: String( term.id ),\n\t\t} ) );\n\n\t// We use a custom type guard here to ensure that the parent property is\n\t// defined on all terms. The type of the `parent` property is `number | null`\n\t// and we need to ensure that it is `number`. This is because we use the\n\t// `parent` property as a key in the `termsByParent` object.\n\tif ( ! ensureParentsAreDefined( flatTermsWithParentAndChildren ) ) {\n\t\treturn flatTermsWithParentAndChildren;\n\t}\n\n\tconst termsByParent = flatTermsWithParentAndChildren.reduce(\n\t\t( acc: TermsByParent, term ) => {\n\t\t\tconst { parent } = term;\n\t\t\tif ( ! acc[ parent ] ) {\n\t\t\t\tacc[ parent ] = [];\n\t\t\t}\n\t\t\tacc[ parent ].push( term );\n\t\t\treturn acc;\n\t\t},\n\t\t{}\n\t);\n\n\tconst fillWithChildren = (\n\t\tterms: TermWithParentAndChildren[]\n\t): TermWithParentAndChildren[] => {\n\t\treturn terms.map( ( term ) => {\n\t\t\tconst children = termsByParent[ term.id ];\n\t\t\treturn {\n\t\t\t\t...term,\n\t\t\t\tchildren:\n\t\t\t\t\tchildren && children.length\n\t\t\t\t\t\t? fillWithChildren( children )\n\t\t\t\t\t\t: [],\n\t\t\t};\n\t\t} );\n\t};\n\n\treturn fillWithChildren( termsByParent[ '0' ] || [] );\n}\n"],"mappings":"AAAA;AACA;AACA;;AAQA,MAAMA,uBAAuB,GAC5BC,KAAkC,IACiC;EACnE,OAAOA,KAAK,CAACC,KAAK,CAAIC,IAAI,IAAMA,IAAI,CAACC,MAAM,KAAK,IAAK,CAAC;AACvD,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAAEC,SAA2C,EAAG;EAC7E,MAAMC,8BAA2D,GAChED,SAAS,CAACE,GAAG,CAAIL,IAAI,KAAQ;IAC5BM,QAAQ,EAAE,EAAE;IACZL,MAAM,EAAE,IAAI;IACZ,GAAGD,IAAI;IACPO,EAAE,EAAEC,MAAM,CAAER,IAAI,CAACO,EAAG;EACrB,CAAC,CAAG,CAAC;;EAEN;EACA;EACA;EACA;EACA,IAAK,CAAEV,uBAAuB,CAAEO,8BAA+B,CAAC,EAAG;IAClE,OAAOA,8BAA8B;EACtC;EAEA,MAAMK,aAAa,GAAGL,8BAA8B,CAACM,MAAM,CAC1D,CAAEC,GAAkB,EAAEX,IAAI,KAAM;IAC/B,MAAM;MAAEC;IAAO,CAAC,GAAGD,IAAI;IACvB,IAAK,CAAEW,GAAG,CAAEV,MAAM,CAAE,EAAG;MACtBU,GAAG,CAAEV,MAAM,CAAE,GAAG,EAAE;IACnB;IACAU,GAAG,CAAEV,MAAM,CAAE,CAACW,IAAI,CAAEZ,IAAK,CAAC;IAC1B,OAAOW,GAAG;EACX,CAAC,EACD,CAAC,CACF,CAAC;EAED,MAAME,gBAAgB,GACrBf,KAAkC,IACD;IACjC,OAAOA,KAAK,CAACO,GAAG,CAAIL,IAAI,IAAM;MAC7B,MAAMM,QAAQ,GAAGG,aAAa,CAAET,IAAI,CAACO,EAAE,CAAE;MACzC,OAAO;QACN,GAAGP,IAAI;QACPM,QAAQ,EACPA,QAAQ,IAAIA,QAAQ,CAACQ,MAAM,GACxBD,gBAAgB,CAAEP,QAAS,CAAC,GAC5B;MACL,CAAC;IACF,CAAE,CAAC;EACJ,CAAC;EAED,OAAOO,gBAAgB,CAAEJ,aAAa,CAAE,GAAG,CAAE,IAAI,EAAG,CAAC;AACtD"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":[],"sources":["@wordpress/components/src/query-controls/types.ts"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport type { FormTokenFieldProps } from '../form-token-field/types';\nimport type { TreeSelectProps } from '../tree-select/types';\n\nexport type Author = {\n\tid: number;\n\tname: string;\n};\n\nexport type Category = {\n\tid: number;\n\tname: string;\n\tparent: number;\n};\n\nexport type TermWithParentAndChildren = {\n\tid: string;\n\tname: string;\n\tparent: number | null;\n\tchildren: TermWithParentAndChildren[];\n};\n\nexport type TermsByParent = Record< string, TermWithParentAndChildren[] >;\n\nexport type CategorySelectProps = Pick<\n\tTreeSelectProps,\n\t'label' | 'noOptionLabel'\n> & {\n\tcategoriesList: Category[];\n\tonChange: ( newCategory: string ) => void;\n\tselectedCategoryId?: Category[ 'id' ];\n\t__next40pxDefaultSize: boolean;\n};\n\nexport type AuthorSelectProps = Pick<\n\tTreeSelectProps,\n\t'label' | 'noOptionLabel'\n> & {\n\tauthorList?: Author[];\n\tonChange: ( newAuthor: string ) => void;\n\tselectedAuthorId?: Author[ 'id' ];\n\t__next40pxDefaultSize: boolean;\n};\n\ntype Order = 'asc' | 'desc';\ntype OrderBy = 'date' | 'title';\n\ntype BaseQueryControlsProps = {\n\t/**\n\t * An array of the authors to select from.\n\t */\n\tauthorList?: AuthorSelectProps[ 'authorList' ];\n\t/**\n\t * The maximum number of items.\n\t *\n\t * @default 100\n\t */\n\tmaxItems?: number;\n\t/**\n\t * The minimum number of items.\n\t *\n\t * @default 1\n\t */\n\tminItems?: number;\n\t/**\n\t * The selected number of items to retrieve via the query.\n\t */\n\tnumberOfItems?: number;\n\t/**\n\t * A function that receives the new author value.\n\t * If not specified, the author controls are not rendered.\n\t */\n\tonAuthorChange?: AuthorSelectProps[ 'onChange' ];\n\t/**\n\t * A function that receives the new number of items.\n\t * If not specified, then the number of items\n\t * range control is not rendered.\n\t */\n\tonNumberOfItemsChange?: ( newNumber?: number ) => void;\n\t/**\n\t * A function that receives the new order value.\n\t * If this prop or the `onOrderByChange` prop are not specified,\n\t * then the order controls are not rendered.\n\t */\n\tonOrderChange?: ( newOrder: Order ) => void;\n\t/**\n\t * A function that receives the new orderby value.\n\t * If this prop or the `onOrderChange` prop are not specified,\n\t * then the order controls are not rendered.\n\t */\n\tonOrderByChange?: ( newOrderBy: OrderBy ) => void;\n\t/**\n\t * The order in which to retrieve posts.\n\t */\n\torder?: Order;\n\t/**\n\t * The meta key by which to order posts.\n\t */\n\torderBy?: OrderBy;\n\t/**\n\t * The selected author ID.\n\t */\n\tselectedAuthorId?: AuthorSelectProps[ 'selectedAuthorId' ];\n\t/**\n\t * Start opting into the larger default height that will become the\n\t * default size in a future version.\n\t *\n\t * @default false\n\t */\n\t__next40pxDefaultSize?: boolean;\n};\n\nexport type QueryControlsWithSingleCategorySelectionProps =\n\tBaseQueryControlsProps & {\n\t\t/**\n\t\t * An array of categories. When passed in conjunction with the\n\t\t * `onCategoryChange` prop, it causes the component to render UI that allows\n\t\t * selecting one category at a time.\n\t\t */\n\t\tcategoriesList?: CategorySelectProps[ 'categoriesList' ];\n\t\t/**\n\t\t * The selected category for the `categoriesList` prop.\n\t\t */\n\t\tselectedCategoryId?: CategorySelectProps[ 'selectedCategoryId' ];\n\t\t/**\n\t\t * A function that receives the new category value. If not specified, the\n\t\t * category controls are not rendered.\n\t\t * The function's signature changes depending on whether multiple category\n\t\t * selection is enabled or not.\n\t\t */\n\t\tonCategoryChange?: CategorySelectProps[ 'onChange' ];\n\t};\n\nexport type QueryControlsWithMultipleCategorySelectionProps =\n\tBaseQueryControlsProps & {\n\t\t/**\n\t\t * An object of categories with the category name as the key. When passed in\n\t\t * conjunction with the `onCategoryChange` prop, it causes the component to\n\t\t * render UI that enables multiple selection.\n\t\t */\n\t\tcategorySuggestions?: Record< Category[ 'name' ], Category >;\n\t\t/**\n\t\t * The selected categories for the `categorySuggestions` prop.\n\t\t */\n\t\tselectedCategories?: Category[];\n\t\t/**\n\t\t * A function that receives the new category value. If not specified, the\n\t\t * category controls are not rendered.\n\t\t * The function's signature changes depending on whether multiple category\n\t\t * selection is enabled or not.\n\t\t */\n\t\tonCategoryChange?: FormTokenFieldProps[ 'onChange' ];\n\t};\n\nexport type QueryControlsProps =\n\t| QueryControlsWithSingleCategorySelectionProps\n\t| QueryControlsWithMultipleCategorySelectionProps;\n"],"mappings":""}