@automattic/launchpad 1.0.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 (71) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +35 -0
  3. package/dist/cjs/badge/index.js +13 -0
  4. package/dist/cjs/badge/index.js.map +1 -0
  5. package/dist/cjs/badge/style.scss +50 -0
  6. package/dist/cjs/checklist/index.js +18 -0
  7. package/dist/cjs/checklist/index.js.map +1 -0
  8. package/dist/cjs/checklist/style.scss +9 -0
  9. package/dist/cjs/checklist-item/index.js +35 -0
  10. package/dist/cjs/checklist-item/index.js.map +1 -0
  11. package/dist/cjs/checklist-item/style.scss +214 -0
  12. package/dist/cjs/index.js +14 -0
  13. package/dist/cjs/index.js.map +1 -0
  14. package/dist/cjs/launchpad.js +19 -0
  15. package/dist/cjs/launchpad.js.map +1 -0
  16. package/dist/cjs/setup-actions.js +156 -0
  17. package/dist/cjs/setup-actions.js.map +1 -0
  18. package/dist/cjs/types.js +3 -0
  19. package/dist/cjs/types.js.map +1 -0
  20. package/dist/esm/badge/index.js +10 -0
  21. package/dist/esm/badge/index.js.map +1 -0
  22. package/dist/esm/badge/style.scss +50 -0
  23. package/dist/esm/checklist/index.js +15 -0
  24. package/dist/esm/checklist/index.js.map +1 -0
  25. package/dist/esm/checklist/style.scss +9 -0
  26. package/dist/esm/checklist-item/index.js +32 -0
  27. package/dist/esm/checklist-item/index.js.map +1 -0
  28. package/dist/esm/checklist-item/style.scss +214 -0
  29. package/dist/esm/index.js +6 -0
  30. package/dist/esm/index.js.map +1 -0
  31. package/dist/esm/launchpad.js +16 -0
  32. package/dist/esm/launchpad.js.map +1 -0
  33. package/dist/esm/setup-actions.js +151 -0
  34. package/dist/esm/setup-actions.js.map +1 -0
  35. package/dist/esm/types.js +2 -0
  36. package/dist/esm/types.js.map +1 -0
  37. package/dist/tsconfig-cjs.tsbuildinfo +1 -0
  38. package/dist/tsconfig.tsbuildinfo +1 -0
  39. package/dist/types/badge/index.d.ts +10 -0
  40. package/dist/types/badge/index.d.ts.map +1 -0
  41. package/dist/types/checklist/index.d.ts +12 -0
  42. package/dist/types/checklist/index.d.ts.map +1 -0
  43. package/dist/types/checklist-item/index.d.ts +11 -0
  44. package/dist/types/checklist-item/index.d.ts.map +1 -0
  45. package/dist/types/index.d.ts +6 -0
  46. package/dist/types/index.d.ts.map +1 -0
  47. package/dist/types/launchpad.d.ts +12 -0
  48. package/dist/types/launchpad.d.ts.map +1 -0
  49. package/dist/types/setup-actions.d.ts +3 -0
  50. package/dist/types/setup-actions.d.ts.map +1 -0
  51. package/dist/types/types.d.ts +64 -0
  52. package/dist/types/types.d.ts.map +1 -0
  53. package/jest.config.js +5 -0
  54. package/package.json +59 -0
  55. package/src/badge/index.tsx +27 -0
  56. package/src/badge/style.scss +50 -0
  57. package/src/checklist/index.tsx +43 -0
  58. package/src/checklist/style.scss +9 -0
  59. package/src/checklist-item/index.tsx +94 -0
  60. package/src/checklist-item/style.scss +214 -0
  61. package/src/index.ts +5 -0
  62. package/src/launchpad.tsx +45 -0
  63. package/src/setup-actions.ts +168 -0
  64. package/src/test/badge.tsx +50 -0
  65. package/src/test/checklist-item.tsx +96 -0
  66. package/src/test/checklist.tsx +25 -0
  67. package/src/test/launchpad.tsx +49 -0
  68. package/src/test/lib/fixtures.ts +322 -0
  69. package/src/types.ts +70 -0
  70. package/tsconfig-cjs.json +7 -0
  71. package/tsconfig.json +11 -0
@@ -0,0 +1,10 @@
1
+ /// <reference types="react" />
2
+ import './style.scss';
3
+ export interface BadgeProps {
4
+ type?: 'warning' | 'warning-clear' | 'success' | 'info' | 'info-blue' | 'info-green' | 'info-purple' | 'error';
5
+ className?: string;
6
+ children?: React.ReactNode;
7
+ }
8
+ declare const Badge: React.FunctionComponent<BadgeProps>;
9
+ export default Badge;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/badge/index.tsx"],"names":[],"mappings":";AAEA,OAAO,cAAc,CAAC;AAEtB,MAAM,WAAW,UAAU;IAC1B,IAAI,CAAC,EACF,SAAS,GACT,eAAe,GACf,SAAS,GACT,MAAM,GACN,WAAW,GACX,YAAY,GACZ,aAAa,GACb,OAAO,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,QAAA,MAAM,KAAK,EAAE,KAAK,CAAC,iBAAiB,CAAE,UAAU,CAM/C,CAAC;AAEF,eAAe,KAAK,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { Task } from '../types';
2
+ import './style.scss';
3
+ interface ChecklistProps {
4
+ tasks: Task[] | null;
5
+ makeLastTaskPrimaryAction?: boolean;
6
+ }
7
+ declare const Checklist: {
8
+ ({ tasks, makeLastTaskPrimaryAction }: ChecklistProps): import("react/jsx-runtime").JSX.Element;
9
+ Placeholder(): import("react/jsx-runtime").JSX.Element;
10
+ };
11
+ export default Checklist;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/checklist/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,OAAO,cAAc,CAAC;AAEtB,UAAU,cAAc;IACvB,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IACrB,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED,QAAA,MAAM,SAAS;2CAA2C,cAAc;;CAkBvE,CAAC;AAaF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { Task } from '../types';
2
+ import './style.scss';
3
+ declare const ChecklistItem: {
4
+ ({ task, isPrimaryAction }: {
5
+ task: Task;
6
+ isPrimaryAction?: boolean | undefined;
7
+ }): import("react/jsx-runtime").JSX.Element;
8
+ Placeholder(): import("react/jsx-runtime").JSX.Element;
9
+ };
10
+ export default ChecklistItem;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/checklist-item/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,OAAO,cAAc,CAAC;AAEtB,QAAA,MAAM,aAAa;;cAAwC,IAAI;;;;CA0E9D,CAAC;AAYF,eAAe,aAAa,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { default as Checklist } from './checklist';
2
+ export { default as ChecklistItem } from './checklist-item';
3
+ export { default as Launchpad } from './launchpad';
4
+ export { setUpActionsForTasks } from './setup-actions';
5
+ export * from './types';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,cAAc,SAAS,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Task } from './types';
2
+ import type { UseLaunchpadOptions } from '@automattic/data-stores';
3
+ export interface LaunchpadProps {
4
+ siteSlug: string | null;
5
+ checklistSlug?: string | 0 | null | undefined;
6
+ makeLastTaskPrimaryAction?: boolean;
7
+ taskFilter?: (tasks: Task[]) => Task[];
8
+ useLaunchpadOptions?: UseLaunchpadOptions;
9
+ }
10
+ declare const Launchpad: ({ siteSlug, checklistSlug, taskFilter, makeLastTaskPrimaryAction, useLaunchpadOptions, }: LaunchpadProps) => import("react/jsx-runtime").JSX.Element;
11
+ export default Launchpad;
12
+ //# sourceMappingURL=launchpad.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launchpad.d.ts","sourceRoot":"","sources":["../../src/launchpad.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,MAAM,WAAW,cAAc;IAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9C,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,UAAU,CAAC,EAAE,CAAE,KAAK,EAAE,IAAI,EAAE,KAAM,IAAI,EAAE,CAAC;IACzC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC1C;AAED,QAAA,MAAM,SAAS,6FAMZ,cAAc,4CAsBhB,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { LaunchpadTaskActionsProps, Task } from './types';
2
+ export declare const setUpActionsForTasks: ({ siteSlug, tasks, tracksData, extraActions, uiContext, }: LaunchpadTaskActionsProps) => Task[];
3
+ //# sourceMappingURL=setup-actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-actions.d.ts","sourceRoot":"","sources":["../../src/setup-actions.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,yBAAyB,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAW/D,eAAO,MAAM,oBAAoB,8DAM9B,yBAAyB,KAAI,IAAI,EAiJnC,CAAC"}
@@ -0,0 +1,64 @@
1
+ /// <reference types="react" />
2
+ export interface TaskExtraData {
3
+ about_page_id?: number;
4
+ }
5
+ export interface Task {
6
+ id: string;
7
+ completed: boolean;
8
+ disabled: boolean;
9
+ title?: string;
10
+ subtitle?: string | React.ReactNode | null;
11
+ badge_text?: string;
12
+ actionDispatch?: () => void;
13
+ isLaunchTask?: boolean;
14
+ extra_data?: TaskExtraData;
15
+ calypso_path?: string;
16
+ target_repetitions?: number;
17
+ repetition_count?: number;
18
+ order?: number;
19
+ }
20
+ export type LaunchpadChecklist = Task[];
21
+ export type LaunchpadTracksData = {
22
+ checklistSlug: string;
23
+ launchpadContext: string;
24
+ recordTracksEvent: (event: string, properties: Record<string, unknown>) => void;
25
+ tasklistCompleted: boolean;
26
+ };
27
+ export interface LaunchpadFlowTaskList {
28
+ [string: string]: string[];
29
+ }
30
+ export interface TranslatedLaunchpadStrings {
31
+ flowName: string;
32
+ title: string;
33
+ launchTitle?: string;
34
+ subtitle: string;
35
+ }
36
+ export interface LaunchpadStatuses {
37
+ links_edited?: boolean;
38
+ site_edited?: boolean;
39
+ site_launched?: boolean;
40
+ first_post_published?: boolean;
41
+ video_uploaded?: boolean;
42
+ publish_first_course?: boolean;
43
+ plan_selected?: boolean;
44
+ plan_completed?: boolean;
45
+ domain_upsell_deferred?: boolean;
46
+ }
47
+ export interface LaunchpadResponse {
48
+ site_intent: string;
49
+ launchpad_screen: boolean | string;
50
+ checklist_statuses: LaunchpadStatuses[];
51
+ }
52
+ export interface PermittedActions {
53
+ setShareSiteModalIsOpen?: (isOpen: boolean) => void;
54
+ siteLaunched?: () => void;
55
+ setActiveChecklist: (siteSlug: string, activeChecklistSlug: string) => void;
56
+ }
57
+ export interface LaunchpadTaskActionsProps {
58
+ siteSlug: string | null;
59
+ tasks: Task[];
60
+ tracksData: LaunchpadTracksData;
61
+ extraActions: PermittedActions;
62
+ uiContext?: 'calypso';
63
+ }
64
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";AAAA,MAAM,WAAW,aAAa;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AACD,MAAM,WAAW,IAAI;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,EAAE,CAAC;AAExC,MAAM,MAAM,mBAAmB,GAAG;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,CAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAE,MAAM,EAAE,OAAO,CAAE,KAAM,IAAI,CAAC;IACpF,iBAAiB,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACrC,CAAE,MAAM,EAAE,MAAM,GAAI,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,OAAO,GAAG,MAAM,CAAC;IACnC,kBAAkB,EAAE,iBAAiB,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,gBAAgB;IAChC,uBAAuB,CAAC,EAAE,CAAE,MAAM,EAAE,OAAO,KAAM,IAAI,CAAC;IACtD,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,kBAAkB,EAAE,CAAE,QAAQ,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,KAAM,IAAI,CAAC;CAC9E;AAED,MAAM,WAAW,yBAAyB;IACzC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,UAAU,EAAE,mBAAmB,CAAC;IAChC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,SAAS,CAAC,EAAE,SAAS,CAAC;CACtB"}
package/jest.config.js ADDED
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ preset: '../../test/packages/jest-preset.js',
3
+ testEnvironment: 'jsdom',
4
+ transformIgnorePatterns: [ 'node_modules/(?!gridicons)(?!.*\\.svg)' ],
5
+ };
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@automattic/launchpad",
3
+ "version": "1.0.0",
4
+ "description": "Launchpad components",
5
+ "homepage": "https://github.com/Automattic/wp-calypso",
6
+ "license": "GPL-2.0-or-later",
7
+ "author": "Automattic Inc.",
8
+ "main": "dist/cjs/index.js",
9
+ "module": "dist/esm/index.js",
10
+ "calypso:src": "src/index.ts",
11
+ "sideEffects": [
12
+ "*.css",
13
+ "*.scss"
14
+ ],
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/Automattic/wp-calypso.git",
18
+ "directory": "packages/launchpad"
19
+ },
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "bugs": "https://github.com/Automattic/wp-calypso/issues",
24
+ "types": "dist/types",
25
+ "scripts": {
26
+ "clean": "tsc --build ./tsconfig.json ./tsconfig-cjs.json --clean && rm -rf dist",
27
+ "build": "tsc --build ./tsconfig.json ./tsconfig-cjs.json && copy-assets",
28
+ "prepack": "yarn run clean && yarn run build",
29
+ "watch": "tsc --build ./tsconfig.json --watch"
30
+ },
31
+ "dependencies": {
32
+ "@automattic/components": "^2.0.1",
33
+ "@automattic/data-stores": "^3.0.1",
34
+ "@automattic/i18n-utils": "^1.2.0",
35
+ "classnames": "^2.3.1",
36
+ "tslib": "^2.3.0",
37
+ "utility-types": "^3.10.0",
38
+ "wpcom-proxy-request": "^7.0.4"
39
+ },
40
+ "devDependencies": {
41
+ "@automattic/calypso-build": "^10.0.0",
42
+ "@automattic/calypso-typescript-config": "^1.0.0",
43
+ "postcss": "^8.4.5",
44
+ "react": "^18.2.0",
45
+ "react-dom": "^18.2.0",
46
+ "redux": "^4.2.1",
47
+ "typescript": "^5.2.2",
48
+ "webpack": "^5.68.0"
49
+ },
50
+ "peerDependencies": {
51
+ "@wordpress/data": "^9.11.0",
52
+ "@wordpress/element": "^5.18.0",
53
+ "@wordpress/i18n": "^4.41.0",
54
+ "debug": "^4.3.3",
55
+ "react": "^18.2.0",
56
+ "react-dom": "^18.2.0",
57
+ "redux": "^4.2.1"
58
+ }
59
+ }
@@ -0,0 +1,27 @@
1
+ import classNames from 'classnames';
2
+
3
+ import './style.scss';
4
+
5
+ export interface BadgeProps {
6
+ type?:
7
+ | 'warning'
8
+ | 'warning-clear'
9
+ | 'success'
10
+ | 'info'
11
+ | 'info-blue'
12
+ | 'info-green'
13
+ | 'info-purple'
14
+ | 'error';
15
+ className?: string;
16
+ children?: React.ReactNode;
17
+ }
18
+
19
+ const Badge: React.FunctionComponent< BadgeProps > = ( props ) => {
20
+ const className = props.className;
21
+ const type = props.type || 'warning';
22
+ return (
23
+ <div className={ classNames( `badge badge--${ type }`, className ) }>{ props.children }</div>
24
+ );
25
+ };
26
+
27
+ export default Badge;
@@ -0,0 +1,50 @@
1
+ .badge {
2
+ display: inline-block;
3
+ // A number large enough to exceed height of any badge to make it look like a pill
4
+ border-radius: 1000px; /* stylelint-disable-line scales/radii */
5
+ padding: $badge-padding-y $badge-padding-x;
6
+ font-size: $font-body-small;
7
+ line-height: 17px;
8
+ height: 18px;
9
+ }
10
+
11
+ .badge--warning-clear {
12
+ color: var(--color-warning);
13
+ border: 1px solid var(--color-warning);
14
+ border-radius: 12px; /* stylelint-disable-line scales/radii */
15
+ }
16
+
17
+ .badge--warning {
18
+ color: var(--color-warning-80);
19
+ background-color: var(--color-warning-20);
20
+ }
21
+
22
+ .badge--success {
23
+ color: var(--color-text-inverted);
24
+ background-color: var(--color-success);
25
+ }
26
+
27
+ .badge--info {
28
+ color: var(--color-neutral-70);
29
+ background-color: var(--color-neutral-5);
30
+ }
31
+
32
+ .badge--info-blue {
33
+ background-color: var(--studio-blue-50);
34
+ color: var(--color-text-inverted);
35
+ }
36
+
37
+ .badge--info-green {
38
+ color: var(--studio-green-80);
39
+ background-color: rgba(184, 230, 191, 0.64);
40
+ }
41
+
42
+ .badge--info-purple {
43
+ color: var(--studio-woocommerce-purple-80);
44
+ background-color: var(--studio-woocommerce-purple-5);
45
+ }
46
+
47
+ .badge--error {
48
+ background-color: var(--color-error);
49
+ color: var(--color-text-inverted);
50
+ }
@@ -0,0 +1,43 @@
1
+ import classNames from 'classnames';
2
+ import ChecklistItem from '../checklist-item';
3
+ import { Task } from '../types';
4
+
5
+ import './style.scss';
6
+
7
+ interface ChecklistProps {
8
+ tasks: Task[] | null;
9
+ makeLastTaskPrimaryAction?: boolean;
10
+ }
11
+
12
+ const Checklist = ( { tasks, makeLastTaskPrimaryAction }: ChecklistProps ) => {
13
+ return (
14
+ <ul
15
+ className={ classNames( 'checklist__tasks', {
16
+ 'checklist__has-primary-action': makeLastTaskPrimaryAction,
17
+ } ) }
18
+ aria-label="Launchpad Checklist"
19
+ >
20
+ { tasks &&
21
+ tasks.map( ( task: Task, index: number ) => (
22
+ <ChecklistItem
23
+ key={ task.id }
24
+ task={ task }
25
+ isPrimaryAction={ makeLastTaskPrimaryAction && index === tasks.length - 1 }
26
+ />
27
+ ) ) }
28
+ </ul>
29
+ );
30
+ };
31
+
32
+ Checklist.Placeholder = () => {
33
+ return (
34
+ <ul className="checklist__tasks" aria-label="Launchpad Checklist">
35
+ <ChecklistItem.Placeholder />
36
+ <ChecklistItem.Placeholder />
37
+ <ChecklistItem.Placeholder />
38
+ <ChecklistItem.Placeholder />
39
+ </ul>
40
+ );
41
+ };
42
+
43
+ export default Checklist;
@@ -0,0 +1,9 @@
1
+ @import "@wordpress/base-styles/mixins";
2
+ @import "@wordpress/base-styles/breakpoints";
3
+ @import "@automattic/typography/styles/variables";
4
+
5
+ .checklist__tasks {
6
+ list-style: none;
7
+ margin: 0;
8
+ padding: 0;
9
+ }
@@ -0,0 +1,94 @@
1
+ import { Badge, Button, Gridicon } from '@automattic/components';
2
+ import classnames from 'classnames';
3
+ import { translate, useRtl } from 'i18n-calypso';
4
+ import { Task } from '../types';
5
+
6
+ import './style.scss';
7
+
8
+ const ChecklistItem = ( { task, isPrimaryAction }: { task: Task; isPrimaryAction?: boolean } ) => {
9
+ const isRtl = useRtl();
10
+ const { id, completed, disabled, title, subtitle, actionDispatch } = task;
11
+
12
+ // Display chevron if task is incomplete. Don't display chevron and badge at the same time.
13
+ const shouldDisplayChevron = ! completed && ! disabled && ! task.badge_text;
14
+
15
+ const handlePrimaryAction = () => {
16
+ localStorage.removeItem( 'launchpad_siteSlug' );
17
+ actionDispatch && actionDispatch();
18
+ };
19
+
20
+ // Display task counter if task is incomplete and has the count properties;
21
+ const shouldDisplayTaskCounter =
22
+ task.target_repetitions &&
23
+ null !== task.repetition_count &&
24
+ undefined !== task.repetition_count;
25
+
26
+ return (
27
+ <li
28
+ className={ classnames( 'checklist-item__task', {
29
+ completed: completed,
30
+ pending: ! completed,
31
+ enabled: ! disabled,
32
+ disabled: disabled,
33
+ } ) }
34
+ >
35
+ { isPrimaryAction ? (
36
+ <Button
37
+ className="checklist-item__checklist-primary-button"
38
+ disabled={ disabled }
39
+ data-task={ id }
40
+ onClick={ handlePrimaryAction }
41
+ >
42
+ { title }
43
+ </Button>
44
+ ) : (
45
+ <Button
46
+ className="checklist-item__task-content"
47
+ disabled={ disabled }
48
+ data-task={ id }
49
+ onClick={ actionDispatch }
50
+ >
51
+ { completed && (
52
+ // show checkmark for completed tasks regardless if they are disabled or kept active
53
+ <div className="checklist-item__checkmark-container">
54
+ <Gridicon
55
+ aria-label={ translate( 'Task complete' ) }
56
+ className="checklist-item__checkmark"
57
+ icon="checkmark"
58
+ size={ 18 }
59
+ />
60
+ </div>
61
+ ) }
62
+ <span className="checklist-item__text">{ title }</span>
63
+ { task.badge_text ? <Badge type="info-blue">{ task.badge_text }</Badge> : null }
64
+ { shouldDisplayTaskCounter && (
65
+ <span className="checklist-item__counter">
66
+ { task.repetition_count }/{ task.target_repetitions }
67
+ </span>
68
+ ) }
69
+ { shouldDisplayChevron && (
70
+ <Gridicon
71
+ aria-label={ translate( 'Task enabled' ) }
72
+ className="checklist-item__chevron"
73
+ icon={ `chevron-${ isRtl ? 'left' : 'right' }` }
74
+ size={ 18 }
75
+ />
76
+ ) }
77
+ { subtitle && <p className="checklist-item__subtext">{ subtitle }</p> }
78
+ </Button>
79
+ ) }
80
+ </li>
81
+ );
82
+ };
83
+
84
+ ChecklistItem.Placeholder = () => {
85
+ return (
86
+ <div className="checklist-item__task-content is-placeholder">
87
+ <div className="checklist-item__content">
88
+ <div></div>
89
+ </div>
90
+ </div>
91
+ );
92
+ };
93
+
94
+ export default ChecklistItem;
@@ -0,0 +1,214 @@
1
+ @import "@wordpress/base-styles/mixins";
2
+ @import "@wordpress/base-styles/breakpoints";
3
+ @import "@automattic/typography/styles/variables";
4
+
5
+ .checklist-item__task-content {
6
+ align-items: flex-start;
7
+ background-color: transparent;
8
+ border-bottom: 1px solid var(--studio-gray-5);
9
+ border-left: none;
10
+ border-right: none;
11
+ border-top: none;
12
+ display: flex;
13
+ flex-wrap: wrap;
14
+ padding: 16px 0;
15
+ width: 100%;
16
+ margin: 0;
17
+ color: var(--color-neutral-100);
18
+
19
+ &.is-placeholder {
20
+ padding: 16px 0 16px 0;
21
+ }
22
+ }
23
+
24
+ .checklist-item__content {
25
+ width: 100%;
26
+
27
+ .is-placeholder & {
28
+ animation: loading-fade 1.6s ease-in-out infinite;
29
+ background-color: var(--color-neutral-light);
30
+ color: transparent;
31
+ min-height: 44px;
32
+ }
33
+
34
+ >div {
35
+ .is-placeholder & {
36
+ color: transparent;
37
+ }
38
+ }
39
+ }
40
+
41
+ .button.checklist-item__task-content:hover:not([disabled]),
42
+ .button.checklist-item__task-content:focus:not([disabled]) {
43
+ fill: var(--studio-blue-50);
44
+ color: var(--studio-blue-50);
45
+ border-bottom: 1px solid var(--studio-gray-5);
46
+ }
47
+
48
+ .checklist-item__task-content .badge {
49
+ margin-left: auto;
50
+ background-color: var(--studio-blue-5);
51
+ color: var(--studio-blue-80);
52
+ font-size: $font-body-extra-small;
53
+ }
54
+
55
+ .checklist-item__task-content[disabled],
56
+ .checklist-item__task-content[disabled]:focus {
57
+ background-color: transparent;
58
+ pointer-events: none;
59
+ }
60
+
61
+ .checklist-item__task-content[data-task="verify_email"] {
62
+ color: var(--color-text);
63
+ }
64
+
65
+ .checklist-item__task-content[data-task="set_up_payments"] .badge {
66
+ background-color: var(--studio-green-5);
67
+ cursor: default;
68
+ }
69
+
70
+ .checklist-item__checkmark-container {
71
+ margin-right: 8px;
72
+ width: 20px;
73
+
74
+ .checklist-item__checkmark {
75
+ top: 2px;
76
+ vertical-align: text-bottom;
77
+ }
78
+ }
79
+
80
+ // general styles
81
+ .checklist-item__text {
82
+ font-weight: 600;
83
+ flex-grow: 1;
84
+ text-align: left;
85
+ }
86
+
87
+ .checklist-item__subtext {
88
+ flex-basis: 100%;
89
+ margin-left: 28px;
90
+ margin-top: 8px;
91
+ text-align: left;
92
+ font-size: $font-body-small;
93
+ line-height: 20px;
94
+
95
+ a,
96
+ a:visited {
97
+ text-decoration: underline;
98
+ color: var(--color-neutral-100);
99
+
100
+ &:hover {
101
+ color: var(--studio-blue-50);
102
+ }
103
+ }
104
+ }
105
+
106
+ .checklist-item__task-content:hover .checklist-item__subtext {
107
+ color: var(--color-neutral-100);
108
+ }
109
+
110
+ .checklist__has-primary-action .checklist-item__task:nth-last-child(2) {
111
+
112
+ // remove bottom border for last checklist item before the primary button
113
+ .checklist-item__task-content,
114
+ .checklist-item__task-content:hover,
115
+ .checklist-item__task-content:focus {
116
+ border-bottom: none;
117
+ }
118
+ }
119
+
120
+ .checklist-item__task:last-child {
121
+ .checklist-item__task-content,
122
+ .checklist-item__task-content:hover,
123
+ .checklist-item__task-content:focus {
124
+ border-bottom: none;
125
+ }
126
+ }
127
+
128
+ // completed tasks (both enabled and disabled)
129
+ .checklist-item__task.completed.disabled,
130
+ .checklist-item__task.completed.enabled {
131
+ .checklist-item__text {
132
+ color: var(--color-neutral-40);
133
+ font-weight: 400;
134
+ }
135
+
136
+ .checklist-item__chevron,
137
+ .checklist-item__checkmark {
138
+ fill: var(--color-neutral-40);
139
+ }
140
+ .checklist-item__counter {
141
+ color: var(--color-neutral-40);
142
+ font-weight: 400;
143
+ margin-right: 0;
144
+ }
145
+ }
146
+
147
+ // pending tasks and completed enabled
148
+ .checklist-item__task.completed.enabled:hover,
149
+ .checklist-item__task.pending:hover,
150
+ .checklist-item__task.completed.enabled > a:focus,
151
+ .checklist-item__task.pending > a:focus {
152
+ .checklist-item__text {
153
+ color: var(--studio-blue-50);
154
+ }
155
+
156
+ .checklist-item__chevron,
157
+ .checklist-item__checkmark {
158
+ fill: var(--studio-blue-50);
159
+ }
160
+
161
+ // change badge color on hover (Choose a Plan step)
162
+ .badge {
163
+ background: var(--studio-blue-10);
164
+ }
165
+
166
+ .checklist-item__task-content[data-task="set_up_payments"] .badge {
167
+ background-color: var(--studio-green-5);
168
+ }
169
+ }
170
+
171
+ // pending disabled tasks
172
+ .checklist-item__task.pending.disabled {
173
+ .checklist-item__text {
174
+ color: inherit;
175
+ }
176
+ }
177
+
178
+ .checklist-item__chevron {
179
+ display: flex;
180
+ line-height: 20px;
181
+ width: 30px;
182
+ }
183
+
184
+ .gridicon.checklist-item__chevron {
185
+ top: 2px;
186
+ margin-top: 0;
187
+ }
188
+
189
+ .checklist-item__counter {
190
+ margin-right: 1em;
191
+ font-weight: 600;
192
+ }
193
+
194
+ .checklist-item__checklist-primary-button {
195
+ width: 100%;
196
+ font-weight: 500;
197
+ padding: 11px;
198
+ margin-top: 12px;
199
+ background-color: var(--color-primary);
200
+ border-color: var(--color-primary);
201
+ color: var(--color-text-inverted);
202
+
203
+ &:hover:not([disabled]) {
204
+ background-color: var(--color-primary-60);
205
+ border-color: var(--color-primary-60);
206
+ color: var(--color-text-inverted);
207
+ }
208
+
209
+ &[disabled] {
210
+ background-color: var(--color-primary-10);
211
+ border-color: var(--color-primary-10);
212
+ color: var(--color-text-inverted);
213
+ }
214
+ }
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export { default as Checklist } from './checklist';
2
+ export { default as ChecklistItem } from './checklist-item';
3
+ export { default as Launchpad } from './launchpad';
4
+ export { setUpActionsForTasks } from './setup-actions';
5
+ export * from './types';