├── .nvmrc ├── .yarnrc ├── .node-version ├── .prettierignore ├── .stylelintignore ├── CODEOWNERS ├── assets ├── css │ └── tailwind.css ├── scss │ ├── components │ │ ├── _appBadges.scss │ │ ├── _chunk.scss │ │ ├── _adminBar.scss │ │ ├── _infoToggle.scss │ │ ├── _tooltip.scss │ │ ├── _dropdown.scss │ │ ├── _lockedBadge.scss │ │ ├── _signup.scss │ │ ├── _bounds.scss │ │ ├── _inlineblockList.scss │ │ ├── _toggleSwitch.scss │ │ ├── _accentHeader.scss │ │ ├── _footer.scss │ │ ├── _radio.scss │ │ ├── _checkbox.scss │ │ ├── _section.scss │ │ ├── _loading.scss │ │ ├── _typeahead.scss │ │ ├── _all.scss │ │ ├── _toast.scss │ │ ├── _textInput.scss │ │ ├── _icon.scss │ │ ├── _togglePill.scss │ │ ├── _popover.scss │ │ └── _accordion.scss │ ├── util │ │ ├── _vars.scss │ │ └── _color-mappings.scss │ ├── main.scss │ └── storybook.scss ├── images │ └── app_download │ │ ├── ios │ │ ├── download_de.png │ │ ├── download_en.png │ │ ├── download_es.png │ │ ├── download_fr.png │ │ ├── download_it.png │ │ ├── download_ja.png │ │ ├── download_ko.png │ │ ├── download_nl.png │ │ ├── download_pl.png │ │ ├── download_pt.png │ │ ├── download_ru.png │ │ ├── download_th.png │ │ └── download_tr.png │ │ └── android │ │ ├── download_de.png │ │ ├── download_en.png │ │ ├── download_es.png │ │ ├── download_fr.png │ │ ├── download_it.png │ │ ├── download_ja.png │ │ ├── download_ko.png │ │ ├── download_nl.png │ │ ├── download_pl.png │ │ ├── download_pt.png │ │ ├── download_ru.png │ │ ├── download_th.png │ │ └── download_tr.png └── svg │ ├── facebook.svg │ ├── email.svg │ ├── message.svg │ ├── proDashboard.svg │ ├── apple.svg │ ├── google.svg │ ├── host-badge.svg │ └── notification.svg ├── .eslintignore ├── Makefile ├── .github ├── PULL_REQUEST_TEMPLATE.md └── dependabot.yml ├── src ├── layout │ ├── __snapshots__ │ │ ├── chunk.test.jsx.snap │ │ ├── stripe.test.jsx.snap │ │ ├── flex.test.jsx.snap │ │ ├── section.test.jsx.snap │ │ ├── bounds.test.jsx.snap │ │ ├── card.test.jsx.snap │ │ └── formSection.test.jsx.snap │ ├── chunk.test.jsx │ ├── formSection.test.jsx │ ├── bounds.test.jsx │ ├── SectionTitle.jsx │ ├── Chunk.jsx │ ├── flexItem.test.jsx │ ├── inlineBlockList.test.jsx │ ├── Bounds.jsx │ └── FormSection.jsx ├── forms │ ├── __snapshots__ │ │ ├── typeahead.test.jsx.snap │ │ ├── charCounter.test.jsx.snap │ │ ├── timeInput.test.jsx.snap │ │ ├── button.test.jsx.snap │ │ ├── toggleSwitch.test.jsx.snap │ │ ├── LockedBadge.test.jsx.snap │ │ ├── errorList.test.jsx.snap │ │ ├── selectInput.test.jsx.snap │ │ ├── radioButtonGroup.test.jsx.snap │ │ ├── inputTime.test.jsx.snap │ │ ├── togglePill.test.jsx.snap │ │ ├── numberInput.test.jsx.snap │ │ └── checkbox.test.jsx.snap │ ├── redux-form │ │ ├── RadioButtonGroup.jsx │ │ ├── __snapshots__ │ │ │ ├── checkbox.test.jsx.snap │ │ │ ├── numberInput.test.jsx.snap │ │ │ ├── timeInput.test.jsx.snap │ │ │ ├── togglePill.test.jsx.snap │ │ │ ├── textInput.test.jsx.snap │ │ │ ├── textarea.test.jsx.snap │ │ │ ├── RadioButtonGroup.test.jsx.snap │ │ │ ├── calendarComponent.test.jsx.snap │ │ │ └── selectInput.test.jsx.snap │ │ ├── Checkbox.jsx │ │ ├── checkbox.test.jsx │ │ ├── RadioButtonGroup.test.jsx │ │ ├── numberInput.test.jsx │ │ ├── textarea.test.jsx │ │ ├── textInput.test.jsx │ │ ├── timeInput.test.jsx │ │ ├── calendarComponent.test.jsx │ │ ├── selectInput.test.jsx │ │ ├── Textarea.jsx │ │ ├── TimeInput.jsx │ │ ├── TextInput.jsx │ │ ├── SelectInput.jsx │ │ ├── NumberInput.jsx │ │ ├── TogglePill.jsx │ │ ├── togglePill.test.jsx │ │ └── CalendarComponent.jsx │ ├── TypeaheadItem.jsx │ ├── timeInput.test.jsx │ ├── charCounter.test.jsx │ ├── LockedBadge.story.jsx │ ├── errorList.test.jsx │ ├── CharCounter.jsx │ ├── errorList.story.jsx │ ├── radioButton.story.jsx │ ├── togglePill.test.jsx │ ├── ErrorList.jsx │ ├── LockedBadge.test.jsx │ ├── radioButton.test.jsx │ ├── togglepill.story.jsx │ ├── inputTime.test.jsx │ ├── toggleSwitch.story.jsx │ ├── select.test.jsx │ ├── RadioButton.jsx │ ├── checkbox.story.jsx │ ├── TogglePill.jsx │ └── NumberInput.jsx ├── utils │ ├── components │ │ ├── ConditionalWrap.jsx │ │ ├── __snapshots__ │ │ │ ├── toggleWrapper.test.jsx.snap │ │ │ ├── withLoading.test.jsx.snap │ │ │ └── withErrorList.test.jsx.snap │ │ ├── DeprecationWarning.jsx │ │ ├── withLoading.jsx │ │ └── withLoading.test.jsx │ ├── a11yPassThrough.js │ ├── bindAll.js │ ├── storyComponents.js │ ├── decorators.jsx │ ├── designConstants.js │ ├── testUtils.js │ └── getSocialLinks.js ├── types.js ├── __snapshots__ │ ├── accentHeader.test.jsx.snap │ └── hscroll.test.jsx.snap ├── media │ ├── appBadges.story.jsx │ ├── __snapshots__ │ │ ├── loading.test.jsx.snap │ │ └── appBadges.test.jsx.snap │ ├── avatar.story.jsx │ ├── loading.test.jsx │ ├── appBadges.test.jsx │ └── icon.story.jsx ├── navigation │ └── components │ │ ├── notifications │ │ ├── __snapshots__ │ │ │ ├── NotificationsDropdown.test.jsx.snap │ │ │ └── Notifications.test.jsx.snap │ │ ├── NotificationsDropdown.test.jsx │ │ └── Notifications.test.jsx │ │ ├── groupDraftItem │ │ ├── __snapshots__ │ │ │ └── GroupDraftItem.test.jsx.snap │ │ ├── GroupDraftItem.jsx │ │ └── GroupDraftItem.test.jsx │ │ ├── profile │ │ └── ProfileDropdown.test.jsx │ │ └── dashboard │ │ └── DashboardDropdown.test.jsx ├── interactive │ ├── __snapshots__ │ │ └── toast.test.jsx.snap │ └── InfoToggle.jsx ├── accentHeader.test.jsx ├── AccentHeader.jsx ├── signupModal.story.jsx ├── AccentHeader.story.jsx ├── SignupModal.test.jsx ├── hscroll.story.jsx └── Hscroll.jsx ├── .stylelintrc ├── .storybook ├── addons.js ├── config.js └── webpack.config.js ├── .babelrc ├── __mocks__ ├── emptyString.js ├── base64-image-loader.js └── textContentMocks.js ├── util ├── setupTest.js ├── sassRelativeImporter.js └── jestSystemShim.js ├── flow-typed ├── npm │ ├── flow-bin_v0.x.x.js │ ├── @storybook │ │ ├── addon-actions_v3.x.x.js │ │ ├── addon-knobs_v3.x.x.js │ │ └── react_v3.x.x.js │ ├── @alrra │ │ └── travis-scripts_vx.x.x.js │ ├── classnames_v2.x.x.js │ ├── raf-schd_vx.x.x.js │ ├── babel-jest_vx.x.x.js │ ├── raw-loader_vx.x.x.js │ ├── eslint-loader_vx.x.x.js │ ├── babel-preset-flow_vx.x.x.js │ ├── babel-preset-react_vx.x.x.js │ ├── babel-preset-es2015_vx.x.x.js │ ├── @meetup │ │ └── swarm-styles_vx.x.x.js │ ├── babel-preset-stage-2_vx.x.x.js │ ├── react-portal_v4.1.x.js │ ├── babel-plugin-transform-class-properties_vx.x.x.js │ ├── babel-plugin-transform-flow-strip-types_vx.x.x.js │ ├── file-loader_vx.x.x.js │ ├── storybook-react-router_vx.x.x.js │ ├── babel-plugin-react-intl_vx.x.x.js │ ├── eslint-import-resolver-webpack_vx.x.x.js │ ├── autosize_vx.x.x.js │ ├── babel-register_vx.x.x.js │ ├── raf_vx.x.x.js │ ├── react-flatpickr_vx.x.x.js │ ├── prop-types_v15.x.x.js │ ├── swarm-sasstools_vx.x.x.js │ ├── eslint-plugin-meetup_vx.x.x.js │ ├── stylelint-config-prettier_vx.x.x.js │ ├── babel-register_v6.x.x.js │ └── react-helmet_v5.x.x.js └── design-system.js ├── .flowconfig ├── .prettierrc ├── .npmignore ├── .gitignore ├── .eslintrc.airbnb.js ├── .editorconfig ├── jest.config.json ├── tailwind.config.js └── .eslintrc.js /.nvmrc: -------------------------------------------------------------------------------- 1 | 10.24.1 2 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | save-exact true -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 10.24.1 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | package.json 2 | -------------------------------------------------------------------------------- /.stylelintignore: -------------------------------------------------------------------------------- 1 | /assets/scss/storybook.scss -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @meetup/revenue-guardians 2 | -------------------------------------------------------------------------------- /assets/css/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind components; 2 | @tailwind utilities; 3 | -------------------------------------------------------------------------------- /assets/scss/components/_appBadges.scss: -------------------------------------------------------------------------------- 1 | .getTheApp-downloadImage { 2 | max-width: 160px; 3 | } 4 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/ 2 | coverage/ 3 | flow-typed/ 4 | infrastructure/ 5 | node_modules/ 6 | svg/ 7 | *.log 8 | tests/ -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CI_BUILD_NUMBER ?= $(USER)-snapshot 2 | VERSION ?= 8.1.$(CI_BUILD_NUMBER) 3 | 4 | version: 5 | @echo $(VERSION) 6 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | #### Related issues 2 | Fixes PIVOTAL-xxx 3 | 4 | #### Description 5 | 6 | #### Screenshots (if applicable) 7 | -------------------------------------------------------------------------------- /assets/images/app_download/ios/download_de.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/ios/download_de.png -------------------------------------------------------------------------------- /assets/images/app_download/ios/download_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/ios/download_en.png -------------------------------------------------------------------------------- /assets/images/app_download/ios/download_es.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/ios/download_es.png -------------------------------------------------------------------------------- /assets/images/app_download/ios/download_fr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/ios/download_fr.png -------------------------------------------------------------------------------- /assets/images/app_download/ios/download_it.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/ios/download_it.png -------------------------------------------------------------------------------- /assets/images/app_download/ios/download_ja.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/ios/download_ja.png -------------------------------------------------------------------------------- /assets/images/app_download/ios/download_ko.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/ios/download_ko.png -------------------------------------------------------------------------------- /assets/images/app_download/ios/download_nl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/ios/download_nl.png -------------------------------------------------------------------------------- /assets/images/app_download/ios/download_pl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/ios/download_pl.png -------------------------------------------------------------------------------- /assets/images/app_download/ios/download_pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/ios/download_pt.png -------------------------------------------------------------------------------- /assets/images/app_download/ios/download_ru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/ios/download_ru.png -------------------------------------------------------------------------------- /assets/images/app_download/ios/download_th.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/ios/download_th.png -------------------------------------------------------------------------------- /assets/images/app_download/ios/download_tr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/ios/download_tr.png -------------------------------------------------------------------------------- /assets/images/app_download/android/download_de.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/android/download_de.png -------------------------------------------------------------------------------- /assets/images/app_download/android/download_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/android/download_en.png -------------------------------------------------------------------------------- /assets/images/app_download/android/download_es.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/android/download_es.png -------------------------------------------------------------------------------- /assets/images/app_download/android/download_fr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/android/download_fr.png -------------------------------------------------------------------------------- /assets/images/app_download/android/download_it.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/android/download_it.png -------------------------------------------------------------------------------- /assets/images/app_download/android/download_ja.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/android/download_ja.png -------------------------------------------------------------------------------- /assets/images/app_download/android/download_ko.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/android/download_ko.png -------------------------------------------------------------------------------- /assets/images/app_download/android/download_nl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/android/download_nl.png -------------------------------------------------------------------------------- /assets/images/app_download/android/download_pl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/android/download_pl.png -------------------------------------------------------------------------------- /assets/images/app_download/android/download_pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/android/download_pt.png -------------------------------------------------------------------------------- /assets/images/app_download/android/download_ru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/android/download_ru.png -------------------------------------------------------------------------------- /assets/images/app_download/android/download_th.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/android/download_th.png -------------------------------------------------------------------------------- /assets/images/app_download/android/download_tr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetuparchive/meetup-web-components/HEAD/assets/images/app_download/android/download_tr.png -------------------------------------------------------------------------------- /src/layout/__snapshots__/chunk.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Chunk exists 1`] = ` 4 |
7 | `; 8 | -------------------------------------------------------------------------------- /src/forms/__snapshots__/typeahead.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`TypeaheadItem exists 1`] = ` 4 |

5 | matters 6 |

7 | `; 8 | -------------------------------------------------------------------------------- /src/layout/__snapshots__/stripe.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Stripe exists 1`] = ` 4 |
7 | `; 8 | -------------------------------------------------------------------------------- /src/layout/__snapshots__/flex.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Flex exists 1`] = ` 4 |
7 | `; 8 | -------------------------------------------------------------------------------- /src/layout/__snapshots__/section.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Section exists 1`] = ` 4 |
7 | `; 8 | -------------------------------------------------------------------------------- /src/utils/components/ConditionalWrap.jsx: -------------------------------------------------------------------------------- 1 | const ConditionalWrap = ({ condition, wrap, children }) => 2 | condition ? wrap(children) : children; 3 | 4 | export default ConditionalWrap; 5 | -------------------------------------------------------------------------------- /src/layout/__snapshots__/bounds.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Bounds exists 1`] = ` 4 |
7 | `; 8 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "mwp-config/stylelint/stylelint-config-base", 4 | "mwp-config/stylelint/stylelint-config-swarmProject", 5 | "stylelint-config-prettier" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-knobs/register'; 2 | import '@storybook/addon-actions/register'; 3 | import '@storybook/addon-notes/register'; 4 | import '@storybook/addon-options/register'; -------------------------------------------------------------------------------- /src/types.js: -------------------------------------------------------------------------------- 1 | import { bool, shape } from 'prop-types'; 2 | 3 | export const Media = shape({ 4 | isAtSmallUp: bool, 5 | isAtMediumUp: bool, 6 | isAtLargeUp: bool, 7 | isAtHugeUp: bool, 8 | }); 9 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "es2015", 4 | "react", 5 | "flow", 6 | "stage-2" 7 | ], 8 | "plugins": [ 9 | "transform-class-properties", 10 | "react-docgen" 11 | ] 12 | } -------------------------------------------------------------------------------- /__mocks__/emptyString.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This module can be used to map certain module names to an empty string in 3 | * Jest if you just want the module to output an empty string 4 | */ 5 | module.exports = ''; 6 | -------------------------------------------------------------------------------- /util/setupTest.js: -------------------------------------------------------------------------------- 1 | require('raf/polyfill'); 2 | require('./jestSystemShim'); 3 | const Enzyme = require('enzyme'); 4 | const Adapter = require('enzyme-adapter-react-16'); 5 | 6 | Enzyme.configure({ adapter: new Adapter() }); 7 | -------------------------------------------------------------------------------- /flow-typed/npm/flow-bin_v0.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 6a5610678d4b01e13bbfbbc62bdaf583 2 | // flow-typed version: 3817bc6980/flow-bin_v0.x.x/flow_>=v0.25.x 3 | 4 | declare module "flow-bin" { 5 | declare module.exports: string; 6 | } 7 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ./build/* 3 | ./coverage/* 4 | ./node_modules/radium/* 5 | ./node_modules/stylelint/* 6 | .*.json 7 | ./node_modules/radium/* 8 | ./node_modules/@meetup/swarm-components/* 9 | 10 | [include] 11 | 12 | [libs] 13 | 14 | [options] 15 | -------------------------------------------------------------------------------- /src/forms/__snapshots__/charCounter.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`CharCounter exists 1`] = ` 4 |

8 | 60 9 |

10 | `; 11 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "useTabs": true, 4 | "semi": true, 5 | "singleQuote": true, 6 | "overrides": [ 7 | { 8 | "files": "assets/scss/**/*.scss", 9 | "options": { 10 | "singleQuote": false, 11 | "trailingComma": "none" 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /assets/scss/components/_chunk.scss: -------------------------------------------------------------------------------- 1 | /*doc 2 | --- 3 | title: Chunk 4 | --- 5 | Adds bottom space to an element 6 | or a group of elements. 7 | ``` 8 | */ 9 | 10 | %chunk, 11 | .chunk { 12 | @extend %clearfix; 13 | display: block; 14 | padding-bottom: var(--responsive-space) !important; 15 | } 16 | -------------------------------------------------------------------------------- /src/layout/__snapshots__/card.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Card and variants renders a card 1`] = ` 4 |
7 |

8 | Lorem Ipsum is simply dummy text of the printing and typesetting industry. 9 |

10 |
11 | `; 12 | -------------------------------------------------------------------------------- /src/forms/__snapshots__/timeInput.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`TimeInput TimeInput, with input[time] support renders a time html input with expected props 1`] = ` 4 | 10 | `; 11 | -------------------------------------------------------------------------------- /src/layout/chunk.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | 4 | import { ChunkComponent } from './Chunk'; 5 | 6 | describe('Chunk', function() { 7 | const chunk = shallow(); 8 | 9 | it('exists', function() { 10 | expect(chunk).toMatchSnapshot(); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /assets/scss/components/_adminBar.scss: -------------------------------------------------------------------------------- 1 | .groupAdminLinks { 2 | bottom: 0; 3 | padding: var(--space-1); 4 | position: fixed; 5 | right: 0; 6 | z-index: 9999; 7 | } 8 | 9 | .redbar { 10 | background-color: var(--c-red); 11 | width: 100%; 12 | } 13 | 14 | .greenbar { 15 | background-color: var(--c-teal); 16 | width: 100%; 17 | } 18 | -------------------------------------------------------------------------------- /assets/scss/util/_vars.scss: -------------------------------------------------------------------------------- 1 | // shadow for "interactive" elements, 2 | // like popover or dropdown menus 3 | $interactiveShadow: 0 2px 2px 0 $C_border, 0 3px 1px -2px $C_separator, 4 | 0 1px 5px 0 $C_border; 5 | $animate_easeOutQuad: cubic-bezier( 6 | 0.165, 7 | 0.84, 8 | 0.44, 9 | 1 10 | ); // stylelint-disable-line number-max-precision 11 | -------------------------------------------------------------------------------- /assets/scss/components/_infoToggle.scss: -------------------------------------------------------------------------------- 1 | .infoToggle { 2 | &-trigger { 3 | background-color: var(--c-textSecondary); 4 | border-radius: 50%; 5 | color: var(--c-white); 6 | font-size: 10px; 7 | height: 15px; 8 | width: 15px; 9 | } 10 | &-label { 11 | display: inline-block; 12 | margin-right: var(--space-quarter); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/forms/redux-form/RadioButtonGroup.jsx: -------------------------------------------------------------------------------- 1 | import { mapProps } from 'recompose'; 2 | 3 | import RadioButtonGroup from '../RadioButtonGroup'; 4 | 5 | export const propMapper = ({ input, meta, ...other }) => ({ 6 | selectedValue: input.value, 7 | ...input, 8 | ...other, 9 | }); 10 | 11 | export default mapProps(propMapper)(RadioButtonGroup); 12 | -------------------------------------------------------------------------------- /src/forms/redux-form/__snapshots__/checkbox.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`redux-form Textarea renders a Checkbox component with expected attributes from mock data, should be checked 1`] = ` 4 | 10 | `; 11 | -------------------------------------------------------------------------------- /src/layout/formSection.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | 4 | import FormSection from './FormSection'; 5 | 6 | describe('FormSection', () => { 7 | it('exists and contains form section wrapping elements with proper attributes', () => { 8 | expect(shallow()).toMatchSnapshot(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /assets/scss/components/_tooltip.scss: -------------------------------------------------------------------------------- 1 | .tooltip-bubble { 2 | background-color: $C_darkGray; 3 | 4 | &::after { 5 | border-bottom-color: $C_darkGray; 6 | border-top-color: $C_darkGray; 7 | } 8 | } 9 | 10 | .tooltip-closeBtn { 11 | float: right; 12 | padding: 5px !important; 13 | 14 | .svg-icon { 15 | height: 24px; 16 | width: 24px; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/__snapshots__/accentHeader.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`AccentHeader exists 1`] = ` 4 |
7 |

13 | Test 14 |

15 |
16 | `; 17 | -------------------------------------------------------------------------------- /src/forms/__snapshots__/button.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Button is a HTML button element exists 1`] = ` 4 | 13 | `; 14 | -------------------------------------------------------------------------------- /src/forms/redux-form/__snapshots__/numberInput.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`redux-form NumberInput renders a NumberInput component with expected attributes from mock data 1`] = ` 4 | 10 | `; 11 | -------------------------------------------------------------------------------- /src/forms/redux-form/__snapshots__/timeInput.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`redux-form TimeInput renders a TimeInput component with expected attributes from mock data 1`] = ` 4 | 11 | `; 12 | -------------------------------------------------------------------------------- /src/forms/__snapshots__/toggleSwitch.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`ToggleSwitch basic renders checked toggle switch 1`] = ` 4 | 8 | `; 9 | 10 | exports[`ToggleSwitch basic renders inactive toggle switch 1`] = ` 11 | 14 | `; 15 | -------------------------------------------------------------------------------- /assets/scss/components/_dropdown.scss: -------------------------------------------------------------------------------- 1 | .dropdownMenu-item { 2 | border-bottom: 1px solid $C_border; 3 | box-sizing: border-box; 4 | cursor: pointer; 5 | justify-content: flex-start; 6 | padding: calc(var(--responsive-space) / 2); 7 | 8 | &:hover, 9 | &:focus { 10 | background-color: $C_coolGrayLight; 11 | } 12 | 13 | &:last-child { 14 | border-bottom: 0; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /__mocks__/base64-image-loader.js: -------------------------------------------------------------------------------- 1 | const base64String = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNNyA3YTUgNSAwIDEgMSAxMCAwQTUgNSAwIDAgMSA3IDd6bTUgN2MtNCAwLTkgMy41LTkgNiAwIC44MjguNjU2IDIgMiAyaDE0YzEuMzI4IDAgMi0xLjE3MiAyLTIgMC0yLjUtNS02LTktNnoiLz48L3N2Zz4='; 2 | 3 | module.exports = base64String; 4 | -------------------------------------------------------------------------------- /src/forms/redux-form/__snapshots__/togglePill.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`redux-form TogglePill renders a TogglePill component with expected attributes from mock data 1`] = ` 4 | 11 | Parenting! 12 | 13 | `; 14 | -------------------------------------------------------------------------------- /src/forms/redux-form/__snapshots__/textInput.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`redux-form TextInput renders a TextInput component with expected attributes from mock data 1`] = ` 4 | 12 | `; 13 | -------------------------------------------------------------------------------- /src/utils/a11yPassThrough.js: -------------------------------------------------------------------------------- 1 | import cx from 'classnames'; 2 | 3 | // needed to allow for a11y cases for screen readers with mutli step forms where inputs are 4 | // conditionally rendered 5 | export default (className = '') => 6 | cx('tw-pb-1 tw-block', { 7 | 'visibility--a11yHide': className.includes('visibility--a11yHide'), 8 | 'visibility--a11yShow': className.includes('visiblity--a11yShow'), 9 | }); 10 | -------------------------------------------------------------------------------- /assets/scss/components/_lockedBadge.scss: -------------------------------------------------------------------------------- 1 | .lockedBadge-container { 2 | border-radius: 8px; 3 | cursor: pointer; 4 | padding: 0; 5 | } 6 | 7 | .lockedBadge-label { 8 | font-size: 14px; 9 | line-height: 1.43; 10 | padding-left: 6px; 11 | } 12 | 13 | .lockedBadge-icon-container { 14 | display: inline-flex; 15 | } 16 | 17 | .lockedBadge-badge { 18 | align-items: center; 19 | display: flex; 20 | padding: 6px 8px; 21 | } 22 | -------------------------------------------------------------------------------- /src/forms/redux-form/__snapshots__/textarea.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`redux-form Textarea renders a Textarea component with expected attributes from mock data 1`] = ` 4 | 13 | `; 14 | -------------------------------------------------------------------------------- /util/sassRelativeImporter.js: -------------------------------------------------------------------------------- 1 | // node-sass importer to resolve path names locally of imports from 2 | // node_modules the same way css-loader does with ~ as a prefix 3 | // used in build:css to build css from sass 4 | 5 | const path = require('path'); 6 | 7 | module.exports = function(url, prev, done) { 8 | if (url[0] === '~') { 9 | url = path.resolve('node_modules', url.substr(1)); 10 | } 11 | return { file: url }; 12 | }; 13 | -------------------------------------------------------------------------------- /src/forms/redux-form/__snapshots__/RadioButtonGroup.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`redux-form RadioButtonGroup propMapper should map the props as expected 1`] = ` 4 | Object { 5 | "name": "test-name", 6 | "onBlur": "onBlur", 7 | "onChange": "onChange", 8 | "onFocus": "onFocus", 9 | "otherProp": "otherProp", 10 | "selectedValue": "test-value", 11 | "value": "test-value", 12 | } 13 | `; 14 | -------------------------------------------------------------------------------- /assets/svg/facebook.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/forms/redux-form/Checkbox.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Checkbox from '../Checkbox'; 3 | 4 | const ReduxFormCheckbox = props => { 5 | const { 6 | meta, // eslint-disable-line no-unused-vars 7 | input, 8 | ...other 9 | } = props; 10 | 11 | return ; 12 | }; 13 | 14 | ReduxFormCheckbox.displayName = 'ReduxFormCheckbox'; 15 | 16 | export default ReduxFormCheckbox; 17 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Runtime data 2 | pids 3 | *.pid 4 | *.seed 5 | 6 | # node-waf configuration 7 | .lock-wscript 8 | 9 | # Dependency directory 10 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 11 | node_modules 12 | 13 | .DS_Store 14 | coverage 15 | npm-debug.log 16 | .swo 17 | .swp 18 | .*.swp 19 | .npmrc 20 | 21 | # Generated icon library file 22 | /src/media/iconLibrary.story.jsx 23 | 24 | github_deploy_key 25 | -------------------------------------------------------------------------------- /assets/scss/components/_signup.scss: -------------------------------------------------------------------------------- 1 | .meetup-signupModal-wrapper { 2 | margin: $space $space-2; 3 | } 4 | 5 | .meetup-signupModal-facebook { 6 | background-color: $C_facebook; 7 | 8 | &:hover { 9 | background-color: $C_facebook; 10 | } 11 | } 12 | 13 | .meetup-signupModal-apple img { 14 | margin: -14px -14px; 15 | } 16 | 17 | .meetup-signupModal-apple div { 18 | align-items: center; 19 | } 20 | 21 | .meetup-signupModal-or { 22 | text-transform: uppercase; 23 | } 24 | -------------------------------------------------------------------------------- /src/forms/redux-form/__snapshots__/calendarComponent.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`redux-form Calendar Component renders a Calendar component with expected attributes from mock data 1`] = ` 4 | 14 | `; 15 | -------------------------------------------------------------------------------- /assets/scss/components/_bounds.scss: -------------------------------------------------------------------------------- 1 | /*doc 2 | --- 3 | title: Bounds 4 | --- 5 | Used as a non-visual content container that manages content measure. 6 | 7 | Centers children with auto margin, clears floats, applies 8 | padding, and sets a max-width. 9 | */ 10 | 11 | .bounds { 12 | @extend %clearfix; 13 | box-sizing: border-box; 14 | margin-left: auto; 15 | margin-right: auto; 16 | max-width: $bounds; 17 | width: 100%; 18 | } 19 | 20 | .bounds--wide { 21 | max-width: $bounds-wide; 22 | } 23 | -------------------------------------------------------------------------------- /assets/svg/email.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/forms/TypeaheadItem.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | /** 4 | * @module TypeaheadItem 5 | */ 6 | const TypeaheadItem = ({ value, className, children }) => children; 7 | 8 | export default TypeaheadItem; 9 | 10 | TypeaheadItem.propTypes = { 11 | value: PropTypes.oneOfType([ 12 | PropTypes.string, 13 | PropTypes.array, 14 | PropTypes.object, 15 | ]).isRequired, 16 | className: PropTypes.string, 17 | children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired, 18 | }; 19 | -------------------------------------------------------------------------------- /src/forms/__snapshots__/LockedBadge.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`LockedBadge renders locked badge with default styles 1`] = ` 4 | 9 | `; 10 | 11 | exports[`LockedBadge renders locked badge with neutral styles 1`] = ` 12 | 18 | `; 19 | -------------------------------------------------------------------------------- /flow-typed/npm/@storybook/addon-actions_v3.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 2f5b0f18c5b5b31b01f63163429685c7 2 | // flow-typed version: 5edd39ab2e/@storybook/addon-actions_v3.x.x/flow_>=v0.25.x 3 | 4 | declare module '@storybook/addon-actions' { 5 | declare type Action = (name: string) => (...args: Array) => void; 6 | declare type DecorateFn = (args: Array) => Array; 7 | 8 | declare module.exports: { 9 | action: Action, 10 | decorateAction(args: Array): Action; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /assets/scss/main.scss: -------------------------------------------------------------------------------- 1 | @import "~swarm-constants/dist/scss/colors"; 2 | 3 | @import url("//a248.e.akamai.net/secure.meetupstatic.com/s/fonts/402715706936963211631/graphik.css"); 4 | 5 | // sasstools CSS reset 6 | 7 | @import "~swarm-sasstools/scss/reset/all"; 8 | 9 | // all meetup-web-components component partials 10 | 11 | @import "./components/all"; 12 | 13 | // sasstools modifier classes 14 | 15 | @import "~swarm-sasstools/scss/modifierClasses/all"; 16 | 17 | // tailwind 18 | 19 | @import "../css/tailwind.min"; 20 | -------------------------------------------------------------------------------- /src/forms/timeInput.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TimeInput from './TimeInput'; 4 | 5 | describe('TimeInput', function() { 6 | const props = { 7 | name: 'time', 8 | value: '11:15', 9 | onChange: () => {}, 10 | required: true, 11 | }; 12 | 13 | describe('TimeInput, with input[time] support', () => { 14 | it('renders a time html input with expected props', function() { 15 | expect(shallow()).toMatchSnapshot(); 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Runtime data 2 | pids 3 | *.pid 4 | *.seed 5 | 6 | # node-waf configuration 7 | .lock-wscript 8 | 9 | # Dependency directory 10 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 11 | node_modules 12 | 13 | .DS_Store 14 | .sass-cache/ 15 | coverage 16 | lib 17 | .swo 18 | .swp 19 | .*.swp 20 | *.log 21 | .vscode/ 22 | .idea 23 | 24 | # Generated icon library file 25 | /src/media/iconLibrary.story.jsx 26 | 27 | # static build of storybook 28 | .storybook-out 29 | 30 | github_deploy_key 31 | -------------------------------------------------------------------------------- /src/utils/bindAll.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @function bindAll 3 | * helper for binding prototype methods to class context 4 | * 5 | * for example, instead of doing this in a class `constructor`: 6 | * `this.handleClick = this.handleClick.bind(this)` 7 | * 8 | * you can use `bindAll`: 9 | * ``` 10 | * bindAll(this, 11 | * handleClick, 12 | * someOtherMethod, 13 | * anotherMethod); 14 | * ``` 15 | */ 16 | const bindAll = (context, ...names) => { 17 | names.forEach(name => (context[name] = context[name].bind(context))); 18 | }; 19 | export default bindAll; 20 | -------------------------------------------------------------------------------- /src/forms/redux-form/checkbox.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import ReduxFormCheckbox from './Checkbox'; 4 | 5 | describe('redux-form Textarea', () => { 6 | const props = { 7 | input: { 8 | label: 'Do you want more?', 9 | name: 'want_more', 10 | value: true, 11 | }, 12 | }; 13 | 14 | it('renders a Checkbox component with expected attributes from mock data, should be checked', () => { 15 | const component = shallow(); 16 | expect(component).toMatchSnapshot(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /.eslintrc.airbnb.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | root: true, 3 | parser: 'babel-eslint', 4 | extends: ['airbnb', 'prettier', 'prettier/flowtype', 'prettier/react'], 5 | parserOptions: { 6 | ecmaVersion: 6, 7 | ecmaFeatures: { 8 | jsx: true, 9 | experimentalObjectRestSpread: true, 10 | }, 11 | sourceType: 'module', 12 | }, 13 | env: { 14 | browser: true, 15 | node: true, 16 | jest: true, 17 | jasmine: true, 18 | es6: true, 19 | }, 20 | plugins: ['flowtype', 'react', 'meetup'], 21 | rules: { 22 | 'no-tabs': 0, 23 | }, 24 | }; 25 | 26 | module.exports = config; 27 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: npm 9 | directory: "/" 10 | schedule: 11 | interval: daily 12 | commit-message: 13 | prefix: "chore" 14 | include: "scope" 15 | open-pull-requests-limit: 0 16 | -------------------------------------------------------------------------------- /src/forms/charCounter.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | 4 | import { CharCounter } from './CharCounter'; 5 | 6 | describe('CharCounter', () => { 7 | it('exists', () => { 8 | const component = shallow(); 9 | expect(component).toMatchSnapshot(); 10 | }); 11 | 12 | it('uses error color when over the character limit', () => { 13 | const component = shallow(); 14 | expect(component.prop('className')).toContain('text--error'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = tab 12 | indent_size = 4 13 | max_line_length = 90 14 | 15 | # We recommend you to keep these unchanged 16 | end_of_line = lf 17 | charset = utf-8 18 | trim_trailing_whitespace = true 19 | insert_final_newline = true 20 | 21 | [*.md] 22 | trim_trailing_whitespace = false 23 | 24 | [*.json] 25 | indent_style = space 26 | 27 | -------------------------------------------------------------------------------- /src/layout/__snapshots__/formSection.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`FormSection exists and contains form section wrapping elements with proper attributes 1`] = ` 4 |
7 | 12 | 15 |
19 | 20 | 21 |
22 | `; 23 | -------------------------------------------------------------------------------- /src/media/appBadges.story.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react'; 3 | 4 | import { decorateWithBasics, decorateWithInfo } from '../utils/decorators'; 5 | import AppBadges from './AppBadges'; 6 | 7 | storiesOf('Media/AppBadges', module) 8 | .addDecorator(decorateWithBasics) 9 | .addDecorator(decorateWithInfo) 10 | .add('default', () => ) 11 | .add('only Google Play button', () => ( 12 | 13 | )) 14 | .add('only App Store button', () => ); 15 | -------------------------------------------------------------------------------- /assets/svg/message.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/forms/__snapshots__/errorList.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`ErrorList matches snapshot for input without id 1`] = ` 4 |
    7 |
  • 10 | This is an error message 11 |
  • 12 |
13 | `; 14 | 15 | exports[`ErrorList matches snapshot for single error 1`] = ` 16 |
    20 |
  • 23 | This is an error message 24 |
  • 25 |
26 | `; 27 | -------------------------------------------------------------------------------- /assets/scss/components/_inlineblockList.scss: -------------------------------------------------------------------------------- 1 | %inlineblockList, 2 | .inlineblockList { 3 | margin: 0; 4 | padding: 0; 5 | 6 | > li { 7 | display: inline-block; 8 | padding-right: var(--responsive-space); 9 | 10 | &:last-child { 11 | padding-right: 0; 12 | } 13 | } 14 | } 15 | 16 | .inlineblockList--separated > li { 17 | padding-right: calc(var(--responsive-space) / 2); 18 | 19 | &::after { 20 | content: attr(data-separator); 21 | padding-left: calc(var(--responsive-space) / 2); 22 | speak: none; 23 | } 24 | 25 | &:last-child { 26 | &::after { 27 | display: none; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /flow-typed/design-system.js: -------------------------------------------------------------------------------- 1 | // a list of all constants related to design systems 2 | 3 | declare type MediaSizes = 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl' | 'xxl'; 4 | 5 | declare type MediaSizeMap = {| 6 | xxs: '12', 7 | xs: '16', 8 | s: '24', 9 | m: '36', 10 | l: '48', 11 | xl: '72', 12 | xxl: '120', 13 | |}; 14 | 15 | declare type MediaQuerySize = 'small' | 'medium' | 'large' | 'huge'; 16 | 17 | declare type MediaQueryMap = {| 18 | small: 'screen and (min-width: 440px)', 19 | medium: 'screen and (min-width: 640px)', 20 | large: 'screen and (min-width: 840px)', 21 | huge: 'screen and (min-width: 1024px)', 22 | |} -------------------------------------------------------------------------------- /flow-typed/npm/@alrra/travis-scripts_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: febad60289e1b817e6fddff33cc021b8 2 | // flow-typed version: <>/@alrra/travis-scripts_v3.0.1/flow_v0.76.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * '@alrra/travis-scripts' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module '@alrra/travis-scripts' { 17 | declare module.exports: any; 18 | } 19 | -------------------------------------------------------------------------------- /assets/scss/components/_toggleSwitch.scss: -------------------------------------------------------------------------------- 1 | .toggleSwitch { 2 | /* stylelint-disable */ 3 | /* stylelint disabling is a temporary solution to override styles from swarm ui */ 4 | &[data-swarm-toggle="unchecked"]:not(:disabled) { 5 | border-color: #707070 !important; 6 | [data-swarm-toggle-switch-disc] { 7 | border-color: inherit; 8 | margin-left: -1px; 9 | margin-top: 0; 10 | svg { 11 | fill: #707070 !important; 12 | } 13 | } 14 | } 15 | 16 | &[data-swarm-toggle="checked"] [data-swarm-toggle-switch-disc] { 17 | border-color: #707070; 18 | margin-top: 0; 19 | } 20 | /* stylelint-enable */ 21 | } 22 | -------------------------------------------------------------------------------- /src/forms/redux-form/RadioButtonGroup.test.jsx: -------------------------------------------------------------------------------- 1 | import { propMapper } from './RadioButtonGroup'; 2 | 3 | describe('redux-form RadioButtonGroup', () => { 4 | describe('propMapper', () => { 5 | it('should map the props as expected', () => { 6 | const input = { 7 | value: 'test-value', 8 | onChange: 'onChange', 9 | onBlur: 'onBlur', 10 | name: 'test-name', 11 | onFocus: 'onFocus', 12 | }; 13 | const meta = { 14 | error: 'error', 15 | }; 16 | expect( 17 | propMapper({ 18 | input, 19 | meta, 20 | otherProp: 'otherProp', 21 | }) 22 | ).toMatchSnapshot(); 23 | }); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/forms/__snapshots__/selectInput.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`SelectInput basic renders into the DOM 1`] = ` 4 | 36 | `; 37 | -------------------------------------------------------------------------------- /src/forms/redux-form/__snapshots__/selectInput.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`redux-form SelectInput renders a SelectInput component with expected attributes from mock data 1`] = ` 4 | 26 | `; 27 | -------------------------------------------------------------------------------- /assets/scss/util/_color-mappings.scss: -------------------------------------------------------------------------------- 1 | $C_accent: $C_blue; 2 | $C_secondary: #707070; 3 | $C_viridian: #00798a; 4 | $C_meetupRed: #e32359; 5 | 6 | $C_buttonBGNeutral: $C_coolGrayLightTransp; 7 | $C_buttonBGNeutral--disabled: transparentize($C_coolGrayLightTransp, 0.04); 8 | 9 | $C_buttonBGNeutralInverted: $C_borderInverted; 10 | $C_buttonBGNeutralInverted--disabled: transparentize($C_borderInverted, 0.17); 11 | 12 | $C_svgIcon: rgba(46, 62, 72, 0.75); 13 | $C_svgIconInverted: rgba(255, 255, 255, 0.7); 14 | 15 | :root { 16 | --color-meetup-red: #{$C_meetupRed} !important; 17 | --color-viridian: #{$C_viridian} !important; 18 | --color-gray-6: #{$C_secondary} !important; 19 | } 20 | -------------------------------------------------------------------------------- /src/forms/redux-form/numberInput.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import ReduxFormNumberInput from './NumberInput'; 4 | 5 | describe('redux-form NumberInput', function() { 6 | // props structured to match what redux-form provides to `component` 7 | const props = { 8 | meta: {}, 9 | input: { 10 | label: 'Number of internets', 11 | name: 'internets', 12 | value: 10, 13 | }, 14 | }; 15 | 16 | it('renders a NumberInput component with expected attributes from mock data', () => { 17 | const component = shallow(); 18 | expect(component).toMatchSnapshot(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /flow-typed/npm/classnames_v2.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: cf86673cc32d185bdab1d2ea90578d37 2 | // flow-typed version: 614bf49aa8/classnames_v2.x.x/flow_>=v0.25.x 3 | 4 | type $npm$classnames$Classes = 5 | | string 6 | | { [className: string]: * } 7 | | false 8 | | void 9 | | null; 10 | 11 | declare module "classnames" { 12 | declare module.exports: ( 13 | ...classes: Array<$npm$classnames$Classes | $npm$classnames$Classes[]> 14 | ) => string; 15 | } 16 | 17 | declare module "classnames/bind" { 18 | declare module.exports: $Exports<"classnames">; 19 | } 20 | 21 | declare module "classnames/dedupe" { 22 | declare module.exports: $Exports<"classnames">; 23 | } 24 | -------------------------------------------------------------------------------- /src/forms/LockedBadge.story.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react'; 3 | import { action } from '@storybook/addon-actions'; 4 | import { decorateWithBasics, decorateWithInfo } from '../utils/decorators'; 5 | 6 | import LockedBadge from './LockedBadge'; 7 | 8 | const callbackAction = () => action('Click event'); 9 | 10 | storiesOf('Forms/LockedBadge', module) 11 | .addDecorator(decorateWithBasics) 12 | .addDecorator(decorateWithInfo) 13 | .add('Default', () => ) 14 | .add('Neutral', () => ( 15 | 16 | )); 17 | -------------------------------------------------------------------------------- /src/forms/errorList.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ErrorList from './ErrorList'; 3 | import { shallow } from 'enzyme'; 4 | 5 | const MOCK_ERROR = 'This is an error message'; 6 | const MOCK_ERROR_ID = 'name'; 7 | 8 | describe('ErrorList', () => { 9 | const componentWithId = shallow( 10 | 11 | ); 12 | const componentWithoutId = shallow(); 13 | 14 | it('matches snapshot for single error', () => { 15 | expect(componentWithId).toMatchSnapshot(); 16 | }); 17 | it('matches snapshot for input without id', () => { 18 | expect(componentWithoutId).toMatchSnapshot(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /src/navigation/components/notifications/__snapshots__/NotificationsDropdown.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Notifications Dropdown should match the snapshot with an empty notifications 1`] = ` 4 |
7 |

10 | 11 |

12 | `; 13 | 14 | exports[`Notifications Dropdown should match the snapshot with notifications 1`] = ` 15 |
18 |

21 | 22 |

23 | `; 24 | -------------------------------------------------------------------------------- /src/forms/redux-form/textarea.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import ReduxFormTextarea from './Textarea'; 4 | 5 | describe('redux-form Textarea', () => { 6 | const formAttrs = { 7 | input: { 8 | id: 'heroField', 9 | label: 'Super Hero', 10 | name: 'superhero', 11 | value: 'Wonder Woman and Robin', 12 | maxLength: 20, 13 | required: true, 14 | }, 15 | meta: { 16 | error: 'Did you mean Batman and Robin?', 17 | }, 18 | }; 19 | 20 | it('renders a Textarea component with expected attributes from mock data', () => { 21 | const component = shallow(); 22 | expect(component).toMatchSnapshot(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /src/navigation/components/groupDraftItem/__snapshots__/GroupDraftItem.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Profile Dropdown should match snapshot 1`] = ` 4 |
  • 8 |

    9 | Name of the group 10 |

    11 |
    12 | 13 | In progress 14 | 15 | 19 | 20 | Finish group 21 | 22 | 23 | 28 | 29 |
    30 |
  • 31 | `; 32 | -------------------------------------------------------------------------------- /src/forms/redux-form/textInput.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import ReduxFormTextInput from './TextInput'; 4 | 5 | describe('redux-form TextInput', function() { 6 | const MOCK_ERROR = 'Did you mean Batman and Robin?'; 7 | const formAttrs = { 8 | input: { 9 | label: 'Super Hero', 10 | name: 'superhero', 11 | value: 'Wonder Woman and Robin', 12 | maxLength: 20, 13 | required: true, 14 | }, 15 | meta: { 16 | error: MOCK_ERROR, 17 | }, 18 | }; 19 | 20 | it('renders a TextInput component with expected attributes from mock data', () => { 21 | const component = shallow(); 22 | expect(component).toMatchSnapshot(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /src/utils/components/__snapshots__/toggleWrapper.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`withLoading when this.props.type is checkbox matches snapshot 1`] = ` 4 | 8 | 9 | 10 | `; 11 | 12 | exports[`withLoading when this.props.type is not checkbox or radio matches snapshot 1`] = ` 13 | 17 | 18 | 19 | `; 20 | 21 | exports[`withLoading when this.props.type is radio matches snapshot 1`] = ` 22 | 26 | 27 | 28 | `; 29 | -------------------------------------------------------------------------------- /src/forms/__snapshots__/radioButtonGroup.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`RadioButtonGroup should match the snapshot 1`] = ` 4 | 8 | 12 | 19 | 20 | 24 | 31 | 32 | 33 | `; 34 | -------------------------------------------------------------------------------- /src/forms/redux-form/timeInput.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import ReduxFormTimeInput from './TimeInput'; 4 | 5 | describe('redux-form TimeInput', function() { 6 | // props given in the structure that 7 | // redux form would 8 | const reduxFormProps = { 9 | input: { 10 | label: 'What time is it?', 11 | name: 'partytime', 12 | value: '22:00', 13 | required: true, 14 | }, 15 | meta: { 16 | error: 'Now approaching midnight!!?', 17 | }, 18 | }; 19 | 20 | it('renders a TimeInput component with expected attributes from mock data', () => { 21 | const component = shallow(); 22 | 23 | expect(component).toMatchSnapshot(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/layout/bounds.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | 4 | import { BoundsComponent } from './Bounds'; 5 | 6 | const WIDE_CLASS = 'bounds--wide'; 7 | 8 | describe('Bounds', function() { 9 | const bounds = shallow(); 10 | 11 | it('exists', function() { 12 | expect(bounds).toMatchSnapshot(); 13 | }); 14 | it(`check that default component has '${WIDE_CLASS}' class`, function() { 15 | expect(bounds.find(`.${WIDE_CLASS}`).length).not.toBe(0); 16 | }); 17 | it("check that narrow component does not have the 'bounds--wide' class", function() { 18 | const boundsNarrow = shallow(); 19 | expect(boundsNarrow.find(`.${WIDE_CLASS}`).length).toBe(0); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /src/forms/CharCounter.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | import cx from 'classnames'; 4 | import DeprecationWarning from '../utils/components/DeprecationWarning'; 5 | 6 | export const CharCounter = ({ maxLength, valueLength }) => { 7 | const remainingChars = maxLength - valueLength; 8 | 9 | const classNames = cx('text--tiny', 'text--secondary', 'align--right', 'charCount', { 10 | 'text--error': remainingChars < 0, 11 | }); 12 | 13 | return ( 14 |

    15 | {remainingChars} 16 |

    17 | ); 18 | }; 19 | 20 | CharCounter.propTypes = { 21 | maxLength: PropTypes.number.isRequired, 22 | valueLength: PropTypes.number.isRequired, 23 | }; 24 | 25 | export default DeprecationWarning(CharCounter); 26 | -------------------------------------------------------------------------------- /jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "collectCoverageFrom": [ 3 | "src/**/*.{js,jsx}", 4 | "!**/{node_modules,lib,coverage,assets,utils}/**", 5 | "!**/*.story.{js,jsx}" 6 | ], 7 | "coverageDirectory": "/coverage", 8 | "setupFiles": [ 9 | "/util/setupTest.js" 10 | ], 11 | "moduleFileExtensions": [ 12 | "js", 13 | "jsx" 14 | ], 15 | "moduleNameMapper": { 16 | "\\.(ico|inc|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/__mocks__/emptyString.js" 17 | }, 18 | "testRegex": "src/.*\\.test\\.jsx?$", 19 | "transformIgnorePatterns": [ 20 | "node_modules(?!\/meetup-web-components)" 21 | ], 22 | "snapshotSerializers": [ 23 | "/node_modules/enzyme-to-json/serializer" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/forms/redux-form/calendarComponent.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import ReduxFormCalendarComponent from './CalendarComponent'; 4 | 5 | describe('redux-form Calendar Component', function() { 6 | const attrs = { 7 | input: { 8 | id: 'beyonce', 9 | name: 'halo', 10 | className: 'beyonce-halo', 11 | value: new Date(2012, 9, 12), 12 | }, 13 | meta: { 14 | error: 'pick a different album', 15 | }, 16 | onFocus: jest.fn(), 17 | onBlur: jest.fn(), 18 | onChange: jest.fn(), 19 | }; 20 | 21 | it('renders a Calendar component with expected attributes from mock data', () => { 22 | const component = shallow(); 23 | expect(component).toMatchSnapshot(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /assets/scss/components/_accentHeader.scss: -------------------------------------------------------------------------------- 1 | .accentHeader, 2 | .accentHeaderWrapper { 3 | padding-bottom: calc(var(--responsive-space) * 2); 4 | } 5 | 6 | .accentHeader { 7 | font-size: $font-size-big2; 8 | position: relative; 9 | 10 | &::after { 11 | background-color: $C_blue; 12 | bottom: 0; 13 | content: ""; 14 | height: 3px; 15 | position: absolute; 16 | width: calc(var(--responsive-space) * 2); 17 | } 18 | 19 | @include atMediaUp(medium) { 20 | font-size: $font-size-title; 21 | } 22 | } 23 | 24 | .accentHeader--left { 25 | &::after { 26 | left: 0; 27 | } 28 | } 29 | 30 | .accentHeader--right { 31 | &::after { 32 | right: 0; 33 | } 34 | } 35 | 36 | .accentHeader--center { 37 | &::after { 38 | left: 50%; 39 | transform: translateX(-50%); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/interactive/__snapshots__/toast.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Toast renders into the DOM 1`] = ` 4 |
    10 | 14 | 20 | 27 | Your toast is ready 28 | 29 | 30 | 31 |
    32 | `; 33 | -------------------------------------------------------------------------------- /__mocks__/textContentMocks.js: -------------------------------------------------------------------------------- 1 | export const textContent1 = 'Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source.'; 2 | export const textContent2 = 'Classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source.'; 3 | -------------------------------------------------------------------------------- /src/forms/errorList.story.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ErrorList from './ErrorList'; 3 | import Bounds from '../layout/Bounds'; 4 | import { decorateWithInfo } from '../utils/decorators'; 5 | import { storiesOf } from '@storybook/react'; 6 | 7 | storiesOf('Forms/ErrorList', module) 8 | .addDecorator(decorateWithInfo) 9 | .addParameters({ info: { propTablesExclude: [Bounds] } }) 10 | .add( 11 | 'Single Error', 12 | () => ( 13 | 14 | 15 | 16 | ), 17 | { 18 | info: { 19 | text: 20 | 'ErrorList ensures the error container is always rendered with ARIA attributes. It is rendered using the `withErrorList` higher-order component', 21 | }, 22 | } 23 | ); 24 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure, setAddon } from '@storybook/react'; 2 | import '../assets/scss/storybook.scss'; 3 | import infoAddon from '@storybook/addon-info'; 4 | import { setOptions } from '@storybook/addon-options'; 5 | 6 | import '@meetup/swarm-styles/dist/global.css'; 7 | import '@meetup/swarm-styles/dist/main.css'; 8 | 9 | const componentStories = require.context('../src', true, /\.story\.jsx$/); 10 | 11 | function loadStories() { 12 | componentStories.keys().forEach(componentStories); 13 | } 14 | 15 | setAddon(infoAddon); 16 | 17 | // Storybook runtime configuration 18 | setOptions({ 19 | name: 'Meetup Web Components', 20 | // url the button will take people to 21 | url: 'https://meetup.github.io/swarm-design-system', 22 | showStoriesPanel: true, 23 | showAddonPanel: true, 24 | }); 25 | 26 | configure(loadStories, module); 27 | -------------------------------------------------------------------------------- /src/forms/redux-form/selectInput.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import ReduxFormSelectInput from './SelectInput'; 4 | 5 | describe('redux-form SelectInput', () => { 6 | const testOptions = [ 7 | { label: 'One', value: '1' }, 8 | { label: 'Two', value: '2' }, 9 | { label: 'Three', value: '3' }, 10 | ]; 11 | const formAttrs = { 12 | required: true, 13 | meta: { 14 | touched: false, 15 | error: 'Did you mean Batman and Robin?', 16 | }, 17 | input: { 18 | label: 'Countries', 19 | name: 'formSelectCountries', 20 | options: testOptions, 21 | }, 22 | }; 23 | 24 | it('renders a SelectInput component with expected attributes from mock data', () => { 25 | const component = shallow(); 26 | expect(component).toMatchSnapshot(); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /assets/scss/components/_footer.scss: -------------------------------------------------------------------------------- 1 | .footerStripe--main, 2 | .footerStripe-legal { 3 | -webkit-font-smoothing: antialiased; 4 | -moz-osx-font-smoothing: grayscale; 5 | } 6 | 7 | .footerStripe-main { 8 | background-color: $C_darkGray; 9 | } 10 | 11 | .footerStripe-main--isLight { 12 | background-color: $C_collectionBG; 13 | } 14 | 15 | .footerList-legal li::after { 16 | content: ""; 17 | 18 | @include atMediaUp(medium) { 19 | content: attr(data-separator); 20 | } 21 | } 22 | 23 | .footerStripe-legal { 24 | background-color: darken($C_darkGray, 03%); 25 | } 26 | 27 | .footerStripe-legal--isLight { 28 | background-color: darken($C_collectionBG, 03%); 29 | } 30 | 31 | .bounds--footer { 32 | max-width: 320px; 33 | 34 | @include atMediaUp(medium) { 35 | max-width: $bounds-wide; 36 | } 37 | } 38 | 39 | .footer-item { 40 | padding-bottom: $space-half; 41 | } 42 | -------------------------------------------------------------------------------- /src/utils/storyComponents.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | /** 4 | * Inverted 5 | * 6 | * Creates an inverted stripe for use in a story 7 | */ 8 | export const Inverted = props => ( 9 |
    19 | {props.children} 20 |
    21 | ); 22 | 23 | /** 24 | * StoryLink 25 | * 26 | * `Link` component for use in stories 27 | * where a router context is not necessary 28 | * 29 | * Also disables link from being followed on click 30 | */ 31 | export const StoryLink = props => ( 32 | 37 | {props.children} 38 | 39 | ); 40 | -------------------------------------------------------------------------------- /assets/scss/components/_radio.scss: -------------------------------------------------------------------------------- 1 | .radio-container { 2 | align-items: center; 3 | display: flex; 4 | input { 5 | display: none; 6 | } 7 | } 8 | 9 | .radio { 10 | align-items: center; 11 | border: 1px solid $C_secondary; 12 | border-radius: 50%; 13 | box-sizing: border-box; 14 | cursor: pointer; 15 | display: flex; 16 | height: 19px; 17 | justify-content: center; 18 | margin: 0 $space-half 0 0; 19 | width: 19px; 20 | 21 | @include browser-lessThanIE(10) { 22 | top: $space / 2; 23 | } 24 | 25 | &.checked { 26 | background-color: $C_viridian; 27 | } 28 | &.disabled { 29 | background-color: var(--color-gray-3); 30 | border-color: var(--color-gray-3); 31 | span { 32 | background-color: var(--color-gray-3); 33 | } 34 | } 35 | } 36 | 37 | .radio-indicator { 38 | background-color: white; 39 | display: block; 40 | height: 7px; 41 | width: 7px; 42 | } 43 | -------------------------------------------------------------------------------- /src/forms/__snapshots__/inputTime.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`InputTime InputTime, with input[time] support renders a with expected props 1`] = ` 4 |
    5 | 14 |
    15 | `; 16 | 17 | exports[`InputTime InputTime, with input[time] support renders error state as expected 1`] = ` 18 |
    19 | 30 |
    31 | `; 32 | -------------------------------------------------------------------------------- /src/utils/decorators.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { withInfo } from '@storybook/addon-info'; 3 | 4 | export const decorateWithBasics = story => { 5 | /* 6 | * -- Inline SVG icon sprite -- 7 | * 8 | * raw SVG sprite from `swarm-icons` 9 | */ 10 | const iconSpriteStyle = { display: 'none' }; 11 | const iconSprite = require('raw-loader!swarm-icons/dist/sprite/sprite.inc'); 12 | const styles = { 13 | display: 'flex', 14 | alignItems: 'center', 15 | justifyContent: 'center', 16 | height: '100%', 17 | width: '100%', 18 | }; 19 | 20 | return ( 21 |
    22 |
    26 | {story()} 27 |
    28 | ); 29 | }; 30 | 31 | export const decorateWithInfo = (story, context) => 32 | withInfo(`${context.story} ${context.kind}`)(story)(context); 33 | -------------------------------------------------------------------------------- /assets/svg/proDashboard.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/forms/radioButton.story.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react'; 3 | import { decorateWithBasics, decorateWithInfo } from '../utils/decorators'; 4 | import { withKnobs, text, boolean } from '@storybook/addon-knobs'; 5 | 6 | import RadioButton from './RadioButton'; 7 | 8 | storiesOf('Forms/RadioButton', module) 9 | .addDecorator(withKnobs) 10 | .addDecorator(decorateWithBasics) 11 | .addDecorator(decorateWithInfo) 12 | .add( 13 | 'Basic usage', 14 | () => ( 15 | 23 | ), 24 | { 25 | info: { 26 | text: 'A single radio input with a label. Demonstrates the basic usage', 27 | }, 28 | } 29 | ); 30 | -------------------------------------------------------------------------------- /src/media/__snapshots__/loading.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Loading exists 1`] = ` 4 |
    12 | 23 | 27 | Loading 28 | 29 | 39 | 40 |
    41 | `; 42 | -------------------------------------------------------------------------------- /src/utils/components/__snapshots__/withLoading.test.jsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`withLoading matches snapshot with 0 children 1`] = ``; 4 | 5 | exports[`withLoading matches snapshot with 1 child 1`] = ` 6 | 7 | 8 | World 9 | 10 | 11 | `; 12 | 13 | exports[`withLoading matches snapshot with 2 children 1`] = ` 14 | 15 | 16 | Hello 17 | 18 | 19 | World 20 | 21 | 22 | `; 23 | 24 | exports[`withLoading matches snapshot with isLoading 1`] = ` 25 | 29 | 36 | 37 | `; 38 | -------------------------------------------------------------------------------- /assets/scss/components/_checkbox.scss: -------------------------------------------------------------------------------- 1 | .checkbox-container { 2 | align-items: center; 3 | display: flex; 4 | 5 | input { 6 | display: none; 7 | } 8 | } 9 | 10 | .checkbox { 11 | align-items: center; 12 | background-color: white; 13 | border: 1px solid $C_secondary; 14 | border-radius: 4px; 15 | box-sizing: border-box; 16 | cursor: pointer; 17 | display: flex; 18 | font-size: $font-size; 19 | height: 20px; 20 | justify-content: center; 21 | line-height: $line-height; 22 | margin: 0 8px 0 0 !important; 23 | width: 20px; 24 | 25 | @include browser-lessThanIE(10) { 26 | top: $space / 2; 27 | } 28 | 29 | &:disabled { 30 | background-color: var(--color-gray-3); 31 | border: 1px solid var(--color-gray-3); 32 | } 33 | } 34 | 35 | .checkbox:focus { 36 | outline: 1px solid black; 37 | } 38 | 39 | [data-swarm-checkbox]:focus-within > span:first-of-type { 40 | box-shadow: 0 0 1px 2px #426b8f !important; 41 | } 42 | -------------------------------------------------------------------------------- /src/forms/redux-form/Textarea.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import Textarea from '../Textarea'; 4 | 5 | /** 6 | * This component wraps the standard Textarea component for use with redux-form. 7 | * It deconstructs props that redux-form sets and re-sets them on Textarea. 8 | * @param {object} props React component props 9 | * @return {React.Component} Textarea 10 | */ 11 | const ReduxFormTextarea = props => { 12 | const { meta, input, ...other } = props; 13 | const error = meta.touched || meta.submitFailed ? meta.error : null; 14 | 15 | return