Merge pull request #33134 from woocommerce/dev/33098-migrate-woo-notice-to-ts
Migrate `@woocommerce/notices` to TS
This commit is contained in:
commit
63bb681c14
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Migrate @woocommerce/notices to TS
|
|
@ -20,6 +20,7 @@
|
|||
},
|
||||
"main": "build/index.js",
|
||||
"module": "build-module/index.js",
|
||||
"types": "build-types",
|
||||
"react-native": "src/index",
|
||||
"dependencies": {
|
||||
"@wordpress/a11y": "^3.5.0",
|
||||
|
@ -45,11 +46,13 @@
|
|||
"lint:fix": "eslint src --fix"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@automattic/data-stores": "^2.0.1",
|
||||
"@babel/core": "^7.17.5",
|
||||
"@woocommerce/eslint-plugin": "workspace:*",
|
||||
"eslint": "^8.12.0",
|
||||
"jest": "^27.5.1",
|
||||
"jest-cli": "^27.5.1",
|
||||
"redux": "^4.2.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^27.1.3",
|
||||
"typescript": "^4.6.2"
|
||||
|
|
|
@ -2,22 +2,25 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { uniqueId } from 'lodash';
|
||||
import { Status, Action as WPNoticeAction } from '@wordpress/notices';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { DEFAULT_CONTEXT, DEFAULT_STATUS } from './constants';
|
||||
|
||||
/**
|
||||
* @typedef {Object} WPNoticeAction Object describing a user action option associated with a notice.
|
||||
*
|
||||
* @property {string} label Message to use as action label.
|
||||
* @property {?string} url Optional URL of resource if action incurs
|
||||
* browser navigation.
|
||||
* @property {?Function} onClick Optional function to invoke when action is
|
||||
* triggered by user.
|
||||
*
|
||||
*/
|
||||
export type Options = {
|
||||
id: string;
|
||||
context: string;
|
||||
isDismissible: boolean;
|
||||
type: string;
|
||||
speak: boolean;
|
||||
actions: Array< WPNoticeAction >;
|
||||
icon: null | JSX.Element;
|
||||
explicitDismiss: boolean;
|
||||
onDismiss: ( () => void ) | null;
|
||||
__unstableHTML?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an action object used in signalling that a notice is to be created.
|
||||
|
@ -46,10 +49,15 @@ import { DEFAULT_CONTEXT, DEFAULT_STATUS } from './constants';
|
|||
* can't be dismissed by clicking
|
||||
* the body of the notice.
|
||||
* @param {Function} [options.onDismiss] Called when the notice is dismissed.
|
||||
* @param {boolean} [options.__unstableHTML] Notice message as raw HTML.
|
||||
*
|
||||
* @return {Object} Action object.
|
||||
* @return {Object} WPNoticeAction object.
|
||||
*/
|
||||
export function createNotice( status = DEFAULT_STATUS, content, options = {} ) {
|
||||
export function createNotice(
|
||||
status: Status = DEFAULT_STATUS,
|
||||
content: string,
|
||||
options: Partial< Options > = {}
|
||||
) {
|
||||
const {
|
||||
speak = true,
|
||||
isDismissible = true,
|
||||
|
@ -62,14 +70,13 @@ export function createNotice( status = DEFAULT_STATUS, content, options = {} ) {
|
|||
explicitDismiss = false,
|
||||
onDismiss = null,
|
||||
} = options;
|
||||
|
||||
// The supported value shape of content is currently limited to plain text
|
||||
// strings. To avoid setting expectation that e.g. a WPElement could be
|
||||
// supported, cast to a string.
|
||||
content = String( content );
|
||||
|
||||
return {
|
||||
type: 'CREATE_NOTICE',
|
||||
type: 'CREATE_NOTICE' as const,
|
||||
context,
|
||||
notice: {
|
||||
id,
|
||||
|
@ -98,7 +105,7 @@ export function createNotice( status = DEFAULT_STATUS, content, options = {} ) {
|
|||
*
|
||||
* @return {Object} Action object.
|
||||
*/
|
||||
export function createSuccessNotice( content, options ) {
|
||||
export function createSuccessNotice( content: string, options: Options ) {
|
||||
return createNotice( 'success', content, options );
|
||||
}
|
||||
|
||||
|
@ -113,7 +120,7 @@ export function createSuccessNotice( content, options ) {
|
|||
*
|
||||
* @return {Object} Action object.
|
||||
*/
|
||||
export function createInfoNotice( content, options ) {
|
||||
export function createInfoNotice( content: string, options: Options ) {
|
||||
return createNotice( 'info', content, options );
|
||||
}
|
||||
|
||||
|
@ -128,7 +135,7 @@ export function createInfoNotice( content, options ) {
|
|||
*
|
||||
* @return {Object} Action object.
|
||||
*/
|
||||
export function createErrorNotice( content, options ) {
|
||||
export function createErrorNotice( content: string, options: Options ) {
|
||||
return createNotice( 'error', content, options );
|
||||
}
|
||||
|
||||
|
@ -143,7 +150,7 @@ export function createErrorNotice( content, options ) {
|
|||
*
|
||||
* @return {Object} Action object.
|
||||
*/
|
||||
export function createWarningNotice( content, options ) {
|
||||
export function createWarningNotice( content: string, options: Options ) {
|
||||
return createNotice( 'warning', content, options );
|
||||
}
|
||||
|
||||
|
@ -156,10 +163,12 @@ export function createWarningNotice( content, options ) {
|
|||
*
|
||||
* @return {Object} Action object.
|
||||
*/
|
||||
export function removeNotice( id, context = DEFAULT_CONTEXT ) {
|
||||
export function removeNotice( id: string, context: string = DEFAULT_CONTEXT ) {
|
||||
return {
|
||||
type: 'REMOVE_NOTICE',
|
||||
type: 'REMOVE_NOTICE' as const,
|
||||
id,
|
||||
context,
|
||||
};
|
||||
}
|
||||
|
||||
export type Action = ReturnType< typeof createNotice | typeof removeNotice >;
|
|
@ -12,4 +12,4 @@ export const DEFAULT_CONTEXT = 'global';
|
|||
*
|
||||
* @type {string}
|
||||
*/
|
||||
export const DEFAULT_STATUS = 'info';
|
||||
export const DEFAULT_STATUS = 'info' as const;
|
|
@ -3,8 +3,13 @@
|
|||
*/
|
||||
import { speak } from '@wordpress/a11y';
|
||||
|
||||
export type Action = {
|
||||
message: string;
|
||||
ariaLive?: string;
|
||||
};
|
||||
|
||||
export default {
|
||||
SPEAK( action ) {
|
||||
SPEAK( action: Action ) {
|
||||
speak( action.message, action.ariaLive || 'assertive' );
|
||||
},
|
||||
};
|
|
@ -1,19 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { registerStore } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import reducer from './reducer';
|
||||
import * as actions from './actions';
|
||||
import * as selectors from './selectors';
|
||||
|
||||
// NOTE: This uses core/notices2, if this file is copied back upstream
|
||||
// to Gutenberg this needs to be changed back to core/notices.
|
||||
export default registerStore( 'core/notices2', {
|
||||
reducer,
|
||||
actions,
|
||||
selectors,
|
||||
} );
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { registerStore } from '@wordpress/data';
|
||||
import { SelectFromMap, DispatchFromMap } from '@automattic/data-stores';
|
||||
import { Reducer, AnyAction } from 'redux';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import reducer from './reducer';
|
||||
import * as actions from './actions';
|
||||
import * as selectors from './selectors';
|
||||
import { State } from './types';
|
||||
export * from './types';
|
||||
|
||||
export const STORE_NAME = 'core/notices2';
|
||||
// NOTE: This uses core/notices2, if this file is copied back upstream
|
||||
// to Gutenberg this needs to be changed back to core/notices.
|
||||
export default registerStore< State >( STORE_NAME, {
|
||||
reducer: reducer as Reducer< State, AnyAction >,
|
||||
actions,
|
||||
selectors,
|
||||
} );
|
||||
|
||||
declare module '@wordpress/data' {
|
||||
// TODO: convert action.js to TS
|
||||
function dispatch(
|
||||
key: typeof STORE_NAME
|
||||
): DispatchFromMap< typeof actions >;
|
||||
function select(
|
||||
key: typeof STORE_NAME
|
||||
): SelectFromMap< typeof selectors >;
|
||||
}
|
|
@ -2,22 +2,24 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { reject } from 'lodash';
|
||||
import type { Reducer } from 'redux';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import onSubKey from './utils/on-sub-key';
|
||||
import { Action } from './actions';
|
||||
import { Notices } from './types';
|
||||
|
||||
/**
|
||||
* Reducer returning the next notices state. The notices state is an object
|
||||
* where each key is a context, its value an array of notice objects.
|
||||
* Reducer returning the next notices state. The notices state is an array of notice objects
|
||||
*
|
||||
* @param {Object} state Current state.
|
||||
* @param {Array} state Current state.
|
||||
* @param {Object} action Dispatched action.
|
||||
*
|
||||
* @return {Object} Updated state.
|
||||
*/
|
||||
const notices = onSubKey( 'context' )( ( state = [], action ) => {
|
||||
const notices: Reducer< Notices, Action > = ( state = [], action ) => {
|
||||
switch ( action.type ) {
|
||||
case 'CREATE_NOTICE':
|
||||
// Avoid duplicates on ID.
|
||||
|
@ -29,8 +31,12 @@ const notices = onSubKey( 'context' )( ( state = [], action ) => {
|
|||
case 'REMOVE_NOTICE':
|
||||
return reject( state, { id: action.id } );
|
||||
}
|
||||
|
||||
return state;
|
||||
} );
|
||||
};
|
||||
|
||||
export default notices;
|
||||
export type State = {
|
||||
[ context: string ]: Notices;
|
||||
};
|
||||
|
||||
// Creates a combined reducer object where each key is a context, its value an array of notice objects.
|
||||
export default onSubKey( 'context' )( notices );
|
|
@ -2,6 +2,7 @@
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { DEFAULT_CONTEXT } from './constants';
|
||||
import { State } from './reducer';
|
||||
|
||||
/** @typedef {import('./actions').WPNoticeAction} WPNoticeAction */
|
||||
|
||||
|
@ -14,7 +15,7 @@ import { DEFAULT_CONTEXT } from './constants';
|
|||
*
|
||||
* @type {Array}
|
||||
*/
|
||||
const DEFAULT_NOTICES = [];
|
||||
const DEFAULT_NOTICES: [ ] = [];
|
||||
|
||||
/**
|
||||
* @typedef {Object} WPNotice Notice object.
|
||||
|
@ -51,6 +52,6 @@ const DEFAULT_NOTICES = [];
|
|||
*
|
||||
* @return {WPNotice[]} Array of notices.
|
||||
*/
|
||||
export function getNotices( state, context = DEFAULT_CONTEXT ) {
|
||||
export function getNotices( state: State, context: string = DEFAULT_CONTEXT ) {
|
||||
return state[ context ] || DEFAULT_NOTICES;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { createNotice } from './actions';
|
||||
|
||||
export type Notices = Array< ReturnType< typeof createNotice >[ 'notice' ] >;
|
||||
|
||||
export type State = {
|
||||
[ context: string ]: Notices;
|
||||
};
|
|
@ -1,3 +1,14 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import type { Reducer } from 'redux';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { State, Notices } from '../types';
|
||||
import { Action } from '../actions';
|
||||
|
||||
/**
|
||||
* Higher-order reducer creator which creates a combined reducer object, keyed
|
||||
* by a property on the action object.
|
||||
|
@ -6,10 +17,9 @@
|
|||
*
|
||||
* @return {Function} Higher-order reducer.
|
||||
*/
|
||||
export const onSubKey = ( actionProperty ) => ( reducer ) => (
|
||||
state = {},
|
||||
action
|
||||
) => {
|
||||
export const onSubKey = ( actionProperty: keyof Action ) => (
|
||||
reducer: Reducer< Notices, Action >
|
||||
) => ( state: State = {}, action: Action ) => {
|
||||
// Retrieve subkey from action. Do not track if undefined; useful for cases
|
||||
// where reducer is scoped by action shape.
|
||||
const key = action[ actionProperty ];
|
|
@ -2,6 +2,9 @@
|
|||
"extends": "../tsconfig",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "build-module"
|
||||
"outDir": "build-module",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"declarationDir": "./build-types"
|
||||
}
|
||||
}
|
|
@ -1011,6 +1011,7 @@ importers:
|
|||
|
||||
packages/js/notices:
|
||||
specifiers:
|
||||
'@automattic/data-stores': ^2.0.1
|
||||
'@babel/core': ^7.17.5
|
||||
'@woocommerce/eslint-plugin': workspace:*
|
||||
'@wordpress/a11y': ^3.5.0
|
||||
|
@ -1019,6 +1020,7 @@ importers:
|
|||
eslint: ^8.12.0
|
||||
jest: ^27.5.1
|
||||
jest-cli: ^27.5.1
|
||||
redux: ^4.2.0
|
||||
rimraf: ^3.0.2
|
||||
ts-jest: ^27.1.3
|
||||
typescript: ^4.6.2
|
||||
|
@ -1027,11 +1029,13 @@ importers:
|
|||
'@wordpress/data': 6.4.1
|
||||
'@wordpress/notices': 3.4.1
|
||||
devDependencies:
|
||||
'@automattic/data-stores': 2.0.1_@wordpress+data@6.4.1
|
||||
'@babel/core': 7.17.8
|
||||
'@woocommerce/eslint-plugin': link:../eslint-plugin
|
||||
eslint: 8.12.0
|
||||
jest: 27.5.1
|
||||
jest-cli: 27.5.1
|
||||
redux: 4.2.0
|
||||
rimraf: 3.0.2
|
||||
ts-jest: 27.1.3_b64eba0a9f1c7068f7f3a75addda5ccd
|
||||
typescript: 4.6.2
|
||||
|
@ -34661,6 +34665,12 @@ packages:
|
|||
dependencies:
|
||||
'@babel/runtime': 7.17.7
|
||||
|
||||
/redux/4.2.0:
|
||||
resolution: {integrity: sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.17.7
|
||||
dev: true
|
||||
|
||||
/reflect.ownkeys/0.2.0:
|
||||
resolution: {integrity: sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=}
|
||||
|
||||
|
|
Loading…
Reference in New Issue