├── .eslintignore
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── renovate.json
└── workflows
│ ├── ci.yml
│ ├── release.yml
│ └── security.yml
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── config
├── webpack.config.base.js
├── webpack.config.core.js
└── webpack.config.lib.js
├── jest.config.js
├── package-lock.json
├── package.json
├── src
├── AbstractCoreComponent.test.tsx
├── AbstractCoreComponent.tsx
├── authoring
│ ├── button
│ │ └── v1
│ │ │ ├── ButtonV1.test.tsx
│ │ │ ├── ButtonV1.tsx
│ │ │ └── ButtonV1IsEmptyFn.ts
│ ├── download
│ │ └── v1
│ │ │ ├── DownloadV1.test.tsx
│ │ │ ├── DownloadV1.tsx
│ │ │ └── DownloadV1IsEmptyFn.ts
│ ├── image
│ │ └── v2
│ │ │ ├── ImageV2.test.tsx
│ │ │ ├── ImageV2.tsx
│ │ │ └── ImageV2IsEmptyFn.ts
│ ├── list
│ │ └── v2
│ │ │ ├── ListV2.test.tsx
│ │ │ ├── ListV2.tsx
│ │ │ ├── ListV2IsEmptyFn.ts
│ │ │ ├── ListV2TestMockItems.ts
│ │ │ ├── expected-list.html
│ │ │ └── expected-routed-list.html
│ ├── separator
│ │ └── v1
│ │ │ ├── SeparatorV1.test.tsx
│ │ │ ├── SeparatorV1.tsx
│ │ │ └── SeparatorV1IsEmptyFn.ts
│ ├── teaser
│ │ └── v1
│ │ │ ├── TeaserV1.test.tsx
│ │ │ ├── TeaserV1.tsx
│ │ │ └── TeaserV1IsEmptyFn.ts
│ ├── text
│ │ └── v2
│ │ │ ├── TextV2.test.tsx
│ │ │ ├── TextV2.tsx
│ │ │ └── TextV2IsEmptyFn.ts
│ └── title
│ │ └── v2
│ │ ├── TitleV2.test.tsx
│ │ ├── TitleV2.tsx
│ │ └── TitleV2IsEmptyFn.ts
├── common
│ └── placeholder.tsx
├── default
│ └── v1
│ │ ├── DefaultV1Component.test.tsx
│ │ ├── DefaultV1Component.tsx
│ │ └── DefaultV1ComponentIsEmptyFn.ts
├── index.test.ts
├── index.ts
├── isEmptyFunctions.ts
├── layout
│ ├── breadcrumb
│ │ └── v2
│ │ │ ├── BreadCrumbV2.test.tsx
│ │ │ ├── BreadCrumbV2.tsx
│ │ │ └── BreadCrumbV2IsEmptyFn.ts
│ ├── language-navigation
│ │ └── v1
│ │ │ ├── LanguageNavigationV1.test.tsx
│ │ │ ├── LanguageNavigationV1.tsx
│ │ │ ├── LanguageNavigationV1IsEmptyFn.ts
│ │ │ └── LanguageNavigationV1TestMockItems.ts
│ └── navigation
│ │ └── v1
│ │ ├── NavigationV1.test.tsx
│ │ ├── NavigationV1.tsx
│ │ ├── NavigationV1IsEmptyFn.ts
│ │ └── NavigationV1TestMockItems.ts
├── routing
│ ├── RoutedCoreComponent.tsx
│ ├── RoutedLink.test.tsx
│ └── RoutedLink.tsx
├── setupTests.ts
├── tsconfig.base.json
├── tsconfig.types.json
└── types.ts
└── tsconfig.json
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist/
2 | config/
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[bug]"
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **Package version**
14 | Provide a package version where the bug occurs.
15 |
16 | **To Reproduce**
17 | Steps to reproduce the behavior:
18 | 1. Go to '...'
19 | 2. Click on '....'
20 | 3. Scroll down to '....'
21 | 4. See error
22 |
23 | **Expected behavior**
24 | A clear and concise description of what you expected to happen.
25 |
26 | **Screenshots**
27 | If applicable, add screenshots to help explain your problem.
28 |
29 | **Additional context**
30 | Add any other context about the problem here.
31 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: "[feature] "
5 | labels: feature-request
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "timezone": "Europe/Zurich",
3 | "masterIssue": true,
4 | "packageRules": [
5 | {
6 | "groupName": "@adobe fixes",
7 | "updateTypes": ["patch", "pin", "digest", "minor"],
8 | "automerge": true,
9 | "packagePatterns": ["^@adobe/"],
10 | "schedule": ["at any time"]
11 | },
12 | {
13 | "groupName": "@adobe major",
14 | "updateTypes": ["major"],
15 | "packagePatterns": ["^@adobe/"],
16 | "automerge": false,
17 | "schedule": ["at any time"]
18 | },
19 | {
20 | "groupName": "external fixes",
21 | "updateTypes": ["patch", "pin", "digest", "minor"],
22 | "automerge": false,
23 | "schedule": ["after 1pm on Monday"],
24 | "packagePatterns": ["^.+"],
25 | "excludePackagePatterns": ["^@adobe/"]
26 | },
27 | {
28 | "groupName": "external major",
29 | "updateTypes": ["major"],
30 | "automerge": false,
31 | "packagePatterns": ["^.+"],
32 | "excludePackagePatterns": ["^@adobe/"],
33 | "schedule": ["after 1pm on Monday"]
34 | }
35 | ]
36 | }
37 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Continuous Integration
2 | on: pull_request_target
3 |
4 | jobs:
5 | test-react-base-components:
6 | name: test react-base-components
7 | runs-on: ubuntu-latest
8 | steps:
9 | - name: Checkout source code
10 | uses: actions/checkout@v2
11 | - name: Setup Node.js
12 | uses: actions/setup-node@v1
13 | with:
14 | node-version: '12'
15 | - name: Install dependencies
16 | run: npm ci
17 | - name: Build the project
18 | run: npm run build:production
19 | - name: Run tests and do code coverage check
20 | run: npm run test:coverage
21 | - name: Run code linter
22 | uses: hallee/eslint-action@1.0.3
23 | if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
24 | with:
25 | repo-token: ${{ secrets.GITHUB_TOKEN }}
26 | - name: Upload code coverage report to workflow as an artifact
27 | uses: actions/upload-artifact@v2
28 | with:
29 | name: base-coverage.zip
30 | path: coverage
31 | - name: Upload code coverage report to codecov.io and comment in pull request
32 | uses: codecov/codecov-action@v1
33 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 | on:
3 | push:
4 | branches:
5 | - master
6 | jobs:
7 | release:
8 | name: Release and publish module
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout source code
12 | uses: actions/checkout@v2
13 | with:
14 | fetch-depth: 0
15 | - name: Setup Node.js
16 | uses: actions/setup-node@v2
17 | with:
18 | node-version: 12
19 | - name: Install dependencies
20 | run: npm ci
21 | - name: Build the project
22 | run: npm run build:production
23 | - name: Run tests and do code coverage check
24 | run: npm run test:coverage
25 | - name: Release module and publish it in github.com and npmjs.com
26 | env:
27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28 | NPM_TOKEN: ${{ secrets.ADOBE_BOT_NPM_TOKEN }}
29 | run: npm run semantic-release
30 |
--------------------------------------------------------------------------------
/.github/workflows/security.yml:
--------------------------------------------------------------------------------
1 | name: Vulnerability check
2 | on:
3 | push:
4 | branches:
5 | - master
6 | pull_request_target:
7 |
8 | jobs:
9 | security:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Checkout source code
13 | uses: actions/checkout@master
14 | - name: Run Snyk to check for vulnerabilities
15 | uses: snyk/actions/node@master
16 | env:
17 | SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
18 | with:
19 | command: monitor --all-projects --exclude=examples,pom.xml
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | .idea
3 | .classpath
4 | .metadata
5 | .project
6 | .settings
7 | .externalToolBuilders
8 | maven-eclipse.xml
9 | *.swp
10 | *.iml
11 | *.ipr
12 | *.iws
13 | *.bak
14 | .vlt
15 | .DS_Store
16 | jcr.log
17 | atlassian-ide-plugin.xml
18 | .vlt-sync.log
19 | .vlt-sync-config.properties
20 | node
21 | node_modules
22 | lib
23 | dist
24 | coverage
25 |
26 | src/tsconfig.types.tsbuildinfo
27 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | config
2 | node
3 | node_modules
4 | .eslintignore
5 | .gitignore
6 | *.iml
7 | jest.config.js
8 | pom.xml
9 | tsconfig.json
10 | src
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AEM WCM Components - React Core implementation
2 |
3 | This module provides a React implementation for the [AEM core components](https://www.aemcomponents.dev/).
4 | This enables you to use the core components:
5 | -In the [AEM SPA editor](https://docs.adobe.com/content/help/en/experience-manager-64/developing/headless/spas/spa-overview.html) with React
6 | -In [React web components](https://www.npmjs.com/package/@adobe/react-webcomponent)
7 | -Or in any other React context, provided you have the input needed to instantiate the components.
8 |
9 | [Introduction Video and Demo](https://www.youtube.com/watch?v=9759AhM7fAc)
10 |
11 | Current supported / exported components:
12 |
13 | ### Page Authoring
14 | - Button (V1)
15 | - Download (V1)
16 | - Image (V2)
17 | - List (V2)
18 | - Separator (V1)
19 | - Teaser (V1)
20 | - Text (V2)
21 | - Title (V2)
22 |
23 | ### Layout
24 | - BreadCrumb (V2)
25 | - Language Navigation (V1)
26 | - Navigation (V1)
27 |
28 | ### Abstraction
29 | - AbstractCoreComponent
30 | - CoreComponentModel (interface)
31 |
32 | ### Containers
33 | For the containers (Accordion,Tabs,Carousel,Container) we do not provide any implementation in this project.
34 | It does not make sense to provide it for web-components as you can leverage the normal Core Components implementation such as a Tab Container, and drag your web components in there.
35 | Instead we provide them for the SPA editor only, introducing a dependency, and therefore we moved it into a [separate project](https://www.npmjs.com/package/@adobe/aem-core-components-react-spa).
36 |
37 |
38 | ## Usage
39 |
40 | You can choose to import the entire library at once OR import components individually.
41 | The latter is useful if you want to only enable a few components and you want to save your javascript footprint.
42 | Also, if you want to load all core components, but you want to lazyload them with react suspense, you will need to import them individually.
43 |
44 | ### Importing the whole library:
45 |
46 | ```
47 | import * as BaseCoreComponents from "@adobe/aem-core-components-react-base";
48 | const {ButtonV1, ButtonV1Model, ButtonV1IsEmptyFn} = BaseCoreComponents;
49 | ```
50 |
51 | ### Importing the button component individually:
52 |
53 | ```
54 | import ButtonV1, {ButtonV1Model, ButtonV1IsEmptyFn} from "@adobe/aem-core-components-react-base/dist/authoring/button/v1/ButtonV1";
55 | ```
56 |
57 | ### Using the imported code
58 |
59 | Now that you have the Button and ButtonV1IsEmptyFn imported, you can use them in your project.
60 | The properties of the Button 1 on 1 correspond to the Sling Model Exporter (.model.json) output.
61 |
62 | Note: There are some exceptions where some extra properties are added (mainly i18n labels) that are currently not present in the OOTB sling model exports.
63 | These can be added by the project itself with delegation. If they are not present, the default (English) values will be used.
64 |
65 | #### Button - Direct instantiation with TypeScript:
66 | ```
67 | const modelProps:ButtonV1Model = {
68 | text: 'Example Button',
69 | link: '/content/my/awesome/page.html',
70 | icon: 'iconCssCLass'
71 | };
72 |
73 | const html:JSX.Element = ();
74 | ```
75 |
76 |
77 | #### Button - Example with the spa editor:
78 |
79 | ```
80 | MapTo('my-project/wcm/components/button')(ButtonV1, {isEmpty: ButtonV1IsEmptyFn});
81 | ```
82 |
83 | For a complete project with examples, visit the [github page](https://github.com/adobe/aem-react-core-wcm-components/tree/master/examples).
--------------------------------------------------------------------------------
/config/webpack.config.base.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | const path = require('path');
17 |
18 | const isEnvironmentTest = process.env.NODE_ENV === 'test';
19 | const isEnvironmentProd = process.env.NODE_ENV === 'production';
20 | const nodeExternals = require('webpack-node-externals');
21 | const mode = (isEnvironmentProd) ? 'production' : 'development';
22 | const ManifestPlugin = require('webpack-manifest-plugin');
23 |
24 | module.exports = {
25 | entry: {},
26 | mode: mode,
27 | devtool: 'source-map',
28 | output: {
29 | globalObject: `typeof self !== 'undefined' ? self : this`,
30 | path: path.resolve(__dirname, '../dist'),
31 | filename: '[name].js',
32 | libraryTarget: 'umd'
33 | },
34 | module: {
35 | rules: [
36 | {
37 | test: /\.(js|mjs|jsx|ts|tsx)$/,
38 | use: ['source-map-loader'],
39 | enforce: 'pre',
40 | },
41 | {
42 | test: /\.ts$|\.tsx$/,
43 | exclude: /(node_modules|dist)/,
44 | use: 'ts-loader',
45 | enforce: 'post',
46 | }].concat(isEnvironmentTest ?
47 | {
48 | test: /\.ts$|\.tsx$/,
49 | include: path.resolve(__dirname, 'src'),
50 | use: {
51 | loader: 'istanbul-instrumenter-loader',
52 | options: {
53 | esModules: true,
54 | presets: ["env", "react", "stage-2"]
55 | }
56 | },
57 | enforce: 'post'
58 | } : [])
59 | },
60 | externals: [!isEnvironmentTest ? nodeExternals({
61 | modulesFromFile: {
62 | exclude: ['dependencies']
63 | }
64 | }) : ''],
65 | resolve: {
66 | extensions: ['.ts', '.tsx']
67 | },
68 | plugins: [
69 |
70 | new ManifestPlugin()
71 | ]
72 | };
73 |
--------------------------------------------------------------------------------
/config/webpack.config.core.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | const DllPlugin = require("webpack").DllPlugin;
18 | const config = require('./webpack.config.base');
19 | const path = require('path');
20 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
21 |
22 | config.output.library = 'AbstractCoreComponent';
23 |
24 | config.entry = {
25 | 'AbstractCoreComponent': ['./src/AbstractCoreComponent.tsx'],
26 | };
27 |
28 | config.plugins.push(new CleanWebpackPlugin());
29 | config.plugins.push(
30 | new DllPlugin({
31 | context: path.join(__dirname, '..'),
32 | name: "[name]",
33 | path: path.resolve(__dirname, `./../dist/manifest/[name].json`),
34 | })
35 | );
36 |
37 | module.exports = config;
--------------------------------------------------------------------------------
/config/webpack.config.lib.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | const config = require('./webpack.config.base');
18 |
19 | config.output.library = '@adobe/aem-core-components-react-base';
20 |
21 | config.entry = {
22 | 'index': ['./src/index.ts'],
23 | 'isEmptyFunctions': ['./src/isEmptyFunctions.ts'],
24 | 'authoring/list/v2/ListV2': ['./src/authoring/list/v2/ListV2'],
25 | 'authoring/button/v1/ButtonV1': ['./src/authoring/button/v1/ButtonV1'],
26 | 'authoring/text/v2/TextV2': ['./src/authoring/text/v2/TextV2'],
27 | 'authoring/title/v2/TitleV2': ['./src/authoring/title/v2/TitleV2'],
28 | 'authoring/image/v2/ImageV2': ['./src/authoring/image/v2/ImageV2'],
29 | 'authoring/teaser/v1/TeaserV1': ['./src/authoring/teaser/v1/TeaserV1'],
30 | 'authoring/download/v1/DownloadV1': ['./src/authoring/download/v1/DownloadV1'],
31 | 'authoring/separator/v1/SeparatorV1': ['./src/authoring/separator/v1/SeparatorV1'],
32 | 'layout/breadcrumb/v2/BreadCrumbV2': ['./src/layout/breadcrumb/v2/BreadCrumbV2'],
33 | 'layout/navigation/v1/NavigationV1': ['./src/layout/navigation/v1/NavigationV1'],
34 | 'layout/language-navigation/v1/LanguageNavigationV1': ['./src/layout/language-navigation/v1/LanguageNavigationV1']
35 | };
36 |
37 | module.exports = config;
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | 'use strict';
18 |
19 | module.exports = {
20 | preset: "ts-jest",
21 | setupFilesAfterEnv: ['/src/setupTests.ts'],
22 | testEnvironment: 'jsdom',
23 | transform: {
24 | "^.+\\.tsx?$": "ts-jest"
25 | },
26 | testMatch: ['/**/*.test.ts','/**/*.test.tsx'],
27 | testPathIgnorePatterns: ['node_modules','lib', 'dist', 'node'],
28 | collectCoverageFrom: [
29 | '**/*.{ts,tsx}'
30 | ],
31 | coveragePathIgnorePatterns: [
32 | "/node_modules/",
33 | "/lib/",
34 | "/dist/",
35 | "/node/"
36 | ],
37 | moduleFileExtensions: [
38 | "ts",
39 | "tsx",
40 | "js",
41 | "jsx",
42 | "json",
43 | "node"
44 | ],
45 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@adobe/aem-core-components-react-base",
3 | "version": "1.1.8",
4 | "license": "Apache-2.0",
5 | "keywords": [
6 | "adobe",
7 | "aem",
8 | "cq5",
9 | "react",
10 | "core",
11 | "components"
12 | ],
13 | "description": "AEM - React Implementation for the AEM Core Components",
14 | "author": {
15 | "name": "Adobe Systems Inc."
16 | },
17 | "main": "dist/index.js",
18 | "types": "dist/index.d.ts",
19 | "homepage": "https://github.com/adobe/aem-react-core-wcm-components-base/blob/master/README.md",
20 | "repository": {
21 | "type": "git",
22 | "url": "https://github.com/adobe/aem-react-core-wcm-components-base"
23 | },
24 | "scripts": {
25 | "clean": "shx rm -rf coverage/ dist/ src/tsconfig.types.tsbuildinfo",
26 | "linter": "eslint --ext .ts,.tsx .",
27 | "linter:fix": "eslint --ext .ts,.tsx . --fix",
28 | "test-clear": "jest --clearCache",
29 | "test": "jest",
30 | "test:coverage": "jest --coverage",
31 | "test:debug": "jest --coverage --watchAll",
32 | "build": "npm run clean && webpack --config config/webpack.config.core.js && webpack --config config/webpack.config.lib.js && tsc -p src/tsconfig.types.json",
33 | "build:production": "npm run clean && cross-env NODE_ENV=production webpack --config config/webpack.config.core.js --mode=production && webpack --config config/webpack.config.lib.js --mode=production && tsc -p src/tsconfig.types.json",
34 | "build:types": "npm run clean && tsc -p src/tsconfig.types.json",
35 | "docs": "jsdoc -c ./jsdoc_conf.json && doxdox \"src/**/*.+(js|jsx)\" --layout templates/DOCUMENTATION.hbs --output DOCUMENTATION.md",
36 | "readme": "node node_modules/markdown-include/bin/cli.js markdown-include.config.json",
37 | "docs-readme": "npm run docs && npm run readme",
38 | "semantic-release": "semantic-release"
39 | },
40 | "dependencies": {},
41 | "peerDependencies": {
42 | "react": "^16.14.0",
43 | "react-router-dom": "^5.2.0"
44 | },
45 | "devDependencies": {
46 | "shx": "^0.3.2",
47 | "@babel/cli": "^7.10.5",
48 | "@babel/core": "^7.11.4",
49 | "@babel/preset-env": "^7.11.0",
50 | "@babel/preset-react": "^7.10.4",
51 | "@testing-library/jest-dom": "^4.2.4",
52 | "@testing-library/react": "^9.5.0",
53 | "@testing-library/user-event": "^7.2.1",
54 | "@types/enzyme": "^3.10.5",
55 | "@types/enzyme-adapter-react-16": "^1.0.6",
56 | "@types/jest": "^26.0.14",
57 | "@types/node": "^12.20.10",
58 | "@types/react": "^16.14.5",
59 | "@types/react-dom": "^16.9.8",
60 | "@types/react-router-dom": "^5.1.5",
61 | "@typescript-eslint/eslint-plugin": "^3.9.0",
62 | "@typescript-eslint/parser": "^3.9.0",
63 | "babel-loader": "^8.1.0",
64 | "babel-plugin-istanbul": "^5.2.0",
65 | "source-map-loader": "^1.1.0",
66 | "chai": "^4.2.0",
67 | "clean-webpack-plugin": "^3.0.0",
68 | "cross-env": "^6.0.3",
69 | "doxdox": "^3.0.0",
70 | "enzyme": "^3.11.0",
71 | "enzyme-adapter-react-16": "^1.15.3",
72 | "eslint": "^6.8.0",
73 | "istanbul": "^0.4.5",
74 | "istanbul-instrumenter-loader": "^3.0.1",
75 | "jest": "^26.4.2",
76 | "jest-environment-jsdom-fourteen": "1.0.1",
77 | "jest-resolve": "26.6.2",
78 | "jest-watch-typeahead": "0.6.3",
79 | "jsdoc": "^3.6.5",
80 | "markdown-include": "^0.4.3",
81 | "prop-types": "^15.7.2",
82 | "react": "^16.14.0",
83 | "react-dom": "^16.14.0",
84 | "react-router-dom": "^5.2.0",
85 | "ts-jest": "26.5.6",
86 | "ts-loader": "^6.2.2",
87 | "typescript": "^4.0.2",
88 | "webpack": "^4.46.0",
89 | "webpack-cli": "^3.3.10",
90 | "webpack-manifest-plugin": "^2.2.0",
91 | "webpack-node-externals": "^1.7.2",
92 | "commitizen": "^4.2.3",
93 | "cz-conventional-changelog": "^3.3.0",
94 | "@semantic-release/changelog": "^5.0.1",
95 | "@semantic-release/git": "^9.0.0",
96 | "@semantic-release/github": "^7.2.0",
97 | "semantic-release": "^17.4.1"
98 | },
99 | "eslintConfig": {
100 | "extends": "plugin:@typescript-eslint/recommended",
101 | "parser": "@typescript-eslint/parser",
102 | "parserOptions": {
103 | "ecmaVersion": 2020,
104 | "sourceType": "module"
105 | },
106 | "rules": {
107 | "@typescript-eslint/no-empty-interface": 0
108 | }
109 | },
110 | "browserslist": {
111 | "production": [
112 | ">0.2%",
113 | "not dead",
114 | "not op_mini all"
115 | ],
116 | "development": [
117 | "last 1 chrome version",
118 | "last 1 firefox version",
119 | "last 1 safari version"
120 | ]
121 | },
122 | "config": {
123 | "commitizen": {
124 | "path": "./node_modules/cz-conventional-changelog"
125 | }
126 | },
127 | "release": {
128 | "plugins": [
129 | "@semantic-release/commit-analyzer",
130 | "@semantic-release/release-notes-generator",
131 | "@semantic-release/npm",
132 | [
133 | "@semantic-release/git",
134 | {
135 | "assets": [
136 | "package.json"
137 | ]
138 | }
139 | ]
140 | ]
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/src/AbstractCoreComponent.test.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import React, {Component} from 'react';
18 | import ReactDOM from 'react-dom';
19 | import {mount} from 'enzyme';
20 |
21 |
22 | import {CoreComponentModel,withStandardBaseCssClass, withConditionalPlaceHolder} from './AbstractCoreComponent';
23 |
24 | interface TestType extends CoreComponentModel{
25 | forceEmptyFlag:boolean
26 | }
27 |
28 | class ImplementingClass extends Component{
29 |
30 | render(): JSX.Element {
31 | return
My awesome component
;
32 | }
33 |
34 | }
35 |
36 | const WrappedClass = withConditionalPlaceHolder(withStandardBaseCssClass(ImplementingClass,"base-class"), (props) => props.forceEmptyFlag, "AwesomeComponent");
37 |
38 | it('Renders without crashing', () => {
39 | const div = document.createElement('div');
40 | ReactDOM.render(
41 | ,
42 | div
43 | );
44 | ReactDOM.unmountComponentAtNode(div);
45 | expect(1).toBe(1);
46 | });
47 |
48 | it('Should show our awesome text if the component is not empty', () => {
49 | const wrapper = mount();
50 | expect(wrapper.html()).toEqual("
My awesome component
");
51 | });
52 |
53 | it('Should not show anything if wcmmode is disabled and component is empty', () => {
54 | const wrapper = mount();
55 | expect(wrapper.html()).toBeNull();
56 | });
57 |
58 | it('Should show the proper placeholder with a custom text if wcmmode is edit and component is empty', () => {
59 |
60 | const WrappedOverride = withConditionalPlaceHolder(ImplementingClass, (props) => props.forceEmptyFlag, "AwesomeComponent", "Custom Configure Text");
61 |
62 | const wrapper = mount();
63 | expect(wrapper.html()).toEqual("
AwesomeComponent - Custom Configure Text
");
64 | });
65 |
66 | it('Should NOT show the proper placeholder if wcmmode is edit and component is empty, and hidePlaceHolder is set to true.', () => {
67 | const wrapper = mount();
68 | expect(wrapper.html()).toBeNull();
69 | });
70 |
71 | it('Should change the baseClass if we specify it with properties', () => {
72 | const wrapper = mount();
73 | expect(wrapper.html()).toEqual("
My awesome component
");
74 | });
--------------------------------------------------------------------------------
/src/AbstractCoreComponent.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import * as React from 'react';
18 | import {ComponentType} from 'react';
19 |
20 | import {EditorPlaceHolder} from "./common/placeholder";
21 |
22 | export interface HasBaseCssClass {
23 | baseCssClass?: string
24 | }
25 |
26 | export interface CoreComponentModel extends HasBaseCssClass{
27 | hidePlaceHolder?: boolean
28 | isInEditor?:boolean
29 | }
30 |
31 | export interface CoreComponentState {
32 |
33 | }
34 |
35 | export const withStandardBaseCssClass =
36 | (
37 | Component:ComponentType,
38 | defaultBaseCssClass:string
39 | ):React.ComponentType => {
40 | return (props:M) => {
41 |
42 | const baseCssClass = props.baseCssClass;
43 | const toBeUsedCssClass = baseCssClass && baseCssClass.trim().length > 0 ? baseCssClass : defaultBaseCssClass;
44 |
45 | const mergedProps: M= {
46 | ...props,
47 | baseCssClass: toBeUsedCssClass
48 | };
49 |
50 | return ;
51 | }
52 | };
53 |
54 | export const withConditionalPlaceHolder =
55 | (
56 | Component:ComponentType,
57 | isEmpty:(props:M) => boolean,
58 | componentTitle?:string, emptyText?:string
59 | ):React.ComponentType => {
60 | return (props:M) => {
61 |
62 | const isEmptyResult:boolean = isEmpty(props);
63 | const {hidePlaceHolder = false, isInEditor = false} = props;
64 |
65 | return (
66 | <>
67 | { !isEmptyResult &&
68 |
69 | }
70 | {
71 | (isEmptyResult && isInEditor && !hidePlaceHolder) &&
72 |
76 | }
77 | >
78 | );
79 | }
80 | };
--------------------------------------------------------------------------------
/src/authoring/button/v1/ButtonV1.test.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import React from 'react';
18 | import ReactDOM from 'react-dom';
19 | import {mount} from 'enzyme';
20 |
21 | import ButtonV1, {ButtonV1Model} from './ButtonV1';
22 | import {MemoryRouter} from 'react-router-dom';
23 |
24 |
25 | it('Renders without crashing', () => {
26 | const div = document.createElement('div');
27 | ReactDOM.render(
28 | ,
29 | div
30 | );
31 | ReactDOM.unmountComponentAtNode(div);
32 | expect(1).toBe(1);
33 | });
34 |
35 |
36 | it('Renders a proper button with link', () => {
37 |
38 | let captured = false;
39 |
40 | const properties:ButtonV1Model = {
41 | ariaLabel: "ThisIsAButton",
42 | icon: "iconCSSCls",
43 | link: "/content/some/link.html",
44 | text: "SomeText",
45 | routed:true,
46 | handleOnClick(event): void {
47 | captured = true;
48 | }
49 | };
50 |
51 | const wrapper = mount();
52 |
53 | const button = wrapper.find('a.cmp-button');
54 | expect(button).toHaveLength(1);
55 | button.simulate('click');
56 | expect(captured).toEqual(true);
57 |
58 | const anchor = button.find("a");
59 | expect(anchor).toHaveLength(1);
60 | expect(anchor.prop("aria-label")).toEqual("ThisIsAButton");
61 | expect(anchor.prop("href")).toEqual("/content/some/link.html");
62 |
63 | const iconSpan = anchor.find("span.cmp-button__icon.cmp-button__icon--iconCSSCls");
64 | expect(iconSpan).toHaveLength(1);
65 |
66 | const textSpan = anchor.find("span.cmp-button__text");
67 | expect(textSpan.text()).toEqual("SomeText");
68 | });
69 |
70 |
71 | it('Renders a proper button with link', () => {
72 |
73 | let captured = false;
74 |
75 | const properties:ButtonV1Model = {
76 | ariaLabel: "ThisIsAButton",
77 | icon: "iconCSSCls",
78 | text: "SomeText",
79 | handleOnClick(event): void {
80 | captured = true;
81 | }
82 | };
83 |
84 | const wrapper = mount();
85 |
86 | const button = wrapper.find('.cmp-button');
87 | expect(button).toHaveLength(1);
88 | button.simulate('click');
89 | expect(captured).toEqual(true);
90 |
91 | const anchor = button.find("a");
92 | expect(anchor).toHaveLength(0);
93 |
94 |
95 | const iconSpan = button.find("span.cmp-button__icon.cmp-button__icon--iconCSSCls");
96 | expect(iconSpan).toHaveLength(1);
97 |
98 | const textSpan = button.find("span.cmp-button__text");
99 | expect(textSpan.text()).toEqual("SomeText");
100 | });
--------------------------------------------------------------------------------
/src/authoring/button/v1/ButtonV1.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import React, {MouseEvent} from 'react';
18 | import {withConditionalPlaceHolder, withStandardBaseCssClass} from "../../../AbstractCoreComponent";
19 | import {RoutedCoreComponentModel} from "../../../routing/RoutedCoreComponent";
20 | import {RoutedLink} from "../../../routing/RoutedLink";
21 | import {ButtonV1IsEmptyFn} from "./ButtonV1IsEmptyFn";
22 |
23 |
24 | export interface ButtonV1Model extends RoutedCoreComponentModel{
25 | text?: string;
26 | link?: string;
27 | icon?: string;
28 | ariaLabel?: string;
29 | handleOnClick?(event: MouseEvent): void
30 | }
31 |
32 | export const ButtonV1Content = (props:ButtonV1Model) => {
33 | return (
34 | <>
35 | { props.icon && }
36 | {props.text}
37 | >
38 | );
39 | };
40 |
41 | const ButtonV1Impl = (props:ButtonV1Model) => {
42 |
43 | const handleOnClick = (event:MouseEvent) =>{
44 | if(props.handleOnClick){
45 | props.handleOnClick(event);
46 | }
47 | };
48 |
49 | const generateAttributes = (isLink: boolean) => {
50 | const computedAttrs: any = {
51 | className: props.baseCssClass,
52 | onClick: handleOnClick
53 | };
54 |
55 | if (isLink) {
56 | computedAttrs['aria-label'] = props.ariaLabel;
57 | computedAttrs['href'] = props.link;
58 | }
59 | return computedAttrs;
60 | };
61 |
62 | const isLink = (!!props.link);
63 | const attrs = generateAttributes(isLink);
64 |
65 | if(isLink){
66 | return
67 | }else{
68 | return
69 | }
70 | };
71 |
72 | const ButtonV1 = (props:ButtonV1Model) => {
73 | const Wrapped = withConditionalPlaceHolder(withStandardBaseCssClass(ButtonV1Impl,"cmp-button"), ButtonV1IsEmptyFn, "Button V1");
74 | return
75 | };
76 |
77 | export default ButtonV1;
--------------------------------------------------------------------------------
/src/authoring/button/v1/ButtonV1IsEmptyFn.ts:
--------------------------------------------------------------------------------
1 | import {ButtonV1Model} from "./ButtonV1";
2 |
3 | export function ButtonV1IsEmptyFn(props:ButtonV1Model): boolean{
4 | return props.text == null || props.text.length === 0;
5 | }
--------------------------------------------------------------------------------
/src/authoring/download/v1/DownloadV1.test.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import React from 'react';
18 | import ReactDOM from 'react-dom';
19 | import {mount} from 'enzyme';
20 |
21 |
22 | import DownloadV1, {DownloadV1Model} from "./DownloadV1";
23 |
24 |
25 | it('Renders without crashing', () => {
26 | const div = document.createElement('div');
27 | ReactDOM.render(
28 | ,
29 | div
30 | );
31 | ReactDOM.unmountComponentAtNode(div);
32 | expect(1).toBe(1);
33 | });
34 |
35 |
36 | it('Renders out properly', () => {
37 |
38 | let captured = false;
39 | const props:DownloadV1Model = {
40 | actionText: "Download now!!!",
41 | description: "
--------------------------------------------------------------------------------
/src/authoring/separator/v1/SeparatorV1.test.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import ReactDOM from "react-dom";
18 |
19 | import React from "react";
20 | import SeparatorV1 from "./SeparatorV1";
21 | import {mount} from "enzyme";
22 |
23 | it('Renders without crashing', () => {
24 | const div = document.createElement('div');
25 | ReactDOM.render(
26 | ,
27 | div
28 | );
29 | ReactDOM.unmountComponentAtNode(div);
30 | expect(1).toBe(1);
31 | });
32 |
33 | it('Renders as expected', ()=> {
34 | const element = mount();
35 |
36 | const html = "
";
37 | expect(element.html()).toEqual(html);
38 | })
39 |
--------------------------------------------------------------------------------
/src/authoring/separator/v1/SeparatorV1.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import React, {Component} from "react";
18 | import {CoreComponentModel, withConditionalPlaceHolder, withStandardBaseCssClass} from "../../../AbstractCoreComponent";
19 | import {SeparatorV1IsEmptyFn} from "./SeparatorV1IsEmptyFn";
20 |
21 | const SeparatorV1Impl = (props:CoreComponentModel) => {
22 |
23 | return (
24 |
25 |
26 |
27 | )
28 |
29 | };
30 |
31 | const SeparatorV1 = (props:CoreComponentModel) => {
32 | const Wrapped = withConditionalPlaceHolder(withStandardBaseCssClass(SeparatorV1Impl, "cmp-separator"), SeparatorV1IsEmptyFn, "Separator V1")
33 | return
34 | };
35 |
36 | export default SeparatorV1;
--------------------------------------------------------------------------------
/src/authoring/separator/v1/SeparatorV1IsEmptyFn.ts:
--------------------------------------------------------------------------------
1 | import {CoreComponentModel} from "../../../AbstractCoreComponent";
2 |
3 | export function SeparatorV1IsEmptyFn(props:CoreComponentModel): boolean{
4 | return false
5 | }
--------------------------------------------------------------------------------
/src/authoring/teaser/v1/TeaserV1.test.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import ReactDOM from "react-dom";
18 |
19 | import React from "react";
20 | import TeaserV1, {TeaserV1Model} from "./TeaserV1";
21 | import {mount} from "enzyme";
22 |
23 | const defaultProps:TeaserV1Model = {
24 | imageAlt: "snowy mountains",
25 | imagePath: "/some/image.png",
26 | description: '
63 | )
64 | };
65 |
66 | const TitleV2 = (props:TitleV2Model) => {
67 | const Wrapped = withConditionalPlaceHolder(withStandardBaseCssClass(TitleV2Impl, "cmp-title"), TitleV2IsEmptyFn, "TitleV2")
68 | return
69 | };
70 |
71 | export default TitleV2;
--------------------------------------------------------------------------------
/src/authoring/title/v2/TitleV2IsEmptyFn.ts:
--------------------------------------------------------------------------------
1 | import {TitleV2Model} from "./TitleV2";
2 |
3 | export function TitleV2IsEmptyFn(props:TitleV2Model): boolean{
4 | return props.text == null || props.text.trim().length === 0;
5 | }
--------------------------------------------------------------------------------
/src/common/placeholder.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import React, {Component} from 'react';
17 |
18 | export interface PlaceHolderModel {
19 | componentTitle?: string
20 | classAppend?: string
21 | emptyTextAppend?: string
22 | }
23 | const DEFAULT_EMPTY_TEXT_LABEL = 'Please configure the component';
24 |
25 | export const EditorPlaceHolder = (props:PlaceHolderModel) => {
26 |
27 | const part1: string = (props.componentTitle != null && props.componentTitle.length > 0) ? props.componentTitle + ' - ' : '';
28 | const part2: string = (props.emptyTextAppend != null) ? props.emptyTextAppend : DEFAULT_EMPTY_TEXT_LABEL;
29 | const emptyText = part1 + part2;
30 |
31 | return (
32 |
34 | {emptyText}
35 |
36 | )
37 | };
--------------------------------------------------------------------------------
/src/default/v1/DefaultV1Component.test.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import React from 'react';
18 | import ReactDOM from 'react-dom';
19 | import {mount} from 'enzyme';
20 |
21 | import DefaultV1Component, {DefaultV1Model} from "./DefaultV1Component";
22 | import {DefaultV1IsEmptyFn} from "./DefaultV1ComponentIsEmptyFn";
23 |
24 | it('Renders without crashing', () => {
25 | const div = document.createElement('div');
26 | ReactDOM.render(
27 | test"} />,
28 | div
29 | );
30 | ReactDOM.unmountComponentAtNode(div);
31 | expect(1).toBe(1);
32 | });
33 |
34 | it('Has a proper isEmpty function', () => {
35 |
36 | const props1:DefaultV1Model = {
37 | html:"