Full Code of tcampb/react-calendly for AI

master b88c1db792d0 cached
19 files
36.8 KB
10.6k tokens
43 symbols
1 requests
Download .txt
Repository: tcampb/react-calendly
Branch: master
Commit: b88c1db792d0
Files: 19
Total size: 36.8 KB

Directory structure:
gitextract_z_zg3mar/

├── .editorconfig
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package.json
├── rollup.config.js
├── src/
│   ├── calendly-widget.css
│   ├── calendly.tsx
│   ├── components/
│   │   ├── InlineWidget/
│   │   │   └── InlineWidget.tsx
│   │   ├── LoadingSpinner/
│   │   │   └── LoadingSpinner.tsx
│   │   ├── PopupButton/
│   │   │   └── PopupButton.tsx
│   │   ├── PopupModal/
│   │   │   ├── Modal.tsx
│   │   │   └── ModalContent.tsx
│   │   ├── PopupWidget/
│   │   │   └── PopupWidget.tsx
│   │   └── hooks/
│   │       └── useCalendlyEventListener.ts
│   ├── helpers/
│   │   └── propHelpers.ts
│   └── index.tsx
└── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true


================================================
FILE: .gitignore
================================================

# See https://help.github.com/ignore-files/ for more about ignoring files.

# dependencies
node_modules

# builds
build
.rpt2_cache
dist

# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
typings
example

.idea
.vscode

================================================
FILE: CHANGELOG.md
================================================
# Changelog

## 4.4.0

- Added `className` option to `InlineWidget` component.
- Removed SMS prefill option since it is no longer supported by Calendly.

https://github.com/tcampb/react-calendly/issues/194
https://github.com/tcampb/react-calendly/issues/186


## 4.3.1

- Added `onPageHeightResize` option to `useCalendlyEventListener` hook. This function is called when the Calendly scheduling page's height changes. The event payload includes the new height in pixels.

https://github.com/tcampb/react-calendly/issues/174
https://github.com/tcampb/react-calendly/issues/137
https://github.com/tcampb/react-calendly/issues/133
https://github.com/tcampb/react-calendly/issues/15
https://github.com/tcampb/react-calendly/issues/145

## 4.3.0

- Added `smsReminderNumber` prefill option (https://github.com/tcampb/react-calendly/pull/171).

## 4.2.1

- Removes unused sourcemaps (https://github.com/tcampb/react-calendly/issues/169).

## 4.2.0
- All components now include an optional `LoadingSpinner` prop. This prop is a React component that will be rendered while the Calendly iframe is loading; the default Calendly loading spinner will be displayed if this property is not provided.

## 4.1.1
- `PopupWidget`, `PopupModal`, and `PopupButton` components will throw an error when opened without a `rootElement` prop (https://github.com/tcampb/react-calendly/issues/143).

## 4.1.0

- Added `salesforce_uuid` prefill option (https://github.com/tcampb/react-calendly/pull/128).

## 4.0.1

- Fixed issue that caused the `email` and `guests` prefill options to not be properly encoded (https://github.com/tcampb/react-calendly/issues/116).

## 4.0.0

- Replaced `CalendlyEventListener` component with `useCalendlyEventListener` hook (https://github.com/tcampb/react-calendly/issues/45).
- Updated `react` & `react-dom` peer dependency versions; `react-calendly@4.0.0` now requires react and react-dom version >=16.8.

## 3.0.3

- Supports new React 18 types (https://github.com/tcampb/react-calendly/pull/111).
- Allows closing modal with an overlay click (https://github.com/tcampb/react-calendly/pull/110).

## 3.0.2

- Adds React v18 support (https://github.com/tcampb/react-calendly/issues/106).

## 3.0.1

- Fixes uri encoding bug (https://github.com/tcampb/react-calendly/pull/102).

## 3.0.0

- Removes Calendly widget script dependency (https://assets.calendly.com/assets/external/widget.js).
- Removes `openPopupWidget` and `closePopupWidget` functions (replaced by `PopupModal` component).
- Adds `PopupModal` component.

## 2.2.3

- [#96] Added title attribute to the Calendly scheduling page iframe.

## 2.2.2

- [#88] Fixed bug that caused the loading spinner to remain on the page even after the Calendly widget had finished loading.


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 Tyler Campbell

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# react-calendly
[Calendly integration](https://help.calendly.com/hc/en-us/articles/223147027-Embed-options-overview) for React apps

[![NPM](https://img.shields.io/npm/v/react-calendly.svg)](https://www.npmjs.com/package/react-calendly) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) [![](https://raw.githubusercontent.com/storybooks/brand/master/badge/badge-storybook.svg)](https://tcampb.github.io/react-calendly)

---

<p>
  <strong>Are you looking to fully customize your React booking page?</strong><br/>
  <span>Ship a React booking page you control - with https://components.calforce.pro and <a href="https://github.com/tcampb/react-calendly-scheduler">react-calendly-scheduler</a></span>
</p>

---

<img width="1402" alt="react-calendly" src="https://user-images.githubusercontent.com/33756113/128376592-3cef4ef7-5c8b-4a07-a360-d83da17fff1d.png">

## Installation

Depending on the package manager you are using for your project, use `npm install` or `yarn add` to include react-calendly in your react app.

```bash
npm install --save react-calendly
```

```bash
yarn add react-calendly
```

## Documentation

- [Basic Usage](#basic-usage)
- [Advanced Usage](#advanced-usage)
- [Frequently Asked Questions](#faq)

### Basic Usage

Ensure that React has been included into your page or component. Then, you can import any of the following components from the "react-calendly" package:

- [InlineWidget](#inlinewidget)
- [PopupWidget](#popupwidget)
- [PopupButton](#popupbutton)
- [useCalendlyEventListener](#usecalendlyeventlistener)

#### InlineWidget

```jsx
import React from "react";
import { InlineWidget } from "react-calendly";

const App = () => {
  return (
    <div className="App">
      <InlineWidget url="https://calendly.com/your_scheduling_page" />
    </div>
  );
};

export default App;
```

#### PopupWidget

```jsx
import React from "react";
import { PopupWidget } from "react-calendly";

const App = () => {
  return (
    <div className="App">
      <PopupWidget
        url="https://calendly.com/your_scheduling_page"
        /*
         * react-calendly uses React's Portal feature (https://reactjs.org/docs/portals.html) to render the popup modal. As a result, you'll need to
         * specify the rootElement property to ensure that the modal is inserted into the correct domNode.
         */
        rootElement={document.getElementById("root")}
        text="Click here to schedule!"
        textColor="#ffffff"
        color="#00a2ff"
      />
    </div>
  );
};

export default App;
```

#### PopupButton

```jsx
import React from "react";
import { PopupButton } from "react-calendly";

const App = () => {
  return (
    <div className="App">
      <PopupButton
        url="https://calendly.com/your_scheduling_page"
        /*
         * react-calendly uses React's Portal feature (https://reactjs.org/docs/portals.html) to render the popup modal. As a result, you'll need to
         * specify the rootElement property to ensure that the modal is inserted into the correct domNode.
         */
        rootElement={document.getElementById("root")}
        text="Click here to schedule!"
      />
    </div>
  );
};

export default App;
```

#### useCalendlyEventListener

```jsx
import React from "react";
import { useCalendlyEventListener, InlineWidget } from "react-calendly";

const App = () => {
  useCalendlyEventListener({
    onProfilePageViewed: () => console.log("onProfilePageViewed"),
    onDateAndTimeSelected: () => console.log("onDateAndTimeSelected"),
    onEventTypeViewed: () => console.log("onEventTypeViewed"),
    onEventScheduled: (e) => console.log(e.data.payload),
    onPageHeightResize: (e) => console.log(e.data.payload.height),
  });

  return (
    <div className="App">
      <InlineWidget url="https://calendly.com/your_scheduling_page" />
    </div>
  );
};

export default App;
```

### Advanced Usage

You can also take advantage of using optional props on the component(s) such as including a defined height, color customization options (available on Pro plan only), utm parameters, pre-filling custom questions, etc. Here are the optional props you can use with the inline embed:

#### Inline Embed Height

```jsx
styles={{
  height: '1000px'
}}
```

#### Page Settings

```jsx
pageSettings={{
  backgroundColor: 'ffffff',
  hideEventTypeDetails: false,
  hideLandingPageDetails: false,
  primaryColor: '00a2ff',
  textColor: '4d5055'
}}
```

#### Prefill Values

```jsx
prefill={{
  email: 'test@test.com',
  firstName: 'Jon',
  lastName: 'Snow',
  name: 'Jon Snow',
  guests: [
    'janedoe@example.com',
    'johndoe@example.com'
  ],
  customAnswers: {
    a1: 'a1',
    a2: 'a2',
    a3: 'a3',
    a4: 'a4',
    a5: 'a5',
    a6: 'a6',
    a7: 'a7',
    a8: 'a8',
    a9: 'a9',
    a10: 'a10'
  },
  date: new Date(Date.now() + 86400000)
}}
```

#### UTM Parameters

```jsx
utm={{
  utmCampaign: 'Spring Sale 2019',
  utmContent: 'Shoe and Shirts',
  utmMedium: 'Ad',
  utmSource: 'Facebook',
  utmTerm: 'Spring'
}}
```

## FAQ

#### Why are my page settings not working?

For the page settings to work, you'll need to pass in a `url` prop that is associated with a Calendly account on the [Pro plan](https://calendly.com/pages/pricing).

#### How do I create a custom button that triggers a pop-up scheduler?

```tsx
import { PopupModal } from "react-calendly";

class CustomButtonExample extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isOpen: false,
    };
  }

  render() {
    return (
      <div>
        <button
          style={{ display: "block", margin: "0 auto" }}
          onClick={() => this.setState({ isOpen: true })}
        >
          Custom Button
        </button>
        <PopupModal
          url="https://calendly.com/acmesales"
          pageSettings={this.props.pageSettings}
          utm={this.props.utm}
          prefill={this.props.prefill}
          onModalClose={() => this.setState({ isOpen: false })}
          open={this.state.isOpen}
          /*
           * react-calendly uses React's Portal feature (https://reactjs.org/docs/portals.html) to render the popup modal. As a result, you'll need to
           * specify the rootElement property to ensure that the modal is inserted into the correct domNode.
           */
          rootElement={document.getElementById("root")}
        />
      </div>
    );
  }
}
```

#### How can I access the event details when an event is scheduled?

The [useCalendlyEventListener](https://tcampb.github.io/react-calendly/?path=/story/components--usecalendlyeventlistener) `onEventScheduled` prop receives an event with the following data structure:

```javascript
{
  event: "calendly.event_scheduled",
  payload: {
    event: {
      uri: "https://calendly.com/api/v2/scheduled_events/AAAAAAAAAAAAAA"
    },
    invitee: {
      uri: "https://calendly.com/api/v2/scheduled_events/AAAAAAAAAAAAAA/invitees/AAAAAAAAAAAAAA"
    }
  }
}
```

If you are using [Calendly's v2 api](https://developer.calendly.com/docs/api-docs/docs/A-API-Getting-Started.md) you can reference the event/invitee URIs included in the event payload to retrieve additional information about the event and/or invitee record.

- [Scheduled Event Schema](https://developer.calendly.com/api-docs/e2f95ebd44914-get-event)
- [Invitee Schema](https://developer.calendly.com/api-docs/8305c0ccfac70-get-event-invitee)

#### Can I use react-calendly with Nextjs?

Yes, see https://github.com/tcampb/react-calendly/issues/105 for additional details.

## Additional Resources

[Embed options overview](https://help.calendly.com/hc/en-us/articles/223147027-Embed-options-overview)

[Advanced embed options](https://help.calendly.com/hc/en-us/articles/360020052833-Advanced-embed-options)

[Common embed questions](https://help.calendly.com/hc/en-us/articles/360019861794-Common-embed-questions)

## License

MIT © [tcampb](https://github.com/tcampb)


================================================
FILE: package.json
================================================
{
  "name": "react-calendly",
  "version": "4.4.0",
  "description": "Calendly integration for React apps",
  "author": "tcampb",
  "license": "MIT",
  "repository": "tcampb/react-calendly",
  "main": "dist/index.js",
  "typings": "typings/index.d.ts",
  "module": "dist/index.es.js",
  "jsnext:main": "dist/index.es.js",
  "engines": {
    "node": ">=8",
    "npm": ">=5"
  },
  "keywords": [
    "react",
    "calendly",
    "component"
  ],
  "scripts": {
    "build": "rollup -c && tsc --emitDeclarationOnly",
    "start": "rollup -c -w",
    "prepare": "npm run build"
  },
  "peerDependencies": {
    "react": ">=16.8.0",
    "react-dom": ">=16.8.0"
  },
  "devDependencies": {
    "@rollup/plugin-typescript": "^11.1.4",
    "@types/react": "^16.8.0",
    "@types/react-dom": "^16.8.0",
    "prettier": "2.0.2",
    "react": "^16.8.0",
    "react-dom": "^16.8.0",
    "rollup": "^3.29.4",
    "typescript": "^4.0.5",
    "@rollup/plugin-commonjs": "^25.0.4",
    "@rollup/plugin-node-resolve": "^15.2.1",
    "rollup-plugin-peer-deps-external": "^2.2.4",
    "rollup-plugin-postcss": "^4.0.2",
    "tslib": "^2.6.2"
  },
  "files": [
    "dist",
    "typings"
  ]
}


================================================
FILE: rollup.config.js
================================================
const typescript = require("@rollup/plugin-typescript");
const commonjs = require('@rollup/plugin-commonjs')
const pkg = require("./package.json")
const postcss = require('rollup-plugin-postcss');
const external = require('rollup-plugin-peer-deps-external');

module.exports = {
  input: "src/index.tsx",
  output: [
    {
      file: pkg.main,
      format: "cjs",
      exports: "named"
    },
    {
      file: pkg.module,
      format: "es",
      exports: "named"
    },
  ],
  plugins: [external(), postcss(), typescript(), commonjs()],
};


================================================
FILE: src/calendly-widget.css
================================================
/*
  code is extracted from Calendly's embed stylesheet: https://assets.calendly.com/assets/external/widget.css
*/

.calendly-inline-widget,
.calendly-inline-widget *,
.calendly-badge-widget,
.calendly-badge-widget *,
.calendly-overlay,
.calendly-overlay * {
  font-size: 16px;
  line-height: 1.2em;
}

.calendly-inline-widget {
  min-width: 320px;
  height: 630px;
}

.calendly-inline-widget iframe,
.calendly-badge-widget iframe,
.calendly-overlay iframe {
  display: inline;
  width: 100%;
  height: 100%;
}

.calendly-popup-content {
  position: relative;
}

.calendly-popup-content.calendly-mobile {
  -webkit-overflow-scrolling: touch;
  overflow-y: auto;
}

.calendly-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
  z-index: 9999;
  background-color: #a5a5a5;
  background-color: rgba(31, 31, 31, 0.4);
}

.calendly-overlay .calendly-close-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.calendly-overlay .calendly-popup {
  box-sizing: border-box;
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translateY(-50%) translateX(-50%);
  transform: translateY(-50%) translateX(-50%);
  width: 80%;
  min-width: 900px;
  max-width: 1000px;
  height: 90%;
  max-height: 680px;
}

@media (max-width: 975px) {
  .calendly-overlay .calendly-popup {
    position: fixed;
    top: 50px;
    left: 0;
    right: 0;
    bottom: 0;
    -webkit-transform: none;
    transform: none;
    width: 100%;
    height: auto;
    min-width: 0;
    max-height: none;
  }
}

.calendly-overlay .calendly-popup .calendly-popup-content {
  height: 100%;
}

.calendly-overlay .calendly-popup-close {
  position: absolute;
  top: 25px;
  right: 25px;
  color: #fff;
  width: 19px;
  height: 19px;
  cursor: pointer;
  background: url(https://assets.calendly.com/assets/external/close-icon.svg)
    no-repeat;
  background-size: contain;
}

@media (max-width: 975px) {
  .calendly-overlay .calendly-popup-close {
    top: 15px;
    right: 15px;
  }
}

.calendly-badge-widget {
  position: fixed;
  right: 20px;
  bottom: 15px;
  z-index: 9998;
}

.calendly-badge-widget .calendly-badge-content {
  display: table-cell;
  width: auto;
  height: 45px;
  padding: 0 30px;
  border-radius: 25px;
  box-shadow: rgba(0, 0, 0, 0.25) 0 2px 5px;
  font-family: sans-serif;
  text-align: center;
  vertical-align: middle;
  font-weight: bold;
  font-size: 14px;
  color: #fff;
  cursor: pointer;
}

.calendly-badge-widget .calendly-badge-content.calendly-white {
  color: #666a73;
}

.calendly-badge-widget .calendly-badge-content span {
  display: block;
  font-size: 12px;
}

.calendly-spinner {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  -webkit-transform: translateY(-50%);
  transform: translateY(-50%);
  text-align: center;
  z-index: -1;
}

.calendly-spinner > div {
  display: inline-block;
  width: 18px;
  height: 18px;
  background-color: #e1e1e1;
  border-radius: 50%;
  vertical-align: middle;
  -webkit-animation: calendly-bouncedelay 1.4s infinite ease-in-out;
  animation: calendly-bouncedelay 1.4s infinite ease-in-out;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}

.calendly-spinner .calendly-bounce1 {
  -webkit-animation-delay: -0.32s;
  animation-delay: -0.32s;
}

.calendly-spinner .calendly-bounce2 {
  -webkit-animation-delay: -0.16s;
  animation-delay: -0.16s;
}

@-webkit-keyframes calendly-bouncedelay {
  0%,
  80%,
  100% {
    -webkit-transform: scale(0);
    transform: scale(0);
  }

  40% {
    -webkit-transform: scale(1);
    transform: scale(1);
  }
}

@keyframes calendly-bouncedelay {
  0%,
  80%,
  100% {
    -webkit-transform: scale(0);
    transform: scale(0);
  }

  40% {
    -webkit-transform: scale(1);
    transform: scale(1);
  }
}


================================================
FILE: src/calendly.tsx
================================================
import { sanitizePageSettingsProps } from "./helpers/propHelpers";

type Optional<T extends object> = {
  [P in keyof T]?: T[P];
};

export type Prefill = Optional<{
  name: string;
  email: string;
  firstName: string;
  lastName: string;
  location: string;
  guests: string[];
  customAnswers: Optional<{
    a1: string;
    a2: string;
    a3: string;
    a4: string;
    a5: string;
    a6: string;
    a7: string;
    a8: string;
    a9: string;
    a10: string;
  }>;
  date: Date;
}>;

export enum CalendlyEvent {
  PROFILE_PAGE_VIEWED = "calendly.profile_page_viewed",
  EVENT_TYPE_VIEWED = "calendly.event_type_viewed",
  DATE_AND_TIME_SELECTED = "calendly.date_and_time_selected",
  EVENT_SCHEDULED = "calendly.event_scheduled",
  PAGE_HEIGHT = "calendly.page_height",
}

export type Utm = Optional<{
  utmCampaign: string;
  utmSource: string;
  utmMedium: string;
  utmContent: string;
  utmTerm: string;
  salesforce_uuid: string;
}>;

/**
 * @description The default title is Calendly Scheduling Page
 * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title}
 */
export type IframeTitle = string;

/**
 * @description LoadingSpinner is a React component that will be displayed while the Calendly iframe is loading. If no component is provided, the default Calendly loading spinner will be used.
 */
export type LoadingSpinner = React.FunctionComponent;

export type PageSettings = Optional<{
  /**
   * @description Use this setting to hide your profile picture, name, event duration, location, and description when Calendly is embedded. This will help reduce duplicate information that you may already have on your web page.
   * @see {@link https://help.calendly.com/hc/en-us/articles/360020052833-Advanced-embed-options#2} for further information.
   */
  hideLandingPageDetails: boolean;
  /**
   * @description Use this setting to hide your profile picture, name, event duration, location, and description when Calendly is embedded. This will help reduce duplicate information that you may already have on your web page.
   * @see {@link https://help.calendly.com/hc/en-us/articles/360020052833-Advanced-embed-options#2} for further information.
   */
  hideEventTypeDetails: boolean;
  /**
   * @description This setting is only available for Calendly users on the Pro plan. Use this setting to change your Calendly scheduling page's background color.
   * @example 00a2ff
   * @see {@link https://help.calendly.com/hc/en-us/articles/223147027-Embed-options-overview#3} for further information.
   */
  backgroundColor: string;
  /**
   * @description This setting is only available for Calendly users on the Pro plan. Use this setting to change your Calendly scheduling page's text color.
   * @example ffffff
   * @see {@link https://help.calendly.com/hc/en-us/articles/223147027-Embed-options-overview#3} for further information.
   */
  textColor: string;
  /**
   * @description This setting is only available for Calendly users on the Pro plan. Use this setting to change your Calendly scheduling page's primary color.
   * @example 4d5055
   * @see {@link https://help.calendly.com/hc/en-us/articles/223147027-Embed-options-overview#3} for further information.
   */
  primaryColor: string;
  /**
   * @description The General Data Protection Regulation governs data protection in the EU and EEA. Certain Calendly integrations require access to cookies with user information. If you do not embed the GDPR banner, users in those areas will not have the ability to give their consent in order to access integrations such as Google Analytics, Facebook Pixel, PayPal, and Stripe.
   * @see {@link https://help.calendly.com/hc/en-us/articles/360007385493-Cookie-FAQs} for further information.
   */
  hideGdprBanner: boolean;
}>;

export const formatCalendlyUrl = ({
  url,
  prefill = {},
  pageSettings = {},
  utm = {},
  embedType,
}: {
  url: string;
  prefill?: Prefill;
  pageSettings?: PageSettings;
  utm?: Utm;
  embedType?: "Inline" | "PopupWidget" | "PopupButton";
}) => {
  const sanitizedPageSettings = sanitizePageSettingsProps(pageSettings);

  const {
    backgroundColor,
    hideEventTypeDetails,
    hideLandingPageDetails,
    primaryColor,
    textColor,
    hideGdprBanner,
  } = sanitizedPageSettings;

  const {
    customAnswers,
    date,
    email,
    firstName,
    guests,
    lastName,
    location,
    name,
  } = prefill;

  const {
    utmCampaign,
    utmContent,
    utmMedium,
    utmSource,
    utmTerm,
    salesforce_uuid,
  } = utm;

  const queryStringIndex = url.indexOf("?");
  const hasQueryString = queryStringIndex > -1;
  const queryString = url.slice(queryStringIndex + 1);
  const baseUrl = hasQueryString ? url.slice(0, queryStringIndex) : url;

  const updatedQueryString = [
    hasQueryString ? queryString : null,
    backgroundColor ? `background_color=${backgroundColor}` : null,
    hideEventTypeDetails ? `hide_event_type_details=1` : null,
    hideLandingPageDetails ? `hide_landing_page_details=1` : null,
    primaryColor ? `primary_color=${primaryColor}` : null,
    textColor ? `text_color=${textColor}` : null,
    hideGdprBanner ? `hide_gdpr_banner=1` : null,
    name ? `name=${encodeURIComponent(name)}` : null,
    location ? `location=${encodeURIComponent(location)}` : null,
    firstName ? `first_name=${encodeURIComponent(firstName)}` : null,
    lastName ? `last_name=${encodeURIComponent(lastName)}` : null,
    guests ? `guests=${guests.map(encodeURIComponent).join(",")}` : null,
    email ? `email=${encodeURIComponent(email)}` : null,
    date && date instanceof Date ? `date=${formatDate(date)}` : null,
    utmCampaign ? `utm_campaign=${encodeURIComponent(utmCampaign)}` : null,
    utmContent ? `utm_content=${encodeURIComponent(utmContent)}` : null,
    utmMedium ? `utm_medium=${encodeURIComponent(utmMedium)}` : null,
    utmSource ? `utm_source=${encodeURIComponent(utmSource)}` : null,
    utmTerm ? `utm_term=${encodeURIComponent(utmTerm)}` : null,
    salesforce_uuid
      ? `salesforce_uuid=${encodeURIComponent(salesforce_uuid)}`
      : null,
    embedType ? `embed_type=${embedType}` : null,
    /*
     * https://github.com/tcampb/react-calendly/pull/31
     * embed_domain must be defined to receive messages from the Calendly iframe.
     */
    `embed_domain=1`,
  ]
    .concat(customAnswers ? formatCustomAnswers(customAnswers) : [])
    .filter((item) => item !== null)
    .join("&");

  return `${baseUrl}?${updatedQueryString}`;
};

const formatDate = (d: Date) => {
  const month = d.getMonth() + 1;
  const day = d.getDate();
  const year = d.getFullYear();

  return [
    year,
    month < 10 ? `0${month}` : month,
    day < 10 ? `0${day}` : day,
  ].join("-");
};

const CUSTOM_ANSWER_PATTERN = /^a\d{1,2}$/;
const formatCustomAnswers = (customAnswers: object) => {
  const customAnswersFiltered = Object.keys(customAnswers).filter((key) =>
    key.match(CUSTOM_ANSWER_PATTERN)
  );

  if (!customAnswersFiltered.length) return [];

  return customAnswersFiltered.map(
    (key) => `${key}=${encodeURIComponent(customAnswers[key])}`
  );
};


================================================
FILE: src/components/InlineWidget/InlineWidget.tsx
================================================
import * as React from "react";
import "../../calendly-widget.css";
import {
  PageSettings,
  Prefill,
  Utm,
  IframeTitle,
  formatCalendlyUrl,
  LoadingSpinner,
} from "../../calendly";
import CalendlyLoadingSpinner from "../LoadingSpinner/LoadingSpinner";

export interface Props {
  url: string;
  prefill?: Prefill;
  utm?: Utm;
  styles?: React.CSSProperties | undefined;
  pageSettings?: PageSettings;
  iframeTitle?: IframeTitle;
  LoadingSpinner?: LoadingSpinner;
  className?: string;
}

const defaultClassName = "calendly-inline-widget";

class InlineWidget extends React.Component<Props, { isLoading: boolean }> {
  constructor(props: Props) {
    super(props);

    this.state = {
      isLoading: true,
    };

    this.onLoad = this.onLoad.bind(this);
  }

  private onLoad() {
    this.setState({
      isLoading: false,
    });
  }

  render() {
    const src = formatCalendlyUrl({
      url: this.props.url,
      pageSettings: this.props.pageSettings,
      prefill: this.props.prefill,
      utm: this.props.utm,
      embedType: "Inline",
    });
    const LoadingSpinner = this.props.LoadingSpinner || CalendlyLoadingSpinner;

    return (
      <div
        className={this.props.className || defaultClassName}
        style={this.props.styles || {}}
      >
        {this.state.isLoading && <LoadingSpinner />}
        <iframe
          width="100%"
          height="100%"
          frameBorder="0"
          title={this.props.iframeTitle || "Calendly Scheduling Page"}
          onLoad={this.onLoad}
          src={src}
        ></iframe>
      </div>
    );
  }
}

export default InlineWidget;


================================================
FILE: src/components/LoadingSpinner/LoadingSpinner.tsx
================================================
import * as React from "react";
import "../../calendly-widget.css";

class LoadingSpinner extends React.Component {
  render() {
    return (
      <div className="calendly-spinner">
        <div className="calendly-bounce1"></div>
        <div className="calendly-bounce2"></div>
        <div className="calendly-bounce3"></div>
      </div>
    );
  }
}

export default LoadingSpinner;


================================================
FILE: src/components/PopupButton/PopupButton.tsx
================================================
import * as React from "react";
import "../../calendly-widget.css";
import { PageSettings, Prefill, Utm, IframeTitle, LoadingSpinner } from "../../calendly";
import Modal from "../PopupModal/Modal";

export interface Props {
  url: string;
  text: string;
  rootElement: HTMLElement;
  prefill?: Prefill;
  utm?: Utm;
  pageSettings?: PageSettings;
  styles?: React.CSSProperties | undefined;
  className?: string;
  iframeTitle?: IframeTitle;
  LoadingSpinner?: LoadingSpinner;
}

class PopupButton extends React.Component<Props, { isOpen: boolean }> {
  constructor(props: Props) {
    super(props);

    this.state = {
      isOpen: false,
    };

    this.onClick = this.onClick.bind(this);
    this.onClose = this.onClose.bind(this);
  }

  onClick(e: React.SyntheticEvent) {
    e.preventDefault();
    this.setState({
      isOpen: true,
    });
  }

  onClose(e: React.SyntheticEvent) {
    e.stopPropagation();

    this.setState({
      isOpen: false,
    });
  }

  render() {
    return (
      <>
        <button
          onClick={this.onClick}
          style={this.props.styles || {}}
          className={this.props.className || ""}
        >
          {this.props.text}
        </button>
        <Modal
          {...this.props}
          open={this.state.isOpen}
          onModalClose={this.onClose}
          rootElement={this.props.rootElement}
        />
      </>
    );
  }
}

export default PopupButton;


================================================
FILE: src/components/PopupModal/Modal.tsx
================================================
import * as React from "react";
import * as ReactDom from "react-dom";
import { LoadingSpinner } from "../../calendly";
import ModalContent, { Props as ModalContentProps } from "./ModalContent";

interface Props extends ModalContentProps {
  onModalClose: (e: React.MouseEvent<HTMLElement>) => void;
  open: boolean;
  rootElement: HTMLElement;
  LoadingSpinner?: LoadingSpinner;
}

export default (props: Props) => {
  if (!props.open) return null;

  if (!props.rootElement) {
    throw new Error('[react-calendly]: PopupModal rootElement property cannot be undefined')
  }

  return ReactDom.createPortal(
    <div className="calendly-overlay">
      <div
        onClick={props.onModalClose}
        className="calendly-close-overlay"
      ></div>
      <div className="calendly-popup">
        <div className="calendly-popup-content">
          <ModalContent {...props} />
        </div>
      </div>
      <button
        className="calendly-popup-close"
        onClick={props.onModalClose}
        aria-label="Close modal"
        style={{
          display: "block",
          border: "none",
          padding: 0,
        }}
      ></button>
    </div>,
    props.rootElement
  );
};


================================================
FILE: src/components/PopupModal/ModalContent.tsx
================================================
import * as React from "react";
import "../../calendly-widget.css";
import {
  PageSettings,
  Prefill,
  Utm,
  IframeTitle,
  formatCalendlyUrl,
  LoadingSpinner,
} from "../../calendly";
import CalendlyLoadingSpinner from "../LoadingSpinner/LoadingSpinner";

export interface Props {
  url: string;
  prefill?: Prefill;
  utm?: Utm;
  pageSettings?: PageSettings;
  iframeTitle?: IframeTitle;
  LoadingSpinner?: LoadingSpinner;
}

class ModalContent extends React.Component<Props, { isLoading: boolean }> {
  constructor(props: Props) {
    super(props);

    this.state = {
      isLoading: true,
    };

    this.onLoad = this.onLoad.bind(this);
  }

  private onLoad() {
    this.setState({
      isLoading: false,
    });
  }

  render() {
    const src = formatCalendlyUrl({
      url: this.props.url,
      pageSettings: this.props.pageSettings,
      prefill: this.props.prefill,
      utm: this.props.utm,
      embedType: "Inline",
    });
    const LoadingSpinner = this.props.LoadingSpinner || CalendlyLoadingSpinner;

    return (
      <>
        {this.state.isLoading && <LoadingSpinner />}
        <iframe
          width="100%"
          height="100%"
          frameBorder="0"
          title={this.props.iframeTitle || "Calendly Scheduling Page"}
          onLoad={this.onLoad}
          src={src}
        ></iframe>
      </>
    );
  }
}

export default ModalContent;


================================================
FILE: src/components/PopupWidget/PopupWidget.tsx
================================================
import * as React from "react";
import "../../calendly-widget.css";
import { PageSettings, Prefill, Utm, IframeTitle, LoadingSpinner } from "../../calendly";
import Modal from "../PopupModal/Modal";

export interface Props {
  url: string;
  text: string;
  rootElement: HTMLElement;
  color?: string;
  textColor?: string;
  branding?: boolean;
  prefill?: Prefill;
  utm?: Utm;
  pageSettings?: PageSettings;
  iframeTitle?: IframeTitle;
  LoadingSpinner?: LoadingSpinner;
}

class PopupWidget extends React.Component<Props, { isOpen: boolean }> {
  constructor(props: Props) {
    super(props);

    this.state = {
      isOpen: false,
    };

    this.onClick = this.onClick.bind(this);
    this.onClose = this.onClose.bind(this);
  }

  onClick() {
    this.setState({
      isOpen: true,
    });
  }

  onClose(e: React.SyntheticEvent) {
    e.stopPropagation();

    this.setState({
      isOpen: false,
    });
  }

  render() {
    return (
      <div className="calendly-badge-widget" onClick={this.onClick}>
        <div
          className="calendly-badge-content"
          style={{
            background: this.props.color || "#00a2ff",
            color: this.props.textColor || "#ffffff",
          }}
        >
          {this.props.text || "Schedule time with me"}
          {this.props.branding && <span>powered by Calendly</span>}
        </div>
        <Modal
          {...this.props}
          open={this.state.isOpen}
          onModalClose={this.onClose}
          rootElement={this.props.rootElement}
        />
      </div>
    );
  }
}

export default PopupWidget;


================================================
FILE: src/components/hooks/useCalendlyEventListener.ts
================================================
import * as React from "react";
import { CalendlyEvent } from "../../calendly";

export type DateAndTimeSelectedEvent = MessageEvent<{
  event: CalendlyEvent.DATE_AND_TIME_SELECTED;
  payload: {};
}>;

export type EventScheduledEvent = MessageEvent<{
  event: CalendlyEvent.EVENT_SCHEDULED;
  payload: {
    event: {
      /**
       * @description Canonical reference (unique identifier) to the event that was scheduled.
       * @example https://calendly.com/api/v2/scheduled_events/AAAAAAAAAAAAAA
       * @see {@link https://developer.calendly.com/docs/api-docs/reference/calendly-api/openapi.yaml/paths/~1scheduled_events~1%7Buuid%7D/get} for further information.
       */
      uri: string;
    };
    invitee: {
      /**
       * @description Canonical reference (unique identifier) for the invitee who scheduled the event.
       * @example https://calendly.com/api/v2/scheduled_events/AAAAAAAAAAAAAA/invitees/AAAAAAAAAAAAAA
       * @see {@link https://developer.calendly.com/docs/api-docs/reference/calendly-api/openapi.yaml/paths/~1scheduled_events~1%7Bevent_uuid%7D~1invitees~1%7Binvitee_uuid%7D/get} for further information.
       */
      uri: string;
    };
  };
}>;

export type EventTypeViewedEvent = MessageEvent<{
  event: CalendlyEvent.EVENT_TYPE_VIEWED;
  payload: {};
}>;

export type ProfilePageViewedEvent = MessageEvent<{
  event: CalendlyEvent.PROFILE_PAGE_VIEWED;
  payload: {};
}>;

export type PageHeightResizeEvent = MessageEvent<{
  event: CalendlyEvent.PAGE_HEIGHT;
  payload: {
    /**
       * @description The height of the Calendly scheduling page in pixels.
       * @example 1200px
       */
    height: string;
  };
}>;

export type CalendlyEventHandlers = {
  onDateAndTimeSelected?: (e: DateAndTimeSelectedEvent) => any;
  onEventScheduled?: (e: EventScheduledEvent) => any;
  onEventTypeViewed?: (e: EventTypeViewedEvent) => any;
  onProfilePageViewed?: (e: ProfilePageViewedEvent) => any;
  onPageHeightResize?: (e: PageHeightResizeEvent) => any;
};

const EVENT_NAME = "message";

export default function useCalendlyEventListener(
  eventHandlers: CalendlyEventHandlers
) {
  const {
    onDateAndTimeSelected,
    onEventScheduled,
    onEventTypeViewed,
    onProfilePageViewed,
    onPageHeightResize
  } = eventHandlers || {};

  React.useEffect(() => {
    const onMessage = (e: MessageEvent) => {
      const eventName = e.data.event;

      if (eventName === CalendlyEvent.DATE_AND_TIME_SELECTED) {
        onDateAndTimeSelected && onDateAndTimeSelected(e);
      } else if (eventName === CalendlyEvent.EVENT_SCHEDULED) {
        onEventScheduled && onEventScheduled(e);
      } else if (eventName === CalendlyEvent.EVENT_TYPE_VIEWED) {
        onEventTypeViewed && onEventTypeViewed(e);
      } else if (eventName === CalendlyEvent.PROFILE_PAGE_VIEWED) {
        onProfilePageViewed && onProfilePageViewed(e);
      } else if (eventName === CalendlyEvent.PAGE_HEIGHT) {
        onPageHeightResize && onPageHeightResize(e);
      }
    };

    window.addEventListener(EVENT_NAME, onMessage);

    return function cleanup() {
      window.removeEventListener(EVENT_NAME, onMessage);
    };
  }, [eventHandlers]);
}


================================================
FILE: src/helpers/propHelpers.ts
================================================
import { PageSettings } from "../calendly";

function sanitizeColorString(str: string): string {
  if (str.charAt(0) === "#") {
    return str.slice(1);
  }
  return str;
}

export function sanitizePageSettingsProps(
  props: PageSettings
) {
  if (props?.primaryColor) {
    props.primaryColor = sanitizeColorString(props.primaryColor);
  }

  if (props?.textColor) {
    props.textColor = sanitizeColorString(props.textColor);
  }

  if (props?.backgroundColor) {
    props.backgroundColor = sanitizeColorString(props.backgroundColor);
  }

  return props;
}


================================================
FILE: src/index.tsx
================================================
import InlineWidget from "./components/InlineWidget/InlineWidget";
import PopupButton from "./components/PopupButton/PopupButton";
import PopupWidget from "./components/PopupWidget/PopupWidget";
import PopupModal from "./components/PopupModal/Modal";
import useCalendlyEventListener from "./components/hooks/useCalendlyEventListener";
import type {
  DateAndTimeSelectedEvent,
  EventScheduledEvent,
  EventTypeViewedEvent,
  ProfilePageViewedEvent,
} from "./components/hooks/useCalendlyEventListener";

export { InlineWidget };
export { PopupButton };
export { PopupWidget };
export { PopupModal };
export { useCalendlyEventListener };
export {
  DateAndTimeSelectedEvent,
  EventScheduledEvent,
  EventTypeViewedEvent,
  ProfilePageViewedEvent,
};


================================================
FILE: tsconfig.json
================================================
{
  "compilerOptions": {
    "outDir": "build",
    "module": "esnext",
    "target": "es5",
    "lib": ["es6", "dom", "es2016", "es2017"],
    "sourceMap": true,
    "allowJs": false,
    "jsx": "react",
    "declaration": true,
    "declarationDir": "typings",
    "moduleResolution": "node",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true
  },
  "include": ["src"],
  "exclude": [
    "node_modules",
    "build",
    "dist",
    "rollup.config.js",
    "**/*.stories.tsx"
  ]
}
Download .txt
gitextract_z_zg3mar/

├── .editorconfig
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package.json
├── rollup.config.js
├── src/
│   ├── calendly-widget.css
│   ├── calendly.tsx
│   ├── components/
│   │   ├── InlineWidget/
│   │   │   └── InlineWidget.tsx
│   │   ├── LoadingSpinner/
│   │   │   └── LoadingSpinner.tsx
│   │   ├── PopupButton/
│   │   │   └── PopupButton.tsx
│   │   ├── PopupModal/
│   │   │   ├── Modal.tsx
│   │   │   └── ModalContent.tsx
│   │   ├── PopupWidget/
│   │   │   └── PopupWidget.tsx
│   │   └── hooks/
│   │       └── useCalendlyEventListener.ts
│   ├── helpers/
│   │   └── propHelpers.ts
│   └── index.tsx
└── tsconfig.json
Download .txt
SYMBOL INDEX (43 symbols across 9 files)

FILE: src/calendly.tsx
  type Optional (line 3) | type Optional<T extends object> = {
  type Prefill (line 7) | type Prefill = Optional<{
  type CalendlyEvent (line 29) | enum CalendlyEvent {
  type Utm (line 37) | type Utm = Optional<{
  type IframeTitle (line 50) | type IframeTitle = string;
  type LoadingSpinner (line 55) | type LoadingSpinner = React.FunctionComponent;
  type PageSettings (line 57) | type PageSettings = Optional<{
  constant CUSTOM_ANSWER_PATTERN (line 191) | const CUSTOM_ANSWER_PATTERN = /^a\d{1,2}$/;

FILE: src/components/InlineWidget/InlineWidget.tsx
  type Props (line 13) | interface Props {
  class InlineWidget (line 26) | class InlineWidget extends React.Component<Props, { isLoading: boolean }> {
    method constructor (line 27) | constructor(props: Props) {
    method onLoad (line 37) | private onLoad() {
    method render (line 43) | render() {

FILE: src/components/LoadingSpinner/LoadingSpinner.tsx
  class LoadingSpinner (line 4) | class LoadingSpinner extends React.Component {
    method render (line 5) | render() {

FILE: src/components/PopupButton/PopupButton.tsx
  type Props (line 6) | interface Props {
  class PopupButton (line 19) | class PopupButton extends React.Component<Props, { isOpen: boolean }> {
    method constructor (line 20) | constructor(props: Props) {
    method onClick (line 31) | onClick(e: React.SyntheticEvent) {
    method onClose (line 38) | onClose(e: React.SyntheticEvent) {
    method render (line 46) | render() {

FILE: src/components/PopupModal/Modal.tsx
  type Props (line 6) | interface Props extends ModalContentProps {

FILE: src/components/PopupModal/ModalContent.tsx
  type Props (line 13) | interface Props {
  class ModalContent (line 22) | class ModalContent extends React.Component<Props, { isLoading: boolean }> {
    method constructor (line 23) | constructor(props: Props) {
    method onLoad (line 33) | private onLoad() {
    method render (line 39) | render() {

FILE: src/components/PopupWidget/PopupWidget.tsx
  type Props (line 6) | interface Props {
  class PopupWidget (line 20) | class PopupWidget extends React.Component<Props, { isOpen: boolean }> {
    method constructor (line 21) | constructor(props: Props) {
    method onClick (line 32) | onClick() {
    method onClose (line 38) | onClose(e: React.SyntheticEvent) {
    method render (line 46) | render() {

FILE: src/components/hooks/useCalendlyEventListener.ts
  type DateAndTimeSelectedEvent (line 4) | type DateAndTimeSelectedEvent = MessageEvent<{
  type EventScheduledEvent (line 9) | type EventScheduledEvent = MessageEvent<{
  type EventTypeViewedEvent (line 31) | type EventTypeViewedEvent = MessageEvent<{
  type ProfilePageViewedEvent (line 36) | type ProfilePageViewedEvent = MessageEvent<{
  type PageHeightResizeEvent (line 41) | type PageHeightResizeEvent = MessageEvent<{
  type CalendlyEventHandlers (line 52) | type CalendlyEventHandlers = {
  constant EVENT_NAME (line 60) | const EVENT_NAME = "message";
  function useCalendlyEventListener (line 62) | function useCalendlyEventListener(

FILE: src/helpers/propHelpers.ts
  function sanitizeColorString (line 3) | function sanitizeColorString(str: string): string {
  function sanitizePageSettingsProps (line 10) | function sanitizePageSettingsProps(
Condensed preview — 19 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (41K chars).
[
  {
    "path": ".editorconfig",
    "chars": 147,
    "preview": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_"
  },
  {
    "path": ".gitignore",
    "chars": 311,
    "preview": "\n# See https://help.github.com/ignore-files/ for more about ignoring files.\n\n# dependencies\nnode_modules\n\n# builds\nbuild"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 2745,
    "preview": "# Changelog\n\n## 4.4.0\n\n- Added `className` option to `InlineWidget` component.\n- Removed SMS prefill option since it is "
  },
  {
    "path": "LICENSE",
    "chars": 1071,
    "preview": "MIT License\n\nCopyright (c) 2020 Tyler Campbell\n\nPermission is hereby granted, free of charge, to any person obtaining a "
  },
  {
    "path": "README.md",
    "chars": 7982,
    "preview": "# react-calendly\n[Calendly integration](https://help.calendly.com/hc/en-us/articles/223147027-Embed-options-overview) fo"
  },
  {
    "path": "package.json",
    "chars": 1173,
    "preview": "{\n  \"name\": \"react-calendly\",\n  \"version\": \"4.4.0\",\n  \"description\": \"Calendly integration for React apps\",\n  \"author\": "
  },
  {
    "path": "rollup.config.js",
    "chars": 546,
    "preview": "const typescript = require(\"@rollup/plugin-typescript\");\nconst commonjs = require('@rollup/plugin-commonjs')\nconst pkg ="
  },
  {
    "path": "src/calendly-widget.css",
    "chars": 3789,
    "preview": "/*\n  code is extracted from Calendly's embed stylesheet: https://assets.calendly.com/assets/external/widget.css\n*/\n\n.cal"
  },
  {
    "path": "src/calendly.tsx",
    "chars": 7108,
    "preview": "import { sanitizePageSettingsProps } from \"./helpers/propHelpers\";\n\ntype Optional<T extends object> = {\n  [P in keyof T]"
  },
  {
    "path": "src/components/InlineWidget/InlineWidget.tsx",
    "chars": 1623,
    "preview": "import * as React from \"react\";\nimport \"../../calendly-widget.css\";\nimport {\n  PageSettings,\n  Prefill,\n  Utm,\n  IframeT"
  },
  {
    "path": "src/components/LoadingSpinner/LoadingSpinner.tsx",
    "chars": 388,
    "preview": "import * as React from \"react\";\nimport \"../../calendly-widget.css\";\n\nclass LoadingSpinner extends React.Component {\n  re"
  },
  {
    "path": "src/components/PopupButton/PopupButton.tsx",
    "chars": 1430,
    "preview": "import * as React from \"react\";\nimport \"../../calendly-widget.css\";\nimport { PageSettings, Prefill, Utm, IframeTitle, Lo"
  },
  {
    "path": "src/components/PopupModal/Modal.tsx",
    "chars": 1195,
    "preview": "import * as React from \"react\";\nimport * as ReactDom from \"react-dom\";\nimport { LoadingSpinner } from \"../../calendly\";\n"
  },
  {
    "path": "src/components/PopupModal/ModalContent.tsx",
    "chars": 1391,
    "preview": "import * as React from \"react\";\nimport \"../../calendly-widget.css\";\nimport {\n  PageSettings,\n  Prefill,\n  Utm,\n  IframeT"
  },
  {
    "path": "src/components/PopupWidget/PopupWidget.tsx",
    "chars": 1593,
    "preview": "import * as React from \"react\";\nimport \"../../calendly-widget.css\";\nimport { PageSettings, Prefill, Utm, IframeTitle, Lo"
  },
  {
    "path": "src/components/hooks/useCalendlyEventListener.ts",
    "chars": 3168,
    "preview": "import * as React from \"react\";\nimport { CalendlyEvent } from \"../../calendly\";\n\nexport type DateAndTimeSelectedEvent = "
  },
  {
    "path": "src/helpers/propHelpers.ts",
    "chars": 561,
    "preview": "import { PageSettings } from \"../calendly\";\n\nfunction sanitizeColorString(str: string): string {\n  if (str.charAt(0) ==="
  },
  {
    "path": "src/index.tsx",
    "chars": 751,
    "preview": "import InlineWidget from \"./components/InlineWidget/InlineWidget\";\nimport PopupButton from \"./components/PopupButton/Pop"
  },
  {
    "path": "tsconfig.json",
    "chars": 700,
    "preview": "{\n  \"compilerOptions\": {\n    \"outDir\": \"build\",\n    \"module\": \"esnext\",\n    \"target\": \"es5\",\n    \"lib\": [\"es6\", \"dom\", \""
  }
]

About this extraction

This page contains the full source code of the tcampb/react-calendly GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 19 files (36.8 KB), approximately 10.6k tokens, and a symbol index with 43 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!