Skip to content
This repository was archived by the owner on Nov 4, 2022. It is now read-only.

Commit 77929cb

Browse files
committed
feat: initial commit
1 parent 2d1594c commit 77929cb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+9423
-681
lines changed

.github/workflows/gh-pages.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
- name: Build
2828
run: npm run-script build
2929
env:
30-
PUBLIC_URL: 'https://js-widgets.github.io/example-widget'
30+
PUBLIC_URL: 'https://js-widgets.github.io/example-emojis'
3131
- name: Deploy to GitHub Pages
3232
if: ${{ success() }}
3333
uses: crazy-max/ghaction-github-pages@v2

README.md

Lines changed: 3 additions & 269 deletions
Original file line numberDiff line numberDiff line change
@@ -1,275 +1,9 @@
1-
# Example Widget [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
1+
# Example Emojis [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
22

3-
This example contains documentation and example code for creating widgets using React.
3+
This an example application with emojis!
44

5-
[View the demo](https://js-widgets.github.io/example-widget/index.html)
6-
7-
## Requirements
8-
9-
- [npm](https://www.npmjs.com/) 6.9.0 or higher
10-
- [create-react-app](https://www.npmjs.com/package/create-react-app) 3.0.1 or higher
11-
12-
## Getting started
13-
14-
1. On the [example-widget](https://github.com/js-widgets/example-widget) project page click the **"Use this template"** button to setup a new widget.
15-
2. Give the new repository a **name** and a **description** and then click the "**Create repository from template**" button.
16-
3. Clone the new repository and change the project [**name**](https://github.com/js-widgets/example-widget/blob/master/package.json#L2), [**version**](https://github.com/js-widgets/example-widget/blob/master/package.json#L3), and [**homepage**](https://github.com/js-widgets/example-widget/blob/master/package.json#L4) inside **package.json**.
17-
4. Change the name of the [widget render function](https://github.com/js-widgets/example-widget/blob/master/src/index.js#L35)(`renderExampleWidget`) in **src/index.js**. _Note: It is recommended to use something unique to the widget in order to avoid potential conflicts with other widgets, like the widget repository name._
18-
5. Change the [**renderFunctionName**](https://github.com/js-widgets/example-widget/blob/master/src/public/index.html#L20) in the header of **public/index.html** to match the designated widget render function from the previous step (i.e. `renderExampleWidget`)
19-
6. Install the project dependencies using `npm install`
20-
7. Run the project locally using `npm start`
21-
22-
**IMPORTANT:** Make sure you check the [widget development documentation](/widget-development.md) when developing your own.
23-
24-
## `widget.json`
25-
26-
There is a special file called `widget.json` in the root of the widget. Widget registries, [like this
27-
example](https://github.com/js-widgets/widget-registry-boilerplate), need this file to learn about
28-
this widget. It contains the following keys:
29-
30-
| Name | Required | Example | Description |
31-
| ------------------------ | -------- | -------------------------------------- | ---------------------------------------------------------------------------------------------- |
32-
| shortcode | yes | product-catalog | The machine name identifier for the widget. |
33-
| description | no | A catalog of products for our company. | A longer description for the widget. This is shown in the widget catalog. |
34-
| availableTranslations | yes | `['en', 'es']` | Language codes this widget is available in for internationalization purposes. |
35-
| settingsSchema | no | | A JSON Schema object decribing the input parameters for the widgets at embed time. |
36-
| externalPeerDependencies | no | | List of runtime dependencies for this widget that embedders need to add along with the widget. |
37-
| status | yes | stable | One of `stable`, `beta`, `wip`, or `deprecated`. |
38-
39-
### Configurable widgets
40-
Configuration parameters are specified during the embed process. Drupal will create a form element
41-
automatically to gather those parameters in the editorial screens. For the CMS to know what form
42-
element to use, the widget definition needs to include a [JSON Schema](https://json-schema.org)
43-
definition for every parameter.
44-
45-
This repository contains an example of a configurable parameter. In this case it's the text of the
46-
button. This is [described in `widget.json`](https://github.com/js-widgets/example-widget/blob/master/widget.json#L20-L36) as:
47-
48-
```json
49-
"settingsSchema": {
50-
"type": "object",
51-
"additionalProperties": false,
52-
"properties": {
53-
"fields": {
54-
"type": "object",
55-
"properties": {
56-
"button-text": {
57-
"type": "string",
58-
"title": "Button text",
59-
"description": "Some random string to be displayed when the widget is rendered.",
60-
"examples": ["I am a button", "Please, click me", "CLICK"]
61-
}
62-
}
63-
}
64-
}
65-
},
66-
```
67-
68-
And then accessed in the [widget code `Widget.jsx`](https://github.com/js-widgets/example-widget/blob/master/src/components/Widget.jsx#L25):
69-
70-
```jsx
71-
<p className="is-size-6 pb-4">
72-
<button className="button is-primary">{element.getAttribute('data-button-text')}</button>
73-
</p>
74-
```
75-
76-
Note that since the field name is `button-text`, the value is accessed as `'data-button-text'`.
77-
78-
### External dependencies
79-
80-
`externalPeerDependencies` is a tool designed to share JS dependencies across different widgets.
81-
This module provides an example how to avoid bundling `react`, `react-dom`, and `react-intl` with
82-
the widget's JS, while making Drupal (or any other available integrations) load the dependencies
83-
automatically.
84-
85-
For each dependency you will need to:
86-
87-
1. [Tell Webpack to not include the library](https://github.com/js-widgets/example-widget/blob/master/craco.config.js#L32-L35) in the resulting JS file(s) for this widget.
88-
```js
89-
// webpack.config.js or craco.config.js
90-
externals: {
91-
react: 'React',
92-
'react-dom': 'ReactDOM',
93-
'react-intl': 'ReactIntl',
94-
},
95-
// ...
96-
```
97-
1. [Tell the widget registry (in `widget.json`)](https://github.com/js-widgets/example-widget/blob/master/widget.json#L37-L46), and ultimately the CMS integrations where to find these libraries that were excluded.
98-
```json
99-
"externalPeerDependencies": {
100-
"react": {"src": "https://unpkg.com/react@^17/umd/react.production.min.js"},
101-
"react-dom": {"src": "https://unpkg.com/react-dom@^17/umd/react-dom.production.min.js"},
102-
"react-intl": {"src": "https://unpkg.com/react-intl-bundle@^1/dist/react-intl.production.min.js"}
103-
},
104-
```
105-
106-
### Continuous Integration
107-
108-
Testing and deployment scripts available inside this example repository using [GitHub Actions](https://github.com/features/actions).
109-
110-
## Usage
111-
112-
_Note: Changes made to the **src/public/index.html** file are for development and preview purposes only and will not be compiled into the production version of the widget._
113-
114-
Widgets are referenced in the header of the page and rendered using an orchestrator script. The `document.loadWidget` and `document.loadWidgets` functions allow rendering of multiple widgets, and multiple instances of a single widget.
115-
116-
### loader.js
117-
118-
Within the `<head>` tag reference the widget load callback(renderFunctionName) and tell it which div(instanceId) to render the widget in.
119-
120-
Projects embedding widgets should include the [loader script](https://js-widgets.github.io/widget-registry-boilerplate/widget-registry/production/loader.js) maintained in the Widget Registry. Include the script in the HTML as:
121-
122-
```html
123-
<script
124-
src="//js-widgets.github.io/widget-registry-boilerplate/widget-registry/production/loader.js"
125-
type="application/javascript"
126-
></script>
127-
```
128-
129-
- [See an example](https://github.com/js-widgets/example-widget/blob/master/src/public/index.html#L12) of the loader script implementation.
130-
131-
Remember to use your version of the widget registry instead of `widget-registry-boilerplate`.
132-
133-
#### `document.loadWidget()`
134-
135-
```js
136-
document.loadWidget({
137-
renderFunctionName: 'renderExampleWidget',
138-
instanceId: 'example-widget-1',
139-
language: 'de',
140-
onRenderFinish: (renderedElement) => {
141-
alert('Render process finished.');
142-
},
143-
});
144-
```
145-
146-
- [See an example](https://github.com/js-widgets/example-widget/blob/master/src/public/index.html#L14) of the `loadWidget()` function.
147-
148-
Within the `<body>` tag add the instanceId div wherever you want this widget to render.
149-
150-
```html
151-
<div id="example-widget-1" data-button-text="foobar"></div>
152-
```
153-
154-
- [See an example](https://github.com/js-widgets/example-widget/blob/master/src/public/index.html#L79) of the widget placement implementation.
155-
156-
#### `document.loadWidgets()`
157-
158-
```js
159-
document.loadWidgets({
160-
'widget-1': {
161-
renderFunctionName: 'renderExampleWidget',
162-
instanceId: 'example-widget-1',
163-
},
164-
'widget-2': {
165-
renderFunctionName: 'renderExampleWidget',
166-
instanceId: 'example-widget-2',
167-
},
168-
});
169-
```
170-
171-
```html
172-
<div id="example-widget-1" data-button-text="foo"></div>
173-
<div id="example-widget-2" data-button-text="bar"></div>
174-
```
175-
176-
#### Parameters
177-
178-
| Name | Required | Default | Example | Description |
179-
| ------------------ | -------- | ------------------------ | ----------------------- | ------------------------------------------------------------------------- |
180-
| renderFunctionName | yes | | `renderExampleWidget` | The render function callback. |
181-
| instanceId | yes | | `example-widget-1` | The already present HTML element ID where the react app will be rendered. |
182-
| language | no | en | de | The language code for internationalization purposes. |
183-
| origin | no | `window.location.origin` | https://www.example.org | Protocol and hostname where a JSONAPI endpoint is available. |
184-
| onRenderFinish | no | | | A callback that executes after the widget has been rendered. |
185-
186-
### Attributes
187-
188-
Data attributes of the instanceId div are accessible from the `<App />` React component using the `getAttribute()` method.
189-
190-
```jsx
191-
import React, { Component } from 'react';
192-
193-
class Widget extends Component {
194-
render() {
195-
return <div className="App">{this.props.obj.getAttribute('data-button-text')}</div>;
196-
}
197-
}
198-
199-
export default Widget;
200-
```
201-
202-
- [See an example](https://github.com/js-widgets/example-widget/blob/master/src/components/Widget.js#L25) of the `getAttribute()` method.
203-
204-
#### DIV attributes
205-
206-
```html
207-
<div id="example-widget-1" data-button-text="Hello world!"></div>
208-
```
209-
210-
- [See an example](https://github.com/js-widgets/example-widget/blob/master/src/public/index.html#L79) of the widget attribute implementation.
211-
212-
#### Query string values
213-
214-
```
215-
http://localhost:3000/?data-button-text=Hello%20world!
216-
```
217-
218-
Note: DIV attributes are the preferred method and will always take precedence over the use of query
219-
string values. Query string values are a good way to test a widget quickly without having to alter
220-
the HTML source code.
221-
222-
### Translations
223-
224-
The boilerplate widget has built-in translation support using the **react-intl** module. Use the `FormattedMessage` to create translatable strings within the widget.
225-
226-
```jsx
227-
<FormattedMessage id="App.welcomeMsg" defaultMessage="Welcome!" />
228-
```
229-
230-
- [See an example](https://github.com/js-widgets/example-widget/blob/master/src/components/Widget.js#L15) of the `FormattedMessage` component.
231-
232-
Create all translation messages in `src/messages.js`, following the provided example. Generate locales using the `npm run build:locales` command. This will scan `src/messages.js` for translatable strings and compile them into JSON files for translation under **src/locales/\*.json**.
233-
234-
#### Supported Languages
235-
236-
| Language | Code |
237-
| ---------------------- | ----- |
238-
| Arabic | ar |
239-
| German | de |
240-
| English | en |
241-
| Spanish | es |
242-
| Latin American Spanish | esla |
243-
| French | fr |
244-
| Italian | it |
245-
| Japanese | ja |
246-
| Korean | ko |
247-
| Polish | pl |
248-
| Portuguese | pt |
249-
| Russian | ru |
250-
| Turkish | tr |
251-
| Simplified Chinese | zh-cn |
252-
| Traditional Chinese | zh-tw |
253-
254-
### Typescript
255-
256-
In an effort to improve overall code quality and reduce run-time exceptions, we strongly encourage widget developers to use [Typescript](typescriptlang.org). We understand, though, that using Typescript can be challenging if you don't have prior experience with it and we don't want to impose that restriction upon you.
257-
258-
If you feel comfortable with Typescript or are willing to learn about it ([here](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html) and [here](https://fettblog.eu/typescript-react/) are good resources), you can run `npm run use-typescript`, which will install all the libraries you'll need, update file extensions, and make appropriate configuration changes.
259-
260-
### Styling
261-
262-
In order to scope widget styles to the widget without adversely affecting the styles of the page within which it's embedded, we're using a library called [craco](https://github.com/gsoft-inc/craco). This library allows us to override configuration in apps bootstrapped with Create React App, which is otherwise a closed system. By using this method, we can make alterations to confuration without needing to eject the app. This along with a PostCSS plugin called [postcss-wrap](https://github.com/ruslansavenok/postcss-wrap) allows us to define a CSS class that will be prepended to all CSS selectors, effectively namespacing all styles.
263-
264-
_Uncomment the style rule specified in `index.css` and start the app to see the prepended class from `postcss.config.js` added._ **Remember to define your custom namespace class in `postcss.config.js` and add it to the top-most element in the app, as seen in `Widget.jsx`. If you need to use this method, please remove the `index.css` file and where it's imported in `index.js`.**
265-
266-
It is recommended to rely on the above method strictly for usage of installable component libraries. For custom styling, we recommend installing [Emotion](https://emotion.sh/), which is a library for writing CSS-in-JS.
267-
268-
### Testing
269-
270-
This boilerplate is setup to use [Jest](https://jestjs.io/) and [@testing-library/react](https://testing-library.com/docs/react-testing-library/intro) for testing. See `Widget.test.js` for an example of how to use these libraries.
5+
[View the demo](https://js-widgets.github.io/example-emojis/index.html)
2716

2727
## Current Maintainer(s)
2738

2749
- Mateu Aguiló Bosch ([e0ipso](https://github.com/e0ipso))
275-
- Hunter MacDermut ([huntermacd](https://github.com/huntermacd))

craco.config.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ module.exports = {
3232
externals: {
3333
react: 'React',
3434
'react-dom': 'ReactDOM',
35-
'react-intl': 'ReactIntl',
3635
},
3736
},
3837
},

lint-staged.config.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
module.exports = {
2-
'src/*.{js,jsx,ts,tsx}': ['eslint'],
32
'src/**/*.{js,jsx,ts,tsx,json,md}': ['prettier --write'],
43
};

package-lock.json

Lines changed: 34 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)