├── .babelrc
├── .github
└── ISSUE_TEMPLATE
│ ├── 1.Bug_report.md
│ └── 2.Feature_request.md
├── .gitignore
├── .npmignore
├── .travis.yml
├── LICENSE
├── README.md
├── _config.yml
├── docs
├── _config.yml
├── bundle.js
└── index.html
├── jest.config.js
├── lib
├── enums.js
├── index.js
└── utils.js
├── package-lock.json
├── package.json
├── src
├── docs
│ ├── Button.jsx
│ ├── CodeSnippet.jsx
│ ├── Dropdown.jsx
│ ├── Modal.jsx
│ ├── index.html
│ ├── index.jsx
│ └── styles.css
└── lib
│ ├── enums.js
│ ├── index.jsx
│ ├── utils.js
│ └── utils.test.js
├── webpack.config.js
├── yarn-error.log
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/env", "@babel/react"],
3 | "plugins": [
4 | "@babel/plugin-proposal-object-rest-spread",
5 | "@babel/plugin-proposal-class-properties"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/1.Bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a bug report for React Add to Calendar HOC
4 | ---
5 |
6 | # Bug report
7 |
8 | ## Describe the bug
9 |
10 | A clear and concise description of what the bug is.
11 |
12 | ## To Reproduce
13 |
14 | Steps to reproduce the behavior, please provide code snippets or a repository:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | ## Expected behavior
21 | A clear and concise description of what you expected to happen.
22 |
23 | ## Screenshots
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | ## System information
27 | - OS: [e.g. macOS, Windows]
28 | - Browser (if applies) [e.g. chrome, safari]
29 | - Version of Library: [e.g. 1.0.1]
30 |
31 | ## Additional context
32 |
33 | Add any other context about the problem here.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/2.Feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Create a feature request for React Add to Calendar HOC
4 | ---
5 |
6 | # Feature request
7 |
8 | ## Is your feature request related to a problem? Please describe.
9 | A clear and concise description of what you want and what your use case is.
10 |
11 | ## Describe the solution you'd like
12 | A clear and concise description of what you want to happen.
13 |
14 | ## Describe alternatives you've considered
15 | A clear and concise description of any alternative solutions or features you've considered.
16 |
17 | ## Additional context
18 | Add any other context or screenshots about the feature request here.
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | coverage
2 | node_modules
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | docs
2 | src
3 | .babelrc
4 | webpack.config.js
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 |
3 | language: node_js
4 | node_js:
5 | - 8
6 |
7 | before_install:
8 | - yarn add codecov.io coveralls
9 |
10 | after_success:
11 | - cat ./coverage/lcov.info | ./node_modules/codecov.io/bin/codecov.io.js
12 | - cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
13 |
14 | branches:
15 | only:
16 | - master
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Jason Leibowitz
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://badge.fury.io/js/react-add-to-calendar-hoc)
2 | [](https://travis-ci.org/jasonleibowitz/react-add-to-calendar-hoc)
3 | [](https://coveralls.io/github/jasonleibowitz/react-add-to-calendar-hoc)
4 |
5 | # React Add to Calendar HOC
6 |
7 | ## What is This?
8 |
9 | React Add to Calendar HOC is a very lightweight and flexible higher order component that allows you to add _add to calendar_ functionality to your own components. Use your own button component and either dropdown component or modal component.
10 |
11 | ## Why Should I Use This?
12 |
13 | If you want to add "add to calendar" functionality to your application, this is the lightest-weight and most flexibly library that does this. Other libraries that provide this functionality are over 21x the bundle size and don't give you the flexibility of using your own components. There are also no external dependencies to worry about.
14 |
15 | In your project you most likely already have reusable button components to other styles. Rather than dictating what your Add to Calendar component looks like, you provide your own components for this library to add functionality to. You can style your components with CSS in JS, CSS Modules or anything else. This library doesn't care what you use or dictate changes to how you do things.
16 |
17 | It also doesn't have a bundled date library with it either, giving you the flexibility to use whatever library you want. MomentJS is the most popular, but it's incredibly large. You're in charge of formatting the dateTime string and providing it to this lib. It doesn't care what date lib you use.
18 |
19 | ## Examples
20 |
21 | View examples [here](http://leibowitz.me/react-add-to-calendar-hoc/docs/).
22 |
23 | ## Installation
24 |
25 | Using [npm](https://www.npmjs.com/package/react-add-to-calendar-hoc)
26 |
27 | ```
28 | npm install react-add-to-calendar-hoc --save
29 | yarn add react-add-to-calendar-hoc
30 | ```
31 |
32 | Then, using a module bundler that supports either CommonJS or ES2015 modules, such as [webpack](https://github.com/webpack/webpack):
33 |
34 | ```
35 | // Using an ES6 transpiler like Babel
36 | import AddToCalendarHOC from 'react-add-to-calendar-hoc';
37 |
38 | // Not using an ES6 transpiler
39 | var AddToCalendarHOC = require('react-add-to-calendar-hoc');
40 | ```
41 |
42 | #### Props
43 |
44 | The component takes the following props
45 |
46 | | Prop | Type | Required | Default | Description |
47 | | ------------- | -------------- | -------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
48 | | buttonProps | object | | `{}` | Spread props to the button component you pass in to the HOC |
49 | | buttonText | string | | `Add to Calendar` | Text to render in the button |
50 | | className | string | | `null` | className to use on AddToCalendar container |
51 | | dropdownProps | object | | `{}` | Spread props to the dropdown or modal component you pass in to the HOC |
52 | | event | object | Yes | | Event object we use to create calendar links |
53 | | items | array of enums | | `[GOOGLE, ICAL, OUTLOOK, YAHOO]` | By default AddToCalendar renders all of these calendar links. To render a subset of these or to list them in a different order, provide a list of items using the enum SHARE_SITES, which is a named import from the library |
54 | | linkProps | object | | `{}` | Spread props to the link components we render for each calendar item |
55 |
56 | #### Event Object Shape
57 |
58 | All of these properties are required.
59 |
60 | | Prop | Type | Description |
61 | | ------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
62 | | description | string | Description of event. Put in the notes or body section of event. |
63 | | duration | string or number | Duration of event in hours. If string, must be four digits, e.g. `'0200'` or `'0130'`. If number, must represent hours in decimal form, i.e. `2` or `2.15`. This is only used for Yahoo. |
64 | | endDatetime | string | End date time of event. Must be formatted in `YYYYMMDDTHHmmssZ` format or `YYYYMMDDTHHmmss` if timezone is also provided. Use any date lib you want, but the format must match this. |
65 | | location | string | Location of event. Use an address for best specificity and for Google Maps to populate a Map. Sometimes a location name will also populate a map. |
66 | | startDatetime | string | Start date time of event. Must be formatted in `YYYYMMDDTHHmmssZ` format or `YYYYMMDDTHHmmss` if timezone is also provided. Use any date lib you want, but the format must match this. |
67 | | timezone | string | Valid TZ env variable. See list of [valid options here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). |
68 | | title | string | Name of your event. |
69 |
70 | #### Helper functions
71 |
72 | | Function | Arguments | Description |
73 | | -------------- | --------- | -------------------------------------------------------------------------------------------------------------------------- |
74 | | onRequestClose | event | Handles closing of the modal or dropdown. Can be applied to the Button in the provided Overlay to return to previous view. |
75 |
76 | ## Dependencies
77 |
78 | React Add to Calendar HOC has _zero_ external dependencies.
79 |
80 | ## Edge Cases
81 |
82 | Because this library aims to be extremely unopinionated and lightweight it doesn't handle most edge cases, instead letting you handle them as you'd like. Here are some common edge cases and recommendations for what to do.
83 |
84 | #### Open in Outlook doesn't work on iOS
85 |
86 | The option to download an ICS file to open in Outlook won't work on iOS because iOS devices don't let you choose which app to open certain files in. iOS devices will always open any ics in the default calendar overlay.
87 |
88 | You can handle this case by checking if the user's device is iOS and then customizing the list of items. There's an example in the docs to handle this exact edge case. Look for the section "Handle iPhone Options".
89 |
90 | #### How do I specify an event in a specific timezone
91 |
92 | Instead of passing `startDatetime` and `endDatetime` as UTC values pass in local time formats, i.e. `YYYYMMDDTHHmmss` and also provide a valid `timezone` property. (For a list of valid properties [see the TZ column here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)).
93 |
94 | Doing this will ensure that regardless of the user's local timezone the event created will always be in the correct time for the timezone you specified. It will also include a timezone property in the created event so the user knows what timezone the event is in.
95 |
96 | ## Reporting Issues
97 |
98 | If you believe you've found an issue, please [report it](https://github.com/jasonleibowitz/react-add-to-calendar-hoc/issues) along with any relevant details to reproduce it.
99 |
100 | ## Contributions
101 |
102 | Coming Soon
103 |
104 | ## Compatibility
105 |
106 |
107 |
108 | This component is expected to work on modern browsers, but if it breaks on a particular browser please [file an issue](https://github.com/jasonleibowitz/react-add-to-calendar-hoc/issues/new?template=1.Bug_report.md). We can check the problem using [browserstack](http://browserstack.com) - a great service for cross-browser testing. They also support open source projects like this one.
109 |
110 | ## License
111 |
112 | MIT
113 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-minimal
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
151 | Going to have a lot of fun doing things that we scheduled ahead of time.'
159 | }}
160 | />
161 |
162 | {`
163 | const AddToCalendarDropdown = AddToCalendarHOC(Button, Dropdown);
164 | ...
165 |
172 | `}
173 |
174 |
175 |
iPhones don't allow users to select which app they want to open ics files with, so there is no reason to offer both iCal and Outlook options for users on iOS devices. This example shows how to conditionally change which items to display based on the user's device.
To support events in a specific timezone you have to do a couple of things. First, pass in an additional property, timezone. The value of this should be a valid TZ environment variable (See here for a list).
297 |
You should also pass the value of startDatetime and endDatetime as local values and not UTC. In other words, if you want to create an event at 11am EST you should pass in a time value of 11am, not 7am UTC (EST has -04:00 offset). You can do this by formatting the date as YYYYMMDDTHHmmss - without the Z property.
298 |
Doing this will result in two things -- regardless of the timezone of your users, the event will always be created at the correct time for the timezone set. Secondly, the event will now include timezone information, i.e. it will say Eastern Time.
Moment is known to be a MASSIVE library. v2.22.2 is 64.2kb minified + gzipped and moment-timezone v0.5.21 is 89.8kb minified + gzipped. There are plenty of other date time libraries for JS that are way smaller. Using one of these helps you avoid overly bloating your application and sending too many vendor files to the client. One great option is Luxon. Luxon v.1.4.4 is 16.9kb minified + gzipped.
329 |
This example shows how to use the Luxon library (instead of Moment) to construct startDatetime and endDatetime
330 |
337 |
338 | {`
339 | const AddToCalendarModal = AddToCalendarHOC(Button, CalendarModal);
340 | const startTime = DateTime.fromObject({ year: 2018, month: 10, day: 25, hour: 12 });
341 | const endTime = startTime.plus({ hours: 2 });
342 | const duration = endDatetime.diff(startDatetime).as('hours');
343 | const eventInDifferentTimezone = {
344 | ...event,
345 | description: 'Description of event. Going to have a lot of fun doing things that we scheduled ahead of time.',
346 | duration,
347 | endDatetime: endTime.toFormat('YYYYMMDDTHHmmss'),
348 | location: 'London',
349 | startDatetime: startTime.toFormat('YYYYMMDDTHHmmss'),
350 | timezone: 'Europe/London',
351 | title: 'Super Fun Event',
352 | }
353 | ...
354 |
361 | `}
362 |
363 |