From 53bde8c3f9c4668e62dbd2c670aaacc2bd820427 Mon Sep 17 00:00:00 2001 From: Andy Peatling Date: Fri, 20 Nov 2015 07:54:14 -0800 Subject: [PATCH] Initial commit of wp-calypso Props to the following people whose hard work has gotten us here. @aduth @mtias @scruffian @timmyc @rads @rralian @drewblaisdell @blowery @stephanethomas @ebinnion @gcorne @lezama @bluefuton @retrofox @ehg @dzver @isaackeyet @enej @kellychoffman @johnHackworth @jonathansadowski @shaunandrews @apeatling @ockham @breezyskies @sirbrillig @mcsf @gziolo @seear @adambbecker @fabianapsimoes @roccotripaldi @melchoyce @beaulebens @jancavan @rase- @umurkontaci @mattsherman @mattm @jkudish @dmsnell @folletto @yoavf @johngodley @janm6k @jblz @nb @fredrocious @dllh @omarjackman @mjangda @deBhal @nprasath002 @matthusby @allendav @rodrigoi @akirk @rickybanister @kwight @justinkropp @mattwiebe @gravityrail @drw158 @hewsut @codebykat @kateray @alternatekev @klimeryk @jasmussen @hafizrahman @TooTallNate @justinshreve @lucasartoni @spncrb @lancewillett @peterbutler @skeltoac @dbspringer @mikeshelton1503 @zinigor @Tsarp @artpi @mdawaffe @scottsweb @michaeldcain @gwwar @jenial @Tug @jeremylduvall @jeffstieler @hugobaeta @xyu @bikedorkjon @beaucollins @danhauk @koke @bazza @wahjava --- .dockerignore | 2 + .editorconfig | 12 + .esformatter | 76 + .eslintignore | 2 + .eslintrc | 83 + .gitignore | 35 + .jsfmtrc | 75 + .npmrc | 2 + .rtlcssrc | 10 + CONTRIBUTING.md | 70 + CREDITS.md | 1174 ++++++++++ Dockerfile | 39 + LICENSE.md | 264 +++ Makefile | 152 ++ README.md | 161 ++ Vagrantfile | 11 + Vagrantfile-boot2docker | 29 + assets/stylesheets/README.md | 10 + assets/stylesheets/_components.scss | 301 +++ assets/stylesheets/editor.scss | 4 + assets/stylesheets/layout/_detail-page.scss | 148 ++ assets/stylesheets/layout/_main.scss | 475 ++++ assets/stylesheets/layout/_masterbar.scss | 335 +++ assets/stylesheets/layout/_overlay.scss | 204 ++ assets/stylesheets/layout/_sidebar.scss | 286 +++ .../sections/_billing-history.scss | 630 ++++++ assets/stylesheets/sections/_checkout.scss | 1077 ++++++++++ assets/stylesheets/sections/_devdocs.scss | 217 ++ .../stylesheets/sections/_domain-search.scss | 290 +++ .../sections/_keyboard-shortcuts.scss | 71 + assets/stylesheets/sections/_manage.scss | 28 + assets/stylesheets/sections/_menus.scss | 1034 +++++++++ .../stylesheets/sections/_notifications.scss | 59 + assets/stylesheets/sections/_nux-welcome.scss | 164 ++ assets/stylesheets/sections/_plugins.scss | 56 + .../sections/_post-relative-time-status.scss | 40 + .../stylesheets/sections/_posts-controls.scss | 83 + assets/stylesheets/sections/_posts.scss | 349 +++ assets/stylesheets/sections/_sharing.scss | 1175 ++++++++++ .../stylesheets/sections/_site-settings.scss | 221 ++ assets/stylesheets/sections/_sites.scss | 276 +++ assets/stylesheets/sections/_stats.scss | 1742 +++++++++++++++ assets/stylesheets/sections/_translator.scss | 102 + .../sections/_updated-confirmation.scss | 147 ++ assets/stylesheets/sections/_upgrades.scss | 340 +++ assets/stylesheets/shared/_animation.scss | 255 +++ assets/stylesheets/shared/_colors.scss | 40 + assets/stylesheets/shared/_dropdowns.scss | 124 ++ assets/stylesheets/shared/_extends.scss | 124 ++ assets/stylesheets/shared/_forms.scss | 409 ++++ assets/stylesheets/shared/_functions.scss | 11 + .../shared/_infinite-scroll-end.scss | 29 + assets/stylesheets/shared/_livechat.scss | 1019 +++++++++ assets/stylesheets/shared/_reset.scss | 78 + assets/stylesheets/shared/_toolbar-bulk.scss | 248 +++ assets/stylesheets/shared/_typography.scss | 26 + assets/stylesheets/shared/_utilities.scss | 26 + assets/stylesheets/shared/_welcome.scss | 65 + .../shared/mixins/_breakpoints.scss | 58 + assets/stylesheets/shared/mixins/_calc.scss | 6 + .../stylesheets/shared/mixins/_clear-fix.scss | 13 + .../shared/mixins/_dropdown-menu.scss | 62 + .../mixins/_hide-content-accessibly.scss | 12 + .../shared/mixins/_long-content-fade.scss | 61 + assets/stylesheets/shared/mixins/_mixins.scss | 9 + .../stylesheets/shared/mixins/_noticon.scss | 27 + .../shared/mixins/_placeholder.scss | 14 + .../shared/mixins/_stats-fade-text.scss | 17 + assets/stylesheets/style.scss | 50 + bin/bundler | 1 + bin/generate-devdocs-index | 1 + bin/get-i18n | 1 + bin/i18nlint | 1 + bin/list-assets | 1 + bin/live-reload | 13 + bin/pre-commit | 44 + bin/pre-push | 26 + bin/record-env | 19 + bin/run-all-tests | 87 + bin/run-tests | 10 + bin/update-dependency | 77 + client/README.md | 31 + client/accept-invite/actions.js | 23 + client/accept-invite/controller.js | 24 + client/accept-invite/index.js | 16 + .../invite-form-header/index.jsx | 23 + .../invite-form-header/style.scss | 16 + client/accept-invite/invite-header/index.jsx | 66 + .../accept-invite/invite-header/mock-data.js | 33 + client/accept-invite/invite-header/style.scss | 36 + .../accept-invite/logged-in-accept/index.jsx | 107 + .../accept-invite/logged-in-accept/style.scss | 37 + .../accept-invite/logged-out-invite/index.jsx | 15 + .../logged-out-invite/signup-form.jsx | 123 ++ .../logged-out-invite/style.scss | 4 + client/accept-invite/main.jsx | 96 + client/accept-invite/style.scss | 8 + client/analytics/Makefile | 11 + client/analytics/README.md | 117 + client/analytics/ad-tracking.js | 189 ++ client/analytics/index.js | 199 ++ client/analytics/super-props.js | 38 + client/analytics/test/analytics-tests.js | 68 + client/analytics/test/config.js | 7 + client/analytics/test/load-script.js | 10 + client/auth/Makefile | 7 + client/auth/controller.js | 34 + client/auth/index.js | 13 + client/auth/login.jsx | 156 ++ client/auth/style.scss | 161 ++ client/auth/test/login.jsx | 74 + client/boot/README.md | 21 + client/boot/index.js | 321 +++ client/components/README.md | 6 + client/components/accordion/Makefile | 7 + client/components/accordion/README.md | 32 + client/components/accordion/docs/example.jsx | 77 + client/components/accordion/index.jsx | 95 + client/components/accordion/section.jsx | 15 + client/components/accordion/style.scss | 133 ++ client/components/accordion/test/index.jsx | 89 + client/components/add-new-button/README.md | 23 + .../add-new-button/docs/example.jsx | 34 + client/components/add-new-button/index.jsx | 57 + client/components/add-new-button/style.scss | 46 + client/components/author-selector/README.md | 19 + client/components/author-selector/index.jsx | 290 +++ client/components/author-selector/style.scss | 79 + client/components/bulk-select/README.md | 22 + .../components/bulk-select/docs/example.jsx | 66 + client/components/bulk-select/index.jsx | 50 + client/components/bulk-select/style.scss | 28 + client/components/button-group/README.md | 20 + .../components/button-group/docs/example.jsx | 69 + client/components/button-group/index.jsx | 30 + client/components/button-group/style.scss | 45 + client/components/button/README.md | 24 + client/components/button/docs/example.jsx | 105 + client/components/button/index.jsx | 46 + client/components/button/style.scss | 216 ++ client/components/chart/README.md | 50 + client/components/chart/bar-container.jsx | 65 + client/components/chart/bar.jsx | 133 ++ client/components/chart/index.jsx | 161 ++ client/components/chart/label.jsx | 35 + client/components/chart/legend.jsx | 86 + client/components/chart/style.scss | 566 +++++ client/components/chart/tooltip.jsx | 47 + client/components/chart/x-axis.jsx | 107 + client/components/comment-button/README.md | 23 + .../comment-button/docs/example.jsx | 26 + client/components/comment-button/index.jsx | 47 + client/components/comment-button/style.scss | 23 + client/components/count/Makefile | 10 + client/components/count/README.md | 30 + client/components/count/docs/example.jsx | 28 + client/components/count/index.jsx | 21 + client/components/count/style.scss | 11 + client/components/count/test/index.jsx | 98 + .../data/activating-theme/README.md | 8 + .../components/data/activating-theme/index.js | 49 + client/components/data/cart/README.md | 28 + client/components/data/cart/index.jsx | 30 + .../data/category-list-data/README.md | 46 + .../data/category-list-data/index.jsx | 120 ++ client/components/data/checkout/README.md | 28 + client/components/data/checkout/index.jsx | 32 + .../components/data/current-theme/README.md | 8 + client/components/data/current-theme/index.js | 65 + .../data/domain-management/README.md | 67 + .../data/domain-management/dns/README.md | 48 + .../data/domain-management/dns/index.jsx | 74 + .../email-forwarding/README.md | 47 + .../email-forwarding/index.jsx | 57 + .../data/domain-management/email/README.md | 58 + .../data/domain-management/email/index.jsx | 88 + .../data/domain-management/index.jsx | 69 + .../domain-management/nameservers/README.md | 48 + .../domain-management/nameservers/index.jsx | 82 + .../primary-domain/README.md | 47 + .../primary-domain/index.jsx | 54 + .../domain-management/site-redirect/README.md | 47 + .../domain-management/site-redirect/index.jsx | 48 + .../data/domain-management/transfer/README.md | 48 + .../data/domain-management/transfer/index.jsx | 80 + .../data/domain-management/whois/README.md | 54 + .../data/domain-management/whois/index.jsx | 88 + .../data/email-followers-data/README.md | 18 + .../data/email-followers-data/index.jsx | 110 + .../components/data/followers-data/README.md | 18 + .../components/data/followers-data/index.jsx | 109 + .../media-library-selected-data/README.md | 30 + .../media-library-selected-data/index.jsx | 50 + .../components/data/media-list-data/Makefile | 8 + .../components/data/media-list-data/README.md | 33 + .../components/data/media-list-data/index.jsx | 85 + .../data/media-list-data/test/index.js | 3 + .../data/media-list-data/test/specs/utils.js | 43 + .../components/data/media-list-data/utils.js | 36 + .../data/media-validation-data/README.md | 30 + .../data/media-validation-data/index.jsx | 50 + .../data/page-templates-data/README.md | 41 + .../data/page-templates-data/index.jsx | 99 + .../data/post-counts-data/README.md | 28 + .../data/post-counts-data/index.jsx | 76 + .../data/post-formats-data/README.md | 30 + .../data/post-formats-data/index.jsx | 62 + .../data/preferences-data/README.md | 30 + .../data/preferences-data/index.jsx | 45 + client/components/data/purchases/README.md | 26 + .../purchases/edit-card-details/index.jsx | 57 + client/components/data/purchases/index.jsx | 43 + .../data/purchases/manage-purchase/index.jsx | 60 + .../data/sharing-connections-data/Makefile | 8 + .../data/sharing-connections-data/README.md | 40 + .../data/sharing-connections-data/index.jsx | 70 + .../sharing-connections-data/test/index.jsx | 132 ++ .../components/data/tag-list-data/README.md | 40 + .../components/data/tag-list-data/index.jsx | 71 + client/components/data/viewers-data/README.md | 18 + client/components/data/viewers-data/index.jsx | 100 + client/components/date-picker/README.md | 68 + client/components/date-picker/day.jsx | 121 ++ .../components/date-picker/docs/example.jsx | 75 + client/components/date-picker/index.jsx | 139 ++ client/components/date-picker/style.scss | 232 ++ client/components/dialog/README.md | 153 ++ client/components/dialog/dialog-base.jsx | 163 ++ client/components/dialog/index.jsx | 91 + client/components/dialog/style.scss | 83 + client/components/domains/README.md | 42 + .../domain-mapping-suggestion/index.jsx | 45 + .../domain-mapping-suggestion/style.scss | 40 + .../domains/domain-product-price/index.jsx | 37 + .../domains/domain-product-price/style.scss | 63 + .../domain-registration-suggestion/index.jsx | 62 + .../domains/domain-search-results/index.jsx | 157 ++ .../domains/domain-search-results/style.scss | 24 + .../domains/domain-suggestion/index.jsx | 68 + .../domains/domain-suggestion/style.scss | 90 + .../example-domain-suggestions/index.jsx | 123 ++ .../example-domain-suggestions/style.scss | 84 + .../domains/map-domain-step/index.jsx | 238 +++ .../domains/map-domain-step/style.scss | 56 + .../components/domains/map-domain/index.jsx | 89 + .../domains/register-domain-step/index.jsx | 438 ++++ .../domains/register-domain-step/style.scss | 41 + client/components/drop-zone/Makefile | 7 + client/components/drop-zone/README.md | 51 + client/components/drop-zone/docs/example.jsx | 72 + client/components/drop-zone/index.jsx | 176 ++ client/components/drop-zone/style.scss | 61 + client/components/drop-zone/test/index.jsx | 211 ++ .../components/email-verification/README.md | 21 + .../email-verification-notice.jsx | 163 ++ client/components/email-verification/index.js | 27 + client/components/emojify/README.md | 38 + client/components/emojify/index.jsx | 84 + client/components/emojify/style.scss | 10 + client/components/external-link/README.md | 35 + .../components/external-link/docs/example.jsx | 30 + client/components/external-link/index.jsx | 43 + client/components/external-link/style.scss | 6 + client/components/flag/README.md | 19 + client/components/flag/docs/example.jsx | 38 + client/components/flag/index.jsx | 29 + client/components/flag/style.scss | 31 + client/components/foldable-card/README.md | 43 + .../components/foldable-card/docs/example.jsx | 58 + client/components/foldable-card/index.jsx | 144 ++ client/components/foldable-card/style.scss | 165 ++ client/components/follow-button/README.md | 41 + client/components/follow-button/_style.scss | 95 + client/components/follow-button/button.jsx | 63 + .../components/follow-button/docs/example.jsx | 36 + client/components/follow-button/index.jsx | 66 + client/components/follow-button/style.scss | 64 + client/components/forms/README.md | 88 + .../forms/clipboard-button/README.md | 45 + .../forms/clipboard-button/docs/example.jsx | 43 + .../forms/clipboard-button/index.jsx | 58 + .../forms/counted-textarea/Makefile | 13 + .../forms/counted-textarea/README.md | 43 + .../forms/counted-textarea/docs/example.jsx | 41 + .../forms/counted-textarea/index.jsx | 81 + .../forms/counted-textarea/style.scss | 24 + .../forms/counted-textarea/test/index.jsx | 144 ++ client/components/forms/docs/example.jsx | 237 ++ client/components/forms/form-button/index.jsx | 45 + .../components/forms/form-button/style.scss | 4 + .../forms/form-buttons-bar/index.jsx | 21 + .../forms/form-buttons-bar/style.scss | 3 + .../components/forms/form-checkbox/index.jsx | 19 + .../forms/form-country-select/index.jsx | 41 + .../forms/form-country-select/style.scss | 9 + .../components/forms/form-fieldset/index.jsx | 19 + .../components/forms/form-fieldset/style.scss | 4 + .../forms/form-input-validation/index.jsx | 27 + .../forms/form-input-validation/style.scss | 25 + client/components/forms/form-label/index.jsx | 19 + client/components/forms/form-label/style.scss | 11 + client/components/forms/form-legend/index.jsx | 19 + .../components/forms/form-legend/style.scss | 8 + .../forms/form-password-input/index.jsx | 63 + .../forms/form-password-input/style.scss | 28 + .../forms/form-phone-input/Makefile | 13 + .../forms/form-phone-input/index.jsx | 158 ++ .../forms/form-phone-input/test/index.jsx | 76 + .../test/mock-countries-list-empty.js | 14 + .../test/mock-countries-list.js | 21 + client/components/forms/form-radio/index.jsx | 22 + client/components/forms/form-range/index.jsx | 49 + client/components/forms/form-range/style.scss | 66 + .../forms/form-section-heading/index.jsx | 19 + .../forms/form-section-heading/style.scss | 9 + client/components/forms/form-select/index.jsx | 19 + .../components/forms/form-select/style.scss | 9 + .../forms/form-setting-explanation/index.jsx | 19 + .../forms/form-setting-explanation/style.scss | 8 + .../components/forms/form-tel-input/index.jsx | 34 + .../forms/form-tel-input/style.scss | 13 + .../form-text-input-with-affixes/README.md | 18 + .../form-text-input-with-affixes/index.jsx | 41 + .../form-text-input-with-affixes/style.scss | 86 + .../forms/form-text-input/index.jsx | 44 + .../forms/form-text-input/style.scss | 41 + .../components/forms/form-textarea/index.jsx | 19 + client/components/forms/form-toggle/Makefile | 7 + client/components/forms/form-toggle/README.md | 32 + .../components/forms/form-toggle/compact.jsx | 27 + client/components/forms/form-toggle/index.jsx | 70 + .../components/forms/form-toggle/style.scss | 114 + .../forms/form-toggle/test/index.jsx | 105 + client/components/forms/language-selector.jsx | 56 + .../components/forms/multi-checkbox/Makefile | 7 + .../components/forms/multi-checkbox/README.md | 52 + .../components/forms/multi-checkbox/index.jsx | 66 + .../forms/multi-checkbox/test/index.jsx | 89 + client/components/forms/range/Makefile | 7 + client/components/forms/range/README.md | 38 + .../components/forms/range/docs/example.jsx | 44 + client/components/forms/range/index.jsx | 98 + client/components/forms/range/style.scss | 65 + client/components/forms/range/test/index.jsx | 52 + client/components/forms/select-opt-groups.jsx | 32 + .../components/forms/sortable-list/README.md | 71 + .../components/forms/sortable-list/index.jsx | 320 +++ .../components/forms/sortable-list/index.scss | 106 + client/components/forms/us-state-selector.jsx | 102 + client/components/gallery-shortcode/README.md | 103 + client/components/gallery-shortcode/index.jsx | 124 ++ client/components/gauge/README.md | 31 + client/components/gauge/docs/example.jsx | 26 + client/components/gauge/index.jsx | 91 + client/components/gauge/style.scss | 22 + client/components/gravatar/Makefile | 7 + client/components/gravatar/README.md | 23 + client/components/gravatar/index.jsx | 62 + client/components/gravatar/style.scss | 13 + client/components/gravatar/test/index.jsx | 73 + client/components/header-cake/README.md | 17 + .../components/header-cake/docs/example.jsx | 30 + client/components/header-cake/index.jsx | 54 + client/components/header-cake/style.scss | 53 + client/components/image-preloader/README.md | 41 + client/components/image-preloader/index.jsx | 106 + client/components/infinite-list/Makefile | 7 + client/components/infinite-list/README.md | 88 + client/components/infinite-list/index.jsx | 394 ++++ .../components/infinite-list/scroll-helper.js | 482 +++++ client/components/infinite-list/style.scss | 3 + .../infinite-list/test/scroll-helper.js | 626 ++++++ client/components/info-popover/README.md | 27 + .../components/info-popover/docs/example.jsx | 57 + client/components/info-popover/index.jsx | 71 + client/components/info-popover/style.scss | 22 + client/components/input-chrono/README.md | 40 + .../components/input-chrono/docs/example.jsx | 60 + client/components/input-chrono/index.jsx | 99 + client/components/input-chrono/style.scss | 34 + client/components/like-button/README.md | 50 + client/components/like-button/_style.scss | 64 + client/components/like-button/button.jsx | 99 + .../components/like-button/docs/example.jsx | 68 + client/components/like-button/icons.jsx | 39 + client/components/like-button/index.jsx | 83 + client/components/main/README.md | 22 + client/components/main/index.jsx | 17 + client/components/main/style.scss | 44 + .../mobile-back-to-sidebar/index.jsx | 31 + .../mobile-back-to-sidebar/style.scss | 27 + client/components/notices/docs/example.jsx | 55 + client/components/olark-chatbox/README.md | 36 + client/components/olark-chatbox/index.jsx | 122 ++ client/components/olark-chatbox/style.scss | 26 + client/components/overlay/README.md | 81 + client/components/overlay/overlay.jsx | 110 + client/components/overlay/package.json | 6 + client/components/overlay/toolbar.jsx | 111 + client/components/payment-logo/index.jsx | 20 + client/components/payment-logo/style.scss | 31 + .../components/plans/plan-actions/index.jsx | 305 +++ .../components/plans/plan-actions/style.scss | 168 ++ .../plans/plan-discount-message/index.jsx | 52 + .../plans/plan-discount-message/style.scss | 59 + .../plans/plan-feature-cell/index.jsx | 18 + .../plans/plan-feature-cell/style.scss | 45 + .../components/plans/plan-features/index.jsx | 73 + .../components/plans/plan-features/style.scss | 38 + client/components/plans/plan-header/index.jsx | 24 + .../components/plans/plan-header/style.scss | 185 ++ client/components/plans/plan-list/index.jsx | 92 + client/components/plans/plan-list/style.scss | 5 + client/components/plans/plan-nudge/index.jsx | 94 + .../components/plans/plan-nudge/preview.jsx | 57 + client/components/plans/plan-nudge/style.scss | 191 ++ client/components/plans/plan-price/index.jsx | 48 + client/components/plans/plan-price/style.scss | 84 + client/components/plans/plan/index.jsx | 211 ++ client/components/plans/plan/style.scss | 156 ++ .../components/plans/plans-compare/index.jsx | 172 ++ .../components/plans/plans-compare/style.scss | 10 + .../plans/site-specific-plan-details-mixin.js | 25 + client/components/popover/README.md | 73 + client/components/popover/docs/example.jsx | 106 + client/components/popover/index.jsx | 132 ++ client/components/popover/menu-item.jsx | 35 + client/components/popover/menu.jsx | 153 ++ client/components/popover/style.scss | 196 ++ client/components/post-excerpt/index.jsx | 31 + client/components/post-excerpt/style.scss | 37 + client/components/post-list-fetcher/index.jsx | 156 ++ client/components/post-schedule/README.md | 70 + client/components/post-schedule/clock.jsx | 185 ++ .../components/post-schedule/docs/example.jsx | 263 +++ .../post-schedule/header-controls.jsx | 50 + client/components/post-schedule/header.jsx | 85 + client/components/post-schedule/index.jsx | 222 ++ client/components/post-schedule/style.scss | 125 ++ client/components/post-schedule/utils.js | 62 + client/components/progress-bar/README.md | 29 + .../components/progress-bar/docs/example.jsx | 28 + client/components/progress-bar/index.jsx | 43 + client/components/progress-bar/style.scss | 28 + .../components/progress-indicator/README.md | 48 + .../components/progress-indicator/index.jsx | 48 + .../components/progress-indicator/style.scss | 217 ++ client/components/pulsing-dot/index.jsx | 27 + client/components/pulsing-dot/style.scss | 27 + client/components/rating/README.md | 27 + client/components/rating/docs/example.jsx | 27 + client/components/rating/index.jsx | 77 + client/components/rating/style.scss | 9 + client/components/resizable-iframe/README.md | 46 + client/components/resizable-iframe/index.jsx | 160 ++ client/components/root-child/Makefile | 11 + client/components/root-child/README.md | 36 + client/components/root-child/index.jsx | 46 + client/components/root-child/test/index.jsx | 102 + client/components/search-card/README.md | 5 + client/components/search-card/index.jsx | 43 + client/components/search-card/style.scss | 7 + client/components/search/Makefile | 11 + client/components/search/README.md | 43 + client/components/search/docs/example.jsx | 42 + client/components/search/index.jsx | 297 +++ client/components/search/style.scss | 186 ++ client/components/search/test/index.jsx | 63 + client/components/section-header/README.md | 38 + client/components/section-header/button.jsx | 34 + .../section-header/docs/example.jsx | 42 + client/components/section-header/index.jsx | 38 + client/components/section-header/style.scss | 49 + client/components/section-nav/Makefile | 11 + client/components/section-nav/README.md | 160 ++ .../components/section-nav/docs/example.jsx | 196 ++ client/components/section-nav/index.jsx | 175 ++ client/components/section-nav/item.jsx | 78 + client/components/section-nav/segmented.jsx | 74 + client/components/section-nav/style.scss | 377 ++++ client/components/section-nav/tabs.jsx | 175 ++ client/components/section-nav/test/index.jsx | 89 + client/components/segmented-control/README.md | 177 ++ .../segmented-control/docs/example.jsx | 139 ++ client/components/segmented-control/index.jsx | 226 ++ client/components/segmented-control/item.jsx | 51 + .../components/segmented-control/style.scss | 85 + client/components/select-dropdown/README.md | 192 ++ .../select-dropdown/docs/example.jsx | 108 + client/components/select-dropdown/index.jsx | 339 +++ client/components/select-dropdown/item.jsx | 58 + .../components/select-dropdown/separator.jsx | 15 + client/components/select-dropdown/style.scss | 184 ++ client/components/select/docs/example.jsx | 46 + client/components/shortcode/README.md | 61 + client/components/shortcode/data.jsx | 43 + client/components/shortcode/frame.jsx | 136 ++ client/components/shortcode/index.jsx | 83 + .../components/sidebar-navigation/README.md | 26 + .../components/sidebar-navigation/index.jsx | 38 + .../components/sidebar-navigation/style.scss | 13 + client/components/signup-form/README.md | 37 + client/components/signup-form/index.jsx | 398 ++++ client/components/signup-form/style.scss | 20 + .../README.md | 11 + .../child.js | 116 + .../index.js | 57 + client/components/site-icon/README.md | 24 + client/components/site-icon/package.json | 6 + client/components/site-icon/site-icon.jsx | 78 + client/components/site-icon/style.scss | 26 + .../components/site-selector-modal/README.md | 12 + .../components/site-selector-modal/index.jsx | 93 + .../components/site-selector-modal/style.scss | 8 + client/components/site-selector/README.md | 4 + client/components/site-selector/index.jsx | 203 ++ client/components/site-selector/style.scss | 165 ++ .../site-stats-sticky-link/README.md | 26 + .../site-stats-sticky-link/index.jsx | 60 + .../components/site-users-fetcher/index.jsx | 118 + .../components/site-users-fetcher/readme.md | 20 + client/components/sites-popover/README.md | 8 + client/components/sites-popover/index.jsx | 74 + client/components/sites-popover/style.scss | 90 + client/components/spinner/README.md | 45 + client/components/spinner/docs/example.jsx | 27 + client/components/spinner/index.jsx | 119 ++ client/components/spinner/style.scss | 128 ++ .../stat-update-indicator/README.md | 34 + .../stat-update-indicator/index.jsx | 69 + .../stat-update-indicator/style.scss | 15 + client/components/sticky-panel/index.jsx | 83 + client/components/sticky-panel/style.scss | 8 + client/components/timezone-dropdown/README.md | 36 + .../timezone-dropdown/docs/example.jsx | 47 + client/components/timezone-dropdown/index.jsx | 52 + .../components/timezone-dropdown/style.scss | 4 + client/components/tinymce/README.md | 170 ++ client/components/tinymce/i18n.js | 78 + client/components/tinymce/iframe.scss | 162 ++ client/components/tinymce/index.jsx | 454 ++++ .../tinymce/plugins/advanced/plugin.js | 84 + .../tinymce/plugins/advanced/style.scss | 58 + .../tinymce/plugins/calypso-alert/alert.jsx | 50 + .../tinymce/plugins/calypso-alert/plugin.jsx | 54 + .../tinymce/plugins/calypso-alert/style.scss | 5 + .../plugins/editor-button-analytics/plugin.js | 99 + .../tinymce/plugins/media/README.md | 15 + .../tinymce/plugins/media/drop-zone.jsx | 140 ++ .../tinymce/plugins/media/plugin.jsx | 648 ++++++ .../plugins/media/restrict-size/Makefile | 10 + .../plugins/media/restrict-size/index.js | 86 + .../plugins/media/restrict-size/test/index.js | 101 + .../tinymce/plugins/tabindex/plugin.js | 24 + .../plugins/touch-scroll-toolbar/plugin.js | 97 + .../plugins/wpcom-autoresize/plugin.js | 161 ++ .../tinymce/plugins/wpcom-charmap/charmap.jsx | 338 +++ .../tinymce/plugins/wpcom-charmap/plugin.js | 49 + .../tinymce/plugins/wpcom-charmap/style.scss | 47 + .../tinymce/plugins/wpcom-help/help-modal.jsx | 130 ++ .../tinymce/plugins/wpcom-help/plugin.js | 50 + .../tinymce/plugins/wpcom-help/style.scss | 51 + .../plugins/wpcom-view/gallery-view.jsx | 97 + .../tinymce/plugins/wpcom-view/plugin.js | 876 ++++++++ .../tinymce/plugins/wpcom-view/views.js | 109 + .../plugins/wpcom-view/views/embed/index.js | 105 + .../plugins/wpcom-view/views/embed/view.jsx | 117 + .../tinymce/plugins/wpcom/plugin.js | 664 ++++++ .../tinymce/plugins/wpeditimage/plugin.js | 688 ++++++ .../tinymce/plugins/wplink/dialog.jsx | 280 +++ .../tinymce/plugins/wplink/plugin.js | 190 ++ .../tinymce/plugins/wplink/style.scss | 23 + .../tinymce/plugins/wptextpattern/plugin.js | 183 ++ client/components/tinymce/style.scss | 1902 +++++++++++++++++ client/components/token-field/Makefile | 10 + client/components/token-field/README.md | 47 + .../components/token-field/docs/example.jsx | 52 + client/components/token-field/index.jsx | 446 ++++ client/components/token-field/style.scss | 120 ++ .../token-field/suggestions-list.jsx | 129 ++ .../components/token-field/test/fixtures.js | 45 + client/components/token-field/test/index.jsx | 416 ++++ .../token-field/test/token-field-wrapper.jsx | 42 + client/components/token-field/token-input.jsx | 53 + client/components/token-field/token.jsx | 42 + client/components/tooltip/index.jsx | 45 + client/components/tooltip/style.scss | 77 + .../components/track-input-changes/Makefile | 7 + .../components/track-input-changes/README.md | 28 + .../components/track-input-changes/index.jsx | 57 + .../track-input-changes/test/index.jsx | 119 ++ client/components/typography/README.md | 6 + client/components/typography/docs/example.jsx | 89 + .../upgrades/credit-card-form/README.md | 58 + .../upgrades/credit-card-form/index.jsx | 109 + .../upgrades/credit-card-form/style.scss | 88 + .../credit-card-number-input/README.md | 24 + .../credit-card-number-input/index.jsx | 22 + .../credit-card-number-input/style.scss | 25 + .../components/upgrades/google-apps/README.md | 41 + .../upgrades/google-apps/dialog/index.jsx | 260 +++ .../google-apps/dialog/product-details.jsx | 39 + .../upgrades/google-apps/dialog/users.jsx | 127 ++ .../components/upgrades/google-apps/index.jsx | 78 + client/components/user/index.jsx | 29 + client/components/user/style.scss | 21 + client/components/version/README.md | 39 + client/components/version/docs/example.jsx | 28 + client/components/version/index.jsx | 34 + client/components/version/style.scss | 12 + client/components/vertical-nav/README.md | 24 + client/components/vertical-nav/index.jsx | 16 + client/components/vertical-nav/item/index.jsx | 64 + .../components/vertical-nav/item/style.scss | 35 + client/components/vertical-nav/style.scss | 3 + client/components/web-preview/README.md | 10 + client/components/web-preview/index.jsx | 176 ++ client/components/web-preview/style.scss | 191 ++ client/components/web-preview/toolbar.jsx | 74 + client/components/wordpress-logo/index.jsx | 29 + client/config/.gitignore | 1 + client/config/README.md | 32 + client/config/regenerate.js | 60 + client/devdocs/Makefile | 8 + client/devdocs/README.md | 23 + client/devdocs/controller.js | 104 + client/devdocs/design/index.jsx | 224 ++ client/devdocs/design/style.scss | 72 + client/devdocs/doc.jsx | 103 + client/devdocs/form-state-examples/index.jsx | 57 + client/devdocs/index.js | 19 + client/devdocs/main.jsx | 170 ++ client/devdocs/service.js | 35 + client/devdocs/sidebar.jsx | 50 + client/devdocs/test/doc-test.jsx | 62 + client/layout/README.md | 10 + client/layout/community-translator/README.md | 16 + .../community-translator/invitation-utils.js | 218 ++ .../community-translator/invitation.jsx | 92 + .../layout/community-translator/launcher.jsx | 96 + client/layout/community-translator/style.scss | 118 + client/layout/error.jsx | 55 + client/layout/index.jsx | 118 + client/layout/logged-out-oauth.jsx | 19 + client/layout/logged-out.jsx | 38 + client/layout/masterbar-logged-out-menu.jsx | 29 + client/layout/masterbar-new-post.jsx | 109 + client/layout/masterbar-new-post.scss | 68 + client/layout/masterbar-sections-menu.jsx | 147 ++ client/layout/masterbar.jsx | 154 ++ client/layout/package.json | 6 + client/lib/abtest/README.md | 118 + client/lib/abtest/active-tests.js | 66 + client/lib/abtest/index.js | 246 +++ client/lib/accept/Makefile | 10 + client/lib/accept/README.md | 29 + client/lib/accept/dialog.jsx | 65 + client/lib/accept/index.js | 35 + client/lib/accept/style.scss | 4 + client/lib/accept/test/index.js | 81 + client/lib/accessible-focus/README.md | 8 + client/lib/accessible-focus/index.js | 28 + client/lib/account-password-data/index.js | 115 + client/lib/ads/Makefile | 11 + client/lib/ads/README.md | 202 ++ client/lib/ads/actions.js | 111 + client/lib/ads/earnings-store.js | 81 + client/lib/ads/settings-store.js | 110 + client/lib/ads/test/lib/mock-actions.js | 26 + client/lib/ads/test/lib/mock-earnings.js | 30 + client/lib/ads/test/lib/mock-settings.js | 17 + client/lib/ads/test/lib/mock-site.js | 31 + client/lib/ads/test/test-store.js | 71 + client/lib/ads/tos-store.js | 98 + client/lib/ads/utils.js | 20 + .../lib/application-passwords-data/README.md | 26 + .../lib/application-passwords-data/index.js | 99 + client/lib/billing-history-data/README.md | 4 + client/lib/billing-history-data/index.js | 74 + client/lib/cart-values/Makefile | 14 + client/lib/cart-values/cart-items.js | 697 ++++++ client/lib/cart-values/index.js | 119 ++ client/lib/cart-values/schema.json | 54 + client/lib/cart-values/test/abtest.js | 1 + .../lib/cart-values/test/lib/user-settings.js | 29 + client/lib/cart-values/test/lib/user.js | 27 + client/lib/cart-values/test/test.js | 119 ++ client/lib/cart/store/Makefile | 15 + client/lib/cart/store/cart-analytics.js | 26 + client/lib/cart/store/cart-synchronizer.js | 251 +++ client/lib/cart/store/index.js | 138 ++ client/lib/cart/store/test/abtest.js | 1 + .../cart/store/test/cart-synchronizer-test.js | 67 + client/lib/cart/store/test/fake-wpcom.js | 50 + .../lib/cart/store/test/lib/user-settings.js | 29 + client/lib/cart/store/test/lib/user.js | 27 + client/lib/comment-like-store/Makefile | 14 + client/lib/comment-like-store/actions.js | 76 + .../comment-like-store/comment-like-store.js | 216 ++ client/lib/comment-like-store/constants.js | 9 + .../test/comment-like-store-test.js | 163 ++ client/lib/comment-like-store/utils.js | 8 + client/lib/comment-store/Makefile | 14 + client/lib/comment-store/actions.js | 140 ++ client/lib/comment-store/comment-store.js | 438 ++++ client/lib/comment-store/constants.js | 16 + .../comment-store/test/comment-store-test.js | 121 ++ client/lib/comment-store/test/lib/wp.js | 14 + client/lib/comment-store/utils.js | 8 + .../lib/connected-applications-data/README.md | 20 + .../lib/connected-applications-data/index.js | 120 ++ client/lib/connections-list/README.md | 48 + client/lib/connections-list/index.js | 10 + client/lib/connections-list/list.js | 592 +++++ client/lib/countries-list/README.md | 34 + client/lib/countries-list/index.js | 188 ++ client/lib/credit-card-details/Makefile | 14 + client/lib/credit-card-details/README.md | 24 + client/lib/credit-card-details/index.js | 12 + client/lib/credit-card-details/masking.js | 81 + client/lib/credit-card-details/test/test.js | 40 + client/lib/credit-card-details/validation.js | 191 ++ client/lib/customize/muse.js | 23 + client/lib/data-poller/README.md | 47 + client/lib/data-poller/index.js | 70 + client/lib/data-poller/poller.js | 103 + client/lib/desktop/README.md | 30 + client/lib/desktop/index.js | 147 ++ client/lib/desktop/page-notifier.js | 30 + .../lib/detect-history-navigation/README.md | 19 + client/lib/detect-history-navigation/index.js | 17 + client/lib/deterministic-stringify/Makefile | 9 + client/lib/deterministic-stringify/README.md | 21 + client/lib/deterministic-stringify/index.js | 32 + .../lib/deterministic-stringify/test/test.js | 46 + client/lib/devices/README.md | 8 + client/lib/devices/index.js | 58 + client/lib/domains/Makefile | 12 + client/lib/domains/README.md | 39 + client/lib/domains/assembler.js | 83 + client/lib/domains/constants.js | 8 + client/lib/domains/dns/Makefile | 9 + client/lib/domains/dns/index.js | 87 + client/lib/domains/dns/reducer.js | 74 + client/lib/domains/dns/store.js | 19 + client/lib/domains/dns/test/index.js | 28 + client/lib/domains/email-forwarding/Makefile | 12 + .../lib/domains/email-forwarding/reducer.js | 124 ++ client/lib/domains/email-forwarding/store.js | 15 + .../email-forwarding/test/store-test.js | 123 ++ .../domains/google-apps-users/assembler.js | 12 + client/lib/domains/google-apps-users/index.js | 71 + .../lib/domains/google-apps-users/reducer.js | 46 + client/lib/domains/google-apps-users/store.js | 19 + client/lib/domains/index.js | 158 ++ client/lib/domains/nameservers/Makefile | 12 + client/lib/domains/nameservers/index.js | 37 + client/lib/domains/nameservers/reducer.js | 71 + client/lib/domains/nameservers/store.js | 15 + .../domains/nameservers/test/store-test.js | 95 + client/lib/domains/reducer.js | 119 ++ client/lib/domains/site-redirect/README.md | 25 + client/lib/domains/site-redirect/reducer.js | 105 + client/lib/domains/site-redirect/store.js | 19 + client/lib/domains/store.js | 11 + client/lib/domains/test/assembler-test.js | 85 + .../lib/domains/wapi-domain-info/assembler.js | 8 + .../lib/domains/wapi-domain-info/reducer.js | 97 + client/lib/domains/wapi-domain-info/store.js | 17 + client/lib/domains/whois/Makefile | 12 + client/lib/domains/whois/README.md | 33 + client/lib/domains/whois/assembler.js | 29 + client/lib/domains/whois/reducer.js | 73 + client/lib/domains/whois/store.js | 15 + .../lib/domains/whois/test/assembler-test.js | 110 + client/lib/domains/whois/test/store-test.js | 134 ++ client/lib/dss/README.md | 22 + client/lib/dss/actions.js | 59 + client/lib/dss/constants.js | 15 + client/lib/dss/image-store.js | 48 + client/lib/dss/preview-store.js | 29 + client/lib/email-followers/Makefile | 12 + client/lib/email-followers/README.md | 84 + client/lib/email-followers/actions.js | 61 + client/lib/email-followers/store.js | 181 ++ .../email-followers/test/lib/mock-actions.js | 45 + .../test/lib/mock-email-followers.js | 17 + .../test/lib/mock-more-email-followers.js | 17 + .../lib/email-followers/test/lib/mock-site.js | 31 + client/lib/email-followers/test/test-store.js | 91 + client/lib/embeds/README.md | 30 + client/lib/embeds/actions.js | 51 + client/lib/embeds/list-store.js | 82 + client/lib/embeds/store.js | 59 + client/lib/features-list/Makefile | 12 + client/lib/features-list/README.md | 16 + client/lib/features-list/index.js | 120 ++ client/lib/features-list/test/data.js | 47 + client/lib/features-list/test/lib/wp.js | 4 + client/lib/features-list/test/test.js | 38 + client/lib/feed-post-store/Makefile | 15 + client/lib/feed-post-store/README.md | 26 + client/lib/feed-post-store/actions.js | 89 + client/lib/feed-post-store/constants.js | 3 + client/lib/feed-post-store/display-types.js | 18 + client/lib/feed-post-store/index.js | 286 +++ .../feed-post-store/normalization-rules.js | 108 + .../lib/feed-post-store/post-batch-fetcher.js | 104 + .../test/feed-post-store-test.js | 144 ++ .../test/lib/post-normalizer.js | 22 + client/lib/feed-post-store/test/lib/wp.js | 20 + client/lib/feed-store/Makefile | 15 + client/lib/feed-store/actions.js | 36 + client/lib/feed-store/constants.js | 11 + client/lib/feed-store/index.js | 104 + .../lib/feed-store/test/feed-store-tests.js | 116 + client/lib/feed-store/test/lib/formatting.js | 7 + client/lib/feed-stream-store/Makefile | 15 + client/lib/feed-stream-store/actions.js | 174 ++ client/lib/feed-stream-store/constants.js | 13 + .../feed-stream-store/feed-stream-cache.js | 10 + client/lib/feed-stream-store/feed-stream.js | 523 +++++ client/lib/feed-stream-store/index.js | 159 ++ .../test/lib/post-normalizer.js | 22 + client/lib/feed-stream-store/test/lib/wp.js | 20 + .../test/post-list-store-tests.js | 368 ++++ client/lib/follow-list/Makefile | 12 + client/lib/follow-list/README.md | 41 + client/lib/follow-list/index.js | 38 + client/lib/follow-list/site.js | 61 + client/lib/follow-list/test/lib/wp.js | 33 + client/lib/follow-list/test/test.js | 81 + client/lib/followers/Makefile | 13 + client/lib/followers/README.md | 84 + client/lib/followers/actions.js | 60 + client/lib/followers/store.js | 181 ++ client/lib/followers/test/lib/mock-actions.js | 45 + client/lib/followers/test/lib/mock-site.js | 31 + .../test/lib/mock-wpcom-followers1.js | 23 + .../test/lib/mock-wpcom-followers2.js | 23 + client/lib/followers/test/test-store.js | 91 + client/lib/form-state/Makefile | 7 + client/lib/form-state/README.md | 4 + .../form-state/examples/async-initialize.jsx | 84 + .../form-state/examples/sync-initialize.jsx | 72 + client/lib/form-state/index.js | 366 ++++ .../lib/form-state/store/async-initialize.js | 42 + client/lib/form-state/store/core.js | 29 + client/lib/form-state/store/index.js | 78 + .../lib/form-state/store/sync-initialize.js | 36 + client/lib/form-state/test/index.js | 160 ++ client/lib/geocoding/Makefile | 10 + client/lib/geocoding/README.md | 16 + client/lib/geocoding/index.js | 24 + client/lib/geocoding/test/index.js | 42 + client/lib/google-apps/index.js | 12 + client/lib/happiness-engineers/Makefile | 11 + client/lib/happiness-engineers/README.md | 76 + client/lib/happiness-engineers/actions.js | 32 + client/lib/happiness-engineers/constants.js | 5 + client/lib/happiness-engineers/store.js | 37 + .../test/lib/mock-actions.js | 9 + .../test/lib/mock-happiness-engineers.js | 62 + .../happiness-engineers/test/test-actions.js | 22 + .../happiness-engineers/test/test-store.js | 47 + client/lib/help-search/Makefile | 12 + client/lib/help-search/README.md | 10 + client/lib/help-search/actions.js | 33 + client/lib/help-search/constants.js | 5 + client/lib/help-search/store.js | 37 + .../lib/help-search/test/lib/mock-actions.js | 9 + .../help-search/test/lib/mock-help-links.js | 27 + client/lib/help-search/test/test-store.js | 39 + client/lib/highlight/Makefile | 7 + client/lib/highlight/README.md | 17 + client/lib/highlight/index.js | 106 + client/lib/highlight/test/highlight-test.js | 77 + client/lib/human-date/index.js | 55 + client/lib/importer/actions.js | 127 ++ client/lib/importer/common.js | 75 + client/lib/importer/constants.js | 40 + client/lib/importer/store.js | 112 + client/lib/infinite-list/actions.js | 48 + client/lib/infinite-list/positions-store.js | 48 + client/lib/infinite-list/scroll-store.js | 35 + client/lib/inflight/index.js | 16 + client/lib/interpolate-components/Makefile | 7 + client/lib/interpolate-components/README.md | 40 + client/lib/interpolate-components/index.js | 130 ++ .../interpolate-components/test/lib/warn.js | 6 + .../lib/interpolate-components/test/text.jsx | 263 +++ client/lib/interpolate-components/tokenize.js | 33 + client/lib/invites/Makefile | 11 + client/lib/invites/actions.js | 52 + client/lib/invites/constants.js | 16 + .../invites/reducers/invites-validation.js | 27 + client/lib/invites/reducers/list-invites.js | 38 + .../lib/invites/stores/invites-validation.js | 12 + client/lib/invites/stores/list-invites.js | 11 + client/lib/invites/test/list-invites-store.js | 76 + client/lib/keyboard-shortcuts/Makefile | 12 + client/lib/keyboard-shortcuts/README.md | 68 + client/lib/keyboard-shortcuts/global.js | 92 + client/lib/keyboard-shortcuts/index.js | 166 ++ client/lib/keyboard-shortcuts/key-bindings.js | 187 ++ client/lib/keyboard-shortcuts/menu.jsx | 126 ++ .../test/lib/mixins/i18n.js | 16 + client/lib/keyboard-shortcuts/test/test.js | 58 + client/lib/layout-focus/README.md | 21 + client/lib/layout-focus/index.js | 129 ++ client/lib/like-store/Makefile | 15 + client/lib/like-store/actions.js | 124 ++ client/lib/like-store/like-store.js | 229 ++ client/lib/like-store/test/lib/wp.js | 13 + client/lib/like-store/test/like-store-test.js | 225 ++ client/lib/like-store/utils.js | 8 + client/lib/load-script/README.md | 28 + client/lib/load-script/index.js | 64 + client/lib/local-list/Makefile | 7 + client/lib/local-list/README.md | 65 + client/lib/local-list/index.js | 109 + client/lib/local-list/test/test.js | 165 ++ client/lib/local-storage/Makefile | 7 + client/lib/local-storage/README.md | 18 + client/lib/local-storage/index.js | 53 + client/lib/local-storage/test/test.js | 43 + client/lib/locale-suggestions/actions.js | 22 + client/lib/locale-suggestions/index.js | 40 + client/lib/media-serialization/Makefile | 12 + client/lib/media-serialization/constants.js | 15 + .../create-element-from-string.js | 20 + .../lib/media-serialization/detect-format.js | 39 + client/lib/media-serialization/index.js | 18 + .../lib/media-serialization/strategies/api.js | 41 + .../lib/media-serialization/strategies/dom.js | 74 + .../media-serialization/strategies/index.js | 8 + .../media-serialization/strategies/object.js | 9 + .../strategies/shortcode.js | 76 + .../media-serialization/strategies/string.js | 61 + .../media-serialization/strategies/unknown.js | 17 + client/lib/media-serialization/test/index.js | 137 ++ client/lib/media/Makefile | 10 + client/lib/media/README.md | 49 + client/lib/media/actions.js | 254 +++ client/lib/media/constants.js | 182 ++ client/lib/media/library-selected-store.js | 146 ++ client/lib/media/list-store.js | 270 +++ client/lib/media/store.js | 129 ++ client/lib/media/test/actions.js | 389 ++++ .../lib/media/test/library-selected-store.js | 135 ++ client/lib/media/test/list-store.js | 388 ++++ client/lib/media/test/store.js | 164 ++ client/lib/media/test/utils.js | 463 ++++ client/lib/media/test/validation-store.js | 305 +++ client/lib/media/utils.js | 370 ++++ client/lib/media/validation-store.js | 207 ++ client/lib/menu-data/Makefile | 10 + client/lib/menu-data/README.md | 10 + client/lib/menu-data/index.js | 11 + client/lib/menu-data/menu-data.js | 991 +++++++++ client/lib/menu-data/test/fixtures.js | 52 + client/lib/menu-data/test/lib/mixins/i18n.js | 12 + client/lib/menu-data/test/lib/sites-list.js | 21 + client/lib/menu-data/test/lib/wp.js | 27 + client/lib/menu-data/test/test-menu-data.js | 572 +++++ client/lib/mixins/analytics/index.js | 755 +++++++ client/lib/mixins/close-on-esc/README.md | 16 + client/lib/mixins/close-on-esc/index.js | 65 + client/lib/mixins/data-observe/Makefile | 7 + client/lib/mixins/data-observe/README.md | 18 + client/lib/mixins/data-observe/index.js | 51 + client/lib/mixins/data-observe/test/test.js | 122 ++ client/lib/mixins/i18n/Makefile | 12 + client/lib/mixins/i18n/README.md | 271 +++ client/lib/mixins/i18n/index.js | 404 ++++ client/lib/mixins/i18n/number-format.js | 36 + client/lib/mixins/i18n/test/data.js | 280 +++ .../lib/mixins/i18n/test/i18nLocalStrings.js | 2 + .../lib/mixins/i18n/test/lib/user-settings.js | 29 + client/lib/mixins/i18n/test/lib/user.js | 27 + client/lib/mixins/i18n/test/test.jsx | 199 ++ client/lib/mixins/i18n/timezone.js | 14 + client/lib/mixins/infinite-scroll/README.md | 38 + client/lib/mixins/infinite-scroll/index.js | 60 + client/lib/mixins/lock/README.md | 53 + client/lib/mixins/lock/index.js | 60 + .../lib/mixins/observe-window-resize/index.js | 30 + client/lib/mixins/pageable/Makefile | 12 + client/lib/mixins/pageable/README.md | 30 + client/lib/mixins/pageable/index.js | 182 ++ client/lib/mixins/pageable/test/test.js | 138 ++ client/lib/mixins/protect-form/README.md | 40 + client/lib/mixins/protect-form/index.js | 61 + client/lib/mixins/render-visualizer/README.md | 27 + client/lib/mixins/render-visualizer/index.js | 246 +++ client/lib/mixins/searchable/Makefile | 7 + client/lib/mixins/searchable/README.md | 100 + client/lib/mixins/searchable/index.js | 82 + client/lib/mixins/searchable/test/test.js | 122 ++ client/lib/mixins/trap-focus/README.md | 16 + client/lib/mixins/trap-focus/index.js | 89 + .../lib/mixins/update-post-status/README.md | 33 + .../lib/mixins/update-post-status/index.jsx | 179 ++ client/lib/mixins/url-search/Makefile | 7 + client/lib/mixins/url-search/README.md | 67 + client/lib/mixins/url-search/build-url.js | 26 + client/lib/mixins/url-search/index.js | 65 + .../lib/mixins/url-search/test/build-url.js | 47 + client/lib/network-connection/Makefile | 12 + client/lib/network-connection/README.md | 61 + client/lib/network-connection/index.js | 150 ++ .../lib/network-connection/test/index-test.js | 74 + .../lib/notification-settings-store/Makefile | 12 + .../notification-settings-store/actions.js | 61 + .../notification-settings-store/constants.js | 11 + .../lib/notification-settings-store/index.js | 81 + .../test/store-test.js | 249 +++ .../toggle-state.js | 37 + client/lib/oauth-store/Makefile | 7 + client/lib/oauth-store/README.md | 19 + client/lib/oauth-store/actions.js | 26 + client/lib/oauth-store/constants.js | 12 + client/lib/oauth-store/index.js | 84 + client/lib/oauth-store/test/oauth-store.js | 125 ++ client/lib/oauth-token/README.md | 14 + client/lib/oauth-token/index.js | 33 + client/lib/olark-api/README.md | 4 + client/lib/olark-api/index.js | 88 + client/lib/olark-events/Makefile | 12 + client/lib/olark-events/README.md | 62 + client/lib/olark-events/index.js | 102 + .../lib/olark-events/test/lib/mock-olark.js | 18 + .../olark-events/test/test-onready-event.js | 33 + client/lib/olark-store/Makefile | 12 + client/lib/olark-store/README.md | 85 + client/lib/olark-store/actions.js | 75 + client/lib/olark-store/constants.js | 16 + client/lib/olark-store/index.js | 50 + .../lib/olark-store/test/olark-store-test.js | 19 + client/lib/olark/README.md | 4 + client/lib/olark/index.js | 370 ++++ client/lib/page-templates/actions.js | 35 + client/lib/page-templates/store.js | 55 + client/lib/paths/Makefile | 7 + client/lib/paths/index.js | 93 + client/lib/paths/test/index.js | 129 ++ client/lib/paygate-loader/README.md | 28 + client/lib/paygate-loader/index.js | 47 + client/lib/people/Makefile | 12 + client/lib/people/README.md | 9 + client/lib/people/actions.js | 17 + client/lib/people/log-store.js | 145 ++ client/lib/people/test/lib/mock-actions.js | 47 + client/lib/people/test/lib/mock-site.js | 31 + client/lib/people/test/test-store.js | 108 + client/lib/phone-validation/Makefile | 10 + client/lib/phone-validation/README.md | 5 + client/lib/phone-validation/index.jsx | 54 + client/lib/phone-validation/test/test.jsx | 48 + client/lib/plans-list/Makefile | 12 + client/lib/plans-list/README.md | 16 + client/lib/plans-list/index.js | 160 ++ client/lib/plans-list/test/data.js | 110 + client/lib/plans-list/test/lib/wp.js | 4 + client/lib/plans-list/test/test.js | 31 + client/lib/plugins/Makefile | 12 + client/lib/plugins/README.md | 218 ++ client/lib/plugins/actions.js | 461 ++++ client/lib/plugins/log-store.js | 186 ++ client/lib/plugins/notices.jsx | 674 ++++++ client/lib/plugins/store.js | 455 ++++ client/lib/plugins/test/lib/mixins/i18n.js | 12 + client/lib/plugins/test/lib/mock-actions.js | 329 +++ .../lib/plugins/test/lib/mock-multi-site.js | 68 + .../plugins/test/lib/mock-plugins-updated.js | 36 + client/lib/plugins/test/lib/mock-plugins.js | 62 + client/lib/plugins/test/lib/mock-site.js | 36 + .../lib/plugins/test/lib/mock-sites-list.js | 19 + .../plugins/test/lib/mock-updated-plugin.js | 13 + client/lib/plugins/test/lib/mock-wpcom.js | 83 + client/lib/plugins/test/lib/wp.js | 6 + client/lib/plugins/test/test-actions.js | 90 + client/lib/plugins/test/test-log-store.js | 22 + client/lib/plugins/test/test-store.js | 512 +++++ client/lib/plugins/test/test-utils.js | 208 ++ client/lib/plugins/utils.js | 269 +++ client/lib/plugins/wporg-data/Makefile | 11 + client/lib/plugins/wporg-data/README.md | 133 ++ client/lib/plugins/wporg-data/actions.js | 129 ++ client/lib/plugins/wporg-data/list-store.js | 155 ++ client/lib/plugins/wporg-data/store.js | 99 + .../wporg-data/test/lib/data-actions.js | 117 + .../wporg-data/test/lib/mock-actions.js | 18 + .../wporg-data/test/lib/mock-local-store.js | 25 + .../plugins/wporg-data/test/lib/mock-store.js | 4 + .../plugins/wporg-data/test/lib/mock-wporg.js | 29 + .../wporg-data/test/lib/mocked-actions.js | 9 + .../plugins/wporg-data/test/test-actions.js | 77 + .../wporg-data/test/test-list-store.js | 279 +++ .../lib/plugins/wporg-data/test/test-store.js | 69 + client/lib/popup-monitor/Makefile | 12 + client/lib/popup-monitor/README.md | 26 + client/lib/popup-monitor/index.js | 120 ++ client/lib/popup-monitor/test/index.js | 27 + client/lib/post-formats/Makefile | 12 + client/lib/post-formats/README.md | 38 + client/lib/post-formats/actions.js | 34 + client/lib/post-formats/store.js | 41 + client/lib/post-formats/test/actions.js | 83 + client/lib/post-formats/test/store.js | 70 + client/lib/post-metadata/Makefile | 12 + client/lib/post-metadata/README.md | 13 + client/lib/post-metadata/index.js | 121 ++ client/lib/post-metadata/test/index.js | 218 ++ client/lib/post-normalizer/Makefile | 17 + client/lib/post-normalizer/README.md | 5 + client/lib/post-normalizer/index.js | 682 ++++++ .../test/lib/safe-image-url.js | 6 + .../test/post-normalizer-test.js | 774 +++++++ client/lib/post-stats/README.md | 29 + client/lib/post-stats/actions.js | 65 + client/lib/post-stats/constants.js | 14 + client/lib/post-stats/store.js | 123 ++ client/lib/post-types-list/README.md | 39 + client/lib/post-types-list/index.js | 10 + client/lib/post-types-list/list.js | 92 + client/lib/posts/Makefile | 10 + client/lib/posts/README.md | 42 + client/lib/posts/actions.js | 537 +++++ client/lib/posts/post-content-images-store.js | 67 + client/lib/posts/post-counts-store.js | 232 ++ client/lib/posts/post-edit-store.js | 500 +++++ client/lib/posts/post-list-cache-store.js | 130 ++ client/lib/posts/post-list-store.js | 371 ++++ client/lib/posts/posts-store.js | 67 + client/lib/posts/stats.js | 116 + client/lib/posts/test/actions.js | 203 ++ client/lib/posts/test/post-edit-store.js | 1004 +++++++++ client/lib/posts/test/utils.js | 110 + client/lib/posts/utils.js | 234 ++ client/lib/preferences/Makefile | 12 + client/lib/preferences/README.md | 37 + client/lib/preferences/actions.js | 97 + client/lib/preferences/constants.js | 4 + client/lib/preferences/store.js | 80 + client/lib/preferences/test/actions.js | 199 ++ client/lib/preferences/test/store.js | 93 + client/lib/products-list/README.md | 18 + client/lib/products-list/index.js | 134 ++ client/lib/products-values/index.js | 272 +++ client/lib/products-values/schema.json | 14 + client/lib/products-values/sort.js | 73 + client/lib/purchases/Makefile | 12 + client/lib/purchases/assembler.js | 86 + client/lib/purchases/index.js | 175 ++ client/lib/purchases/store.js | 87 + client/lib/purchases/stored-cards/Makefile | 12 + .../lib/purchases/stored-cards/assembler.js | 19 + client/lib/purchases/stored-cards/reducer.js | 88 + client/lib/purchases/stored-cards/store.js | 7 + .../stored-cards/test/assembler-test.js | 28 + .../purchases/stored-cards/test/constants.js | 48 + .../purchases/stored-cards/test/store-test.js | 132 ++ client/lib/purchases/test/assembler-test.js | 43 + client/lib/purchases/test/store-test.js | 35 + client/lib/react-pass-to-children/Makefile | 7 + client/lib/react-pass-to-children/README.md | 21 + client/lib/react-pass-to-children/index.js | 26 + .../lib/react-pass-to-children/test/index.jsx | 107 + client/lib/react-smart-set-state/index.js | 12 + client/lib/react-test-env-setup/Makefile | 7 + client/lib/react-test-env-setup/README.md | 27 + client/lib/react-test-env-setup/index.js | 30 + client/lib/react-test-env-setup/test/index.js | 59 + .../Makefile | 15 + .../actions.js | 70 + .../constants.js | 19 + .../index.js | 266 +++ .../comment-email-subscription-store-test.js | 124 ++ client/lib/reader-feed-subscriptions/Makefile | 15 + .../lib/reader-feed-subscriptions/actions.js | 205 ++ .../reader-feed-subscriptions/constants.js | 22 + .../lib/reader-feed-subscriptions/helper.js | 10 + client/lib/reader-feed-subscriptions/index.js | 382 ++++ .../test/feed-subscription-store-test.js | 287 +++ client/lib/reader-lists/README.md | 0 client/lib/reader-lists/actions.js | 138 ++ client/lib/reader-lists/lists.js | 83 + client/lib/reader-lists/subscriptions.js | 126 ++ .../reader-post-email-subscriptions/Makefile | 15 + .../actions.js | 97 + .../constants.js | 22 + .../reader-post-email-subscriptions/index.js | 316 +++ .../post-email-subscription-store-test.js | 216 ++ client/lib/reader-sidebar/actions.js | 63 + client/lib/reader-site-blocks/Makefile | 15 + client/lib/reader-site-blocks/actions.js | 60 + client/lib/reader-site-blocks/constants.js | 15 + client/lib/reader-site-blocks/index.js | 155 ++ .../test/site-block-store-test.js | 53 + client/lib/reader-site-store/Makefile | 15 + client/lib/reader-site-store/actions.js | 32 + client/lib/reader-site-store/constants.js | 11 + client/lib/reader-site-store/index.js | 98 + .../test/reader-site-store-tests.js | 182 ++ client/lib/reader-tags/README.md | 0 client/lib/reader-tags/actions.js | 106 + client/lib/reader-tags/subscriptions.js | 128 ++ client/lib/reader-tags/tags.js | 67 + client/lib/reader-teams/Makefile | 15 + client/lib/reader-teams/actions.js | 34 + client/lib/reader-teams/constants.js | 10 + client/lib/reader-teams/index.js | 85 + .../lib/reader-teams/test/team-store-test.js | 70 + client/lib/recommended-sites-store/Makefile | 15 + client/lib/recommended-sites-store/actions.js | 57 + .../lib/recommended-sites-store/constants.js | 2 + client/lib/recommended-sites-store/store.js | 55 + .../test/action-tests.js | 168 ++ .../test/store-tests.js | 28 + client/lib/resize-image-url/Makefile | 8 + client/lib/resize-image-url/README.md | 12 + client/lib/resize-image-url/index.js | 24 + client/lib/resize-image-url/test/test.js | 24 + client/lib/route/Makefile | 10 + client/lib/route/README.md | 25 + client/lib/route/index.js | 16 + client/lib/route/normalize.js | 15 + client/lib/route/path.js | 137 ++ client/lib/route/redirect.js | 14 + client/lib/route/test/index.js | 215 ++ client/lib/route/trailingslashit.js | 6 + client/lib/route/untrailingslashit.js | 8 + client/lib/safe-image-url/Makefile | 11 + client/lib/safe-image-url/README.md | 7 + client/lib/safe-image-url/index.js | 51 + client/lib/safe-image-url/test/index.js | 68 + client/lib/safe-protocol-url/Makefile | 8 + client/lib/safe-protocol-url/README.md | 3 + client/lib/safe-protocol-url/index.js | 39 + client/lib/safe-protocol-url/test/test.js | 49 + client/lib/scroll-to/Makefile | 9 + client/lib/scroll-to/README.md | 17 + client/lib/scroll-to/index.js | 54 + client/lib/scroll-to/test/test.js | 45 + client/lib/security-checkup/Makefile | 10 + .../account-recovery-store.js | 245 +++ client/lib/security-checkup/actions.js | 114 + client/lib/security-checkup/constants.js | 44 + .../test/account-recovery-store.js | 142 ++ client/lib/security-checkup/test/actions.js | 203 ++ client/lib/security-checkup/test/constants.js | 79 + client/lib/services-list/README.md | 41 + client/lib/services-list/index.js | 10 + client/lib/services-list/list.js | 84 + client/lib/sharing-buttons-list/README.md | 39 + client/lib/sharing-buttons-list/index.js | 175 ++ client/lib/shortcode/Makefile | 7 + client/lib/shortcode/README.md | 47 + client/lib/shortcode/index.js | 239 +++ client/lib/shortcode/test/index.js | 261 +++ client/lib/shortcodes/README.md | 28 + client/lib/shortcodes/actions.js | 36 + client/lib/shortcodes/constants.js | 10 + client/lib/shortcodes/store.js | 100 + client/lib/siftscience/README.md | 6 + client/lib/siftscience/index.js | 39 + client/lib/signup/Makefile | 12 + client/lib/signup/README.md | 81 + client/lib/signup/actions.js | 67 + client/lib/signup/cart.js | 39 + client/lib/signup/dependency-store.js | 108 + client/lib/signup/flow-controller.js | 194 ++ client/lib/signup/progress-store.js | 163 ++ client/lib/signup/step-actions.js | 150 ++ client/lib/signup/test/analytics.js | 7 + .../lib/signup/test/dependency-store-test.js | 39 + .../lib/signup/test/flow-controller-test.js | 148 ++ client/lib/signup/test/lib/user/index.js | 11 + client/lib/signup/test/lib/wp/index.js | 13 + client/lib/signup/test/progress-store-test.js | 108 + client/lib/signup/test/signup/config/flows.js | 35 + client/lib/signup/test/signup/config/steps.js | 64 + client/lib/site-roles/Makefile | 15 + client/lib/site-roles/README.md | 4 + client/lib/site-roles/actions.js | 33 + client/lib/site-roles/store.js | 68 + .../lib/site-roles/test/lib/mock-actions.js | 11 + client/lib/site-roles/test/lib/mock-roles.js | 128 ++ client/lib/site-roles/test/lib/mock-site.js | 31 + client/lib/site-roles/test/test-store.js | 52 + .../README.md | 13 + .../site-specific-plans-details-list/index.js | 147 ++ client/lib/site-stats-sticky-tab/README.md | 25 + client/lib/site-stats-sticky-tab/actions.js | 22 + client/lib/site-stats-sticky-tab/constants.js | 8 + client/lib/site-stats-sticky-tab/store.js | 133 ++ client/lib/site/Makefile | 12 + client/lib/site/README.md | 12 + client/lib/site/index.js | 246 +++ client/lib/site/jetpack.js | 409 ++++ client/lib/site/test/lib/wp.js | 4 + client/lib/site/test/test.js | 101 + client/lib/site/utils.js | 62 + client/lib/sites-list/Makefile | 12 + client/lib/sites-list/README.md | 45 + client/lib/sites-list/actions.js | 73 + client/lib/sites-list/delete-site-store.js | 51 + client/lib/sites-list/docs/example.jsx | 27 + client/lib/sites-list/index.js | 29 + client/lib/sites-list/list.js | 580 +++++ client/lib/sites-list/log-store.js | 137 ++ client/lib/sites-list/notices.js | 141 ++ client/lib/sites-list/test/data.js | 322 +++ client/lib/sites-list/test/lib/mixins/i18n.js | 5 + .../lib/sites-list/test/lib/mock-actions.js | 33 + client/lib/sites-list/test/lib/mock-site.js | 30 + client/lib/sites-list/test/lib/user.js | 11 + client/lib/sites-list/test/lib/wp.js | 4 + client/lib/sites-list/test/test-log-store.js | 26 + client/lib/sites-list/test/test.js | 104 + client/lib/states-list/README.md | 28 + client/lib/states-list/index.js | 165 ++ client/lib/stats/README.md | 8 + client/lib/stats/stats-list/Makefile | 12 + client/lib/stats/stats-list/README.md | 48 + client/lib/stats/stats-list/index.js | 239 +++ client/lib/stats/stats-list/stats-parser.js | 844 ++++++++ client/lib/stats/stats-list/test/analytics.js | 6 + client/lib/stats/stats-list/test/data.js | 95 + .../stats/stats-list/test/lib/mixins/i18n.js | 6 + client/lib/stats/stats-list/test/lib/user.js | 11 + client/lib/stats/stats-list/test/lib/wp.js | 72 + .../stats/stats-list/test/test-stats-list.js | 142 ++ .../stats-list/test/test-stats-parser.js | 65 + client/lib/stats/summary-list/README.md | 18 + client/lib/stats/summary-list/index.js | 97 + client/lib/stats/summary/README.md | 28 + client/lib/stats/summary/index.js | 171 ++ client/lib/store-transactions/README.md | 65 + client/lib/store-transactions/index.js | 242 +++ client/lib/store/Makefile | 13 + client/lib/store/README.md | 22 + client/lib/store/index.js | 85 + client/lib/store/test/index-test.js | 127 ++ client/lib/stored-cards/README.md | 16 + client/lib/stored-cards/index.js | 113 + client/lib/tags-list/README.md | 25 + client/lib/tags-list/index.js | 76 + client/lib/terms/Makefile | 15 + client/lib/terms/README.md | 41 + client/lib/terms/actions.js | 162 ++ client/lib/terms/category-store-factory.js | 25 + client/lib/terms/category-store.js | 279 +++ client/lib/terms/constants.js | 15 + client/lib/terms/store.js | 72 + client/lib/terms/tag-store.js | 155 ++ client/lib/terms/test/actions.js | 194 ++ client/lib/terms/test/category-store.js | 313 +++ client/lib/terms/test/common.js | 119 ++ client/lib/terms/test/data.js | 70 + client/lib/terms/test/store.js | 109 + client/lib/terms/test/tag-store.js | 142 ++ client/lib/ticker/index.js | 74 + client/lib/touch-detect/README.md | 12 + client/lib/touch-detect/index.js | 20 + client/lib/track-scroll-page/index.js | 10 + client/lib/transaction/store.js | 112 + client/lib/translator-jumpstart/README.md | 19 + client/lib/translator-jumpstart/index.js | 337 +++ client/lib/tree-convert/Makefile | 7 + client/lib/tree-convert/README.md | 26 + client/lib/tree-convert/index.js | 93 + client/lib/tree-convert/test/fixtures.js | 60 + .../tree-convert/test/test-tree-convert.js | 70 + client/lib/tree-convert/tree-traverser.js | 176 ++ client/lib/trophies-data/README.md | 4 + client/lib/trophies-data/index.js | 66 + client/lib/two-step-authorization/README.md | 8 + client/lib/two-step-authorization/index.js | 214 ++ client/lib/upgrades/actions/cart.js | 92 + client/lib/upgrades/actions/checkout.js | 59 + .../lib/upgrades/actions/domain-management.js | 527 +++++ client/lib/upgrades/actions/domain-search.js | 31 + client/lib/upgrades/actions/index.js | 5 + client/lib/upgrades/actions/purchases.js | 150 ++ client/lib/upgrades/constants.js | 74 + client/lib/user-profile-links/README.md | 4 + client/lib/user-profile-links/index.js | 134 ++ client/lib/user-settings/Makefile | 12 + client/lib/user-settings/README.md | 4 + client/lib/user-settings/index.js | 221 ++ client/lib/user-settings/test/index.js | 31 + client/lib/user-settings/test/lib/user.js | 5 + client/lib/user-settings/test/lib/wp.js | 21 + client/lib/user/Makefile | 12 + client/lib/user/README.md | 34 + client/lib/user/index.js | 38 + client/lib/user/shared-utils.js | 1 + client/lib/user/test/utils.js | 96 + client/lib/user/user.js | 244 +++ client/lib/user/utils.js | 49 + client/lib/username/README.md | 4 + client/lib/username/index.js | 96 + client/lib/users/Makefile | 13 + client/lib/users/README.md | 89 + client/lib/users/actions.js | 140 ++ client/lib/users/store.js | 212 ++ client/lib/users/test/lib/mock-actions.js | 84 + .../users/test/lib/mock-deleted-user-data.js | 52 + .../users/test/lib/mock-more-users-data.js | 28 + client/lib/users/test/lib/mock-single-user.js | 11 + client/lib/users/test/lib/mock-site.js | 31 + .../test/lib/mock-updated-single-user.js | 11 + client/lib/users/test/lib/mock-users-data.js | 64 + client/lib/users/test/test-store.js | 198 ++ client/lib/version-compare/README.md | 4 + client/lib/version-compare/index.js | 121 ++ client/lib/viewers/Makefile | 12 + client/lib/viewers/README.md | 4 + client/lib/viewers/actions.js | 61 + client/lib/viewers/store.js | 135 ++ client/lib/viewers/test/lib/mock-actions.js | 41 + client/lib/viewers/test/lib/mock-site.js | 31 + client/lib/viewers/test/lib/mock-viewers-1.js | 25 + client/lib/viewers/test/lib/mock-viewers-2.js | 25 + client/lib/viewers/test/test-store.js | 125 ++ client/lib/viewport/README.md | 16 + client/lib/viewport/index.js | 65 + client/lib/warn/index.js | 14 + client/lib/wpcom-xhr-wrapper/Makefile | 7 + client/lib/wpcom-xhr-wrapper/README.md | 39 + client/lib/wpcom-xhr-wrapper/index.js | 15 + .../test/wpcom-xhr-wrapper.js | 94 + client/lib/wporg/index.js | 77 + client/lib/wporg/jsonp.js | 90 + client/mailing-lists/controller.js | 24 + client/mailing-lists/index.js | 19 + client/mailing-lists/main.jsx | 193 ++ client/mailing-lists/utils.js | 39 + client/me/account-password/README.md | 5 + client/me/account-password/index.jsx | 172 ++ client/me/account-password/style.scss | 20 + client/me/account/README.md | 4 + client/me/account/index.jsx | 551 +++++ client/me/account/style.scss | 25 + client/me/action-remove/README.md | 4 + client/me/action-remove/index.jsx | 34 + client/me/action-remove/style.scss | 20 + client/me/application-password-item/README.md | 4 + client/me/application-password-item/index.jsx | 66 + .../me/application-password-item/style.scss | 16 + client/me/application-passwords/README.md | 4 + client/me/application-passwords/index.jsx | 207 ++ client/me/application-passwords/style.scss | 41 + client/me/billing-history/README.md | 11 + .../billing-history/billing-history-table.jsx | 77 + client/me/billing-history/index.jsx | 82 + client/me/billing-history/table-rows.js | 72 + .../billing-history/transactions-header.jsx | 254 +++ .../me/billing-history/transactions-table.jsx | 159 ++ .../upcoming-charges-table.jsx | 32 + .../me/billing-history/view-receipt-modal.jsx | 208 ++ .../me/connected-application-icon/README.md | 4 + .../me/connected-application-icon/index.jsx | 30 + .../me/connected-application-icon/style.scss | 16 + .../me/connected-application-item/README.md | 4 + .../me/connected-application-item/index.jsx | 235 ++ .../me/connected-application-item/style.scss | 160 ++ client/me/connected-applications/README.md | 4 + client/me/connected-applications/index.jsx | 139 ++ client/me/connected-applications/style.scss | 9 + client/me/controller.js | 338 +++ client/me/credit-cards/credit-card-delete.jsx | 71 + .../me/credit-cards/credit-card-delete.scss | 13 + client/me/credit-cards/credit-cards.scss | 13 + client/me/credit-cards/index.jsx | 65 + client/me/event-recorder/index.js | 65 + client/me/form-base/index.js | 90 + client/me/help/README.md | 3 + client/me/help/controller.js | 32 + .../help/help-contact-confirmation/index.jsx | 32 + .../help/help-contact-confirmation/style.scss | 62 + client/me/help/help-contact-form/index.jsx | 172 ++ client/me/help/help-contact-form/style.scss | 54 + client/me/help/help-contact/index.jsx | 247 +++ client/me/help/help-contact/style.scss | 5 + .../help/help-happiness-engineers/index.jsx | 52 + .../help/help-happiness-engineers/style.scss | 36 + client/me/help/help-results/index.jsx | 40 + client/me/help/help-results/item.jsx | 37 + client/me/help/help-results/style.scss | 61 + client/me/help/help-search/index.jsx | 113 + client/me/help/help-search/style.scss | 37 + client/me/help/index.js | 8 + client/me/help/main.jsx | 57 + client/me/help/style.scss | 29 + client/me/index.js | 119 ++ client/me/next-steps/index.jsx | 193 ++ client/me/next-steps/next-steps-box.jsx | 49 + client/me/next-steps/next-steps-box.scss | 71 + client/me/next-steps/next-steps.scss | 31 + client/me/next-steps/steps.js | 134 ++ .../blogs-settings/blog.jsx | 58 + .../blogs-settings/header.jsx | 89 + .../blogs-settings/index.jsx | 74 + .../blogs-settings/placeholder.jsx | 40 + .../blogs-settings/style.scss | 128 ++ .../comment-settings/index.jsx | 89 + .../comment-settings/style.scss | 6 + client/me/notification-settings/index.jsx | 76 + .../me/notification-settings/navigation.jsx | 56 + .../reader-subscriptions/index.jsx | 213 ++ .../settings-form/actions.jsx | 36 + .../settings-form/constants.js | 3 + .../settings-form/device-selector.jsx | 42 + .../settings-form/index.jsx | 50 + .../settings-form/labels-list.jsx | 31 + .../settings-form/labels.jsx | 31 + .../settings-form/locales.js | 25 + .../settings-form/settings.jsx | 104 + .../settings-form/stream-header.jsx | 34 + .../settings-form/stream-options.jsx | 47 + .../settings-form/stream-selector.jsx | 43 + .../settings-form/stream.jsx | 78 + .../settings-form/style.scss | 142 ++ .../wpcom-settings/index.jsx | 130 ++ .../wpcom-settings/style.scss | 6 + client/me/paths.js | 8 + client/me/profile-gravatar/README.md | 4 + client/me/profile-gravatar/index.jsx | 51 + client/me/profile-gravatar/style.scss | 118 + client/me/profile-link/README.md | 4 + client/me/profile-link/index.jsx | 73 + client/me/profile-link/style.scss | 65 + client/me/profile-links-add-other/README.md | 4 + client/me/profile-links-add-other/index.jsx | 165 ++ client/me/profile-links-add-other/style.scss | 15 + .../me/profile-links-add-wordpress/README.md | 4 + .../me/profile-links-add-wordpress/index.jsx | 227 ++ .../me/profile-links-add-wordpress/style.scss | 26 + client/me/profile-links/README.md | 4 + client/me/profile-links/index.jsx | 207 ++ client/me/profile-links/style.scss | 20 + client/me/profile/README.me | 4 + client/me/profile/index.jsx | 137 ++ .../cancel-private-registration/index.jsx | 154 ++ .../cancel-private-registration/style.scss | 26 + .../me/purchases/cancel-purchase/button.jsx | 42 + client/me/purchases/cancel-purchase/index.jsx | 116 + .../cancel-purchase/product-information.jsx | 180 ++ .../cancel-purchase/refund-information.jsx | 53 + .../me/purchases/cancel-purchase/style.scss | 102 + .../purchases/cancel-purchase/support-box.jsx | 39 + .../confirm-cancel-purchase/index.jsx | 85 + .../load-endpoint-form.js | 145 ++ .../confirm-cancel-purchase/style.scss | 56 + client/me/purchases/controller.js | 209 ++ client/me/purchases/list/header/index.jsx | 42 + client/me/purchases/list/header/style.scss | 0 client/me/purchases/list/index.jsx | 66 + client/me/purchases/list/item/index.jsx | 147 ++ client/me/purchases/list/item/style.scss | 82 + client/me/purchases/list/site/index.jsx | 52 + client/me/purchases/list/site/style.scss | 21 + client/me/purchases/manage-purchase/index.jsx | 577 +++++ .../me/purchases/manage-purchase/style.scss | 220 ++ client/me/purchases/paths.js | 42 + .../payment/edit-card-details/index.jsx | 222 ++ .../payment/edit-card-details/style.scss | 30 + .../edit-payment-method/credit-card.jsx | 141 ++ .../payment/edit-payment-method/index.jsx | 57 + .../payment/edit-payment-method/paypal.jsx | 107 + .../payment/edit-payment-method/style.scss | 57 + client/me/purchases/purchases-mixin.js | 47 + client/me/reauth-required/index.jsx | 214 ++ client/me/reauth-required/style.scss | 11 + .../security-2fa-app-chooser-item/index.jsx | 127 ++ .../security-2fa-app-chooser-item/style.scss | 4 + .../security-2fa-backup-codes-list/index.jsx | 247 +++ .../security-2fa-backup-codes-list/style.scss | 121 ++ .../index.jsx | 157 ++ .../style.scss | 8 + client/me/security-2fa-backup-codes/README.md | 15 + client/me/security-2fa-backup-codes/index.jsx | 124 ++ .../me/security-2fa-backup-codes/style.scss | 24 + client/me/security-2fa-code-prompt/README.md | 5 + client/me/security-2fa-code-prompt/index.jsx | 275 +++ client/me/security-2fa-code-prompt/style.scss | 20 + client/me/security-2fa-disable/README.md | 4 + client/me/security-2fa-disable/index.jsx | 162 ++ client/me/security-2fa-disable/style.scss | 4 + client/me/security-2fa-enable/index.jsx | 425 ++++ client/me/security-2fa-enable/style.scss | 49 + .../me/security-2fa-initial-setup/README.md | 5 + .../me/security-2fa-initial-setup/index.jsx | 49 + client/me/security-2fa-progress/README.md | 5 + client/me/security-2fa-progress/index.jsx | 60 + .../security-2fa-progress/progress-item.jsx | 43 + client/me/security-2fa-progress/style.scss | 98 + .../security-2fa-setup-backup-codes/README.md | 14 + .../security-2fa-setup-backup-codes/index.jsx | 104 + client/me/security-2fa-setup/README.md | 4 + client/me/security-2fa-setup/index.jsx | 120 ++ client/me/security-2fa-sms-settings/README.md | 5 + client/me/security-2fa-sms-settings/index.jsx | 221 ++ .../me/security-2fa-sms-settings/style.scss | 41 + client/me/security-2fa-status/README.md | 5 + client/me/security-2fa-status/index.jsx | 46 + client/me/security-2fa-status/style.scss | 15 + client/me/security-checkup/buttons.jsx | 54 + client/me/security-checkup/edit-email.jsx | 154 ++ client/me/security-checkup/edit-phone.jsx | 128 ++ client/me/security-checkup/index.jsx | 54 + client/me/security-checkup/manage-contact.jsx | 173 ++ client/me/security-checkup/recovery-email.jsx | 83 + client/me/security-checkup/recovery-phone.jsx | 95 + client/me/security-checkup/style.scss | 114 + client/me/security-section-nav/README.me | 8 + client/me/security-section-nav/index.jsx | 81 + client/me/security/password.jsx | 54 + client/me/select-site.jsx | 37 + client/me/sidebar-navigation/README.md | 20 + client/me/sidebar-navigation/package.json | 6 + .../sidebar-navigation/sidebar-navigation.jsx | 28 + client/me/sidebar-navigation/style.scss | 11 + client/me/sidebar/index.jsx | 151 ++ client/me/sidebar/sidebar-item.jsx | 38 + client/me/sidebar/style.scss | 41 + client/me/two-step/index.jsx | 166 ++ client/me/two-step/style.scss | 10 + client/my-sites/README.md | 27 + client/my-sites/ads/controller.js | 72 + client/my-sites/ads/form-earnings.jsx | 330 +++ client/my-sites/ads/form-settings.jsx | 397 ++++ client/my-sites/ads/index.js | 19 + client/my-sites/ads/main.jsx | 95 + client/my-sites/ads/style.scss | 123 ++ client/my-sites/all-sites-icon/README.md | 22 + client/my-sites/all-sites-icon/index.jsx | 50 + client/my-sites/all-sites-icon/package.json | 9 + client/my-sites/all-sites-icon/style.scss | 105 + client/my-sites/all-sites/README.md | 23 + client/my-sites/all-sites/index.jsx | 67 + client/my-sites/all-sites/style.scss | 14 + client/my-sites/category-selector/README.md | 40 + .../category-selector/add-category.jsx | 207 ++ client/my-sites/category-selector/index.jsx | 231 ++ .../my-sites/category-selector/no-results.jsx | 39 + client/my-sites/category-selector/search.jsx | 25 + client/my-sites/category-selector/search.scss | 20 + client/my-sites/category-selector/style.scss | 110 + client/my-sites/controller.js | 281 +++ client/my-sites/current-site/README.md | 21 + client/my-sites/current-site/index.jsx | 185 ++ client/my-sites/current-site/style.scss | 144 ++ client/my-sites/customize/README.md | 15 + client/my-sites/customize/actions.js | 70 + client/my-sites/customize/controller.js | 38 + client/my-sites/customize/index.js | 18 + client/my-sites/customize/loading-panel.jsx | 59 + client/my-sites/customize/main.jsx | 371 ++++ client/my-sites/customize/package.json | 6 + client/my-sites/customize/style.scss | 192 ++ client/my-sites/draft/README.md | 4 + client/my-sites/draft/index.jsx | 284 +++ client/my-sites/draft/style.scss | 287 +++ client/my-sites/drafts/controller.js | 32 + client/my-sites/drafts/draft-list.jsx | 148 ++ client/my-sites/drafts/index.js | 19 + client/my-sites/drafts/main.jsx | 43 + client/my-sites/drafts/style.scss | 15 + client/my-sites/exporter/advanced-options.jsx | 96 + client/my-sites/exporter/option-fieldset.jsx | 70 + client/my-sites/exporter/style.scss | 61 + client/my-sites/importer/Makefile | 12 + .../my-sites/importer/author-mapping-item.jsx | 58 + .../my-sites/importer/author-mapping-pane.jsx | 59 + client/my-sites/importer/error-pane.jsx | 90 + client/my-sites/importer/file-importer.jsx | 87 + client/my-sites/importer/importer-ghost.jsx | 29 + client/my-sites/importer/importer-header.jsx | 99 + client/my-sites/importer/importer-icons.jsx | 30 + client/my-sites/importer/importer-medium.jsx | 29 + .../importer/importer-squarespace.jsx | 32 + .../my-sites/importer/importer-wordpress.jsx | 60 + client/my-sites/importer/importing-pane.jsx | 149 ++ client/my-sites/importer/style.scss | 195 ++ client/my-sites/importer/test/mock-data.js | 388 ++++ client/my-sites/importer/uploading-pane.jsx | 132 ++ client/my-sites/index.js | 16 + .../jetpack-manage-error-page/README.md | 56 + .../jetpack-manage-error-page/index.jsx | 74 + .../jetpack-manage-error-page/package.json | 6 + client/my-sites/media-library/Makefile | 10 + client/my-sites/media-library/content.jsx | 199 ++ client/my-sites/media-library/content.scss | 28 + client/my-sites/media-library/drop-zone.jsx | 69 + client/my-sites/media-library/filter-bar.jsx | 131 ++ .../media-library/filter-to-mime-prefix.js | 33 + client/my-sites/media-library/header.jsx | 226 ++ client/my-sites/media-library/index.jsx | 147 ++ .../media-library/list-item-audio.jsx | 17 + .../media-library/list-item-document.jsx | 17 + .../media-library/list-item-file-details.jsx | 42 + .../media-library/list-item-file-details.scss | 49 + .../media-library/list-item-image.jsx | 102 + .../media-library/list-item-video.jsx | 55 + .../media-library/list-item-video.scss | 30 + client/my-sites/media-library/list-item.jsx | 139 ++ client/my-sites/media-library/list-item.scss | 114 + .../media-library/list-no-content.jsx | 59 + .../media-library/list-no-results.jsx | 81 + client/my-sites/media-library/list.jsx | 227 ++ client/my-sites/media-library/style.scss | 117 + .../my-sites/media-library/test/fixtures.js | 65 + client/my-sites/media-library/test/list.jsx | 186 ++ .../my-sites/media-library/upload-button.jsx | 73 + .../my-sites/media-library/upload-button.scss | 20 + client/my-sites/media-library/upload-url.jsx | 104 + client/my-sites/media-library/upload-url.scss | 26 + client/my-sites/media/controller.js | 46 + client/my-sites/media/index.js | 20 + client/my-sites/media/main.jsx | 59 + client/my-sites/menus/README.md | 44 + client/my-sites/menus/controller.js | 79 + client/my-sites/menus/index.js | 18 + client/my-sites/menus/item-options/Makefile | 10 + client/my-sites/menus/item-options/README.md | 22 + .../menus/item-options/category-options.jsx | 87 + .../menus/item-options/empty-placeholder.jsx | 85 + .../item-options/loading-placeholder.jsx | 20 + .../menus/item-options/option-list.jsx | 107 + .../my-sites/menus/item-options/options.jsx | 60 + .../my-sites/menus/item-options/post-list.jsx | 45 + client/my-sites/menus/item-options/posts.jsx | 80 + .../menus/item-options/taxonomy-list.jsx | 76 + .../menus/item-options/test/test-posts.jsx | 59 + client/my-sites/menus/loading-placeholder.jsx | 37 + client/my-sites/menus/location-picker.jsx | 56 + client/my-sites/menus/main.jsx | 268 +++ client/my-sites/menus/menu-delete-button.jsx | 79 + client/my-sites/menus/menu-editable-item.jsx | 386 ++++ .../my-sites/menus/menu-item-drop-target.jsx | 48 + client/my-sites/menus/menu-item-list.jsx | 444 ++++ client/my-sites/menus/menu-item-types.js | 199 ++ client/my-sites/menus/menu-name.jsx | 115 + .../my-sites/menus/menu-panel-back-button.jsx | 39 + client/my-sites/menus/menu-picker.jsx | 100 + client/my-sites/menus/menu-placeholder.jsx | 36 + client/my-sites/menus/menu-utils.js | 21 + client/my-sites/menus/menu.jsx | 250 +++ client/my-sites/menus/menus-save-button.jsx | 61 + client/my-sites/navigation/navigation.jsx | 69 + client/my-sites/navigation/package.json | 6 + client/my-sites/no-results/index.jsx | 25 + client/my-sites/no-results/style.scss | 15 + client/my-sites/pages/README.md | 4 + client/my-sites/pages/controller.js | 65 + client/my-sites/pages/helpers.js | 25 + client/my-sites/pages/index.js | 17 + client/my-sites/pages/main.jsx | 113 + client/my-sites/pages/page-list.jsx | 230 ++ client/my-sites/pages/page.jsx | 335 +++ client/my-sites/pages/placeholder.jsx | 38 + client/my-sites/pages/style.scss | 110 + client/my-sites/people/README.md | 25 + client/my-sites/people/controller.js | 115 + client/my-sites/people/delete-user/README.md | 10 + client/my-sites/people/delete-user/index.jsx | 279 +++ client/my-sites/people/delete-user/style.scss | 21 + .../people/edit-team-member-form/README.md | 5 + .../people/edit-team-member-form/index.jsx | 349 +++ .../people/edit-team-member-form/style.scss | 15 + .../my-sites/people/followers-list/README.md | 4 + .../my-sites/people/followers-list/index.jsx | 243 +++ client/my-sites/people/index.js | 45 + client/my-sites/people/main.jsx | 88 + .../people/people-list-item/README.md | 5 + .../people/people-list-item/index.jsx | 69 + .../people/people-list-item/style.scss | 86 + .../my-sites/people/people-notices/README.md | 4 + .../my-sites/people/people-notices/index.jsx | 142 ++ .../my-sites/people/people-notices/style.scss | 3 + .../my-sites/people/people-profile/README.md | 10 + .../my-sites/people/people-profile/index.jsx | 178 ++ .../my-sites/people/people-profile/style.scss | 129 ++ .../people/people-section-nav/README.md | 4 + .../people/people-section-nav/index.jsx | 151 ++ client/my-sites/people/role-select/README.md | 4 + client/my-sites/people/role-select/index.jsx | 93 + client/my-sites/people/team-list/README.md | 4 + client/my-sites/people/team-list/index.jsx | 155 ++ client/my-sites/people/viewers-list/README.md | 4 + client/my-sites/people/viewers-list/index.jsx | 171 ++ client/my-sites/picker/README.md | 4 + client/my-sites/picker/package.json | 6 + client/my-sites/picker/picker.jsx | 105 + client/my-sites/plans/README.md | 19 + client/my-sites/plans/controller.jsx | 147 ++ client/my-sites/plans/index.js | 53 + client/my-sites/plans/main.jsx | 83 + client/my-sites/plans/plans-select.jsx | 64 + client/my-sites/plans/style.scss | 16 + client/my-sites/plugins/README.md | 21 + client/my-sites/plugins/access-control.js | 69 + client/my-sites/plugins/controller.js | 216 ++ .../disconnect-jetpack-button.jsx | 73 + .../disconnect-jetpack-dialog.jsx | 100 + .../plugins/featured-plugins/README.md | 26 + .../plugins/featured-plugins/index.jsx | 44 + .../plugins/featured-plugins/style.scss | 29 + client/my-sites/plugins/index.js | 26 + client/my-sites/plugins/main.jsx | 780 +++++++ .../my-sites/plugins/plugin-action/Makefile | 7 + .../my-sites/plugins/plugin-action/README.md | 48 + .../plugins/plugin-action/plugin-action.jsx | 54 + .../my-sites/plugins/plugin-action/style.scss | 45 + .../plugins/plugin-action/test/index.jsx | 66 + .../plugins/plugin-activate-toggle/Makefile | 10 + .../plugins/plugin-activate-toggle/README.md | 28 + .../plugins/plugin-activate-toggle/index.jsx | 80 + .../plugins/plugin-activate-toggle/style.scss | 7 + .../plugin-activate-toggle/test/fixtures.js | 13 + .../plugin-activate-toggle/test/index.jsx | 79 + .../test/mocks/actions.js | 6 + .../test/mocks/plugin-action.jsx | 10 + .../plugins/plugin-autoupdate-toggle/Makefile | 12 + .../plugin-autoupdate-toggle/README.md | 30 + .../plugin-autoupdate-toggle/index.jsx | 62 + .../plugin-autoupdate-toggle/test/fixtures.js | 15 + .../plugin-autoupdate-toggle/test/index.jsx | 84 + .../test/mocks/actions.js | 6 + .../test/mocks/plugin-action.jsx | 10 + .../plugins/plugin-card-header/README.md | 41 + .../plugins/plugin-card-header/index.jsx | 34 + .../plugins/plugin-card-header/style.scss | 10 + client/my-sites/plugins/plugin-icon/README.md | 22 + .../plugins/plugin-icon/plugin-icon.jsx | 26 + .../my-sites/plugins/plugin-icon/style.scss | 43 + .../plugins/plugin-information/README.md | 9 + .../plugins/plugin-information/index.jsx | 226 ++ .../plugins/plugin-information/style.scss | 116 + .../plugins/plugin-install-button/README.md | 28 + .../plugins/plugin-install-button/index.jsx | 111 + .../plugins/plugin-install-button/style.scss | 61 + client/my-sites/plugins/plugin-item/README.md | 32 + .../plugins/plugin-item/plugin-item.jsx | 251 +++ .../my-sites/plugins/plugin-item/style.scss | 245 +++ client/my-sites/plugins/plugin-meta/README.md | 26 + client/my-sites/plugins/plugin-meta/index.jsx | 259 +++ .../my-sites/plugins/plugin-meta/style.scss | 176 ++ .../my-sites/plugins/plugin-ratings/README.md | 22 + .../my-sites/plugins/plugin-ratings/index.jsx | 73 + .../plugins/plugin-ratings/style.scss | 49 + .../plugins/plugin-remove-button/README.md | 24 + .../plugins/plugin-remove-button/index.jsx | 94 + .../plugins/plugin-remove-button/style.scss | 23 + .../plugins/plugin-sections/README.md | 22 + .../plugins/plugin-sections/index.jsx | 186 ++ .../plugins/plugin-sections/style.scss | 97 + .../plugins/plugin-site-business/README.md | 24 + .../plugins/plugin-site-business/index.jsx | 36 + .../plugins/plugin-site-business/style.scss | 16 + .../plugin-site-disabled-manage/README.md | 24 + .../plugin-site-disabled-manage/index.jsx | 37 + .../plugin-site-disabled-manage/style.scss | 42 + .../plugins/plugin-site-jetpack/README.md | 26 + .../plugins/plugin-site-jetpack/index.jsx | 94 + .../plugins/plugin-site-jetpack/style.scss | 59 + .../plugins/plugin-site-list/README.md | 23 + .../plugins/plugin-site-list/index.jsx | 65 + .../plugins/plugin-site-network/README.md | 28 + .../plugins/plugin-site-network/index.jsx | 148 ++ .../plugins/plugin-site-network/style.scss | 113 + .../plugin-site-update-indicator/README.md | 28 + .../plugin-site-update-indicator/index.jsx | 89 + .../plugin-site-update-indicator/style.scss | 13 + client/my-sites/plugins/plugin-site/README.md | 27 + .../plugins/plugin-site/plugin-site.jsx | 32 + .../my-sites/plugins/plugin-toggle/README.md | 38 + .../plugins/plugin-toggle/plugin-toggle.jsx | 46 + .../my-sites/plugins/plugin-version/README.md | 28 + .../my-sites/plugins/plugin-version/index.jsx | 63 + .../plugins/plugin-version/style.scss | 22 + client/my-sites/plugins/plugin.jsx | 309 +++ .../plugins/plugins-browser-item/README.md | 34 + .../plugins/plugins-browser-item/index.jsx | 84 + .../plugins/plugins-browser-item/style.scss | 126 ++ .../plugins/plugins-browser-list/README.md | 32 + .../plugins/plugins-browser-list/index.jsx | 80 + .../plugins/plugins-browser-list/style.scss | 43 + .../plugins/plugins-browser/README.md | 32 + .../plugins/plugins-browser/index.jsx | 220 ++ .../plugins/plugins-browser/style.scss | 15 + .../my-sites/plugins/plugins-manage-mixin.js | 20 + client/my-sites/plugins/style.scss | 3 + .../post-relative-time-status/README.md | 21 + .../post-relative-time-status/index.jsx | 93 + client/my-sites/post-selector/README.md | 21 + client/my-sites/post-selector/index.jsx | 72 + client/my-sites/post-selector/no-results.jsx | 36 + client/my-sites/post-selector/search.jsx | 30 + client/my-sites/post-selector/search.scss | 20 + client/my-sites/post-selector/selector.jsx | 232 ++ client/my-sites/post-selector/style.scss | 41 + client/my-sites/post-trends/README.md | 19 + client/my-sites/post-trends/day.jsx | 120 ++ client/my-sites/post-trends/index.jsx | 159 ++ client/my-sites/post-trends/month.jsx | 51 + client/my-sites/post-trends/style.scss | 214 ++ client/my-sites/post-trends/week.jsx | 43 + client/my-sites/post/README.md | 4 + client/my-sites/post/post-image/index.jsx | 98 + client/my-sites/post/post-image/style.scss | 38 + client/my-sites/posts/README.md | 5 + client/my-sites/posts/controller.js | 96 + client/my-sites/posts/index.js | 20 + client/my-sites/posts/main.jsx | 52 + client/my-sites/posts/post-controls.jsx | 225 ++ client/my-sites/posts/post-header.jsx | 51 + client/my-sites/posts/post-list.jsx | 265 +++ client/my-sites/posts/post-placeholder.jsx | 45 + client/my-sites/posts/post-total-views.jsx | 98 + client/my-sites/posts/post.jsx | 404 ++++ client/my-sites/posts/posts-navigation.jsx | 381 ++++ client/my-sites/sharing/README.md | 12 + client/my-sites/sharing/buttons/README.md | 38 + .../my-sites/sharing/buttons/appearance.jsx | 115 + client/my-sites/sharing/buttons/buttons.jsx | 136 ++ .../my-sites/sharing/buttons/label-editor.jsx | 87 + client/my-sites/sharing/buttons/options.jsx | 174 ++ .../sharing/buttons/preview-action.jsx | 52 + .../sharing/buttons/preview-button.jsx | 56 + .../sharing/buttons/preview-buttons.jsx | 233 ++ .../sharing/buttons/preview-placeholder.jsx | 51 + .../sharing/buttons/preview-widget.js | 41 + client/my-sites/sharing/buttons/preview.jsx | 198 ++ client/my-sites/sharing/buttons/style.jsx | 56 + client/my-sites/sharing/buttons/tray.jsx | 182 ++ client/my-sites/sharing/connections/README.md | 68 + .../connections/account-dialog-account.jsx | 61 + .../connections/account-dialog-account.scss | 57 + .../sharing/connections/account-dialog.jsx | 185 ++ .../sharing/connections/account-dialog.scss | 53 + .../sharing/connections/connection.jsx | 173 ++ .../sharing/connections/connections.jsx | 140 ++ .../sharing/connections/service-action.jsx | 78 + .../service-connected-accounts.jsx | 84 + .../connections/service-connections.js | 359 ++++ .../connections/service-description.jsx | 99 + .../sharing/connections/service-example.jsx | 37 + .../sharing/connections/service-examples.jsx | 254 +++ .../connections/service-placeholder.jsx | 22 + .../sharing/connections/service-tip.jsx | 69 + .../my-sites/sharing/connections/service.jsx | 247 +++ .../sharing/connections/services-group.jsx | 107 + .../sharing/connections/services-group.scss | 18 + .../connections/services/eventbrite.js | 61 + .../sharing/connections/services/index.js | 3 + client/my-sites/sharing/controller.js | 108 + client/my-sites/sharing/index.js | 20 + client/my-sites/sharing/main.jsx | 77 + client/my-sites/sidebar-navigation/README.md | 20 + .../my-sites/sidebar-navigation/package.json | 6 + .../sidebar-navigation/sidebar-navigation.jsx | 41 + client/my-sites/sidebar-navigation/style.scss | 56 + client/my-sites/sidebar/package.json | 6 + client/my-sites/sidebar/publish-menu.jsx | 214 ++ client/my-sites/sidebar/sidebar-menu-item.jsx | 59 + client/my-sites/sidebar/sidebar.jsx | 660 ++++++ client/my-sites/site-indicator/README.md | 16 + client/my-sites/site-indicator/package.json | 6 + .../site-indicator/site-indicator.jsx | 249 +++ client/my-sites/site-indicator/style.scss | 144 ++ client/my-sites/site-settings/README.md | 53 + .../site-settings/action-panel/body.jsx | 21 + .../site-settings/action-panel/figure.jsx | 37 + .../site-settings/action-panel/footer.jsx | 21 + .../site-settings/action-panel/index.jsx | 26 + .../site-settings/action-panel/style.scss | 83 + .../site-settings/action-panel/title.jsx | 21 + client/my-sites/site-settings/controller.js | 192 ++ .../delete-site-options/index.jsx | 153 ++ .../delete-site-options/style.scss | 83 + .../site-settings/delete-site/index.jsx | 207 ++ .../site-settings/delete-site/style.scss | 61 + .../my-sites/site-settings/form-analytics.jsx | 174 ++ client/my-sites/site-settings/form-base.js | 157 ++ .../site-settings/form-discussion.jsx | 474 ++++ .../my-sites/site-settings/form-general.jsx | 460 ++++ .../site-settings/form-jetpack-monitor.jsx | 165 ++ .../site-settings/form-jetpack-protect.jsx | 151 ++ .../site-settings/form-jetpack-scan.jsx | 485 +++++ .../my-sites/site-settings/form-writing.jsx | 125 ++ client/my-sites/site-settings/index.js | 34 + client/my-sites/site-settings/main.jsx | 127 ++ .../site-settings/press-this-link.jsx | 97 + .../site-settings/related-content-preview.jsx | 68 + .../site-settings/section-analytics.jsx | 29 + .../site-settings/section-discussion.jsx | 29 + .../my-sites/site-settings/section-export.jsx | 88 + .../site-settings/section-general.jsx | 33 + .../my-sites/site-settings/section-import.jsx | 219 ++ .../site-settings/section-security.jsx | 68 + .../site-settings/section-writing.jsx | 29 + .../settings-card-footer/index.jsx | 26 + .../settings-card-footer/style.scss | 26 + .../site-settings/start-over/index.jsx | 78 + client/my-sites/site/README.md | 24 + client/my-sites/site/index.jsx | 90 + client/my-sites/site/placeholder.jsx | 27 + client/my-sites/site/style.scss | 111 + client/my-sites/sites/README.md | 24 + client/my-sites/sites/package.json | 6 + client/my-sites/sites/site-card.jsx | 168 ++ client/my-sites/sites/sites.jsx | 236 ++ client/my-sites/stats/README.md | 199 ++ client/my-sites/stats/action-follow.jsx | 67 + client/my-sites/stats/action-link.jsx | 32 + client/my-sites/stats/action-page.jsx | 36 + client/my-sites/stats/action-spam.jsx | 76 + client/my-sites/stats/all-time/index.jsx | 120 ++ client/my-sites/stats/all-time/style.scss | 135 ++ client/my-sites/stats/controller.js | 755 +++++++ client/my-sites/stats/download-csv/README.md | 22 + client/my-sites/stats/download-csv/index.jsx | 78 + client/my-sites/stats/follows.jsx | 67 + client/my-sites/stats/geochart/README.md | 20 + client/my-sites/stats/geochart/index.jsx | 133 ++ client/my-sites/stats/geochart/style.scss | 16 + client/my-sites/stats/index.js | 49 + client/my-sites/stats/info-panel.jsx | 199 ++ client/my-sites/stats/insights.jsx | 129 ++ client/my-sites/stats/mixin-skeleton.js | 30 + client/my-sites/stats/mixin-toggle.js | 91 + client/my-sites/stats/module-chart-tabs.jsx | 247 +++ client/my-sites/stats/module-comments.jsx | 239 +++ client/my-sites/stats/module-countries.jsx | 164 ++ client/my-sites/stats/module-date-picker.jsx | 75 + client/my-sites/stats/module-error.jsx | 22 + .../my-sites/stats/module-followers-page.jsx | 235 ++ client/my-sites/stats/module-followers.jsx | 249 +++ client/my-sites/stats/module-post-months.jsx | 156 ++ client/my-sites/stats/module-post-weeks.jsx | 179 ++ .../module-site-overview-placeholder.jsx | 59 + .../my-sites/stats/module-summary-chart.jsx | 163 ++ client/my-sites/stats/module-tab.jsx | 59 + client/my-sites/stats/module-tabs.jsx | 51 + .../my-sites/stats/module-video-details.jsx | 67 + client/my-sites/stats/most-popular/index.jsx | 95 + client/my-sites/stats/most-popular/style.scss | 84 + client/my-sites/stats/nux/data.js | 62 + client/my-sites/stats/nux/insights.jsx | 129 ++ client/my-sites/stats/nux/site.jsx | 103 + client/my-sites/stats/nux/style.scss | 130 ++ client/my-sites/stats/overview/README.md | 22 + client/my-sites/stats/overview/index.jsx | 111 + client/my-sites/stats/overview/style.scss | 50 + client/my-sites/stats/pagination/README.md | 22 + client/my-sites/stats/pagination/index.jsx | 75 + .../stats/pagination/pagination-page.jsx | 70 + client/my-sites/stats/pagination/style.scss | 88 + .../my-sites/stats/post-performance/README.md | 20 + .../my-sites/stats/post-performance/index.jsx | 208 ++ client/my-sites/stats/post.jsx | 68 + client/my-sites/stats/site.jsx | 323 +++ client/my-sites/stats/stats-list-item.jsx | 289 +++ client/my-sites/stats/stats-list.jsx | 72 + client/my-sites/stats/stats-module.jsx | 144 ++ client/my-sites/stats/stats-navigation.jsx | 53 + client/my-sites/stats/stats-overview.jsx | 151 ++ client/my-sites/stats/stats-strings.js | 63 + client/my-sites/stats/summary.jsx | 203 ++ client/my-sites/upgrades/README.md | 6 + client/my-sites/upgrades/cart/Makefile | 7 + client/my-sites/upgrades/cart/README.md | 7 + client/my-sites/upgrades/cart/cart-body.jsx | 50 + .../my-sites/upgrades/cart/cart-buttons.jsx | 68 + client/my-sites/upgrades/cart/cart-coupon.jsx | 98 + client/my-sites/upgrades/cart/cart-empty.jsx | 39 + client/my-sites/upgrades/cart/cart-item.jsx | 164 ++ client/my-sites/upgrades/cart/cart-items.jsx | 82 + .../upgrades/cart/cart-messages-mixin.jsx | 69 + .../my-sites/upgrades/cart/cart-plan-ad.jsx | 45 + .../upgrades/cart/cart-summary-bar.jsx | 39 + client/my-sites/upgrades/cart/cart-total.jsx | 56 + .../my-sites/upgrades/cart/popover-cart.jsx | 143 ++ .../my-sites/upgrades/cart/secondary-cart.jsx | 38 + client/my-sites/upgrades/cart/style.scss | 331 +++ .../upgrades/cart/test/test-cart-buttons.jsx | 62 + client/my-sites/upgrades/checkout/README.md | 4 + .../my-sites/upgrades/checkout/checkout.jsx | 154 ++ .../checkout/credit-card-payment-box.jsx | 72 + .../checkout/credit-card-selector.jsx | 95 + .../upgrades/checkout/credits-payment-box.jsx | 64 + .../upgrades/checkout/domain-details-form.jsx | 318 +++ .../checkout/free-cart-payment-box.jsx | 81 + .../upgrades/checkout/new-card-form.jsx | 60 + .../my-sites/upgrades/checkout/package.json | 6 + .../my-sites/upgrades/checkout/pay-button.jsx | 142 ++ .../upgrades/checkout/payment-box.jsx | 25 + .../upgrades/checkout/paypal-payment-box.jsx | 182 ++ .../checkout/privacy-protection-dialog.jsx | 86 + .../checkout/privacy-protection-example.jsx | 86 + .../upgrades/checkout/privacy-protection.jsx | 128 ++ .../upgrades/checkout/secure-payment-form.jsx | 203 ++ .../upgrades/checkout/stored-card.jsx | 25 + .../upgrades/checkout/stored-card.scss | 64 + .../upgrades/checkout/subscription-text.jsx | 27 + .../upgrades/checkout/subscription-text.scss | 14 + .../upgrades/checkout/supporting-text.jsx | 88 + .../upgrades/checkout/terms-of-service.jsx | 31 + .../my-sites/upgrades/checkout/thank-you.jsx | 640 ++++++ .../checkout/transaction-steps-mixin.jsx | 179 ++ client/my-sites/upgrades/components/README.md | 4 + .../components/domain-warnings/Makefile | 12 + .../components/domain-warnings/index.jsx | 195 ++ .../test/test-domain-warnings.jsx | 128 ++ .../components/form/country-select.jsx | 77 + .../upgrades/components/form/focus-mixin.js | 38 + .../upgrades/components/form/hidden-input.jsx | 50 + .../upgrades/components/form/input.jsx | 95 + .../upgrades/components/form/state-select.jsx | 73 + client/my-sites/upgrades/controller.jsx | 254 +++ .../upgrades/domain-management/README.md | 21 + .../add-email-addresses-card.jsx | 305 +++ .../add-google-apps/domains-select.jsx | 47 + .../add-google-apps/index.jsx | 71 + .../components/domain/main-placeholder.jsx | 38 + .../components/domain/primary-flag.jsx | 32 + .../components/form-footer/index.jsx | 21 + .../components/header/index.jsx | 32 + .../components/icann-verification.jsx | 70 + .../contacts-privacy/card.jsx | 97 + .../contacts-privacy/contact-display.jsx | 38 + .../contacts-privacy/index.jsx | 81 + .../upgrades/domain-management/controller.jsx | 313 +++ .../domain-management/dns/a-record.jsx | 65 + .../domain-management/dns/cname-record.jsx | 60 + .../domain-management/dns/dns-add-new.jsx | 187 ++ .../domain-management/dns/dns-details.jsx | 21 + .../domain-management/dns/dns-list.jsx | 53 + .../domain-management/dns/dns-record.jsx | 100 + .../upgrades/domain-management/dns/index.jsx | 77 + .../domain-management/dns/mx-record.jsx | 73 + .../domain-management/dns/srv-record.jsx | 117 + .../domain-management/dns/txt-record.jsx | 69 + .../domain-management/domain-management.jsx | 15 + .../edit-contact-info/form-card.jsx | 289 +++ .../edit-contact-info/index.jsx | 73 + .../privacy-enabled-card.jsx | 31 + .../edit/card/header/index.jsx | 44 + .../card/header/primary-domain-button.jsx | 56 + .../domain-management/edit/card/property.jsx | 21 + .../edit/card/subscription-settings.jsx | 23 + .../upgrades/domain-management/edit/index.jsx | 68 + .../domain-management/edit/mapped-domain.jsx | 112 + .../edit/registered-domain.jsx | 199 ++ .../domain-management/edit/site-redirect.jsx | 82 + .../domain-management/edit/wpcom-domain.jsx | 53 + .../email-forwarding-add-new.jsx | 196 ++ .../email-forwarding-details.jsx | 36 + .../email-forwarding-item.jsx | 58 + .../email-forwarding-limit.jsx | 26 + .../email-forwarding-list.jsx | 38 + .../email-forwarding/index.jsx | 69 + .../email/add-google-apps-card.jsx | 176 ++ .../email/google-apps-users-card.jsx | 145 ++ .../domain-management/email/index.jsx | 167 ++ .../upgrades/domain-management/list/index.jsx | 99 + .../list/item-placeholder.jsx | 26 + .../upgrades/domain-management/list/item.jsx | 49 + .../name-servers/custom-nameservers-form.jsx | 178 ++ .../name-servers/custom-nameservers-row.jsx | 60 + .../name-servers/icann-verification-card.jsx | 45 + .../domain-management/name-servers/index.jsx | 198 ++ .../name-servers/wpcom-nameservers-toggle.jsx | 83 + .../upgrades/domain-management/package.json | 6 + .../primary-domain/index.jsx | 135 ++ .../privacy-protection/card/add-button.jsx | 40 + .../privacy-protection/card/content.jsx | 69 + .../privacy-protection/card/header.jsx | 53 + .../privacy-protection/index.jsx | 102 + .../domain-management/site-redirect/index.jsx | 153 ++ .../site-redirect/notice.jsx | 42 + .../upgrades/domain-management/style.scss | 1006 +++++++++ .../transfer/enable-domain-locking-notice.jsx | 88 + .../transfer/enable-privacy-notice.jsx | 104 + .../transfer/icann-verification-notice.jsx | 48 + .../domain-management/transfer/index.jsx | 101 + .../transfer/pending-transfer-notice.jsx | 135 ++ .../transfer/request-transfer-code.jsx | 245 +++ .../transfer/transfer-prohibited-notice.jsx | 40 + .../my-sites/upgrades/domain-search/Makefile | 11 + .../my-sites/upgrades/domain-search/README.md | 10 + .../upgrades/domain-search/domain-search.jsx | 100 + .../upgrades/domain-search/package.json | 6 + .../domain-search/site-redirect-step.jsx | 142 ++ .../upgrades/domain-search/site-redirect.jsx | 63 + .../test/test-domain-suggestion.jsx | 46 + client/my-sites/upgrades/index.js | 284 +++ client/my-sites/upgrades/navigation.jsx | 213 ++ client/my-sites/upgrades/paths.js | 112 + client/my-sites/welcome/README.md | 67 + client/my-sites/welcome/package.json | 6 + client/my-sites/welcome/welcome.jsx | 55 + client/notices/README.md | 46 + client/notices/arrow-link.jsx | 31 + client/notices/delete-site-notices.jsx | 85 + client/notices/index.js | 191 ++ client/notices/notice.jsx | 91 + client/notices/notices-list.jsx | 95 + client/notices/simple-notice.jsx | 85 + client/notices/site-notice.jsx | 27 + client/notices/style.scss | 293 +++ client/notices/validation-error-list.jsx | 34 + client/notifications/README.md | 35 + client/notifications/index.jsx | 222 ++ client/nux-welcome/README.md | 4 + client/nux-welcome/index.js | 65 + client/nux-welcome/welcome-message.jsx | 96 + client/post-editor/Makefile | 10 + client/post-editor/README.md | 13 + client/post-editor/controller.js | 171 ++ client/post-editor/drafts-button/index.jsx | 31 + client/post-editor/drafts-button/style.scss | 10 + client/post-editor/edit-post-status/index.jsx | 236 ++ .../post-editor/edit-post-status/style.scss | 79 + .../post-editor/editor-action-bar/index.jsx | 106 + .../post-editor/editor-action-bar/style.scss | 40 + client/post-editor/editor-author/index.jsx | 76 + client/post-editor/editor-author/style.scss | 31 + .../post-editor/editor-categories/index.jsx | 118 + .../post-editor/editor-categories/style.scss | 25 + .../post-editor/editor-delete-post/index.jsx | 97 + .../post-editor/editor-delete-post/style.scss | 16 + client/post-editor/editor-discussion/Makefile | 7 + .../post-editor/editor-discussion/index.jsx | 109 + .../post-editor/editor-discussion/style.scss | 8 + .../editor-discussion/test/index.jsx | 179 ++ .../post-editor/editor-drawer-well/index.jsx | 79 + .../post-editor/editor-drawer-well/style.scss | 62 + client/post-editor/editor-drawer/index.jsx | 290 +++ client/post-editor/editor-drawer/style.scss | 56 + .../editor-featured-image/index.jsx | 131 ++ .../preview-container.jsx | 87 + .../editor-featured-image/preview.jsx | 49 + .../editor-featured-image/style.scss | 39 + client/post-editor/editor-fieldset/README.md | 30 + client/post-editor/editor-fieldset/index.jsx | 31 + client/post-editor/editor-fieldset/style.scss | 23 + .../editor-ground-control/Makefile | 10 + .../editor-ground-control/index.jsx | 424 ++++ .../editor-ground-control/style.scss | 150 ++ .../editor-ground-control/test/index.jsx | 461 ++++ client/post-editor/editor-location/index.jsx | 145 ++ .../editor-location/search-result.jsx | 29 + client/post-editor/editor-location/search.jsx | 112 + client/post-editor/editor-location/style.scss | 54 + .../editor-mobile-navigation/index.jsx | 36 + .../editor-mobile-navigation/style.scss | 35 + .../post-editor/editor-more-options/slug.jsx | 49 + .../editor-more-options/style.scss | 12 + .../post-editor/editor-page-order/index.jsx | 73 + .../post-editor/editor-page-order/style.scss | 16 + .../post-editor/editor-page-parent/index.jsx | 55 + .../post-editor/editor-page-parent/style.scss | 48 + client/post-editor/editor-page-slug/index.jsx | 33 + .../editor-page-templates/index.jsx | 85 + client/post-editor/editor-permalink/index.jsx | 144 ++ .../post-editor/editor-permalink/style.scss | 48 + .../editor-post-formats/accordion.jsx | 80 + .../post-editor/editor-post-formats/index.jsx | 102 + .../editor-post-formats/style.scss | 29 + client/post-editor/editor-post-type/index.jsx | 107 + .../post-editor/editor-post-type/style.scss | 45 + client/post-editor/editor-preview/index.jsx | 95 + client/post-editor/editor-revisions/index.jsx | 55 + .../post-editor/editor-revisions/style.scss | 27 + client/post-editor/editor-sharing/Makefile | 10 + .../post-editor/editor-sharing/accordion.jsx | 126 ++ client/post-editor/editor-sharing/index.jsx | 83 + .../editor-sharing/publicize-connection.jsx | 106 + .../editor-sharing/publicize-message.jsx | 97 + .../editor-sharing/publicize-message.scss | 27 + .../editor-sharing/publicize-options.jsx | 215 ++ .../editor-sharing/publicize-options.scss | 40 + .../editor-sharing/publicize-services.jsx | 56 + .../editor-sharing/publicize-services.scss | 12 + .../editor-sharing/sharing-like-options.jsx | 111 + client/post-editor/editor-sharing/style.scss | 74 + .../post-editor/editor-sharing/test/index.js | 3 + .../test/specs/publicize-connection.jsx | 113 + client/post-editor/editor-slug/index.jsx | 127 ++ client/post-editor/editor-slug/style.scss | 39 + client/post-editor/editor-tags/index.jsx | 89 + client/post-editor/editor-taxonomies/Makefile | 10 + .../editor-taxonomies/accordion.jsx | 201 ++ .../editor-taxonomies/test/accordion.jsx | 182 ++ client/post-editor/editor-title/container.jsx | 52 + client/post-editor/editor-title/index.jsx | 110 + client/post-editor/editor-title/style.scss | 55 + .../post-editor/editor-visibility/index.jsx | 390 ++++ .../post-editor/editor-visibility/style.scss | 66 + client/post-editor/index.js | 25 + client/post-editor/invalid-url-dialog.jsx | 91 + client/post-editor/media-modal/Makefile | 10 + .../media-modal/back-to-library.jsx | 17 + client/post-editor/media-modal/constants.js | 10 + .../media-modal/detail/_style.scss | 191 ++ .../media-modal/detail/detail-fields.jsx | 140 ++ .../media-modal/detail/detail-file-info.jsx | 106 + .../media-modal/detail/detail-item.jsx | 131 ++ .../detail/detail-preview-audio.jsx | 26 + .../detail/detail-preview-document.jsx | 21 + .../detail/detail-preview-image.jsx | 36 + .../detail/detail-preview-video.jsx | 31 + .../detail/detail-preview-videopress.jsx | 47 + .../media-modal/detail/detail-title.jsx | 98 + .../post-editor/media-modal/detail/index.jsx | 83 + client/post-editor/media-modal/fieldset.jsx | 25 + client/post-editor/media-modal/fieldset.scss | 35 + .../media-modal/gallery-help-container.jsx | 96 + .../post-editor/media-modal/gallery-help.jsx | 109 + .../media-modal/gallery/caption.jsx | 68 + .../media-modal/gallery/drop-zone.jsx | 52 + .../media-modal/gallery/edit-item.jsx | 51 + .../post-editor/media-modal/gallery/edit.jsx | 62 + .../media-modal/gallery/fields.jsx | 162 ++ .../post-editor/media-modal/gallery/index.jsx | 155 ++ .../media-modal/gallery/preview.jsx | 122 ++ .../media-modal/gallery/remove-button.jsx | 47 + .../media-modal/gallery/style.scss | 242 +++ client/post-editor/media-modal/index.jsx | 389 ++++ client/post-editor/media-modal/index.scss | 324 +++ client/post-editor/media-modal/markup.js | 215 ++ .../post-editor/media-modal/preload-image.js | 10 + .../media-modal/secondary-actions.jsx | 166 ++ client/post-editor/media-modal/style.scss | 4 + client/post-editor/media-modal/test/index.js | 5 + .../media-modal/test/specs/index.jsx | 169 ++ .../media-modal/test/specs/markup.js | 305 +++ .../media-modal/test/specs/preload-image.js | 52 + client/post-editor/post-editor.jsx | 838 ++++++++ client/post-editor/restore-post-dialog.jsx | 95 + client/post-editor/status-label.jsx | 173 ++ client/post-editor/style.scss | 334 +++ client/post-editor/test/post-editor.jsx | 159 ++ client/reader/README.md | 12 + client/reader/_style.scss | 325 +++ client/reader/comments/README.md | 7 + client/reader/comments/comment-likes.jsx | 67 + client/reader/comments/form.jsx | 195 ++ client/reader/comments/helper.jsx | 19 + client/reader/comments/index.jsx | 337 +++ client/reader/comments/style.scss | 243 +++ client/reader/controller.js | 536 +++++ client/reader/discover/README.md | 3 + client/reader/discover/_style.scss | 73 + client/reader/discover/helper.jsx | 45 + client/reader/discover/post-attribution.jsx | 46 + client/reader/discover/site-attribution.jsx | 41 + client/reader/discover/visit-link.jsx | 40 + client/reader/feed-error/README.md | 7 + client/reader/feed-error/index.jsx | 30 + client/reader/feed-header/README.md | 8 + client/reader/feed-header/index.jsx | 83 + client/reader/feed-header/style.scss | 168 ++ client/reader/feed-stream/README.md | 9 + client/reader/feed-stream/empty.jsx | 45 + client/reader/feed-stream/index.jsx | 150 ++ client/reader/follow-button/README.md | 10 + client/reader/follow-button/index.jsx | 36 + client/reader/following-edit/README.md | 9 + client/reader/following-edit/helper.jsx | 36 + client/reader/following-edit/index.jsx | 367 ++++ client/reader/following-edit/list-item.jsx | 127 ++ client/reader/following-edit/navigation.jsx | 33 + .../following-edit/notification-settings.jsx | 175 ++ client/reader/following-edit/placeholder.jsx | 25 + .../reader/following-edit/sort-controls.jsx | 45 + client/reader/following-edit/style.scss | 293 +++ .../following-edit/subscribe-form-result.jsx | 44 + .../reader/following-edit/subscribe-form.jsx | 151 ++ client/reader/following-stream/README.md | 17 + client/reader/following-stream/_style.scss | 262 +++ client/reader/following-stream/empty.jsx | 45 + client/reader/following-stream/index.jsx | 440 ++++ .../reader/following-stream/post-blocked.jsx | 33 + .../following-stream/post-placeholder.jsx | 33 + .../following-stream/post-unavailable.jsx | 41 + client/reader/following-stream/post.jsx | 433 ++++ client/reader/following-stream/x-post.jsx | 151 ++ client/reader/full-post/README.md | 13 + client/reader/full-post/_style.scss | 321 +++ client/reader/full-post/index.jsx | 447 ++++ client/reader/index.js | 81 + client/reader/like-button/README.md | 7 + client/reader/like-button/index.jsx | 21 + client/reader/like-helper.jsx | 18 + client/reader/liked-stream/README.md | 7 + client/reader/liked-stream/empty.jsx | 43 + client/reader/liked-stream/index.jsx | 22 + client/reader/list-gap/README.md | 9 + client/reader/list-gap/_style.scss | 48 + client/reader/list-gap/index.jsx | 48 + client/reader/list-item/README.md | 17 + client/reader/list-item/actions.jsx | 11 + client/reader/list-item/description.jsx | 12 + client/reader/list-item/icon.jsx | 20 + client/reader/list-item/index.jsx | 22 + client/reader/list-item/style.scss | 93 + client/reader/list-item/title.jsx | 16 + client/reader/list-management/README.md | 3 + .../reader/list-management/contents/index.jsx | 29 + .../description-edit/index.jsx | 29 + .../list-management/followers/index.jsx | 29 + .../list-management/navigation/index.jsx | 36 + client/reader/list-management/style.scss | 0 client/reader/list-stream/README.md | 9 + client/reader/list-stream/empty.jsx | 43 + client/reader/list-stream/index.jsx | 115 + client/reader/post-byline/README.md | 8 + client/reader/post-byline/_style.scss | 55 + client/reader/post-byline/index.jsx | 87 + client/reader/post-errors/README.md | 9 + client/reader/post-errors/index.jsx | 130 ++ client/reader/post-errors/style.scss | 11 + client/reader/post-excerpt-link/README.md | 8 + client/reader/post-excerpt-link/index.jsx | 60 + client/reader/post-excerpt-link/style.scss | 54 + client/reader/post-images/README.md | 7 + client/reader/post-images/_style.scss | 185 ++ client/reader/post-images/index.jsx | 186 ++ client/reader/post-options/README.md | 8 + client/reader/post-options/_style.scss | 79 + client/reader/post-options/index.jsx | 170 ++ client/reader/post-permalink/README.md | 8 + client/reader/post-permalink/index.jsx | 36 + client/reader/post-permalink/style.scss | 17 + client/reader/post-time/README.md | 7 + client/reader/post-time/index.jsx | 43 + client/reader/reading-time/README.md | 8 + client/reader/reading-time/index.jsx | 35 + client/reader/reading-time/style.scss | 8 + client/reader/recommendations/README.md | 10 + .../reader/recommendations/for-you/index.jsx | 146 ++ .../recommendations/global-tags/index.jsx | 16 + .../recommendations/navigation/index.jsx | 29 + client/reader/recommendations/sites/index.jsx | 16 + client/reader/recommendations/style.scss | 6 + client/reader/share/README.md | 9 + client/reader/share/index.jsx | 154 ++ client/reader/share/style.scss | 49 + client/reader/sidebar/README.md | 7 + client/reader/sidebar/_style.scss | 104 + client/reader/sidebar/package.json | 6 + client/reader/sidebar/sidebar.jsx | 369 ++++ client/reader/site-and-author-icon/README.md | 9 + .../reader/site-and-author-icon/_style.scss | 18 + client/reader/site-and-author-icon/index.jsx | 74 + client/reader/site-link/README.md | 9 + client/reader/site-link/index.jsx | 28 + client/reader/site-stream/README.md | 8 + client/reader/site-stream/empty.jsx | 45 + client/reader/site-stream/index.jsx | 98 + client/reader/stats.js | 60 + client/reader/stream-header/README.md | 14 + client/reader/stream-header/index.jsx | 57 + client/reader/stream-header/style.scss | 161 ++ client/reader/tag-stream/README.md | 8 + client/reader/tag-stream/empty.jsx | 43 + client/reader/tag-stream/index.jsx | 91 + client/reader/update-notice/README.md | 23 + client/reader/update-notice/_style.scss | 41 + client/reader/update-notice/index.jsx | 59 + client/reader/utils.js | 27 + client/reader/xpost-helper.js | 45 + client/remove-overlay/index.js | 35 + client/sections.js | 201 ++ client/signup/Makefile | 12 + client/signup/README.md | 192 ++ client/signup/config/Makefile | 8 + client/signup/config/flows.js | 159 ++ client/signup/config/step-components.js | 22 + client/signup/config/steps.js | 67 + client/signup/config/test/lib/abtest/index.js | 5 + .../config/test/lib/signup/step-actions.js | 2 + client/signup/config/test/lib/user/index.js | 11 + client/signup/config/test/test.js | 23 + client/signup/controller.js | 128 ++ .../signup/flow-progress-indicator/index.jsx | 36 + .../signup/flow-progress-indicator/style.scss | 11 + client/signup/index.js | 30 + client/signup/locale-suggestions/index.jsx | 111 + client/signup/locale-suggestions/style.scss | 15 + client/signup/log-in-form/index.jsx | 259 +++ client/signup/logged-out-form/index.jsx | 39 + client/signup/logged-out-form/style.scss | 28 + client/signup/main.jsx | 344 +++ client/signup/phone-signup-form/index.jsx | 225 ++ client/signup/phone-signup-form/style.scss | 58 + client/signup/previous-step-button/index.jsx | 55 + client/signup/previous-step-button/style.scss | 28 + client/signup/processing-screen/index.jsx | 76 + client/signup/processing-screen/style.scss | 109 + client/signup/skip-step-button/index.jsx | 30 + client/signup/skip-step-button/style.scss | 6 + client/signup/step-header/index.jsx | 17 + client/signup/step-header/style.scss | 25 + client/signup/step-wrapper/index.jsx | 72 + client/signup/steps/domains/index.jsx | 223 ++ client/signup/steps/domains/style.scss | 4 + client/signup/steps/dss/index.jsx | 105 + client/signup/steps/dss/screenshot.jsx | 116 + client/signup/steps/dss/style.scss | 146 ++ client/signup/steps/dss/theme-thumbnail.jsx | 59 + .../signup/steps/email-signup-form/index.jsx | 116 + client/signup/steps/plans/index.jsx | 143 ++ client/signup/steps/plans/style.scss | 23 + client/signup/steps/site-creation/index.jsx | 288 +++ client/signup/steps/site-creation/style.scss | 11 + client/signup/steps/test-step/index.jsx | 36 + client/signup/steps/theme-selection/index.jsx | 59 + .../signup/steps/theme-selection/style.scss | 44 + .../steps/theme-selection/theme-thumbnail.jsx | 51 + client/signup/style.scss | 63 + client/signup/submit-step-button/index.jsx | 27 + client/signup/test/flows-test.js | 22 + client/signup/test/lib/abtest/index.js | 5 + client/signup/test/lib/user/index.js | 17 + client/signup/test/signup/config/flows.js | 24 + client/signup/test/signup/config/steps.js | 5 + client/signup/test/utils-test.js | 126 ++ client/signup/utils.js | 105 + client/signup/validation-fieldset/index.jsx | 40 + client/signup/validation-fieldset/style.scss | 31 + client/signup/wpcom-login-form/index.jsx | 43 + client/vip/README.md | 13 + client/vip/controller.js | 133 ++ client/vip/index.js | 57 + client/vip/style.scss | 0 client/vip/vip-backups/README.md | 4 + client/vip/vip-backups/index.jsx | 38 + client/vip/vip-billing/README.md | 4 + client/vip/vip-billing/index.jsx | 38 + client/vip/vip-dashboard/README.md | 4 + client/vip/vip-dashboard/index.jsx | 38 + client/vip/vip-deploys/README.md | 4 + client/vip/vip-deploys/index.jsx | 38 + client/vip/vip-logs/README.md | 4 + client/vip/vip-logs/index.jsx | 202 ++ client/vip/vip-logs/logs-table.jsx | 123 ++ client/vip/vip-logs/style.scss | 55 + client/vip/vip-support/README.md | 4 + client/vip/vip-support/index.jsx | 38 + config/README.md | 35 + config/client.json | 27 + config/desktop-mac-app-store.json | 289 +++ config/desktop.json | 285 +++ config/development.json | 312 +++ config/empty-secrets.json | 3 + config/horizon.json | 270 +++ config/production.json | 263 +++ config/stage.json | 267 +++ config/wpcalypso.json | 281 +++ docs/code-reviews.md | 27 + docs/coding-guidelines.md | 35 + docs/coding-guidelines/css.md | 279 +++ docs/coding-guidelines/html.md | 81 + docs/coding-guidelines/javascript.md | 1083 ++++++++++ docs/git-workflow.md | 31 + docs/guide/0-values.md | 23 + docs/guide/index.md | 8 + docs/guide/tech-behind-calypso.md | 93 + docs/icons.md | 69 + docs/merge-checklist.md | 21 + docs/performance.md | 13 + docs/react-component-unit-testing.md | 145 ++ docs/reactivity.md | 19 + docs/rtl.md | 11 + index.js | 27 + jsconfig.json | 10 + package.json | 131 ++ public/fonts/wpeditor.eot | Bin 0 -> 6372 bytes public/fonts/wpeditor.svg | 21 + public/fonts/wpeditor.ttf | Bin 0 -> 6204 bytes public/fonts/wpeditor.woff | Bin 0 -> 3596 bytes public/images/.gitkeep | 0 public/images/authorize/background-1.jpg | Bin 0 -> 181428 bytes public/images/authorize/background-2.jpg | Bin 0 -> 173484 bytes public/images/authorize/background-3.jpg | Bin 0 -> 155333 bytes public/images/authorize/background-4.jpg | Bin 0 -> 173279 bytes public/images/authorize/background-5.jpg | Bin 0 -> 146161 bytes public/images/authorize/background-6.jpg | Bin 0 -> 149864 bytes .../images/comments/illustration_comments.svg | 26 + public/images/delete-site/export-content.png | Bin 0 -> 12814 bytes public/images/delete-site/start-over.png | Bin 0 -> 12093 bytes public/images/devices/iframe-back.png | Bin 0 -> 936 bytes public/images/drake/drake-404.svg | 36 + public/images/drake/drake-500.svg | 44 + public/images/drake/drake-all-done.svg | 32 + public/images/drake/drake-browser.svg | 43 + public/images/drake/drake-empty-results.svg | 30 + public/images/drake/drake-jetpack.svg | 38 + public/images/drake/drake-new.svg | 30 + public/images/drake/drake-nomedia.svg | Bin 0 -> 36408 bytes public/images/drake/drake-nomenus.svg | 40 + public/images/drake/drake-nosites.svg | 38 + public/images/drake/drake-ok.svg | 33 + public/images/drake/drake-whoops.svg | 24 + .../images/favicons/favicon-development.ico | Bin 0 -> 32956 bytes public/images/favicons/favicon-horizon.ico | Bin 0 -> 32956 bytes public/images/favicons/favicon-staging.ico | Bin 0 -> 32956 bytes public/images/favicons/favicon-wpcalypso.ico | Bin 0 -> 32956 bytes public/images/loading.gif | Bin 0 -> 17794 bytes public/images/me/pattern-dark.png | Bin 0 -> 13043 bytes public/images/pages/illustration-pages.svg | 68 + public/images/pages/photolia.jpg | Bin 0 -> 166383 bytes public/images/people/mystery-person.svg | 9 + public/images/plans/plan-beginner.svg | 20 + public/images/plans/plan-business.svg | 65 + public/images/plans/plan-premium.svg | 199 ++ public/images/posts/illustration-posts.svg | 23 + public/images/related-posts/cat-blog.png | Bin 0 -> 57843 bytes public/images/related-posts/devices.jpg | Bin 0 -> 26555 bytes .../images/related-posts/mobile-wedding.jpg | Bin 0 -> 38164 bytes public/images/sharing/eventbrite-list.png | Bin 0 -> 24012 bytes public/images/sharing/eventbrite-widget.png | Bin 0 -> 20773 bytes public/images/sharing/facebook-profile.png | Bin 0 -> 66906 bytes public/images/sharing/facebook-sharing.png | Bin 0 -> 8260 bytes public/images/sharing/google-publicize.png | Bin 0 -> 56814 bytes public/images/sharing/google-sharing.png | Bin 0 -> 8373 bytes public/images/sharing/instagram-media.png | Bin 0 -> 66863 bytes public/images/sharing/instagram-widget.png | Bin 0 -> 76542 bytes public/images/sharing/linkedin-publicize.png | Bin 0 -> 51325 bytes public/images/sharing/linkedin-sharing.png | Bin 0 -> 8579 bytes public/images/sharing/path-publicize.png | Bin 0 -> 32362 bytes public/images/sharing/tumblr-publicize.png | Bin 0 -> 152087 bytes public/images/sharing/tumblr-sharing.png | Bin 0 -> 8275 bytes public/images/sharing/twitter-publicize.png | Bin 0 -> 53284 bytes public/images/sharing/twitter-timeline.png | Bin 0 -> 52498 bytes public/images/stats/chart-today.png | Bin 0 -> 3778 bytes public/images/stats/chart.png | Bin 0 -> 6492 bytes public/images/stats/chart2.png | Bin 0 -> 11051 bytes public/images/stats/date-picker.png | Bin 0 -> 33247 bytes .../images/stats/illustration-stats-intro.svg | 88 + public/images/stats/illustration-stats.svg | 43 + public/images/stats/left-arrow.svg | 7 + public/images/stats/map.jpg | Bin 0 -> 29662 bytes public/images/stats/right-arrow.svg | 7 + public/images/stats/search-engine.png | Bin 0 -> 404 bytes public/images/stats/stats-geo-chart.png | Bin 0 -> 335298 bytes public/images/upgrades/cc-amex-disabled.svg | 47 + public/images/upgrades/cc-amex.svg | 1 + .../images/upgrades/cc-discover-disabled.svg | 53 + public/images/upgrades/cc-discover.svg | 1 + .../upgrades/cc-mastercard-disabled.svg | 56 + public/images/upgrades/cc-mastercard.svg | 1 + public/images/upgrades/cc-placeholder.svg | 14 + public/images/upgrades/cc-visa-disabled.svg | 28 + public/images/upgrades/cc-visa.svg | 1 + public/images/upgrades/google-apps-logo.png | Bin 0 -> 5680 bytes public/images/upgrades/paypal-disabled.svg | 85 + public/images/upgrades/paypal.svg | 2 + public/images/upgrades/plugins/ecwid.png | Bin 0 -> 29286 bytes public/images/upgrades/plugins/gumroad.png | Bin 0 -> 26229 bytes .../images/upgrades/plugins/shopify-store.png | Bin 0 -> 34431 bytes .../tinymce/skins/wordpress/images/audio.png | Bin 0 -> 412 bytes .../skins/wordpress/images/dashicon-edit.png | Bin 0 -> 368 bytes .../skins/wordpress/images/dashicon-no.png | Bin 0 -> 339 bytes .../skins/wordpress/images/embedded.png | Bin 0 -> 8177 bytes .../skins/wordpress/images/gallery-2x.png | Bin 0 -> 447 bytes .../skins/wordpress/images/gallery.png | Bin 0 -> 379 bytes .../skins/wordpress/images/more-2x.png | Bin 0 -> 603 bytes .../tinymce/skins/wordpress/images/more.png | Bin 0 -> 414 bytes .../skins/wordpress/images/pagebreak-2x.png | Bin 0 -> 835 bytes .../skins/wordpress/images/pagebreak.png | Bin 0 -> 1140 bytes .../skins/wordpress/images/playlist-audio.png | Bin 0 -> 440 bytes .../skins/wordpress/images/playlist-video.png | Bin 0 -> 290 bytes .../tinymce/skins/wordpress/images/video.png | Bin 0 -> 363 bytes public/tinymce/skins/wordpress/wp-content.css | 539 +++++ server/README.md | 14 + server/api/Makefile | 12 + server/api/README.md | 8 + server/api/index.js | 27 + server/api/oauth.js | 61 + server/api/test/test.js | 102 + server/boot/index.js | 77 + server/build/README.md | 6 + server/build/index.js | 72 + server/bundler/README.md | 85 + server/bundler/assets.js | 13 + server/bundler/bin/bundler.js | 82 + server/bundler/bin/list-assets.js | 11 + server/bundler/hot-reloader.js | 70 + server/bundler/index.js | 63 + server/bundler/loader.js | 111 + server/bundler/plugin.js | 44 + server/bundler/utils.js | 39 + server/config/index.js | 63 + server/devdocs/README.md | 11 + server/devdocs/bin/generate-devdocs-index | 118 + server/devdocs/index.js | 202 ++ server/i18n/Makefile | 15 + server/i18n/README.md | 22 + server/i18n/bin/i18n-cli.js | 75 + server/i18n/index.js | 194 ++ server/i18n/preprocess-xgettextjs-match.js | 107 + server/i18n/test/.gitignore | 2 + .../i18n-test-example-second-file.jsx | 9 + .../i18n/test/examples/i18n-test-examples.jsx | 69 + server/i18n/test/test.js | 101 + server/i18nlint/Makefile | 7 + server/i18nlint/README.md | 45 + server/i18nlint/bin/i18nlint-cli.js | 63 + server/i18nlint/i18nlint.js | 396 ++++ server/i18nlint/test/test-i18nlint.js | 136 ++ .../testfiles/concatenation-and-quotes.js | 12 + .../test/testfiles/duplicate-placeholders.js | 20 + server/i18nlint/test/testfiles/fine.js | 29 + server/i18nlint/test/testfiles/hashbang.js | 21 + .../testfiles/missing-singular-placeholder.js | 21 + .../non-literal-translate-arguments.js | 24 + server/i18nlint/test/testfiles/testfile.jsx | 39 + server/pages/404.jade | 27 + server/pages/500.jade | 23 + server/pages/README.md | 6 + server/pages/desktop.jade | 44 + server/pages/index.jade | 97 + server/pages/index.js | 387 ++++ server/sanitize/index.js | 53 + server/user-bootstrap/index.js | 58 + server/user-bootstrap/shared-utils.js | 71 + shared/README.md | 48 + shared/components/card/README.md | 34 + shared/components/card/compact.jsx | 25 + shared/components/card/docs/example.jsx | 64 + shared/components/card/index.jsx | 40 + shared/components/card/style.scss | 56 + shared/components/data/screen-title/index.jsx | 30 + .../data/store-connection/index.jsx | 60 + .../data/themes-list-fetcher/README.md | 12 + .../data/themes-list-fetcher/index.jsx | 124 ++ shared/components/empty-content/README.md | 66 + .../empty-content/empty-content.jsx | 120 ++ .../empty-content/no-sites-message/README.md | 12 + .../empty-content/no-sites-message/index.jsx | 25 + shared/components/empty-content/package.json | 6 + shared/components/empty-content/style.scss | 60 + shared/components/gridicon/README.md | 20 + shared/components/gridicon/docs/example.jsx | 165 ++ shared/components/gridicon/index.jsx | 533 +++++ shared/components/gridicon/style.scss | 7 + shared/components/theme/Makefile | 13 + shared/components/theme/README.md | 11 + shared/components/theme/docs/example.jsx | 39 + shared/components/theme/index.jsx | 150 ++ shared/components/theme/more-button.jsx | 95 + shared/components/theme/style.scss | 225 ++ shared/components/theme/test/index.jsx | 151 ++ shared/components/themes-list/Makefile | 13 + shared/components/themes-list/README.md | 13 + shared/components/themes-list/index.jsx | 105 + shared/components/themes-list/style.scss | 14 + shared/components/themes-list/test/index.jsx | 93 + shared/dispatcher/index.js | 22 + shared/lib/formatting/Makefile | 8 + shared/lib/formatting/README.md | 4 + .../lib/formatting/decode-entities/browser.js | 5 + shared/lib/formatting/decode-entities/node.js | 1 + .../formatting/decode-entities/package.json | 10 + shared/lib/formatting/index.js | 346 +++ shared/lib/formatting/test/test.js | 93 + shared/lib/i18n-utils/Makefile | 9 + shared/lib/i18n-utils/README.md | 10 + shared/lib/i18n-utils/browser.js | 11 + shared/lib/i18n-utils/node.js | 10 + shared/lib/i18n-utils/package.json | 7 + shared/lib/i18n-utils/test/utils-test.js | 27 + shared/lib/i18n-utils/utils.js | 45 + shared/lib/mixins/emitter/index.js | 18 + shared/lib/screen-title/README.md | 5 + shared/lib/screen-title/actions.js | 36 + shared/lib/screen-title/constants.js | 11 + shared/lib/screen-title/store.js | 55 + shared/lib/screen-title/utils.js | 58 + shared/lib/themes/Makefile | 13 + shared/lib/themes/README.md | 28 + shared/lib/themes/actions.js | 220 ++ shared/lib/themes/constants.js | 31 + shared/lib/themes/helpers.js | 89 + shared/lib/themes/reducers/current-theme.js | 39 + .../lib/themes/reducers/themes-last-event.js | 45 + .../lib/themes/reducers/themes-last-query.js | 45 + shared/lib/themes/reducers/themes-list.js | 138 ++ shared/lib/themes/reducers/themes.js | 46 + shared/lib/themes/stores/current-theme.js | 14 + shared/lib/themes/stores/themes-last-event.js | 12 + shared/lib/themes/stores/themes-last-query.js | 18 + shared/lib/themes/stores/themes-list.js | 15 + shared/lib/themes/stores/themes.js | 16 + shared/lib/themes/test/current-theme-store.js | 38 + shared/lib/themes/test/themes-list-store.js | 173 ++ shared/lib/themes/test/themes-store.js | 74 + shared/lib/url/index.js | 23 + shared/lib/wp/README.md | 10 + shared/lib/wp/browser.js | 36 + shared/lib/wp/node.js | 6 + shared/lib/wp/package.json | 7 + shared/lib/wpcom-undocumented/README.md | 16 + shared/lib/wpcom-undocumented/index.js | 75 + shared/lib/wpcom-undocumented/lib/export.js | 74 + .../wpcom-undocumented/lib/mailing-list.js | 117 + shared/lib/wpcom-undocumented/lib/me.js | 288 +++ shared/lib/wpcom-undocumented/lib/site.js | 196 ++ .../wpcom-undocumented/lib/undocumented.js | 1760 +++++++++++++++ shared/my-sites/themes/README.md | 28 + shared/my-sites/themes/controller.js | 60 + .../my-sites/themes/current-theme/README.md | 10 + .../my-sites/themes/current-theme/button.jsx | 45 + .../my-sites/themes/current-theme/index.jsx | 73 + .../my-sites/themes/current-theme/style.scss | 128 ++ shared/my-sites/themes/index.js | 43 + .../jetpack-manage-disabled-message.jsx | 45 + .../themes/jetpack-upgrade-message.jsx | 33 + shared/my-sites/themes/main.jsx | 154 ++ shared/my-sites/themes/style.scss | 68 + shared/my-sites/themes/thanks-modal.jsx | 152 ++ shared/my-sites/themes/theme-options.js | 124 ++ .../themes/themes-search-card/index.jsx | 147 ++ .../themes-search-card/select-dropdown.jsx | 56 + .../themes/themes-search-card/style.scss | 31 + shared/my-sites/themes/themes-selection.jsx | 119 ++ .../themes/themes-site-selector-modal.jsx | 76 + webpack.config.js | 116 + webpack.config.node.js | 80 + 2838 files changed, 245118 insertions(+) create mode 100644 .dockerignore create mode 100644 .editorconfig create mode 100644 .esformatter create mode 100644 .eslintignore create mode 100644 .eslintrc create mode 100644 .gitignore create mode 100644 .jsfmtrc create mode 100644 .npmrc create mode 100644 .rtlcssrc create mode 100644 CONTRIBUTING.md create mode 100644 CREDITS.md create mode 100644 Dockerfile create mode 100644 LICENSE.md create mode 100644 Makefile create mode 100644 README.md create mode 100644 Vagrantfile create mode 100644 Vagrantfile-boot2docker create mode 100644 assets/stylesheets/README.md create mode 100644 assets/stylesheets/_components.scss create mode 100644 assets/stylesheets/editor.scss create mode 100644 assets/stylesheets/layout/_detail-page.scss create mode 100644 assets/stylesheets/layout/_main.scss create mode 100644 assets/stylesheets/layout/_masterbar.scss create mode 100644 assets/stylesheets/layout/_overlay.scss create mode 100644 assets/stylesheets/layout/_sidebar.scss create mode 100644 assets/stylesheets/sections/_billing-history.scss create mode 100644 assets/stylesheets/sections/_checkout.scss create mode 100644 assets/stylesheets/sections/_devdocs.scss create mode 100644 assets/stylesheets/sections/_domain-search.scss create mode 100644 assets/stylesheets/sections/_keyboard-shortcuts.scss create mode 100644 assets/stylesheets/sections/_manage.scss create mode 100644 assets/stylesheets/sections/_menus.scss create mode 100644 assets/stylesheets/sections/_notifications.scss create mode 100644 assets/stylesheets/sections/_nux-welcome.scss create mode 100644 assets/stylesheets/sections/_plugins.scss create mode 100644 assets/stylesheets/sections/_post-relative-time-status.scss create mode 100644 assets/stylesheets/sections/_posts-controls.scss create mode 100644 assets/stylesheets/sections/_posts.scss create mode 100644 assets/stylesheets/sections/_sharing.scss create mode 100644 assets/stylesheets/sections/_site-settings.scss create mode 100644 assets/stylesheets/sections/_sites.scss create mode 100644 assets/stylesheets/sections/_stats.scss create mode 100644 assets/stylesheets/sections/_translator.scss create mode 100644 assets/stylesheets/sections/_updated-confirmation.scss create mode 100644 assets/stylesheets/sections/_upgrades.scss create mode 100644 assets/stylesheets/shared/_animation.scss create mode 100644 assets/stylesheets/shared/_colors.scss create mode 100644 assets/stylesheets/shared/_dropdowns.scss create mode 100644 assets/stylesheets/shared/_extends.scss create mode 100644 assets/stylesheets/shared/_forms.scss create mode 100644 assets/stylesheets/shared/_functions.scss create mode 100644 assets/stylesheets/shared/_infinite-scroll-end.scss create mode 100644 assets/stylesheets/shared/_livechat.scss create mode 100644 assets/stylesheets/shared/_reset.scss create mode 100644 assets/stylesheets/shared/_toolbar-bulk.scss create mode 100644 assets/stylesheets/shared/_typography.scss create mode 100644 assets/stylesheets/shared/_utilities.scss create mode 100644 assets/stylesheets/shared/_welcome.scss create mode 100644 assets/stylesheets/shared/mixins/_breakpoints.scss create mode 100644 assets/stylesheets/shared/mixins/_calc.scss create mode 100644 assets/stylesheets/shared/mixins/_clear-fix.scss create mode 100644 assets/stylesheets/shared/mixins/_dropdown-menu.scss create mode 100644 assets/stylesheets/shared/mixins/_hide-content-accessibly.scss create mode 100644 assets/stylesheets/shared/mixins/_long-content-fade.scss create mode 100644 assets/stylesheets/shared/mixins/_mixins.scss create mode 100644 assets/stylesheets/shared/mixins/_noticon.scss create mode 100644 assets/stylesheets/shared/mixins/_placeholder.scss create mode 100644 assets/stylesheets/shared/mixins/_stats-fade-text.scss create mode 100644 assets/stylesheets/style.scss create mode 120000 bin/bundler create mode 120000 bin/generate-devdocs-index create mode 120000 bin/get-i18n create mode 120000 bin/i18nlint create mode 120000 bin/list-assets create mode 100755 bin/live-reload create mode 100755 bin/pre-commit create mode 100755 bin/pre-push create mode 100755 bin/record-env create mode 100755 bin/run-all-tests create mode 100755 bin/run-tests create mode 100755 bin/update-dependency create mode 100644 client/README.md create mode 100644 client/accept-invite/actions.js create mode 100644 client/accept-invite/controller.js create mode 100644 client/accept-invite/index.js create mode 100644 client/accept-invite/invite-form-header/index.jsx create mode 100644 client/accept-invite/invite-form-header/style.scss create mode 100644 client/accept-invite/invite-header/index.jsx create mode 100644 client/accept-invite/invite-header/mock-data.js create mode 100644 client/accept-invite/invite-header/style.scss create mode 100644 client/accept-invite/logged-in-accept/index.jsx create mode 100644 client/accept-invite/logged-in-accept/style.scss create mode 100644 client/accept-invite/logged-out-invite/index.jsx create mode 100644 client/accept-invite/logged-out-invite/signup-form.jsx create mode 100644 client/accept-invite/logged-out-invite/style.scss create mode 100644 client/accept-invite/main.jsx create mode 100644 client/accept-invite/style.scss create mode 100644 client/analytics/Makefile create mode 100644 client/analytics/README.md create mode 100644 client/analytics/ad-tracking.js create mode 100644 client/analytics/index.js create mode 100644 client/analytics/super-props.js create mode 100644 client/analytics/test/analytics-tests.js create mode 100644 client/analytics/test/config.js create mode 100644 client/analytics/test/load-script.js create mode 100644 client/auth/Makefile create mode 100644 client/auth/controller.js create mode 100644 client/auth/index.js create mode 100644 client/auth/login.jsx create mode 100644 client/auth/style.scss create mode 100644 client/auth/test/login.jsx create mode 100644 client/boot/README.md create mode 100644 client/boot/index.js create mode 100644 client/components/README.md create mode 100644 client/components/accordion/Makefile create mode 100644 client/components/accordion/README.md create mode 100644 client/components/accordion/docs/example.jsx create mode 100644 client/components/accordion/index.jsx create mode 100644 client/components/accordion/section.jsx create mode 100644 client/components/accordion/style.scss create mode 100644 client/components/accordion/test/index.jsx create mode 100644 client/components/add-new-button/README.md create mode 100644 client/components/add-new-button/docs/example.jsx create mode 100644 client/components/add-new-button/index.jsx create mode 100644 client/components/add-new-button/style.scss create mode 100644 client/components/author-selector/README.md create mode 100644 client/components/author-selector/index.jsx create mode 100644 client/components/author-selector/style.scss create mode 100644 client/components/bulk-select/README.md create mode 100644 client/components/bulk-select/docs/example.jsx create mode 100644 client/components/bulk-select/index.jsx create mode 100644 client/components/bulk-select/style.scss create mode 100644 client/components/button-group/README.md create mode 100644 client/components/button-group/docs/example.jsx create mode 100644 client/components/button-group/index.jsx create mode 100644 client/components/button-group/style.scss create mode 100644 client/components/button/README.md create mode 100644 client/components/button/docs/example.jsx create mode 100644 client/components/button/index.jsx create mode 100644 client/components/button/style.scss create mode 100644 client/components/chart/README.md create mode 100644 client/components/chart/bar-container.jsx create mode 100644 client/components/chart/bar.jsx create mode 100644 client/components/chart/index.jsx create mode 100644 client/components/chart/label.jsx create mode 100644 client/components/chart/legend.jsx create mode 100644 client/components/chart/style.scss create mode 100644 client/components/chart/tooltip.jsx create mode 100644 client/components/chart/x-axis.jsx create mode 100644 client/components/comment-button/README.md create mode 100644 client/components/comment-button/docs/example.jsx create mode 100644 client/components/comment-button/index.jsx create mode 100644 client/components/comment-button/style.scss create mode 100644 client/components/count/Makefile create mode 100644 client/components/count/README.md create mode 100644 client/components/count/docs/example.jsx create mode 100644 client/components/count/index.jsx create mode 100644 client/components/count/style.scss create mode 100644 client/components/count/test/index.jsx create mode 100644 client/components/data/activating-theme/README.md create mode 100644 client/components/data/activating-theme/index.js create mode 100644 client/components/data/cart/README.md create mode 100644 client/components/data/cart/index.jsx create mode 100644 client/components/data/category-list-data/README.md create mode 100644 client/components/data/category-list-data/index.jsx create mode 100644 client/components/data/checkout/README.md create mode 100644 client/components/data/checkout/index.jsx create mode 100644 client/components/data/current-theme/README.md create mode 100644 client/components/data/current-theme/index.js create mode 100644 client/components/data/domain-management/README.md create mode 100644 client/components/data/domain-management/dns/README.md create mode 100644 client/components/data/domain-management/dns/index.jsx create mode 100644 client/components/data/domain-management/email-forwarding/README.md create mode 100644 client/components/data/domain-management/email-forwarding/index.jsx create mode 100644 client/components/data/domain-management/email/README.md create mode 100644 client/components/data/domain-management/email/index.jsx create mode 100644 client/components/data/domain-management/index.jsx create mode 100644 client/components/data/domain-management/nameservers/README.md create mode 100644 client/components/data/domain-management/nameservers/index.jsx create mode 100644 client/components/data/domain-management/primary-domain/README.md create mode 100644 client/components/data/domain-management/primary-domain/index.jsx create mode 100644 client/components/data/domain-management/site-redirect/README.md create mode 100644 client/components/data/domain-management/site-redirect/index.jsx create mode 100644 client/components/data/domain-management/transfer/README.md create mode 100644 client/components/data/domain-management/transfer/index.jsx create mode 100644 client/components/data/domain-management/whois/README.md create mode 100644 client/components/data/domain-management/whois/index.jsx create mode 100644 client/components/data/email-followers-data/README.md create mode 100644 client/components/data/email-followers-data/index.jsx create mode 100644 client/components/data/followers-data/README.md create mode 100644 client/components/data/followers-data/index.jsx create mode 100644 client/components/data/media-library-selected-data/README.md create mode 100644 client/components/data/media-library-selected-data/index.jsx create mode 100644 client/components/data/media-list-data/Makefile create mode 100644 client/components/data/media-list-data/README.md create mode 100644 client/components/data/media-list-data/index.jsx create mode 100644 client/components/data/media-list-data/test/index.js create mode 100644 client/components/data/media-list-data/test/specs/utils.js create mode 100644 client/components/data/media-list-data/utils.js create mode 100644 client/components/data/media-validation-data/README.md create mode 100644 client/components/data/media-validation-data/index.jsx create mode 100644 client/components/data/page-templates-data/README.md create mode 100644 client/components/data/page-templates-data/index.jsx create mode 100644 client/components/data/post-counts-data/README.md create mode 100644 client/components/data/post-counts-data/index.jsx create mode 100644 client/components/data/post-formats-data/README.md create mode 100644 client/components/data/post-formats-data/index.jsx create mode 100644 client/components/data/preferences-data/README.md create mode 100644 client/components/data/preferences-data/index.jsx create mode 100644 client/components/data/purchases/README.md create mode 100644 client/components/data/purchases/edit-card-details/index.jsx create mode 100644 client/components/data/purchases/index.jsx create mode 100644 client/components/data/purchases/manage-purchase/index.jsx create mode 100644 client/components/data/sharing-connections-data/Makefile create mode 100644 client/components/data/sharing-connections-data/README.md create mode 100644 client/components/data/sharing-connections-data/index.jsx create mode 100644 client/components/data/sharing-connections-data/test/index.jsx create mode 100644 client/components/data/tag-list-data/README.md create mode 100644 client/components/data/tag-list-data/index.jsx create mode 100644 client/components/data/viewers-data/README.md create mode 100644 client/components/data/viewers-data/index.jsx create mode 100644 client/components/date-picker/README.md create mode 100644 client/components/date-picker/day.jsx create mode 100644 client/components/date-picker/docs/example.jsx create mode 100644 client/components/date-picker/index.jsx create mode 100644 client/components/date-picker/style.scss create mode 100644 client/components/dialog/README.md create mode 100644 client/components/dialog/dialog-base.jsx create mode 100644 client/components/dialog/index.jsx create mode 100644 client/components/dialog/style.scss create mode 100644 client/components/domains/README.md create mode 100644 client/components/domains/domain-mapping-suggestion/index.jsx create mode 100644 client/components/domains/domain-mapping-suggestion/style.scss create mode 100644 client/components/domains/domain-product-price/index.jsx create mode 100644 client/components/domains/domain-product-price/style.scss create mode 100644 client/components/domains/domain-registration-suggestion/index.jsx create mode 100644 client/components/domains/domain-search-results/index.jsx create mode 100644 client/components/domains/domain-search-results/style.scss create mode 100644 client/components/domains/domain-suggestion/index.jsx create mode 100644 client/components/domains/domain-suggestion/style.scss create mode 100644 client/components/domains/example-domain-suggestions/index.jsx create mode 100644 client/components/domains/example-domain-suggestions/style.scss create mode 100644 client/components/domains/map-domain-step/index.jsx create mode 100644 client/components/domains/map-domain-step/style.scss create mode 100644 client/components/domains/map-domain/index.jsx create mode 100644 client/components/domains/register-domain-step/index.jsx create mode 100644 client/components/domains/register-domain-step/style.scss create mode 100644 client/components/drop-zone/Makefile create mode 100644 client/components/drop-zone/README.md create mode 100644 client/components/drop-zone/docs/example.jsx create mode 100644 client/components/drop-zone/index.jsx create mode 100644 client/components/drop-zone/style.scss create mode 100644 client/components/drop-zone/test/index.jsx create mode 100644 client/components/email-verification/README.md create mode 100644 client/components/email-verification/email-verification-notice.jsx create mode 100644 client/components/email-verification/index.js create mode 100644 client/components/emojify/README.md create mode 100644 client/components/emojify/index.jsx create mode 100644 client/components/emojify/style.scss create mode 100644 client/components/external-link/README.md create mode 100644 client/components/external-link/docs/example.jsx create mode 100644 client/components/external-link/index.jsx create mode 100644 client/components/external-link/style.scss create mode 100644 client/components/flag/README.md create mode 100644 client/components/flag/docs/example.jsx create mode 100644 client/components/flag/index.jsx create mode 100644 client/components/flag/style.scss create mode 100644 client/components/foldable-card/README.md create mode 100644 client/components/foldable-card/docs/example.jsx create mode 100644 client/components/foldable-card/index.jsx create mode 100644 client/components/foldable-card/style.scss create mode 100644 client/components/follow-button/README.md create mode 100644 client/components/follow-button/_style.scss create mode 100644 client/components/follow-button/button.jsx create mode 100644 client/components/follow-button/docs/example.jsx create mode 100644 client/components/follow-button/index.jsx create mode 100644 client/components/follow-button/style.scss create mode 100644 client/components/forms/README.md create mode 100644 client/components/forms/clipboard-button/README.md create mode 100644 client/components/forms/clipboard-button/docs/example.jsx create mode 100644 client/components/forms/clipboard-button/index.jsx create mode 100644 client/components/forms/counted-textarea/Makefile create mode 100644 client/components/forms/counted-textarea/README.md create mode 100644 client/components/forms/counted-textarea/docs/example.jsx create mode 100644 client/components/forms/counted-textarea/index.jsx create mode 100644 client/components/forms/counted-textarea/style.scss create mode 100644 client/components/forms/counted-textarea/test/index.jsx create mode 100644 client/components/forms/docs/example.jsx create mode 100644 client/components/forms/form-button/index.jsx create mode 100644 client/components/forms/form-button/style.scss create mode 100644 client/components/forms/form-buttons-bar/index.jsx create mode 100644 client/components/forms/form-buttons-bar/style.scss create mode 100644 client/components/forms/form-checkbox/index.jsx create mode 100644 client/components/forms/form-country-select/index.jsx create mode 100644 client/components/forms/form-country-select/style.scss create mode 100644 client/components/forms/form-fieldset/index.jsx create mode 100644 client/components/forms/form-fieldset/style.scss create mode 100644 client/components/forms/form-input-validation/index.jsx create mode 100644 client/components/forms/form-input-validation/style.scss create mode 100644 client/components/forms/form-label/index.jsx create mode 100644 client/components/forms/form-label/style.scss create mode 100644 client/components/forms/form-legend/index.jsx create mode 100644 client/components/forms/form-legend/style.scss create mode 100644 client/components/forms/form-password-input/index.jsx create mode 100644 client/components/forms/form-password-input/style.scss create mode 100644 client/components/forms/form-phone-input/Makefile create mode 100644 client/components/forms/form-phone-input/index.jsx create mode 100644 client/components/forms/form-phone-input/test/index.jsx create mode 100644 client/components/forms/form-phone-input/test/mock-countries-list-empty.js create mode 100644 client/components/forms/form-phone-input/test/mock-countries-list.js create mode 100644 client/components/forms/form-radio/index.jsx create mode 100644 client/components/forms/form-range/index.jsx create mode 100644 client/components/forms/form-range/style.scss create mode 100644 client/components/forms/form-section-heading/index.jsx create mode 100644 client/components/forms/form-section-heading/style.scss create mode 100644 client/components/forms/form-select/index.jsx create mode 100644 client/components/forms/form-select/style.scss create mode 100644 client/components/forms/form-setting-explanation/index.jsx create mode 100644 client/components/forms/form-setting-explanation/style.scss create mode 100644 client/components/forms/form-tel-input/index.jsx create mode 100644 client/components/forms/form-tel-input/style.scss create mode 100644 client/components/forms/form-text-input-with-affixes/README.md create mode 100644 client/components/forms/form-text-input-with-affixes/index.jsx create mode 100644 client/components/forms/form-text-input-with-affixes/style.scss create mode 100644 client/components/forms/form-text-input/index.jsx create mode 100644 client/components/forms/form-text-input/style.scss create mode 100644 client/components/forms/form-textarea/index.jsx create mode 100644 client/components/forms/form-toggle/Makefile create mode 100644 client/components/forms/form-toggle/README.md create mode 100644 client/components/forms/form-toggle/compact.jsx create mode 100644 client/components/forms/form-toggle/index.jsx create mode 100644 client/components/forms/form-toggle/style.scss create mode 100644 client/components/forms/form-toggle/test/index.jsx create mode 100644 client/components/forms/language-selector.jsx create mode 100644 client/components/forms/multi-checkbox/Makefile create mode 100644 client/components/forms/multi-checkbox/README.md create mode 100644 client/components/forms/multi-checkbox/index.jsx create mode 100644 client/components/forms/multi-checkbox/test/index.jsx create mode 100644 client/components/forms/range/Makefile create mode 100644 client/components/forms/range/README.md create mode 100644 client/components/forms/range/docs/example.jsx create mode 100644 client/components/forms/range/index.jsx create mode 100644 client/components/forms/range/style.scss create mode 100644 client/components/forms/range/test/index.jsx create mode 100644 client/components/forms/select-opt-groups.jsx create mode 100644 client/components/forms/sortable-list/README.md create mode 100644 client/components/forms/sortable-list/index.jsx create mode 100644 client/components/forms/sortable-list/index.scss create mode 100644 client/components/forms/us-state-selector.jsx create mode 100644 client/components/gallery-shortcode/README.md create mode 100644 client/components/gallery-shortcode/index.jsx create mode 100644 client/components/gauge/README.md create mode 100644 client/components/gauge/docs/example.jsx create mode 100644 client/components/gauge/index.jsx create mode 100644 client/components/gauge/style.scss create mode 100644 client/components/gravatar/Makefile create mode 100644 client/components/gravatar/README.md create mode 100644 client/components/gravatar/index.jsx create mode 100644 client/components/gravatar/style.scss create mode 100644 client/components/gravatar/test/index.jsx create mode 100644 client/components/header-cake/README.md create mode 100644 client/components/header-cake/docs/example.jsx create mode 100644 client/components/header-cake/index.jsx create mode 100644 client/components/header-cake/style.scss create mode 100644 client/components/image-preloader/README.md create mode 100644 client/components/image-preloader/index.jsx create mode 100644 client/components/infinite-list/Makefile create mode 100644 client/components/infinite-list/README.md create mode 100644 client/components/infinite-list/index.jsx create mode 100644 client/components/infinite-list/scroll-helper.js create mode 100644 client/components/infinite-list/style.scss create mode 100644 client/components/infinite-list/test/scroll-helper.js create mode 100644 client/components/info-popover/README.md create mode 100644 client/components/info-popover/docs/example.jsx create mode 100644 client/components/info-popover/index.jsx create mode 100644 client/components/info-popover/style.scss create mode 100644 client/components/input-chrono/README.md create mode 100644 client/components/input-chrono/docs/example.jsx create mode 100644 client/components/input-chrono/index.jsx create mode 100644 client/components/input-chrono/style.scss create mode 100644 client/components/like-button/README.md create mode 100644 client/components/like-button/_style.scss create mode 100644 client/components/like-button/button.jsx create mode 100644 client/components/like-button/docs/example.jsx create mode 100644 client/components/like-button/icons.jsx create mode 100644 client/components/like-button/index.jsx create mode 100644 client/components/main/README.md create mode 100644 client/components/main/index.jsx create mode 100644 client/components/main/style.scss create mode 100644 client/components/mobile-back-to-sidebar/index.jsx create mode 100644 client/components/mobile-back-to-sidebar/style.scss create mode 100644 client/components/notices/docs/example.jsx create mode 100644 client/components/olark-chatbox/README.md create mode 100644 client/components/olark-chatbox/index.jsx create mode 100644 client/components/olark-chatbox/style.scss create mode 100644 client/components/overlay/README.md create mode 100644 client/components/overlay/overlay.jsx create mode 100644 client/components/overlay/package.json create mode 100644 client/components/overlay/toolbar.jsx create mode 100644 client/components/payment-logo/index.jsx create mode 100644 client/components/payment-logo/style.scss create mode 100644 client/components/plans/plan-actions/index.jsx create mode 100644 client/components/plans/plan-actions/style.scss create mode 100644 client/components/plans/plan-discount-message/index.jsx create mode 100644 client/components/plans/plan-discount-message/style.scss create mode 100644 client/components/plans/plan-feature-cell/index.jsx create mode 100644 client/components/plans/plan-feature-cell/style.scss create mode 100644 client/components/plans/plan-features/index.jsx create mode 100644 client/components/plans/plan-features/style.scss create mode 100644 client/components/plans/plan-header/index.jsx create mode 100644 client/components/plans/plan-header/style.scss create mode 100644 client/components/plans/plan-list/index.jsx create mode 100644 client/components/plans/plan-list/style.scss create mode 100644 client/components/plans/plan-nudge/index.jsx create mode 100644 client/components/plans/plan-nudge/preview.jsx create mode 100644 client/components/plans/plan-nudge/style.scss create mode 100644 client/components/plans/plan-price/index.jsx create mode 100644 client/components/plans/plan-price/style.scss create mode 100644 client/components/plans/plan/index.jsx create mode 100644 client/components/plans/plan/style.scss create mode 100644 client/components/plans/plans-compare/index.jsx create mode 100644 client/components/plans/plans-compare/style.scss create mode 100644 client/components/plans/site-specific-plan-details-mixin.js create mode 100644 client/components/popover/README.md create mode 100644 client/components/popover/docs/example.jsx create mode 100644 client/components/popover/index.jsx create mode 100644 client/components/popover/menu-item.jsx create mode 100644 client/components/popover/menu.jsx create mode 100644 client/components/popover/style.scss create mode 100644 client/components/post-excerpt/index.jsx create mode 100644 client/components/post-excerpt/style.scss create mode 100644 client/components/post-list-fetcher/index.jsx create mode 100644 client/components/post-schedule/README.md create mode 100644 client/components/post-schedule/clock.jsx create mode 100644 client/components/post-schedule/docs/example.jsx create mode 100644 client/components/post-schedule/header-controls.jsx create mode 100644 client/components/post-schedule/header.jsx create mode 100644 client/components/post-schedule/index.jsx create mode 100644 client/components/post-schedule/style.scss create mode 100644 client/components/post-schedule/utils.js create mode 100644 client/components/progress-bar/README.md create mode 100644 client/components/progress-bar/docs/example.jsx create mode 100644 client/components/progress-bar/index.jsx create mode 100644 client/components/progress-bar/style.scss create mode 100644 client/components/progress-indicator/README.md create mode 100644 client/components/progress-indicator/index.jsx create mode 100644 client/components/progress-indicator/style.scss create mode 100644 client/components/pulsing-dot/index.jsx create mode 100644 client/components/pulsing-dot/style.scss create mode 100644 client/components/rating/README.md create mode 100644 client/components/rating/docs/example.jsx create mode 100644 client/components/rating/index.jsx create mode 100644 client/components/rating/style.scss create mode 100644 client/components/resizable-iframe/README.md create mode 100644 client/components/resizable-iframe/index.jsx create mode 100644 client/components/root-child/Makefile create mode 100644 client/components/root-child/README.md create mode 100644 client/components/root-child/index.jsx create mode 100644 client/components/root-child/test/index.jsx create mode 100644 client/components/search-card/README.md create mode 100644 client/components/search-card/index.jsx create mode 100644 client/components/search-card/style.scss create mode 100644 client/components/search/Makefile create mode 100644 client/components/search/README.md create mode 100644 client/components/search/docs/example.jsx create mode 100644 client/components/search/index.jsx create mode 100644 client/components/search/style.scss create mode 100644 client/components/search/test/index.jsx create mode 100644 client/components/section-header/README.md create mode 100644 client/components/section-header/button.jsx create mode 100644 client/components/section-header/docs/example.jsx create mode 100644 client/components/section-header/index.jsx create mode 100644 client/components/section-header/style.scss create mode 100644 client/components/section-nav/Makefile create mode 100644 client/components/section-nav/README.md create mode 100644 client/components/section-nav/docs/example.jsx create mode 100644 client/components/section-nav/index.jsx create mode 100644 client/components/section-nav/item.jsx create mode 100644 client/components/section-nav/segmented.jsx create mode 100644 client/components/section-nav/style.scss create mode 100644 client/components/section-nav/tabs.jsx create mode 100644 client/components/section-nav/test/index.jsx create mode 100644 client/components/segmented-control/README.md create mode 100644 client/components/segmented-control/docs/example.jsx create mode 100644 client/components/segmented-control/index.jsx create mode 100644 client/components/segmented-control/item.jsx create mode 100644 client/components/segmented-control/style.scss create mode 100644 client/components/select-dropdown/README.md create mode 100644 client/components/select-dropdown/docs/example.jsx create mode 100644 client/components/select-dropdown/index.jsx create mode 100644 client/components/select-dropdown/item.jsx create mode 100644 client/components/select-dropdown/separator.jsx create mode 100644 client/components/select-dropdown/style.scss create mode 100644 client/components/select/docs/example.jsx create mode 100644 client/components/shortcode/README.md create mode 100644 client/components/shortcode/data.jsx create mode 100644 client/components/shortcode/frame.jsx create mode 100644 client/components/shortcode/index.jsx create mode 100644 client/components/sidebar-navigation/README.md create mode 100644 client/components/sidebar-navigation/index.jsx create mode 100644 client/components/sidebar-navigation/style.scss create mode 100644 client/components/signup-form/README.md create mode 100644 client/components/signup-form/index.jsx create mode 100644 client/components/signup-form/style.scss create mode 100644 client/components/single-child-css-transition-group/README.md create mode 100644 client/components/single-child-css-transition-group/child.js create mode 100644 client/components/single-child-css-transition-group/index.js create mode 100644 client/components/site-icon/README.md create mode 100644 client/components/site-icon/package.json create mode 100644 client/components/site-icon/site-icon.jsx create mode 100644 client/components/site-icon/style.scss create mode 100644 client/components/site-selector-modal/README.md create mode 100644 client/components/site-selector-modal/index.jsx create mode 100644 client/components/site-selector-modal/style.scss create mode 100644 client/components/site-selector/README.md create mode 100644 client/components/site-selector/index.jsx create mode 100644 client/components/site-selector/style.scss create mode 100644 client/components/site-stats-sticky-link/README.md create mode 100644 client/components/site-stats-sticky-link/index.jsx create mode 100644 client/components/site-users-fetcher/index.jsx create mode 100644 client/components/site-users-fetcher/readme.md create mode 100644 client/components/sites-popover/README.md create mode 100644 client/components/sites-popover/index.jsx create mode 100644 client/components/sites-popover/style.scss create mode 100644 client/components/spinner/README.md create mode 100644 client/components/spinner/docs/example.jsx create mode 100644 client/components/spinner/index.jsx create mode 100644 client/components/spinner/style.scss create mode 100644 client/components/stat-update-indicator/README.md create mode 100644 client/components/stat-update-indicator/index.jsx create mode 100644 client/components/stat-update-indicator/style.scss create mode 100644 client/components/sticky-panel/index.jsx create mode 100644 client/components/sticky-panel/style.scss create mode 100644 client/components/timezone-dropdown/README.md create mode 100644 client/components/timezone-dropdown/docs/example.jsx create mode 100644 client/components/timezone-dropdown/index.jsx create mode 100644 client/components/timezone-dropdown/style.scss create mode 100644 client/components/tinymce/README.md create mode 100644 client/components/tinymce/i18n.js create mode 100644 client/components/tinymce/iframe.scss create mode 100644 client/components/tinymce/index.jsx create mode 100644 client/components/tinymce/plugins/advanced/plugin.js create mode 100644 client/components/tinymce/plugins/advanced/style.scss create mode 100644 client/components/tinymce/plugins/calypso-alert/alert.jsx create mode 100644 client/components/tinymce/plugins/calypso-alert/plugin.jsx create mode 100644 client/components/tinymce/plugins/calypso-alert/style.scss create mode 100644 client/components/tinymce/plugins/editor-button-analytics/plugin.js create mode 100644 client/components/tinymce/plugins/media/README.md create mode 100644 client/components/tinymce/plugins/media/drop-zone.jsx create mode 100644 client/components/tinymce/plugins/media/plugin.jsx create mode 100644 client/components/tinymce/plugins/media/restrict-size/Makefile create mode 100644 client/components/tinymce/plugins/media/restrict-size/index.js create mode 100644 client/components/tinymce/plugins/media/restrict-size/test/index.js create mode 100644 client/components/tinymce/plugins/tabindex/plugin.js create mode 100644 client/components/tinymce/plugins/touch-scroll-toolbar/plugin.js create mode 100644 client/components/tinymce/plugins/wpcom-autoresize/plugin.js create mode 100644 client/components/tinymce/plugins/wpcom-charmap/charmap.jsx create mode 100644 client/components/tinymce/plugins/wpcom-charmap/plugin.js create mode 100644 client/components/tinymce/plugins/wpcom-charmap/style.scss create mode 100644 client/components/tinymce/plugins/wpcom-help/help-modal.jsx create mode 100644 client/components/tinymce/plugins/wpcom-help/plugin.js create mode 100644 client/components/tinymce/plugins/wpcom-help/style.scss create mode 100644 client/components/tinymce/plugins/wpcom-view/gallery-view.jsx create mode 100644 client/components/tinymce/plugins/wpcom-view/plugin.js create mode 100644 client/components/tinymce/plugins/wpcom-view/views.js create mode 100644 client/components/tinymce/plugins/wpcom-view/views/embed/index.js create mode 100644 client/components/tinymce/plugins/wpcom-view/views/embed/view.jsx create mode 100644 client/components/tinymce/plugins/wpcom/plugin.js create mode 100644 client/components/tinymce/plugins/wpeditimage/plugin.js create mode 100644 client/components/tinymce/plugins/wplink/dialog.jsx create mode 100644 client/components/tinymce/plugins/wplink/plugin.js create mode 100644 client/components/tinymce/plugins/wplink/style.scss create mode 100644 client/components/tinymce/plugins/wptextpattern/plugin.js create mode 100644 client/components/tinymce/style.scss create mode 100644 client/components/token-field/Makefile create mode 100644 client/components/token-field/README.md create mode 100644 client/components/token-field/docs/example.jsx create mode 100644 client/components/token-field/index.jsx create mode 100644 client/components/token-field/style.scss create mode 100644 client/components/token-field/suggestions-list.jsx create mode 100644 client/components/token-field/test/fixtures.js create mode 100644 client/components/token-field/test/index.jsx create mode 100644 client/components/token-field/test/token-field-wrapper.jsx create mode 100644 client/components/token-field/token-input.jsx create mode 100644 client/components/token-field/token.jsx create mode 100644 client/components/tooltip/index.jsx create mode 100644 client/components/tooltip/style.scss create mode 100644 client/components/track-input-changes/Makefile create mode 100644 client/components/track-input-changes/README.md create mode 100644 client/components/track-input-changes/index.jsx create mode 100644 client/components/track-input-changes/test/index.jsx create mode 100644 client/components/typography/README.md create mode 100644 client/components/typography/docs/example.jsx create mode 100644 client/components/upgrades/credit-card-form/README.md create mode 100644 client/components/upgrades/credit-card-form/index.jsx create mode 100644 client/components/upgrades/credit-card-form/style.scss create mode 100644 client/components/upgrades/credit-card-number-input/README.md create mode 100644 client/components/upgrades/credit-card-number-input/index.jsx create mode 100644 client/components/upgrades/credit-card-number-input/style.scss create mode 100644 client/components/upgrades/google-apps/README.md create mode 100644 client/components/upgrades/google-apps/dialog/index.jsx create mode 100644 client/components/upgrades/google-apps/dialog/product-details.jsx create mode 100644 client/components/upgrades/google-apps/dialog/users.jsx create mode 100644 client/components/upgrades/google-apps/index.jsx create mode 100644 client/components/user/index.jsx create mode 100644 client/components/user/style.scss create mode 100644 client/components/version/README.md create mode 100644 client/components/version/docs/example.jsx create mode 100644 client/components/version/index.jsx create mode 100644 client/components/version/style.scss create mode 100644 client/components/vertical-nav/README.md create mode 100644 client/components/vertical-nav/index.jsx create mode 100644 client/components/vertical-nav/item/index.jsx create mode 100644 client/components/vertical-nav/item/style.scss create mode 100644 client/components/vertical-nav/style.scss create mode 100644 client/components/web-preview/README.md create mode 100644 client/components/web-preview/index.jsx create mode 100644 client/components/web-preview/style.scss create mode 100644 client/components/web-preview/toolbar.jsx create mode 100644 client/components/wordpress-logo/index.jsx create mode 100644 client/config/.gitignore create mode 100644 client/config/README.md create mode 100755 client/config/regenerate.js create mode 100644 client/devdocs/Makefile create mode 100644 client/devdocs/README.md create mode 100644 client/devdocs/controller.js create mode 100644 client/devdocs/design/index.jsx create mode 100644 client/devdocs/design/style.scss create mode 100644 client/devdocs/doc.jsx create mode 100644 client/devdocs/form-state-examples/index.jsx create mode 100644 client/devdocs/index.js create mode 100644 client/devdocs/main.jsx create mode 100644 client/devdocs/service.js create mode 100644 client/devdocs/sidebar.jsx create mode 100644 client/devdocs/test/doc-test.jsx create mode 100644 client/layout/README.md create mode 100644 client/layout/community-translator/README.md create mode 100644 client/layout/community-translator/invitation-utils.js create mode 100644 client/layout/community-translator/invitation.jsx create mode 100644 client/layout/community-translator/launcher.jsx create mode 100644 client/layout/community-translator/style.scss create mode 100644 client/layout/error.jsx create mode 100644 client/layout/index.jsx create mode 100644 client/layout/logged-out-oauth.jsx create mode 100644 client/layout/logged-out.jsx create mode 100644 client/layout/masterbar-logged-out-menu.jsx create mode 100644 client/layout/masterbar-new-post.jsx create mode 100644 client/layout/masterbar-new-post.scss create mode 100644 client/layout/masterbar-sections-menu.jsx create mode 100644 client/layout/masterbar.jsx create mode 100644 client/layout/package.json create mode 100644 client/lib/abtest/README.md create mode 100644 client/lib/abtest/active-tests.js create mode 100644 client/lib/abtest/index.js create mode 100644 client/lib/accept/Makefile create mode 100644 client/lib/accept/README.md create mode 100644 client/lib/accept/dialog.jsx create mode 100644 client/lib/accept/index.js create mode 100644 client/lib/accept/style.scss create mode 100644 client/lib/accept/test/index.js create mode 100644 client/lib/accessible-focus/README.md create mode 100644 client/lib/accessible-focus/index.js create mode 100644 client/lib/account-password-data/index.js create mode 100644 client/lib/ads/Makefile create mode 100644 client/lib/ads/README.md create mode 100644 client/lib/ads/actions.js create mode 100644 client/lib/ads/earnings-store.js create mode 100644 client/lib/ads/settings-store.js create mode 100644 client/lib/ads/test/lib/mock-actions.js create mode 100644 client/lib/ads/test/lib/mock-earnings.js create mode 100644 client/lib/ads/test/lib/mock-settings.js create mode 100644 client/lib/ads/test/lib/mock-site.js create mode 100644 client/lib/ads/test/test-store.js create mode 100644 client/lib/ads/tos-store.js create mode 100644 client/lib/ads/utils.js create mode 100644 client/lib/application-passwords-data/README.md create mode 100644 client/lib/application-passwords-data/index.js create mode 100644 client/lib/billing-history-data/README.md create mode 100644 client/lib/billing-history-data/index.js create mode 100644 client/lib/cart-values/Makefile create mode 100644 client/lib/cart-values/cart-items.js create mode 100644 client/lib/cart-values/index.js create mode 100644 client/lib/cart-values/schema.json create mode 100644 client/lib/cart-values/test/abtest.js create mode 100644 client/lib/cart-values/test/lib/user-settings.js create mode 100644 client/lib/cart-values/test/lib/user.js create mode 100644 client/lib/cart-values/test/test.js create mode 100644 client/lib/cart/store/Makefile create mode 100644 client/lib/cart/store/cart-analytics.js create mode 100644 client/lib/cart/store/cart-synchronizer.js create mode 100644 client/lib/cart/store/index.js create mode 100644 client/lib/cart/store/test/abtest.js create mode 100644 client/lib/cart/store/test/cart-synchronizer-test.js create mode 100644 client/lib/cart/store/test/fake-wpcom.js create mode 100644 client/lib/cart/store/test/lib/user-settings.js create mode 100644 client/lib/cart/store/test/lib/user.js create mode 100644 client/lib/comment-like-store/Makefile create mode 100644 client/lib/comment-like-store/actions.js create mode 100644 client/lib/comment-like-store/comment-like-store.js create mode 100644 client/lib/comment-like-store/constants.js create mode 100644 client/lib/comment-like-store/test/comment-like-store-test.js create mode 100644 client/lib/comment-like-store/utils.js create mode 100644 client/lib/comment-store/Makefile create mode 100644 client/lib/comment-store/actions.js create mode 100644 client/lib/comment-store/comment-store.js create mode 100644 client/lib/comment-store/constants.js create mode 100644 client/lib/comment-store/test/comment-store-test.js create mode 100644 client/lib/comment-store/test/lib/wp.js create mode 100644 client/lib/comment-store/utils.js create mode 100644 client/lib/connected-applications-data/README.md create mode 100644 client/lib/connected-applications-data/index.js create mode 100644 client/lib/connections-list/README.md create mode 100644 client/lib/connections-list/index.js create mode 100644 client/lib/connections-list/list.js create mode 100644 client/lib/countries-list/README.md create mode 100644 client/lib/countries-list/index.js create mode 100644 client/lib/credit-card-details/Makefile create mode 100644 client/lib/credit-card-details/README.md create mode 100644 client/lib/credit-card-details/index.js create mode 100644 client/lib/credit-card-details/masking.js create mode 100644 client/lib/credit-card-details/test/test.js create mode 100644 client/lib/credit-card-details/validation.js create mode 100644 client/lib/customize/muse.js create mode 100644 client/lib/data-poller/README.md create mode 100644 client/lib/data-poller/index.js create mode 100644 client/lib/data-poller/poller.js create mode 100644 client/lib/desktop/README.md create mode 100644 client/lib/desktop/index.js create mode 100644 client/lib/desktop/page-notifier.js create mode 100644 client/lib/detect-history-navigation/README.md create mode 100644 client/lib/detect-history-navigation/index.js create mode 100644 client/lib/deterministic-stringify/Makefile create mode 100644 client/lib/deterministic-stringify/README.md create mode 100644 client/lib/deterministic-stringify/index.js create mode 100644 client/lib/deterministic-stringify/test/test.js create mode 100644 client/lib/devices/README.md create mode 100644 client/lib/devices/index.js create mode 100644 client/lib/domains/Makefile create mode 100644 client/lib/domains/README.md create mode 100644 client/lib/domains/assembler.js create mode 100644 client/lib/domains/constants.js create mode 100644 client/lib/domains/dns/Makefile create mode 100644 client/lib/domains/dns/index.js create mode 100644 client/lib/domains/dns/reducer.js create mode 100644 client/lib/domains/dns/store.js create mode 100644 client/lib/domains/dns/test/index.js create mode 100644 client/lib/domains/email-forwarding/Makefile create mode 100644 client/lib/domains/email-forwarding/reducer.js create mode 100644 client/lib/domains/email-forwarding/store.js create mode 100644 client/lib/domains/email-forwarding/test/store-test.js create mode 100644 client/lib/domains/google-apps-users/assembler.js create mode 100644 client/lib/domains/google-apps-users/index.js create mode 100644 client/lib/domains/google-apps-users/reducer.js create mode 100644 client/lib/domains/google-apps-users/store.js create mode 100644 client/lib/domains/index.js create mode 100644 client/lib/domains/nameservers/Makefile create mode 100644 client/lib/domains/nameservers/index.js create mode 100644 client/lib/domains/nameservers/reducer.js create mode 100644 client/lib/domains/nameservers/store.js create mode 100644 client/lib/domains/nameservers/test/store-test.js create mode 100644 client/lib/domains/reducer.js create mode 100644 client/lib/domains/site-redirect/README.md create mode 100644 client/lib/domains/site-redirect/reducer.js create mode 100644 client/lib/domains/site-redirect/store.js create mode 100644 client/lib/domains/store.js create mode 100644 client/lib/domains/test/assembler-test.js create mode 100644 client/lib/domains/wapi-domain-info/assembler.js create mode 100644 client/lib/domains/wapi-domain-info/reducer.js create mode 100644 client/lib/domains/wapi-domain-info/store.js create mode 100644 client/lib/domains/whois/Makefile create mode 100644 client/lib/domains/whois/README.md create mode 100644 client/lib/domains/whois/assembler.js create mode 100644 client/lib/domains/whois/reducer.js create mode 100644 client/lib/domains/whois/store.js create mode 100644 client/lib/domains/whois/test/assembler-test.js create mode 100644 client/lib/domains/whois/test/store-test.js create mode 100644 client/lib/dss/README.md create mode 100644 client/lib/dss/actions.js create mode 100644 client/lib/dss/constants.js create mode 100644 client/lib/dss/image-store.js create mode 100644 client/lib/dss/preview-store.js create mode 100644 client/lib/email-followers/Makefile create mode 100644 client/lib/email-followers/README.md create mode 100644 client/lib/email-followers/actions.js create mode 100644 client/lib/email-followers/store.js create mode 100644 client/lib/email-followers/test/lib/mock-actions.js create mode 100644 client/lib/email-followers/test/lib/mock-email-followers.js create mode 100644 client/lib/email-followers/test/lib/mock-more-email-followers.js create mode 100644 client/lib/email-followers/test/lib/mock-site.js create mode 100644 client/lib/email-followers/test/test-store.js create mode 100644 client/lib/embeds/README.md create mode 100644 client/lib/embeds/actions.js create mode 100644 client/lib/embeds/list-store.js create mode 100644 client/lib/embeds/store.js create mode 100644 client/lib/features-list/Makefile create mode 100644 client/lib/features-list/README.md create mode 100644 client/lib/features-list/index.js create mode 100644 client/lib/features-list/test/data.js create mode 100644 client/lib/features-list/test/lib/wp.js create mode 100644 client/lib/features-list/test/test.js create mode 100644 client/lib/feed-post-store/Makefile create mode 100644 client/lib/feed-post-store/README.md create mode 100644 client/lib/feed-post-store/actions.js create mode 100644 client/lib/feed-post-store/constants.js create mode 100644 client/lib/feed-post-store/display-types.js create mode 100644 client/lib/feed-post-store/index.js create mode 100644 client/lib/feed-post-store/normalization-rules.js create mode 100644 client/lib/feed-post-store/post-batch-fetcher.js create mode 100644 client/lib/feed-post-store/test/feed-post-store-test.js create mode 100644 client/lib/feed-post-store/test/lib/post-normalizer.js create mode 100644 client/lib/feed-post-store/test/lib/wp.js create mode 100644 client/lib/feed-store/Makefile create mode 100644 client/lib/feed-store/actions.js create mode 100644 client/lib/feed-store/constants.js create mode 100644 client/lib/feed-store/index.js create mode 100644 client/lib/feed-store/test/feed-store-tests.js create mode 100644 client/lib/feed-store/test/lib/formatting.js create mode 100644 client/lib/feed-stream-store/Makefile create mode 100644 client/lib/feed-stream-store/actions.js create mode 100644 client/lib/feed-stream-store/constants.js create mode 100644 client/lib/feed-stream-store/feed-stream-cache.js create mode 100644 client/lib/feed-stream-store/feed-stream.js create mode 100644 client/lib/feed-stream-store/index.js create mode 100644 client/lib/feed-stream-store/test/lib/post-normalizer.js create mode 100644 client/lib/feed-stream-store/test/lib/wp.js create mode 100644 client/lib/feed-stream-store/test/post-list-store-tests.js create mode 100644 client/lib/follow-list/Makefile create mode 100644 client/lib/follow-list/README.md create mode 100644 client/lib/follow-list/index.js create mode 100644 client/lib/follow-list/site.js create mode 100644 client/lib/follow-list/test/lib/wp.js create mode 100644 client/lib/follow-list/test/test.js create mode 100644 client/lib/followers/Makefile create mode 100644 client/lib/followers/README.md create mode 100644 client/lib/followers/actions.js create mode 100644 client/lib/followers/store.js create mode 100644 client/lib/followers/test/lib/mock-actions.js create mode 100644 client/lib/followers/test/lib/mock-site.js create mode 100644 client/lib/followers/test/lib/mock-wpcom-followers1.js create mode 100644 client/lib/followers/test/lib/mock-wpcom-followers2.js create mode 100644 client/lib/followers/test/test-store.js create mode 100644 client/lib/form-state/Makefile create mode 100644 client/lib/form-state/README.md create mode 100644 client/lib/form-state/examples/async-initialize.jsx create mode 100644 client/lib/form-state/examples/sync-initialize.jsx create mode 100644 client/lib/form-state/index.js create mode 100644 client/lib/form-state/store/async-initialize.js create mode 100644 client/lib/form-state/store/core.js create mode 100644 client/lib/form-state/store/index.js create mode 100644 client/lib/form-state/store/sync-initialize.js create mode 100644 client/lib/form-state/test/index.js create mode 100644 client/lib/geocoding/Makefile create mode 100644 client/lib/geocoding/README.md create mode 100644 client/lib/geocoding/index.js create mode 100644 client/lib/geocoding/test/index.js create mode 100644 client/lib/google-apps/index.js create mode 100644 client/lib/happiness-engineers/Makefile create mode 100644 client/lib/happiness-engineers/README.md create mode 100644 client/lib/happiness-engineers/actions.js create mode 100644 client/lib/happiness-engineers/constants.js create mode 100644 client/lib/happiness-engineers/store.js create mode 100644 client/lib/happiness-engineers/test/lib/mock-actions.js create mode 100644 client/lib/happiness-engineers/test/lib/mock-happiness-engineers.js create mode 100644 client/lib/happiness-engineers/test/test-actions.js create mode 100644 client/lib/happiness-engineers/test/test-store.js create mode 100644 client/lib/help-search/Makefile create mode 100644 client/lib/help-search/README.md create mode 100644 client/lib/help-search/actions.js create mode 100644 client/lib/help-search/constants.js create mode 100644 client/lib/help-search/store.js create mode 100644 client/lib/help-search/test/lib/mock-actions.js create mode 100644 client/lib/help-search/test/lib/mock-help-links.js create mode 100644 client/lib/help-search/test/test-store.js create mode 100644 client/lib/highlight/Makefile create mode 100644 client/lib/highlight/README.md create mode 100644 client/lib/highlight/index.js create mode 100644 client/lib/highlight/test/highlight-test.js create mode 100644 client/lib/human-date/index.js create mode 100644 client/lib/importer/actions.js create mode 100644 client/lib/importer/common.js create mode 100644 client/lib/importer/constants.js create mode 100644 client/lib/importer/store.js create mode 100644 client/lib/infinite-list/actions.js create mode 100644 client/lib/infinite-list/positions-store.js create mode 100644 client/lib/infinite-list/scroll-store.js create mode 100644 client/lib/inflight/index.js create mode 100644 client/lib/interpolate-components/Makefile create mode 100644 client/lib/interpolate-components/README.md create mode 100644 client/lib/interpolate-components/index.js create mode 100644 client/lib/interpolate-components/test/lib/warn.js create mode 100644 client/lib/interpolate-components/test/text.jsx create mode 100644 client/lib/interpolate-components/tokenize.js create mode 100644 client/lib/invites/Makefile create mode 100644 client/lib/invites/actions.js create mode 100644 client/lib/invites/constants.js create mode 100644 client/lib/invites/reducers/invites-validation.js create mode 100644 client/lib/invites/reducers/list-invites.js create mode 100644 client/lib/invites/stores/invites-validation.js create mode 100644 client/lib/invites/stores/list-invites.js create mode 100644 client/lib/invites/test/list-invites-store.js create mode 100644 client/lib/keyboard-shortcuts/Makefile create mode 100644 client/lib/keyboard-shortcuts/README.md create mode 100644 client/lib/keyboard-shortcuts/global.js create mode 100644 client/lib/keyboard-shortcuts/index.js create mode 100644 client/lib/keyboard-shortcuts/key-bindings.js create mode 100644 client/lib/keyboard-shortcuts/menu.jsx create mode 100644 client/lib/keyboard-shortcuts/test/lib/mixins/i18n.js create mode 100644 client/lib/keyboard-shortcuts/test/test.js create mode 100644 client/lib/layout-focus/README.md create mode 100644 client/lib/layout-focus/index.js create mode 100644 client/lib/like-store/Makefile create mode 100644 client/lib/like-store/actions.js create mode 100644 client/lib/like-store/like-store.js create mode 100644 client/lib/like-store/test/lib/wp.js create mode 100644 client/lib/like-store/test/like-store-test.js create mode 100644 client/lib/like-store/utils.js create mode 100644 client/lib/load-script/README.md create mode 100644 client/lib/load-script/index.js create mode 100644 client/lib/local-list/Makefile create mode 100644 client/lib/local-list/README.md create mode 100644 client/lib/local-list/index.js create mode 100644 client/lib/local-list/test/test.js create mode 100644 client/lib/local-storage/Makefile create mode 100644 client/lib/local-storage/README.md create mode 100644 client/lib/local-storage/index.js create mode 100644 client/lib/local-storage/test/test.js create mode 100644 client/lib/locale-suggestions/actions.js create mode 100644 client/lib/locale-suggestions/index.js create mode 100644 client/lib/media-serialization/Makefile create mode 100644 client/lib/media-serialization/constants.js create mode 100644 client/lib/media-serialization/create-element-from-string.js create mode 100644 client/lib/media-serialization/detect-format.js create mode 100644 client/lib/media-serialization/index.js create mode 100644 client/lib/media-serialization/strategies/api.js create mode 100644 client/lib/media-serialization/strategies/dom.js create mode 100644 client/lib/media-serialization/strategies/index.js create mode 100644 client/lib/media-serialization/strategies/object.js create mode 100644 client/lib/media-serialization/strategies/shortcode.js create mode 100644 client/lib/media-serialization/strategies/string.js create mode 100644 client/lib/media-serialization/strategies/unknown.js create mode 100644 client/lib/media-serialization/test/index.js create mode 100644 client/lib/media/Makefile create mode 100644 client/lib/media/README.md create mode 100644 client/lib/media/actions.js create mode 100644 client/lib/media/constants.js create mode 100644 client/lib/media/library-selected-store.js create mode 100644 client/lib/media/list-store.js create mode 100644 client/lib/media/store.js create mode 100644 client/lib/media/test/actions.js create mode 100644 client/lib/media/test/library-selected-store.js create mode 100644 client/lib/media/test/list-store.js create mode 100644 client/lib/media/test/store.js create mode 100644 client/lib/media/test/utils.js create mode 100644 client/lib/media/test/validation-store.js create mode 100644 client/lib/media/utils.js create mode 100644 client/lib/media/validation-store.js create mode 100644 client/lib/menu-data/Makefile create mode 100644 client/lib/menu-data/README.md create mode 100644 client/lib/menu-data/index.js create mode 100644 client/lib/menu-data/menu-data.js create mode 100644 client/lib/menu-data/test/fixtures.js create mode 100644 client/lib/menu-data/test/lib/mixins/i18n.js create mode 100644 client/lib/menu-data/test/lib/sites-list.js create mode 100644 client/lib/menu-data/test/lib/wp.js create mode 100644 client/lib/menu-data/test/test-menu-data.js create mode 100644 client/lib/mixins/analytics/index.js create mode 100644 client/lib/mixins/close-on-esc/README.md create mode 100644 client/lib/mixins/close-on-esc/index.js create mode 100644 client/lib/mixins/data-observe/Makefile create mode 100644 client/lib/mixins/data-observe/README.md create mode 100644 client/lib/mixins/data-observe/index.js create mode 100644 client/lib/mixins/data-observe/test/test.js create mode 100644 client/lib/mixins/i18n/Makefile create mode 100644 client/lib/mixins/i18n/README.md create mode 100644 client/lib/mixins/i18n/index.js create mode 100644 client/lib/mixins/i18n/number-format.js create mode 100644 client/lib/mixins/i18n/test/data.js create mode 100644 client/lib/mixins/i18n/test/i18nLocalStrings.js create mode 100644 client/lib/mixins/i18n/test/lib/user-settings.js create mode 100644 client/lib/mixins/i18n/test/lib/user.js create mode 100644 client/lib/mixins/i18n/test/test.jsx create mode 100644 client/lib/mixins/i18n/timezone.js create mode 100644 client/lib/mixins/infinite-scroll/README.md create mode 100644 client/lib/mixins/infinite-scroll/index.js create mode 100644 client/lib/mixins/lock/README.md create mode 100644 client/lib/mixins/lock/index.js create mode 100644 client/lib/mixins/observe-window-resize/index.js create mode 100644 client/lib/mixins/pageable/Makefile create mode 100644 client/lib/mixins/pageable/README.md create mode 100644 client/lib/mixins/pageable/index.js create mode 100644 client/lib/mixins/pageable/test/test.js create mode 100644 client/lib/mixins/protect-form/README.md create mode 100644 client/lib/mixins/protect-form/index.js create mode 100644 client/lib/mixins/render-visualizer/README.md create mode 100644 client/lib/mixins/render-visualizer/index.js create mode 100644 client/lib/mixins/searchable/Makefile create mode 100644 client/lib/mixins/searchable/README.md create mode 100644 client/lib/mixins/searchable/index.js create mode 100644 client/lib/mixins/searchable/test/test.js create mode 100644 client/lib/mixins/trap-focus/README.md create mode 100644 client/lib/mixins/trap-focus/index.js create mode 100644 client/lib/mixins/update-post-status/README.md create mode 100644 client/lib/mixins/update-post-status/index.jsx create mode 100644 client/lib/mixins/url-search/Makefile create mode 100644 client/lib/mixins/url-search/README.md create mode 100644 client/lib/mixins/url-search/build-url.js create mode 100644 client/lib/mixins/url-search/index.js create mode 100644 client/lib/mixins/url-search/test/build-url.js create mode 100644 client/lib/network-connection/Makefile create mode 100644 client/lib/network-connection/README.md create mode 100644 client/lib/network-connection/index.js create mode 100644 client/lib/network-connection/test/index-test.js create mode 100644 client/lib/notification-settings-store/Makefile create mode 100644 client/lib/notification-settings-store/actions.js create mode 100644 client/lib/notification-settings-store/constants.js create mode 100644 client/lib/notification-settings-store/index.js create mode 100644 client/lib/notification-settings-store/test/store-test.js create mode 100644 client/lib/notification-settings-store/toggle-state.js create mode 100644 client/lib/oauth-store/Makefile create mode 100644 client/lib/oauth-store/README.md create mode 100644 client/lib/oauth-store/actions.js create mode 100644 client/lib/oauth-store/constants.js create mode 100644 client/lib/oauth-store/index.js create mode 100644 client/lib/oauth-store/test/oauth-store.js create mode 100644 client/lib/oauth-token/README.md create mode 100644 client/lib/oauth-token/index.js create mode 100644 client/lib/olark-api/README.md create mode 100644 client/lib/olark-api/index.js create mode 100644 client/lib/olark-events/Makefile create mode 100644 client/lib/olark-events/README.md create mode 100644 client/lib/olark-events/index.js create mode 100644 client/lib/olark-events/test/lib/mock-olark.js create mode 100644 client/lib/olark-events/test/test-onready-event.js create mode 100644 client/lib/olark-store/Makefile create mode 100644 client/lib/olark-store/README.md create mode 100644 client/lib/olark-store/actions.js create mode 100644 client/lib/olark-store/constants.js create mode 100644 client/lib/olark-store/index.js create mode 100644 client/lib/olark-store/test/olark-store-test.js create mode 100644 client/lib/olark/README.md create mode 100644 client/lib/olark/index.js create mode 100644 client/lib/page-templates/actions.js create mode 100644 client/lib/page-templates/store.js create mode 100644 client/lib/paths/Makefile create mode 100644 client/lib/paths/index.js create mode 100644 client/lib/paths/test/index.js create mode 100644 client/lib/paygate-loader/README.md create mode 100644 client/lib/paygate-loader/index.js create mode 100644 client/lib/people/Makefile create mode 100644 client/lib/people/README.md create mode 100644 client/lib/people/actions.js create mode 100644 client/lib/people/log-store.js create mode 100644 client/lib/people/test/lib/mock-actions.js create mode 100644 client/lib/people/test/lib/mock-site.js create mode 100644 client/lib/people/test/test-store.js create mode 100644 client/lib/phone-validation/Makefile create mode 100644 client/lib/phone-validation/README.md create mode 100644 client/lib/phone-validation/index.jsx create mode 100644 client/lib/phone-validation/test/test.jsx create mode 100644 client/lib/plans-list/Makefile create mode 100644 client/lib/plans-list/README.md create mode 100644 client/lib/plans-list/index.js create mode 100644 client/lib/plans-list/test/data.js create mode 100644 client/lib/plans-list/test/lib/wp.js create mode 100644 client/lib/plans-list/test/test.js create mode 100644 client/lib/plugins/Makefile create mode 100644 client/lib/plugins/README.md create mode 100644 client/lib/plugins/actions.js create mode 100644 client/lib/plugins/log-store.js create mode 100644 client/lib/plugins/notices.jsx create mode 100644 client/lib/plugins/store.js create mode 100644 client/lib/plugins/test/lib/mixins/i18n.js create mode 100644 client/lib/plugins/test/lib/mock-actions.js create mode 100644 client/lib/plugins/test/lib/mock-multi-site.js create mode 100644 client/lib/plugins/test/lib/mock-plugins-updated.js create mode 100644 client/lib/plugins/test/lib/mock-plugins.js create mode 100644 client/lib/plugins/test/lib/mock-site.js create mode 100644 client/lib/plugins/test/lib/mock-sites-list.js create mode 100644 client/lib/plugins/test/lib/mock-updated-plugin.js create mode 100644 client/lib/plugins/test/lib/mock-wpcom.js create mode 100644 client/lib/plugins/test/lib/wp.js create mode 100644 client/lib/plugins/test/test-actions.js create mode 100644 client/lib/plugins/test/test-log-store.js create mode 100644 client/lib/plugins/test/test-store.js create mode 100644 client/lib/plugins/test/test-utils.js create mode 100644 client/lib/plugins/utils.js create mode 100644 client/lib/plugins/wporg-data/Makefile create mode 100644 client/lib/plugins/wporg-data/README.md create mode 100644 client/lib/plugins/wporg-data/actions.js create mode 100644 client/lib/plugins/wporg-data/list-store.js create mode 100644 client/lib/plugins/wporg-data/store.js create mode 100644 client/lib/plugins/wporg-data/test/lib/data-actions.js create mode 100644 client/lib/plugins/wporg-data/test/lib/mock-actions.js create mode 100644 client/lib/plugins/wporg-data/test/lib/mock-local-store.js create mode 100644 client/lib/plugins/wporg-data/test/lib/mock-store.js create mode 100644 client/lib/plugins/wporg-data/test/lib/mock-wporg.js create mode 100644 client/lib/plugins/wporg-data/test/lib/mocked-actions.js create mode 100644 client/lib/plugins/wporg-data/test/test-actions.js create mode 100644 client/lib/plugins/wporg-data/test/test-list-store.js create mode 100644 client/lib/plugins/wporg-data/test/test-store.js create mode 100644 client/lib/popup-monitor/Makefile create mode 100644 client/lib/popup-monitor/README.md create mode 100644 client/lib/popup-monitor/index.js create mode 100644 client/lib/popup-monitor/test/index.js create mode 100644 client/lib/post-formats/Makefile create mode 100644 client/lib/post-formats/README.md create mode 100644 client/lib/post-formats/actions.js create mode 100644 client/lib/post-formats/store.js create mode 100644 client/lib/post-formats/test/actions.js create mode 100644 client/lib/post-formats/test/store.js create mode 100644 client/lib/post-metadata/Makefile create mode 100644 client/lib/post-metadata/README.md create mode 100644 client/lib/post-metadata/index.js create mode 100644 client/lib/post-metadata/test/index.js create mode 100644 client/lib/post-normalizer/Makefile create mode 100644 client/lib/post-normalizer/README.md create mode 100644 client/lib/post-normalizer/index.js create mode 100644 client/lib/post-normalizer/test/lib/safe-image-url.js create mode 100644 client/lib/post-normalizer/test/post-normalizer-test.js create mode 100644 client/lib/post-stats/README.md create mode 100644 client/lib/post-stats/actions.js create mode 100644 client/lib/post-stats/constants.js create mode 100644 client/lib/post-stats/store.js create mode 100644 client/lib/post-types-list/README.md create mode 100644 client/lib/post-types-list/index.js create mode 100644 client/lib/post-types-list/list.js create mode 100644 client/lib/posts/Makefile create mode 100644 client/lib/posts/README.md create mode 100644 client/lib/posts/actions.js create mode 100644 client/lib/posts/post-content-images-store.js create mode 100644 client/lib/posts/post-counts-store.js create mode 100644 client/lib/posts/post-edit-store.js create mode 100644 client/lib/posts/post-list-cache-store.js create mode 100644 client/lib/posts/post-list-store.js create mode 100644 client/lib/posts/posts-store.js create mode 100644 client/lib/posts/stats.js create mode 100644 client/lib/posts/test/actions.js create mode 100644 client/lib/posts/test/post-edit-store.js create mode 100644 client/lib/posts/test/utils.js create mode 100644 client/lib/posts/utils.js create mode 100644 client/lib/preferences/Makefile create mode 100644 client/lib/preferences/README.md create mode 100644 client/lib/preferences/actions.js create mode 100644 client/lib/preferences/constants.js create mode 100644 client/lib/preferences/store.js create mode 100644 client/lib/preferences/test/actions.js create mode 100644 client/lib/preferences/test/store.js create mode 100644 client/lib/products-list/README.md create mode 100644 client/lib/products-list/index.js create mode 100644 client/lib/products-values/index.js create mode 100644 client/lib/products-values/schema.json create mode 100644 client/lib/products-values/sort.js create mode 100644 client/lib/purchases/Makefile create mode 100644 client/lib/purchases/assembler.js create mode 100644 client/lib/purchases/index.js create mode 100644 client/lib/purchases/store.js create mode 100644 client/lib/purchases/stored-cards/Makefile create mode 100644 client/lib/purchases/stored-cards/assembler.js create mode 100644 client/lib/purchases/stored-cards/reducer.js create mode 100644 client/lib/purchases/stored-cards/store.js create mode 100644 client/lib/purchases/stored-cards/test/assembler-test.js create mode 100644 client/lib/purchases/stored-cards/test/constants.js create mode 100644 client/lib/purchases/stored-cards/test/store-test.js create mode 100644 client/lib/purchases/test/assembler-test.js create mode 100644 client/lib/purchases/test/store-test.js create mode 100644 client/lib/react-pass-to-children/Makefile create mode 100644 client/lib/react-pass-to-children/README.md create mode 100644 client/lib/react-pass-to-children/index.js create mode 100644 client/lib/react-pass-to-children/test/index.jsx create mode 100644 client/lib/react-smart-set-state/index.js create mode 100644 client/lib/react-test-env-setup/Makefile create mode 100644 client/lib/react-test-env-setup/README.md create mode 100644 client/lib/react-test-env-setup/index.js create mode 100644 client/lib/react-test-env-setup/test/index.js create mode 100644 client/lib/reader-comment-email-subscriptions/Makefile create mode 100644 client/lib/reader-comment-email-subscriptions/actions.js create mode 100644 client/lib/reader-comment-email-subscriptions/constants.js create mode 100644 client/lib/reader-comment-email-subscriptions/index.js create mode 100644 client/lib/reader-comment-email-subscriptions/test/comment-email-subscription-store-test.js create mode 100644 client/lib/reader-feed-subscriptions/Makefile create mode 100644 client/lib/reader-feed-subscriptions/actions.js create mode 100644 client/lib/reader-feed-subscriptions/constants.js create mode 100644 client/lib/reader-feed-subscriptions/helper.js create mode 100644 client/lib/reader-feed-subscriptions/index.js create mode 100644 client/lib/reader-feed-subscriptions/test/feed-subscription-store-test.js create mode 100644 client/lib/reader-lists/README.md create mode 100644 client/lib/reader-lists/actions.js create mode 100644 client/lib/reader-lists/lists.js create mode 100644 client/lib/reader-lists/subscriptions.js create mode 100644 client/lib/reader-post-email-subscriptions/Makefile create mode 100644 client/lib/reader-post-email-subscriptions/actions.js create mode 100644 client/lib/reader-post-email-subscriptions/constants.js create mode 100644 client/lib/reader-post-email-subscriptions/index.js create mode 100644 client/lib/reader-post-email-subscriptions/test/post-email-subscription-store-test.js create mode 100644 client/lib/reader-sidebar/actions.js create mode 100644 client/lib/reader-site-blocks/Makefile create mode 100644 client/lib/reader-site-blocks/actions.js create mode 100644 client/lib/reader-site-blocks/constants.js create mode 100644 client/lib/reader-site-blocks/index.js create mode 100644 client/lib/reader-site-blocks/test/site-block-store-test.js create mode 100644 client/lib/reader-site-store/Makefile create mode 100644 client/lib/reader-site-store/actions.js create mode 100644 client/lib/reader-site-store/constants.js create mode 100644 client/lib/reader-site-store/index.js create mode 100644 client/lib/reader-site-store/test/reader-site-store-tests.js create mode 100644 client/lib/reader-tags/README.md create mode 100644 client/lib/reader-tags/actions.js create mode 100644 client/lib/reader-tags/subscriptions.js create mode 100644 client/lib/reader-tags/tags.js create mode 100644 client/lib/reader-teams/Makefile create mode 100644 client/lib/reader-teams/actions.js create mode 100644 client/lib/reader-teams/constants.js create mode 100644 client/lib/reader-teams/index.js create mode 100644 client/lib/reader-teams/test/team-store-test.js create mode 100644 client/lib/recommended-sites-store/Makefile create mode 100644 client/lib/recommended-sites-store/actions.js create mode 100644 client/lib/recommended-sites-store/constants.js create mode 100644 client/lib/recommended-sites-store/store.js create mode 100644 client/lib/recommended-sites-store/test/action-tests.js create mode 100644 client/lib/recommended-sites-store/test/store-tests.js create mode 100644 client/lib/resize-image-url/Makefile create mode 100644 client/lib/resize-image-url/README.md create mode 100644 client/lib/resize-image-url/index.js create mode 100644 client/lib/resize-image-url/test/test.js create mode 100644 client/lib/route/Makefile create mode 100644 client/lib/route/README.md create mode 100644 client/lib/route/index.js create mode 100644 client/lib/route/normalize.js create mode 100644 client/lib/route/path.js create mode 100644 client/lib/route/redirect.js create mode 100644 client/lib/route/test/index.js create mode 100644 client/lib/route/trailingslashit.js create mode 100644 client/lib/route/untrailingslashit.js create mode 100644 client/lib/safe-image-url/Makefile create mode 100644 client/lib/safe-image-url/README.md create mode 100644 client/lib/safe-image-url/index.js create mode 100644 client/lib/safe-image-url/test/index.js create mode 100644 client/lib/safe-protocol-url/Makefile create mode 100644 client/lib/safe-protocol-url/README.md create mode 100644 client/lib/safe-protocol-url/index.js create mode 100644 client/lib/safe-protocol-url/test/test.js create mode 100644 client/lib/scroll-to/Makefile create mode 100644 client/lib/scroll-to/README.md create mode 100644 client/lib/scroll-to/index.js create mode 100644 client/lib/scroll-to/test/test.js create mode 100644 client/lib/security-checkup/Makefile create mode 100644 client/lib/security-checkup/account-recovery-store.js create mode 100644 client/lib/security-checkup/actions.js create mode 100644 client/lib/security-checkup/constants.js create mode 100644 client/lib/security-checkup/test/account-recovery-store.js create mode 100644 client/lib/security-checkup/test/actions.js create mode 100644 client/lib/security-checkup/test/constants.js create mode 100644 client/lib/services-list/README.md create mode 100644 client/lib/services-list/index.js create mode 100644 client/lib/services-list/list.js create mode 100644 client/lib/sharing-buttons-list/README.md create mode 100644 client/lib/sharing-buttons-list/index.js create mode 100644 client/lib/shortcode/Makefile create mode 100644 client/lib/shortcode/README.md create mode 100644 client/lib/shortcode/index.js create mode 100644 client/lib/shortcode/test/index.js create mode 100644 client/lib/shortcodes/README.md create mode 100644 client/lib/shortcodes/actions.js create mode 100644 client/lib/shortcodes/constants.js create mode 100644 client/lib/shortcodes/store.js create mode 100644 client/lib/siftscience/README.md create mode 100644 client/lib/siftscience/index.js create mode 100644 client/lib/signup/Makefile create mode 100644 client/lib/signup/README.md create mode 100644 client/lib/signup/actions.js create mode 100644 client/lib/signup/cart.js create mode 100644 client/lib/signup/dependency-store.js create mode 100644 client/lib/signup/flow-controller.js create mode 100644 client/lib/signup/progress-store.js create mode 100644 client/lib/signup/step-actions.js create mode 100644 client/lib/signup/test/analytics.js create mode 100644 client/lib/signup/test/dependency-store-test.js create mode 100644 client/lib/signup/test/flow-controller-test.js create mode 100644 client/lib/signup/test/lib/user/index.js create mode 100644 client/lib/signup/test/lib/wp/index.js create mode 100644 client/lib/signup/test/progress-store-test.js create mode 100644 client/lib/signup/test/signup/config/flows.js create mode 100644 client/lib/signup/test/signup/config/steps.js create mode 100644 client/lib/site-roles/Makefile create mode 100644 client/lib/site-roles/README.md create mode 100644 client/lib/site-roles/actions.js create mode 100644 client/lib/site-roles/store.js create mode 100644 client/lib/site-roles/test/lib/mock-actions.js create mode 100644 client/lib/site-roles/test/lib/mock-roles.js create mode 100644 client/lib/site-roles/test/lib/mock-site.js create mode 100644 client/lib/site-roles/test/test-store.js create mode 100644 client/lib/site-specific-plans-details-list/README.md create mode 100644 client/lib/site-specific-plans-details-list/index.js create mode 100644 client/lib/site-stats-sticky-tab/README.md create mode 100644 client/lib/site-stats-sticky-tab/actions.js create mode 100644 client/lib/site-stats-sticky-tab/constants.js create mode 100644 client/lib/site-stats-sticky-tab/store.js create mode 100644 client/lib/site/Makefile create mode 100644 client/lib/site/README.md create mode 100644 client/lib/site/index.js create mode 100644 client/lib/site/jetpack.js create mode 100644 client/lib/site/test/lib/wp.js create mode 100644 client/lib/site/test/test.js create mode 100644 client/lib/site/utils.js create mode 100644 client/lib/sites-list/Makefile create mode 100644 client/lib/sites-list/README.md create mode 100644 client/lib/sites-list/actions.js create mode 100644 client/lib/sites-list/delete-site-store.js create mode 100644 client/lib/sites-list/docs/example.jsx create mode 100644 client/lib/sites-list/index.js create mode 100644 client/lib/sites-list/list.js create mode 100644 client/lib/sites-list/log-store.js create mode 100644 client/lib/sites-list/notices.js create mode 100644 client/lib/sites-list/test/data.js create mode 100644 client/lib/sites-list/test/lib/mixins/i18n.js create mode 100644 client/lib/sites-list/test/lib/mock-actions.js create mode 100644 client/lib/sites-list/test/lib/mock-site.js create mode 100644 client/lib/sites-list/test/lib/user.js create mode 100644 client/lib/sites-list/test/lib/wp.js create mode 100644 client/lib/sites-list/test/test-log-store.js create mode 100644 client/lib/sites-list/test/test.js create mode 100644 client/lib/states-list/README.md create mode 100644 client/lib/states-list/index.js create mode 100644 client/lib/stats/README.md create mode 100644 client/lib/stats/stats-list/Makefile create mode 100644 client/lib/stats/stats-list/README.md create mode 100644 client/lib/stats/stats-list/index.js create mode 100644 client/lib/stats/stats-list/stats-parser.js create mode 100644 client/lib/stats/stats-list/test/analytics.js create mode 100644 client/lib/stats/stats-list/test/data.js create mode 100644 client/lib/stats/stats-list/test/lib/mixins/i18n.js create mode 100644 client/lib/stats/stats-list/test/lib/user.js create mode 100644 client/lib/stats/stats-list/test/lib/wp.js create mode 100644 client/lib/stats/stats-list/test/test-stats-list.js create mode 100644 client/lib/stats/stats-list/test/test-stats-parser.js create mode 100644 client/lib/stats/summary-list/README.md create mode 100644 client/lib/stats/summary-list/index.js create mode 100644 client/lib/stats/summary/README.md create mode 100644 client/lib/stats/summary/index.js create mode 100644 client/lib/store-transactions/README.md create mode 100644 client/lib/store-transactions/index.js create mode 100644 client/lib/store/Makefile create mode 100644 client/lib/store/README.md create mode 100644 client/lib/store/index.js create mode 100644 client/lib/store/test/index-test.js create mode 100644 client/lib/stored-cards/README.md create mode 100644 client/lib/stored-cards/index.js create mode 100644 client/lib/tags-list/README.md create mode 100644 client/lib/tags-list/index.js create mode 100644 client/lib/terms/Makefile create mode 100644 client/lib/terms/README.md create mode 100644 client/lib/terms/actions.js create mode 100644 client/lib/terms/category-store-factory.js create mode 100644 client/lib/terms/category-store.js create mode 100644 client/lib/terms/constants.js create mode 100644 client/lib/terms/store.js create mode 100644 client/lib/terms/tag-store.js create mode 100644 client/lib/terms/test/actions.js create mode 100644 client/lib/terms/test/category-store.js create mode 100644 client/lib/terms/test/common.js create mode 100644 client/lib/terms/test/data.js create mode 100644 client/lib/terms/test/store.js create mode 100644 client/lib/terms/test/tag-store.js create mode 100644 client/lib/ticker/index.js create mode 100644 client/lib/touch-detect/README.md create mode 100644 client/lib/touch-detect/index.js create mode 100644 client/lib/track-scroll-page/index.js create mode 100644 client/lib/transaction/store.js create mode 100644 client/lib/translator-jumpstart/README.md create mode 100644 client/lib/translator-jumpstart/index.js create mode 100644 client/lib/tree-convert/Makefile create mode 100644 client/lib/tree-convert/README.md create mode 100644 client/lib/tree-convert/index.js create mode 100644 client/lib/tree-convert/test/fixtures.js create mode 100644 client/lib/tree-convert/test/test-tree-convert.js create mode 100644 client/lib/tree-convert/tree-traverser.js create mode 100644 client/lib/trophies-data/README.md create mode 100644 client/lib/trophies-data/index.js create mode 100644 client/lib/two-step-authorization/README.md create mode 100644 client/lib/two-step-authorization/index.js create mode 100644 client/lib/upgrades/actions/cart.js create mode 100644 client/lib/upgrades/actions/checkout.js create mode 100644 client/lib/upgrades/actions/domain-management.js create mode 100644 client/lib/upgrades/actions/domain-search.js create mode 100644 client/lib/upgrades/actions/index.js create mode 100644 client/lib/upgrades/actions/purchases.js create mode 100644 client/lib/upgrades/constants.js create mode 100644 client/lib/user-profile-links/README.md create mode 100644 client/lib/user-profile-links/index.js create mode 100644 client/lib/user-settings/Makefile create mode 100644 client/lib/user-settings/README.md create mode 100644 client/lib/user-settings/index.js create mode 100644 client/lib/user-settings/test/index.js create mode 100644 client/lib/user-settings/test/lib/user.js create mode 100644 client/lib/user-settings/test/lib/wp.js create mode 100644 client/lib/user/Makefile create mode 100644 client/lib/user/README.md create mode 100644 client/lib/user/index.js create mode 120000 client/lib/user/shared-utils.js create mode 100644 client/lib/user/test/utils.js create mode 100644 client/lib/user/user.js create mode 100644 client/lib/user/utils.js create mode 100644 client/lib/username/README.md create mode 100644 client/lib/username/index.js create mode 100644 client/lib/users/Makefile create mode 100644 client/lib/users/README.md create mode 100644 client/lib/users/actions.js create mode 100644 client/lib/users/store.js create mode 100644 client/lib/users/test/lib/mock-actions.js create mode 100644 client/lib/users/test/lib/mock-deleted-user-data.js create mode 100644 client/lib/users/test/lib/mock-more-users-data.js create mode 100644 client/lib/users/test/lib/mock-single-user.js create mode 100644 client/lib/users/test/lib/mock-site.js create mode 100644 client/lib/users/test/lib/mock-updated-single-user.js create mode 100644 client/lib/users/test/lib/mock-users-data.js create mode 100644 client/lib/users/test/test-store.js create mode 100644 client/lib/version-compare/README.md create mode 100644 client/lib/version-compare/index.js create mode 100644 client/lib/viewers/Makefile create mode 100644 client/lib/viewers/README.md create mode 100644 client/lib/viewers/actions.js create mode 100644 client/lib/viewers/store.js create mode 100644 client/lib/viewers/test/lib/mock-actions.js create mode 100644 client/lib/viewers/test/lib/mock-site.js create mode 100644 client/lib/viewers/test/lib/mock-viewers-1.js create mode 100644 client/lib/viewers/test/lib/mock-viewers-2.js create mode 100644 client/lib/viewers/test/test-store.js create mode 100644 client/lib/viewport/README.md create mode 100644 client/lib/viewport/index.js create mode 100644 client/lib/warn/index.js create mode 100644 client/lib/wpcom-xhr-wrapper/Makefile create mode 100644 client/lib/wpcom-xhr-wrapper/README.md create mode 100644 client/lib/wpcom-xhr-wrapper/index.js create mode 100644 client/lib/wpcom-xhr-wrapper/test/wpcom-xhr-wrapper.js create mode 100644 client/lib/wporg/index.js create mode 100644 client/lib/wporg/jsonp.js create mode 100644 client/mailing-lists/controller.js create mode 100644 client/mailing-lists/index.js create mode 100644 client/mailing-lists/main.jsx create mode 100644 client/mailing-lists/utils.js create mode 100644 client/me/account-password/README.md create mode 100644 client/me/account-password/index.jsx create mode 100644 client/me/account-password/style.scss create mode 100644 client/me/account/README.md create mode 100644 client/me/account/index.jsx create mode 100644 client/me/account/style.scss create mode 100644 client/me/action-remove/README.md create mode 100644 client/me/action-remove/index.jsx create mode 100644 client/me/action-remove/style.scss create mode 100644 client/me/application-password-item/README.md create mode 100644 client/me/application-password-item/index.jsx create mode 100644 client/me/application-password-item/style.scss create mode 100644 client/me/application-passwords/README.md create mode 100644 client/me/application-passwords/index.jsx create mode 100644 client/me/application-passwords/style.scss create mode 100644 client/me/billing-history/README.md create mode 100644 client/me/billing-history/billing-history-table.jsx create mode 100644 client/me/billing-history/index.jsx create mode 100644 client/me/billing-history/table-rows.js create mode 100644 client/me/billing-history/transactions-header.jsx create mode 100644 client/me/billing-history/transactions-table.jsx create mode 100644 client/me/billing-history/upcoming-charges-table.jsx create mode 100644 client/me/billing-history/view-receipt-modal.jsx create mode 100644 client/me/connected-application-icon/README.md create mode 100644 client/me/connected-application-icon/index.jsx create mode 100644 client/me/connected-application-icon/style.scss create mode 100644 client/me/connected-application-item/README.md create mode 100644 client/me/connected-application-item/index.jsx create mode 100644 client/me/connected-application-item/style.scss create mode 100644 client/me/connected-applications/README.md create mode 100644 client/me/connected-applications/index.jsx create mode 100644 client/me/connected-applications/style.scss create mode 100644 client/me/controller.js create mode 100644 client/me/credit-cards/credit-card-delete.jsx create mode 100644 client/me/credit-cards/credit-card-delete.scss create mode 100644 client/me/credit-cards/credit-cards.scss create mode 100644 client/me/credit-cards/index.jsx create mode 100644 client/me/event-recorder/index.js create mode 100644 client/me/form-base/index.js create mode 100644 client/me/help/README.md create mode 100644 client/me/help/controller.js create mode 100644 client/me/help/help-contact-confirmation/index.jsx create mode 100644 client/me/help/help-contact-confirmation/style.scss create mode 100644 client/me/help/help-contact-form/index.jsx create mode 100644 client/me/help/help-contact-form/style.scss create mode 100644 client/me/help/help-contact/index.jsx create mode 100644 client/me/help/help-contact/style.scss create mode 100644 client/me/help/help-happiness-engineers/index.jsx create mode 100644 client/me/help/help-happiness-engineers/style.scss create mode 100644 client/me/help/help-results/index.jsx create mode 100644 client/me/help/help-results/item.jsx create mode 100644 client/me/help/help-results/style.scss create mode 100644 client/me/help/help-search/index.jsx create mode 100644 client/me/help/help-search/style.scss create mode 100644 client/me/help/index.js create mode 100644 client/me/help/main.jsx create mode 100644 client/me/help/style.scss create mode 100644 client/me/index.js create mode 100644 client/me/next-steps/index.jsx create mode 100644 client/me/next-steps/next-steps-box.jsx create mode 100644 client/me/next-steps/next-steps-box.scss create mode 100644 client/me/next-steps/next-steps.scss create mode 100644 client/me/next-steps/steps.js create mode 100644 client/me/notification-settings/blogs-settings/blog.jsx create mode 100644 client/me/notification-settings/blogs-settings/header.jsx create mode 100644 client/me/notification-settings/blogs-settings/index.jsx create mode 100644 client/me/notification-settings/blogs-settings/placeholder.jsx create mode 100644 client/me/notification-settings/blogs-settings/style.scss create mode 100644 client/me/notification-settings/comment-settings/index.jsx create mode 100644 client/me/notification-settings/comment-settings/style.scss create mode 100644 client/me/notification-settings/index.jsx create mode 100644 client/me/notification-settings/navigation.jsx create mode 100644 client/me/notification-settings/reader-subscriptions/index.jsx create mode 100644 client/me/notification-settings/settings-form/actions.jsx create mode 100644 client/me/notification-settings/settings-form/constants.js create mode 100644 client/me/notification-settings/settings-form/device-selector.jsx create mode 100644 client/me/notification-settings/settings-form/index.jsx create mode 100644 client/me/notification-settings/settings-form/labels-list.jsx create mode 100644 client/me/notification-settings/settings-form/labels.jsx create mode 100644 client/me/notification-settings/settings-form/locales.js create mode 100644 client/me/notification-settings/settings-form/settings.jsx create mode 100644 client/me/notification-settings/settings-form/stream-header.jsx create mode 100644 client/me/notification-settings/settings-form/stream-options.jsx create mode 100644 client/me/notification-settings/settings-form/stream-selector.jsx create mode 100644 client/me/notification-settings/settings-form/stream.jsx create mode 100644 client/me/notification-settings/settings-form/style.scss create mode 100644 client/me/notification-settings/wpcom-settings/index.jsx create mode 100644 client/me/notification-settings/wpcom-settings/style.scss create mode 100644 client/me/paths.js create mode 100644 client/me/profile-gravatar/README.md create mode 100644 client/me/profile-gravatar/index.jsx create mode 100644 client/me/profile-gravatar/style.scss create mode 100644 client/me/profile-link/README.md create mode 100644 client/me/profile-link/index.jsx create mode 100644 client/me/profile-link/style.scss create mode 100644 client/me/profile-links-add-other/README.md create mode 100644 client/me/profile-links-add-other/index.jsx create mode 100644 client/me/profile-links-add-other/style.scss create mode 100644 client/me/profile-links-add-wordpress/README.md create mode 100644 client/me/profile-links-add-wordpress/index.jsx create mode 100644 client/me/profile-links-add-wordpress/style.scss create mode 100644 client/me/profile-links/README.md create mode 100644 client/me/profile-links/index.jsx create mode 100644 client/me/profile-links/style.scss create mode 100644 client/me/profile/README.me create mode 100644 client/me/profile/index.jsx create mode 100644 client/me/purchases/cancel-private-registration/index.jsx create mode 100644 client/me/purchases/cancel-private-registration/style.scss create mode 100644 client/me/purchases/cancel-purchase/button.jsx create mode 100644 client/me/purchases/cancel-purchase/index.jsx create mode 100644 client/me/purchases/cancel-purchase/product-information.jsx create mode 100644 client/me/purchases/cancel-purchase/refund-information.jsx create mode 100644 client/me/purchases/cancel-purchase/style.scss create mode 100644 client/me/purchases/cancel-purchase/support-box.jsx create mode 100644 client/me/purchases/confirm-cancel-purchase/index.jsx create mode 100644 client/me/purchases/confirm-cancel-purchase/load-endpoint-form.js create mode 100644 client/me/purchases/confirm-cancel-purchase/style.scss create mode 100644 client/me/purchases/controller.js create mode 100644 client/me/purchases/list/header/index.jsx create mode 100644 client/me/purchases/list/header/style.scss create mode 100644 client/me/purchases/list/index.jsx create mode 100644 client/me/purchases/list/item/index.jsx create mode 100644 client/me/purchases/list/item/style.scss create mode 100644 client/me/purchases/list/site/index.jsx create mode 100644 client/me/purchases/list/site/style.scss create mode 100644 client/me/purchases/manage-purchase/index.jsx create mode 100644 client/me/purchases/manage-purchase/style.scss create mode 100644 client/me/purchases/paths.js create mode 100644 client/me/purchases/payment/edit-card-details/index.jsx create mode 100644 client/me/purchases/payment/edit-card-details/style.scss create mode 100644 client/me/purchases/payment/edit-payment-method/credit-card.jsx create mode 100644 client/me/purchases/payment/edit-payment-method/index.jsx create mode 100644 client/me/purchases/payment/edit-payment-method/paypal.jsx create mode 100644 client/me/purchases/payment/edit-payment-method/style.scss create mode 100644 client/me/purchases/purchases-mixin.js create mode 100644 client/me/reauth-required/index.jsx create mode 100644 client/me/reauth-required/style.scss create mode 100644 client/me/security-2fa-app-chooser-item/index.jsx create mode 100644 client/me/security-2fa-app-chooser-item/style.scss create mode 100644 client/me/security-2fa-backup-codes-list/index.jsx create mode 100644 client/me/security-2fa-backup-codes-list/style.scss create mode 100644 client/me/security-2fa-backup-codes-prompt/index.jsx create mode 100644 client/me/security-2fa-backup-codes-prompt/style.scss create mode 100644 client/me/security-2fa-backup-codes/README.md create mode 100644 client/me/security-2fa-backup-codes/index.jsx create mode 100644 client/me/security-2fa-backup-codes/style.scss create mode 100644 client/me/security-2fa-code-prompt/README.md create mode 100644 client/me/security-2fa-code-prompt/index.jsx create mode 100644 client/me/security-2fa-code-prompt/style.scss create mode 100644 client/me/security-2fa-disable/README.md create mode 100644 client/me/security-2fa-disable/index.jsx create mode 100644 client/me/security-2fa-disable/style.scss create mode 100644 client/me/security-2fa-enable/index.jsx create mode 100644 client/me/security-2fa-enable/style.scss create mode 100644 client/me/security-2fa-initial-setup/README.md create mode 100644 client/me/security-2fa-initial-setup/index.jsx create mode 100644 client/me/security-2fa-progress/README.md create mode 100644 client/me/security-2fa-progress/index.jsx create mode 100644 client/me/security-2fa-progress/progress-item.jsx create mode 100644 client/me/security-2fa-progress/style.scss create mode 100644 client/me/security-2fa-setup-backup-codes/README.md create mode 100644 client/me/security-2fa-setup-backup-codes/index.jsx create mode 100644 client/me/security-2fa-setup/README.md create mode 100644 client/me/security-2fa-setup/index.jsx create mode 100644 client/me/security-2fa-sms-settings/README.md create mode 100644 client/me/security-2fa-sms-settings/index.jsx create mode 100644 client/me/security-2fa-sms-settings/style.scss create mode 100644 client/me/security-2fa-status/README.md create mode 100644 client/me/security-2fa-status/index.jsx create mode 100644 client/me/security-2fa-status/style.scss create mode 100644 client/me/security-checkup/buttons.jsx create mode 100644 client/me/security-checkup/edit-email.jsx create mode 100644 client/me/security-checkup/edit-phone.jsx create mode 100644 client/me/security-checkup/index.jsx create mode 100644 client/me/security-checkup/manage-contact.jsx create mode 100644 client/me/security-checkup/recovery-email.jsx create mode 100644 client/me/security-checkup/recovery-phone.jsx create mode 100644 client/me/security-checkup/style.scss create mode 100644 client/me/security-section-nav/README.me create mode 100644 client/me/security-section-nav/index.jsx create mode 100644 client/me/security/password.jsx create mode 100644 client/me/select-site.jsx create mode 100644 client/me/sidebar-navigation/README.md create mode 100644 client/me/sidebar-navigation/package.json create mode 100644 client/me/sidebar-navigation/sidebar-navigation.jsx create mode 100644 client/me/sidebar-navigation/style.scss create mode 100644 client/me/sidebar/index.jsx create mode 100644 client/me/sidebar/sidebar-item.jsx create mode 100644 client/me/sidebar/style.scss create mode 100644 client/me/two-step/index.jsx create mode 100644 client/me/two-step/style.scss create mode 100644 client/my-sites/README.md create mode 100644 client/my-sites/ads/controller.js create mode 100644 client/my-sites/ads/form-earnings.jsx create mode 100644 client/my-sites/ads/form-settings.jsx create mode 100644 client/my-sites/ads/index.js create mode 100644 client/my-sites/ads/main.jsx create mode 100644 client/my-sites/ads/style.scss create mode 100644 client/my-sites/all-sites-icon/README.md create mode 100644 client/my-sites/all-sites-icon/index.jsx create mode 100644 client/my-sites/all-sites-icon/package.json create mode 100644 client/my-sites/all-sites-icon/style.scss create mode 100644 client/my-sites/all-sites/README.md create mode 100644 client/my-sites/all-sites/index.jsx create mode 100644 client/my-sites/all-sites/style.scss create mode 100644 client/my-sites/category-selector/README.md create mode 100644 client/my-sites/category-selector/add-category.jsx create mode 100644 client/my-sites/category-selector/index.jsx create mode 100644 client/my-sites/category-selector/no-results.jsx create mode 100644 client/my-sites/category-selector/search.jsx create mode 100644 client/my-sites/category-selector/search.scss create mode 100644 client/my-sites/category-selector/style.scss create mode 100644 client/my-sites/controller.js create mode 100644 client/my-sites/current-site/README.md create mode 100644 client/my-sites/current-site/index.jsx create mode 100644 client/my-sites/current-site/style.scss create mode 100644 client/my-sites/customize/README.md create mode 100644 client/my-sites/customize/actions.js create mode 100644 client/my-sites/customize/controller.js create mode 100644 client/my-sites/customize/index.js create mode 100644 client/my-sites/customize/loading-panel.jsx create mode 100644 client/my-sites/customize/main.jsx create mode 100644 client/my-sites/customize/package.json create mode 100644 client/my-sites/customize/style.scss create mode 100644 client/my-sites/draft/README.md create mode 100644 client/my-sites/draft/index.jsx create mode 100644 client/my-sites/draft/style.scss create mode 100644 client/my-sites/drafts/controller.js create mode 100644 client/my-sites/drafts/draft-list.jsx create mode 100644 client/my-sites/drafts/index.js create mode 100644 client/my-sites/drafts/main.jsx create mode 100644 client/my-sites/drafts/style.scss create mode 100644 client/my-sites/exporter/advanced-options.jsx create mode 100644 client/my-sites/exporter/option-fieldset.jsx create mode 100644 client/my-sites/exporter/style.scss create mode 100644 client/my-sites/importer/Makefile create mode 100644 client/my-sites/importer/author-mapping-item.jsx create mode 100644 client/my-sites/importer/author-mapping-pane.jsx create mode 100644 client/my-sites/importer/error-pane.jsx create mode 100644 client/my-sites/importer/file-importer.jsx create mode 100644 client/my-sites/importer/importer-ghost.jsx create mode 100644 client/my-sites/importer/importer-header.jsx create mode 100644 client/my-sites/importer/importer-icons.jsx create mode 100644 client/my-sites/importer/importer-medium.jsx create mode 100644 client/my-sites/importer/importer-squarespace.jsx create mode 100644 client/my-sites/importer/importer-wordpress.jsx create mode 100644 client/my-sites/importer/importing-pane.jsx create mode 100644 client/my-sites/importer/style.scss create mode 100644 client/my-sites/importer/test/mock-data.js create mode 100644 client/my-sites/importer/uploading-pane.jsx create mode 100644 client/my-sites/index.js create mode 100644 client/my-sites/jetpack-manage-error-page/README.md create mode 100644 client/my-sites/jetpack-manage-error-page/index.jsx create mode 100644 client/my-sites/jetpack-manage-error-page/package.json create mode 100644 client/my-sites/media-library/Makefile create mode 100644 client/my-sites/media-library/content.jsx create mode 100644 client/my-sites/media-library/content.scss create mode 100644 client/my-sites/media-library/drop-zone.jsx create mode 100644 client/my-sites/media-library/filter-bar.jsx create mode 100644 client/my-sites/media-library/filter-to-mime-prefix.js create mode 100644 client/my-sites/media-library/header.jsx create mode 100644 client/my-sites/media-library/index.jsx create mode 100644 client/my-sites/media-library/list-item-audio.jsx create mode 100644 client/my-sites/media-library/list-item-document.jsx create mode 100644 client/my-sites/media-library/list-item-file-details.jsx create mode 100644 client/my-sites/media-library/list-item-file-details.scss create mode 100644 client/my-sites/media-library/list-item-image.jsx create mode 100644 client/my-sites/media-library/list-item-video.jsx create mode 100644 client/my-sites/media-library/list-item-video.scss create mode 100644 client/my-sites/media-library/list-item.jsx create mode 100644 client/my-sites/media-library/list-item.scss create mode 100644 client/my-sites/media-library/list-no-content.jsx create mode 100644 client/my-sites/media-library/list-no-results.jsx create mode 100644 client/my-sites/media-library/list.jsx create mode 100644 client/my-sites/media-library/style.scss create mode 100644 client/my-sites/media-library/test/fixtures.js create mode 100644 client/my-sites/media-library/test/list.jsx create mode 100644 client/my-sites/media-library/upload-button.jsx create mode 100644 client/my-sites/media-library/upload-button.scss create mode 100644 client/my-sites/media-library/upload-url.jsx create mode 100644 client/my-sites/media-library/upload-url.scss create mode 100644 client/my-sites/media/controller.js create mode 100644 client/my-sites/media/index.js create mode 100644 client/my-sites/media/main.jsx create mode 100644 client/my-sites/menus/README.md create mode 100644 client/my-sites/menus/controller.js create mode 100644 client/my-sites/menus/index.js create mode 100644 client/my-sites/menus/item-options/Makefile create mode 100644 client/my-sites/menus/item-options/README.md create mode 100644 client/my-sites/menus/item-options/category-options.jsx create mode 100644 client/my-sites/menus/item-options/empty-placeholder.jsx create mode 100644 client/my-sites/menus/item-options/loading-placeholder.jsx create mode 100644 client/my-sites/menus/item-options/option-list.jsx create mode 100644 client/my-sites/menus/item-options/options.jsx create mode 100644 client/my-sites/menus/item-options/post-list.jsx create mode 100644 client/my-sites/menus/item-options/posts.jsx create mode 100644 client/my-sites/menus/item-options/taxonomy-list.jsx create mode 100644 client/my-sites/menus/item-options/test/test-posts.jsx create mode 100644 client/my-sites/menus/loading-placeholder.jsx create mode 100644 client/my-sites/menus/location-picker.jsx create mode 100644 client/my-sites/menus/main.jsx create mode 100644 client/my-sites/menus/menu-delete-button.jsx create mode 100644 client/my-sites/menus/menu-editable-item.jsx create mode 100644 client/my-sites/menus/menu-item-drop-target.jsx create mode 100644 client/my-sites/menus/menu-item-list.jsx create mode 100644 client/my-sites/menus/menu-item-types.js create mode 100644 client/my-sites/menus/menu-name.jsx create mode 100644 client/my-sites/menus/menu-panel-back-button.jsx create mode 100644 client/my-sites/menus/menu-picker.jsx create mode 100644 client/my-sites/menus/menu-placeholder.jsx create mode 100644 client/my-sites/menus/menu-utils.js create mode 100644 client/my-sites/menus/menu.jsx create mode 100644 client/my-sites/menus/menus-save-button.jsx create mode 100644 client/my-sites/navigation/navigation.jsx create mode 100644 client/my-sites/navigation/package.json create mode 100644 client/my-sites/no-results/index.jsx create mode 100644 client/my-sites/no-results/style.scss create mode 100644 client/my-sites/pages/README.md create mode 100644 client/my-sites/pages/controller.js create mode 100644 client/my-sites/pages/helpers.js create mode 100644 client/my-sites/pages/index.js create mode 100644 client/my-sites/pages/main.jsx create mode 100644 client/my-sites/pages/page-list.jsx create mode 100644 client/my-sites/pages/page.jsx create mode 100644 client/my-sites/pages/placeholder.jsx create mode 100644 client/my-sites/pages/style.scss create mode 100644 client/my-sites/people/README.md create mode 100644 client/my-sites/people/controller.js create mode 100644 client/my-sites/people/delete-user/README.md create mode 100644 client/my-sites/people/delete-user/index.jsx create mode 100644 client/my-sites/people/delete-user/style.scss create mode 100644 client/my-sites/people/edit-team-member-form/README.md create mode 100644 client/my-sites/people/edit-team-member-form/index.jsx create mode 100644 client/my-sites/people/edit-team-member-form/style.scss create mode 100644 client/my-sites/people/followers-list/README.md create mode 100644 client/my-sites/people/followers-list/index.jsx create mode 100644 client/my-sites/people/index.js create mode 100644 client/my-sites/people/main.jsx create mode 100644 client/my-sites/people/people-list-item/README.md create mode 100644 client/my-sites/people/people-list-item/index.jsx create mode 100644 client/my-sites/people/people-list-item/style.scss create mode 100644 client/my-sites/people/people-notices/README.md create mode 100644 client/my-sites/people/people-notices/index.jsx create mode 100644 client/my-sites/people/people-notices/style.scss create mode 100644 client/my-sites/people/people-profile/README.md create mode 100644 client/my-sites/people/people-profile/index.jsx create mode 100644 client/my-sites/people/people-profile/style.scss create mode 100644 client/my-sites/people/people-section-nav/README.md create mode 100644 client/my-sites/people/people-section-nav/index.jsx create mode 100644 client/my-sites/people/role-select/README.md create mode 100644 client/my-sites/people/role-select/index.jsx create mode 100644 client/my-sites/people/team-list/README.md create mode 100644 client/my-sites/people/team-list/index.jsx create mode 100644 client/my-sites/people/viewers-list/README.md create mode 100644 client/my-sites/people/viewers-list/index.jsx create mode 100644 client/my-sites/picker/README.md create mode 100644 client/my-sites/picker/package.json create mode 100644 client/my-sites/picker/picker.jsx create mode 100644 client/my-sites/plans/README.md create mode 100644 client/my-sites/plans/controller.jsx create mode 100644 client/my-sites/plans/index.js create mode 100644 client/my-sites/plans/main.jsx create mode 100644 client/my-sites/plans/plans-select.jsx create mode 100644 client/my-sites/plans/style.scss create mode 100644 client/my-sites/plugins/README.md create mode 100644 client/my-sites/plugins/access-control.js create mode 100644 client/my-sites/plugins/controller.js create mode 100644 client/my-sites/plugins/disconnect-jetpack/disconnect-jetpack-button.jsx create mode 100644 client/my-sites/plugins/disconnect-jetpack/disconnect-jetpack-dialog.jsx create mode 100644 client/my-sites/plugins/featured-plugins/README.md create mode 100644 client/my-sites/plugins/featured-plugins/index.jsx create mode 100644 client/my-sites/plugins/featured-plugins/style.scss create mode 100644 client/my-sites/plugins/index.js create mode 100644 client/my-sites/plugins/main.jsx create mode 100644 client/my-sites/plugins/plugin-action/Makefile create mode 100644 client/my-sites/plugins/plugin-action/README.md create mode 100644 client/my-sites/plugins/plugin-action/plugin-action.jsx create mode 100644 client/my-sites/plugins/plugin-action/style.scss create mode 100644 client/my-sites/plugins/plugin-action/test/index.jsx create mode 100644 client/my-sites/plugins/plugin-activate-toggle/Makefile create mode 100644 client/my-sites/plugins/plugin-activate-toggle/README.md create mode 100644 client/my-sites/plugins/plugin-activate-toggle/index.jsx create mode 100644 client/my-sites/plugins/plugin-activate-toggle/style.scss create mode 100644 client/my-sites/plugins/plugin-activate-toggle/test/fixtures.js create mode 100644 client/my-sites/plugins/plugin-activate-toggle/test/index.jsx create mode 100644 client/my-sites/plugins/plugin-activate-toggle/test/mocks/actions.js create mode 100644 client/my-sites/plugins/plugin-activate-toggle/test/mocks/plugin-action.jsx create mode 100644 client/my-sites/plugins/plugin-autoupdate-toggle/Makefile create mode 100644 client/my-sites/plugins/plugin-autoupdate-toggle/README.md create mode 100644 client/my-sites/plugins/plugin-autoupdate-toggle/index.jsx create mode 100644 client/my-sites/plugins/plugin-autoupdate-toggle/test/fixtures.js create mode 100644 client/my-sites/plugins/plugin-autoupdate-toggle/test/index.jsx create mode 100644 client/my-sites/plugins/plugin-autoupdate-toggle/test/mocks/actions.js create mode 100644 client/my-sites/plugins/plugin-autoupdate-toggle/test/mocks/plugin-action.jsx create mode 100644 client/my-sites/plugins/plugin-card-header/README.md create mode 100644 client/my-sites/plugins/plugin-card-header/index.jsx create mode 100644 client/my-sites/plugins/plugin-card-header/style.scss create mode 100644 client/my-sites/plugins/plugin-icon/README.md create mode 100644 client/my-sites/plugins/plugin-icon/plugin-icon.jsx create mode 100644 client/my-sites/plugins/plugin-icon/style.scss create mode 100644 client/my-sites/plugins/plugin-information/README.md create mode 100644 client/my-sites/plugins/plugin-information/index.jsx create mode 100644 client/my-sites/plugins/plugin-information/style.scss create mode 100644 client/my-sites/plugins/plugin-install-button/README.md create mode 100644 client/my-sites/plugins/plugin-install-button/index.jsx create mode 100644 client/my-sites/plugins/plugin-install-button/style.scss create mode 100644 client/my-sites/plugins/plugin-item/README.md create mode 100644 client/my-sites/plugins/plugin-item/plugin-item.jsx create mode 100644 client/my-sites/plugins/plugin-item/style.scss create mode 100644 client/my-sites/plugins/plugin-meta/README.md create mode 100644 client/my-sites/plugins/plugin-meta/index.jsx create mode 100644 client/my-sites/plugins/plugin-meta/style.scss create mode 100644 client/my-sites/plugins/plugin-ratings/README.md create mode 100644 client/my-sites/plugins/plugin-ratings/index.jsx create mode 100644 client/my-sites/plugins/plugin-ratings/style.scss create mode 100644 client/my-sites/plugins/plugin-remove-button/README.md create mode 100644 client/my-sites/plugins/plugin-remove-button/index.jsx create mode 100644 client/my-sites/plugins/plugin-remove-button/style.scss create mode 100644 client/my-sites/plugins/plugin-sections/README.md create mode 100644 client/my-sites/plugins/plugin-sections/index.jsx create mode 100644 client/my-sites/plugins/plugin-sections/style.scss create mode 100644 client/my-sites/plugins/plugin-site-business/README.md create mode 100644 client/my-sites/plugins/plugin-site-business/index.jsx create mode 100644 client/my-sites/plugins/plugin-site-business/style.scss create mode 100644 client/my-sites/plugins/plugin-site-disabled-manage/README.md create mode 100644 client/my-sites/plugins/plugin-site-disabled-manage/index.jsx create mode 100644 client/my-sites/plugins/plugin-site-disabled-manage/style.scss create mode 100644 client/my-sites/plugins/plugin-site-jetpack/README.md create mode 100644 client/my-sites/plugins/plugin-site-jetpack/index.jsx create mode 100644 client/my-sites/plugins/plugin-site-jetpack/style.scss create mode 100644 client/my-sites/plugins/plugin-site-list/README.md create mode 100644 client/my-sites/plugins/plugin-site-list/index.jsx create mode 100644 client/my-sites/plugins/plugin-site-network/README.md create mode 100644 client/my-sites/plugins/plugin-site-network/index.jsx create mode 100644 client/my-sites/plugins/plugin-site-network/style.scss create mode 100644 client/my-sites/plugins/plugin-site-update-indicator/README.md create mode 100644 client/my-sites/plugins/plugin-site-update-indicator/index.jsx create mode 100644 client/my-sites/plugins/plugin-site-update-indicator/style.scss create mode 100644 client/my-sites/plugins/plugin-site/README.md create mode 100644 client/my-sites/plugins/plugin-site/plugin-site.jsx create mode 100644 client/my-sites/plugins/plugin-toggle/README.md create mode 100644 client/my-sites/plugins/plugin-toggle/plugin-toggle.jsx create mode 100644 client/my-sites/plugins/plugin-version/README.md create mode 100644 client/my-sites/plugins/plugin-version/index.jsx create mode 100644 client/my-sites/plugins/plugin-version/style.scss create mode 100644 client/my-sites/plugins/plugin.jsx create mode 100644 client/my-sites/plugins/plugins-browser-item/README.md create mode 100644 client/my-sites/plugins/plugins-browser-item/index.jsx create mode 100644 client/my-sites/plugins/plugins-browser-item/style.scss create mode 100644 client/my-sites/plugins/plugins-browser-list/README.md create mode 100644 client/my-sites/plugins/plugins-browser-list/index.jsx create mode 100644 client/my-sites/plugins/plugins-browser-list/style.scss create mode 100644 client/my-sites/plugins/plugins-browser/README.md create mode 100644 client/my-sites/plugins/plugins-browser/index.jsx create mode 100644 client/my-sites/plugins/plugins-browser/style.scss create mode 100644 client/my-sites/plugins/plugins-manage-mixin.js create mode 100644 client/my-sites/plugins/style.scss create mode 100644 client/my-sites/post-relative-time-status/README.md create mode 100644 client/my-sites/post-relative-time-status/index.jsx create mode 100644 client/my-sites/post-selector/README.md create mode 100644 client/my-sites/post-selector/index.jsx create mode 100644 client/my-sites/post-selector/no-results.jsx create mode 100644 client/my-sites/post-selector/search.jsx create mode 100644 client/my-sites/post-selector/search.scss create mode 100644 client/my-sites/post-selector/selector.jsx create mode 100644 client/my-sites/post-selector/style.scss create mode 100644 client/my-sites/post-trends/README.md create mode 100644 client/my-sites/post-trends/day.jsx create mode 100644 client/my-sites/post-trends/index.jsx create mode 100644 client/my-sites/post-trends/month.jsx create mode 100644 client/my-sites/post-trends/style.scss create mode 100644 client/my-sites/post-trends/week.jsx create mode 100644 client/my-sites/post/README.md create mode 100644 client/my-sites/post/post-image/index.jsx create mode 100644 client/my-sites/post/post-image/style.scss create mode 100644 client/my-sites/posts/README.md create mode 100644 client/my-sites/posts/controller.js create mode 100644 client/my-sites/posts/index.js create mode 100644 client/my-sites/posts/main.jsx create mode 100644 client/my-sites/posts/post-controls.jsx create mode 100644 client/my-sites/posts/post-header.jsx create mode 100644 client/my-sites/posts/post-list.jsx create mode 100644 client/my-sites/posts/post-placeholder.jsx create mode 100644 client/my-sites/posts/post-total-views.jsx create mode 100644 client/my-sites/posts/post.jsx create mode 100644 client/my-sites/posts/posts-navigation.jsx create mode 100644 client/my-sites/sharing/README.md create mode 100644 client/my-sites/sharing/buttons/README.md create mode 100644 client/my-sites/sharing/buttons/appearance.jsx create mode 100644 client/my-sites/sharing/buttons/buttons.jsx create mode 100644 client/my-sites/sharing/buttons/label-editor.jsx create mode 100644 client/my-sites/sharing/buttons/options.jsx create mode 100644 client/my-sites/sharing/buttons/preview-action.jsx create mode 100644 client/my-sites/sharing/buttons/preview-button.jsx create mode 100644 client/my-sites/sharing/buttons/preview-buttons.jsx create mode 100644 client/my-sites/sharing/buttons/preview-placeholder.jsx create mode 100644 client/my-sites/sharing/buttons/preview-widget.js create mode 100644 client/my-sites/sharing/buttons/preview.jsx create mode 100644 client/my-sites/sharing/buttons/style.jsx create mode 100644 client/my-sites/sharing/buttons/tray.jsx create mode 100644 client/my-sites/sharing/connections/README.md create mode 100644 client/my-sites/sharing/connections/account-dialog-account.jsx create mode 100644 client/my-sites/sharing/connections/account-dialog-account.scss create mode 100644 client/my-sites/sharing/connections/account-dialog.jsx create mode 100644 client/my-sites/sharing/connections/account-dialog.scss create mode 100644 client/my-sites/sharing/connections/connection.jsx create mode 100644 client/my-sites/sharing/connections/connections.jsx create mode 100644 client/my-sites/sharing/connections/service-action.jsx create mode 100644 client/my-sites/sharing/connections/service-connected-accounts.jsx create mode 100644 client/my-sites/sharing/connections/service-connections.js create mode 100644 client/my-sites/sharing/connections/service-description.jsx create mode 100644 client/my-sites/sharing/connections/service-example.jsx create mode 100644 client/my-sites/sharing/connections/service-examples.jsx create mode 100644 client/my-sites/sharing/connections/service-placeholder.jsx create mode 100644 client/my-sites/sharing/connections/service-tip.jsx create mode 100644 client/my-sites/sharing/connections/service.jsx create mode 100644 client/my-sites/sharing/connections/services-group.jsx create mode 100644 client/my-sites/sharing/connections/services-group.scss create mode 100644 client/my-sites/sharing/connections/services/eventbrite.js create mode 100644 client/my-sites/sharing/connections/services/index.js create mode 100644 client/my-sites/sharing/controller.js create mode 100644 client/my-sites/sharing/index.js create mode 100644 client/my-sites/sharing/main.jsx create mode 100644 client/my-sites/sidebar-navigation/README.md create mode 100644 client/my-sites/sidebar-navigation/package.json create mode 100644 client/my-sites/sidebar-navigation/sidebar-navigation.jsx create mode 100644 client/my-sites/sidebar-navigation/style.scss create mode 100644 client/my-sites/sidebar/package.json create mode 100644 client/my-sites/sidebar/publish-menu.jsx create mode 100644 client/my-sites/sidebar/sidebar-menu-item.jsx create mode 100644 client/my-sites/sidebar/sidebar.jsx create mode 100644 client/my-sites/site-indicator/README.md create mode 100644 client/my-sites/site-indicator/package.json create mode 100644 client/my-sites/site-indicator/site-indicator.jsx create mode 100644 client/my-sites/site-indicator/style.scss create mode 100644 client/my-sites/site-settings/README.md create mode 100644 client/my-sites/site-settings/action-panel/body.jsx create mode 100644 client/my-sites/site-settings/action-panel/figure.jsx create mode 100644 client/my-sites/site-settings/action-panel/footer.jsx create mode 100644 client/my-sites/site-settings/action-panel/index.jsx create mode 100644 client/my-sites/site-settings/action-panel/style.scss create mode 100644 client/my-sites/site-settings/action-panel/title.jsx create mode 100644 client/my-sites/site-settings/controller.js create mode 100644 client/my-sites/site-settings/delete-site-options/index.jsx create mode 100644 client/my-sites/site-settings/delete-site-options/style.scss create mode 100644 client/my-sites/site-settings/delete-site/index.jsx create mode 100644 client/my-sites/site-settings/delete-site/style.scss create mode 100644 client/my-sites/site-settings/form-analytics.jsx create mode 100644 client/my-sites/site-settings/form-base.js create mode 100644 client/my-sites/site-settings/form-discussion.jsx create mode 100644 client/my-sites/site-settings/form-general.jsx create mode 100644 client/my-sites/site-settings/form-jetpack-monitor.jsx create mode 100644 client/my-sites/site-settings/form-jetpack-protect.jsx create mode 100644 client/my-sites/site-settings/form-jetpack-scan.jsx create mode 100644 client/my-sites/site-settings/form-writing.jsx create mode 100644 client/my-sites/site-settings/index.js create mode 100644 client/my-sites/site-settings/main.jsx create mode 100644 client/my-sites/site-settings/press-this-link.jsx create mode 100644 client/my-sites/site-settings/related-content-preview.jsx create mode 100644 client/my-sites/site-settings/section-analytics.jsx create mode 100644 client/my-sites/site-settings/section-discussion.jsx create mode 100644 client/my-sites/site-settings/section-export.jsx create mode 100644 client/my-sites/site-settings/section-general.jsx create mode 100644 client/my-sites/site-settings/section-import.jsx create mode 100644 client/my-sites/site-settings/section-security.jsx create mode 100644 client/my-sites/site-settings/section-writing.jsx create mode 100644 client/my-sites/site-settings/settings-card-footer/index.jsx create mode 100644 client/my-sites/site-settings/settings-card-footer/style.scss create mode 100644 client/my-sites/site-settings/start-over/index.jsx create mode 100644 client/my-sites/site/README.md create mode 100644 client/my-sites/site/index.jsx create mode 100644 client/my-sites/site/placeholder.jsx create mode 100644 client/my-sites/site/style.scss create mode 100644 client/my-sites/sites/README.md create mode 100644 client/my-sites/sites/package.json create mode 100644 client/my-sites/sites/site-card.jsx create mode 100644 client/my-sites/sites/sites.jsx create mode 100644 client/my-sites/stats/README.md create mode 100644 client/my-sites/stats/action-follow.jsx create mode 100644 client/my-sites/stats/action-link.jsx create mode 100644 client/my-sites/stats/action-page.jsx create mode 100644 client/my-sites/stats/action-spam.jsx create mode 100644 client/my-sites/stats/all-time/index.jsx create mode 100644 client/my-sites/stats/all-time/style.scss create mode 100644 client/my-sites/stats/controller.js create mode 100644 client/my-sites/stats/download-csv/README.md create mode 100644 client/my-sites/stats/download-csv/index.jsx create mode 100644 client/my-sites/stats/follows.jsx create mode 100644 client/my-sites/stats/geochart/README.md create mode 100644 client/my-sites/stats/geochart/index.jsx create mode 100644 client/my-sites/stats/geochart/style.scss create mode 100644 client/my-sites/stats/index.js create mode 100644 client/my-sites/stats/info-panel.jsx create mode 100644 client/my-sites/stats/insights.jsx create mode 100644 client/my-sites/stats/mixin-skeleton.js create mode 100644 client/my-sites/stats/mixin-toggle.js create mode 100644 client/my-sites/stats/module-chart-tabs.jsx create mode 100644 client/my-sites/stats/module-comments.jsx create mode 100644 client/my-sites/stats/module-countries.jsx create mode 100644 client/my-sites/stats/module-date-picker.jsx create mode 100644 client/my-sites/stats/module-error.jsx create mode 100644 client/my-sites/stats/module-followers-page.jsx create mode 100644 client/my-sites/stats/module-followers.jsx create mode 100644 client/my-sites/stats/module-post-months.jsx create mode 100644 client/my-sites/stats/module-post-weeks.jsx create mode 100644 client/my-sites/stats/module-site-overview-placeholder.jsx create mode 100644 client/my-sites/stats/module-summary-chart.jsx create mode 100644 client/my-sites/stats/module-tab.jsx create mode 100644 client/my-sites/stats/module-tabs.jsx create mode 100644 client/my-sites/stats/module-video-details.jsx create mode 100644 client/my-sites/stats/most-popular/index.jsx create mode 100644 client/my-sites/stats/most-popular/style.scss create mode 100644 client/my-sites/stats/nux/data.js create mode 100644 client/my-sites/stats/nux/insights.jsx create mode 100644 client/my-sites/stats/nux/site.jsx create mode 100644 client/my-sites/stats/nux/style.scss create mode 100644 client/my-sites/stats/overview/README.md create mode 100644 client/my-sites/stats/overview/index.jsx create mode 100644 client/my-sites/stats/overview/style.scss create mode 100644 client/my-sites/stats/pagination/README.md create mode 100644 client/my-sites/stats/pagination/index.jsx create mode 100644 client/my-sites/stats/pagination/pagination-page.jsx create mode 100644 client/my-sites/stats/pagination/style.scss create mode 100644 client/my-sites/stats/post-performance/README.md create mode 100644 client/my-sites/stats/post-performance/index.jsx create mode 100644 client/my-sites/stats/post.jsx create mode 100644 client/my-sites/stats/site.jsx create mode 100644 client/my-sites/stats/stats-list-item.jsx create mode 100644 client/my-sites/stats/stats-list.jsx create mode 100644 client/my-sites/stats/stats-module.jsx create mode 100644 client/my-sites/stats/stats-navigation.jsx create mode 100644 client/my-sites/stats/stats-overview.jsx create mode 100644 client/my-sites/stats/stats-strings.js create mode 100644 client/my-sites/stats/summary.jsx create mode 100644 client/my-sites/upgrades/README.md create mode 100644 client/my-sites/upgrades/cart/Makefile create mode 100644 client/my-sites/upgrades/cart/README.md create mode 100644 client/my-sites/upgrades/cart/cart-body.jsx create mode 100644 client/my-sites/upgrades/cart/cart-buttons.jsx create mode 100644 client/my-sites/upgrades/cart/cart-coupon.jsx create mode 100644 client/my-sites/upgrades/cart/cart-empty.jsx create mode 100644 client/my-sites/upgrades/cart/cart-item.jsx create mode 100644 client/my-sites/upgrades/cart/cart-items.jsx create mode 100644 client/my-sites/upgrades/cart/cart-messages-mixin.jsx create mode 100644 client/my-sites/upgrades/cart/cart-plan-ad.jsx create mode 100644 client/my-sites/upgrades/cart/cart-summary-bar.jsx create mode 100644 client/my-sites/upgrades/cart/cart-total.jsx create mode 100644 client/my-sites/upgrades/cart/popover-cart.jsx create mode 100644 client/my-sites/upgrades/cart/secondary-cart.jsx create mode 100644 client/my-sites/upgrades/cart/style.scss create mode 100644 client/my-sites/upgrades/cart/test/test-cart-buttons.jsx create mode 100644 client/my-sites/upgrades/checkout/README.md create mode 100644 client/my-sites/upgrades/checkout/checkout.jsx create mode 100644 client/my-sites/upgrades/checkout/credit-card-payment-box.jsx create mode 100644 client/my-sites/upgrades/checkout/credit-card-selector.jsx create mode 100644 client/my-sites/upgrades/checkout/credits-payment-box.jsx create mode 100644 client/my-sites/upgrades/checkout/domain-details-form.jsx create mode 100644 client/my-sites/upgrades/checkout/free-cart-payment-box.jsx create mode 100644 client/my-sites/upgrades/checkout/new-card-form.jsx create mode 100644 client/my-sites/upgrades/checkout/package.json create mode 100644 client/my-sites/upgrades/checkout/pay-button.jsx create mode 100644 client/my-sites/upgrades/checkout/payment-box.jsx create mode 100644 client/my-sites/upgrades/checkout/paypal-payment-box.jsx create mode 100644 client/my-sites/upgrades/checkout/privacy-protection-dialog.jsx create mode 100644 client/my-sites/upgrades/checkout/privacy-protection-example.jsx create mode 100644 client/my-sites/upgrades/checkout/privacy-protection.jsx create mode 100644 client/my-sites/upgrades/checkout/secure-payment-form.jsx create mode 100644 client/my-sites/upgrades/checkout/stored-card.jsx create mode 100644 client/my-sites/upgrades/checkout/stored-card.scss create mode 100644 client/my-sites/upgrades/checkout/subscription-text.jsx create mode 100644 client/my-sites/upgrades/checkout/subscription-text.scss create mode 100644 client/my-sites/upgrades/checkout/supporting-text.jsx create mode 100644 client/my-sites/upgrades/checkout/terms-of-service.jsx create mode 100644 client/my-sites/upgrades/checkout/thank-you.jsx create mode 100644 client/my-sites/upgrades/checkout/transaction-steps-mixin.jsx create mode 100644 client/my-sites/upgrades/components/README.md create mode 100644 client/my-sites/upgrades/components/domain-warnings/Makefile create mode 100644 client/my-sites/upgrades/components/domain-warnings/index.jsx create mode 100644 client/my-sites/upgrades/components/domain-warnings/test/test-domain-warnings.jsx create mode 100644 client/my-sites/upgrades/components/form/country-select.jsx create mode 100644 client/my-sites/upgrades/components/form/focus-mixin.js create mode 100644 client/my-sites/upgrades/components/form/hidden-input.jsx create mode 100644 client/my-sites/upgrades/components/form/input.jsx create mode 100644 client/my-sites/upgrades/components/form/state-select.jsx create mode 100644 client/my-sites/upgrades/controller.jsx create mode 100644 client/my-sites/upgrades/domain-management/README.md create mode 100644 client/my-sites/upgrades/domain-management/add-google-apps/add-email-addresses-card.jsx create mode 100644 client/my-sites/upgrades/domain-management/add-google-apps/domains-select.jsx create mode 100644 client/my-sites/upgrades/domain-management/add-google-apps/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/components/domain/main-placeholder.jsx create mode 100644 client/my-sites/upgrades/domain-management/components/domain/primary-flag.jsx create mode 100644 client/my-sites/upgrades/domain-management/components/form-footer/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/components/header/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/components/icann-verification.jsx create mode 100644 client/my-sites/upgrades/domain-management/contacts-privacy/card.jsx create mode 100644 client/my-sites/upgrades/domain-management/contacts-privacy/contact-display.jsx create mode 100644 client/my-sites/upgrades/domain-management/contacts-privacy/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/controller.jsx create mode 100644 client/my-sites/upgrades/domain-management/dns/a-record.jsx create mode 100644 client/my-sites/upgrades/domain-management/dns/cname-record.jsx create mode 100644 client/my-sites/upgrades/domain-management/dns/dns-add-new.jsx create mode 100644 client/my-sites/upgrades/domain-management/dns/dns-details.jsx create mode 100644 client/my-sites/upgrades/domain-management/dns/dns-list.jsx create mode 100644 client/my-sites/upgrades/domain-management/dns/dns-record.jsx create mode 100644 client/my-sites/upgrades/domain-management/dns/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/dns/mx-record.jsx create mode 100644 client/my-sites/upgrades/domain-management/dns/srv-record.jsx create mode 100644 client/my-sites/upgrades/domain-management/dns/txt-record.jsx create mode 100644 client/my-sites/upgrades/domain-management/domain-management.jsx create mode 100644 client/my-sites/upgrades/domain-management/edit-contact-info/form-card.jsx create mode 100644 client/my-sites/upgrades/domain-management/edit-contact-info/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/edit-contact-info/privacy-enabled-card.jsx create mode 100644 client/my-sites/upgrades/domain-management/edit/card/header/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/edit/card/header/primary-domain-button.jsx create mode 100644 client/my-sites/upgrades/domain-management/edit/card/property.jsx create mode 100644 client/my-sites/upgrades/domain-management/edit/card/subscription-settings.jsx create mode 100644 client/my-sites/upgrades/domain-management/edit/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/edit/mapped-domain.jsx create mode 100644 client/my-sites/upgrades/domain-management/edit/registered-domain.jsx create mode 100644 client/my-sites/upgrades/domain-management/edit/site-redirect.jsx create mode 100644 client/my-sites/upgrades/domain-management/edit/wpcom-domain.jsx create mode 100644 client/my-sites/upgrades/domain-management/email-forwarding/email-forwarding-add-new.jsx create mode 100644 client/my-sites/upgrades/domain-management/email-forwarding/email-forwarding-details.jsx create mode 100644 client/my-sites/upgrades/domain-management/email-forwarding/email-forwarding-item.jsx create mode 100644 client/my-sites/upgrades/domain-management/email-forwarding/email-forwarding-limit.jsx create mode 100644 client/my-sites/upgrades/domain-management/email-forwarding/email-forwarding-list.jsx create mode 100644 client/my-sites/upgrades/domain-management/email-forwarding/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/email/add-google-apps-card.jsx create mode 100644 client/my-sites/upgrades/domain-management/email/google-apps-users-card.jsx create mode 100644 client/my-sites/upgrades/domain-management/email/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/list/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/list/item-placeholder.jsx create mode 100644 client/my-sites/upgrades/domain-management/list/item.jsx create mode 100644 client/my-sites/upgrades/domain-management/name-servers/custom-nameservers-form.jsx create mode 100644 client/my-sites/upgrades/domain-management/name-servers/custom-nameservers-row.jsx create mode 100644 client/my-sites/upgrades/domain-management/name-servers/icann-verification-card.jsx create mode 100644 client/my-sites/upgrades/domain-management/name-servers/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/name-servers/wpcom-nameservers-toggle.jsx create mode 100644 client/my-sites/upgrades/domain-management/package.json create mode 100644 client/my-sites/upgrades/domain-management/primary-domain/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/privacy-protection/card/add-button.jsx create mode 100644 client/my-sites/upgrades/domain-management/privacy-protection/card/content.jsx create mode 100644 client/my-sites/upgrades/domain-management/privacy-protection/card/header.jsx create mode 100644 client/my-sites/upgrades/domain-management/privacy-protection/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/site-redirect/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/site-redirect/notice.jsx create mode 100644 client/my-sites/upgrades/domain-management/style.scss create mode 100644 client/my-sites/upgrades/domain-management/transfer/enable-domain-locking-notice.jsx create mode 100644 client/my-sites/upgrades/domain-management/transfer/enable-privacy-notice.jsx create mode 100644 client/my-sites/upgrades/domain-management/transfer/icann-verification-notice.jsx create mode 100644 client/my-sites/upgrades/domain-management/transfer/index.jsx create mode 100644 client/my-sites/upgrades/domain-management/transfer/pending-transfer-notice.jsx create mode 100644 client/my-sites/upgrades/domain-management/transfer/request-transfer-code.jsx create mode 100644 client/my-sites/upgrades/domain-management/transfer/transfer-prohibited-notice.jsx create mode 100644 client/my-sites/upgrades/domain-search/Makefile create mode 100644 client/my-sites/upgrades/domain-search/README.md create mode 100644 client/my-sites/upgrades/domain-search/domain-search.jsx create mode 100644 client/my-sites/upgrades/domain-search/package.json create mode 100644 client/my-sites/upgrades/domain-search/site-redirect-step.jsx create mode 100644 client/my-sites/upgrades/domain-search/site-redirect.jsx create mode 100644 client/my-sites/upgrades/domain-search/test/test-domain-suggestion.jsx create mode 100644 client/my-sites/upgrades/index.js create mode 100644 client/my-sites/upgrades/navigation.jsx create mode 100644 client/my-sites/upgrades/paths.js create mode 100644 client/my-sites/welcome/README.md create mode 100644 client/my-sites/welcome/package.json create mode 100644 client/my-sites/welcome/welcome.jsx create mode 100644 client/notices/README.md create mode 100644 client/notices/arrow-link.jsx create mode 100644 client/notices/delete-site-notices.jsx create mode 100644 client/notices/index.js create mode 100644 client/notices/notice.jsx create mode 100644 client/notices/notices-list.jsx create mode 100644 client/notices/simple-notice.jsx create mode 100644 client/notices/site-notice.jsx create mode 100644 client/notices/style.scss create mode 100644 client/notices/validation-error-list.jsx create mode 100644 client/notifications/README.md create mode 100644 client/notifications/index.jsx create mode 100644 client/nux-welcome/README.md create mode 100644 client/nux-welcome/index.js create mode 100644 client/nux-welcome/welcome-message.jsx create mode 100644 client/post-editor/Makefile create mode 100644 client/post-editor/README.md create mode 100644 client/post-editor/controller.js create mode 100644 client/post-editor/drafts-button/index.jsx create mode 100644 client/post-editor/drafts-button/style.scss create mode 100644 client/post-editor/edit-post-status/index.jsx create mode 100644 client/post-editor/edit-post-status/style.scss create mode 100644 client/post-editor/editor-action-bar/index.jsx create mode 100644 client/post-editor/editor-action-bar/style.scss create mode 100644 client/post-editor/editor-author/index.jsx create mode 100644 client/post-editor/editor-author/style.scss create mode 100644 client/post-editor/editor-categories/index.jsx create mode 100644 client/post-editor/editor-categories/style.scss create mode 100644 client/post-editor/editor-delete-post/index.jsx create mode 100644 client/post-editor/editor-delete-post/style.scss create mode 100644 client/post-editor/editor-discussion/Makefile create mode 100644 client/post-editor/editor-discussion/index.jsx create mode 100644 client/post-editor/editor-discussion/style.scss create mode 100644 client/post-editor/editor-discussion/test/index.jsx create mode 100644 client/post-editor/editor-drawer-well/index.jsx create mode 100644 client/post-editor/editor-drawer-well/style.scss create mode 100644 client/post-editor/editor-drawer/index.jsx create mode 100644 client/post-editor/editor-drawer/style.scss create mode 100644 client/post-editor/editor-featured-image/index.jsx create mode 100644 client/post-editor/editor-featured-image/preview-container.jsx create mode 100644 client/post-editor/editor-featured-image/preview.jsx create mode 100644 client/post-editor/editor-featured-image/style.scss create mode 100644 client/post-editor/editor-fieldset/README.md create mode 100644 client/post-editor/editor-fieldset/index.jsx create mode 100644 client/post-editor/editor-fieldset/style.scss create mode 100644 client/post-editor/editor-ground-control/Makefile create mode 100644 client/post-editor/editor-ground-control/index.jsx create mode 100644 client/post-editor/editor-ground-control/style.scss create mode 100644 client/post-editor/editor-ground-control/test/index.jsx create mode 100644 client/post-editor/editor-location/index.jsx create mode 100644 client/post-editor/editor-location/search-result.jsx create mode 100644 client/post-editor/editor-location/search.jsx create mode 100644 client/post-editor/editor-location/style.scss create mode 100644 client/post-editor/editor-mobile-navigation/index.jsx create mode 100644 client/post-editor/editor-mobile-navigation/style.scss create mode 100644 client/post-editor/editor-more-options/slug.jsx create mode 100644 client/post-editor/editor-more-options/style.scss create mode 100644 client/post-editor/editor-page-order/index.jsx create mode 100644 client/post-editor/editor-page-order/style.scss create mode 100644 client/post-editor/editor-page-parent/index.jsx create mode 100644 client/post-editor/editor-page-parent/style.scss create mode 100644 client/post-editor/editor-page-slug/index.jsx create mode 100644 client/post-editor/editor-page-templates/index.jsx create mode 100644 client/post-editor/editor-permalink/index.jsx create mode 100644 client/post-editor/editor-permalink/style.scss create mode 100644 client/post-editor/editor-post-formats/accordion.jsx create mode 100644 client/post-editor/editor-post-formats/index.jsx create mode 100644 client/post-editor/editor-post-formats/style.scss create mode 100644 client/post-editor/editor-post-type/index.jsx create mode 100644 client/post-editor/editor-post-type/style.scss create mode 100644 client/post-editor/editor-preview/index.jsx create mode 100644 client/post-editor/editor-revisions/index.jsx create mode 100644 client/post-editor/editor-revisions/style.scss create mode 100644 client/post-editor/editor-sharing/Makefile create mode 100644 client/post-editor/editor-sharing/accordion.jsx create mode 100644 client/post-editor/editor-sharing/index.jsx create mode 100644 client/post-editor/editor-sharing/publicize-connection.jsx create mode 100644 client/post-editor/editor-sharing/publicize-message.jsx create mode 100644 client/post-editor/editor-sharing/publicize-message.scss create mode 100644 client/post-editor/editor-sharing/publicize-options.jsx create mode 100644 client/post-editor/editor-sharing/publicize-options.scss create mode 100644 client/post-editor/editor-sharing/publicize-services.jsx create mode 100644 client/post-editor/editor-sharing/publicize-services.scss create mode 100644 client/post-editor/editor-sharing/sharing-like-options.jsx create mode 100644 client/post-editor/editor-sharing/style.scss create mode 100644 client/post-editor/editor-sharing/test/index.js create mode 100644 client/post-editor/editor-sharing/test/specs/publicize-connection.jsx create mode 100644 client/post-editor/editor-slug/index.jsx create mode 100644 client/post-editor/editor-slug/style.scss create mode 100644 client/post-editor/editor-tags/index.jsx create mode 100644 client/post-editor/editor-taxonomies/Makefile create mode 100644 client/post-editor/editor-taxonomies/accordion.jsx create mode 100644 client/post-editor/editor-taxonomies/test/accordion.jsx create mode 100644 client/post-editor/editor-title/container.jsx create mode 100644 client/post-editor/editor-title/index.jsx create mode 100644 client/post-editor/editor-title/style.scss create mode 100644 client/post-editor/editor-visibility/index.jsx create mode 100644 client/post-editor/editor-visibility/style.scss create mode 100644 client/post-editor/index.js create mode 100644 client/post-editor/invalid-url-dialog.jsx create mode 100644 client/post-editor/media-modal/Makefile create mode 100644 client/post-editor/media-modal/back-to-library.jsx create mode 100644 client/post-editor/media-modal/constants.js create mode 100644 client/post-editor/media-modal/detail/_style.scss create mode 100644 client/post-editor/media-modal/detail/detail-fields.jsx create mode 100644 client/post-editor/media-modal/detail/detail-file-info.jsx create mode 100644 client/post-editor/media-modal/detail/detail-item.jsx create mode 100644 client/post-editor/media-modal/detail/detail-preview-audio.jsx create mode 100644 client/post-editor/media-modal/detail/detail-preview-document.jsx create mode 100644 client/post-editor/media-modal/detail/detail-preview-image.jsx create mode 100644 client/post-editor/media-modal/detail/detail-preview-video.jsx create mode 100644 client/post-editor/media-modal/detail/detail-preview-videopress.jsx create mode 100644 client/post-editor/media-modal/detail/detail-title.jsx create mode 100644 client/post-editor/media-modal/detail/index.jsx create mode 100644 client/post-editor/media-modal/fieldset.jsx create mode 100644 client/post-editor/media-modal/fieldset.scss create mode 100644 client/post-editor/media-modal/gallery-help-container.jsx create mode 100644 client/post-editor/media-modal/gallery-help.jsx create mode 100644 client/post-editor/media-modal/gallery/caption.jsx create mode 100644 client/post-editor/media-modal/gallery/drop-zone.jsx create mode 100644 client/post-editor/media-modal/gallery/edit-item.jsx create mode 100644 client/post-editor/media-modal/gallery/edit.jsx create mode 100644 client/post-editor/media-modal/gallery/fields.jsx create mode 100644 client/post-editor/media-modal/gallery/index.jsx create mode 100644 client/post-editor/media-modal/gallery/preview.jsx create mode 100644 client/post-editor/media-modal/gallery/remove-button.jsx create mode 100644 client/post-editor/media-modal/gallery/style.scss create mode 100644 client/post-editor/media-modal/index.jsx create mode 100644 client/post-editor/media-modal/index.scss create mode 100644 client/post-editor/media-modal/markup.js create mode 100644 client/post-editor/media-modal/preload-image.js create mode 100644 client/post-editor/media-modal/secondary-actions.jsx create mode 100644 client/post-editor/media-modal/style.scss create mode 100644 client/post-editor/media-modal/test/index.js create mode 100644 client/post-editor/media-modal/test/specs/index.jsx create mode 100644 client/post-editor/media-modal/test/specs/markup.js create mode 100644 client/post-editor/media-modal/test/specs/preload-image.js create mode 100644 client/post-editor/post-editor.jsx create mode 100644 client/post-editor/restore-post-dialog.jsx create mode 100644 client/post-editor/status-label.jsx create mode 100644 client/post-editor/style.scss create mode 100644 client/post-editor/test/post-editor.jsx create mode 100644 client/reader/README.md create mode 100644 client/reader/_style.scss create mode 100644 client/reader/comments/README.md create mode 100644 client/reader/comments/comment-likes.jsx create mode 100644 client/reader/comments/form.jsx create mode 100644 client/reader/comments/helper.jsx create mode 100644 client/reader/comments/index.jsx create mode 100644 client/reader/comments/style.scss create mode 100644 client/reader/controller.js create mode 100644 client/reader/discover/README.md create mode 100644 client/reader/discover/_style.scss create mode 100644 client/reader/discover/helper.jsx create mode 100644 client/reader/discover/post-attribution.jsx create mode 100644 client/reader/discover/site-attribution.jsx create mode 100644 client/reader/discover/visit-link.jsx create mode 100644 client/reader/feed-error/README.md create mode 100644 client/reader/feed-error/index.jsx create mode 100644 client/reader/feed-header/README.md create mode 100644 client/reader/feed-header/index.jsx create mode 100644 client/reader/feed-header/style.scss create mode 100644 client/reader/feed-stream/README.md create mode 100644 client/reader/feed-stream/empty.jsx create mode 100644 client/reader/feed-stream/index.jsx create mode 100644 client/reader/follow-button/README.md create mode 100644 client/reader/follow-button/index.jsx create mode 100644 client/reader/following-edit/README.md create mode 100644 client/reader/following-edit/helper.jsx create mode 100644 client/reader/following-edit/index.jsx create mode 100644 client/reader/following-edit/list-item.jsx create mode 100644 client/reader/following-edit/navigation.jsx create mode 100644 client/reader/following-edit/notification-settings.jsx create mode 100644 client/reader/following-edit/placeholder.jsx create mode 100644 client/reader/following-edit/sort-controls.jsx create mode 100644 client/reader/following-edit/style.scss create mode 100644 client/reader/following-edit/subscribe-form-result.jsx create mode 100644 client/reader/following-edit/subscribe-form.jsx create mode 100644 client/reader/following-stream/README.md create mode 100644 client/reader/following-stream/_style.scss create mode 100644 client/reader/following-stream/empty.jsx create mode 100644 client/reader/following-stream/index.jsx create mode 100644 client/reader/following-stream/post-blocked.jsx create mode 100644 client/reader/following-stream/post-placeholder.jsx create mode 100644 client/reader/following-stream/post-unavailable.jsx create mode 100644 client/reader/following-stream/post.jsx create mode 100644 client/reader/following-stream/x-post.jsx create mode 100644 client/reader/full-post/README.md create mode 100644 client/reader/full-post/_style.scss create mode 100644 client/reader/full-post/index.jsx create mode 100644 client/reader/index.js create mode 100644 client/reader/like-button/README.md create mode 100644 client/reader/like-button/index.jsx create mode 100644 client/reader/like-helper.jsx create mode 100644 client/reader/liked-stream/README.md create mode 100644 client/reader/liked-stream/empty.jsx create mode 100644 client/reader/liked-stream/index.jsx create mode 100644 client/reader/list-gap/README.md create mode 100644 client/reader/list-gap/_style.scss create mode 100644 client/reader/list-gap/index.jsx create mode 100644 client/reader/list-item/README.md create mode 100644 client/reader/list-item/actions.jsx create mode 100644 client/reader/list-item/description.jsx create mode 100644 client/reader/list-item/icon.jsx create mode 100644 client/reader/list-item/index.jsx create mode 100644 client/reader/list-item/style.scss create mode 100644 client/reader/list-item/title.jsx create mode 100644 client/reader/list-management/README.md create mode 100644 client/reader/list-management/contents/index.jsx create mode 100644 client/reader/list-management/description-edit/index.jsx create mode 100644 client/reader/list-management/followers/index.jsx create mode 100644 client/reader/list-management/navigation/index.jsx create mode 100644 client/reader/list-management/style.scss create mode 100644 client/reader/list-stream/README.md create mode 100644 client/reader/list-stream/empty.jsx create mode 100644 client/reader/list-stream/index.jsx create mode 100644 client/reader/post-byline/README.md create mode 100644 client/reader/post-byline/_style.scss create mode 100644 client/reader/post-byline/index.jsx create mode 100644 client/reader/post-errors/README.md create mode 100644 client/reader/post-errors/index.jsx create mode 100644 client/reader/post-errors/style.scss create mode 100644 client/reader/post-excerpt-link/README.md create mode 100644 client/reader/post-excerpt-link/index.jsx create mode 100644 client/reader/post-excerpt-link/style.scss create mode 100644 client/reader/post-images/README.md create mode 100644 client/reader/post-images/_style.scss create mode 100644 client/reader/post-images/index.jsx create mode 100644 client/reader/post-options/README.md create mode 100644 client/reader/post-options/_style.scss create mode 100644 client/reader/post-options/index.jsx create mode 100644 client/reader/post-permalink/README.md create mode 100644 client/reader/post-permalink/index.jsx create mode 100644 client/reader/post-permalink/style.scss create mode 100644 client/reader/post-time/README.md create mode 100644 client/reader/post-time/index.jsx create mode 100644 client/reader/reading-time/README.md create mode 100644 client/reader/reading-time/index.jsx create mode 100644 client/reader/reading-time/style.scss create mode 100644 client/reader/recommendations/README.md create mode 100644 client/reader/recommendations/for-you/index.jsx create mode 100644 client/reader/recommendations/global-tags/index.jsx create mode 100644 client/reader/recommendations/navigation/index.jsx create mode 100644 client/reader/recommendations/sites/index.jsx create mode 100644 client/reader/recommendations/style.scss create mode 100644 client/reader/share/README.md create mode 100644 client/reader/share/index.jsx create mode 100644 client/reader/share/style.scss create mode 100644 client/reader/sidebar/README.md create mode 100644 client/reader/sidebar/_style.scss create mode 100644 client/reader/sidebar/package.json create mode 100644 client/reader/sidebar/sidebar.jsx create mode 100644 client/reader/site-and-author-icon/README.md create mode 100644 client/reader/site-and-author-icon/_style.scss create mode 100644 client/reader/site-and-author-icon/index.jsx create mode 100644 client/reader/site-link/README.md create mode 100644 client/reader/site-link/index.jsx create mode 100644 client/reader/site-stream/README.md create mode 100644 client/reader/site-stream/empty.jsx create mode 100644 client/reader/site-stream/index.jsx create mode 100644 client/reader/stats.js create mode 100644 client/reader/stream-header/README.md create mode 100644 client/reader/stream-header/index.jsx create mode 100644 client/reader/stream-header/style.scss create mode 100644 client/reader/tag-stream/README.md create mode 100644 client/reader/tag-stream/empty.jsx create mode 100644 client/reader/tag-stream/index.jsx create mode 100644 client/reader/update-notice/README.md create mode 100644 client/reader/update-notice/_style.scss create mode 100644 client/reader/update-notice/index.jsx create mode 100644 client/reader/utils.js create mode 100644 client/reader/xpost-helper.js create mode 100644 client/remove-overlay/index.js create mode 100644 client/sections.js create mode 100644 client/signup/Makefile create mode 100644 client/signup/README.md create mode 100644 client/signup/config/Makefile create mode 100644 client/signup/config/flows.js create mode 100644 client/signup/config/step-components.js create mode 100644 client/signup/config/steps.js create mode 100644 client/signup/config/test/lib/abtest/index.js create mode 100644 client/signup/config/test/lib/signup/step-actions.js create mode 100644 client/signup/config/test/lib/user/index.js create mode 100644 client/signup/config/test/test.js create mode 100644 client/signup/controller.js create mode 100644 client/signup/flow-progress-indicator/index.jsx create mode 100644 client/signup/flow-progress-indicator/style.scss create mode 100644 client/signup/index.js create mode 100644 client/signup/locale-suggestions/index.jsx create mode 100644 client/signup/locale-suggestions/style.scss create mode 100644 client/signup/log-in-form/index.jsx create mode 100644 client/signup/logged-out-form/index.jsx create mode 100644 client/signup/logged-out-form/style.scss create mode 100644 client/signup/main.jsx create mode 100644 client/signup/phone-signup-form/index.jsx create mode 100644 client/signup/phone-signup-form/style.scss create mode 100644 client/signup/previous-step-button/index.jsx create mode 100644 client/signup/previous-step-button/style.scss create mode 100644 client/signup/processing-screen/index.jsx create mode 100644 client/signup/processing-screen/style.scss create mode 100644 client/signup/skip-step-button/index.jsx create mode 100644 client/signup/skip-step-button/style.scss create mode 100644 client/signup/step-header/index.jsx create mode 100644 client/signup/step-header/style.scss create mode 100644 client/signup/step-wrapper/index.jsx create mode 100644 client/signup/steps/domains/index.jsx create mode 100644 client/signup/steps/domains/style.scss create mode 100644 client/signup/steps/dss/index.jsx create mode 100644 client/signup/steps/dss/screenshot.jsx create mode 100644 client/signup/steps/dss/style.scss create mode 100644 client/signup/steps/dss/theme-thumbnail.jsx create mode 100644 client/signup/steps/email-signup-form/index.jsx create mode 100644 client/signup/steps/plans/index.jsx create mode 100644 client/signup/steps/plans/style.scss create mode 100644 client/signup/steps/site-creation/index.jsx create mode 100644 client/signup/steps/site-creation/style.scss create mode 100644 client/signup/steps/test-step/index.jsx create mode 100644 client/signup/steps/theme-selection/index.jsx create mode 100644 client/signup/steps/theme-selection/style.scss create mode 100644 client/signup/steps/theme-selection/theme-thumbnail.jsx create mode 100644 client/signup/style.scss create mode 100644 client/signup/submit-step-button/index.jsx create mode 100644 client/signup/test/flows-test.js create mode 100644 client/signup/test/lib/abtest/index.js create mode 100644 client/signup/test/lib/user/index.js create mode 100644 client/signup/test/signup/config/flows.js create mode 100644 client/signup/test/signup/config/steps.js create mode 100644 client/signup/test/utils-test.js create mode 100644 client/signup/utils.js create mode 100644 client/signup/validation-fieldset/index.jsx create mode 100644 client/signup/validation-fieldset/style.scss create mode 100644 client/signup/wpcom-login-form/index.jsx create mode 100644 client/vip/README.md create mode 100644 client/vip/controller.js create mode 100644 client/vip/index.js create mode 100644 client/vip/style.scss create mode 100644 client/vip/vip-backups/README.md create mode 100644 client/vip/vip-backups/index.jsx create mode 100644 client/vip/vip-billing/README.md create mode 100644 client/vip/vip-billing/index.jsx create mode 100644 client/vip/vip-dashboard/README.md create mode 100644 client/vip/vip-dashboard/index.jsx create mode 100644 client/vip/vip-deploys/README.md create mode 100644 client/vip/vip-deploys/index.jsx create mode 100644 client/vip/vip-logs/README.md create mode 100644 client/vip/vip-logs/index.jsx create mode 100644 client/vip/vip-logs/logs-table.jsx create mode 100644 client/vip/vip-logs/style.scss create mode 100644 client/vip/vip-support/README.md create mode 100644 client/vip/vip-support/index.jsx create mode 100644 config/README.md create mode 100644 config/client.json create mode 100644 config/desktop-mac-app-store.json create mode 100644 config/desktop.json create mode 100644 config/development.json create mode 100644 config/empty-secrets.json create mode 100644 config/horizon.json create mode 100644 config/production.json create mode 100644 config/stage.json create mode 100644 config/wpcalypso.json create mode 100644 docs/code-reviews.md create mode 100644 docs/coding-guidelines.md create mode 100644 docs/coding-guidelines/css.md create mode 100644 docs/coding-guidelines/html.md create mode 100644 docs/coding-guidelines/javascript.md create mode 100644 docs/git-workflow.md create mode 100644 docs/guide/0-values.md create mode 100644 docs/guide/index.md create mode 100644 docs/guide/tech-behind-calypso.md create mode 100644 docs/icons.md create mode 100644 docs/merge-checklist.md create mode 100644 docs/performance.md create mode 100644 docs/react-component-unit-testing.md create mode 100644 docs/reactivity.md create mode 100644 docs/rtl.md create mode 100644 index.js create mode 100644 jsconfig.json create mode 100644 package.json create mode 100644 public/fonts/wpeditor.eot create mode 100644 public/fonts/wpeditor.svg create mode 100644 public/fonts/wpeditor.ttf create mode 100644 public/fonts/wpeditor.woff create mode 100644 public/images/.gitkeep create mode 100644 public/images/authorize/background-1.jpg create mode 100644 public/images/authorize/background-2.jpg create mode 100644 public/images/authorize/background-3.jpg create mode 100644 public/images/authorize/background-4.jpg create mode 100644 public/images/authorize/background-5.jpg create mode 100644 public/images/authorize/background-6.jpg create mode 100644 public/images/comments/illustration_comments.svg create mode 100644 public/images/delete-site/export-content.png create mode 100644 public/images/delete-site/start-over.png create mode 100644 public/images/devices/iframe-back.png create mode 100644 public/images/drake/drake-404.svg create mode 100644 public/images/drake/drake-500.svg create mode 100644 public/images/drake/drake-all-done.svg create mode 100644 public/images/drake/drake-browser.svg create mode 100644 public/images/drake/drake-empty-results.svg create mode 100644 public/images/drake/drake-jetpack.svg create mode 100644 public/images/drake/drake-new.svg create mode 100644 public/images/drake/drake-nomedia.svg create mode 100644 public/images/drake/drake-nomenus.svg create mode 100644 public/images/drake/drake-nosites.svg create mode 100644 public/images/drake/drake-ok.svg create mode 100644 public/images/drake/drake-whoops.svg create mode 100644 public/images/favicons/favicon-development.ico create mode 100644 public/images/favicons/favicon-horizon.ico create mode 100644 public/images/favicons/favicon-staging.ico create mode 100644 public/images/favicons/favicon-wpcalypso.ico create mode 100644 public/images/loading.gif create mode 100644 public/images/me/pattern-dark.png create mode 100644 public/images/pages/illustration-pages.svg create mode 100644 public/images/pages/photolia.jpg create mode 100644 public/images/people/mystery-person.svg create mode 100644 public/images/plans/plan-beginner.svg create mode 100644 public/images/plans/plan-business.svg create mode 100644 public/images/plans/plan-premium.svg create mode 100644 public/images/posts/illustration-posts.svg create mode 100644 public/images/related-posts/cat-blog.png create mode 100644 public/images/related-posts/devices.jpg create mode 100644 public/images/related-posts/mobile-wedding.jpg create mode 100644 public/images/sharing/eventbrite-list.png create mode 100644 public/images/sharing/eventbrite-widget.png create mode 100644 public/images/sharing/facebook-profile.png create mode 100644 public/images/sharing/facebook-sharing.png create mode 100644 public/images/sharing/google-publicize.png create mode 100644 public/images/sharing/google-sharing.png create mode 100644 public/images/sharing/instagram-media.png create mode 100644 public/images/sharing/instagram-widget.png create mode 100644 public/images/sharing/linkedin-publicize.png create mode 100644 public/images/sharing/linkedin-sharing.png create mode 100644 public/images/sharing/path-publicize.png create mode 100644 public/images/sharing/tumblr-publicize.png create mode 100644 public/images/sharing/tumblr-sharing.png create mode 100644 public/images/sharing/twitter-publicize.png create mode 100644 public/images/sharing/twitter-timeline.png create mode 100644 public/images/stats/chart-today.png create mode 100644 public/images/stats/chart.png create mode 100644 public/images/stats/chart2.png create mode 100644 public/images/stats/date-picker.png create mode 100644 public/images/stats/illustration-stats-intro.svg create mode 100644 public/images/stats/illustration-stats.svg create mode 100644 public/images/stats/left-arrow.svg create mode 100644 public/images/stats/map.jpg create mode 100644 public/images/stats/right-arrow.svg create mode 100644 public/images/stats/search-engine.png create mode 100644 public/images/stats/stats-geo-chart.png create mode 100644 public/images/upgrades/cc-amex-disabled.svg create mode 100644 public/images/upgrades/cc-amex.svg create mode 100644 public/images/upgrades/cc-discover-disabled.svg create mode 100644 public/images/upgrades/cc-discover.svg create mode 100644 public/images/upgrades/cc-mastercard-disabled.svg create mode 100644 public/images/upgrades/cc-mastercard.svg create mode 100644 public/images/upgrades/cc-placeholder.svg create mode 100644 public/images/upgrades/cc-visa-disabled.svg create mode 100644 public/images/upgrades/cc-visa.svg create mode 100644 public/images/upgrades/google-apps-logo.png create mode 100644 public/images/upgrades/paypal-disabled.svg create mode 100644 public/images/upgrades/paypal.svg create mode 100644 public/images/upgrades/plugins/ecwid.png create mode 100644 public/images/upgrades/plugins/gumroad.png create mode 100644 public/images/upgrades/plugins/shopify-store.png create mode 100644 public/tinymce/skins/wordpress/images/audio.png create mode 100644 public/tinymce/skins/wordpress/images/dashicon-edit.png create mode 100644 public/tinymce/skins/wordpress/images/dashicon-no.png create mode 100644 public/tinymce/skins/wordpress/images/embedded.png create mode 100644 public/tinymce/skins/wordpress/images/gallery-2x.png create mode 100644 public/tinymce/skins/wordpress/images/gallery.png create mode 100644 public/tinymce/skins/wordpress/images/more-2x.png create mode 100644 public/tinymce/skins/wordpress/images/more.png create mode 100644 public/tinymce/skins/wordpress/images/pagebreak-2x.png create mode 100644 public/tinymce/skins/wordpress/images/pagebreak.png create mode 100644 public/tinymce/skins/wordpress/images/playlist-audio.png create mode 100644 public/tinymce/skins/wordpress/images/playlist-video.png create mode 100644 public/tinymce/skins/wordpress/images/video.png create mode 100644 public/tinymce/skins/wordpress/wp-content.css create mode 100644 server/README.md create mode 100644 server/api/Makefile create mode 100644 server/api/README.md create mode 100644 server/api/index.js create mode 100644 server/api/oauth.js create mode 100644 server/api/test/test.js create mode 100644 server/boot/index.js create mode 100644 server/build/README.md create mode 100644 server/build/index.js create mode 100644 server/bundler/README.md create mode 100644 server/bundler/assets.js create mode 100755 server/bundler/bin/bundler.js create mode 100755 server/bundler/bin/list-assets.js create mode 100644 server/bundler/hot-reloader.js create mode 100644 server/bundler/index.js create mode 100644 server/bundler/loader.js create mode 100644 server/bundler/plugin.js create mode 100644 server/bundler/utils.js create mode 100644 server/config/index.js create mode 100644 server/devdocs/README.md create mode 100755 server/devdocs/bin/generate-devdocs-index create mode 100644 server/devdocs/index.js create mode 100644 server/i18n/Makefile create mode 100644 server/i18n/README.md create mode 100755 server/i18n/bin/i18n-cli.js create mode 100644 server/i18n/index.js create mode 100644 server/i18n/preprocess-xgettextjs-match.js create mode 100644 server/i18n/test/.gitignore create mode 100644 server/i18n/test/examples/i18n-test-example-second-file.jsx create mode 100644 server/i18n/test/examples/i18n-test-examples.jsx create mode 100644 server/i18n/test/test.js create mode 100644 server/i18nlint/Makefile create mode 100644 server/i18nlint/README.md create mode 100755 server/i18nlint/bin/i18nlint-cli.js create mode 100644 server/i18nlint/i18nlint.js create mode 100644 server/i18nlint/test/test-i18nlint.js create mode 100644 server/i18nlint/test/testfiles/concatenation-and-quotes.js create mode 100644 server/i18nlint/test/testfiles/duplicate-placeholders.js create mode 100644 server/i18nlint/test/testfiles/fine.js create mode 100644 server/i18nlint/test/testfiles/hashbang.js create mode 100644 server/i18nlint/test/testfiles/missing-singular-placeholder.js create mode 100644 server/i18nlint/test/testfiles/non-literal-translate-arguments.js create mode 100644 server/i18nlint/test/testfiles/testfile.jsx create mode 100644 server/pages/404.jade create mode 100644 server/pages/500.jade create mode 100644 server/pages/README.md create mode 100644 server/pages/desktop.jade create mode 100644 server/pages/index.jade create mode 100644 server/pages/index.js create mode 100644 server/sanitize/index.js create mode 100644 server/user-bootstrap/index.js create mode 100644 server/user-bootstrap/shared-utils.js create mode 100644 shared/README.md create mode 100644 shared/components/card/README.md create mode 100644 shared/components/card/compact.jsx create mode 100644 shared/components/card/docs/example.jsx create mode 100644 shared/components/card/index.jsx create mode 100644 shared/components/card/style.scss create mode 100644 shared/components/data/screen-title/index.jsx create mode 100644 shared/components/data/store-connection/index.jsx create mode 100644 shared/components/data/themes-list-fetcher/README.md create mode 100644 shared/components/data/themes-list-fetcher/index.jsx create mode 100644 shared/components/empty-content/README.md create mode 100644 shared/components/empty-content/empty-content.jsx create mode 100644 shared/components/empty-content/no-sites-message/README.md create mode 100644 shared/components/empty-content/no-sites-message/index.jsx create mode 100644 shared/components/empty-content/package.json create mode 100644 shared/components/empty-content/style.scss create mode 100644 shared/components/gridicon/README.md create mode 100644 shared/components/gridicon/docs/example.jsx create mode 100644 shared/components/gridicon/index.jsx create mode 100644 shared/components/gridicon/style.scss create mode 100644 shared/components/theme/Makefile create mode 100644 shared/components/theme/README.md create mode 100644 shared/components/theme/docs/example.jsx create mode 100644 shared/components/theme/index.jsx create mode 100644 shared/components/theme/more-button.jsx create mode 100644 shared/components/theme/style.scss create mode 100644 shared/components/theme/test/index.jsx create mode 100644 shared/components/themes-list/Makefile create mode 100644 shared/components/themes-list/README.md create mode 100644 shared/components/themes-list/index.jsx create mode 100644 shared/components/themes-list/style.scss create mode 100644 shared/components/themes-list/test/index.jsx create mode 100644 shared/dispatcher/index.js create mode 100644 shared/lib/formatting/Makefile create mode 100644 shared/lib/formatting/README.md create mode 100644 shared/lib/formatting/decode-entities/browser.js create mode 100644 shared/lib/formatting/decode-entities/node.js create mode 100644 shared/lib/formatting/decode-entities/package.json create mode 100644 shared/lib/formatting/index.js create mode 100644 shared/lib/formatting/test/test.js create mode 100644 shared/lib/i18n-utils/Makefile create mode 100644 shared/lib/i18n-utils/README.md create mode 100644 shared/lib/i18n-utils/browser.js create mode 100644 shared/lib/i18n-utils/node.js create mode 100644 shared/lib/i18n-utils/package.json create mode 100644 shared/lib/i18n-utils/test/utils-test.js create mode 100644 shared/lib/i18n-utils/utils.js create mode 100644 shared/lib/mixins/emitter/index.js create mode 100644 shared/lib/screen-title/README.md create mode 100644 shared/lib/screen-title/actions.js create mode 100644 shared/lib/screen-title/constants.js create mode 100644 shared/lib/screen-title/store.js create mode 100644 shared/lib/screen-title/utils.js create mode 100644 shared/lib/themes/Makefile create mode 100644 shared/lib/themes/README.md create mode 100644 shared/lib/themes/actions.js create mode 100644 shared/lib/themes/constants.js create mode 100644 shared/lib/themes/helpers.js create mode 100644 shared/lib/themes/reducers/current-theme.js create mode 100644 shared/lib/themes/reducers/themes-last-event.js create mode 100644 shared/lib/themes/reducers/themes-last-query.js create mode 100644 shared/lib/themes/reducers/themes-list.js create mode 100644 shared/lib/themes/reducers/themes.js create mode 100644 shared/lib/themes/stores/current-theme.js create mode 100644 shared/lib/themes/stores/themes-last-event.js create mode 100644 shared/lib/themes/stores/themes-last-query.js create mode 100644 shared/lib/themes/stores/themes-list.js create mode 100644 shared/lib/themes/stores/themes.js create mode 100644 shared/lib/themes/test/current-theme-store.js create mode 100644 shared/lib/themes/test/themes-list-store.js create mode 100644 shared/lib/themes/test/themes-store.js create mode 100644 shared/lib/url/index.js create mode 100644 shared/lib/wp/README.md create mode 100644 shared/lib/wp/browser.js create mode 100644 shared/lib/wp/node.js create mode 100644 shared/lib/wp/package.json create mode 100644 shared/lib/wpcom-undocumented/README.md create mode 100644 shared/lib/wpcom-undocumented/index.js create mode 100644 shared/lib/wpcom-undocumented/lib/export.js create mode 100644 shared/lib/wpcom-undocumented/lib/mailing-list.js create mode 100644 shared/lib/wpcom-undocumented/lib/me.js create mode 100644 shared/lib/wpcom-undocumented/lib/site.js create mode 100644 shared/lib/wpcom-undocumented/lib/undocumented.js create mode 100644 shared/my-sites/themes/README.md create mode 100644 shared/my-sites/themes/controller.js create mode 100644 shared/my-sites/themes/current-theme/README.md create mode 100644 shared/my-sites/themes/current-theme/button.jsx create mode 100644 shared/my-sites/themes/current-theme/index.jsx create mode 100644 shared/my-sites/themes/current-theme/style.scss create mode 100644 shared/my-sites/themes/index.js create mode 100644 shared/my-sites/themes/jetpack-manage-disabled-message.jsx create mode 100644 shared/my-sites/themes/jetpack-upgrade-message.jsx create mode 100644 shared/my-sites/themes/main.jsx create mode 100644 shared/my-sites/themes/style.scss create mode 100644 shared/my-sites/themes/thanks-modal.jsx create mode 100644 shared/my-sites/themes/theme-options.js create mode 100644 shared/my-sites/themes/themes-search-card/index.jsx create mode 100644 shared/my-sites/themes/themes-search-card/select-dropdown.jsx create mode 100644 shared/my-sites/themes/themes-search-card/style.scss create mode 100644 shared/my-sites/themes/themes-selection.jsx create mode 100644 shared/my-sites/themes/themes-site-selector-modal.jsx create mode 100644 webpack.config.js create mode 100644 webpack.config.node.js diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000000000..85dcc16df69a98 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +.git +node_modules diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000000..63108ec4c9c4c9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = tab +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.esformatter b/.esformatter new file mode 100644 index 00000000000000..36cc5407a042cd --- /dev/null +++ b/.esformatter @@ -0,0 +1,76 @@ +{ + "root": true, + + "preset": "default", + "indent": { + "value": "\t", + "IfStatementConditional": 2, + "SwitchStatement": 1, + "TopLevelFunctionBlock": 1 + }, + "lineBreak": { + "before": { + "VariableDeclarationWithoutInit": 0, + "ArrayExpressionClosing": 1 + }, + "after": { + "AssignmentOperator": -1, + "ArrayExpressionOpening": 1, + "ArrayExpressionComma": 1 + } + }, + "whiteSpace": { + "before": { + "ArgumentList": 1, + "ArgumentListArrayExpression": 1, + "ArgumentListFunctionExpression": 1, + "ArgumentListObjectExpression": 1, + "ArrayExpressionClosing": 1, + "ExpressionClosingParentheses": 1, + "ForInStatementExpressionClosing": 1, + "ForStatementExpressionClosing": 1, + "IfStatementConditionalClosing": 1, + "MemberExpressionClosing": 1, + "ParameterList": 1, + "SwitchDiscriminantClosing": 1, + "WhileStatementConditionalClosing": 1, + "CallExpression": -1 + }, + "after": { + "ArgumentList": 1, + "ArgumentListArrayExpression": 1, + "ArgumentListFunctionExpression": 1, + "ArgumentListObjectExpression": 1, + "ArrayExpressionOpening": 1, + "ExpressionOpeningParentheses": 1, + "ForInStatementExpressionOpening": 1, + "ForStatementExpressionOpening": 1, + "IfStatementConditionalOpening": 1, + "MemberExpressionOpening": 1, + "ParameterList": 1, + "SwitchDiscriminantOpening": 1, + "WhileStatementConditionalOpening": 1, + "CallExpression": 0 + } + }, + "collapseObjects": { + "ObjectExpression": { + "maxLineLength": 120, + "maxKeys": 1, + "forbidden": [ "FunctionExpression" ] + }, + "ArrayExpression": { + "maxLineLength": 120, + "maxKeys": 10, + "forbidden": [ "FunctionExpression" ] + } + }, + "plugins": [ + "esformatter-quotes", + "esformatter-semicolons", + "esformatter-braces", + "esformatter-dot-notation", + "esformatter-special-bangs", + "esformatter-collapse-objects-a8c" + ] +} diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000000000..c6136853bc84eb --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +server/devdocs/search-index.js +client/components/tinymce/plugins/wptextpattern/plugin.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000000000..acb3fe6bc903c0 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,83 @@ +{ + "parser": "babel-eslint", + "env": { + "browser": true, + "es6": true, + "mocha": true, + "node": true + }, + "ecmaFeatures": { + "jsx": true, + "modules": true + }, + "plugins": [ + "eslint-plugin-react" + ], + "rules": { + "brace-style": [ 1, "1tbs" ], + // REST API objects include underscores + "camelcase": 0, + "comma-dangle": 0, + "comma-spacing": 1, + // Allows returning early as undefined + "consistent-return": 0, + "dot-notation": 1, + "eqeqeq": [ 2, "allow-null" ], + "eol-last": 1, + "indent": [ 1, "tab", { "SwitchCase": 1 } ], + "key-spacing": 1, + // Most common is "Emitter", should be improved + "new-cap": 1, + "no-cond-assign": 2, + "no-else-return": 1, + "no-empty": 1, + // Flux stores use switch case fallthrough + "no-fallthrough": 0, + "no-lonely-if": 1, + "no-mixed-requires": 0, + "no-mixed-spaces-and-tabs": 1, + "no-multiple-empty-lines": [ 1, { max: 1 } ], + "no-multi-spaces": 1, + "no-nested-ternary": 1, + "no-new": 1, + "no-process-exit": 1, + "no-shadow": 1, + "no-spaced-func": 1, + "no-trailing-spaces": 1, + "no-undef": 1, + "no-underscore-dangle": 0, + // Allows Chai `expect` expressions + "no-unused-expressions": 0, + "no-unused-vars": 1, + // Teach eslint about React+JSX + "react/jsx-uses-react": 1, + "react/jsx-uses-vars": 1, + // Allows function use before declaration + "no-use-before-define": [ 2, "nofunc" ], + // We split external, internal, module variables + "one-var": 0, + "operator-linebreak": [ 1, "after", { "overrides": { + "?": "before", + ":": "before" + } } ], + "padded-blocks": [ 1, "never" ], + "quote-props": [ 1, "as-needed" ], + "quotes": [ 1, "single", "avoid-escape" ], + "semi-spacing": 1, + "space-after-keywords": [ 1, "always" ], + "space-before-blocks": [ 1, "always" ], + "space-before-function-paren": [ 1, "never" ], + // Our array literal index exception violates this rule + "space-in-brackets": 0, + "space-in-parens": [ 1, "always" ], + "space-infix-ops": [ 1, { "int32Hint": false } ], + // Ideal for "!" but not for "++" + "space-unary-ops": 0, + // Assumed by default with Babel + "strict": [ 2, "never" ], + "valid-jsdoc": [ 1, { "requireReturn": false } ], + // Common top-of-file requires, expressions between external, interal + "vars-on-top": 1, + "yoda": 0 + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000000..e137661def55d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +.sass-cache +.vagrant +.unison +.env +.DS_Store +.idea +*.iml +*.iws +tags +node_modules +/npm-debug.log* +*.sw? +!*.swf + +# script used during docker build that is specific to the environment +env-config.sh + +# added during build +/config/secrets.json + +/build + +/public/*.js +/public/style*.css +/public/style*.css.map +/public/editor*.css +/server/devdocs/search-index.js +/server/bundler/assets-*.json + +*.rdb +*.db + +/calypso-strings.php +cover.html +.test.log diff --git a/.jsfmtrc b/.jsfmtrc new file mode 100644 index 00000000000000..2b43ca2e0547b5 --- /dev/null +++ b/.jsfmtrc @@ -0,0 +1,75 @@ +{ + "preset": "default", + "indent": { + "value": "\t", + "IfStatementConditional": 2, + "SwitchStatement": 1, + "TopLevelFunctionBlock": 1 + }, + "lineBreak": { + "before": { + "VariableDeclarationWithoutInit": 0, + "ArrayExpressionClosing": 1 + }, + "after": { + "AssignmentOperator": -1, + "ArrayExpressionOpening": 1, + "ArrayExpressionComma": 1 + } + }, + "whiteSpace": { + "before": { + "ArgumentList": 1, + "ArgumentListArrayExpression": 1, + "ArgumentListFunctionExpression": 1, + "ArgumentListObjectExpression": 1, + "ArrayExpressionClosing": 1, + "ExpressionClosingParentheses": 1, + "ForInStatementExpressionClosing": 1, + "ForStatementExpressionClosing": 1, + "IfStatementConditionalClosing": 1, + "MemberExpressionClosing": 1, + "ParameterList": 1, + "SwitchDiscriminantClosing": 1, + "WhileStatementConditionalClosing": 1, + "CallExpression": -1 + }, + "after": { + "ArgumentList": 1, + "ArgumentListArrayExpression": 1, + "ArgumentListFunctionExpression": 1, + "ArgumentListObjectExpression": 1, + "ArrayExpressionOpening": 1, + "ExpressionOpeningParentheses": 1, + "ForInStatementExpressionOpening": 1, + "ForStatementExpressionOpening": 1, + "IfStatementConditionalOpening": 1, + "MemberExpressionOpening": 1, + "ParameterList": 1, + "SwitchDiscriminantOpening": 1, + "WhileStatementConditionalOpening": 1, + "CallExpression": 0 + } + }, + "collapseObjects": { + "ObjectExpression": { + "maxLineLength": 120, + "maxKeys": 1, + "forbidden": [ "FunctionExpression" ] + }, + "ArrayExpression": { + "maxLineLength": 120, + "maxKeys": 10, + "forbidden": [ "FunctionExpression" ] + } + }, + "plugins": [ + "esformatter-quotes", + "esformatter-semicolons", + "esformatter-braces", + "esformatter-dot-notation", + "esformatter-special-bangs", + "esformatter-jsx-ignore", + "esformatter-collapse-objects-a8c" + ] +} diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000000000..7306b7e1427939 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +save-exact = true + diff --git a/.rtlcssrc b/.rtlcssrc new file mode 100644 index 00000000000000..d1411f1a17ea3e --- /dev/null +++ b/.rtlcssrc @@ -0,0 +1,10 @@ +{ + "options": { + "preserveComments": true, + "preserveDirectives": false, + "swapLeftRightInUrl": true, + "swapLtrRtlInUrl": true, + "swapWestEastInUrl": false, + "autoRename": false + } +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000000000..7b531fe75a42d1 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,70 @@ +Contributing to Calypso +======================= + +Calypso is Open Source software licensed under [GNU General Public License v2 (or later)](./LICENSE.md). + +-------- + +We want to help you start off on the right foot when working with Calypso, reading this is a great first step. + +**The most important things to know when starting out are:** + +1. All code written for Calypso goes through a peer code review process before it is merged to master. +2. The workflows for Calypso are different than what you're used to at Automattic, it will take time to adjust. +3. We are all in this together, building a great WordPress powered experience. We're here to help you along the way. +4. Good judgement trumps all. + +If you can keep those in mind during your first couple of months working with Calypso, you're going to do great. Don't stop reading here though, there's some more important details for each of the above points. + +The peer code review process +---------------------------- + +Code reviews are an important part of the Calypso workflow. They help to keep code quality consistent, and they help every person working on Calypso improve over time. We want to make you the best Calypso contributor you can be. + +Every PR should be reviewed and approved by someone other than the author. Fresh eyes can find problems that can hide in the open if you've been working on the code for a while. + +This is one of the primary reasons PRs should be kept small and pushed often (more about that below). We can help you with decisions, make suggestions, and help guide your feature *as you're building it.* + +*Everyone* is encouraged to review PRs and add feedback and ask questions, even people who are new to calypso. Also, don't just review PRs from your own team. Reading other people's code is a great way to learn new techniques, and seeing code outside of your own feature helps you to see patterns across the project. It's also helpful to see the feedback other contributors are getting on their PRs. + +The final thumbs-up and **[Status] Ready to Merge** should come from a Calypso contributor that has authored and reviewed a number of merged PRs if the change is substantial. + +[A positive mindset towards code reviews](https://medium.com/medium-eng/the-code-review-mindset-3280a4af0a89) is really important. We're building something together that is greater than the sum of its parts, everyone should feel ownership of code going into Calypso and want to make it the best it can be. + +If you feel yourself waiting for someone to review a PR, don't hesitate to ask for someone to review on Slack or to ping someone directly via a Github mention. _The PR author is responsible for pushing the change through._ + +The Calypso Workflow +-------------------- + +When you're first starting out, your natural instinct when creating a new feature will be to create a local feature branch, and start building away. If you start doing this, *stop*, take your hands off the keyboard, grab a coffee and read on. :) + +**It's important to break your feature down into small pieces first**, each piece should become its own pull request. Even if after finishing the first piece your feature isn't functional, that is okay, we love merging unfinished code early and often. You can place your feature behind a [feature-check](config/README.md#feature-flags) to make sure it's not exposed until all pieces are completed. It's also a good idea to read up on [the CSS/SASS coding guidelines](docs/coding-guidelines/css.md), to ensure form and syntax is consistent. + +Once you know what the first small piece of your feature will be, follow this general process while working: + +1. Create a new branch, use the [proper naming](docs/git-workflow.md#branch-naming-scheme), _e.g._ `add/video-preview` or `fix/1337-language-too-geeky` +2. Make your first commit: any will do even if empty or trivial, but we need something in order to create the initial pull request. Create the pull request and prefix the name with the section of the product, _e.g._ _Posts: Prepare store for desktop app_. + - Write a detailed description of the problem you are solving, the part of Calypso it affects, and how you plan on going about solving it. + - Add the **[Status] In Progress** label. This indicates that the pull request isn't ready for final review and may still be incomplete. On the other hand, it welcomes early feedback and encourages collaboration during the development process. +3. Start developing and pushing out commits to your new branch. + - Push your changes out frequently and try to avoid getting yourself stuck in a long-running branch or a merge nightmare. When your local work diverges enough from the master branch it can be hard to review and hard to reconcile conflicts. + - Follow the [merge checklist](docs/merge-checklist.md) before pushing. This ensures that your code follows the style guidelines and doesn't accidentally introduce any errors or regressions. + - Note that you can automate some of these tasks by setting up [githooks](docs/coding-guidelines/javascript.md#setting-up-githooks) and they will run whenever you `git commit`. + - Don’t be afraid to change, [squash](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html), and rearrange commits or to force push - `git push -f origin fix/something-broken`. Keep in mind, however, that if other people are working on the same branch then you can mess up their history. You are perfectly safe if you are the only one pushing commits to that branch. + - Do proactively squash minor commits such as typo fixes or [fixes to previous commits](http://fle.github.io/git-tip-keep-your-branch-clean-with-fixup-and-autosquash.html) in the pull request. +4. If you end up needing more than a few commits, consider splitting the pull request into separate components. Discuss in the new pull request and in the comments why the branch was broken apart and any changes that may have taken place that necessitated the split. Our goal is to catch early in the review process those pull requests that attempt to do too much. +5. When you feel that you are ready for a formal review or for merging into `master` make sure you check this list and our [merge checklist](docs/merge-checklist.md). + - Make sure your branch merges cleanly and consider rebasing against `master` to keep the branch history short and clean. + - If there are visual changes, add before and after screenshots in the pull request comments. + - Add unit tests, or at a minimum, provide helpful instructions for the reviewer so he or she can test your changes. This will help speed up the review process. + - Ensure that your commit messages are [meaningful](http://robots.thoughtbot.com/5-useful-tips-for-a-better-commit-message). +6. Remove the **[Status] In Progress** label from the pull request and add the **[Status] Needs Review** label - someone will provide feedback on the latest unreviewed changes. The reviewer will also mark the pull request as **[Status] Awaiting Fixes** if he or she thinks changes are needed. +7. If you get a , , , , or a LGTM and the status has been changed to **[Status] Ready to Merge**, merge the changes into `master`. + +> Reviewing can be a time-consuming process if only handled by a few developers. Why not skim the list of open pull requests while waiting and review someone else's work in the meantime? Everyone is welcome to add comments at any level, from basic programming style to advanced Calypso ways and means. You may not feel comfortable signing off on someone else's work, but they reviewing you are more-fully joining the project and helping to share the load. **We're all in this together**. + + +We're here to help along the way +-------------------------------- + +Don't be afraid to ask for help at any point. We want your first experience with Calypso to be a good one, so don't be shy. If you're wondering why something is the way it is, or how a decision was made, you can tag issues with **[Type] Question**. diff --git a/CREDITS.md b/CREDITS.md new file mode 100644 index 00000000000000..1622aed96e7064 --- /dev/null +++ b/CREDITS.md @@ -0,0 +1,1174 @@ +Credits +======= + +This project makes use of Open Source components. Below is a list of these components included in this project's source code, and their license information. This project also uses NPM packages, released under open licenses by NPM, see [package.json](/package.json). Source code and license information for each of these packages is available at https://npmjs.org. Many thanks to all of the original authors! + +### https://github.com/thoughtbot/bourbon +#### assets/stylesheets/shared/\_functions.scss +```text +The MIT License (MIT) + +Copyright © 2011–2015 thoughtbot, inc. + +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. +``` +### https://github.com/facebook/react +#### client/components/single-child-css-transition-group +```text +BSD License + +For React software + +Copyright (c) 2013-2015, Facebook, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE +``` + +### https://github.com/WordPress/WordPress +#### client/components/tinymce/plugins/wpcom +#### client/components/tinymce/plugins/wpcom-autoresize +#### client/components/tinymce/plugins/wpcom-view +#### client/components/tinymce/plugins/wpeditimage +#### client/components/tinymce/plugins/wplink +#### client/components/tinymce/plugins/wptextpattern +#### client/lib/media/constants.js +#### client/post-editor/media-modal/markup.js +#### shared/lib/formatting/index.js +```text +WordPress - Web publishing software + +Copyright 2015 by the contributors + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +This program incorporates work covered by the following copyright and +permission notices: + + b2 is (c) 2001, 2002 Michel Valdrighi - m@tidakada.com - + http://tidakada.com + + Wherever third party code has been used, credit has been given in the code's + comments. + + b2 is released under the GPL + +and + + WordPress - Web publishing software + + Copyright 2003-2010 by the contributors + + WordPress is released under the GPL + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + +WRITTEN OFFER + +The source code for any program binaries or compressed scripts that are +included with WordPress can be freely obtained at the following URL: + + https://wordpress.org/download/source/ + +### https://github.com/tinymce/tinymce +#### client/components/tinymce/plugins/wpcom-charmap + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! +``` + +### https://github.com/slevithan/xregexp +#### client/lib/embeds/list-store.js +```text +The MIT License + +Copyright (c) 2007-2015 Steven Levithan + +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. +``` + +### https://github.com/kvz/phpjs/ +#### client/lib/version-compare +#### client/lib/mixins/i18n/number-format.js +```text +Copyright (c) 2013 Kevin van Zonneveld (http://kvz.io) +and Contributors (http://phpjs.org/authors) + +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. +``` + +### https://github.com/redsunsoft/react-render-visualizer +#### client/lib/mixins/render-visualizer +```text +The MIT License (MIT) + +Copyright (c) 2015 Tony + +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. +``` + +### https://github.com/Modernizr/Modernizr +#### client/lib/touch-detect/index.js +```text + +Modernizr is available under the MIT license: + +MIT License +Copyright © 2009-2015 +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. +``` + +### https://github.com/strongloop/express +#### server/devdocs/bin/generate-devdocs-index +```text + +(The MIT License) + +Copyright (c) 2009-2014 TJ Holowaychuk +Copyright (c) 2013-2014 Roman Shtylman +Copyright (c) 2014-2015 Douglas Christopher Wilson + +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. +``` + +### https://github.com/sindresorhus/escape-string-regexp +#### server/devdocs/index.js +```text + +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +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. +``` + +### https://github.com/alexei/sprintf.js +#### server/i18nlint/i18nlint.js +```text + +Copyright (c) 2007-2014, Alexandru Marasteanu +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of this software nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +``` + +### https://github.com/SalesforceEng/secure-filters +#### server/sanitize/index.js +```text + +Copyright (c) 2013, GoInstant Inc., a salesforce.com company +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the name of salesforce.com, nor GoInstant, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +``` + +### Olark +#### assets/stylesheets/shared/\_livechat.scss +#### client/lib/olark-api +```text +Copyright © 2013 Habla, Inc. Habla Inc. (dba Olark) + +Permission kindly granted by Ben Congleton, of Olark. +``` diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000000000..ad985389cbdd83 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,39 @@ +FROM debian:wheezy + +MAINTAINER Automattic + +WORKDIR /calypso + +RUN mkdir -p /tmp +COPY ./env-config.sh /tmp/ +RUN bash /tmp/env-config.sh +RUN apt-get -y update && apt-get -y install \ + wget \ + git \ + python \ + make \ + build-essential +RUN wget http://nodejs.org/dist/v0.12.6/node-v0.12.6-linux-x64.tar.gz && \ + tar -zxf node-v0.12.6-linux-x64.tar.gz -C /usr/local && \ + ln -sf node-v0.12.6-linux-x64 /usr/local/node && \ + ln -sf /usr/local/node/bin/npm /usr/local/bin/ && \ + ln -sf /usr/local/node/bin/node /usr/local/bin/ && \ + rm node-v0.12.6-linux-x64.tar.gz + +ENV NODE_PATH /calypso/server:/calypso/shared + +# Install base npm packages to take advantage of the docker cache +COPY ./package.json /calypso/package.json +RUN npm install --production + +COPY . /calypso + +# Build javascript bundles for each environment and change ownership +RUN CALYPSO_ENV=wpcalypso make build-wpcalypso && \ + CALYPSO_ENV=horizon make build-horizon && \ + CALYPSO_ENV=stage make build-stage && \ + CALYPSO_ENV=production make build-production && \ + chown -R nobody /calypso + +USER nobody +CMD NODE_ENV=production node build/bundle-$CALYPSO_ENV.js diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000000000..096a2b4f26c5eb --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,264 @@ +The GNU General Public License, Version 2, June 1991 (GPLv2) +============================================================ + +> Copyright (C) 1989, 1991 Free Software Foundation, Inc. +> 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + + +Preamble +-------- + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public License is intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to most +of the Free Software Foundation's software and to any other program whose +authors commit to using it. (Some other Free Software Foundation software is +covered by the GNU Library General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom to +distribute copies of free software (and charge for this service if you wish), +that you receive source code or can get it if you want it, that you can change +the software or use pieces of it in new free programs; and that you know you can +do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny +you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a +fee, you must give the recipients all the rights that you have. You must make +sure that they, too, receive or can get the source code. And you must show them +these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer +you this license which gives you legal permission to copy, distribute and/or +modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients to +know that what they have is not the original, so that any problems introduced by +others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish +to avoid the danger that redistributors of a free program will individually +obtain patent licenses, in effect making the program proprietary. To prevent +this, we have made it clear that any patent must be licensed for everyone's free +use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification +follow. + + +Terms And Conditions For Copying, Distribution And Modification +--------------------------------------------------------------- + +**0.** This License applies to any program or other work which contains a notice +placed by the copyright holder saying it may be distributed under the terms of +this General Public License. The "Program", below, refers to any such program or +work, and a "work based on the Program" means either the Program or any +derivative work under copyright law: that is to say, a work containing the +Program or a portion of it, either verbatim or with modifications and/or +translated into another language. (Hereinafter, translation is included without +limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by +this License; they are outside its scope. The act of running the Program is not +restricted, and the output from the Program is covered only if its contents +constitute a work based on the Program (independent of having been made by +running the Program). Whether that is true depends on what the Program does. + +**1.** You may copy and distribute verbatim copies of the Program's source code +as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this License +and to the absence of any warranty; and give any other recipients of the Program +a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at +your option offer warranty protection in exchange for a fee. + +**2.** You may modify your copy or copies of the Program or any portion of it, +thus forming a work based on the Program, and copy and distribute such +modifications or work under the terms of Section 1 above, provided that you also +meet all of these conditions: + +* **a)** You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change. + +* **b)** You must cause any work that you distribute or publish, that in whole + or in part contains or is derived from the Program or any part thereof, to + be licensed as a whole at no charge to all third parties under the terms of + this License. + +* **c)** If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use in the + most ordinary way, to print or display an announcement including an + appropriate copyright notice and a notice that there is no warranty (or + else, saying that you provide a warranty) and that users may redistribute + the program under these conditions, and telling the user how to view a copy + of this License. (Exception: if the Program itself is interactive but does + not normally print such an announcement, your work based on the Program is + not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Program, and can be reasonably +considered independent and separate works in themselves, then this License, and +its terms, do not apply to those sections when you distribute them as separate +works. But when you distribute the same sections as part of a whole which is a +work based on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the entire whole, +and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise the +right to control the distribution of derivative or collective works based on the +Program. + +In addition, mere aggregation of another work not based on the Program with the +Program (or with a work based on the Program) on a volume of a storage or +distribution medium does not bring the other work under the scope of this +License. + +**3.** You may copy and distribute the Program (or a work based on it, under +Section 2) in object code or executable form under the terms of Sections 1 and 2 +above provided that you also do one of the following: + +* **a)** Accompany it with the complete corresponding machine-readable source + code, which must be distributed under the terms of Sections 1 and 2 above on + a medium customarily used for software interchange; or, + +* **b)** Accompany it with a written offer, valid for at least three years, to + give any third party, for a charge no more than your cost of physically + performing source distribution, a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of Sections 1 + and 2 above on a medium customarily used for software interchange; or, + +* **c)** Accompany it with the information you received as to the offer to + distribute corresponding source code. (This alternative is allowed only for + noncommercial distribution and only if you received the program in object + code or executable form with such an offer, in accord with Subsection b + above.) + +The source code for a work means the preferred form of the work for making +modifications to it. For an executable work, complete source code means all the +source code for all modules it contains, plus any associated interface +definition files, plus the scripts used to control compilation and installation +of the executable. However, as a special exception, the source code distributed +need not include anything that is normally distributed (in either source or +binary form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component itself +accompanies the executable. + +If distribution of executable or object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the source code +from the same place counts as distribution of the source code, even though third +parties are not compelled to copy the source along with the object code. + +**4.** You may not copy, modify, sublicense, or distribute the Program except as +expressly provided under this License. Any attempt otherwise to copy, modify, +sublicense or distribute the Program is void, and will automatically terminate +your rights under this License. However, parties who have received copies, or +rights, from you under this License will not have their licenses terminated so +long as such parties remain in full compliance. + +**5.** You are not required to accept this License, since you have not signed +it. However, nothing else grants you permission to modify or distribute the +Program or its derivative works. These actions are prohibited by law if you do +not accept this License. Therefore, by modifying or distributing the Program (or +any work based on the Program), you indicate your acceptance of this License to +do so, and all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +**6.** Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these terms and +conditions. You may not impose any further restrictions on the recipients' +exercise of the rights granted herein. You are not responsible for enforcing +compliance by third parties to this License. + +**7.** If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), conditions +are imposed on you (whether by court order, agreement or otherwise) that +contradict the conditions of this License, they do not excuse you from the +conditions of this License. If you cannot distribute so as to satisfy +simultaneously your obligations under this License and any other pertinent +obligations, then as a consequence you may not distribute the Program at all. +For example, if a patent license would not permit royalty-free redistribution of +the Program by all those who receive copies directly or indirectly through you, +then the only way you could satisfy both it and this License would be to refrain +entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply and the +section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or +other property right claims or to contest validity of any such claims; this +section has the sole purpose of protecting the integrity of the free software +distribution system, which is implemented by public license practices. Many +people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing to +distribute software through any other system and a licensee cannot impose that +choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +**8.** If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original copyright +holder who places the Program under this License may add an explicit +geographical distribution limitation excluding those countries, so that +distribution is permitted only in or among countries not thus excluded. In such +case, this License incorporates the limitation as if written in the body of this +License. + +**9.** The Free Software Foundation may publish revised and/or new versions of +the General Public License from time to time. Such new versions will be similar +in spirit to the present version, but may differ in detail to address new +problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies +a version number of this License which applies to it and "any later version", +you have the option of following the terms and conditions either of that version +or of any later version published by the Free Software Foundation. If the +Program does not specify a version number of this License, you may choose any +version ever published by the Free Software Foundation. + +**10.** If you wish to incorporate parts of the Program into other free programs +whose distribution conditions are different, write to the author to ask for +permission. For software which is copyrighted by the Free Software Foundation, +write to the Free Software Foundation; we sometimes make exceptions for this. +Our decision will be guided by the two goals of preserving the free status of +all derivatives of our free software and of promoting the sharing and reuse of +software generally. + + +No Warranty +----------- + +**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM +"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA +BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER +OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 00000000000000..a35ffe5b316718 --- /dev/null +++ b/Makefile @@ -0,0 +1,152 @@ +# get Makefile directory name: http://stackoverflow.com/a/5982798/376773 +THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) +THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd) + +empty:= +space:=$(empty) $(empty) +THIS_DIR:= $(subst $(space),\$(space),$(THIS_DIR)) + +# BIN +BIN := $(THIS_DIR)/bin + +# NODE BIN folder +NODE_BIN := $(THIS_DIR)/node_modules/.bin + +# applications +NODE ?= node +NPM ?= $(NODE) $(shell which npm) +BUNDLER ?= $(BIN)/bundler +SASS ?= $(NODE_BIN)/node-sass --include-path 'client:shared' +RTLCSS ?= $(NODE_BIN)/rtlcss +AUTOPREFIXER ?= $(NODE_BIN)/autoprefixer +RECORD_ENV ?= $(BIN)/record-env +GET_I18N ?= $(BIN)/get-i18n +I18NLINT ?= $(BIN)/i18nlint +LIST_ASSETS ?= $(BIN)/list-assets +ALL_DEVDOCS_JS ?= $(THIS_DIR)/server/devdocs/bin/generate-devdocs-index + +# files used as prereqs +SASS_FILES := $(shell find client assets -type f -name '*.scss') +JS_FILES := $(shell find . -type f \( -name '*.js' -or -name '*.jsx' \) -and -not \( -path './node_modules/*' -or -path './public/*' \) ) +MD_FILES := $(shell find . -name '*.md' -and -not -path '*node_modules*' -and -not -path '*.git*' | sed 's/ /\\ /g') +CLIENT_CONFIG_FILE := client/config/index.js + +# variables +NODE_ENV ?= development +CALYPSO_ENV ?= $(NODE_ENV) + +export NODE_ENV := $(NODE_ENV) +export CALYPSO_ENV := $(CALYPSO_ENV) +export NODE_PATH := server:shared:$(THIS_DIR) + +.DEFAULT_GOAL := install + +install: node_modules + +# Simply running `make run` will spawn the Node.js server instance. +run: install build + @$(NODE) build/bundle-$(CALYPSO_ENV).js + +# a helper rule to ensure that a specific module is installed, +# without relying on a generic `npm install` command +node_modules/%: + @$(NPM) install $(notdir $@) + +# ensures that the `node_modules` directory is installed and up-to-date with +# the dependencies listed in the "package.json" file. +node_modules: package.json + @$(NPM) prune + @$(NPM) install + @touch node_modules + +# run `make test` in all discovered Makefiles +test: build + @$(BIN)/run-all-tests + +lint: node_modules/eslint node_modules/eslint-plugin-react node_modules/babel-eslint + @$(NODE_BIN)/eslint --quiet $(JS_FILES) + +eslint: lint + +eslint-branch: node_modules/eslint node_modules/eslint-plugin-react node_modules/babel-eslint + @git diff --name-only $$(git merge-base $$(git rev-parse --abbrev-ref HEAD) master)..HEAD | grep '\.jsx\?$$' | xargs $(NODE_BIN)/eslint + +# Skip test directories (with the sed regex) for i18nlint in lieu of proper +# ignore functionality +i18n-lint: + @echo "$(JS_FILES)" | sed 's/\([^ ]*\/test\/[^ ]* *\)//g' | xargs -n1 $(I18NLINT) + +# keep track of the current CALYPSO_ENV so that it can be used as a +# prerequisite for other rules +.env: FORCE + @$(RECORD_ENV) $@ + +# generate the client-side `config` js file +$(CLIENT_CONFIG_FILE): .env config/$(CALYPSO_ENV).json config/client.json client/config/regenerate.js + @$(NODE) client/config/regenerate.js > $@ + +public/style.css: node_modules $(SASS_FILES) + @$(SASS) assets/stylesheets/style.scss $@ + @$(AUTOPREFIXER) $@ + +public/style-debug.css: node_modules $(SASS_FILES) + @$(SASS) --source-map "$(@D)/style-debug.css.map" assets/stylesheets/style.scss $@ + @$(AUTOPREFIXER) $@ + +public/style-rtl.css: public/style.css + @$(RTLCSS) $(THIS_DIR)/public/style.css $@ + +public/editor.css: node_modules $(SASS_FILES) + @$(SASS) assets/stylesheets/editor.scss $@ + @$(AUTOPREFIXER) $@ + +server/devdocs/search-index.js: $(MD_FILES) $(ALL_DEVDOCS_JS) + @$(ALL_DEVDOCS_JS) $(MD_FILES) + +build-server: install + @mkdir -p build + @CALYPSO_ENV=$(CALYPSO_ENV) $(NODE_BIN)/webpack --display-error-details --config webpack.config.node.js + +build: install build-$(CALYPSO_ENV) + +build-css: public/style.css public/style-rtl.css public/style-debug.css public/editor.css + +build-development: build-server $(CLIENT_CONFIG_FILE) server/devdocs/search-index.js build-css + +build-wpcalypso: build-server $(CLIENT_CONFIG_FILE) server/devdocs/search-index.js build-css + @$(BUNDLER) + +build-desktop build-desktop-mac-app-store build-horizon build-stage build-production: build-server $(CLIENT_CONFIG_FILE) build-css + @$(BUNDLER) + +# the `clean` rule deletes all the files created from `make build`, but not +# those created by `make install` +clean: + @rm -rf public/style*.css public/style-debug.css.map public/*.js $(CLIENT_CONFIG_FILE) server/devdocs/search-index.js public/editor.css build/* server/bundler/*.json + +# the `distclean` rule deletes all the files created from `make install` +distclean: + @rm -rf node_modules + +# create list of translations, saved as `./calypso-strings.php` +translate: node_modules $(CLIENT_CONFIG_FILE) + @CALYPSO_ENV=stage $(BUNDLER) + @CALYPSO_ENV=stage $(LIST_ASSETS) | xargs $(GET_I18N) ./calypso-strings.php calypso_i18n_strings + +# install all git hooks +githooks: githooks-commit githooks-push + +# install git pre-commit hook +githooks-commit: + @if [ ! -e .git/hooks/pre-commit ]; then ln -s ../../bin/pre-commit .git/hooks/pre-commit; fi + +# install git pre-push hook +githooks-push: + @if [ ! -e .git/hooks/pre-push ]; then ln -s ../../bin/pre-push .git/hooks/pre-push; fi + +# rule that can be used as a prerequisite for other rules to force them to always run +FORCE: + +.PHONY: build build-development build-server +.PHONY: run install test clean distclean translate route +.PHONY: githooks githooks-commit githooks-push diff --git a/README.md b/README.md new file mode 100644 index 00000000000000..71e37ab8e12605 --- /dev/null +++ b/README.md @@ -0,0 +1,161 @@ +Calypso +======= + +Calypso is a web application that allows users to manage all of their WordPress blogs in one place. Calypso is Open Source software licensed under [GNU General Public License v2 (or later)](./LICENSE.md). + +Making Changes +-------------- + +Our workflow is different — before jumping in and writing thousands of lines of code, you should read the [Contributing to Calypso](CONTRIBUTING.md) document. It describes the process that we're using. Understanding and following that procedure will save you a bunch of pain down the road. :grinning: + +Getting Started +--------------- + +1. Check the prerequisites are installed (Git, Node, NPM). See below for more details. +2. Clone this repository locally. +3. Add `127.0.0.1 calypso.localhost` to your local hosts file. +4. With the command line open at the repository root, execute `make run`. See below for more details. +5. Open `calypso.localhost:3000` in your browser. + +### Prerequisites + +To be able to clone and run the application you need: + +- [Node.js](http://nodejs.org/) and [NPM](https://www.npmjs.com/) installed. Here's a [handy installer](https://nodejs.org/dist/latest/) for Windows, Mac, and Linux. +- [Git](http://git-scm.com/). Try the `git` command from your terminal, if it's not found then use this [installer](http://git-scm.com/download/). +- The repository also uses `make` to orchestrate compiling the JavaScript, running the server, and several other tasks. + +### Installing and Running + +Clone this git repo to your machine via the terminal using the `git clone` command and then run `make` from the root calypso directory: + +```bash +$ git clone git@github.com:Automattic/calypso-pre-oss.git +$ cd calypso-pre-oss +$ make run +``` + +The `make run` command will install any node dependencies and start the application. When changes are made to either the JavaScript files or the Sass stylesheets, the build process will run when making a request to the application via the browser. The build process compiles both the JavaScript and CSS to make sure that you have the latest versions of both. + +To run Calypso locally, you'll need to add `127.0.0.1 calypso.localhost` to your hosts file, and load the app at http://calypso.localhost:3000 instead of localhost. This is necessary because only certain origins are allowed to make use of the REST API via the iframe proxy. + +Our Approach +------------ + +After evaluating several JavaScript libraries and frameworks designed to make creating single-page apps easier, we decided to forego a monolithic framework altogether and build our own system with the help of small open source modules made available via [npm](https://www.npmjs.com/). Significantly we have chosen to use [React](http://facebook.github.io/react/) for the view layer, and have been heavily influenced by the React community. + +Coding Guidelines +----------------- + +[Coding Guidelines »](docs/coding-guidelines.md) + +I18n Guidelines +--------------- + +[I18n Guidelines »](client/lib/mixins/i18n/README.md) + +Browser Support +--------------- + +We support the latest two versions of all major browsers (see [browse happy](http://browsehappy.com) for current latest versions). + +Directory Structure +------------------- + +Since we're using [Node.js](http://nodejs.org) on the server, there is going to be a lot of JavaScript code in the application. This only gets compounded by the fact that both server-side and client-side modules reside on the same `npm` package manager (though that ends up being a net positive due to reusability and discovery). + +The structure of the project is as follows: + +``` +├── README.md +├── index.js +├── package.json +├── Makefile +├── assets +│   └── stylesheets +├── client +│   ├── boot +│   ├── config +│   └── … more modules +├── config +│   ├── client.json +│   ├── development.json +│   └── production.json +├── server +│ ├── boot +│   ├── config +│   └── … more modules +└── public + ├── index.html + ├── build.js + ├── build.css +    └── … more static files +``` + +Let's explain the main directories individually: + +#### `config` + +This dir is used to store `.json` config files. At boot-up time, the server decides which config file to use based on the `CALYPSO_ENV` environment variable variable. The default value is `"development"`. + +To run calypso use a value other than the default, you can specify the value in the command: + +```bash +CALYPSO_ENV=wpcalypso make run +``` + +One of the main uses of the config, is to enable/disable features for different environments. This allows us to merge early and often. + +See the main config [README](config/README.md) for more information. + +#### `assets` + +This directory contains the [Sass](http://sass-lang.com/) stylesheets that are compiled into a single style.css when `make build` runs. + +#### `server` + +This dir contains all server-side logic, in self-contained modules within this directory. There should be no other files in this directory other than directories of self-contained modules. The server entry point is usually the `boot` module, which should be a function that returns a "http request handler" function (with the `function (req, res) {}` signature), like the one returned from Express. + +#### `client` + +This dir is similar in structure to the `server` dir, except that this JavaScript code ends up running on the client-side. + +Similar to the `server` dir, the client should have a `boot` module that is the entry point to the client-side application. Often times this file uses [page.js](http://visionmedia.github.io/page.js) to set up the client-side routes, which makes for nice symmetry with the server-side. + +#### `public` + +This dir contains static assets to be served via the sever-side static provider (Express.js' `static()` middleware since we're being particular). The default Makefile setup ends up compiling: + +- `build-[environment].[hash].js` - webpack bundle of the client-side application. +- `build-logged-out-[environment].[hash].js` - webpack bundle of the logged-out client-side application. +- `[section].[hash].js` - webpack chunk for each section in `sections.js`. +- `style.css` - the compiled `*.scss` SASS files concat'd into a single CSS file. + +Of course, any other static assets may be dropped into this directory as well (web font files, icon packs, the favicon, images, etc.). + +Debugging +--------- + +Calypso uses the [debug](https://github.com/visionmedia/debug) module to handle debug messaging. To turn on debug mode for all modules, type the following in the browser console: + +```js +localStorage.setItem( 'debug', '*' ); +``` + +You can also limit the debugging to a particular scope + +```js +localStorage.setItem( 'debug', 'calypso:*' ); +``` + +The Node server uses the DEBUG environment variable instead of localStorage. `make run` will pass along it's environment, so you can turn on all debug messages with + +```bash +DEBUG=* make run +``` + +or limit it as before with + +```base +DEBUG=calypso:* make run +``` diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 00000000000000..267a8266762f37 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,11 @@ +Vagrant.configure("2") do |config| + config.vm.define "app" do |app| + app.vm.provider "docker" do |d| + d.build_dir = "." + d.host_vm_build_dir_options = { rsync__args: ["--verbose", "--archive", "--delete", "-z", "--links"] } + d.ports = ["3000:3000"] + d.create_args = ["--env", "CALYPSO_ENV=wpcalypso"] + d.vagrant_vagrantfile = "./Vagrantfile-boot2docker" + end + end +end diff --git a/Vagrantfile-boot2docker b/Vagrantfile-boot2docker new file mode 100644 index 00000000000000..b246d9a0250634 --- /dev/null +++ b/Vagrantfile-boot2docker @@ -0,0 +1,29 @@ +Vagrant.configure("2") do |config| + config.vm.box = "mitchellh/boot2docker" + config.vm.network :forwarded_port, guest: 3000, host: 3000 + + config.vm.provider "virtualbox" do |v| + # On VirtualBox, we don't have guest additions or a functional vboxsf + # in TinyCore Linux, so tell Vagrant that so it can be smarter. + v.check_guest_additions = false + v.functional_vboxsf = false + v.memory = 2048 + end + + ["vmware_fusion", "vmware_workstation"].each do |vmware| + config.vm.provider vmware do |v| + if v.respond_to?(:functional_hgfs=) + v.functional_hgfs = false + end + v.vmx["memsize"] = "2048" + end + end + + # b2d doesn't support NFS + config.nfs.functional = false + + # b2d doesn't persist filesystem between reboots + if config.ssh.respond_to?(:insert_key) + config.ssh.insert_key = false + end +end diff --git a/assets/stylesheets/README.md b/assets/stylesheets/README.md new file mode 100644 index 00000000000000..bc4df33c3f27a5 --- /dev/null +++ b/assets/stylesheets/README.md @@ -0,0 +1,10 @@ +Styles +====== + +Calypso uses SASS to build its CSS and compile it to `public/style.css`. Remember that all styles end up in a single file, so all styles will apply to every page, all the time. Make sure you namespace your styles for the page you are working on. + +### Adding a new SASS file + +If you are adding a new SASS file to `assets/stylesheets` you will need to reference the file in `assets/stylesheets/style.scss` for it to load. We have three directories to organize the respective files: layout, sections, and shared. If you are adding a new file you are likely adding it to `sections`. + +Check [our styleguide](https://github.com/Automattic/calypso-pre-oss/blob/master/docs/coding-guidelines/css.md) for more information on how we use SASS. diff --git a/assets/stylesheets/_components.scss b/assets/stylesheets/_components.scss new file mode 100644 index 00000000000000..f4ecc907e8c624 --- /dev/null +++ b/assets/stylesheets/_components.scss @@ -0,0 +1,301 @@ +// ========================================================================== +// Components +// +// This is an import of all component CSS that is bundled with each component. +// Please keep these imports sorted and use specificity to ensure that +// stylesheet order does not matter. +// ========================================================================== + +@import 'accept-invite/invite-form-header/style'; +@import 'accept-invite/invite-header/style'; +@import 'accept-invite/logged-in-accept/style'; +@import 'accept-invite/style'; +@import 'auth/style'; +@import 'accept-invite/logged-out-invite/style'; +@import 'components/accordion/style'; +@import 'components/add-new-button/style'; +@import 'components/author-selector/style'; +@import 'components/bulk-select/style'; +@import 'components/button/style'; +@import 'components/button-group/style'; +@import 'components/card/style'; +@import 'components/chart/style'; +@import 'components/comment-button/style'; +@import 'components/count/style'; +@import 'components/date-picker/style'; +@import 'components/dialog/style'; +@import 'components/domains/domain-mapping-suggestion/style'; +@import 'components/domains/domain-product-price/style'; +@import 'components/domains/domain-search-results/style'; +@import 'components/domains/domain-suggestion/style'; +@import 'components/domains/example-domain-suggestions/style'; +@import 'components/domains/map-domain-step/style'; +@import 'components/domains/register-domain-step/style'; +@import 'components/drop-zone/style'; +@import 'components/emojify/style'; +@import 'components/empty-content/style'; +@import 'components/external-link/style'; +@import 'components/flag/style'; +@import 'components/foldable-card/style'; +@import 'components/follow-button/style'; +@import 'components/gauge/style'; +@import 'components/gravatar/style'; +@import 'components/gridicon/style'; +@import 'components/header-cake/style'; +@import 'components/infinite-list/style'; +@import 'components/info-popover/style'; +@import 'components/input-chrono/style'; +@import 'components/like-button/style'; +@import 'components/main/style'; +@import 'components/mobile-back-to-sidebar/style'; +@import 'components/payment-logo/style'; +@import 'components/progress-bar/style'; +@import 'components/progress-indicator/style'; +@import 'components/popover/style'; +@import 'components/post-excerpt/style'; +@import 'components/pulsing-dot/style'; +@import 'components/rating/style'; +@import 'components/search/style'; +@import 'components/search-card/style'; +@import 'components/section-nav/style'; +@import 'components/segmented-control/style'; +@import 'components/select-dropdown/style'; +@import 'components/site-icon/style'; +@import 'components/site-selector/style'; +@import 'components/site-selector-modal/style'; +@import 'components/sites-popover/style'; +@import 'components/spinner/style'; +@import 'components/stat-update-indicator/style'; +@import 'components/sticky-panel/style'; +@import 'components/theme/style'; +@import 'components/themes-list/style'; +@import 'components/timezone-dropdown/style'; +@import 'components/tinymce/style'; +@import 'components/token-field/style'; +@import 'components/forms/counted-textarea/style'; +@import 'components/forms/form-button/style'; +@import 'components/forms/form-buttons-bar/style'; +@import 'components/forms/form-fieldset/style'; +@import 'components/forms/form-input-validation/style'; +@import 'components/forms/form-label/style'; +@import 'components/forms/form-legend/style'; +@import 'components/forms/form-password-input/style'; +@import 'components/forms/form-range/style'; +@import 'components/forms/form-section-heading/style'; +@import 'components/forms/form-select/style'; +@import 'components/forms/form-setting-explanation/style'; +@import 'components/forms/form-tel-input/style'; +@import 'components/forms/form-text-input/style'; +@import 'components/forms/form-text-input-with-affixes/style'; +@import 'components/forms/form-toggle/style'; +@import 'components/forms/range/style'; +@import 'components/forms/sortable-list/index'; +@import 'components/olark-chatbox/style'; +@import 'components/plans/plan/style'; +@import 'components/plans/plan-actions/style'; +@import 'components/plans/plan-discount-message/style'; +@import 'components/plans/plan-features/style'; +@import 'components/plans/plan-feature-cell/style'; +@import 'components/plans/plan-header/style'; +@import 'components/plans/plan-list/style'; +@import 'components/plans/plan-nudge/style'; +@import 'components/plans/plan-price/style'; +@import 'components/plans/plans-compare/style'; +@import 'components/post-schedule/style'; +@import 'components/section-header/style'; +@import 'components/signup-form/style'; +@import 'components/tooltip/style'; +@import 'components/upgrades/credit-card-form/style'; +@import 'components/upgrades/credit-card-number-input/style'; +@import 'components/user/style'; +@import 'components/web-preview/style'; +@import 'components/version/style'; +@import 'components/vertical-nav/style'; +@import 'components/vertical-nav/item/style'; +@import 'layout/community-translator/style'; +@import 'layout/masterbar-new-post'; +@import 'lib/accept/style'; +@import 'me/account-password/style'; +@import 'me/account/style'; +@import 'me/action-remove/style'; +@import 'me/application-password-item/style'; +@import 'me/application-passwords/style'; +@import 'me/connected-application-item/style'; +@import 'me/connected-applications/style'; +@import 'me/connected-application-icon/style'; +@import 'me/credit-cards/credit-card-delete'; +@import 'me/credit-cards/credit-cards'; +@import 'me/help/help-contact-confirmation/style'; +@import 'me/help/help-contact/style'; +@import 'me/help/help-contact-form/style'; +@import 'me/help/help-happiness-engineers/style'; +@import 'me/help/help-results/style'; +@import 'me/help/help-search/style'; +@import 'me/help/style'; +@import 'me/next-steps/next-steps'; +@import 'me/next-steps/next-steps-box'; +@import 'me/notification-settings/blogs-settings/style'; +@import 'me/notification-settings/comment-settings/style'; +@import 'me/notification-settings/settings-form/style'; +@import 'me/notification-settings/wpcom-settings/style'; +@import 'me/profile-gravatar/style'; +@import 'me/profile-link/style'; +@import 'me/profile-links-add-other/style'; +@import 'me/profile-links-add-wordpress/style'; +@import 'me/profile-links/style'; +@import 'me/purchases/cancel-private-registration/style'; +@import 'me/purchases/cancel-purchase/style'; +@import 'me/purchases/confirm-cancel-purchase/style'; +@import 'me/purchases/list/item/style'; +@import 'me/purchases/list/site/style'; +@import 'me/purchases/manage-purchase/style'; +@import 'me/purchases/payment/edit-card-details/style'; +@import 'me/purchases/payment/edit-payment-method/style'; +@import 'me/reauth-required/style'; +@import 'me/security-2fa-backup-codes-list/style'; +@import 'me/security-2fa-backup-codes-prompt/style'; +@import 'me/security-2fa-backup-codes/style'; +@import 'me/security-2fa-code-prompt/style'; +@import 'me/security-2fa-disable/style'; +@import 'me/security-2fa-enable/style'; +@import 'me/security-2fa-progress/style'; +@import 'me/security-2fa-sms-settings/style'; +@import 'me/security-2fa-status/style'; +@import 'me/security-checkup/style'; +@import 'me/sidebar-navigation/style'; +@import 'me/sidebar/style'; +@import 'me/two-step/style'; +@import 'my-sites/ads/style'; +@import 'my-sites/all-sites/style'; +@import 'my-sites/all-sites-icon/style'; +@import 'my-sites/category-selector/style'; +@import 'my-sites/current-site/style'; +@import 'my-sites/customize/style'; +@import 'my-sites/draft/style'; +@import 'my-sites/drafts/style'; +@import 'my-sites/exporter/style'; +@import 'my-sites/media-library/style'; +@import 'my-sites/no-results/style'; +@import 'my-sites/pages/style'; +@import 'my-sites/people/delete-user/style'; +@import 'my-sites/people/edit-team-member-form/style'; +@import 'my-sites/people/people-list-item/style'; +@import 'my-sites/people/people-profile/style'; +@import 'my-sites/people/people-notices/style'; +@import 'my-sites/plans/style'; +@import 'my-sites/post/post-image/style'; +@import 'my-sites/post-selector/style'; +@import 'my-sites/post-trends/style'; +@import 'my-sites/plugins/featured-plugins/style'; +@import 'my-sites/plugins/style'; +@import 'my-sites/plugins/plugin-action/style'; +@import 'my-sites/plugins/plugin-activate-toggle/style'; +@import 'my-sites/plugins/plugin-card-header/style'; +@import 'my-sites/plugins/plugin-icon/style'; +@import 'my-sites/plugins/plugin-information/style'; +@import 'my-sites/plugins/plugin-item/style'; +@import 'my-sites/plugins/plugin-meta/style'; +@import 'my-sites/plugins/plugin-ratings/style'; +@import 'my-sites/plugins/plugin-sections/style'; +@import 'my-sites/plugins/plugin-site-network/style'; +@import 'my-sites/plugins/plugin-site-disabled-manage/style'; +@import 'my-sites/plugins/plugin-site-jetpack/style'; +@import 'my-sites/plugins/plugin-site-update-indicator/style'; +@import 'my-sites/plugins/plugin-site-business/style'; +@import 'my-sites/plugins/plugin-install-button/style'; +@import 'my-sites/plugins/plugin-remove-button/style'; +@import 'my-sites/plugins/plugins-browser-item/style'; +@import 'my-sites/plugins/plugins-browser-list/style'; +@import 'my-sites/plugins/plugins-browser/style'; +@import 'my-sites/plugins/plugin-version/style'; +@import 'my-sites/sharing/connections/account-dialog'; +@import 'my-sites/sharing/connections/account-dialog-account'; +@import 'my-sites/sharing/connections/services-group'; +@import 'my-sites/sidebar-navigation/style'; +@import 'my-sites/site-indicator/style'; +@import 'my-sites/site-settings/action-panel/style'; +@import 'my-sites/site-settings/delete-site-options/style'; +@import 'my-sites/site-settings/delete-site/style'; +@import 'my-sites/site-settings/settings-card-footer/style'; +@import 'my-sites/importer/style'; +@import 'my-sites/site/style'; +@import 'my-sites/stats/all-time/style'; +@import 'my-sites/stats/geochart/style'; +@import 'my-sites/stats/most-popular/style'; +@import 'my-sites/stats/pagination/style'; +@import 'my-sites/stats/overview/style'; +@import 'my-sites/stats/nux/style'; +@import 'my-sites/themes/current-theme/style'; +@import 'my-sites/themes/style'; +@import 'my-sites/themes/themes-search-card/style'; +@import 'my-sites/upgrades/cart/style'; +@import 'my-sites/upgrades/checkout/stored-card'; +@import 'my-sites/upgrades/checkout/subscription-text'; +@import 'notices/style'; +@import 'my-sites/upgrades/domain-management/style'; +@import 'post-editor/style'; +@import 'post-editor/drafts-button/style'; +@import 'post-editor/edit-post-status/style'; +@import 'post-editor/editor-action-bar/style'; +@import 'post-editor/editor-author/style'; +@import 'post-editor/editor-categories/style'; +@import 'post-editor/editor-delete-post/style'; +@import 'post-editor/editor-discussion/style'; +@import 'post-editor/editor-drawer/style'; +@import 'post-editor/editor-drawer-well/style'; +@import 'post-editor/editor-featured-image/style'; +@import 'post-editor/editor-fieldset/style'; +@import 'post-editor/editor-ground-control/style'; +@import 'post-editor/editor-location/style'; +@import 'post-editor/editor-mobile-navigation/style'; +@import 'post-editor/editor-more-options/style'; +@import 'post-editor/editor-page-parent/style'; +@import 'post-editor/editor-page-order/style'; +@import 'post-editor/editor-permalink/style'; +@import 'post-editor/editor-post-formats/style'; +@import 'post-editor/editor-post-type/style'; +@import 'post-editor/editor-revisions/style'; +@import 'post-editor/editor-sharing/style'; +@import 'post-editor/editor-slug/style'; +@import 'post-editor/editor-title/style'; +@import 'post-editor/editor-visibility/style'; +@import 'post-editor/media-modal/style'; +@import 'reader/comments/style'; +@import 'reader/discover/style'; +@import 'reader/feed-header/style'; +@import 'reader/following-edit/style'; +@import 'reader/following-stream/style'; +@import 'reader/full-post/style'; +@import 'reader/list-gap/style'; +@import 'reader/list-item/style'; +@import 'reader/list-management/style'; +@import 'reader/post-byline/style'; +@import 'reader/post-errors/style'; +@import 'reader/post-excerpt-link/style'; +@import 'reader/post-permalink/style'; +@import 'reader/post-options/style'; +@import 'reader/post-images/style'; +@import 'reader/reading-time/style'; +@import 'reader/recommendations/style'; +@import 'reader/share/style'; +@import 'reader/sidebar/style'; +@import 'reader/site-and-author-icon/style'; +@import 'reader/style'; +@import 'reader/stream-header/style'; +@import 'reader/update-notice/style'; +@import 'signup/style'; +@import 'signup/flow-progress-indicator/style'; +@import 'signup/locale-suggestions/style'; +@import 'signup/logged-out-form/style'; +@import 'signup/phone-signup-form/style'; +@import 'signup/previous-step-button/style'; +@import 'signup/processing-screen/style'; +@import 'signup/skip-step-button/style'; +@import 'signup/step-header/style'; +@import 'signup/steps/domains/style'; +@import 'signup/steps/plans/style'; +@import 'signup/steps/site-creation/style'; +@import 'signup/steps/theme-selection/style'; +@import 'signup/validation-fieldset/style'; +@import 'vip/vip-logs/style'; +@import 'signup/steps/dss/style'; diff --git a/assets/stylesheets/editor.scss b/assets/stylesheets/editor.scss new file mode 100644 index 00000000000000..610e2438bf0747 --- /dev/null +++ b/assets/stylesheets/editor.scss @@ -0,0 +1,4 @@ +@import 'shared/colors'; +@import 'shared/typography'; + +@import 'components/tinymce/iframe'; diff --git a/assets/stylesheets/layout/_detail-page.scss b/assets/stylesheets/layout/_detail-page.scss new file mode 100644 index 00000000000000..074f4740bfc824 --- /dev/null +++ b/assets/stylesheets/layout/_detail-page.scss @@ -0,0 +1,148 @@ +.detail-page__backdrop { + padding: 1px; // this fixes a strange rendering bug at the bottom of the full post card in safari and chrome -shaun + z-index: 190; // above the masterbar + box-sizing: border-box; + margin: 0; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: $white; + + // Entrance transitions + &.detail-page-enter { + opacity: 0; + transform: translateX( 200px ); + } + + &.detail-page-enter-active { + opacity: 1; + transform: translateX( 0 ); + transition: all 0.1s ease-out; + } + + // Exit transitions + &.detail-page-leave { + transition: all 0.1s ease-in; + } + + &.detail-page-leave-active { + opacity: 0; + transform: translateX( 200px ); + } + + .card { + margin: 0 auto; + min-height: 100vh; + background: transparent; + padding: 0; + box-shadow: none; + } +} + +.detail-page__content { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow-y: scroll; + overflow-x: hidden; + -webkit-overflow-scrolling: touch; + -webkit-backface-visibility: hidden; +} + +.detail-page__action-buttons { + position: absolute; + top: 0; + left: 0; + right: 0; + margin: 0; + z-index: 200; // above the masterbar + list-style: none; + text-align: right; + padding: 7px 6px; + box-sizing: border-box; + background: rgba( $white, 0.98 ); + border-bottom: 1px solid lighten( $gray, 30 ); + + // These make our fixed inside fixed stuff work in Chrome + -webkit-backface-visibility: hidden; + -webkit-transform: translateZ(0); + + .button.action-button { + color: lighten( $gray, 10 ); + padding: 0 8px; + line-height: 32px; + text-align: center; + cursor: pointer; + background: transparent; + border: none; + border-radius: 0; + + span { + display: none; + font-weight: normal; + color: $gray; + } + + &:hover { + color: $blue-medium; + } + + &:before { + position: relative; + margin-right: 4px; + } + } + + .detail-page-close { + float: left; + + &:before { + @include noticon( '\f430', 32px ); + top: 1px; + left: -6px; + margin-right: 0; + } + } + + .like-button, .comment-button, .reader-share { + top: 2px; + float: right; + margin-right: 16px; + } + + .post-options { + float: right; + margin-right: 4px; + + .post-options__trigger .gridicon__ellipsis { + padding: 4px 8px; + } + } +} + + +// Setup transitions for content +html.detail-page-active { + overflow: hidden; // This prevents the normal page from scrolling -shaun + + .wp-primary { + transition: all 0.1s ease-in; + } +} + +// Transitions for content +html.detail-page-open { + .reader-update-notice { + opacity: 0; + } + + .wp-primary { + opacity: 0; + transform: translateX( -100px ); + pointer-events: none; + } +} diff --git a/assets/stylesheets/layout/_main.scss b/assets/stylesheets/layout/_main.scss new file mode 100644 index 00000000000000..b10fa0d11bc5b5 --- /dev/null +++ b/assets/stylesheets/layout/_main.scss @@ -0,0 +1,475 @@ +/** + * Layout Views + */ + +.wpcom-site__logo { + color: lighten( $gray, 20% ); + font-size: 12vw; + position: fixed; + top: 50%; + left: 50%; + transform: translate( -50%, -50% ); + + @include breakpoint( ">960px" ) { + font-size: 120px; + } +} + +.layout__loader { + background: $blue-wordpress; + border-bottom: 1px solid darken( $blue-wordpress, 4% ); + height: 46px; + margin-left: -30px; + position: absolute; + left: 50%; + top: 0; + width: 60px; + z-index: 200; + + // set a delay threshold for opacity changes + // prevents showing loader on fast connections + visibility: hidden; + opacity: 0; + transition: opacity 0.1s linear; + transition-delay: 0.4s; +} + +.layout__loader.is-active { + visibility: visible; + opacity: 1; +} + +/* =Global +----------------------------------------------- */ + +@-webkit-viewport { width : device-width; } +@-moz-viewport { width : device-width; } +@-ms-viewport { width : device-width; } +@-o-viewport { width : device-width; } +@viewport { width : device-width; } + +* { + -webkit-tap-highlight-color: rgba( 0, 0, 0, 0); +} + +body { + background: $gray-light; + -ms-overflow-style: scrollbar; +} + +::selection { + background: rgba( $blue-light, 0.7 ); + color: $gray-dark; +} + +body, +button, +input, +select, +textarea, +.button, +#footer, +#footer a.readmore { + font-family: $sans; +} + +/*rtl:ignore*/ +body.rtl, +.rtl button, +.rtl input, +.rtl select, +.rtl textarea, +.rtl .button, +.rtl #footer, +.rtl #footer a.readmore { + font-family: $sans-rtl; +} + +/*rtl:ignore*/ +:lang(he) body.rtl, +:lang(he) .rtl button, +:lang(he) .rtl input, +:lang(he) .rtl select, +:lang(he) .rtl textarea, +:lang(he) .rtl .button, +:lang(he) .rtl #footer, +:lang(he) .rtl #footer a.readmore { + font-family: $sans; +} + +.notifications { + display: inherit; +} + +body { + color: #404040; + font-size: 15px; + line-height: 1.5; +} + +/* Headings */ +h1,h2,h3,h4,h5,h6 { + clear: both; +} +hr { + background: #ccc; + border: 0; + height: 1px; + margin-bottom: 1.5em; +} + +/* Text elements */ +p { + margin-bottom: 1.5em; +} +ul, ol { + margin: 0 0 1.5em 3em; +} +ul { + list-style: disc; +} +ol { + list-style: decimal; +} +ul ul, ol ol, ul ol, ol ul { + margin-bottom: 0; + margin-left: 1.5em; +} +dt { + font-weight: 600; +} +dd { + margin: 0 1.5em 1.5em; +} +b, strong { + font-weight: 600; +} +dfn, cite, em, i { + font-style: italic; +} +blockquote { + margin: 10px 0 0 0; + background: #f7f7f7; + padding: 10px 10px 1px; + margin: 10px 0 0 0; + border-radius: 2px; +} +address { + margin: 0 0 1.5em; +} +pre { + background: #eee; + font-family: $monospace; + font-size: 15px; + line-height: 1.6; + margin-bottom: 1.6em; + padding: 1.6em; + overflow: auto; + max-width: 100%; +} +code, kbd, tt, var { + font: 15px $code; +} +abbr, acronym { + border-bottom: 1px dotted #666; + cursor: help; +} +mark, ins { + background: #fff9c0; + text-decoration: none; +} +small { + font-size: 75%; +} +big { + font-size: 125%; +} +figure { + margin: 0; +} +table { + margin: 0 0 1.5em; + width: 100%; +} +th { + font-weight: 600; +} + +.hide, .hidden { display: none; } + +/* Links */ +a, +a:visited { + color: $blue-wordpress; +} + +a:hover, +a:focus, +a:active { + color: $link-highlight; +} + +.link--caution, +.link--caution:visited, +.is-link.link--caution, +.is-link.link--caution:visited { + + &, + &:hover, + &:focus, + &:active { + color: $alert-red; + } +} + +html.iframed { + overflow: hidden; +} + +.noticon:before, +.noticon:after { + @extend %clear-text; + + font-family: Noticons; + line-height: 1; +} + + +/* =General Layout +----------------------------------------------- */ +.wp-content { + @include clear-fix; + position: relative; + width: 100%; + margin: 47px auto 0; + box-sizing: border-box; + overflow-y: hidden; +} + +.wp-primary { + padding: 32px; + margin-left: 272px; +} + +// Tablets +@include breakpoint( "<960px" ) { + .wp-primary { + margin-left: 224px; + } +} + +// Mobile (Full Width) +@include breakpoint( "<660px" ) { + .wp-primary { + margin-left: 0; + padding: 8px; + + .focus-sidebar & { + transform: translateX( 100vw ); + } + + .focus-sidebar.is-section-post & { + transform: translateX( 0 ); + } + } +} + + +/* =Sidebar Transitions +----------------------------------------------- */ +.wp-primary { + transition: all 0.15s ease-in-out; +} + +.wpcom-sidebar, +.site-selector, +.current-site, +.sidebar-menu { + transform: translateX( 0 ); + transition: all 0.15s cubic-bezier(0.075, 0.820, 0.165, 1.000); +} + +.site-selector { + opacity: 0; + pointer-events: none; +} + +.focus-sites { + .wp-primary { + opacity: 0.2; + pointer-events: none; + } + + .site-selector { + opacity: 1; + transform: translateX( 272px ); + pointer-events: auto; + + @include breakpoint( "<660px" ) { + transform: translateX( 100vw ); + } + } + + .wpcom-sidebar { + pointer-events: none; + } + + .current-site, + .sidebar-menu { + opacity: 0; + transform: translateX( 64px ); + } +} + +.focus-sidebar { + overflow: hidden; +} + + +/* =Content +----------------------------------------------- */ + +.wp-content a { + text-decoration: none; +} + +/* =Media +----------------------------------------------- */ + +img { + max-width: 100%; /* Fluid images for posts, comments, and widgets */ + height: auto; +} + +/* Make sure embeds and iframes fit their containers */ +embed, +iframe, +object { + max-width: 100%; +} + +/* Netter min-height for the SoundCloud embeds */ +.wpcom-soundcloud-player, +.embed-soundcloud iframe { + min-height: 150px; +} + + +/* Disabled blocks of content */ + +.disabled-block { + opacity: 0.5; +} + +body.promo { + margin-top: 0; +} + +body.newdash div.wordpress-com-extension-promo { + display: none !important; +} + +.design-assets { + @include breakpoint( "<660px" ) { + padding: 0 6px; + } +} + +.design-assets h2, +.design-assets h2 a:first-child { + color: $gray-dark; + font-family: $serif; + font-size: 38px; + font-weight: bold; + margin: 40px 0 15px; +} +.design-assets h3 { + font-weight: bold; + margin-bottom: 8px; +} +.design-assets hr { + background: transparent; + clear: both; + height: 2px; + margin: 15px 0; +} + +.environment-badge { + position: fixed; + bottom: 16px; + left: 16px; + z-index: 999; + backface-visibility: hidden; + + .bug-report { + position: relative; + display: inline-block; + width: 26px; + height: 26px; + background-color: $white; + border: solid 1px $gray-dark; + border-radius: 50%; + color: $gray-dark; + text-decoration: none; + text-align: center; + z-index: 1000; + transition: border-radius 0.2s ease-out; + &:before { + @include noticon( '\f50a', 14px ); + vertical-align: middle; + } + } + + .environment { + position: relative; + display: inline-block; + font-size: 9px; + font-weight: 600; + line-height: 1; + text-transform: uppercase; + padding: 4px 7px 4px 6px; + vertical-align: middle; + &:before { + content: ''; + position: absolute; + left: -4px; + right: 0; + top: 0; + bottom: 0; + z-index: -1; + background-color: $white; + border: solid 1px $gray-dark; + } + &.is-staging { + &:before { + background-color: $alert-yellow; + } + } + &.is-wpcalypso { + &:before { + background-color: #B1EED0; + } + } + &.is-horizon, + &.is-feedback { + &:before { + background-color: $blue-light; + } + } + } + + .notouch & { + .bug-report { + &:hover { + border-radius: 4px; + } + } + } +} + +@include breakpoint( "<960px" ) { + // Don't show environment badge on smaller screens. It just gets in the way. + .environment-badge { + display: none; + } +} diff --git a/assets/stylesheets/layout/_masterbar.scss b/assets/stylesheets/layout/_masterbar.scss new file mode 100644 index 00000000000000..ff00691aa7dccb --- /dev/null +++ b/assets/stylesheets/layout/_masterbar.scss @@ -0,0 +1,335 @@ +$masterbar-height: 46px; +$autobar-height: 20px; + +/** + * The WordPress.com Masterbar + */ +.masterbar { + background: $blue-wordpress; + border-bottom: 1px solid darken( $blue-wordpress, 4% ); + color: $white; + font-size: 0.9em; + height: $masterbar-height; + margin: 0; + position: absolute; + left: 0; + top: 0; + width: 100%; + z-index: 180; + -webkit-font-smoothing: subpixel-antialiased; + + @include breakpoint( ">660px" ) { + position: fixed; + backface-visibility: hidden; + } + + .wpcom-navigation { + padding: 0 12px 0 0; + } + + #wpnt-notes-panel { + top: 48px; + } + + .noticon { + font-size: 28px; + height: 28px; + width: 28px; + vertical-align: middle; + } + + .sections-menu { + box-sizing: border-box; + list-style: none; + margin: 0; + padding: 0; + + &.menu-right { + float: right; + } + } + + .section-label { + margin-left: 8px; + } + + li { + float: left; + + &.active { + a, + a:hover, + a:focus { + background: $blue-dark; + } + } + + a { + box-sizing: border-box; + color: $white; + + cursor: pointer; + display: block; + height: $masterbar-height; + line-height: $masterbar-height; + margin: 0; + padding: 0 12px; + text-decoration: none; + transition: background 100ms ease-in-out, color 80ms ease-in-out; + + @include breakpoint( ">660px" ) { + padding: 0 15px; + } + + &:hover, + &:focus { + background: $blue-medium; + background: rgba( 255, 255, 255, 0.15 ); + color: $white; + outline: 0; + } + } + } + + &.collapsible { + @include breakpoint( "<660px" ) { + .wpcom-navigation { + padding: 0; + } + + .sections-menu { + width: 40%; + + &.menu-right { + width: 60%; + + li { + width: 33.33%; + } + } + } + + .noticon { + display: block; + margin: 0 auto; + } + + .section-label { + display: block !important; + font-size: 10px; + height: 13px; + margin: 0; + overflow: hidden; + text-align: center; + text-overflow: clip; + white-space: nowrap; + } + + li { + width: 50%; + + a { + line-height: 1; + padding: 3px 0 0 0; + } + } + } + } + + .is-button { + margin-left: 10px; + + a { + background: $white; + border-radius: 5px; + color: $blue-wordpress; + height: 34px; + line-height: 34px; + margin-top: 6px; + overflow: hidden; + padding: 0 3px; + vertical-align: middle; + + &:hover, + &:focus { + background: $gray-light; + color: $blue-wordpress; + } + } + + .noticon { + @include breakpoint( "<480px" ) { + display: none; + } + } + + .section-label { + margin: 0 10px; + } + } + + /** + * Me + */ + .me { + .section-label { + @include breakpoint( ">660px" ) { + clip: rect( 1px, 1px, 1px, 1px ); + height: 1px; + overflow: hidden; + position: absolute !important; + width: 1px; + } + } + } + + /** + * Notifications + */ + .notifications { + display: block; + position: relative; + white-space: nowrap; + + .section-label { + @include breakpoint( ">660px" ) { + clip: rect( 1px, 1px, 1px, 1px ); + height: 1px; + overflow: hidden; + position: absolute !important; + width: 1px; + } + } + + .noticon-bell { + font-size: 24px; + position: relative; + top: 2px; + + @include breakpoint( ">660px" ) { + top: 1px; + } + } + + .notification-bubble { + display: none; + } + + &.unread { + .notification-bubble { + background: $orange-jazzy; + border: solid 2px $blue-wordpress; + border-radius: 50%; + display: block; + font-size: 8px; + height: 8px; + letter-spacing: 0; + line-height: 12px; + margin: 0; + padding: 0; + position: absolute; + top: 2px; + left: calc( 50% - 9px ); + width: 8px; + z-index: 99999; + + // Animation + transform: translateZ(0); + animation: unread-indication .5s linear both; + + @include breakpoint( ">660px" ) { + font-size: 9px; + height: 9px; + left: 18px; + top: 7px; + width: 9px; + } + } + + &.initial-load .notification-bubble { + animation: none; + } + + &.active { + .notification-bubble { + border-color: $blue-dark; + } + } + } + } + + .wpcom-title { + .section-label { + font-size: 16px; + font-weight: 300; + letter-spacing: 0.5px; + line-height: 46px; + line-height: 4.6rem; + text-decoration: none; + @include breakpoint( "<480px" ) { + display: none; + } + } + + @include breakpoint( ">480px" ) { + .noticon { + height: 31px; // This was the only way I found to center the noticon vertically + } + } + + .tld { + color: rgba(255, 255, 255, 0.6); + } + } +} + +@keyframes unread-indication { + 30% { + transform: scale(1.5); + } + 60% { + transform: scale(.85); + } + 80% { + transform: scale(1.1); + } +} + +.masterbar .gravatar { + border: 2px solid $white; + border-radius: 50%; + height: 22px; + margin-bottom: 2px; + vertical-align: middle; + width: 22px; + + @include breakpoint( "<660px" ) { + display: block; + height: 20px; + margin: 2px auto 2px; + width: 20px; + } +} + +.rtl { + .masterbar { + .noticon-reader, + .new-post, + .noticon-bell { + filter: fliph; /* IE */ + transform: rotateY( 180deg ); + } + } +} + +// Horizon replacement logo +.masterbar .noticon.noticon-horizon { + font-size: 59px; + margin: -32px 21px 0 -27px; + padding-left: 15px; + + @include breakpoint( "<660px" ) { + margin: -15px 0px 15px 8px; + padding-left: 0; + } +} diff --git a/assets/stylesheets/layout/_overlay.scss b/assets/stylesheets/layout/_overlay.scss new file mode 100644 index 00000000000000..c89199f329945a --- /dev/null +++ b/assets/stylesheets/layout/_overlay.scss @@ -0,0 +1,204 @@ +/* + * WP.com Overlay + * Used for Site specific contexts and the Editor + */ + +// Overlay +// 1: Indicate that clicking on the background performs an action (closes overlay) +// 2: Reverse 1) + +.wp-overlay { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 9999; + height: 100%; + overflow: scroll; + -webkit-overflow-scrolling: touch; + transform: translate3d( 0, 100%, 0 ); + background-color: rgba( $gray-dark, 0 ); + cursor: pointer; // 1 + + .overlay-content { + cursor: default; // 2 + } + + // Make overlay cover entire view + .overlay-is-front & { + transform: translate3d( 0, 0, 0 ); + } + + // Make overlay visually appear to the user + .overlay-open & { + background-color: rgba( $gray-dark, 0.9 ); + } + + .wpcom-masterbar { + background: transparent; + box-shadow: none; + position: absolute; + right: 0; + left: 0; + top: -56px; + width: auto; + + .overlay-navigation { + background: transparent; + padding: 0; + overflow: hidden; + + .user-actions ul { + list-style-type: none; + } + + .user-actions, + .user-actions ul, + .user-actions ul li { + float: none; + } + } + } + + // Close button + // 1: //To have the button label be optically centered, moving the icon half an icon size to the left + // 2: Optically align label including the x-icon + // 2: Needed for now to override settings, should be looked over once the overlay is more widely used + + // Hack for now to make the button appear like a regular primary button + // Only used for the overlay Close button in Stats overlays + .user-actions ul li .button { + padding: 0 16px 0 22px; // 1 + line-height: 40px; + height: 40px; // 2 + float: right; + + // Need to overrule default masterbar settings on hover :( + // These are copied from _buttons.scss + &:hover { + background: $gray-light; + box-shadow: 0 -1px 0 rgba(255,255,255,0.8) inset; + } + } + + // Include X noticon + // Only used for the overlay Close button in Stats overlays + // TODO: shouldn't be called .settings-done but currently all secondary buttons are + .user-actions ul li a.settings-done::before { + @include noticon( '\f405' , 24px ); + line-height: 40px; + margin-left: -12px; // 2 + } + + // Keep .site-settings here to not break Jetpack and Stats + // until those are updated + .site-settings .site { + float: left; + width: 28%; + + @include breakpoint( "<660px" ) { + float: none; + width: 100%; + } + + .site-content { + margin-bottom: 0; + + @include breakpoint( "<660px" ) { + margin: 6px; + } + } + + .site-options, + .site-more-options { + display: none; + } + + &.jetpack { + border-bottom: 2px solid #8cc258; + } + } + + // 1: Height of masterbar (46px) + (10px+2) margins top/bottom + .wp-content { + @include breakpoint( "<660px" ) { + background: lighten( $gray, 30% ); + margin-top: 66px; + } + } + + .content-header { + @include breakpoint( "<660px" ) { + margin-top: 10px; + } + .noticon-menu { + display: none; + } + } + + /** + * Iframe within the overlay to contain + * elements like the Customizer + */ + iframe { + width: 100%; + height: 100%; + } +} + +.overlay-content { + opacity: 0; + background: lighten( $gray, 30% ); + margin: 0 auto 0; + max-width: 960px; + overflow: visible; + + .overlay-is-front & { + opacity: 1; + } + + @include breakpoint( ">960px" ) { + border-radius: 3px; + } +} + +.overlay-open body, .overlay-open { + overflow: hidden; + overflow-y: hidden; +} + +// 1: Roughly the width of the close button with all its bells and whistles on mobile +.wp-overlay .current-site { + background-color: transparent; + box-shadow: none; + text-align: left; + padding-right: 100px; // 1 + + @include breakpoint( "<960px" ) { + padding-left: 10px; + } +} + +.wp-overlay .actions-menu { + position: absolute; + top: 6px; + right: 0; + + @include breakpoint( "<960px" ) { + right: 10px; + } +} + +.wp-overlay .current-site .site { + color: lighten( $gray, 30% ); + padding-left: 50px; +} + +.wp-overlay .current-site .site-icon { + left: 0; +} + +.wp-overlay .current-site .user-icon { + border-radius: 50%; +} diff --git a/assets/stylesheets/layout/_sidebar.scss b/assets/stylesheets/layout/_sidebar.scss new file mode 100644 index 00000000000000..29e2d8bd1ca297 --- /dev/null +++ b/assets/stylesheets/layout/_sidebar.scss @@ -0,0 +1,286 @@ +// Setting up the sidebar container +.sidebar, +.secondary-cart { // This selects the sidebar on /checkout + overflow: auto; + padding: 0; + background: lighten( $gray, 30% ); + position: fixed; + top: 47px; + bottom: 0; + + @include breakpoint( "<960px" ) { + border-right: 1px solid lighten( $gray, 25% ); + width: 224px; + } + + @include breakpoint( ">960px" ) { + border-right: 1px solid lighten( $gray, 25% ); + left: 0; + width: 272px; + } + + @include breakpoint( "<660px" ) { + left: -100vw; + width: 100vw; + max-height: calc(100vh - 47px ); + pointer-events: none; + transform: translateX( 0 ); + transition: all 0.15s cubic-bezier(0.770, 0.000, 0.175, 1.000); + + .focus-sidebar & { + pointer-events: auto; + -webkit-overflow-scrolling: touch; + transform: translateX( 100vw ); + } + + .focus-sites & { + transform: translateX( 100vw ); + } + } +} + + +// Clearing out the sidebar list styles +.wpcom-sidebar { + margin: 0; + + ul { + list-style: none; + margin: 0; + } + + li { + position: relative; + } +} + + +// Sidebar group headings +.sidebar-heading { + color: darken( $gray, 10% ); + font-weight: 600; + font-size: 12px; + margin: 16px 8px 6px 14px; +} + + +// Menu Links +.sidebar-menu { + display: block; + + @include breakpoint( "<660px" ) { + margin-top: 24px; + } + + li { + display: flex; + + @include breakpoint( "<660px" ) { + background-color: $gray-light; + border-bottom: 1px solid rgba( lighten( $gray, 20% ), 0.5 ); + + &:first-child { + border-top: 1px solid lighten( $gray, 20% ); + } + + &:last-child { + border-bottom: 1px solid lighten( $gray, 20% ); + } + } + } + + a:first-child { + flex: 1 0 auto; + width: 0; + + // Fade overlay for longer labels + &:after { + content: ''; + text-align: right; + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 15%; + background: linear-gradient( + to right, + rgba( lighten( $gray, 30% ), 0 ), + rgba( lighten( $gray, 30% ), 1 ) 50% ); + + @include breakpoint( "<660px" ) { + background: linear-gradient( + to right, + rgba( $gray-light, 0 ), + rgba( $gray-light, 1 ) 50% ); + } + } + } + + a { + font-size: 13px; + position: relative; + padding: 14px 16px 14px 55px; + color: $gray-dark; + box-sizing: border-box; + white-space: nowrap; + overflow: hidden; + display: flex; + + &:focus { + outline: none; + } + + @include breakpoint( "<660px" ) { + padding: 18px 16px 18px 53px; + } + } + + a.add-new { + padding: 2px 8px 3px 8px; + height: 24px; + margin: 11px 8px 0 0; + line-height: 18px; + background-color: $gray-light; + color: darken( $gray, 20% ); + font-size: 11px; + font-weight: 600; + border-radius: 3px; + border: 1px solid lighten( $gray, 20% ); + + @include breakpoint( "<660px" ) { + font-size: 14px; + height: 35px; + padding: 8px 16px; + margin: 10px 10px 0 0; + } + } + + a.plan-name { + padding: 3px 8px 4px 8px; + position: absolute; + top: 12px; + right: 8px; + color: darken( $gray, 20% ); + font-size: 11px; + + @include breakpoint( "<660px" ) { + top: 16px; + right: 16px; + } + } + + .gridicon { + position: absolute; + top: 11px; + left: 20px; + fill: $gray; + height: 24px; + width: 24px; + + @include breakpoint( "<660px" ) { + top: 15px; + left: 16px; + height: 24px; + width: 24px; + } + + // External indicator for sections that aren't available in Calypso + &.gridicons-external { + position: absolute; + top: 13px; + right: 8px; + left: auto; + z-index: 1; + height: 18px; + + @include breakpoint( "<660px" ) { + top: 17px; + } + } + } + + .noticon-external { + position: absolute; + top: 15px; + right: 19px; + z-index: 1; + color: $gray; + + @include breakpoint( "<660px" ) { + top: 9px; + right: 16px; + font-size: 32px; + } + } +} + + +// Selected Menu +@include breakpoint( ">660px" ) { + .sidebar-menu .selected { + background-color: $gray; + + a { + color: $white; + + &:first-child:after { + background: linear-gradient( + to right, + rgba( $gray, 0 ), + rgba( $gray, 1 ) 50% ); + } + } + + a.add-new { + color: darken( $gray, 30% ); + border: 1px solid darken( $gray, 10% ); + } + + .gridicon { + fill: $white; + } + + &.is-action-button-selected a { + &:first-child:after { + background: linear-gradient( + to right, + rgba( $gray-light, 0 ), + rgba( $gray-light, 1 ) 50% ); + } + } + } +} + + +// Menu Hover +.notouch .sidebar-menu li:hover { + &:not(.selected) { + background-color: $gray-light; + + a { + color: $blue-medium; + + &:first-child:after { + background: linear-gradient( + to right, + rgba( $gray-light, 0 ), + rgba( $gray-light, 1 ) 50% ); + } + + &.add-new { + background-color: $white; + color: $gray-dark; + } + } + + .gridicon { + fill: $blue-medium; + } + } +} + +.notouch .sidebar-menu li:not(.selected) a { + &.add-new:hover { + color: $blue-medium; + } +} diff --git a/assets/stylesheets/sections/_billing-history.scss b/assets/stylesheets/sections/_billing-history.scss new file mode 100644 index 00000000000000..4159da14bef5c0 --- /dev/null +++ b/assets/stylesheets/sections/_billing-history.scss @@ -0,0 +1,630 @@ +.billing-history-page { + + #billing-history-wrapper * { + box-sizing: border-box; + } + + #billing-history-content, + #upcoming-charges { + background-color: $white; + } + + .billing-history-header p { + font-size: 14px; + } + + // Transactions Table + // ============================================= + + .transactions { + border-collapse: collapse; + } + + .transactions__no-results { + display: table-row; + + td { + padding: 20px 0; + text-align: center; + } + } + + // Table Header + // ----------------------------------- + + .transactions thead { + background-color: $gray-light; + } + + .transactions thead .header-row { + vertical-align: top; + height: 40px; + } + + .transactions thead .header-column { + vertical-align: top; + padding-top: 4px; + } + + .search-form { + text-align: right; + } + + .search_terms { + display: inline-block; + font-size: 13px; + margin-top: 2px; + margin-right: 12px; + text-align: left; + width: 100px; + padding: 3px 9px; + background-color: $white; + border-radius: 15px; + border: 1px solid lighten( $gray, 30% ); + transition: width 0.25s ease-out; + outline: 0; + + &:focus, + &:active { + width: 150px; + } + } + + .reset-search { + display: none; + } + + // Table Body + // ----------------------------------- + + .transaction { + color: $gray-dark; + font-size: 14px; + height: 66px; + border-bottom: 1px solid lighten( $gray, 30% ); + } + + .transaction td { + vertical-align: top; + padding: 10px 0; + } + + .transactions tbody .date { + width: 140px; + padding: 12px; + } + + .transactions tbody .trans-app { + padding-left: 12px; + padding-right: 12px; + } + + .transactions tbody .amount { + text-align: right; + padding: 12px; + width: 110px; + } + + .trans-wrap { + @include clear-fix; + } + + .service-name { + strong { + font-weight: normal; + } + + small { + color: $gray; + display: block; + font-size: 12px; + font-style: italic; + } + } + + .service-description { + float: left; + } + + .transaction-links { + font-size: 12px; + margin: 4px 0 0 0; + + a { + padding-right: 8px; + } + } + + // Filter Popovers + // ============================================= + + .filter-popover { + position: relative; + display: inline-block; + padding: 4px 12px; + vertical-align: top; + } + + .filter-popover-content { + display: none; + position: absolute; + top: 35px; + z-index: 1; + border-radius: 4px; + background-color: $white; + box-shadow: 0 1px 6px rgba(0,0,0,0.2), 0 0 25px 10px rgba(0,0,0,0.1); + outline: 0; + + &.datepicker { + right: -115px; + } + + &.app { + right: -147px; + } + } + + .popped .filter-popover-content { + display: block; + } + + .filter-popover-content:before { + @extend %clear-text; + + display: block; + position: absolute; + top: -25px; + left: 21px; + color: $blue-wordpress; + content: '\f500'; + font-family: Noticons; + font-size: 20px; + } + + .filter-popover-content .overflow { + overflow-x: auto; + overflow-y: hidden; + } + + .filter-popover-content table { + margin-bottom: 0; + } + + .filter-popover-content tr:hover td { + background: rgba(0,0,0,0.02); + cursor: pointer; + color: $blue-light; + } + + .filter-popover-content tr.selected td { + background-color: $gray-dark; + color: $white; + } + + .filter-popover-content th { + @extend %clear-text; + padding: 8px 10px; + font-size: 12px; + font-weight: 600; + color: $white; + background: $blue-wordpress; + text-shadow: 0 -1px 0 rgba(0,0,0,0.2); + text-align: left; + border-bottom: 1px solid rgba(0,0,0,0.3); + white-space: nowrap; + } + + .filter-popover-content th.transactions-header__count { + text-align: right; + } + + .filter-popover-content thead:first-of-type th:first-child { + border-top-left-radius: 4px; + } + + .filter-popover-content thead:first-of-type th:last-child { + border-top-right-radius: 4px; + } + + .filter-popover-content td { + padding: 8px 10px; + font-size: 13px; + border-top: 1px dotted rgba(0,0,0,0.1); + color: $blue-wordpress; + } + .filter-popover-content td.descriptor { + font-weight: 400; + font-size: 13px; + } + .filter-popover-content td.transactions-header__count { + font-weight: 600; + font-size: 14px; + text-align: right; + color: #777; + color: rgba(0,0,0,0.8); + } + + .filter-popover-toggle { + padding: 5px 10px; + border-radius: 3px; + cursor: pointer; + border-radius: 3px; + border: 1px solid transparent; + + &:hover { + background-color: $white; + border-color: rgba(0,0,0,0.05); + } + + &:after { + display: inline-block; + content: '\f431'; + font-family: Noticons; + color: $blue-wordpress; + margin-left: 5px; + position: relative; + top: 2px; + } + } + + .popped .filter-popover-toggle { + background-color: rgba(0,0,0,0.1); + border-color: rgba(0,0,0,0.05); + box-shadow: 0 1px 0 rgba(255,255,255,0.4); + } + + // View Receipt Modal + // ============================================= + + .wp-overlay { + .overlay-content { + background: $white; + width: 640px; + max-width: 100%; + } + + .overlay-navigation { + background: $gray-dark; + padding: 10px; + } + + .wp-content { + background: $white; + + @include breakpoint( "<960px" ) { + padding: 0; + } + } + + .settings-done { + margin-right: 10px; + } + + .current-site .site { + padding-left: 20px; + + @include breakpoint( "<480px" ) { + padding-left: 0; + } + } + + .site-title, + .site-icon { + display: none; + } + + .site-description { + font-size: 20px; + padding: 3px; + } + } + + + .view-receipt-wrapper { + margin: 30px auto 0 auto; + padding: 20px 0 0 0; + + .app-overview { + min-height: 65px; + padding: 10px 40px; + position: relative; + overflow: auto; + + @include breakpoint( "<480px" ) { + padding: 10px 20px; + } + + img { + max-width: 65px; + min-height: 65px; + float: left; + + @include breakpoint( "<480px" ) { + left: 20px; + } + } + + h2 { + clear: none; + float: left; + padding: 10px 20px; + + @include breakpoint( "<480px" ) { + padding-top: 0; + } + + small { + display: block; + } + } + + .transaction-date { + color: $gray; + font-size: 13px; + font-style: italic; + padding: 5px 0 0 0; + + @include breakpoint( ">480px" ) { + position: absolute; + top: 10px; + right: 40px; + } + } + } + + ul { + background: $gray-light; + list-style: none; + padding: 20px 40px; + margin: 20px 0 0 0; + overflow: auto; + + @include breakpoint( "<480px" ) { + padding: 20px; + } + + li { + color: $gray-dark; + font-size: 13px; + margin: 0 0 15px 0; + padding: 0; + + &:last-child { + margin: 0; + } + + strong { + color: darken( $gray, 20% ); + display: block; + font-size: 12px; + font-weight: 600; + margin: 0 5px 0 0; + text-transform: uppercase; + } + } + + li.billing-details div:hover { + border: 2px black dashed; + } + } + + .resend { + padding: 0; + margin-left: 0; + } + + .receipt { + padding: 30px 40px; + + @include breakpoint( "<480px" ) { + padding: 30px 20px; + } + + h4 { + font-size: 20px; + } + + .receipt-line-items { + margin: 0; + padding: 0; + width: 100%; + + th { + border-bottom: 2px solid lighten( $gray, 25% ); + color: $gray; + font-size: 12px; + font-weight: 400; + text-transform: uppercase; + width: auto; + } + + th.receipt-desc { + width: 75%; + text-align: left; + } + + th.receipt-amount { + text-align: right; + } + + td, + th { + padding: 10px 0; + } + + td.receipt-amount { + color: #444; + text-align: right; + vertical-align: middle; + } + + .receipt-item-name { + small { + color: $gray; + font-size: 13px; + margin-left: 5px; + text-transform: lowercase; + } + em { + color: $gray; + display: block; + font-size: 13px; + } + } + + tbody tr { + td { + border-bottom: 1px solid lighten( $gray, 30% ); + } + + &:last-child td { + border: none; + } + } + + tfoot { + font-weight: 400; + text-align: right; + vertical-align: bottom; + + td { + border-top: 2px solid lighten( $gray, 25% ); + padding-bottom: 0; + } + } + } + } + + .receipt-links { + border-top: 1px solid lighten( $gray, 25% ); + margin: 0; + overflow: auto; + padding: 30px 40px; + + @include breakpoint( "<480px" ) { + padding: 20px; + } + + .button { + display: block; + margin: 10px 0; + padding: 15px; + text-align: center; + + @include breakpoint( ">480px" ) { + float: left; + margin: 0 1%; + width: 48%; + } + } + } + } +} + +@include breakpoint( "<480px" ) { + .billing-history-page { + thead { + display: block; + } + + .transactions { + display: block; + max-width: 100%; + + thead { + margin: 0 -16px; + } + + .transaction { + display: inline-block; + height: auto; + padding: 1em; + + &:first-of-type { + border-top: none; + } + } + + .header-row { + display: block; + height: auto !important; + padding: .5em 0; + + .date, .trans-app { + display: none; + } + + .search-field { + display: block; + padding-top: 0; + width: 100%; + } + + .search-form { + text-align: center; + + .search_terms { + margin: 0; + width: 80%; + } + } + } + + tbody { + td { + display: inline-block; + width: 100%; + padding: 0 !important; + + &.amount { + text-align: left; + } + + &.date { + font-weight: 600; + } + } + } + } + + .view-receipt-wrapper { + .app-overview { + h2 { + small { + display: block; + } + } + } + + dl { + padding: 0 30px; + + dt { + text-align: left; + width: 50%; + } + + dd { + width: 50%; + } + } + } + } +} + +@media print { + #overlay-header, + #primary, + .receipt-links { + display: none; + } + + .billing-history-page { + .wp-overlay .overlay-content, + .wp-content { + margin: 0 auto; + max-width: none; + width: 100%; + } + } +} diff --git a/assets/stylesheets/sections/_checkout.scss b/assets/stylesheets/sections/_checkout.scss new file mode 100644 index 00000000000000..aa00bc97ad0106 --- /dev/null +++ b/assets/stylesheets/sections/_checkout.scss @@ -0,0 +1,1077 @@ +.checkout { + position: relative; + + .payment-box { + height: 0; + margin-bottom: 0; + opacity: 0; + overflow: hidden; + padding: 0; + transform: translateZ(0) scale(.8); // Zoom out effect + transition: all .3s ease-in-out; + visibility: hidden; // To deal with layering issues + width: 100%; + + &:not(.domain-details) { + @include breakpoint( "<660px" ) { + background-color: transparent; + box-shadow: none; + } + } + + &.selected { + height: auto; + opacity: 1; + transform: translateZ(0) scale(1); // Zoom in effect + visibility: visible; // To deal with layering issues + } + + &.is-empty { + .payment-box-section { + border: 1px solid lighten( $gray, 30% ); + margin: 5px 0; + display: flex; + flex-flow: row wrap; + justify-content: space-around; + background-color: $white; + padding: 10px; + } + + .placeholder { + animation: pulse-light 0.8s ease-in-out infinite; + background: lighten( $gray, 20% ); + width: 100%; + height: 100%; + } + + .payment-box__title { + @extend .placeholder; + height: 22px; + width: 130px; + + :after { + content: ''; + } + + } + + .payment-box__header { + height: 16px; + width: 170px; + flex: 0 0 170px; + } + + .placeholder-row { + height: 40px; + flex: 0 0 100%; + margin-bottom: 15px; + } + + .placeholder-col-narrow { + height: 40px; + flex: 1 1 auto; + margin-bottom: 15px; + + @include breakpoint( ">480px" ) { + flex: 2 1 auto; + } + } + + .placeholder-inline-pad { + padding-right: 15px; + } + + .placeholder-inline-pad-only-wide { + @include breakpoint( ">480px" ) { + padding-right: 15px; + } + } + + .placeholder-col-wide { + height: 40px; + margin-bottom: 15px; + flex: 0 0 100%; + + @include breakpoint( ">480px" ) { + flex: 6 3 auto; + } + } + + .placeholder-button { + height: 50px; + width: 100%; + + @include breakpoint ( ">480px" ) { + width: 80px; + height: 40px; + } + } + + .placeholder-button-container { + margin-top: 55px; + + @include breakpoint( ">480px" ) { + margin-top: 20px; + } + } + + .payment-box-hr { + margin: 40px 0 20px 0; + width: 100%; + height: 0; + border-bottom: 1px solid lighten( $gray, 30% ); + + @include breakpoint( "<480px" ) { + display: none; + } + } + } + } + + .payment-box__content { + min-height: 140px; + margin-top: 10px; + } + + h5 { + color: darken( $gray, 10% ); + font-size: 15px; + font-weight: 600; + opacity: 0.7; + text-transform: uppercase; + + :after { + @include noticon( '\f470', (13 / 12) * 1em ); + float: right; + } + } + + .box-padding { + padding: 16px 0; + + @include breakpoint( ">660px" ) { + padding: 30px 30px 20px 30px; + } + } + + .domain-details { + .box-padding { + @include breakpoint( "<660px" ) { + padding: 16px; + } + } + } + + form { + margin-top: 5px; + + @include breakpoint( ">660px" ) { + @include clear-fix; + } + } + + button[type=submit].button-pay { + @include breakpoint( "<660px" ) { + width: 100%; + + #wpcom & { + min-height: 50px; + } + } + + @include breakpoint( ">660px" ) { + clear: both; + float: left; + } + } + + input[type=number] { + &::-webkit-outer-spin-button, + &::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } + } + + // Floating labels + // ----------------------------------- + + .checkout-field { + margin-top: 15px; + position: relative; + + select { + font-size: 15px; + width: 100%; + } + + &.invalid { + input, + select { + border-color: $alert-red; + } + } + + input[ disabled ] { + cursor: not-allowed; + } + } + + // Payment Boxes + // ============================================= + + .checkout-terms { + color: darken( $gray, 10% ); + font-size: 12px; + font-weight: 100; + margin: 10px 0; + padding: 0 30px; + text-align: center; + + @include breakpoint( ">660px" ) { + margin-bottom: 20px; + padding: 0; + text-align: left; + } + } + + .payment-box-actions { + @include breakpoint( ">660px" ) { + margin: 20px -30px 0px -30px; + padding: 20px 30px 0 30px; + border-top: 1px solid lighten( $gray, 30% ); + @include clear-fix; + } + } + + .credit-card-payment-box { + .payment-box-sections { + background-color: $white; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + + @include breakpoint( ">660px" ) { + box-shadow: none; + } + } + + .payment-box-section { + cursor: pointer; + border-bottom: 1px solid lighten( $gray, 30% ); + + &:first-of-type { + border-top: 1px solid lighten( $gray, 30% ); + } + + &.selected { + cursor: default; + } + } + + .payment-box-section-inner { + border-left: 1px solid lighten( $gray, 30% ); + padding-left: 2px; + position: relative; + border-right: 1px solid lighten( $gray, 30% ); + min-height: 50px; + } + + .payment-box-section.selected .payment-box-section-inner { + background-color: #fafdf6; + padding-left: 0; + } + + .payment-box-section.selected:not( .no-stored-cards ) { + .payment-box-section-inner { + border-left: 3px solid $alert-green; + } + .new-card-fields { + background-color: #fafdf6; + } + } + + .no-stored-cards .new-card-fields > .checkout-field:first-child { + margin-top: 0; + } + + .payment-box-section .new-card-toggle { + box-shadow: none; + cursor: pointer; + font-size: 13px; + position: absolute; + } + + .payment-box-section .new-card-fields { + background-color: $white; + max-height: 0; + overflow: hidden; + padding: 0 15px 0 12px; + position: relative; + transition: all 0.5s ease-in-out; + } + + .payment-box-section.selected .new-card-fields { + max-height: 500px; + margin-bottom: 0; + padding-top: 15px; + padding-bottom: 15px; + } + + .new-card-toggle { + color: $blue-wordpress; + padding: 15px 15px 15px 12px; + border: 0; + background: transparent; + } + + .new-card-header { + color: $blue-medium; + font-weight: 400; + } + + .all-fields-required { + color: lighten( $gray, 10% ); + display: block; + font-size: 12px; + font-style: italic; + + @include breakpoint( ">660px" ) { + top: 7px; + } + + &.has-saved-cards { + top: 18px; + + @include breakpoint( ">660px" ) { + position: absolute; + right: 18px; + } + } + } + } + + // PayPal Payment Box + // ----------------------------------- + + .paypal-payment-box, + .credits-payment-box { + .payment-box-section { + background-color: $white; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + + @include breakpoint( ">660px" ) { + border: 1px solid lighten( $gray, 30% ); + box-shadow: none; + } + } + } + + .paypal-payment-box { + .payment-box-section { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + padding-bottom: 15px; + padding-right: 15px; + } + + .country, + .postal-code { + margin-left: 15px; + } + + .country { + flex-basis: auto; + flex-grow: 3; + flex-shrink: 0; + + label { + display: none; + } + } + + .postal-code { + flex-basis: 8em; + flex-grow: 2; + flex-shrink: 0; + margin-top: 15px; + + label { + display: none; + } + } + } + + // Credits Payment Box + // ----------------------------------- + .credits-payment-box { + .payment-box-section { + box-sizing: border-box; + min-height: 91px; + padding: 20px 20px 20px 80px; + position: relative; + + &::before { + color: $blue-medium; + left: 10px; + position: absolute; + top: 15px; + @include noticon( '\f205', 60px ); + } + + > h6 { + color: $blue-medium; + font-size: 18px; + } + + > span { + color: darken( $gray, 10% ); + font-size: 15px; + } + + @include breakpoint( ">660px" ) { + padding-left: 100px; + } + } + } + + // Supporting Text / Fine Print + // ----------------------------------- + .supporting-text { + border-top: 1px solid lighten( $gray, 20% ); + font-size: 13px; + list-style: none; + margin: 0; + padding: 15px 0; + @include clear-fix; + + @include breakpoint( ">660px" ) { + border-bottom: 1px solid lighten( $gray, 20% ); + margin: 30px 0; + } + + li { + color: lighten( $gray, 10% ); + text-align: center; + + @include breakpoint( ">660px" ) { + float: left; + margin: 0 5%; + width: 40%; + } + + @include breakpoint( "<660px" ) { + margin: 0; + padding: 15px; + } + + h6 { + color: darken( $gray, 20% ); + font-size: 14px; + font-weight: 600; + } + + p { + font-size: 12px; + font-weight: 100; + margin: 10px 0 0 0; + } + } + } + + .credit-card-supporting-text__refund-link { + white-space: nowrap; + color: lighten( $gray, 10% ); + text-decoration: underline; + } + + // + // Domain Registration Details Page + // + + .domain-details { + .first-name { + margin-top: 0; + } + + @include breakpoint( ">660px" ) { + .last-name { + margin-top: 0; + } + + .hidden-input a, + .checkout-field { + float: left; + width: 100%; + } + + .last-name, + .phone, + .postal-code { + float: right; + } + + .email, + .first-name, + .last-name, + .phone { + width: calc( 50% - 7px ); + } + + .city, + .postal-code, + .state { + width: calc( 33% - 8px ); + } + + .state { + margin-left: 14px; + + label + select { + min-width: inherit; + } + } + } + + .hidden-input a { + display: block; + font-size: 12px; + margin-top: 5px; + } + } +} + +.privacy-protection { + background-color: $gray-light; + float: left; + margin-bottom: 15px; + margin-top: 15px; + padding: 10px; + + @include breakpoint( ">660px" ) { + box-sizing: border-box; + padding: 15px; + width: 100%; + + section { + display: flex; + } + } + + h6 { + font-size: 16px; + font-weight: 600; + } + + label { + background-color: $white; + border: 3px solid $white; + border-radius: 3px; + display: block; + margin-top: 10px; + padding: 12px; + transition: all 0.3s ease-in-out; + + &.selected { + border-color: #00AADC; + } + + @include breakpoint( ">660px" ) { + display: flex; + flex-direction: column; + justify-content: space-between; + margin-top: 15px; + width: 50%; + + &:last-child { + margin-left: 15px; + } + } + } + + strong { + display: block; + font-size: 14px; + font-weight: normal; + line-height: 130%; + } + + p { + color: #7096af; + font-size: 11px; + margin-bottom: 0; + margin-top: 5px; + } + + input { + display: none; + } + + button { + margin-top: 10px; + white-space: normal; + width: 100%; + } +} + +.privacy-protection-dialog.dialog.card { + max-height: 95%; + overflow-y: auto; + + .dialog__content { + header { + text-align: center; + + h1 { + font-size: 30px; + font-weight: 200; + line-height: 130%; + height: auto; + } + + p { + font-size: 13px; + } + + .line-break { + @include breakpoint( ">660px" ) { + display: block; + } + } + } + } + + .privacy-features { + border-bottom: 1px solid $gray-light; + border-top: 1px solid $gray-light; + list-style: none; + margin: 20px 0; + padding: 5px 0; + + li { + padding: 5px 10px; + text-align: center; + + @include breakpoint( ">660px" ) { + display: inline-block; + padding: 5px 30px; + } + } + + h2 { + font-size: 14px; + font-weight: 600; + + &:before { + @include noticon( '\f418', 28px ); + color: $alert-green; + vertical-align: middle; + } + } + } + + .privacy-comparison { + list-style: none; + margin: 0; + padding: 0 0 20px 0; + + @include breakpoint( ">660px" ) { + overflow: auto; + padding-top: 20px; + } + + li { + border: 1px solid lighten( $gray, 30% ); + border-radius: 3px; + box-sizing: border-box; + margin: 40px 0 0 0; + padding: 20px; + position: relative; + + @include breakpoint( ">660px" ) { + float: left; + margin: 0 2%; + width: 46%; + } + + &:before { + border-radius: 50%; + color: #FFF; + display: block; + height: 25px; + position: absolute; + left: -8px; + top: -8px; + width: 25px; + } + + &.with-privacy:before { + @include noticon( '\f418', 25px ); + background: $alert-green; + } + + &.without-privacy:before { + background: $alert-yellow; + content: '!'; + font-size: 18px; + font-weight: 600; + line-height: 25px; + text-align: center; + } + + h3 { + font-size: 16px; + font-weight: 600; + margin: 0; + text-align: center; + } + + .privacy-price { + color: $gray; + font-size: 13px; + font-style: italic; + font-weight: 400; + text-align: center; + } + + p { + background: $gray-light; + font-size: 12px; + margin: 20px -20px; + min-height: 126px; + padding: 20px; + + span { + display: block; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + + .button { + width: 100%; + } + } + } +} + +.checkout-thank-you { + box-sizing: border-box; + position: static; + text-align: center; + width: 100%; + + .thank-you-message { + padding-bottom: 20px; + + .receipt-icon { + display: inline-block; + position: relative; + + &::before { + @include noticon( '\f425', 70px ); + color: lighten( $gray, 20% ); + } + + &::after { + @include noticon( '\f418', 18px ); + background: #53b66c; + border-radius: 18px; + color: $white; + position: absolute; + top: 6px; + right: 15px; + width: 18px; + height: 18px; + } + } + + > h1 { + color: $gray-dark; + font-weight: 100; + margin: 0; + } + + > h2 { + color: $gray-dark; + font-weight: 200; + opacity: 0.6; + } + } + + .try-out-message { + padding-top: 20px; + + > h3 { + font-weight: 600; + } + } + + .purchase-details-list { + list-style: none; + } + + .purchase-detail { + display: inline-block; + width: 33.333333%; + + .purchase-detail-text { + &::before { + color: lighten( $gray, 20% ); + @include noticon( '\f803' ); + top: -8px; + } + + > h3 { + font-weight: 600; + } + + > p { + font-size: 12px; + opacity: 0.7; + } + } + + &.get-free-domain { + .purchase-detail-text::before { + @include noticon( '\f475' ); + } + } + + &.customize-fonts-and-colors { + .purchase-detail-text::before { + @include noticon( '\f103' ); + } + } + + &.upload-to-videopress { + .purchase-detail-text::before { + @include noticon( '\f104' ); + } + } + + &.ads-have-been-removed { + .purchase-detail-text::before { + @include noticon( '\f803' ); + top: -7px; + } + } + + &.ecommerce { + .purchase-detail-text::before { + @include noticon( '\f447' ); + } + } + + &.live-chat { + .purchase-detail-text::before { + @include noticon( '\f108' ); + } + } + + &.unlimited-premium-themes { + .purchase-detail-text::before { + @include noticon( '\f103' ); + } + } + + &.important { + .purchase-detail-text::before { + @include noticon( '\f303' ); + } + } + + &.your-primary-domain { + .purchase-detail-text::before { + @include noticon( '\f475' ); + } + } + + &.upgrade-now { + .purchase-detail-text::before { + @include noticon( '\f800' ); + } + } + + &.google-apps-details { + .purchase-detail-text::before { + @include noticon( '\f410' ); + } + } + + &.redirect-now-working { + .purchase-detail-text::before { + @include noticon( '\f442' ); + } + } + + &.change-redirect-settings { + .purchase-detail-text::before { + @include noticon( '\f411' ); + } + } + } + + .get-support { + border-top: 1px solid lighten( $gray, 20% ); + color: darken($gray, 10%); + font-size: 14px; + + > h3 { + font-weight: 600; + } + + > p { + margin-bottom: 0; + } + + a { + border-bottom: 1px solid $blue-medium; + } + } +} + +// Mobile styles +@include breakpoint( "<660px" ) { + .checkout-thank-you { + background: transparent; + padding: 14px; + + .card { + background: none; + box-shadow: none; + padding: 0; + } + + .thank-you-message { + > h1, + > h2 { + font-size: 17px; + } + } + + .purchase-details-list { + display: inline-block; + margin: 0 0 10px 0; + } + + .purchase-detail { + background: $white; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-sizing: border-box; + display: inline-block; + margin-bottom: 20px; + padding: 20px 10px; + text-align: left; + width: 100%; + + .purchase-detail-text { + padding-left: 64px; + position: relative; + + &::before { + font-size: 50px; + position: absolute; + left: 0; + } + } + + > button { + height: 42px; + line-height: 42px; + padding: 0; + vertical-align: top; + width: 100%; + } + } + + .get-support { + border-bottom: 1px solid lighten( $gray, 20% ); + padding: 20px 0; + } + } +} + +// Desktop styles +@include breakpoint( ">660px" ) { + .checkout-thank-you { + .thank-you-message { + border-bottom: 1px solid lighten( $gray, 30% ); + + > h1 { + font-size: 25px; + } + > h2 { + font-size: 20px; + max-width: 50%; + margin: auto; + } + } + + .purchase-details-list { + margin: 0; + padding: 30px 0; + } + + .purchase-detail { + vertical-align: top; + } + + .purchase-detail-text { + &::before { + font-size: 70px; + } + + > p { + margin: 0 50px 10px 50px; + } + } + + .get-support { + padding: 20px; + + > h3 { + display: inline; + margin-right: 15px; + } + + > p { + display: inline; + } + } + } +} + +// If there's no sidebar, we don't show the cart on the checkout page. +@include breakpoint( "<660px" ) { + .secondary-cart { + display: none; + } +} + +@include breakpoint( ">660px" ) { + .pay-button { + float: left; + } +} + +.credit-card-payment-box__switch-link { + color: $link-highlight; + font-style: italic; + font-weight: 800; + line-height: 40px; + display: block; + clear: both; + font-size: 12px; + + @include breakpoint( "<660px" ) { + margin: 20px 0 0 0; + text-align: center; + } + + @include breakpoint( ">960px" ) { + float: right; + clear: none; + } +} diff --git a/assets/stylesheets/sections/_devdocs.scss b/assets/stylesheets/sections/_devdocs.scss new file mode 100644 index 00000000000000..b2627e9b5e60d9 --- /dev/null +++ b/assets/stylesheets/sections/_devdocs.scss @@ -0,0 +1,217 @@ +.devdocs, +.design-assets { + font-size: 18px; + line-height: 1.618; + color: $gray-dark; + margin: 0 auto; + max-width: 960px; + padding: 1.777em 8.184em; + + @include breakpoint( "<960px" ) { + padding: 24px; + max-width: 100%; + } +} + +.is-section-devdocs .wp-content { + display: flex; + max-width: 100%; + margin-top: 47px; + margin-left: 0; + + .wp-primary { + order: 2; + flex: 1; + } + + .wp-secondary { + background: $white; + flex: 0 300px; + box-shadow: inset -0.296em 0 0 rgba(0,80,130,0.2); + + @include breakpoint( "<960px" ) { + flex: 0 200px; + } + } +} + +.devdocs__sidebar { + margin-top: 48px; +} + +.devdocs__title { + color: darken( $gray, 20% ); + font-weight: 300; + font-size: 24px; + padding: 24px; +} + +.devdocs__navigation { + list-style-type: none; + margin: 0; + padding: 0; +} + +.devdocs__navigation-item a { + display: block; + padding: 16px 24px; + box-shadow: inset -0.296em 0 0 rgba(0,80,130,0.2); + color: $gray; + font-size: 16px; + + &:hover { + background: $blue-medium; + color: $white; + } +} + +.devdocs__result { + @extend %container; + + margin: 0.5em 0; + padding: 10px 0; + + header { + overflow: hidden; + padding: 0 18px; + h1 { + clear: none; + float: left; + } + h1 a { + &:hover { + color: $blue-medium; + } + font-size: 18px; + color: $gray-dark; + } + h2 { + font-size: ( 12 / 15 ) * 1em; + clear: none; + color: $gray; + float: right; + margin: 8px 0 0; + } + } +} + +.devdocs__result-snippet { + p { + margin-bottom: 0; + } + margin: 0; + margin-top: 10px; + border-top: 1px solid lighten( $gray, 20% ); + padding: 9px 18px; + font-size: ( 13 / 15 ) * 0.8em; + background-color: $white; +} + +.devdocs__doc { + h1, h2, h3, h4, h5, h6 { + font-family: Merriweather, Georgia, "Times New Roman", Times, serif; + font-weight: 700; + line-height: 1.5em; + margin-bottom: 0.6em; + } + + h1 { + color: $blue-medium; + font-size: 3.157em; + line-height: 1.333; + } + + h2 { + font-size: 1.777em; + } + + pre { + padding: (12 / 15) * 1em; + background: $white; + background-color: $white; + } + + code { + font-size: (13 / 15) * 1em; + background-color: $white; + padding: 0.2em; + border-radius: 3px; + } + + pre > code { + background-color: $transparent; + } + + header { + @extend %container; + + padding : 1em; + + h2 { + font-size : ( 12 / 15 ) * 1em; + color : $gray-dark; + margin-bottom: 0; + + a { + float: right; + } + } + } + + .emoji { + height: 18px; + } + + .label { + $invert: $white; + font-weight: bold; + font-size: 12px; + padding: 1px 5px 2px 5px; + border-radius: 2px; + + &.status-awaiting-fixes { + background: #ea652d; + color: $invert; + } + + &.status-needs-review { + background: #fbc92f; + } + + &.status-ready-to-merge { + background: #d6fa82; + } + + &.status-in-progress { + background: #2880e2; + color: $invert; + } + } +} + +.design-assets__toggle { + float: right; +} + +.design-assets__group { + color: $gray-dark; +} + +.design-assets__group > .gridicon:hover { + fill: $gray; + cursor: pointer; +} + +// ========================================================================== +// Button component styles +// ========================================================================== + +.design-assets__button-row { + &:first-child { + margin-top: -16px; + } + .button { + margin-top: 16px !important; + margin-right: 16px !important; + } +} diff --git a/assets/stylesheets/sections/_domain-search.scss b/assets/stylesheets/sections/_domain-search.scss new file mode 100644 index 00000000000000..422d466a1deebf --- /dev/null +++ b/assets/stylesheets/sections/_domain-search.scss @@ -0,0 +1,290 @@ +// domain search + +.domain-search__content { + overflow: visible; + padding: 0 0 20px 0; + position: static; +} + +.domain-search-page-wrapper h2 { + @extend %heading; + margin: 0 0 10px 0; +} + +.domain-search-page-wrapper h3 { + color: $gray-dark; + font-size: 15px; + word-wrap: break-word; + + @include breakpoint( ">660px" ) { + font-size: 17px; + } +} + +// site redirect step + +.site-redirect-step { + padding: 0; + + fieldset { + clear: left; + } + + form.map-domain-step__form { + padding: 20px; + margin-bottom: 9px; + } + + p { + color: $gray-dark; + font-size: 13px; + font-weight: 600; + margin-bottom: 0; + opacity: 0.7; + } + + .domain-product-price { + @include breakpoint( ">660px" ) { + float: right; + margin-top: -5px; + } + } +} + +.site-redirect-step__domain-description { + @include breakpoint( ">660px" ) { + float: left; + margin-bottom: 20px; + } +} + +input.site-redirect-step__external-domain { + @include breakpoint( ">660px" ) { + float: left; + width: calc( 100% - 90px ); + } +} + +.site-redirect-step__go { + margin: 10px 0 0 0; + width: 100%; + + @include breakpoint( ">660px" ) { + float: right; + margin: 0; + width: 80px; + } +} + +// +// Google Apps +// + +// The `form` selector adds specificity to override the padding from the +// `.card` class. +form.google-apps-dialog { + padding: 0; + + .google-apps-dialog__product-details { + background: $gray-light; + padding: 24px 0; + text-align: center; + } + + .google-apps-dialog__product-name { + color: #888; + font-size: 25px; + font-weight: 100; + margin: 0; + } + + .google-apps-dialog__product-logo { + background: url('/calypso/images/upgrades/google-apps-logo.png'); + background-repeat: no-repeat; + background-size: contain; + display: inline-block; + height: 34px; + margin: 2px 7px 0 0; + text-indent: -999999px; + vertical-align: text-top; + width: 102px; + } + + .google-apps-dialog__header { + padding: 18px; + text-align: center; + + .google-apps-dialog__title { + color: $gray-dark; + font-weight: 600; + margin: 0; + } + } + + .google-apps-dialog__no-setup-required { + color: lighten( $gray-dark, 20% ); + } + + .google-apps-dialog__file-storage, + .google-apps-dialog__professional-email { + color: darken( $gray, 10% ); + font-size: 13px; + font-weight: 600; + line-height: 130%; + } + + .google-apps-dialog__professional-email { + border-bottom: 1px solid darken( $gray-light, 10% ); + display: inline-block; + margin-bottom: 8px; + padding-bottom: 12px; + } + + .google-apps-dialog__price-per-user { + color: $blue-medium; + font-size: 18px; + font-weight: 600; + } + + .google-apps-dialog__billing-period { + color: lighten( $gray, 10% ); + font-size: 12px; + text-transform: uppercase; + } + + .notice li { + list-style: disc; + } +} + +.google-apps-dialog__users-enter { + max-height: 0; + overflow: hidden; + transition: max-height 0.2s ease-in-out; +} + + +.google-apps-dialog__users-enter.google-apps-dialog__users-enter-active { + max-height: 300px; +} + +.google-apps-dialog__users { + border-bottom: 1px solid darken( $gray-light, 5% ); + display: block; + padding: 0 30px; + + h4 { + color: #7799ae; + margin-top: 30px; + margin-bottom: 4px; + } + + .google-apps-dialog__user-fields { + animation: google-apps-user-show 0.3s ease-in-out; + margin-bottom: 20px; + } + + .google-apps-dialog__user-email { + margin-bottom: 9px; + } + + .google-apps-dialog__user-first-name { + margin-bottom: 9px; + + @include breakpoint( ">660px" ) { + display: inline-block; + margin: 0 4px 0 0; + width: calc( 50% - 4px ); + } + } + + .google-apps-dialog__user-last-name { + @include breakpoint( ">660px" ) { + display: inline-block; + margin: 0 0 0 5px; + width: calc( 50% - 5px ); + } + } + + .google-apps-dialog__add-another-user-button { + border: 2px dashed lighten( $gray, 20% ); + color: $gray; + cursor: pointer; + margin: 0 0 30px; + padding: 12px 18px 12px 45px; + position: relative; + text-align: left; + width: 100%; + + &:before { + position: absolute; + left: 15px; + top: 6px; + @include noticon( '\f8b3', 60px ); + } + } +} + +@keyframes "google-apps-user-show" { + 0% { + max-height: 0px; + } + + 100% { + max-height: 150px; + } +} + +.google-apps-dialog__footer { + padding: 30px; + @include clear-fix; + + @include breakpoint( ">660px" ) { + padding: 18px; + } + + .google-apps-dialog__cancel-link { + color: $blue-medium; + display: block; + font-size: 13px; + text-align: center; + + @include breakpoint( ">660px" ) { + float: left; + line-height: 38px; + } + } + + .google-apps-dialog__continue-button { + @include breakpoint( "<660px" ) { + margin-bottom: 18px; + width: 100%; + } + + @include breakpoint( ">660px" ) { + float: right; + } + } + + .button { + width: 100%; + margin-top: 10px; + + @include breakpoint( ">660px" ) { + width: auto; + margin: 0 auto auto 10px; + } + + &:first-of-type { + margin-left: 0; + margin-top: 0; + &.is-primary { + margin-top: 10px; + + @include breakpoint( ">660px" ) { + margin-top: 0; + } + } + } + } +} diff --git a/assets/stylesheets/sections/_keyboard-shortcuts.scss b/assets/stylesheets/sections/_keyboard-shortcuts.scss new file mode 100644 index 00000000000000..740671f2d27b5c --- /dev/null +++ b/assets/stylesheets/sections/_keyboard-shortcuts.scss @@ -0,0 +1,71 @@ +/** + * The keyboard shortcuts menu + */ + +.dialog.keyboard-shortcuts .keyboard-shortcuts__title { + margin: 0; + text-align: center; + line-height: 1em; +} + +.keyboard-shortcuts__categories { + list-style: none; + margin: 0; + max-width: 620px; + color: $gray-dark; +} + +.keyboard-shortcuts__category { + display: inline-block; + width: 50%; + margin-bottom: 15px; + float: left; +} + +.keyboard-shortcuts__category-disabled { + color: $gray; +} + +.keyboard-shortcuts__site-navigation { + float: right; +} + +.keyboard-shortcuts__category h3 { + font-weight: bold; + margin-bottom: 10px; + margin-left: 88px; +} + +.keyboard-shortcuts__list { + list-style: none; + margin: 0; + font-size: 12px; +} + +.keyboard-shortcuts__list li { + clear: left; + margin-bottom: 8px; +} + +.keyboard-shortcuts__keys { + width: 80px; + float: left; + text-align: right; +} + +.keyboard-shortcuts__key { + background-color: $white; + border: solid 1px $gray; + padding: 0 5px; + min-width: 8px; + text-align: center; + border-radius: 5px; + box-shadow: 0 1px 1px $gray; + display: inline-block; + margin-right: 3px; +} + +.keyboard-shortcuts__description { + margin-left: 8px; + display: inline-block; +} diff --git a/assets/stylesheets/sections/_manage.scss b/assets/stylesheets/sections/_manage.scss new file mode 100644 index 00000000000000..35d9cf8b0a8d68 --- /dev/null +++ b/assets/stylesheets/sections/_manage.scss @@ -0,0 +1,28 @@ +/* Status indicators */ +.corner-status { + width: 50px; + height: 50px; + transform: rotate(45deg); + + position: absolute; + top: -25px; + right: -25px; +} +.corner-status.connected { background: #47b603; } +.corner-status.disconnected, .corner-status.unapproved { background: #ffbb00; } + +.noticon.status-checkmark, .noticon.status-warning { + position: absolute; + top: 0; + right: 0; + color: #fff; + font-size: 22px; + width: auto; + height: auto; +} + +.noticon.status-warning { + font-size: 13px; + top: 4px; + right: 3px; +} diff --git a/assets/stylesheets/sections/_menus.scss b/assets/stylesheets/sections/_menus.scss new file mode 100644 index 00000000000000..aaa110cfde5d0b --- /dev/null +++ b/assets/stylesheets/sections/_menus.scss @@ -0,0 +1,1034 @@ +/** + * Menus: Mixins + */ +@mixin menus-depth-levels( $max-depth, $extra-selector:"" ) { + @for $i from 1 through $max-depth { + &.depth-#{ $i } #{ $extra-selector } { + margin-left: #{ $i * 2 }rem; + } + } +} +@mixin menus-depth-levels-undo( $max-depth, $extra-selector:"" ) { + @for $i from 1 through $max-depth { + &.depth-#{ $i } #{ $extra-selector } { + margin-left: #{ $i * -2 }rem; + } + } +} + + +/** + * Menus: Empty Content + */ +.manage-menus .empty-content { + clear: both; +} + +/** + * Menus: Placeholders + */ +.menus__pickers, +.menus__menu-header, +.menus__items { + .placeholder-text { + color: transparent; + background-color: lighten( $gray, 30% ); + animation: loading-fade 1.6s ease-in-out infinite; + } +} + +.menus__picker label .placeholder-text { + font-size: 10px; +} + +.menus__picker-select-placeholder { + display: block; + padding: 23px 40px 10px 52px; + + .placeholder-text { + font-size: 12px; + } +} + + + + + +/** + * Menus: Pickers + */ +.menus__pickers { + background-color: lighten( $gray, 30% ); + background-size: cover; + width: 100%; + box-sizing: border-box; + overflow: hidden; + + padding: 3%; + box-shadow: 0 -2px 0 lighten( $gray, 10% ) inset; +} + +.menus__pickers-conjunction { + float: left; + height: 55px; + font-size: 0.8em; + line-height: 4.6; + + width: 10%; + padding: 0; + margin: 0; + text-align: center; + + @include breakpoint( "<480px" ) { + width: 100%; + height: 30px; + line-height: 2.3; + } +} + +.menus__picker { + width: 45%; + float: left; + position: relative; + background: $white; /* required for -moz-appearance below */ + + @include breakpoint( "<480px" ) { + width: 100%; + } + + label, + select { + display: block; + width: 100%; + cursor: pointer; + } + + label { + pointer-events: none; /* click through :D */ + font-size: 0.8em; + color: $gray; + position: absolute; + top: 10px; + left: 10px; + padding: 0px 30px 20px 42px; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + width: calc(100% - 20px); + + + &:before { + position: absolute; + left: 1px; + top: 1px; + color: $blue-dark; + } + + &:after { + @include noticon( '\f431', 22px ); + position: absolute; + top: 7px; + right: 0; + color: $blue-medium; + } + } + + &.is-location label:before { + @include noticon( '\f8a9', 32px ); + } + + &.is-menu label:before { + @include noticon( '\f505', 32px ); + } + + select { + background: $white; + height: 55px; + border: none; + border-radius: 0; + + -webkit-appearance: none; + padding: 20px 40px 5px 52px; + + &::-ms-expand { + display: none; /* Remove arrow in IE */ + } + } +} + + +/** + * Menu: Header + */ +.menus__menu-header { + display: flex; + flex-direction: row; + margin: 20px 0; + + .menus__menu-name { + flex: 1 1 auto; + width: 0%; /* Firefox 35 and IE 10 fix */ + } + + .menus__menu-actions { + flex: 0 0 auto; + margin-left: auto; + } +} + +.menus__menu-name { + font-size: 1.6em; + font-weight: 200; + float: left; + + // The rendered field + span.is-editable { + + span { + display: block; + float: left; + max-width: 90%; /* should be less to avoid a bug on touch + tag that auto-closes the area, but ellipsis wouldn't work */ + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + + a { + margin-left: 4px; + cursor: pointer; + &:before { + @include noticon( '\f411', 16px ); + color: darken( $gray, 10% ); + vertical-align: baseline; + } + } + } + + // The same field, edited + input.is-editable { + margin: -20px -30px -20px 0; + font-size: inherit; + font-weight: inherit; + width: calc(100% - 40px); + margin-right: 40px; + } +} + +.menus__menu-actions { + float: right; + + .button { + margin-left: 0.7em; + + &.noticon:before { + line-height: 1.35; + color: $gray-dark; + + /* Reset noticon parts overridden by button */ + font-size: 16px; + font-weight: 400; + } + } +} + + +/** + * Menu: List + */ +.menus__items { + margin: 0; + clear: both; + list-style-type: none; + background-color: lighten( $gray, 30% ); + + ul { + padding: 0; + + &.depth-0 { + margin-left: 0; + } + } +} + +.menus__menu-item { + @include menus-depth-levels( 7 ); + + display: flex; + flex-direction: row; + color: $blue-dark; + background-color: $white; + text-decoration: none; + border-bottom: 1px solid lighten( $gray, 30% ); + border-left: 1px solid lighten( $gray, 30% ); + padding: 17px 20px 16px 16px; + font-size: 13px; + cursor: default; + position: relative; + z-index: 2; + + .menu-item-name { + flex: 1 1 auto; + color: $gray-dark; + font-size: 1.1em; + line-height: 1.5em; + font-family: inherit; + text-align: left; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + + &:before { + font-size: 16px; + margin-right: 12px; + color: $blue-medium; + vertical-align: -2px; + } + + &.noticon-placeholder:before { + color: transparent; + background-color: lighten( $gray, 30% ); + animation: loading-fade 1.6s ease-in-out infinite; + + vertical-align: -4px; + font-size: 19px; + } + } + + .action-tray { + flex: 0 0 auto; + float: right; + margin-right: -8px; /* compensate buttons padding, more universal */ + transition: background 200ms ease-in, color 50ms ease-in; + + /* Buttons */ + button { + margin-left: 1em; + margin-top: -8px; + margin-bottom: -8px; + font-size: inherit; + line-height: 1.45; + } + + .menu-item-action { + float: left; + color: darken( $gray, 10% ); + margin: -5px 0 -5px; + padding: 8px 6px 8px; + text-transform: uppercase; + font-size: 0.85em; + font-weight: 500; + vertical-align: top; + cursor: pointer; + + transition: all 200ms ease-out; + border-radius: 100%; + + text-indent: -6666em; + width: 22px; /* Fix: Firefox won't respect margins with text-indent on otherwise. */ + + /* Icon Buttons */ + &:before { + content: ""; + color: $blue-medium; + float: left; + font-size: 16px; + text-indent: 0; + width: 22px; + } + + &.edit:before { + @include noticon( '\f411', 16px ); + } + + &.add:before { + @include noticon( '\f510', 16px ); + } + + &.cancel:before { + @include noticon( '\f405', 16px ); + font-size: 19px; + margin-bottom: -3px; /* Sigh it's smaller... */ + } + + &.move { + color: $blue-medium; + text-indent: 0; + width: auto; + + &:hover { + color: $blue-light; + border-radius: 0; + background: transparent; + } + &:before { + content: none; + } + } + + &:hover, + &:focus { + color: $white; + background: $blue-medium; + } + + &:hover:before, + &:focus:before { + color: $white; + } + } + } + + /** + * Menu item is selected + */ + &.is-selected { + background: $blue-medium; + padding: 6px; + border-bottom: 0; /* remove gap */ + + .noticon { + color: $white; + padding: 14px 16px 5px 10px; + } + + input { + width: calc(100% - 70px); + padding: 12px 14px; + border: 0; + color: $blue-dark; + font-size: 14px; + } + } + + /** + * Menu 3-pronged lander areas + */ + &.is-lander { + background: lighten( $gray-light, 2% ); + border-left: 1px solid lighten( $gray, 30% ); + z-index: 1; + + &:hover { + background: $blue-medium; + } + &:hover span, + &:hover span:before { + color: $white; + } + + span { + color: $blue-dark; + font-size: 1.1em; + line-height: 1.5em; + font-family: inherit; + + &:before { + font-size: 16px; + margin-right: 12px; + color: $blue-medium; + vertical-align: -2px; + } + } + } + + /** + * Item target when dragging with mouse + */ + &.is-dragdrop-target { + background: $gray-light; + border: 1px dashed lighten( $gray, 20 ); + margin-top: 10px; + margin-bottom: 10px; + + span { + visibility: hidden; + } + + .add, + .edit { + display: none; + } + } + + /** + * Hide drag 'ghost' image, because it makes the drop + * target hard to see + */ + &:-webkit-drag { + visibility: hidden; + + div { + display: none; + } + } + + /** + * Menu is Empty, show special add icon + */ + &.is-empty { + margin-left: calc(100% - 61px); + padding-left: 13px; + } + + /** + * Item is to be deleted, pending user confirmation + */ + &.is-deleted { + background: $gray-light; + + .menu-item-name, + .menu-item-name::before { + color: $gray; + } + } + + &.is-corrupt { + border-left: 5px solid $alert-yellow; + } +} + + +/** + * Menu: add menu item label + */ +.menus__add-item-footer-label { + float: right; + padding: 10px 25px 2px 0; + + color: $gray; + font-size: 10px; + text-transform: uppercase; + + animation: menus__fade-from-bottom 1.0s ease-in-out; + + &:after { + content: "\2191"; /* Up arrow */ + color: $blue-medium; + font-size: 16px; + padding: 0 0 0 10px; + } +} + + +/** + * Menu: Edit Item & New Item views + */ +.menus__menu-item-open-container { + background: $gray-light; + + @include breakpoint( "<480px" ) { + &.is-panel-left { + .menu-item-options { + display: none !important; + } + } + + &.is-panel-right { + .menu-item-options { + width: auto !important; + left: 0 !important; + border: 0 !important; + } + } + } + + // If done properly, might be an alternative for mobile. + // Seems not working properly with -webkit-perspective turned on. + /*@include responsive( mobile ) { + z-index: 190; // Higher than masterbar? + border: 0; + padding: 80px 0 0; + background: rgba(244, 248, 250, 0.9); + + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + }*/ +} + +.menus__menu-item-open { + @include menus-depth-levels( 7 ); + @include menus-depth-levels-undo( 7, ".editable-item-content" ); + + display: block; + color: $blue-dark; + background-color: $white; + text-decoration: none; + border-left: 1px solid lighten( $gray, 30% ); + + &:before { + /* The top arrow */ + margin-top: -17px; + margin-left: 15px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + border-color: rgba(255, 255, 255, 0); + border-bottom-color: #ffffff; + border-width: 9px; + z-index: 2; + } + + .editable-item-content { + $editable-item-options-width: 75%; + + background: $white; + border-top: 1px solid lighten( $gray, 30% ); + border-bottom: 1px solid lighten( $gray, 30% ); + + /** + * General + */ + .separated { + border-bottom: 1px solid lighten( $gray, 30% ); + } + + .separated:after { + content: " "; + display: block; + height: 0; + clear: both; + } + + input:not([type='radio']):not([type='checkbox']) { + display: block; + font-size: 14px; + margin: -1px 0; + transition: all 200ms ease-out; + } + + /** + * Menu Item Name + */ + .menus__menu-item-form-name { + display: flex; + flex-direction: row; + + label { + flex: 0 0 auto; + padding: 9px 12px; + + display: block; + line-height: 2.4; + color: $gray; + font-size: 10px; + text-transform: uppercase; + } + + input { + flex: 1 1 auto; + width: $editable-item-options-width; + background: $gray-light; + } + } + + /** + * Menu Item Types + */ + .menus__menu-item-form-types { + list-style: none; + margin: 0; + position: relative; + width: 136px; + + &:hover { + border-top-color: $gray-light; + border-bottom-color: $gray-light; + } + + @include breakpoint( "<480px" ) { + width: 100%; + } + + li { + border: 0; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + border-right: 1px solid lighten( $gray, 30% ); + transition: all 200ms ease-in-out, color 150ms ease-in-out; + + & > label { + font-family: inherit; + font-size: 14px; + padding: 16px 12px; + color: $gray-dark; + line-height: 1.3; + display: block; + text-align: left; + margin-bottom: -1px; + font-weight: 400; + transition: all 250ms ease-in-out, color 150ms ease-in-out; + cursor: pointer; + -webkit-font-smoothing: inherit; /* Fix the noticon change */ + -moz-osx-font-smoothing: inherit; /* Fix the noticon change */ + + &:before { + color: lighten( $gray, 20% ); + font-size: 16px; + margin-right: 8px; + vertical-align: -3px; + transition: all 250ms ease-in-out, color 150ms ease-in-out; + } + + &:hover { + color: $blue-medium; + + &:before { + color: $blue-medium; + } + } + } + + /** + * Selected states + */ + &.is-selected { + border-top-color: lighten( $gray, 30% ); + border-bottom-color: lighten( $gray, 30% ); + border-right-color: $white; + color: $gray-dark; + + @include breakpoint( "<480px" ) { + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + } + + &:first-child { + border-top-color: $white; + } + + &:last-child { + border-bottom-color: $white; + } + + & > label { + color: $blue-medium; + + &:before { + color: $blue-medium; + } + } + } + } + } + + .menus__types-and-options-container { + position: relative; + + .menu-item-options { + position: absolute; + right: 0; + top: 0; + bottom: 0; + width: $editable-item-options-width; + + background: $white; + font-size: 14px; + padding: 10px 13px; + + .menu-item-tag-container { + margin: 10px; + + .menu-item-tag { + display: inline-block; + padding: 0 3px; + background-color: lighten( $gray, 20% ); + color: $white; + font-size: 10px; + border-radius: 3px; + margin-left: 5px; + text-transform: uppercase; + vertical-align: middle; + letter-spacing: 0.02em; + + &:first-of-type { + margin-left: 0; + } + } + } + + + .menu-item-back-button { + display: none; + transition: 200ms all ease-in; + + a { + display: block; + font-family: inherit; + font-size: 14px; + color: lighten( $gray-dark, 5% ); + text-align: left; + line-height: 1.3; + background: $white; + padding: 16px 12px 15px; + margin: -10px -13px 10px; + border-bottom: 1px solid lighten( $gray, 30% ); + -webkit-font-smoothing: inherit; + + &:before { + color: $blue-light; + font-size: 16px; + margin-right: 8px; + vertical-align: -3px; + } + } + + @include breakpoint( "<480px" ) { + display: block; + } + } + + .menu-item-form-label { + float: none; + width: auto; + border: 0; + + display: block; + padding: 0 0 10px 0; + color: $gray; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + } + + .menu-item-form-address { + margin-bottom: 1rem; + } + + input[type='checkbox'] + label { + margin-left: 4px; + color: $gray-dark; + } + + li { + padding: 2px 0; + + input[type=radio] + label { + margin-left: 4px; + transition: all 200ms ease-out; + color: $gray-dark; + + &:hover { + color: $blue-medium; + } + } + } + + form > label { + cursor: pointer; + } + + input:not([type='radio']):not([type='checkbox']) { + width: 95%; + } + + .is-empty-content { + color: $gray; + + a { + color: $gray; + text-decoration: underline; + } + } + + .search-container { + position: relative; + + .noticon-search { + position: absolute; + left: 0; + padding: 9px 9px; + } + + .search-box { + right: 0; + width: 100%; + height: 35px; + margin-bottom: 1rem; + padding: 5px 5px 5px 30px; + background: $white; + + -webkit-appearance: none; + } + } + + // Scroll + overflow: hidden; + overflow-y: auto; + + &::-webkit-scrollbar { + width: 9px; + height: 9px; + } + &::-webkit-scrollbar-button:start:decrement, + &::-webkit-scrollbar-button:end:increment { + display: block; + height: 0; + background-color: transparent; + } + &::-webkit-scrollbar-track-piece { + background-color: transparent; + -webkit-border-radius: 0; + -webkit-border-bottom-right-radius: 8px; + -webkit-border-bottom-left-radius: 8px; + } + &::-webkit-scrollbar-thumb:vertical, + &::-webkit-scrollbar-thumb:horizontal { + background-color: lighten( $gray, 20% ); + -webkit-border-radius: 8px; + border: 1px solid $white; + } + } + } + + + /** + * A notice for unsupported item types + */ + .unsupported-notice { + padding: 1em; + + h1 { + color: $gray-dark; + font-size: 16px; + margin-bottom: 1em; + } + + p, small { + color: $gray; + } + + p { + font-size: 14px; + margin-bottom: 0; + } + } + } +} + + +/** + * Menu: Item Action Buttons + */ +.menus__menu-item-actions { + clear: both; + padding: 0.5em; + border-top: 1px solid lighten( $gray, 30% ); + text-align: right; + + .button { + margin-left: 0.5em; + line-height: 1.3em; + + &.noticon { + // Noticon override + font-family: inherit; + -webkit-font-smoothing: inherit; + color: #6f7a88; // Button color? + + &:hover { + color: #324155; // Button color? + } + + &:before { + font-size: 16px; + vertical-align: -3px; + margin: 0px -3px -1px; + } + } + } +} + + +/** + * Menu: animations, pure CSS fade-ins + */ +@keyframes menus__fade-from-bottom { + 0% { + opacity: 0.0; // Let's add a small delay + } + 20% { + opacity: 0.0; + transform: translateY(10px); + } + 70% { + opacity: 1.0; + } + 100% { + opacity: 1.0; + transform: none; + } +} + + +/** + * Menu: animations, ReactCSSTransitionGroup + */ +.menus__droptarget-slidevertical-enter, +.menus__droptarget-slidevertical-leave { + transform: translateZ(0); /* Turns acceleration on if possible */ + + &.menus__droptarget-slidevertical-enter-active, + &.menus__droptarget-slidevertical-leave-active { + /* Fix for Safari / Safari Mobile: the transition doesn't work unless it's on the *-active + * Reference: + * https://github.com/facebook/react/issues/2227 + * https://github.com/facebook/react/issues/2104 + */ + transition: margin 200ms ease-out, opacity 200ms ease-out; + } + + &.is-lander { + span { + opacity: 0.0; + } + + &:hover { + background: inherit; + color: inherit; + } + } +} + +.menus__droptarget-slidevertical-enter { + margin-top: -55px; + opacity: 0.0; + + &.is-position-before { + margin-top: 0; + margin-bottom: -55px; + } + + &.menus__droptarget-slidevertical-enter-active { + margin-top: 0; + opacity: 1.0; + + &.is-position-before { + margin-bottom: 0; + } + } +} + +.menus__droptarget-slidevertical-leave { + margin-top: 0; + opacity: 1.0; + + &.is-position-before { + margin-bottom: 0; + } + + &.menus__droptarget-slidevertical-leave-active { + margin-top: -55px; + opacity: 0.0; + + &.is-position-before { + margin-top: 0; + margin-bottom: -55px; + } + } +} diff --git a/assets/stylesheets/sections/_notifications.scss b/assets/stylesheets/sections/_notifications.scss new file mode 100644 index 00000000000000..c542b6af3a77ec --- /dev/null +++ b/assets/stylesheets/sections/_notifications.scss @@ -0,0 +1,59 @@ +/** + * Notifications + */ + +#wpnt-notes-panel2 { + position: fixed; + top: 47px; + right: 0; + bottom: 0; + min-width: 400px; + + @include breakpoint( "<480px" ) { + width: 100%; + min-width: 0; + } + + &.wpnt-open { + opacity: 1; + pointer-events: auto; + } + + &.wpnt-closed { + opacity: 0; + pointer-events: none; + + @include breakpoint( "<480px" ) { + display: none; + } + } +} + +#wpnt-notes-panel2.wide { + border-left: 0px; + box-shadow: none; +} + +html.touch #wpnt-notes-panel2 { + overflow-y: scroll; + -webkit-overflow-scrolling: touch; +} + +iframe#wpnt-notes-iframe2 { + width: 400px; + height: 100%; + + @include breakpoint( "<480px" ) { + width: 100%; + } +} + +iframe#wpnt-notes-iframe2.wide { + width: 410px; + + @include breakpoint( ">960px" ) { + &.widescreen { + width: 810px; + } + } +} diff --git a/assets/stylesheets/sections/_nux-welcome.scss b/assets/stylesheets/sections/_nux-welcome.scss new file mode 100644 index 00000000000000..b339a2d6121bec --- /dev/null +++ b/assets/stylesheets/sections/_nux-welcome.scss @@ -0,0 +1,164 @@ +.NuxWelcome { + background: none; + position: relative; + padding: 24px 18px 0; + margin-bottom: 66px; + box-shadow: none; + &:before { + content: ''; + position: absolute; + top: 100%; + left: 0; + right: 0; + height: 1px; + margin-top: 35px; + z-index: -1; + background: linear-gradient(to right, fade-out(lighten( $gray, 20% ), 1) 0%, lighten( $gray, 20% ) 20%, lighten( $gray, 20% ) 80%, fade-out(lighten( $gray, 20% ), 1) 100%); + } + &:after { + @include noticon( '\f205', 22px ); + position: absolute; + top: 100%; + left: 50%; + height: 22px; + margin-left: -11px; + margin-top: 24px; + color: $gray; + padding: 0 8px; + background-color: lighten( $gray, 30% ); + visibility: visible; + } + .close-button { + padding: 6px; + } +} + +.NuxWelcomeMessage__title { + color: $gray-dark; + font-family: $serif; + font-weight: 600; + font-size: 24px; + line-height: 32px; + margin-bottom: 12px; + padding-right: 24px; +} + +.NuxWelcomeMessage__primary-content { + font-size: 16px; + line-height: 24px; + // margin-bottom: 20px; + p { + margin-bottom: 20px; + } + .button { + display: block; + width: 100%; + padding: 12px 24px; + margin-bottom: 8px; + text-align: center; + } + img { + display: none; + @media only screen and (max-width: 930px) { + max-height: 106px; + } + } +} + +.NuxWelcomeMessage__intro { + a { + color: $blue-medium; + text-shadow: 1px 0 lighten( $gray, 30% ), 2px 0 lighten( $gray, 30% ), -1px 0 lighten( $gray, 30% ), -2px 0 lighten( $gray, 30% ); + background-image: linear-gradient(to bottom, transparent 50%, $blue-medium 50%); + background-repeat: repeat-x; + background-size: 2px 2px; + background-position: 0 85%; + } +} + +.NuxWelcomeMessage__label { + color: $gray-dark; + font-size: 14px; + line-height: 18px; + font-weight: 600; + margin-bottom: 10px; +} + +.NuxWelcomeMessage__list { + list-style-position: inside; + margin-left: 0; + li { + font-size: 14px; + line-height: 18px; + margin-bottom: 6px; + } +} + +@include breakpoint( ">660px" ) { + + .NuxWelcome { + padding: 12px 0 0; + .close-button { + &:before, + &:after { + content: ''; + position: absolute; + top: 0; + right: 0; + } + &:before { + width: 108px; + height: 1px; + background: linear-gradient(to right, fade-out(lighten( $gray, 20% ), 1) 0%, lighten( $gray, 20% ) 100%); + } + &:after { + width: 1px; + height: 108px; + background: linear-gradient(to bottom, lighten( $gray, 20% ) 0%, fade-out(lighten( $gray, 20% ), 1) 100%); + } + } + .notouch & { + .close-button { + &:before, + &:after { + transition: transform 0.2s ease; + } + &:before { + transform-origin: right; + } + &:after { + transform-origin: top; + } + &:hover { + &:before { + transform: scaleX(1.4); + } + &:after { + transform: scaleY(1.4); + } + } + } + } + } + + .NuxWelcomeMessage__title { + clear: none; + } + + .NuxWelcomeMessage__primary-content { + margin-bottom: 0; + .button { + display: inline-block; + width: auto; + padding: 7px 24px; + margin-right: 24px; + } + img { + display: block; + float: right; + width: (212 / 960) * 100%; + margin: 6px 48px 24px 12px; + } + } + +} diff --git a/assets/stylesheets/sections/_plugins.scss b/assets/stylesheets/sections/_plugins.scss new file mode 100644 index 00000000000000..08da4e7d8076d8 --- /dev/null +++ b/assets/stylesheets/sections/_plugins.scss @@ -0,0 +1,56 @@ +// ========================================================================== +// .plugins +// +// section-specific styles +// ========================================================================== + + +// .toolbar-bulk customizations +.toolbar-bulk__toggle { + .plugins & { + color: $blue-wordpress; + margin: -49px 40px 0 0; + z-index: 21; + + @include breakpoint( '>660px' ) { + margin: -39px 84px 0 0; + } + &:hover { + color: $link-highlight; + } + } +} + +.plugin__page .plugin-icon { + margin-bottom: 20px; +} + +.plugin__page.is-wpcom .plugin-icon { + margin-bottom: 0; +} + +.section-group-title { + margin-bottom: 5px; + font-size: 13px; + text-transform: uppercase; + + .plugin__information + &, + .card.is-compact + & { + margin-top: 32px; + } +} + +.plugins__list, +.toolbar-bulk.is-all-sites { + margin-bottom: 20px; +} + +.plugins__list-header { + background: $white; + color: $gray-dark; + font-size: 12px; + box-shadow: 0 0 0 1px transparentize( lighten( $gray, 20% ), .5 ), + 0 1px 2px lighten( $gray, 30% ); + padding: 14px 24px; + text-transform: uppercase; +} diff --git a/assets/stylesheets/sections/_post-relative-time-status.scss b/assets/stylesheets/sections/_post-relative-time-status.scss new file mode 100644 index 00000000000000..54e170e5a45458 --- /dev/null +++ b/assets/stylesheets/sections/_post-relative-time-status.scss @@ -0,0 +1,40 @@ +.post-relative-time-status { + .time, + .status { + display: inline-block; + margin-right: (11 / 12) * 1em; + } + + .time .time-text { + display: inline-block; + &::first-letter { + text-transform: capitalize; + } + } + + .status .status-text { + text-transform: capitalize; + } + + .noticon { + display: inline-block; + font-size: (13 / 12) * 1em; + margin-right: (3 / 13) * 1em; + } + + // Apply colors on /posts/* cards + .posts__list & { + .is-sticky { + color: $orange-jazzy; + } + .is-pending { + color: $alert-yellow; + } + .is-scheduled { + color: $blue-medium; + } + .is-trash { + color: $alert-red; + } + } +} diff --git a/assets/stylesheets/sections/_posts-controls.scss b/assets/stylesheets/sections/_posts-controls.scss new file mode 100644 index 00000000000000..4f604125e14a54 --- /dev/null +++ b/assets/stylesheets/sections/_posts-controls.scss @@ -0,0 +1,83 @@ +/** + * Post Controls + */ +.post-controls { + box-sizing: border-box; + background-color: $gray-light; + overflow: hidden; + position: relative; + width: 100%; + height: (43 / 15) * 1em; +} + +.post-controls__pane { + // Flex + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: flex-start; + align-content: flex-start; + align-items: stretch; + // Normal + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + list-style: none; + font-size: (14 / 15) * 1em; + margin: 0; + transition: transform 0.2s ease, opacity 0.2s ease; + > li { + // Flex + flex-grow: 1; + flex-shrink: 0; + flex-basis: auto; + // Normal + box-sizing: border-box; + text-align: center; + border-left: solid 1px lighten( $gray, 30% ); + &:first-child { + border-left: none; + } + a { + display: block; + box-sizing: border-box; + font-size: inherit; + padding: (11 / 14) * 1em 0; + &:hover { + cursor: pointer; + } + .gridicon{ + position: relative; + top: 3px; + margin-right: 6px; + } + } + } +} + + + +.post-controls__more-options { + transform: scale(0); + opacity: 0; + pointer-events: none; +} + +// @todo should be moved, together with its logic, to "post-controls" not "post" +.post { + // Show More Options + &.show-more-options { + .post-controls__main-options { + transform: scale(0); + opacity: 0; + pointer-events: none; + } + .post-controls__more-options { + transform: scale(1); + opacity: 1; + pointer-events: auto; + } + } +} diff --git a/assets/stylesheets/sections/_posts.scss b/assets/stylesheets/sections/_posts.scss new file mode 100644 index 00000000000000..26818a6a9569da --- /dev/null +++ b/assets/stylesheets/sections/_posts.scss @@ -0,0 +1,349 @@ +/** + * Posts + */ + +.posts__list { + + .post { + position: relative; + padding: 0; + margin-bottom: (24 / 15) * 1em; + @include breakpoint( "<660px" ) { + font-size: 13px; + } + } + + .post__body { + background-color: $white; + } + + .post-attribution, + .post__content, + .post__info { + box-sizing: border-box; + padding: (14 / 10) * 1rem; // from _reset.scss: html { font-size: 62.5% } (or 10px), hence base 10 + @include breakpoint( ">660px" ) { + padding: (24 / 10) * 1rem; + } + } + + .post-attribution { + width: 100%; + font-size: (14 / 15) * 1em; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + color: $gray; + a { + color: inherit; + } + span:first-child { + .post-attribution-avatar { + margin-left: 0; + } + } + + .post__content { + padding-top: 0; + } + @include breakpoint( ">660px" ) { + padding: (16 / 10) * 1rem (24 / 10) * 1rem; + } + } + + .post-attribution-avatar { + width: (24 / 14) * 1em; + height: (24 / 14) * 1em; + margin: 0 (5 / 14) * 1em 0 (7 / 14) * 1em; + vertical-align: middle; + display: inline-block; + &.is-rounded { + border-radius: 50%; + } + } + + .post__content { + padding-top: (16 / 10) * 1rem; + padding-bottom: (8 / 10) * 1rem; + margin: 0; + overflow: hidden; + + .post__info { + padding-top: 0; + } + @include breakpoint( ">660px" ) { + padding-bottom: (12 / 10) * 1rem; + } + } + + .post__content-link { + display: block; + } + + .post__title-link { + + .post__excerpt { + margin-top: (7 / 15) * 1em; + } + + .featured-standard { + margin-top: (13 / 15) * 1em; + + .post__excerpt { + margin-top: (7 / 15) * 1em; + } + } + } + + .post__title { + color: $gray-dark; + font-size: (24 / 15) * 1em; + line-height: (32 / 24) * 1em; + font-family: $serif; + font-weight: 700; + } + + .post__excerpt { + color: darken( $gray, 20 ); + font-size: (16 / 15) * 1em; + line-height: (24 / 16) * 1em; + font-family: $serif; + p { + margin: 0; + } + } + + .post__quote { + background: none; + font-family: $serif; + font-style: italic; + padding: 0; + margin: 0; + border-radius: 0; + } + + .post__info { + width: 100%; + font-size: (14 / 15) * 1em; + padding-top: (16 / 10) * 1rem; + padding-bottom: (16 / 10) * 1rem; + color: $gray; + overflow: hidden; + @include breakpoint( ">660px" ) { + padding-top: (20 / 10) * 1rem; + padding-bottom: (20 / 10) * 1rem; + } + } + + .post-relative-time-status { + float: left; + margin: 0; + .noticon { + font-size: (16 / 14) * 1em; + margin: (3 / 13) * 1em (3 / 13) * 1em 0 0; + } + a { + color: inherit; + } + small { + font-size: 0.9em; + color: lighten( $gray, 10% ); + } + } + + .post__meta { + float: right; + margin: 0; + list-style: none; + box-sizing: border-box; + li { + display: inline-block; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + margin-left: (15 / 14) * 1em; + color: $gray; + vertical-align: top; + &:first-child { + margin-left: 0; + } + a { + color: inherit; + &:before { + @extend %noticon; + font-size: (21 / 14) * 1em; + vertical-align: top; + } + &.is-empty { + .gridicon { + color: lighten( $gray, 20% ); + } + } + .gridicon{ + position: relative; + top: 6px; + } + } + span { + display: inline-block; + margin: (1 / 14) * 1em 0 0 (3 / 14) * 1em; + } + } + } + + // ---- Image Elements ---- + .image-large-format { + background-color: $gray-light; + // Flex + display: flex; + flex-wrap: nowrap; + align-content: flex-start; + .image-item { + box-sizing: border-box; + max-height: 100%; + padding: 0 (6 / 10) * 1rem; + flex: 1 0 auto; + } + .image-item-media { + vertical-align: bottom; + } + } + + .post__header { + + .post__content-link { + .image-large-format { + margin-top: (16 / 10) * 1rem; + } + } + } + + // NOTE: Gallery & Image single are large formats + .image-gallery { + padding: (6 / 10) * 1rem (8 / 10) * 1rem; + // Flex + flex-direction: row; + justify-content: flex-start; + align-items: center; + @include breakpoint( ">660px" ) { + padding: (6 / 10) * 1rem (18 / 10) * 1rem; + } + } + + .image-single { + height: (226 / 15) * 1em; + background-size: cover; + background-repeat: no-repeat; + background-position: center; + @include breakpoint( ">960px" ) { + background-size: contain; + } + } + + // NOTE: Standard is meant to be inline with excerpt on standard posts + .featured-standard { + float: right; + width: (2 / 5) * 100%; + max-height: (136 / 15) * 1em; + margin: 0 0 (14 / 15) * 1em (14 / 15) * 1em; + overflow: hidden; + img { + display: block; + } + @include breakpoint( ">660px" ) { + margin: 0 0 (24 / 15) * 1em (24 / 15) * 1em; + } + @include breakpoint( ">960px" ) { + margin-bottom: 0; + } + } + + // ---- Post Variations ---- + .post { + // Protected + &.is-protected { + .post__title { + &:before { + @include noticon( '\f470', 1em ); + color: $gray; + margin-right: (4 / 24) * 1em; + } + } + } + // Placeholder + &.is-placeholder { + .post__time { + &:before { + content: ''; + margin-right: 0; + } + } + .post-attribution-avatar { + display: inline-block; + background-color: lighten( $gray, 30% ); + } + } + } + + // ---- Placeholder helpers ---- + .placeholder-text { + color: transparent; + background-color: lighten( $gray, 30% ); + animation: loading-fade 1.6s ease-in-out infinite; + } + +} + +.post__header { + // Optical alignment of text to base grid + padding: 14px 16px 0; + + @include breakpoint( ">660px" ) { + padding: 14px 24px 0; + } +} +.post .site-icon { + position: absolute; + top: 16px; + left: 16px; + @include breakpoint( ">660px" ) { + left: 24px; + } +} +.post__site-title { + color: darken( $gray, 20 ); + display: block; + font-size: 14px; + line-height: 38px; + margin-right: 12px; + padding-left: 48px; + + a { + color: darken( $gray, 20 ); + } +} +.post__header.has-author { + // Vertically position the title + .post__site-title { + line-height: 1.4; + } +} +.post__author { + display: block; + color: $gray; + font-size: 12px; + padding-left: 48px; +} + + +/* RTL */ +.rtl .posts__list { + //smaller font, let's use Tahoma + .post__quote { + font-family: $sans-rtl; + } + //we can use the default sans for titles + .post__title { + font-family: $sans; + } +} + +:lang(he) .rtl .posts__list { + .post__quote { + font-family: $sans; + } +} diff --git a/assets/stylesheets/sections/_sharing.scss b/assets/stylesheets/sections/_sharing.scss new file mode 100644 index 00000000000000..5c0460379b6221 --- /dev/null +++ b/assets/stylesheets/sections/_sharing.scss @@ -0,0 +1,1175 @@ +$color-facebook: #39579a; +$color-twitter: #55ACEE; +$color-gplus: #df4a32; +$color-tumblr: #35465c; +$color-linkedin: #0976b4; +$color-path: #df3b2f; +$color-instagram: #517fa4; +$color-eventbrite: #ff8000; +$color-stumbleupon: #eb4924; +$color-reddit: #5f99cf; +$color-pinterest: #cc2127; +$color-pocket: #ee4256; +$color-email: #f8f8f8; +$color-print: #f8f8f8; + +.sharing-settings { + // labels, checkboxes, radio + + label label { + margin: 0; + } + + select { + font-size: 18px; + } + + input[type='number'] { + width: 50px; + height: 20px; + padding: 0 0 1px 2px; + } + + h4 { + font-size: 18px; + margin-bottom: 0.5em; + } + + @include breakpoint( "<660px" ) { + padding: 0 4em; + } + + @include breakpoint( "<480px" ) { + padding: 0 0.25em; + } +} + +.sharing-settings.sharing-connections { + @include breakpoint( "<480px" ) { + padding: 16px 0; + } + + h2 { + font-size: 20px; + margin-bottom: 10px; + } + + .sharing-link p { + margin-bottom: 1em; + } + + .button.is-warning { + background: darken( $alert-yellow, 3% ); + border-color: darken( $alert-yellow, 10% ); + color: $white; + + &:hover { + border-color: darken( $alert-yellow, 15% ); + } + + &:focus { + border-color: darken( $alert-yellow, 15% ); + } + + &[disabled] { + background: lighten( $alert-yellow, 12% ) !important; + color: $white !important; + border-color: lighten( $alert-yellow, 8% ) !important; + } + } + + .noticon-checkmark, + .noticon-warning { + vertical-align: middle; + margin-right: 0.25em; + } + + .noticon-checkmark { + font-size: 18px; + margin: 0 1px 0 -3px; + } + + .noticon-warning { + font-size: 12px; + margin: -1px 6px 0 0; + } + + .sharing-service__content.is-placeholder .sharing-service-examples, + .sharing-service__content.is-placeholder .sharing-service-accounts-detail, + .sharing-service__content.is-placeholder .sharing-service-tip { + display: none; + } + + .sharing-service-example { + display: inline-block; + vertical-align: top; + width: 48%; + + @include breakpoint( "<660px" ) { + display: block; + width: 100%; + margin: 20px 0; + padding: 0; + } + + &:first-child { + padding-right: 4%; + + @include breakpoint( "<660px" ) { + border-bottom: 1px solid lighten( $gray, 30% ); + padding-bottom: 10px; + } + + @include breakpoint( "<480px" ) { + margin-bottom: 16px; + padding: 0 0 16px 0; + } + } + + &.is-single { + width: 100%; + } + } + + .sharing-service-example-screenshot { + border: 1px solid lighten( $gray, 30% ); + + img { + vertical-align: top; + } + } + + .sharing-service-example-screenshot-label { + margin-top: 10px; + } + + .sharing-service-tip { + margin-top: 16px; + font-size: 14px; + color: darken( $gray,10 ); + + .noticon-info { + margin: 3px 3px 0 0; + } + } + + .sharing-service-tip:empty { + display: none; + } + + .sharing-service { + position: relative; + overflow: hidden; + background: $white; + + &.not-connected .sharing-service-examples { + display: block; + } + + &.not-connected .sharing-service-accounts-detail, + &.not-connected .sharing-service-tip { + display: none; + } + } + + .sharing-service-examples { + display: none; + } + + .sharing-service-accounts-detail { + + h2 { + font-size: 1.2em; + } + + .new-account { + padding-bottom: 0.48em; + background: $white; + #content & { + font-size: 0.9em; + } + } + } + + .sharing-service-connected-accounts { + margin-left: 0; + margin-bottom: 8px; + } +} + +.sharing-service { + //@extend %container; + box-shadow: 0 0 0 1px rgba( lighten( $gray, 20% ), 0.5 ), 0 1px 2px lighten( $gray, 30% ); + margin-bottom: 16px; + padding: 0; + + &:hover { + box-shadow: 0 0 0 1px lighten( $gray, 15% ); + } + + @include breakpoint( "<660px" ) { + margin: 0 0 16px 0; + } + + &.is-open { + box-shadow: 0 0 0 1px lighten( $gray, 10% ); + } +} + +.sharing-service-action { + position: absolute; + right: 16px; + top: 22px; + + @include breakpoint( "<660px" ) { + right: 10px; + top: 15px; + } + + @include breakpoint( "<480px" ) { + top: 11px; + } + + &.is-warning { + background: darken( $alert-yellow, 3% ); + border-color: darken( $alert-yellow, 10% ); + color: $white; + + &:hover { + border-color: darken( $alert-yellow, 15% ); + } + + &:focus { + border-color: darken( $alert-yellow, 15% ); + } + + &[disabled] { + background: lighten( $alert-yellow, 12% ) !important; + color: $white !important; + border-color: lighten( $alert-yellow, 8% ) !important; + } + } +} + +.sharing-service__content { + position: relative; + display: none; + padding: 15px 20px 20px 20px; + background: lighten( $gray, 30% ); + border-top: 1px solid lighten( $gray, 20% ); + + &.is-placeholder { + height: 180px; + } + + &.is-placeholder::before { + content: ''; + position: absolute; + top: 16px; + right: 16px; + bottom: 16px; + left: 16px; + background-color: lighten( $gray, 20% ); + animation: loading-fade 1.6s ease-in-out infinite; + } +} + +.sharing-service.is-open .sharing-service__content { + display: block; +} + +.sharing-service__overview { + padding: 16px; + cursor: pointer; + user-select: none; +} + +.sharing-service__overview:hover .sharing-service__content-toggle { + color: $blue-medium; +} + +.sharing-service__icon { + float: left; + height: 42px; + padding-top: 10px; + margin: 0 15px 0 32px; + text-align: center; + width: 50px; + border-radius: 4px; + + @include breakpoint( "<660px" ) { + height: 21px; + padding-top: 5px; + margin: 2px 8px 0 32px; + width: 25px; + } +} + +.sharing-service__glyph.noticon { + color: $white; + font-size: 32px; + margin: 0; + line-height: 1; + width: auto; + height: auto; + + @include breakpoint( "<660px" ) { + font-size: 16px; + } +} + +@mixin sharing-service( $name, $color ) { + .sharing-service.#{ $name } .sharing-service__icon { + background: $color; + } + + .sharing-service.#{ $name } .sharing-service__name { + color: $color; + } + + .sharing-connection__account-avatar.is-fallback.#{ $name } { + background-color: $color; + } +} + +@include sharing-service( "facebook", $color-facebook ); +@include sharing-service( "twitter", $color-twitter ); +@include sharing-service( "google_plus", $color-gplus ); +@include sharing-service( "tumblr", $color-tumblr ); +@include sharing-service( "linkedin", $color-linkedin ); +@include sharing-service( "path", $color-path ); +@include sharing-service( "instagram", $color-instagram ); +@include sharing-service( "eventbrite", $color-eventbrite ); + +.sharing-service__name { + clear: none; + font-size: 20px; +} + +.sharing-service__description { + margin: 0; + color: darken( $gray, 20% ); + + @include breakpoint( "<480px" ) { + display: none; + } + + @include breakpoint( "<660px" ) { + margin-left: 30px; + } +} + +.sharing-service.connected .sharing-service__description { + font-style: italic; +} + +.sharing-service.reconnect .sharing-service__description { + font-weight: bold; +} + +.sharing-service__content-toggle { + position: absolute; + left: 12px; + top: 30px; + font-size: 22px; + color: #aeb8be; + + @include breakpoint( "<480px" ) { + left: 14px; + top: 20px; + } +} + +.sharing-service.is-placeholder .sharing-service__icon, +.sharing-service.is-placeholder .sharing-service__name, +.sharing-service.is-placeholder .sharing-service__description { + background-color: lighten( $gray, 30% ); + animation: loading-fade 1.6s ease-in-out infinite; +} + +.sharing-service.is-placeholder .sharing-service__name, +.sharing-service.is-placeholder .sharing-service__description { + margin-left: 97px; + + @include breakpoint( "<660px" ) { + margin-left: 65px; + } +} + +.sharing-service.is-placeholder .sharing-service__name { + margin-top: 4px; + margin-bottom: 4px; + height: 22px; + width: 20%; + + @include breakpoint( "<660px" ) { + width: 30%; + } +} + +.sharing-service.is-placeholder .sharing-service__description { + margin-top: 8px; + margin-bottom: 2px; + height: 16px; + width: 45%; +} + +.sharing-connection { + position: relative; + background: transparent; + box-shadow: none; + border-bottom: 1px solid lighten( $gray, 30% ); + list-style-type: none; + margin-bottom: 0; + padding: 8px 0; + + &:first-child { + border-top: 1px solid lighten( $gray, 30% ); + } + + &.disabled { + opacity: 0.4; + } +} + +.sharing-connection__account-avatar { + position: absolute; + left: 0; + top: 8px; + height: 40px; + width: 40px; + border: 1px solid $gray-light; + color: white; + + &.is-fallback::before { + @include noticon( '\f304', 40px ); + } +} + +.sharing-connection__account-status { + padding: 10px 90px 10px 48px; + + &.is-shareable { + padding-top: 0; + padding-bottom: 0; + } + + @include breakpoint( "<480px" ) { + padding-right: 0; + } +} + +.sharing-service.reconnect .sharing-connection__account-status { + padding-right: 200px; + + @include breakpoint( "<480px" ) { + padding-right: 0; + } +} + +.sharing-connection__account-name { + font-weight: 600; +} + +.sharing-connection__keyring-user { + display: inline-block; + margin-left: 8px; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + color: $gray; +} + +.sharing-connection__account-sitewide-connection { + display: block; +} + +.sharing-connection__account-sitewide-connection input[type="checkbox"] { + margin-top: 3px; +} + +.sharing-connection.disabled .sharing-connection__account-action { + cursor: default; + cursor: progress; +} + +.sharing-connection__account-actions { + position: absolute; + right: -10px; + top: 50%; + margin-top: -16px; + + @include breakpoint( "<480px" ) { + position: static; + margin-top: 4px; + text-align: right; + } +} + +.sharing-connection__account-action { + display: inline-block; + padding: 8px 10px; + cursor: pointer; + line-height: 16px; +} + +.sharing-connection__account-action.reconnect { + color: $alert-yellow; + + &:before { + @include noticon( '\f414', 16px ); + margin-right: 8px; + } +} + +.sharing-connection.disabled .sharing-connection__account-action { + cursor: default; + cursor: progress; +} + +// Sharing Buttons Section + +.sharing-settings.sharing-buttons { + .sharing-button-styles { + box-shadow: 0 -2px 0 lighten( $gray, 30% ) inset; + padding-bottom: 0.5em; + } + + // Preview (sourced from Sharing plugin) + + .official-preview { + vertical-align: top; + } + + .add-new-service, + .sharing-buttons-add, + .sharing-buttons-add-save, + .sharing-buttons-add-cancel { + cursor: pointer; + } + + .sharing-buttons-add { + float: right; + + .noticon { + font-size: 32px; + margin: 7px -18px -2px 0 #{"/*rtl:ignore*/"}; + } + + &.inactive { + opacity: 0.3; + } + } +} + +.sharing-buttons__submit { + float: right; +} + +.sharing-buttons-tray__buttons { + @include breakpoint ( "<480px" ) { + margin-right: -16px; + } +} + +.sharing-buttons-preview-buttons__more { + position: absolute; + z-index: 1000; + max-width: 400px; + margin-top: -4px; + padding-top: 12px; + transform: scaleY( 0 ); + transform-origin: 50% 6px; + transition: transform 0.2s ease-out; + + &.is-visible { + transition-timing-function: ease-in; + transform: scaleY( 1 ); + } +} + +.sharing-buttons-preview-buttons__more-inner { + min-width: 68px; + min-height: 34px; + padding: 10px 0 2px 8px; + border: 1px solid #ccc; + border-radius: 2px; + background-color: $white; + box-shadow: 0px 5px 20px rgba( 0, 0, 0, .2 ); +} + +.sharing-buttons-preview-buttons__more-inner .sharing-buttons-preview-button, +.sharing-buttons-preview-buttons__more-inner .sharing-buttons-preview-button.style-icon { + margin-top: 0; + margin-bottom: 8px; +} + +.sharing-buttons-preview-buttons__more::before { + content: ""; + position: absolute; + top: 8px; + left: 20px #{"/*rtl:ignore*/"}; + display: block; + width: 8px; + height: 8px; + transform: rotate( 45deg ); + background-color: $white; + border-top: 1px solid #ccc; + border-left: 1px solid #ccc #{"/*rtl:ignore*/"}; +} + +.sharing-buttons__panel { + @include clear-fix; + position: relative; + margin-bottom: 20px; + padding: 20px 24px; + background: $white; + box-shadow: 0 0 0 1px rgba( lighten( $gray, 20% ), 0.5 ), 0 1px 2px lighten( $gray, 30% ); +} + +.sharing-buttons__fieldset-group { + @include clear-fix; + margin: 0 -3%; + + @include breakpoint( "<660px" ) { + margin: 0; + } +} + +.sharing-buttons__fieldset { + float: left; + display: block; + width: 50%; + padding: 0 3%; + margin-bottom: 20px; + + @include breakpoint( "<660px" ) { + width: 100%; + padding: 0; + } +} + +.sharing-buttons__fieldset input[type="radio"], +.sharing-buttons__fieldset input[type="checkbox"] { + margin-right: 8px; +} + +.sharing-buttons__fieldset label { + display: block; + cursor: pointer; +} + +.sharing-buttons__fieldset-heading { + margin-bottom: 5px; + font-weight: 600; +} + +.sharing-buttons__fieldset-detail { + display: block; + margin: 5px 0; + font-size: 13px; + font-style: italic; + color: $gray; +} + +.sharing-buttons-preview { + position: relative; + margin: 20px 0; +} + +.sharing-buttons-preview__reblog-like { + margin: 14px 0; +} + +.sharing-buttons-preview__reblog-like .sharing-buttons-preview-button { + margin: 0 1em 3px 0; +} + +.sharing-buttons-preview__reblog, +.sharing-buttons-preview__like { + padding: 1px 8px 0px 5px; + line-height: 25px; + + &:before { + display: none; + } + + &:hover { + color: #777; + } +} + +.sharing-buttons-preview__reblog .noticon, +.sharing-buttons-preview__like .noticon { + vertical-align: top; + margin: 3px 4px 0 0; + color: $blue-medium; +} + +.sharing-buttons-preview__like .noticon { + margin: 3px 2px 0 -1px; +} + +.sharing-buttons-preview__fake-user { + border: 1px solid lighten( $gray, 20% ); + display: inline-block; + height: 24px; + width: 24px; + line-height: 1; + vertical-align: top; +} + +.sharing-buttons-preview__fake-like { + color: darken( $gray, 10% ); + font-size: 11px; + font-weight: 300; +} + +.sharing-buttons-preview .sortable-list__navigation { + margin-right: 16px; +} + +.sharing-buttons-preview-action { + position: relative; + overflow: visible; + display: none; + padding: 8px 8px 8px 26px; + cursor: pointer; + border: 1px solid lighten( $gray, 20% ); + border-radius: 4px; + box-shadow: 0 0 8px rgba( $gray-dark, 0.04 ); + background-color: $white; + text-align: left; + line-height: 1; + color: $blue-wordpress; + + @include breakpoint( "<480px") { + padding-right: 0; + } + + &:hover { + color: $blue-medium; + } + + &.is-active { + display: inline-block; + } + + &.is-edit::before { + @include noticon( '\f411', 16px ); + margin-right: 4px; + } + + &:disabled { + cursor: default; + border-color: lighten( $gray, 30% ); + color: lighten( $gray, 30% ); + } + + &.is-add::before { + @include noticon( '\f510', 16px ); + margin-right: 4px; + } + + &.is-top::after, + &.is-bottom::after { + content: ''; + position: absolute; + display: block; + width: 12px; + height: 12px; + border: 1px solid lighten( $gray, 20% ); + background-color: $white; + transform: rotate( 45deg ); + } + + &:disabled.is-top::after, + &:disabled.is-bottom::after { + border-color: lighten( $gray, 30% ); + } + + &.is-top { + margin-bottom: 14px; + } + + &.is-bottom { + margin-top: 14px; + @include breakpoint( "<480px" ) { + margin: 14px 1% 0; + } + } + + &.is-top::after { + bottom: -7px; + border-top-width: 0; + border-left-width: 0 #{"/*rtl:ignore*/"}; + } + + &.is-bottom::after { + top: -7px; + border-right-width: 0 #{"/*rtl:ignore*/"}; + border-bottom-width: 0; + } + + &.is-left::after { + left: 30px; + } + + &.is-right::after { + right: 15px; + } +} + +.sharing-buttons-preview-action .noticon { + position: absolute; + left: 6px; + top: 50%; + margin-top: -8px; + font-size: 16px; +} + +.sharing-buttons-preview__button-tray-actions { + @include breakpoint( "<480px" ) { + margin: 0 -6%; + } +} + +.sharing-buttons-preview-action + .sharing-buttons-preview-action { + margin-left: 8px; + + @include breakpoint( "<480px" ) { + margin-left: 1%; + } +} + +.sharing-buttons-preview-action:last-child { + @include breakpoint( "<480px" ) { + width: 46%; + } +} + +.sharing-buttons-preview-action { + @include breakpoint( "<480px" ) { + width: 50%; + } + + &::before { + @include breakpoint( "<480px" ) { + float: left; + margin: 6px 6px 0 0; + } + } +} + +.sharing-buttons-preview__display { + padding: 10px 20px; + border: 1px solid lighten( $gray, 30% ); + box-shadow: 0 3px 6px -3px rgba( 0, 0, 0, 0.05 ); +} + +.sharing-buttons-preview__heading { + margin: 0; + padding: 8px 0; + background-color: $gray-light; + border: 1px solid lighten( $gray, 30% ); + border-bottom: 0; + font-size: 11px; + line-height: 1; + font-weight: bold; + text-transform: uppercase; + text-align: center; + color: $gray; +} + +.sharing-buttons-preview.is-placeholder .sharing-buttons-preview__label, +.sharing-buttons-preview.is-placeholder .sharing-buttons-preview__buttons { + display: block; + background-color: lighten( $gray, 30% ); + animation: loading-fade 1.6s ease-in-out infinite; +} + +.sharing-buttons-preview__label { + display: block; + margin: 8px 0; + font-size: 11px; + font-weight: bold; + line-height: 1.2; + text-transform: uppercase; + color: #767676; +} + +.sharing-buttons-preview.is-placeholder .sharing-buttons-preview__label { + height: 13px; + width: 80px; +} + +.sharing-buttons-preview__buttons { + margin-top: 0.25em; +} + +.sharing-buttons-preview.is-placeholder .sharing-buttons-preview__buttons { + height: 26px; + width: 75%; + margin-bottom: 16px; +} + +.sharing-buttons-preview-button { + display: inline-block; + margin: 8px 8px 0 0; + cursor: default; + font-size: 12px; + border-radius: 3px; + color: #777; + background: #f8f8f8; + border: 1px solid #ccc; + box-shadow: 0 1px 0 rgba( 0, 0, 0, .08 ); + line-height: 23px; + padding: 1px 8px 0px 5px; + + &.style-icon { + border-radius: 50%; + border: 0; + box-shadow: none; + padding: 8px; + position: relative; + top: -2px; + line-height: 1; + width: auto; + height: auto; + margin-bottom: 0; + } +} + +.sharing-buttons-preview__display .sharing-buttons-preview-button { + display: none; + + &.is-enabled { + display: inline-block; + } +} + +&.style-text .sharing-buttons-preview-button__glyph, +&.style-text .sharing-buttons-preview-button__custom-icon, +&.style-icon .sharing-buttons-preview-button__service { + display: none; +} + +.sharing-buttons-preview-button__service { + line-height: 23px; + margin-left: 3px; +} + +.sharing-buttons-preview-button.style-icon .sharing-buttons-preview-button__service { + line-height: 1; +} + +.sharing-buttons-preview-button__glyph { + vertical-align: top; + position: relative; + top: 3px; + text-align: center; +} + +.sharing-buttons-preview-button.style-icon .sharing-buttons-preview-button__glyph { + top: 0; + color: $white; +} + +.sharing-buttons-preview-button.style-icon.share-email .sharing-buttons-preview-button__glyph, +.sharing-buttons-preview-button.style-icon.share-print .sharing-buttons-preview-button__glyph { + color: #777; +} + +.sharing-buttons-preview-button__custom-icon { + display: inline-block; + vertical-align: top; + width: 16px; + height: 16px; + background-position: left center; + background-repeat: no-repeat; + background-size: 100%; +} + +@mixin sharing-button-service( $name, $color ) { + .sharing-buttons-preview-button.style-icon.share-#{ $name } { + background: $color; + + &:hover { + background: rgba( $color, 0.9 ); + } + } +} + +@include sharing-button-service( "facebook", $color-facebook ); +@include sharing-button-service( "twitter", $color-twitter ); +@include sharing-button-service( "press-this", $blue-wordpress ); +@include sharing-button-service( "path", $color-path ); +@include sharing-button-service( "google-plus-1", $color-gplus ); +@include sharing-button-service( "instagram", $color-instagram ); +@include sharing-button-service( "eventbrite", $color-eventbrite ); +@include sharing-button-service( "linkedin", $color-linkedin ); +@include sharing-button-service( "stumbleupon", $color-stumbleupon ); +@include sharing-button-service( "tumblr", $color-tumblr ); +@include sharing-button-service( "reddit", $color-reddit ); +@include sharing-button-service( "pinterest", $color-pinterest ); +@include sharing-button-service( "pocket", $color-pocket ); +@include sharing-button-service( "email", $color-email ); +@include sharing-button-service( "print", $color-email ); + +.sharing-buttons-preview__panel { + position: relative; + display: none; + background: $white; + border: 1px solid lighten( $gray, 20% ); + border-radius: 4px; + box-shadow: 0 0 8px rgba( $gray-dark, 0.04 ); + + &::before { + content: ''; + position: absolute; + border: 1px solid lighten( $gray, 20% ); + border-right-width: 0 #{"/*rtl:ignore*/"}; + border-bottom-width: 0; + background: $white; + display: block; + width: 12px; + height: 12px; + transform: rotate( 45deg ); + } + + &.is-top { + margin: 0 0 14px; + } + + &.is-top::before { + bottom: -7px; + left: 30px; + border-width: 0 1px 1px 0 #{"/*rtl:ignore*/"}; + } + + &.is-bottom { + margin: 14px 0 0; + @include breakpoint( "<480px" ) { + margin: 15px -8px 0 -8px; + } + } + + &.is-bottom::before { + top: -7px; + left: 30px; + } + + &.is-active { + display: block; + } + + &.buttons-hidden::before { + left: 208px; + } +} + +.sharing-buttons-preview__panel-content { + padding: 16px; +} + +.sharing-buttons-preview__panel-heading { + font-size: 20px; + font-weight: normal; + color: $gray-dark; +} + +.sharing-buttons-preview__panel-instructions, +.sharing-buttons-preview__panel-notice { + display: block; + color: $gray; + margin: 8px 0; +} + +.sharing-buttons-preview__panel-instruction-text { + .touch &.is-notouch-context, + &.is-touch-reorder-context, + &.is-notouch-reorder-context, + &.is-touch-context { + display: none; + } + + .touch &.is-touch-context { + display: inline; + } +} + +.sharing-buttons-preview__panel.is-reordering .sharing-buttons-preview__panel-instruction-text { + &.is-notouch-reorder-context, + .touch &.is-touch-reorder-context { + display: inline; + } + + &.is-notouch-context, + &.is-touch-reorder-context, + .touch &.is-touch-context, + .touch &.is-notouch-reorder-context { + display: none; + } +} + +.sharing-buttons-preview__panel-content .sharing-buttons-preview-button { + margin-top: 8px; + cursor: pointer; + @include breakpoint( "<480px" ) { + margin: 18px 18px 0 0; + } + + &.style-icon:hover { + border: none; + opacity: .6; + } + + &.is-enabled { + opacity: .3; + } + + &.is-enabled.style-icon { + opacity: .2; + } +} + +.sharing-buttons-preview__panel.is-reordering .sharing-buttons-preview-button.is-enabled { + opacity: 1; +} + +.sharing-buttons-preview__panel.is-reordering .sortable-list__item.is-draggable.is-active .sharing-buttons-preview-button { + margin: 0; +} + +.sharing-buttons-preview__panel-actions { + padding: 10px 20px; + text-align: right; + border-top: 1px solid lighten( $gray, 30% ); +} + +.sharing-buttons-preview__panel-action { + margin-left: 10px; + + &.is-left { + float: left; + margin-left: 0; + margin-right: 10px; + } +} + +.sharing-buttons-label-editor__input { + max-width: 300px; +} + +@include breakpoint( "<660px" ) { + + .right-column { + box-sizing: border-box; + } + + .sharing-content { + .new-account { + margin-left: 10px; + } + } +} diff --git a/assets/stylesheets/sections/_site-settings.scss b/assets/stylesheets/sections/_site-settings.scss new file mode 100644 index 00000000000000..54352762d00bd1 --- /dev/null +++ b/assets/stylesheets/sections/_site-settings.scss @@ -0,0 +1,221 @@ +.site-settings { + fieldset { + clear: both; + margin-bottom: 20px; + } + + label { + display: block; + } + + input { + display: inline-block; + } + + .form-setting-explanation { + margin: 5px 0; + } + + .short-settings { + display: block; + min-width: 200px; + } + + select + label { + margin-top: 24px; // Give labels some margin when they immediately follow a select + } + + input[type="number"] { + padding: 0; + width: 50px; + text-align: center; + } + + input[type="text"] { + -webkit-appearance: none; + } + + legend, + label { + margin-bottom: 5px; + font-size: 14px; + font-weight: 600; + } + + legend + label, + label + label, + li label, + input[type="checkbox"] + label, + input[type="radio"] + label, + label input[type="checkbox"], + label input[type="radio"] { + font-weight: normal; + } + + .is-primary { + float: right; + + &:first-child { + margin-bottom: 20px; + } + } + + .empty-content { + .is-primary { + float: none; + } + } + + p.settings-explanation { + display: block; + margin: 5px 0; + font-size: 13px; + font-style: italic; + font-weight: 400; + color: $gray; + } + + p.settings-alert { + font-weight: 400; + color: $alert-red; + } + + ul li, + ol li { + margin-bottom: 0; + } + + .analytics-settings { + padding-top: 20px; + } + + .blogaddress-settings { + @include breakpoint( ">660px" ) { + display: flex; + } + + .button { + margin: 8px 0 0 0; + text-align: center; + width: 100%; + + @include breakpoint( ">660px" ) { + margin: 0 0 0 16px; + width: 45%; + } + } + } +} + +.writing-settings, +.general-settings { + @include breakpoint( "<660px" ) { + select{ + width: 100%; + } + } +} + + +.press-this { + /* press this isn't functional on a touch device */ + .touch & { + display: none; + } + + p.pressthis { + margin: 20px 0; + + a, + a:hover, + a:focus, + a:active { + display: inline-block; + position: relative; + cursor: move; + padding: 10px; + font-style: normal; + line-height: 16px; + font-size: 14px; + text-decoration: none; + color: #333; + background: lighten( $gray, 30% ); + border-radius: 3px; + border: 1px solid lighten( $gray, 20% ); + } + + a span { + display: inline-block; + margin: 0 10px 0 0; + font-family: $sans; + + &:before { + color: #777; + font-family: Noticons; + } + } + } +} + +.jp-relatedposts { + position: relative; + margin: 1em 0; + padding: 1em 1em .5em; + width: 100%; + background: $gray-light; + box-sizing: border-box; + + &:after { + content: ''; + display: block; + clear: both; + } + + .jp-relatedposts-headline { + margin: 0 0 1em 0; + display: inline-block; + float: left; + font-size: 10px; + font-weight: 600; + font-family: inherit; + } + + .jp-relatedposts-items { + clear: left; + } + + .jp-relatedposts-post .jp-relatedposts-post-title a { + font-weight: normal; + text-decoration: none; + opacity: 1; + } + + .jp-relatedposts-post { + float: left; + width: 33%; + box-sizing: border-box; + margin: 0 0 1em; + padding: 0 5px; + + @include breakpoint( "<660px" ) { + width: 50%; + } + + @include breakpoint( "<480px" ) { + width: 100%; + } + } + + .jp-relatedposts-post img, + .jp-relatedposts-post span { + display: block; + max-width: 90%; + overflow: hidden; + text-overflow: ellipsis; + } + + .jp-relatedposts-post .jp-relatedposts-post-context { + opacity: .6; + } + +} diff --git a/assets/stylesheets/sections/_sites.scss b/assets/stylesheets/sections/_sites.scss new file mode 100644 index 00000000000000..3a7c690db94f4c --- /dev/null +++ b/assets/stylesheets/sections/_sites.scss @@ -0,0 +1,276 @@ +/** + * Site Grid + */ +.sites-grid { + width: 100%; + float: left; + box-sizing: border-box; + padding-bottom: 80px; + + @include breakpoint( "<660px" ) { + padding-left: .25em; + padding-right: .25em; + } +} + +.sites__select-heading { + clear: both; + color: darken( $gray, 30% ); + display: block; + font-family: $serif; + font-size: 32px; + font-weight: bold; + margin-bottom: 20px; +} + +.site-card__add-new { + .noticon { + font-size: 64px; + height: 65px; + margin-top: 20px; + color: darken( $gray, 10% ); + transition: all 0.1s ease-in-out; + } + + a:hover .noticon { + color: $blue-medium; + } + + .site-card__content { + min-height: 192px; + box-sizing: border-box; + background: none; + box-shadow: none; + border: 2px dashed lighten( $gray, 20% ); + padding-top: 25px; + + .site-card__title { + color: darken( $gray, 10% ); + } + } + + &:hover { + .site-card__content { + box-shadow: none; + border: 2px dashed $blue-medium; + + .site-card__title { + color: $blue-medium; + } + } + } +} + +// Start SiteCard component +.site-card { + box-sizing: border-box; + cursor: pointer; + float: left; + margin-bottom: 20px; + margin-right: 2%; + width: 32%; + + @include breakpoint( "<480px" ) { + width: 100%; + } + + &:nth-child( 3n ) { + margin-right: 0; + + @include breakpoint( "<480px" ) { + margin: 0; + } + } + + &.has-update { + .site-options li { + display: none; + } + .site-options li:last-child { + background: $alert-yellow; + display: block; + font-size: 12px; + width: 100%; + letter-spacing: 0; + padding: 8px 0; + position: absolute; + bottom: 0; + left: 0; + right: 0; + text-transform: none; + + a::before { + @include noticon( '\f420', 16px ); + margin-right: 8px; + opacity: 0.6; + vertical-align: text-bottom; + } + } + .update-available { + color: $white; + } + } + + &.has-problem { + .site-options li { + display: none; + } + .site-options li:last-child { + background: $alert-red; + display: block; + font-size: 12px; + width: 100%; + letter-spacing: 0; + padding: 8px 0; + position: absolute; + bottom: 0; + left: 0; + right: 0; + text-transform: none; + + a::before { + @include noticon( '\f414', 16px ); + margin-right: 8px; + opacity: 0.6; + vertical-align: text-bottom; + } + + a { + color: $white; + } + } + } + + &:hover { + .site-content { + box-shadow: 0 1px 4px rgba( $gray-dark, 0.2 ); + @include breakpoint( "<660px" ) { + box-shadow: none; + } + } + + .site-title, .site-description { + color: $blue-medium; + @include breakpoint( "<660px" ) { + color: $gray-dark; + } + } + .site-description { + color: $blue-medium; + @include breakpoint( "<660px" ) { + color: $gray; + } + } + } +} + +.site-card__content { + background-color: $white; + box-shadow: 0 1px 2px rgba(0,0,0,0.075); + margin-bottom: 0; + min-height: 144px; + padding: 40px 20px 10px; + position: relative; + text-align: center; + + // Placeholder boxes for loading sites + &.is-empty { + min-height: 144px; + + .site-card__title, + .site-card__description, + .site-icon { + animation: pulse-light 0.8s ease-in-out infinite; + } + + .site-card__title { + background: lighten( $gray, 20% ); + height: 16px; + margin: 4px auto 10px; + width: 50%; + } + + .site-card__description { + background: lighten( $gray, 20% ); + height: 10px; + margin: 4px auto; + width: 70%; + } + } + + // Banner image + .site-card__header { + background-color: $gray-light; + background-size: cover; + position: absolute; + top: 0; + left: 0; + height: 80px; + width: 100%; + overflow: hidden; + + img { + max-width: 150%; + max-height: none; + } + } + + // Site icon / blavatar + .site-icon { + display: inline-block; + border: 2px solid white; + margin-bottom: .4em; + box-shadow: 0 1px 1px rgba($gray-dark, 0.2); + } + + .site-card__title { + white-space: nowrap; + font-size: 16px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + /** + * Show lock icon on private sites + * todo: use @extend noticon + */ + .is-private &::before { + font: normal 16px/1 Noticons; + display: inline-block; + color: $gray; + content: "\f470"; + vertical-align: bottom; + height: 20px; + line-height: 1.1; + margin-right: 2px; + } + } + .site-card__description { + font-size: 13px; + font-weight: 200; + color: $gray; + font-style: italic; + line-height: 1.4em; + margin-bottom: .4em; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + .site-card__options { + margin: 0; + + li { + font-size: 11px; + list-style: none; + display: inline-block; + color: $gray; + text-transform: uppercase; + letter-spacing: 0.1em; + + &:nth-child(2):before { + content:'\00a0\2022\00a0'; + } + } + } +} +// End SiteCard component diff --git a/assets/stylesheets/sections/_stats.scss b/assets/stylesheets/sections/_stats.scss new file mode 100644 index 00000000000000..4382cdb3fca155 --- /dev/null +++ b/assets/stylesheets/sections/_stats.scss @@ -0,0 +1,1742 @@ +/* + Priest Vito Cornelius: You're a monster, Zorg. + Zorg: I know. +*/ + +// Site sections +.module-list { + @include clear-fix; +} + +.stats-nonperiodic { + &.has-no-recent { + color: $gray-dark; + font-weight: 300; + + p { + @include breakpoint( "<660px" ) { + margin-left: 24px; + margin-right: 24px; + } + + @include breakpoint( "<480px" ) { + text-align: center; + } + } + } +} + +// Section title + +.stats-section-title { + @extend %heading; + + @include breakpoint( "<660px" ) { + margin-left: 24px; + margin-right: 24px; + } + + @include breakpoint( "<480px" ) { + text-align: center; + } +} + +// Module container + +@include breakpoint( ">960px" ) { + .module-column { + float: left; + width: 48.8%; + width: calc(50% - 0.5em); + + &:last-child { + float: right; + } + } +} + +.old-stats-link .button .gridicon { + margin-bottom: -2px; + margin-left: 4px; +} + +// Module Placeholder + +@keyframes delay-fade-in { + 0%, 66% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +.stats-module.is-loading { + + // Hide elements + .module-header .site-icon, + .module-header .toggle-info, + .chart, + .module-content-table, + .stats-popular__item { + display: none; + } + + .module-header-link, + .module-header-title { + max-width: 120px; + white-space: nowrap; + overflow: hidden; + + .gridicon { + display: none; + } + } + + // Make text invisible + .module-content-list-header .label, + .module-content-list-header .value, + .module-header-title span, + ul.module-content-tabs li:hover .label, + ul.module-content-tabs li.module-tab.is-selected:hover .label { + color: $transparent; + } +} + +.stats-module.is-hidden { + display: none; +} + +// 1: ### Showing/hiding should not be handled by CSS +.module-placeholder { + display: none; + padding: 0 24px; + min-height: 140px; + + // 1 + &.show, + .stats-module.is-loading & { + display: block; + } + + // Block placeholder, primarily for SVGs and similar + &.is-block { + background: $gray-light; + } + + // Spinner placeholder, to be used in Summary views, where we already have some data + &.is-spinner, + &.is-void { + background: url("images/loading.gif") no-repeat 50% 50%; + background-size: 32px 32px; + opacity: 1; + } + + // 'Void' placeholder, don't stare too long into the void or the void will stare back into you + &.is-void { + -webkit-animation: delay-fade-in 6s 1; // Animating in this silly way to have the graphic actually be visible once the animation is completed + } + + &.is-chart { + height: 244px; + } +} + +// Module Expand +// (link that shows only if there are more results than we can show in the overview) + +.module-expand { + line-height: 40px; + + @include breakpoint( "<480px" ) { + line-height: 48px; + } + + .stats-module.is-expanded & { + display: block; + } + + &, + .stats-module.is-loading &, + .stats-module.has-no-data & { + display: none; + } + + a { + @extend %mobile-link-element; + position: relative; + display: block; + padding: 0 24px; + border-top: 1px solid $gray-light; + font-size: 14px; + + // Hover state + @include breakpoint( ">480px" ) { + &:hover { + background: $gray-light; + border-top-color: $white; + } + } + + // Focus state + &:focus { + background: $gray-light; + border-top-color: $white; + } + + @include breakpoint( ">960px" ) { + .module-list & { + font-size: 12px; + } + } + } + + .right { + color: $gray; + position: absolute; + right: 24px; + top: 0; + } +} + +// Module Header + +.module-header { + position: relative; + background: $white; + line-height: 40px; + height: 40px; + padding-left: 24px; + + .stats-module.is-loading & { + cursor: default; + height: 40px; + } + + .stats-module.summary & { + cursor: default; + } +} + +// Module Header Title +// 1: If really long titles wrap, hide the excess + +.module-header-title { + @extend %mobile-interface-element; + @extend %placeholder; + + width: auto; + font-weight: bold; + font-weight: 600; + height: 40px; // 1 + overflow: hidden; // 1 + color: $gray-dark; +} + +// Module Header Actions +// 1: To align optically to right line and create bigger touch target +// 2: So the focus outline isn't covered by the fading pseudo-element + +ul.module-header-actions { + position: absolute; + list-style: none; + top: 0; + right: 0; + height: 40px; + margin: 0; + background: $white; + + // Fade really long module titles + &::before { + @include stats-fade-text($white); + } + + .module-header-action { + display: inline-block; + + &:last-child .module-header-action-link { + &, + &::after { + padding-right: 12px; // 1 + } + } + + .summary &.toggle-services { + display: none; + } + } + + .gridicon { + @extend %placeholder-icon; + vertical-align: middle; + } + + .module-header-action-link { + @extend %mobile-interface-element; + height: 40px; + min-width: 40px; + line-height: 40px; + display: inline-block; + text-align: center; + position: relative; // 2 + z-index: 2; // 2 + color: $gray; + + .stats-module.is-loading & { + cursor: default; + } + } + + // Hover state + @include breakpoint( ">480px" ) { + .stats-module:hover & .module-header-action-link { + color: $blue-wordpress; + } + + .module-header & .module-header-action-link:hover { + color: $link-highlight; + } + } + + // Focus state + .module-header & .module-header-action-link:focus { + color: $link-highlight; + } + + // Info button + .toggle-info { + + &, + .stats-module.is-loading & { + display: none; + } + + .stats-module.is-expanded & { + display: inline-block; + } + } + + // Toggle + .toggle-services .gridicon { + transition: .2s transform ease-out; + transform: translate3d(0,0,0); + } + + .stats-module.is-expanded & .toggle-services .gridicon { + transform: rotate(180deg); + } +} + +// Module Content Text + +.module-content-text { + width: 100%; + min-height: 1em; + font-size: 13px; + color: $gray-dark; + + a:focus { + outline: thin dotted; + } + + @include breakpoint( ">960px" ) { + .module-list & { + font-size: 12px; + } + } + + // Don't show text when loading, even if it's info text and the module is empty + .stats-module.has-no-data &, + .stats-module.is-loading & { + display: none; + } + + // Hidden info box (help) + // 1: 'inline-block' to get around margin collapse issue, cleaner than 1px top padding + // 2: Temporary for the welcome guide, don't show info boxes while modules are loading even if the welcome message is still open + .error & { + display: block; + } + + // Hidden info box + &-info { + display: none; + position: relative; + background: $gray-light; + color: $gray-dark; + box-shadow: inset 0 1px 0 $gray-light; + + .stats-module.is-showing-info & { + display: inline-block; // 1 + } + + .stats-module.is-loading.is-showing-info & { + display: none; // 2 + } + } + + // Error messages + &.is-error { + color: $gray; + + .stats-module.is-showing-error & { + display: inline-block; + } + } + + ul, + ol, + p { + margin: 1em 24px; + } + + // Representation of what the published status looks like within a list of posts and pages + .legend.published { + padding-left: 12px; + border-left: 4px solid $orange-jazzy; + } + + .legend.achievement { + color: $alert-yellow; + } + + // Hide legends if there is no data + .stats-module.has-no-data & .legend { + display: none; + } + + // List of associated FAQ items, support pages, tips and tricks, etc + .documentation { + list-style: none; + + li { + line-height: 2em; + font-size: 14px; + + @include breakpoint( ">960px" ) { + .module-list & { + font-size: 12px; + } + } + + @include breakpoint( "<480px" ) { + border-bottom: 1px solid $gray-light; + + &:last-child { + border: none; + margin-bottom: -12px; + } + } + } + + a { + @extend %mobile-link-element; + display: block; + position: relative; + padding: 6px 0 6px 30px; + + @include breakpoint( "<480px" ) { + padding-top: 12px; + padding-bottom: 12px; + } + } + + .gridicon { + position: absolute; + left: 0; + vertical-align: middle; + } + } +} + +// Filter Select +.select-dropdown__wrapper { + margin: 1em 20px; + + .select-dropdown__container { + position: relative; + } + + .stats-module.is-loading &, + .stats-module.has-no-data & { + display: none; + } +} + +// Tab Content (for comments module) + +.tab-content { + display: none; +} + +.tab-email-followers .tab-content.email-followers, +.tab-wpcom-followers .tab-content.wpcom-followers, +.tab-top-authors .tab-content.top-authors, +.tab-top-content .tab-content.top-content { + display: block; +} + +// Module Tabs +// (currently only used for the bar chart module at the top) + +ul.module-tabs { + @include clear-fix; + border-top: 1px solid $gray-light; + list-style: none; + background: $white; + margin: 0; + + .module-tab { + margin: 0; + font-size: 16px; + clear: none; + border-top: 1px solid $gray-light; + box-sizing: border-box; + + &:first-child { + border-top: none; + } + + @include breakpoint( ">480px" ) { + border-top: none; + border-left: 1px solid $gray-light; + float: left; + width: 25%; + text-align: center; + + &.is-post-summary { + width: 33%; + } + + &:first-child { + border-left: none; + } + } + + @include breakpoint( "<480px" ) { + width: auto; + float: none; + text-align: left; + } + + a, + .no-link { + @extend %mobile-interface-element; + @include clear-fix; + padding: 5px 0 10px; + display: block; + background: $white; + color: $gray-dark; + + @include breakpoint( "<480px" ) { + line-height: 24px; + padding-top: 10px; + -webkit-touch-callout: none; + } + } + + .label { + font-size: 11px; + letter-spacing: 0.1em; + line-height: inherit; + text-transform: uppercase; + + @include breakpoint( "<480px" ) { + font-size: 14px; + line-height: 24px; + float: left; + } + } + + .gridicon { + vertical-align: middle; + margin-right: 4px; + margin-top: -2px; + + @include breakpoint( "<480px" ) { + width: 24px; + height: 24px; + margin-left: 24px; + margin-right: 8px; + float: left; + } + } + + .value { + clear: both; + display: block; + line-height: 24px; + color: $blue-wordpress; + transition: font-size .3s 0 ease-out; + + @include breakpoint( "<480px" ) { + clear: none; + float: right; + margin-right: 24px; + } + } + + @include breakpoint( ">480px" ) { + // Hover state + a:hover, + a:hover .value, + &.is-low a:hover, + &.is-low a:hover .value { + color: $link-highlight; + } + + a:hover { + background: rgba(255,255,255,.5); + } + } + + // Focus state + a:focus, + a:focus .value, + .stats-module &.is-selected a:focus, + .stats-module &.is-selected a:focus .value, + &.is-low a:focus, + &.is-low a:focus .value { + color: $link-highlight; + } + + a:focus { + background: rgba(255,255,255,.5); + } + + // Selected state + .stats-module &.is-selected a { + background: $white; + border-top: 1px solid $white; + margin-top: -1px; + cursor: default; + } + + &.is-selected a, + &.is-selected.is-low a { + color: $gray-dark; + } + + &.is-selected a .value, + &.is-selected.is-low a .value, + &.is-selected a:hover .value { + color: $orange-jazzy; + } + + // Low state ('disabled') + &.is-low a .value { + color: $gray; + } + + // Individual tab loading state + &.is-loading a, + &.is-loading a:hover { + cursor: default; + } + + .no-link .value { + color: $gray-dark; + + &.is-low { + color: $gray; + } + } + + &.is-loading a .value, + &.is-loading a:hover .value, + &.is-loading .no-link .value { + animation: loading-fade 1.6s ease-in-out infinite; + cursor: default; + font-size: 110%; + color: $gray; + } + + &.is-loading.is-selected a .value, + &.is-loading.is-selected a:hover .value { + color: $gray; + } + } + + // If there's only one tab (used on the Post/Video Details page) + li:only-child { + width: auto; + float: none; + text-align: left; + + a { + line-height: 24px; + padding-top: 10px; + } + + .label { + font-size: 14px; + line-height: 24px; + float: left; + } + + .gridicon { + width: 24px; + height: 24px; + margin: 0 8px 0 24px; + float: left; + } + + .value { + clear: none; + float: right; + margin-right: 24px; + } + } + + &.is-enabled { + background: $gray-light; + + &, + li { + border-color: $gray-light; + } + + a { + background: $gray-light; + } + } +} + +// Module Content + +.module-content { + display: none; + position: relative; + + .stats-module.is-expanded & { + display: block; + } +} + +// Module Content List + +.module-content-list { + padding: 0; + margin: 0 0 .5em; + list-style-type: none; + + .stats-module.is-loading &, + .stats-module.has-no-data &, + .stats-module.is-showing-error & { + display: none; + } + + .stats-module.is-loading &-legend { + display: block; + } +} + +// Module Content List Item + +.module-content-list-item { + // Smaller font-size for narrower, two-column modules + font-size: 14px; + line-height: 40px; + + // List item height shorter on 2-column modules + @include breakpoint( ">960px" ) { + .module-list & { + font-size: 12px; + line-height: 28px; + } + } + + border-top: 1px solid $transparent; + + // Increase touch targets on mobile + @include breakpoint( "<480px" ) { + line-height: 48px; + border-top: 1px solid $gray-light; + + &:first-child { + border-top-color: $transparent; + } + + // Darken color for sublists + .module-content-list-sublist & { + border-top-color: $gray-light; + } + } + + &.disabled { + .module-content-list-item-label, + .module-content-list-item-value { + opacity: .15; + transition: opacity .3s ease .15s; + } + + .module-content-list-item-right { + &:before { + display: none; + } + } + + .module-content-list-item-actions { + cursor: pointer; + opacity: 1; + transition: opacity .3s ease .15s; + position: relative; + right: -20px; + } + } +} + +// Module Content List Item Wrapper +// (wrapper element, what's actually hovered for each list item) + +.module-content-list-item-wrapper { + @extend %mobile-interface-element; + background: $white; // Default non-active color + display: block; + line-height: inherit; + clear: both; // To make sure no rows overlap no matter the circumstances + padding: 0 24px; + + span { + font-size: 14px; + // Always let child elements inherit line heights + line-height: inherit; + } + + @include breakpoint( ">960px" ) { + + .module-list & { + line-height: 28px; + + span { + font-size: 12px; + // Always let child elements inherit line heights + line-height: inherit; + } + } + } + + // Post was published within the selected period + // 1: Move so far out left that only half the icon is showing to reduce footprint + .module-content-list-item.published & { + box-shadow: inset 4px 0 0 $orange-jazzy; + } + +} + +// Module Content List Item Hover + +@include breakpoint( ">480px" ) { + .module-content-list-item-link .module-content-list-item-wrapper:hover { + + &, + .module-content-list-item-right { + background-color: $gray-light; + } + + .module-content-list-item-right::before { + background-image: linear-gradient(to right, $transparent 0%, $gray-light 90%); + } + + // Display hidden actions + .module-content-list-item-action-hidden { + display: inline-block; + } + } +} + +// Module Content List Item Focus +// Active on non-links as well so you can easily go to them and digest information + +.module-content-list-item .module-content-list-item-wrapper:focus { + + &, + .module-content-list-item-right { + background-color: $gray-light; + } + + .module-content-list-item-right::before { + background-image: linear-gradient(to right, $transparent 0%, $gray-light 90%); + } + + // Display hidden actions + .module-content-list-item-action-hidden { + display: inline-block; + } +} + +// Highlight toggle icon if item has a sublist + +@include breakpoint( ">480px" ) { + .module-content-list > .module-content-list-item-toggle > .module-content-list-item-wrapper:hover .module-content-list-item-label::before { + color: $link-highlight; + } +} + +.module-content-list > .module-content-list-item-toggle > .module-content-list-item-wrapper:focus .module-content-list-item-label::before { + color: $link-highlight; +} + +// Module Content List Item Label +// 1: To create the illusion that text is fading out (break up even long chunks of text) +// 2: ### always has to be the line-height -- could we sync up with a variable? + +.module-content-list-item-label { + display: block; + overflow: hidden; + word-break: break-all; // 1 + height: 40px; // 2 + + // List item height shorter on 2-column modules + @include breakpoint( ">960px" ) { + .module-list & { + height: 28px; + } + } + + @include breakpoint( "<480px" ) { + height: 48px; // ### see ^ + } + + // Icons + .icon, + .gridicon { + margin-right: 8px; + } + + .icon { + $icon-size: 24px; + + position: relative; + display: inline-block; + width: $icon-size; + height: $icon-size; + overflow: hidden; + vertical-align: middle; + min-width: 24px; + line-height: inherit; + + img { + display: block; + background: $white; + position: relative; + } + + // Hide for user avatars + .followers &, + .top-authors &, + .authorviews & { + background: none; + + &::before { + content: none; + } + } + } + + .gridicon { + vertical-align: middle; + } + + // Icons smaller on 2col + @include breakpoint( ">960px" ) { + .module-list & .icon { + font-size: 20px; + line-height: 1.3; + } + + .module-list & .gridicon { + width: 18px; + height: 18px; + } + } + + .avatar { + width: 24px; + height: 24px; + } + + .avatar-user { + border-radius: 12px + } + + .user-selectable & { + -webkit-user-select: text; + -khtml-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; + } + + // Label sections: For when multiple data points are displayed in one expandable list item + .module-content-list-item-label-section { + margin-right: 11px; + padding-right: 12px; + border-right: 1px solid $gray-light; + + &:last-child { + margin: 0; + padding: 0; + border: none; + } + } +} + +// Module Content List Item Right column + +.module-content-list-item-right { + position: relative; + float: right; + background: $white; + margin-left: -48px; // ### keep? experimental: to force labels to go longer than they normally would to make sure the fade out shows + + + @include breakpoint( ">960px" ) { + .module-list & { + height: 28px; + } + } + + @include breakpoint( "<480px" ) { + height: 48px; + } + + // Fade out value if long + &::before { + @include stats-fade-text($white); + } +} + +// Module Content List Item Value +// 1: Makes secondary actions aligned up to values of '99,999' or a string like '99 hours' +.module-content-list-item-value { + display: inline-block; + text-align: right; + min-width: 44px; // 1 + + .followers & { + min-width: 60px; // 1 + } +} + +// Module Content List Item Actions (in right column) +// Actions list +ul.module-content-list-item-actions { + display: inline-block; + margin: 0 .5em 0 0; + + // ### guess we need to abstract this to a mixin since its repeated now + // ### this should be fixed but refraining since we're going to use + // the popover and select UI patterns more closely in the future + &.collapsed { + @include dropdown-menu; + + background: $gray-light; + display: none; + z-index: 3; + margin: 0; + top: 30px; + right: auto; + left: -172px; // module-content-list-item-right is relative, so this is min-width 220px - action width 48px = 172 + + .module-content-list-item-right.is-expanded & { + display: inline-block; + } + + &::after { + border-bottom-color: $gray-light; + right: 18px; // Logically this should be 24px but thanks to the borders (?) 18px is actually centered + left: auto; + } + + .module-content-list-item-action-wrapper, + ul.module-content-list-item-action-submenu { + display: block; + text-align: left; + } + + // If displayed in a sublist or otherwise expanded item, swap background color + .module-content-list-item-toggle.is-expanded & { + background-color: $white; + + &::after { + border-bottom-color: $white; + } + } + } + + @include breakpoint( "<480px" ) { + @include dropdown-menu; + + background: $gray-light; + display: none; + z-index: 2; + margin: 0; + top: 46px; + right: auto; + left: -172px; // module-content-list-item-right is relative, so this is min-width 220px - action width 48px = 172 + + .module-content-list-item-right.is-expanded & { + display: inline-block; + } + + &::after { + border-bottom-color: $gray-light; + right: 18px; // Logically this should be 24px but thanks to the borders (?) 18px is actually centered + left: auto; + } + + .module-content-list-item-action-wrapper, + ul.module-content-list-item-action-submenu { + display: block; + text-align: left; + } + + // If displayed in a sublist or otherwise expanded item, swap background color + .module-content-list-item-toggle.is-expanded & { + background-color: $white; + + &::after { + border-bottom-color: $white; + } + } + } +} + +// Actions toggle +// (a toggle that's only shown on smaller screen sizes) +// 1: ### Showing/hiding should not be handled by CSS + +.module-content-list-item-actions-toggle { + display: none; + min-width: 24px; + padding: 0 12px; + height: 40px; + line-height: inherit; + + @include breakpoint( ">960px" ) { + .module-list & { + height: 28px; + } + } + + .gridicon { + vertical-align: middle; + } + + @include breakpoint( "<480px" ) { + display: inline-block; + height: 48px; + } + + // 1 + &.show { + display: inline-block; + height: 30px; + } +} + +// Actions Menu +// (Used for links that should be hidden even on desktop) +ul.module-content-list-item-action-submenu { + display: inline-block; + list-style: none; + margin: 0; + + @include breakpoint( ">480px" ) { + + @include dropdown-menu; + + display: none; + z-index: 2; + margin: 0; + top: 32px; + right: -20px; + + .module-content-list-item-action.hidden-action.is-expanded & { + display: inline-block; + } + + &::after { + right: 24px; + left: auto; + } + + .module-content-list-item-action-wrapper { + display: block; + text-align: left; + } + } +} + +// Action +.module-content-list-item-action { + display: inline-block; + margin: 0 1em 0 0; + + // So that 'View' label is moved more to the right since icon has been dropped + @include breakpoint( ">960px" ) { + .module-list & { + margin: 0; + } + } + + @include breakpoint( "<480px" ) { + margin-right: 0; + } + + // Action wrapper, what's actually selected + .module-content-list-item-action-wrapper { + @extend %mobile-interface-element; + display: inline-block; + text-align: center; + margin: 0; + line-height: inherit; + + @include breakpoint( "<480px" ) { + min-width: 24px; + padding: 0 12px; + + &.toggle { + display: none; + } + } + + .module-content-list-item-action-label.unfollow { + display: none; + } + + // Hide 'View' label next to icon on 2-column modules + @include breakpoint( ">960px" ) { + .module-list & span.module-content-list-item-action-label-view { + display: none; + } + } + } + + // Color follow action when already following + .module-content-list-item-action-wrapper.following .module-content-list-item-action-label { + color: $alert-green; + } + + // Display hidden label and change icon for Unfollow action + .module-content-list-item-action-wrapper.following:focus, + .module-content-list-item-action-wrapper.following:hover { + + .module-content-list-item-action-label { + display: none; + color: $link-highlight; + } + + .module-content-list-item-action-label.unfollow { + display: inline-block; + } + } + + // Icon settings + // 1: Optically align a bit better + .gridicon { + vertical-align: middle; + margin-right: 4px; + margin-top: -2px; // 1 + } + + // Color spam action red + .module-content-list-item-action-wrapper.spam { + color: $alert-red; + + // Hover state + @include breakpoint( ">480px" ) { + &:hover { + color: tint($alert-red, 30%); + } + } + + // Focus state + &:focus { + color: tint($alert-red, 30%); + } + } +} + + +// Module Content List style: Legend +// (a legend for the data displayed) + +ul.module-content-list-legend { + margin-top: .5em; + margin-bottom: 0; +} + +.module-content-list-legend .module-content-list-item .module-content-list-item-value, +.module-content-list-legend .module-content-list-item .module-content-list-item-label { + @extend %placeholder; + + color: $gray; + font-weight: bold; + + // Limit width when loading for placeholders to take less visual space + .stats-module.is-loading & { + max-width: 60px; + } +} + +// Display full action labels in header to use them as legends for the list's actions +.module-content-list-legend .module-content-list-item .module-content-list-item-action .module-content-list-item-action-label { + @include breakpoint( "<480px" ) { + display: inline; + } +} + +// Module Content List Item style: Disabled +// (there's absolutely no data or bad error) +// ### Do :empty for value to input N/A? Or placeholder content in general? + +.module-content-list > .module-content-list-item-disabled { + cursor: default; + + .module-content-list-item-value, + .module-content-list-item-label { + color: $gray; + } +} + + +// Module Content List Item style: Large +// (a larger display of a list item, currently only used for the Authors module) + +.module-content-list > .module-content-list-item-large { + + > .module-content-list-item-wrapper { + line-height: 48px; + @include breakpoint( ">960px" ) { + .module-list & { + line-height: 28px; + } + } + } + + > .module-content-list-item-wrapper .module-content-list-item-label { + height: 48px; + @include breakpoint( ">960px" ) { + .module-list & { + height: 28px; + } + } + } + + > .module-content-list-item-wrapper .module-content-list-item-label .avatar { + font-size: 32px; + margin-right: 10px; + } + + > .module-content-list-item-wrapper .module-content-list-item-label .icon { + font-size: 32px; + line-height: 32px; + width: 32px; + height: 32px; + @include breakpoint( ">960px" ) { + .module-list & { + width: 24px; + height: 24px; + } + } + } + + @include breakpoint( ">960px" ) { + .module-list & > .module-content-list-item-wrapper .module-content-list-item-label .icon { + margin-top: -2px; // Really couldn't figure out a better way to correctly position the avatar + } + } + + > .module-content-list-item-wrapper .module-content-list-item-label .avatar { + width: 32px; + height: 32px; + @include breakpoint( ">960px" ) { + .module-list & { + width: 24px; + height: 24px; + } + } + } + + > .module-content-list-item-wrapper .module-content-list-item-label .avatar-user { + border-radius: 16px; + } +} + +// Module Content List Item style: Link +// (this item has a main action or links somewhere) + +.module-content-list > .module-content-list-item-link { + cursor: pointer; + + &.disabled { + cursor: default; + } + + // Change colors to highlight label when row is highlighted + .module-content-list-item-label { + color: $blue-wordpress; + } + + // Highlight main action (usually what's indicated in the label) + + @include breakpoint( ">480px" ) { + .module-content-list-item-wrapper:hover .module-content-list-item-label { + color: $link-highlight; + } + } + + .module-content-list-item-wrapper:focus .module-content-list-item-label { + color: $link-highlight; + } +} + +// Module Content List Item style: Toggle +// (this item's main action is to show an enclosed sublist or something else) + +.module-content-list > .module-content-list-item-toggle { + position: relative; + + // Toggle icon + > .module-content-list-item-wrapper .module-content-list-item-label .gridicons-chevron-down { + vertical-align: middle; + transition: .2s transform ease-out; + transform: translate3d(0,0,0); + } +} + +// Active (sublist is showing) +.module-content-list-item-toggle.is-expanded { + border-top-color: $gray-light; + + > .module-content-list { + display: block; + } + + // Lock in hover states to show that the list item is now selected (active) + &, + > .module-content-list-item-wrapper, + > .module-content-list-item-wrapper .module-content-list-item-right { + background: $gray-light; + } + + > .module-content-list-item-wrapper .module-content-list-item-value { + color: $gray; + } + + > .module-content-list-item-wrapper .module-content-list-item-right::before { + background-image: linear-gradient(to right, $transparent 0%, $gray-light 90%); + } + + // Rotate toggle icon + > .module-content-list-item-wrapper .module-content-list-item-label .gridicons-chevron-down { + transform: rotate(180deg); + } + + // Hide the top border of an active sub-list + > .module-content-list-item { + border-top-color: $transparent; + } + + // Hover changes + @include breakpoint( ">480px" ) { + > .module-content-list-item-wrapper:hover { + + // Change background and gradient color + &, + .module-content-list-item-right { + background-color: $white; + } + + span.module-content-list-item-right::before { + background-image: linear-gradient(to right, $transparent 0%, $white 90%); + } + } + } +} + +// Module Content List: Sublist +// (modified content list fit for sublists to be displayed inside other lists) + +.module-content-list-sublist { + display: none; + padding: 4px 0; + + // Add more padding for third level nested lists + .module-content-list-sublist .module-content-list-item-wrapper { + padding-left: 56px; + } +} + +.module-content-list-sublist .module-content-list-item { + + // Change background and gradient color + > .module-content-list-item-wrapper .module-content-list-item-right, + > .module-content-list-item-wrapper { + background: $gray-light; // Default non-active color + } + + .module-content-list-item-right::before { + background-image: linear-gradient(to right, $transparent 0%, $gray-light 90%); + } + + // Hover changes + @include breakpoint( ">480px" ) { + &-link .module-content-list-item-wrapper:hover, + &-normal .module-content-list-item-wrapper:hover { + + // Change background and gradient color + &, + .module-content-list-item-right { + background-color: $white; + } + + span.module-content-list-item-right::before { + background-image: linear-gradient(to right, $transparent 0%, $white 90%); + } + } + } +} + +// Module Content Table + +.module-content-table { + position: relative; + + .module-content-table-scroll { + overflow: auto; + overflow-x: auto; + overflow-y: visible; + min-height: 210px; + } + + // Table cells + // 1: Make sure table cells are always only on one line, otherwise the sticky left tds don't have the right size + // 2: Make right padding much greater to accommodate for increased gradient + td, + th { + font-size: 14px; + padding: 8px 12px; + border-bottom: 1px solid $gray-light; + border-right: 1px solid $gray-light; + white-space: nowrap; // 1 + + &:first-child { + padding-left: 24px; + } + + &:last-child { + padding-right: 60px; // 2 + border-right: none; + } + } + + tbody tr:last-child th, + tbody tr:last-child td { + border-bottom: none; + } + + tbody th:first-child { + background: $white; + position: absolute; + z-index: 2; + + // Disable fixed legend for mobile + @include breakpoint( "<480px" ) { + position: static; + } + } + + // Left this modifier as-is because these tables are likely going to change + // a lot or otherwise be removed, and at least it's directly dependent on + // being associated with a td in this structure + @include breakpoint( ">480px" ) { + .stats-module & td.has-no-data:hover, // 1 + tbody tr:hover td, + tbody tr:hover th { + background: $gray-light; + } + + .stats-module & td.highest-count:hover, + tbody tr td:hover { + background: $gray-light; + color: $gray-dark; + } + } + + .stats-module & td.highest-count { + position: relative; + color: $alert-yellow; + } + + .spacer { + color: transparent; + } + + .date, + .value { + white-space: nowrap; + } + + .value { + display: inline-block; + } + + .value-rising, + .value-falling { + color: $alert-green; + + .gridicon { + margin-right: 4px; + margin-bottom: -2px; + } + } + + .value-falling { + color: $alert-red; + } + + thead th, + .date { + color: $gray; + } + + .date { + display: block; + font-size: 11px; + text-transform: uppercase; + letter-spacing: .1em; + } + + // Fade out sides of tables to hint at horizontal scrolling + // 1: 16px should cover for any scrollbar + // 2: Much wider to show horizontal scrolling better (since the window loads scrolled to the left) + &::before, + &::after { + content: ""; + display: block; + position: absolute; + top: 0; + bottom: 16px; // 1 + left: 0; + z-index: 1; + width: 20px; + background-image: linear-gradient(to left, $transparent 0%, $white 90%); + } + + &::after { + right: 0; + left: auto; + width: 60px; // 2 + background-image: linear-gradient(to right, $transparent 0%, $white 90%); + } +} + +// Module specific tweaks + +// Countries +.countryviews { + + &.is-block { + display: none; + } + + .stats-module.is-loading & .summary .module-placeholder.is-block { + display: block; + } + + .module-content-list-item-label .icon img { + background-color: $gray-light; + } +} + +// Show block placeholder on the summary page only +.stats-module.is-loading.summary .module-placeholder.is-block { + display: block; +} + +// --- Module specific tweaks, avoid adding things here + +// Overlay + +.main-column.stats-centered { + float: none; + margin: 0 auto; + + @include breakpoint( ">960px" ) { + min-width: 640px; + } + + @include breakpoint( "<660px" ) { + .stats-module { + margin-left: .25em; + margin-right: .25em; + } + } + + @include breakpoint( ">480px" ) { + .stats-section-title { + text-align: left; + } + } +} + +// Welcome Stats message +// -- extends .welcome-message /assets/stylesheets/shared/welcome.scss + +.stats-message { + + // Container for 'Visit the old stats layout' link + @include breakpoint( "<480px" ) { + &.switch-stats { + text-align: center; + } + } +} + +// Insights poll + +.stats-poll { + color: $gray-dark; + text-align: center; + + &.is-gone { + animation: fade-out-once .7s forwards; // Poll disappears forever after voting + animation-delay: 2s; + } +} + +@keyframes fade-out-once { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +.stats-poll__message { + + @include breakpoint( "<480px" ) { + display: block; + } +} + +.stats-poll__button { + display: inline-block; + margin: -9px 0 -9px 7px; + + @include breakpoint( "<480px" ) { + width: 40%; + margin: 9px 0 9px 7px; + } +} + +.card { + &.stats-module { + padding: 0; + } +} diff --git a/assets/stylesheets/sections/_translator.scss b/assets/stylesheets/sections/_translator.scss new file mode 100644 index 00000000000000..3c76a1c88ee364 --- /dev/null +++ b/assets/stylesheets/sections/_translator.scss @@ -0,0 +1,102 @@ +#translator-launcher { + position: fixed; + bottom: 45px; + right: 20px; + + border-radius: 27px; + background: $blue-wordpress; + padding: 4px; + font-size: 16px; + z-index: 99; + + a { + color: $white; + text-decoration: none; + outline: 0; + + .noticon { + font-size: 32px; + width: 32px; + } + + .text { + float: right; + width: 0; + overflow: hidden; + height: 32px; + line-height: 32px; + white-space: nowrap; + } + + &:hover { + .text { + transition: all 0.25s ease-in-out; + width: auto; + margin-right: 6px; + padding: 0 2px; + } + } + } + + &.active { + background: $white; + a { + color: $blue-wordpress; + } + } +} + +//Overwriting the popup defaults +body { + .webui-popover { + border-radius: 2px; + padding: 0; + text-align: inherit; + border-color: lighten( $gray, 20% ); + + .webui-popover-title { + background-color: lighten( $gray, 20% ); + border-color: lighten( $gray, 30% ); + border-radius: 1px 1px 0 0; + } + + &.top, + &.top-right, + &.top-left { + .arrow { + border-top-color: lighten( $gray, 20% ); + } + } + + &.right, + &.right-top, + &.right-bottom { + .arrow { + border-right-color: lighten( $gray, 20% ); + } + } + + &.left, + &.left-top, + &.left-bottom { + .arrow { + border-left-color: lighten( $gray, 20% ); + } + } + + &.bottom, + &.bottom-right, + &.bottom-left { + .arrow { + border-bottom-color: lighten( $gray, 20% ); + &:after { + border-bottom-color: lighten( $gray, 20% ); + } + } + } + } +} + +.translator-modal { + max-width: 400px; +} diff --git a/assets/stylesheets/sections/_updated-confirmation.scss b/assets/stylesheets/sections/_updated-confirmation.scss new file mode 100644 index 00000000000000..e1478e54a661b6 --- /dev/null +++ b/assets/stylesheets/sections/_updated-confirmation.scss @@ -0,0 +1,147 @@ + +/** + * Updated-confirmation (for post and page changes) + */ + +.updated-confirmation { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + z-index: 2; + background-color: rgba(255, 255, 255, 0.8); + .conf-alert { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%) scale(1); + width: (166 / 16) * 1em; + font-size: (16 / 15) * 1em; + padding: (12 / 16) * 1em; + text-align: center; + background-color: $white; + border-radius: 3px; + border: solid 1px $alert-green; + color: $alert-green; + transition: border-color 0.3s ease, color 0.3s ease; + .conf-alert_title { + &:after { + @extend %noticon; + content: '\f418'; + font-size: (24 / 16) * 1em; + vertical-align: top; + } + } + hr { + background: #eee; + margin: (10 / 16) * 1em 0 0; + } + .undo { + display: block; + font-size: (12 / 16) * 1em; + color: $gray; + padding: (10 / 12) * 1em 0 0; + &:hover { + cursor: pointer; + } + .pages-list & { + display: inline; + } + span { + display: inline-block; + border-bottom: solid 1px lighten( $gray, 20% ); + } + } + .pages-list & { + width: auto; + white-space: nowrap; + padding: (4 / 16) * 1em (12 / 16) * 1em; + } + &.conf-alert--trashed, + &.conf-alert--deleted, + &.conf-alert--error { + border-color: $alert-red; + color: $alert-red; + } + &.conf-alert--trashing, + &.conf-alert--updating { + border-color: $blue-wordpress; + color: $blue-wordpress; + .loading-dot { + animation-name: loading-dot-pulse; + animation-duration: 0.5s; + animation-fill-mode: both; + animation-iteration-count: infinite; + &:nth-child(2) { + animation-delay: 0.15s; + } + &:last-child { + animation-delay: 0.3s; + } + } + .conf-alert_title { + &:after { + content: ''; + } + } + } + &.conf-alert--trashed { + .conf-alert_title { + &:after { + content: '\f407'; + } + } + } + &.conf-alert--deleted, + &.conf-alert--error { + .conf-alert_title { + &:after { + content: ''; + } + } + } + } +} + +.updated-trans-enter { + transition: opacity 0.3s ease; + opacity: 0; + .updated-confirmation { + pointer-events: none; + } + .conf-alert { + transition: transform 0.3s cubic-bezier(0.160, 0.390, 0.220, 1.275), border-color 0.3s ease, color 0.3s ease; + transform: translate(-50%, -50%) scale(0.5); + } + &.updated-trans-enter-active { + opacity: 1; + .updated-confirmation { + pointer-events: auto; + } + .conf-alert { + transform: translate(-50%, -50%) scale(1); + } + } +} + +.updated-trans-leave { + transition: opacity 0.3s ease; + opacity: 1; + .updated-confirmation { + pointer-events: none; + } + .conf-alert { + transition: transform 0.3s cubic-bezier(0.160, 0.390, 0.220, 1.275), border-color 0.3s ease, color 0.3s ease; + transform: translate(-50%, -50%) scale(1); + } + &.updated-trans-leave-active { + opacity: 0; + .updated-confirmation { + pointer-events: none; + } + .conf-alert { + transform: translate(-50%, -50%) scale(0.5); + } + } +} diff --git a/assets/stylesheets/sections/_upgrades.scss b/assets/stylesheets/sections/_upgrades.scss new file mode 100644 index 00000000000000..205d26cadf0513 --- /dev/null +++ b/assets/stylesheets/sections/_upgrades.scss @@ -0,0 +1,340 @@ +.upgrades { + .right-column { + overflow: hidden; + } +} + +// Purchased Products +.purchased { + + hr { + float: left; + width: 100%; + display: block; + height: 2px; + background: lighten( $gray, 20% ); + } + + .product { + position: relative; + float: left; + width: 100%; + margin: 0 0 15px 0; + padding: 15px; + background: $white; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-sizing: border-box; + + .name { + width: 42%; + float: left; + margin: 0 10px 0 0; + + h3 { + margin: 0 0 10px; + font-size: 15px; + line-height: 1; + } + + p { + margin: 0; + padding: 0; + font-size: 13px; + color: darken( $gray, 10% ); + } + } + + .status { + float: left; + width: auto; + + h4 { + margin: 2px 0 10px; + font-size: 13px; + line-height: 1; + } + + p { + margin: 0; + padding: 0; + font-size: 13px; + color: $gray; + + } + } + + .actions { + float: right; + width: auto; + margin: 6px 0 0 0; + + .toggle { + float: right; + display: inline-block; + width: 32px; + height: 32px; + margin: 0 0 0 5px; + color: $gray; + + .noticon { + width: 32px; + text-align: center; + line-height: 32px; + } + } + + .button { + float: right; + } + } + } +} + +// Expiring Products +.expiring { + .product { + position: relative; + float: left; + width: 100%; + margin: 0 0 15px 0; + padding: 15px; + background: $white; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-sizing: border-box; + + .name { + width: 42%; + float: left; + margin: 0 10px 0 0; + + h3 { + margin: 0 0 10px; + font-size: 15px; + line-height: 1; + } + + p { + margin: 0; + padding: 0; + font-size: 13px; + color: $gray; + } + } + + .status { + float: left; + width: auto; + + h4 { + margin: 2px 0 10px; + font-size: 13px; + line-height: 1; + } + + p { + margin: 0; + padding: 0; + font-size: 13px; + color: $alert-red; + + } + } + + .actions { + float: right; + width: auto; + margin: 6px 0 0 0; + + .toggle { + float: right; + display: inline-block; + width: 32px; + height: 32px; + margin: 0 0 0 5px; + color: $gray; + + .noticon { + width: 32px; + text-align: center; + line-height: 32px; + } + } + + .button { + float: right; + } + } + } +} + +@media screen and (max-width: 770px) { + body { + } +} + +@media screen and (max-width: 450px) { + + .plan { + float: left; + width: 100%; + margin: 0 0 15px 0; + + .plan-header { + float: left; + width: 100%; + height: 50px; + box-sizing: border-box; + + .badge { + display: none; + } + + h4 { + float: left; + display: inline-block; + margin: 0; + padding: 0; + text-align: left; + font-size: 13px; + line-height: 20px; + } + + h3 { + display: inline-block; + margin: 0; + padding: 0; + font-size: 20px; + line-height: 20px; + text-align: right; + } + + p { + display: inline-block; + text-align: right; + } + } + + .plan-details { + float: left; + width: 100%; + box-sizing: border-box; + + p { + margin: 0; + padding: 0; + } + + .illustration { + display: none; + } + } + + .actions { + float: left; + width: 100%; + padding: 15px; + box-sizing: border-box; + border-top: 1px solid lighten( $gray, 30% ); + + p { + margin: 0; + padding: 0; + + &.current-plan { + margin: 0; + padding: 0; + color: $alert-green; + line-height: 1; + border: none; + + &:before { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + content: '\f418'; + display: inline-block; + margin: -3px 5px 0 0; + font: normal 16px/1 Noticons; + vertical-align: middle; + + } + } + } + } + } + + // Purchased Upgrades + + .purchased { + + .product { + padding: 0; + background: $gray-light; + + .name { + float: left; + width: 100%; + margin: 0; + padding: 15px; + border-bottom: 2px solid lighten( $gray, 30% ); + box-sizing: border-box; + background: $white; + + h3 { + display: inline; + float: left; + margin: 0; + padding: 0; + font-size: 13px; + font-weight: 600; + } + + p { + display: inline; + float: right; + margin: 0; + padding: 0; + font-size: 13px; + line-height: 1; + } + } + + .status { + float: left; + width: auto; + margin: 2px 0 0 0; + padding: 0 0 0 15px; + + h4 { + display: inline; + float: left; + margin: 0 5px 0 0; + padding: 0; + font-size: 13px; + line-height: 46px; + } + + p { + display: inline; + float: left; + margin: 0; + padding: 0; + font-size: 13px; + line-height: 46px; + } + } + + .actions { + float: right; + width: auto; + margin: 0; + padding: 10px 15px 10px 0; + + a { + font-size: 13px; + } + } + } + } + +} diff --git a/assets/stylesheets/shared/_animation.scss b/assets/stylesheets/shared/_animation.scss new file mode 100644 index 00000000000000..656be52911c31e --- /dev/null +++ b/assets/stylesheets/shared/_animation.scss @@ -0,0 +1,255 @@ +/* + * Animations + * + * Defines `slide-in-up` `slide-out-up` `scale-fade` + * Used for section overlays + */ + +$sidebar-width: 269px; + +body, +html { + // Setup default styles for some animation classes + .slide-in-up { + transform: translate3d( 0, 100%, 0 ); + } + .scale-fade { + opacity: 1; + } + .fade { + opacity: 0; + } + .slide-in-left { + transform: translate3d( -100%, 0, 0 ); + } + .show-in { + opacity: 0; + + &:nth-child(10n + 2) { + animation-delay: .05s !important; + } + &:nth-child(10n + 3) { + animation-delay: .1s !important; + } + &:nth-child(10n + 4) { + animation-delay: .15s !important; + } + &:nth-child(10n + 5) { + animation-delay: .2s !important; + } + &:nth-child(10n + 6) { + animation-delay: .25s !important; + } + &:nth-child(10n + 7) { + animation-delay: .3s !important; + } + &:nth-child(10n + 8) { + animation-delay: .35s !important; + } + &:nth-child(10n + 9) { + animation-delay: .4s !important; + } + &:nth-child(10n + 10) { + animation-delay: .45s !important; + } + } + + // Setup transition parameter on `animate` + // Includes timings and animation curves + &.animate { + .slide-out-up { + transition: transform .2s ease-out; + transform: translate3d( 0, 0, 0 ) ; + } + .slide-in-up { + transition: transform .4s cubic-bezier( .215, .61, .355, 1 ); + } + .slide-in-left { + transition: transform .3s cubic-bezier( .215, .61, .355, 1 ), opacity .3s cubic-bezier( .19, 1, .22, 1 ); + } + .slide-out-right { + transition: transform .5s cubic-bezier( .215, .61, .355, 1 ), opacity .5s cubic-bezier( .19, 1, .22, 1 ); + } + .scale-fade { + transition: transform .5s, opacity .5s; + transform-origin: 50% 60px; + } + .fade { + transition: opacity .5s cubic-bezier( .4, 1, .4, 1 ); + } + .fade-background { + transition: background-color .2s cubic-bezier( .4, 1, .4, 1 ); + } + } + + // Transformations for overlay class animation + &.overlay-open { + .slide-out-up { + transform: translate3d( 0, -46px, 0 ); + } + .slide-in-up { + transform: translate3d( 0, 0, 0 ); + } + .scale-fade { + transform: scale( .95 ); + opacity: .8; + } + .fade { + opacity: 1; + } + } + + &.customizer-section { + .slide-in-left { + transform: translate3d( -40%, 0, 0 ); + } + } + + &.themes-section { + .slide-out-right { + transform: translate3d( 100%, 0, 0 ); + } + .slide-in-left { + transform: translate3d( 0, 0, 0 ); + } + } +} + +// Content sliding left and right to show sidebar + +@keyframes slideContentRight { + 0% { + transform: translate3d( 0, 0, 0 ); + transform: translate3d( 0, 0, 0 ); + } + + 70% { + transform: translate3d( $sidebar-width + 20, 0, 0 ); + } + + 100% { + transform: translate3d( $sidebar-width, 0, 0 ); + } +} + +@keyframes slideContentLeft { + 0% { + transform: translate3d( 0, 0, 0 ); + } + + 30% { + transform: translate3d( 20px, 0, 0 ); + } + + 100% { + transform: translate3d( -$sidebar-width, 0, 0 ); + } +} + +// Sliding responsive filter and nav menus up and down + +@keyframes slideMenuDown { + 0% { + opacity: 0; + transform: translate3d( 0, 0, 0 ); + } + + 80% { + opacity: 1; + transform: translate3d( 0, 22px, 0 ); + } + + 100% { + opacity: 1; + transform: translate3d( 0, 17px, 0 ); + } +} + +@keyframes slideMenuUp { + 0% { + opacity: 1; + transform: translate3d( 0, 0, 0 ); + } + + 20% { + opacity: 1; + transform: translate3d( 0, 5px, 0 ); + } + + 100% { + opacity: 0; + transform: translate3d( 0, -20px, 0 ); + } +} + +// Rotating chevrons when expanding and collapsing sections + +@keyframes rotateOpen { + 0% { + transform: rotate(0); + } + + 50% { + transform: rotate(200deg) + } + + 75% { + transform: rotate(175deg); + } + + 90% { + transform: rotate(185deg) + } + + 100% { + transform: rotate(180deg) + } +} + +@keyframes rotateClosed { + 0% { + transform: rotate(180deg) + } + + 50% { + transform: rotate(-20deg) + } + + 75% { + transform: rotate(5deg); + } + + 90% { + transform: rotate(-5deg); + } + + 100% { + transform: rotate(0); + } +} + +// Simple animation to make elements appear +@keyframes "appear" { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + +@keyframes "pulse-light" { + 50% { background-color: lighten( $gray, 30% ); } +} + +@keyframes "loading-dot-pulse" { + 0% { opacity: 0; } + 50% { opacity: 1; } + 100% { opacity: 0; } +} + +@keyframes "loading-fade" { + 0% { opacity: .5; } + 50% { opacity: 1; } + 100% { opacity: .5; } +} diff --git a/assets/stylesheets/shared/_colors.scss b/assets/stylesheets/shared/_colors.scss new file mode 100644 index 00000000000000..10f056f211c107 --- /dev/null +++ b/assets/stylesheets/shared/_colors.scss @@ -0,0 +1,40 @@ +// Blues +$blue-wordpress: #0087be; +$blue-light: #78dcfa; +$blue-medium: #00aadc; +$blue-dark: #005082; + +// Grays +$gray: #87a6bc; + +// $gray color functions: +// +// lighten( $gray, 10% ) +// lighten( $gray, 20% ) +// lighten( $gray, 30% ) +// darken( $gray, 10% ) +// darken( $gray, 20% ) +// darken( $gray, 30% ) +// +// See wordpress.com/design-handbook/colors/ for more info. + +$gray-light: lighten( $gray, 33% ); //#f3f6f8 +$gray-dark: darken( $gray, 38% ); //#2e4453 + +// Oranges +$orange-jazzy: #f0821e; +$orange-fire: #d54e21; + +// Alerts +$alert-yellow: #f0b849; +$alert-red: #d94f4f; +$alert-green: #4ab866; + +// Link hovers +$link-highlight: tint($blue-medium, 20%); + +// Essentials +$white: rgba(255,255,255,1); +$transparent: rgba(255,255,255,0); + +$border-ultra-light-gray: #e8f0f5; diff --git a/assets/stylesheets/shared/_dropdowns.scss b/assets/stylesheets/shared/_dropdowns.scss new file mode 100644 index 00000000000000..bcadb24c2fbcb3 --- /dev/null +++ b/assets/stylesheets/shared/_dropdowns.scss @@ -0,0 +1,124 @@ +/** + * Dropdown menu for extra site options + */ +.dropdown-menu { + background-color: $white; + box-shadow: 0 1px 4px rgba($gray-dark, 0.2); + position: absolute; + right: 0; + top: 130%; + z-index: 9999; + display: none; + float: left; + margin: 2px 0 0; + padding: 6px 0; + + .pointer { + position: absolute; + right: 8px; + top: -7px; + width: 12px; + height: 10px; + float: left; + overflow: hidden; + + .pointer-outer, + .pointer-inner { + position: absolute; + top: 0; + left: 0; + display: inline-block; + margin-left: -1px; + } + + .pointer-outer { + left: 0; + top: 0; + border-bottom: 7px solid rgba(0,0,0,0.06); + border-left: 7px solid transparent; + border-right: 7px solid transparent; + } + + .pointer-inner { + top: 1px; + left: 1px; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid $white; + } + } + + ul { + margin: 0; + padding: 0; + list-style-type: none; + } + + li { + box-sizing: border-box; + display: block; + float: none; + white-space: nowrap; + + a { + background: transparent; + display: block; + font-size: 12px; + padding: 5px 20px 5px 18px; + text-align: left; + + &:hover { + background: $gray-light; + } + } + } +} + +/** + * Gear toggle button + */ +.gear-dropdown { + cursor: pointer; + position: absolute; + right: 10px; + top: 8px; + display: block; + height: 30px; + width: 30px; + + &:after { + background: $gray-light; + border: 1px solid lighten( $gray, 20% ); + border-radius: 3px; + display: inline-block; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font: normal 18px/1 Noticons; + content: '\f445'; + color: darken( $gray, 10% ); + position: absolute; + top: 0; + left: 0; + height: 28px; + width: 28px; + line-height: 28px; + text-align: center; + z-index: 0; + box-shadow: 0 1px 1px rgba($gray-dark,0.1); + } + + &:hover:after { + color: darken( $gray, 10% ); + } + + &.gear-open { + .dropdown-menu { + display: block; + } + &:after { + border-color: rgba( $blue-wordpress, 0.8 ); + background: rgba( $blue-wordpress, 0.8 ); + color: $white; + } + } +} diff --git a/assets/stylesheets/shared/_extends.scss b/assets/stylesheets/shared/_extends.scss new file mode 100644 index 00000000000000..6fe475147c5a71 --- /dev/null +++ b/assets/stylesheets/shared/_extends.scss @@ -0,0 +1,124 @@ +%clear-text { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +%noticon { + @extend %clear-text; + display: inline-block; + font: normal 16px/1 Noticons; + vertical-align: middle; +} + +%container { + position: relative; + margin-bottom: 6%; + padding: 0 20px 12px; + background: $white; + box-shadow: 0 1px 2px rgba(0,0,0,0.075); + + @include clear-fix; + + ul, + ol { + font-size: 14px; + margin-bottom: 4px; + } + + @include breakpoint( "<480px" ) { + margin-left: .25em; + margin-right: .25em; + } +} + +%container-header { + background: $gray-light; + padding: 13px 20px 10px; + margin: 0 -20px; + min-height: 37px; + font-size: 14px; + line-height: 135%; + border-bottom: 1px solid #EBF0F2; +} + +%status { + padding: 3px 5px; + font-size: 11px; + letter-spacing: 1px; + font-weight: 300; + text-transform: uppercase; + color: $white; + border-radius: 3px; +} + +%status-draft, +%status-pending { + background: $alert-yellow; + box-shadow: inset 0px 1px 0 darken($alert-yellow, 5%); +} + +%status-scheduled { + background: $alert-green; + box-shadow: inset 0px 1px 0 darken($alert-green, 5%); +} + +%placeholder { + + .stats-module.is-loading & * { + color: transparent; + } + + .stats-module.is-loading & { + animation: loading-fade 1.6s ease-in-out infinite; + position: relative; + color: transparent; + cursor: default; + } + + .stats-module.is-loading &::after { + content: ""; + display: block; + position: absolute; + background: $gray-light; + top: 35%; + bottom: 35%; + left: 0; + right: 0; + z-index: 2; + } +} + +%placeholder-icon { + + .stats-module.is-loading & { + animation: loading-fade 1.6s ease-in-out infinite; + } + + .stats-module.is-loading &:hover::before, + .stats-module.is-loading &::before, + .stats-module.is-loading &:hover, + .stats-module.is-loading & { + color: $gray-light; + fill: $gray-light; + } +} + +%heading { + color: darken( $gray, 20% ); + font-size: 2rem; + font-weight: 300; + margin: 1em 0; +} + +%mobile-link-element { + -webkit-tap-highlight-color: rgba($white, .4); // Until we capture ontouch events in JS this is better than :active + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +%mobile-interface-element { + @extend %mobile-link-element; + -webkit-touch-callout: none; +} diff --git a/assets/stylesheets/shared/_forms.scss b/assets/stylesheets/shared/_forms.scss new file mode 100644 index 00000000000000..49e3bc1dfb1e55 --- /dev/null +++ b/assets/stylesheets/shared/_forms.scss @@ -0,0 +1,409 @@ +// Below, you can choose from either using global form styles or class-driven +// form styles. By default, the global styles are on. + +%form { + ul { + margin: 0; + padding: 0; + list-style: none; + } +} + +%form-field { + margin: 0; + padding: 7px 14px; + width: 100%; + color: $gray-dark; + font-size: 16px; + line-height: 1.5; + border: 1px solid lighten( $gray, 20% ); + background-color: $white; + transition: all .15s ease-in-out; + box-sizing: border-box; + + &::placeholder { + color: $gray; + } + + &:hover { + border-color: lighten( $gray, 10% ); + } + + &:focus { + border-color: $blue-wordpress; + outline: none; + box-shadow: 0 0 0 2px $blue-light; + + &::-ms-clear { + display: none; + } + } + + &:disabled { + background: $gray-light; + border-color: lighten( $gray, 30% ); + color: lighten( $gray, 10% ); + + &:hover { + cursor: default; + } + + &::placeholder { + color: lighten( $gray, 10% ); + } + } +} + +%textarea { + min-height: 92px; +} + + +// ========================================================================== +// Global form elements +// ========================================================================== + +form { + @extend %form; +} +input[type="text"], +input[type="search"], +input[type="email"], +input[type="number"], +input[type="password"], +input[type=checkbox], +input[type=radio], +input[type="tel"], +input[type="url"], +textarea { + @extend %form-field; +} +textarea { + @extend %textarea; +} + +fieldset, +input[type="text"], +input[type="search"], +input[type="email"], +input[type="number"], +input[type="password"], +input[type="tel"], +input[type="url"], +textarea, +select, +label { + box-sizing: border-box; +} + +/*Checkbooms*/ + +input[type=checkbox], +input[type=radio] { + clear: none; + cursor: pointer; + display: inline-block; + line-height: 0; + height: 16px; + margin: 4px 0 0; + float: left; + outline: 0; + padding: 0; + text-align: center; + vertical-align: middle; + width: 16px; + min-width: 16px; + appearance: none; +} + +input[type=checkbox] + span, +input[type=radio] + span { + display: block; + margin-left: 24px; +} + +input[type=checkbox] { + &:checked:before { + @extend %clear-text; + + content: '\f418'; + margin: -4px 0 0 -5px; + float: left; + display: inline-block; + vertical-align: middle; + width: 16px; + font: 400 23px/1 Noticons; + speak: none; + color: $blue-medium; + } + &:disabled:checked:before { + color: lighten( $gray, 10% ); + } +} + +input[type=radio] { + border-radius: 50%; + margin-right: 4px; + line-height: 10px; + + &:checked:before { + float: left; + display: inline-block; + content: '\2022'; + margin: 3px; + width: 8px; + height: 8px; + text-indent: -9999px; + background: $blue-medium; + vertical-align: middle; + border-radius: 50%; + animation: grow .2s ease-in-out; + } + + &:disabled:checked:before { + background: lighten( $gray, 30% ); + } +} + +@keyframes grow { + 0% { + transform: scale(0.3); + } + + 60% { + transform: scale(1.15); + } + + 100% { + transform: scale(1); + } +} + +@keyframes grow { + 0% { + transform: scale(0.3); + } + + 60% { + transform: scale(1.15); + } + + 100% { + transform: scale(1); + } +} + +/* end checkbooms */ + + +// ========================================================================== +// Custom form elements +// ========================================================================== + +// Tristate checkbox for bulk selection options + +// Example: +// +// Check all +// + +.checkbox-tristate { + @extend input[type=checkbox]; + position: relative; + margin: 20px 0 19px 20px; + + &:before { + position: absolute; + color: $blue-medium; + font-family: Noticons; + } + + .some-selected & { + &:before { + content: '\f421'; // .noticon-minimize + top: 7px; + left: 0; + } + } + .all-selected & { + &:before { + content: url("data:image/svg+xml;utf8,"); + height: 100%; + width: 100%; + top: 0; + } + } +} + + +// Toggle switches +.toggle[type="checkbox"] { + display: none; +} + +.toggle { + + .toggle-label { + position: relative; + display: inline-block; + border-radius: 12px; + padding: 2px; + width: 40px; + height: 24px; + background: lighten( $gray, 10% ); + vertical-align: middle; + outline: 0; + cursor: pointer; + transition: all .4s ease; + + &:after, &:before{ + position: relative; + display: block; + content: ""; + width: 20px; + height: 20px; + } + &:after{ + left: 0; + border-radius: 50%; + background: #fff; + transition: all .2s ease; + } + &:before{ + display: none; + } + &:hover{ + background: lighten( $gray, 20% ); + } + } + &:focus{ + + .toggle-label{ + box-shadow: 0 0 0 2px $blue-medium; + } + &:checked + .toggle-label{ + box-shadow: 0 0 0 2px $blue-light; + } + } + &:checked{ + + .toggle-label{ + background: $blue-medium; + + &:after{ + left: 16px; + } + } + } + &:checked:hover{ + + .toggle-label{ + background: $blue-light; + } + } + + &:disabled, + &:disabled:hover { + + .toggle-label{ + background: lighten( $gray, 30% ); + } + } +} + +// Classes for toggle state before action is complete (updating plugin or something) +.toggle.is-toggling { + + .toggle-label { + background: $blue-medium; + } + &:checked { + + .toggle-label { + background: lighten( $gray, 20% ); + } + } +} + +select { + background: $white url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB3aWR0aD0iMjBweCIgaGVpZ2h0PSIyMHB4IiB2aWV3Qm94PSIwIDAgMjAgMjAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sbnM6c2tldGNoPSJodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2gvbnMiPiAgICAgICAgPHRpdGxlPmFycm93LWRvd248L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4gICAgPGRlZnM+PC9kZWZzPiAgICA8ZyBpZD0iUGFnZS0xIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBza2V0Y2g6dHlwZT0iTVNQYWdlIj4gICAgICAgIDxnIGlkPSJhcnJvdy1kb3duIiBza2V0Y2g6dHlwZT0iTVNBcnRib2FyZEdyb3VwIiBmaWxsPSIjQzhEN0UxIj4gICAgICAgICAgICA8cGF0aCBkPSJNMTUuNSw2IEwxNyw3LjUgTDEwLjI1LDE0LjI1IEwzLjUsNy41IEw1LDYgTDEwLjI1LDExLjI1IEwxNS41LDYgWiIgaWQ9IkRvd24tQXJyb3ciIHNrZXRjaDp0eXBlPSJNU1NoYXBlR3JvdXAiPjwvcGF0aD4gICAgICAgIDwvZz4gICAgPC9nPjwvc3ZnPg==) no-repeat right 10px center; + border-color: lighten( $gray, 20% ); + border-style: solid; + border-radius: 4px; + border-width: 1px 1px 2px; + color: $gray-dark; + cursor: pointer; + display: inline-block; + margin: 0; + outline: 0; + overflow: hidden; + font-size: 14px; + line-height: 21px; + font-weight: 600; + text-overflow: ellipsis; + text-decoration: none; + vertical-align: top; + white-space: nowrap; + box-sizing: border-box; + padding: 7px 32px 9px 14px; // Aligns the text to the 8px baseline grid and adds padding on right to allow for the arrow. + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + + &:hover { + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB3aWR0aD0iMjBweCIgaGVpZ2h0PSIyMHB4IiB2aWV3Qm94PSIwIDAgMjAgMjAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sbnM6c2tldGNoPSJodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2gvbnMiPiAgICAgICAgPHRpdGxlPmFycm93LWRvd248L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4gICAgPGRlZnM+PC9kZWZzPiAgICA8ZyBpZD0iUGFnZS0xIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBza2V0Y2g6dHlwZT0iTVNQYWdlIj4gICAgICAgIDxnIGlkPSJhcnJvdy1kb3duIiBza2V0Y2g6dHlwZT0iTVNBcnRib2FyZEdyb3VwIiBmaWxsPSIjYThiZWNlIj4gICAgICAgICAgICA8cGF0aCBkPSJNMTUuNSw2IEwxNyw3LjUgTDEwLjI1LDE0LjI1IEwzLjUsNy41IEw1LDYgTDEwLjI1LDExLjI1IEwxNS41LDYgWiIgaWQ9IkRvd24tQXJyb3ciIHNrZXRjaDp0eXBlPSJNU1NoYXBlR3JvdXAiPjwvcGF0aD4gICAgICAgIDwvZz4gICAgPC9nPjwvc3ZnPg==); + } + + &:focus { + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB3aWR0aD0iMjBweCIgaGVpZ2h0PSIyMHB4IiB2aWV3Qm94PSIwIDAgMjAgMjAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sbnM6c2tldGNoPSJodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2gvbnMiPiA8dGl0bGU+YXJyb3ctZG93bjwvdGl0bGU+IDxkZXNjPkNyZWF0ZWQgd2l0aCBTa2V0Y2guPC9kZXNjPiA8ZGVmcz48L2RlZnM+IDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHNrZXRjaDp0eXBlPSJNU1BhZ2UiPiA8ZyBpZD0iYXJyb3ctZG93biIgc2tldGNoOnR5cGU9Ik1TQXJ0Ym9hcmRHcm91cCIgZmlsbD0iIzJlNDQ1MyI+IDxwYXRoIGQ9Ik0xNS41LDYgTDE3LDcuNSBMMTAuMjUsMTQuMjUgTDMuNSw3LjUgTDUsNiBMMTAuMjUsMTEuMjUgTDE1LjUsNiBaIiBpZD0iRG93bi1BcnJvdyIgc2tldGNoOnR5cGU9Ik1TU2hhcGVHcm91cCI+PC9wYXRoPiA8L2c+IDwvZz48L3N2Zz4=); + border-color: $blue-medium; + box-shadow: 0 0 0 2px $blue-light; + outline: 0; + -moz-outline:none; + -moz-user-focus:ignore; + } + + &:disabled, + &:hover:disabled { + background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB3aWR0aD0iMjBweCIgaGVpZ2h0PSIyMHB4IiB2aWV3Qm94PSIwIDAgMjAgMjAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sbnM6c2tldGNoPSJodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2gvbnMiPiAgICAgICAgPHRpdGxlPmFycm93LWRvd248L3RpdGxlPiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4gICAgPGRlZnM+PC9kZWZzPiAgICA8ZyBpZD0iUGFnZS0xIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBza2V0Y2g6dHlwZT0iTVNQYWdlIj4gICAgICAgIDxnIGlkPSJhcnJvdy1kb3duIiBza2V0Y2g6dHlwZT0iTVNBcnRib2FyZEdyb3VwIiBmaWxsPSIjZTllZmYzIj4gICAgICAgICAgICA8cGF0aCBkPSJNMTUuNSw2IEwxNyw3LjUgTDEwLjI1LDE0LjI1IEwzLjUsNy41IEw1LDYgTDEwLjI1LDExLjI1IEwxNS41LDYgWiIgaWQ9IkRvd24tQXJyb3ciIHNrZXRjaDp0eXBlPSJNU1NoYXBlR3JvdXAiPjwvcGF0aD4gICAgICAgIDwvZz4gICAgPC9nPjwvc3ZnPg==) no-repeat right 10px center;; + } + + // A smaller variant that works well when presented inline with text + &.is-compact { + min-width: 0; + padding: 0 20px 2px 6px; + margin: 0 4px; + background-position: right 5px center; + background-size: 12px 12px; + } + + // Make it display:block when it follows a label + label &, + label + & { + display: block; + min-width: 200px; + + &.is-compact { + display: inline-block; + min-width: 0; + } + } + + // IE: Remove the default arrow + &::-ms-expand { + display: none; + } + + // IE: Remove default background and color styles on focus + &::-ms-value { + background: none; + color: $gray-dark; + } + + // Firefox: Remove the focus outline, see http://stackoverflow.com/questions/3773430/remove-outline-from-select-box-in-ff/18853002#18853002 + &:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 $gray-dark; + } +} + +/*Search Inputs*/ +input[type="search"]::-webkit-search-decoration { + // We don't use the native results="" UI + // Ensures the input text is flush to the start of the element, as in regular text inputs + // See, for example, http://geek.michaelgrace.org/2011/06/webkit-search-input-styling/ + display: none; +} diff --git a/assets/stylesheets/shared/_functions.scss b/assets/stylesheets/shared/_functions.scss new file mode 100644 index 00000000000000..32dddb923ad52c --- /dev/null +++ b/assets/stylesheets/shared/_functions.scss @@ -0,0 +1,11 @@ +// Add percentage of white to a color +// Copyright © 2011–2015 thoughtbot. See CREDITS.md#L3 +@function tint($color, $percent){ + @return mix(white, $color, $percent); +} + +// Add percentage of black to a color +// Copyright © 2011–2015 thoughtbot. See CREDITS.md#L3 +@function shade($color, $percent){ + @return mix(black, $color, $percent); +} diff --git a/assets/stylesheets/shared/_infinite-scroll-end.scss b/assets/stylesheets/shared/_infinite-scroll-end.scss new file mode 100644 index 00000000000000..a8c0b300700527 --- /dev/null +++ b/assets/stylesheets/shared/_infinite-scroll-end.scss @@ -0,0 +1,29 @@ +/** +* Infinite Scroll End: +* ------ +* Marker that gets appended to the end of a list (e.g. posts) once +* infinite scroll has reached the last page. +*/ + +.infinite-scroll-end { + position: relative; + width: 100%; + margin-top: (15 / 15) * 1em; + text-align: center; + &:before { + content: ''; + position: absolute; + top: 50%; + left: 0; + right: 0; + z-index: -1; + border-bottom: solid 1px lighten( $gray, 25% ); + } + &:after { + @include noticon( '\f205', (24 / 15) * 1em ); + color: $gray; + font-size: (22 / 15) * 1em; + padding: 0 (8 / 22) * 1em; + background-color: $gray-light; + } +} diff --git a/assets/stylesheets/shared/_livechat.scss b/assets/stylesheets/shared/_livechat.scss new file mode 100644 index 00000000000000..15b9b606ac27c3 --- /dev/null +++ b/assets/stylesheets/shared/_livechat.scss @@ -0,0 +1,1019 @@ +// © Copyright Olark 2015 +#habla_window_div, +#habla_window_div a, +#habla_window_div abbr, +#habla_window_div acronym, +#habla_window_div address, +#habla_window_div applet, +#habla_window_div article, +#habla_window_div aside, +#habla_window_div audio, +#habla_window_div b, +#habla_window_div big, +#habla_window_div blockquote, +#habla_window_div caption, +#habla_window_div cite, +#habla_window_div code, +#habla_window_div dd, +#habla_window_div del, +#habla_window_div dfn, +#habla_window_div dialog, +#habla_window_div div, +#habla_window_div dl, +#habla_window_div dt, +#habla_window_div em, +#habla_window_div fieldset, +#habla_window_div figure, +#habla_window_div font, +#habla_window_div footer, +#habla_window_div form, +#habla_window_div h1, +#habla_window_div h2, +#habla_window_div h3, +#habla_window_div h4, +#habla_window_div h5, +#habla_window_div h6, +#habla_window_div header, +#habla_window_div hgroup, +#habla_window_div hr, +#habla_window_div i, +#habla_window_div iframe, +#habla_window_div img, +#habla_window_div input, +#habla_window_div ins, +#habla_window_div kbd, +#habla_window_div label, +#habla_window_div legend, +#habla_window_div li, +#habla_window_div mark, +#habla_window_div menu, +#habla_window_div nav, +#habla_window_div object, +#habla_window_div ol, +#habla_window_div option, +#habla_window_div p, +#habla_window_div pre, +#habla_window_div q, +#habla_window_div s, +#habla_window_div samp, +#habla_window_div section, +#habla_window_div select, +#habla_window_div small, +#habla_window_div span, +#habla_window_div strike, +#habla_window_div strong, +#habla_window_div sub, +#habla_window_div sup, +#habla_window_div table, +#habla_window_div tbody, +#habla_window_div td, +#habla_window_div textarea, +#habla_window_div tfoot, +#habla_window_div th, +#habla_window_div thead, +#habla_window_div time, +#habla_window_div tr, +#habla_window_div tt, +#habla_window_div ul, +#habla_window_div var, +#habla_window_div video { + background-attachment:scroll; + background-color:transparent; + background-image:none; + background-position:0 0; + background-repeat:repeat; + border-color:#000; + border-style:none; + border-width:medium; + clear:none; + clip:auto; + color:inherit; + counter-increment:none; + counter-reset:none; + cursor:auto; + direction:inherit; + display:inline; + float:none; + font-family:inherit; + font-size:inherit; + font-style:inherit; + font-variant:normal; + font-weight:inherit; + height:auto; + letter-spacing:normal; + line-height:inherit; + list-style:inside; + list-style-type:inherit; + margin:0; + max-height:none; + max-width:none; + outline:none; + overflow:visible; + padding:0; + position:static; + quotes:"" ""; + table-layout:auto; + text-align:inherit; + text-decoration:inherit; + text-transform:none; + unicode-bidi:normal; + vertical-align:baseline; + visibility:visible; + white-space:normal; + width:auto; + word-spacing:normal; + z-index:auto; + border-radius:0; + -moz-border-radius:0; + -webkit-border-radius:0; + opacity:1; +} + +#habla_window_div, +#habla_window_div address, +#habla_window_div article, +#habla_window_div aside, +#habla_window_div blockquote, +#habla_window_div caption, +#habla_window_div dd, +#habla_window_div dialog, +#habla_window_div div, +#habla_window_div dl, +#habla_window_div dt, +#habla_window_div fieldset, +#habla_window_div figure, +#habla_window_div footer, +#habla_window_div form, +#habla_window_div h1, +#habla_window_div h2, +#habla_window_div h3, +#habla_window_div h4, +#habla_window_div h5, +#habla_window_div h6, +#habla_window_div header, +#habla_window_div hgroup, +#habla_window_div hr, +#habla_window_div menu, +#habla_window_div nav, +#habla_window_div ol, +#habla_window_div option, +#habla_window_div p, +#habla_window_div pre, +#habla_window_div section, +#habla_window_div select, +#habla_window_div table, +#habla_window_div tbody, +#habla_window_div td, +#habla_window_div textarea, +#habla_window_div tfoot, +#habla_window_div th, +#habla_window_div thead, +#habla_window_div tr, +#habla_window_div ul { + display:block; +} + +#habla_window_div nav ol, +#habla_window_div nav ul { + list-style-type:none; +} + +#habla_window_div menu, +#habla_window_div ul { + list-style-type:disc; +} + +#habla_window_div ol { + list-style-type:decimal; +} + +#habla_window_div menu menu, +#habla_window_div menu ul, +#habla_window_div ol menu, +#habla_window_div ol ul, +#habla_window_div ul menu, +#habla_window_div ul ul { + list-style-type:circle; +} + +#habla_window_div menu menu menu, +#habla_window_div menu menu ul, +#habla_window_div menu ol menu, +#habla_window_div menu ol ul, +#habla_window_div menu ul menu, +#habla_window_div menu ul ul, +#habla_window_div ol menu menu, +#habla_window_div ol menu ul, +#habla_window_div ol ol menu, +#habla_window_div ol ol ul, +#habla_window_div ol ul menu, +#habla_window_div ol ul ul, +#habla_window_div ul menu menu, +#habla_window_div ul menu ul, +#habla_window_div ul ol menu, +#habla_window_div ul ol ul, +#habla_window_div ul ul menu, +#habla_window_div ul ul ul { + list-style-type:square; +} + +#habla_window_div li { + display:list-item; + min-height:auto; + min-width:auto; +} + +#habla_window_div strong { + font-weight:700; +} + +#habla_window_div em { + font-style:italic; +} + +#habla_window_div code, +#habla_window_div kbd, +#habla_window_div samp { + font-family:monospace; +} + +#habla_window_div a, +#habla_window_div a *, +#habla_window_div input[type=checkbox], +#habla_window_div input[type=radio], +#habla_window_div input[type=submit], +#habla_window_div select { + cursor:pointer; +} + +#habla_window_div a:hover { + text-decoration:underline; +} + +#habla_window_div button, +#habla_window_div input[type=submit] { + text-align:center; +} + +#habla_window_div input[type=hidden] { + display:none; +} + +#habla_window_div abbr[title], +#habla_window_div acronym[title], +#habla_window_div dfn[title] { + cursor:help; + border-bottom-width:1px; + border-bottom-style:dotted; +} + +#habla_window_div ins { + background-color:#ff9; + color:#000; +} + +#habla_window_div del { + text-decoration:line-through; +} + +#habla_window_div blockquote, +#habla_window_div q { + quotes:none; +} + +#habla_window_div blockquote:after, +#habla_window_div blockquote:before, +#habla_window_div li:after, +#habla_window_div li:before, +#habla_window_div q:after, +#habla_window_div q:before { + content:""; + content:none; +} + +#habla_window_div input, +#habla_window_div select { vertical-align:middle; +} + +#habla_window_div input, +#habla_window_div select, +#habla_window_div textarea { + border:1px solid #ccc; +} + +#habla_window_div table { + border-collapse:collapse; + border-spacing:0; +} + +#habla_window_div hr { + display:block; + height:1px; + border:0; + border-top:1px solid #ccc; + margin:1em 0; +} + +#habla_window_div [dir=rtl] { + direction:rtl; +} + +#habla_window_div mark { + background-color:#ff9; + color:#000; + font-style:italic; + font-weight:700; +} + +// End of Reset sorta stuff +////////////////////////////////////////////////// + +#habla_window_div { + line-height:1; + direction:ltr; + text-align:left; + color:#000; + font-style:normal; + font-weight:400; + text-decoration:none; +} + +#habla_window_div.habla_window_div_base { + display:block!important; + z-index:99999999; +} + +#habla_window_div #olark-callout-bubble, +#habla_window_div #olark-callout-bubble-offline, +#habla_window_div #olark-callout-bubble-online { + position:relative!important; +} + +#habla_window_div #habla_panel_div { + overflow:hidden; +} + +#habla_window_div #habla_middle_div { + padding:6px 10px 3px; + background: $white; +} + +:first-child+html #habla_window_div #habla_middle_div { + padding:6px 0 0; +} + +#habla_window_div textarea { + max-width:100%; + width:100%; +} + +:first-child+html #habla_window_div textarea { + width:97%; +} + +#habla_window_div #habla_input_div { + +} + +:first-child+html #habla_window_div #habla_input_div { + margin-left:0; + margin-right:0; + width:95%; +} + +#habla_window_div #habla_chatform_form { + margin-top: 5px; +} + +#habla_window_div #habla_conversation_div { + padding:6px 10px 0; + margin:-6px -10px 0; +} + +:first-child+html #habla_window_div #habla_conversation_div, +:first-child+html #habla_window_div #habla_offline_message_div, +:first-child+html #habla_window_div #habla_pre_chat_div { + width:97%; +} + +#habla_window_div #habla_name_input, +#habla_window_div #habla_offline_body_input, +#habla_window_div #habla_offline_email_input, +#habla_window_div #habla_pre_chat_email_input, +#habla_window_div #habla_pre_chat_name_input { + // overflow:hidden; +} + +#habla_window_div #habla_offline_message_div, +#habla_window_div #habla_offline_message_sent_div, +#habla_window_div #habla_pre_chat_div { + +} + +:first-child+html #habla_window_div #habla_offline_message_div, +:first-child+html #habla_window_div #habla_offline_message_sent_div, +:first-child+html #habla_window_div #habla_pre_chat_div { + padding:5px; + margin-left:0; +} + +#habla_middle_div { + line-height:1.5em; +} + +#habla_window_div #habla_expanded_div { + // border-left:1px solid lighten( $gray, 30% ); + // border-right:1px solid lighten( $gray, 30% ); + border-left: 1px solid lighten( $gray, 20% ); + border-right: 1px solid lighten( $gray, 20% ); + box-shadow: -3px 1px 10px -2px rgba( $gray-dark, 0.075 ); +} + +#habla_window_div.habla_window_div_position_inline .habla_panel_border { + border-bottom:1px solid lighten( $gray, 30% ); +} + +#habla_window_div.olrk-fixed-bottom #habla_topbar_div, +#habla_window_div.olrk-fixed-bottom .habla_panel_border { + // -moz-border-radius-topleft:5px; + // -moz-border-radius-topright:5px; + // border-top-left-radius:5px; + // border-top-right-radius:5px; +} + +#habla_window_div.olrk-fixed-top .habla_panel_border { + // -moz-border-radius-bottomleft:5px; + // -moz-border-radius-bottomright:5px; + // border-bottom-left-radius:5px; + // border-bottom-right-radius:5px; +} + +#habla_window_div.olrk-fixed-top #habla_expanded_div { + border-bottom:1px solid lighten( $gray, 30% ); +} + +#habla_window_div .habla_conversation_div { + background:0 0; + border-bottom:1px solid lighten( $gray, 30% ); + line-height:1.5em; + overflow:auto; + color:#000; + width:100%; +} + +#habla_window_div #habla_wcsend_input { + background:0 0; + overflow:auto; + padding:5px; + vertical-align:text-top; + line-height:1.5em; + min-height: 0 !important; + height: auto !important; +} + +#habla_window_div .habla_wcsend_input_normal { + border:1px solid #b6b6b6; + color:#000; +} + +#habla_window_div .habla_wcsend_input_pre { + color: $gray-dark; +} + +#habla_window_div .habla_wcsend_input_highlighted { + border-color: $gray-dark !important; + color:#000; +} + +#habla_window_div .habla_conversation_p_item { + background:0 0; + color:#000; + padding:0; + margin:0 0 0 20px; + text-indent:-20px; + overflow:visible; +} + +#habla_window_div .habla_conversation_person1 { + color: lighten( $gray, 20% ); + padding-right:5px; + display:inline; +} + +#habla_window_div .habla_conversation_person2 { + color: $blue-wordpress; + padding-right:5px; +} + +#habla_window_div .olrk_avatar { + float:right; + border:1px solid #d3d3d3; + margin-left:5px; + margin-bottom:5px; +} + +#habla_window_div #habla_offline_message_span, +#habla_window_div #habla_pre_chat_span { + margin-bottom:5px; + display:block; +} + +#habla_window_div #habla_offline_message_div, +#habla_window_div #habla_pre_chat_div { + line-height:1.5em; +} + +#habla_window_div #habla_offline_message_span { + margin-bottom:5px; + display:block; +} + +#habla_window_div #habla_name_input, +#habla_window_div #habla_offline_body_input, +#habla_window_div #habla_offline_email_input, +#habla_window_div #habla_pre_chat_email_input, +#habla_window_div #habla_pre_chat_name_input { + padding: 5px; + margin-bottom: 5px; + min-height: 0 !important; + height: auto!important; +} + +#habla_window_div .habla_offline_submit_input { + border-radius: 3px; + border-style: solid; + border-width: 1px 1px 2px; + cursor: pointer; + display: inline-block; + font-size: 13px; + margin: 0; + outline: 0; + overflow: hidden; + padding: .4em .9em; + text-overflow: ellipsis; + text-decoration: none; + vertical-align: top; + white-space: nowrap; + appearance: none; + box-shadow: 0 -1px 0 rgba(255,255,255,0.8) inset; + box-sizing: border-box; + background: $blue-medium; + border-color: shade( $blue-medium, 15% ); + border-top-color: shade( $blue-medium, 10% ); + border-bottom-color: shade( $blue-medium, 20% ); + color: $white; + box-shadow: 0 -1px 0 rgba(255,255,255,0.15) inset; + + &:hover, + &:focus { + background: $link-highlight; + border-color: shade($link-highlight, 15%); + border-bottom-color: shade($link-highlight, 20%) + } + + &:focus { + border-color: $gray-dark; // MT / check this color + box-shadow: inset 0 1px 0 rgba(120, 200, 230, .6), 1px 1px 2px rgba(0, 0, 0, .4); + } +} + +#habla_window_div #habla_pre_chat_error_span, +#habla_window_div .habla_offline_error_span { + margin-top:-20px; + float:left; + padding-bottom:10px; + font-style:italic; + line-height:1.5em; +} + +#habla_window_div #habla_topbar_div { + background: $blue-medium; + color: $white; + padding:10px; + cursor:pointer; +} + +#habla_window_div #habla_oplink_a { + color:#fff; + text-decoration:none; +} + +#habla_window_div #habla_oplink_a.habla_oplink_a_hover { + text-decoration:underline; +} + +#habla_window_div .clear_style { + clear:both; +} + +#habla_window_div .habla_button { + float:right; + margin-top:-1px; + margin-left:4px; + padding:0; + width:16px; + height:16px; + cursor:pointer!important; + overflow:hidden; +} + +#habla_window_div .habla_button:hover { + background-color: rgba(255, 255, 255, 0.15); +} + +#habla_window_div #habla_sizebutton_a { + + &:before { + display: inline-block; + width: 16px; + height: 16px; + font: 16px/1 Noticons; + content: '\f108'; + } +} + +.olrk-state-expanded #habla_window_div #habla_sizebutton_a { + + &:before { + display: inline-block; + width: 16px; + height: 16px; + font: 16px/1 Noticons; + content: '\f431'; + } +} + +#habla_window_div #habla_sizebutton_a:hover { + background-color: rgba(255, 255, 255, 0.15); +} + +#habla_window_div #habla_closebutton_a { + + &:before { + display: inline-block; + width: 16px; + height: 16px; + font: 16px/1 Noticons; + content: '\f405'; + } +} + +#habla_window_div #habla_closebutton_a:hover { + background-color: rgba(255, 255, 255, 0.15); +} + +#habla_window_div #habla_popout_a { + + &:before { + width: 16px; + height: 16px; + font: 16px/1 Noticons; + content: '\f442'; + } +} + +#habla_window_div #habla_popout_a:hover { + background-color: rgba(255, 255, 255, 0.15); +} + +#habla_window_div #habla_panel_div #habla_conversation_div a, +#habla_window_div #habla_panel_div #habla_conversation_div a:active, +#habla_window_div #habla_panel_div #habla_conversation_div a:visited, +#habla_window_div #habla_panel_div #habla_expanded_div a, +#habla_window_div #habla_panel_div #habla_expanded_div a:active, +#habla_window_div #habla_panel_div #habla_expanded_div a:visited { + color: $blue-wordpress; +} + +#habla_conversation_div .habla_conversation_p_item { + word-break: break-word; + word-wrap: break-word; +} + +#habla_conversation_div .olark-feedback-wrapper { + background-color:#fff!important; + border:1px solid #e6e6e6; + border-radius:0; + -webkit-border-radius:0; + -moz-border-radius:0; + color:$gray-dark; + padding:10px 10px 12px!important; + filter:none!important; +} + +#habla_conversation_div p .olark-feedback-wrapper { + color:$gray-dark; + color:rgba(0,0,0,.7); + line-height:1.2em; + font-size:13px; +} + +#habla_conversation_div p.olark-feedback-question { + color:$gray-dark; + color:rgba(0,0,0,.7); + font-weight:700; +} + +#habla_conversation_div .olark-feedback-error { + background-color:#FF9581; + border-radius:2px; + -webkit-border-radius:2px; + -moz-border-radius:2px; + color:#fff; + margin-bottom:3px; + padding:5px; +} + +#habla_conversation_div .olark-feedback-hidden { + display:none; +} + +#habla_conversation_div .olark-feedback-high-answer, +#habla_conversation_div .olark-feedback-low-answer { + background:#E4E089; + border-radius:2px; + -webkit-border-radius:2px; + -moz-border-radius:2px; + color:$gray-dark; + display:inline-block; + font-size:12px; + line-height:1em; + margin:8px 0 15px; + padding:5px; + position:relative; + text-align:center; + max-width:42%; +} + +#habla_conversation_div .olark-feedback-high-answer { + float:right; +} + +#habla_conversation_div .olark-feedback-high-answer:after, +#habla_conversation_div .olark-feedback-low-answer:after, +#habla_conversation_div p .olark-feedback-high-answer:before, +#habla_conversation_div p .olark-feedback-low-answer:before { + content:""; + position:absolute; + width:0; + height:0; +} + +#habla_conversation_div .olark-feedback-low-answer:after, +#habla_conversation_div p .olark-feedback-low-answer:before { + left:5px; + bottom:-5px; + border:4px solid; + border-color:#E4E089 transparent transparent #E4E089; +} + +#habla_conversation_div .olark-feedback-high-answer:after, +#habla_conversation_div p .olark-feedback-high-answer:before { + right:5px; + bottom:-5px; + border:4px solid; + border-color:#E4E089 #E4E089 transparent transparent; +} + +#habla_conversation_div .olark-feedback-choices-wrap { + border-top:2px solid #CACACA; + clear:both; + height:15px; + text-align:justify; +} + +#habla_conversation_div .olark-feedback-radio { + -webkit-appearance:radio; +} + +#habla_conversation_div .olark-feedback-input { + border:0; + display:inline-block; + margin-top:-20px; +} + +#habla_conversation_div .olark-feedback-choices-wrap:after { + content:''; + width:100%; + display:inline-block; +} + +#habla_conversation_div .olark-feedback-question-number { + color:$gray-dark; + display:inline-block; + font-size:13px; + padding:6px 0; + margin-right:5px; +} + +#habla_conversation_div .olark-feedback-text { + box-sizing:border-box; + color:$gray-dark; + font-size:14px; + min-height:100px; + margin-bottom:5px; + padding:3px; +} + +#habla_conversation_div .olark-feedback-placeholder { + color:#AAA; +} + +#habla_conversation_div .olark-feedback-submit { + background:#1eaedb; + border:0; + border-radius:2px; + -webkit-border-radius:2px; + -moz-border-radius:2px; + color:#fff; + display:inline-block; + font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif; + font-size:13px; + font-weight:700; + line-height:1em; + padding:5px; +} + +#habla_conversation_div .olark-feedback-submit:disabled { + background:#DDD; + color:$gray-dark; +} + +#habla_conversation_div .habla_conversation_notification.olark-feedback-wrapper { + color:$gray-dark!important; +} + +#habla_conversation_div .habla_conversation_notification { + float: left; + color: $gray; + font-style: italic; + margin: 1em 0; +} + +@-webkit-keyframes pulse { + 50% { + background-color:rgba(255,0,0,.7) + } +} + +@-webkit-keyframes tab_in_bottom{ + 0% { + margin-bottom:-50px; + padding-bottom:10px; + } + 50% { + margin-bottom:0; + padding-bottom:15px; + } + 100% { + padding-bottom:10px; + } +} + +@-webkit-keyframes tab_in_top { + 0% { + margin-top:-50px; + padding-top:10px; + } + 50% { + margin-top:0; + padding-top:15px; + } + 100% { + padding-top:10px; + } +} + +.olrk-state-compressed .olrk-fixed-bottom #habla_topbar_div { + -webkit-animation-name:tab_in_bottom; + -webkit-animation-duration:1s; + -webkit-animation-iteration-count:1; + -webkit-animation-direction:alternate; + -webkit-animation-timing-function:ease-in-out; +} + +.olrk-state-compressed .olrk-fixed-top #habla_topbar_div { + -webkit-animation-name:tab_in_top; + -webkit-animation-duration:1s; + -webkit-animation-iteration-count:1; + -webkit-animation-direction:alternate; + -webkit-animation-timing-function:ease-in-out; +} + +#habla_window_div .habla_topbar_div_highlighted { + background:#d05c34; + color:#FFF; + -webkit-animation-name:pulse; + -webkit-animation-duration:3s; + -webkit-animation-iteration-count:2; + -webkit-animation-direction:alternate; + -webkit-animation-timing-function:ease-in-out; +} + +a.hbl_pal_title_fg { + color:!important; +} + +.hbl_pal_main_bg { + background-color:#fff!important; +} + +.hbl_pal_local_fg, +.hbl_pal_title_fg { + color:!important; +} + +.hbl_pal_title_bg { + background-color:!important; +} + +.hbl_pal_offline_submit_fg, +.hbl_pal_remote_fg { + color:!important; +} + +.hbl_pal_offline_submit_bg { + background-color:!important; +} + +div.hbl_pal_main_height { + // height:150px!important; +} + +div.hbl_pal_main_width { + width: 267px!important; +} + +.olrk-fixed-top { + position:fixed; + bottom:auto; + top:0; +} + +.olrk-fixed-bottom { + position:fixed; + bottom:0; + top:auto; +} + +.olrk-fixed-left { + position:fixed; + right:auto; + left:0; +} + +.olrk-fixed-right { + position:fixed; + right:0; + left:auto; +} + +.habla_window_div_position { + bottom:0; + position:fixed; + right:0; + margin-right:10px; + margin-bottom:10px; +} + +.habla_window_div_position_floating { + bottom:0; + position:fixed; + right:0; + margin-right:10px; + margin-bottom:10px; +} + +.habla_window_div_position_floating_ie { + bottom:0; + position:absolute; + right:0; + margin-right:10px; + margin-bottom:10px; +} + +.olrk-state-compressed #habla_window_div #habla_topbar_div { + margin-right: -10px; + background: transparent; +} + +.olrk-state-compressed #habla_panel_div { + background: transparent !important; +} + +.olrk-state-compressed #habla_window_div #habla_sizebutton_a { + background-color: $blue-medium; + padding: 5px 5px 3px 5px; + text-decoration: none; +} + +.olrk-state-compressed #habla_window_div #habla_closebutton_a { + display: none; +} +.olrk-state-compressed #habla_oplink_a { + display: none; +} + +.olrk-state-compressed div.hbl_pal_main_width { + width: 28px !important; +} diff --git a/assets/stylesheets/shared/_reset.scss b/assets/stylesheets/shared/_reset.scss new file mode 100644 index 00000000000000..db5621ff9f6949 --- /dev/null +++ b/assets/stylesheets/shared/_reset.scss @@ -0,0 +1,78 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + border: 0; + font-family: inherit; + font-size: 100%; + font-style: inherit; + font-weight: inherit; + margin: 0; + outline: 0; + padding: 0; + vertical-align: baseline; +} +html { + font-size: 62.5%; /* Corrects text resizing oddly in IE6/7 when body font-size is set using em units http://clagnut.com/blog/348/#c790 */ + overflow-y: scroll; /* Keeps page centred in all browsers regardless of content height */ + -webkit-text-size-adjust: 100%; /* Prevents iOS text size adjust after orientation change, without disabling user zoom */ + -ms-text-size-adjust: 100%; /* www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/ */ +} +body { + background: #fff; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} +ol, ul { + list-style: none; +} +table { /* tables still need 'cellspacing="0"' in the markup */ + border-collapse: separate; + border-spacing: 0; +} +caption, th, td { + font-weight: normal; + text-align: left; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ""; +} +blockquote, q { + quotes: "" ""; +} +a:focus { + outline: thin dotted; +} +a:hover, +a:active { /* Improves readability when focused and also mouse hovered in all browsers people.opera.com/patrickl/experiments/keyboard/test */ + outline: 0; +} +a img { + border: 0; +} + +// Reset the default styling on form inputs in Webkit/iOS +input, +textarea { + border-radius: 0; + appearance: none; +} +input[type="radio"], +input[type="checkbox"] { + -webkit-appearance: none; +} \ No newline at end of file diff --git a/assets/stylesheets/shared/_toolbar-bulk.scss b/assets/stylesheets/shared/_toolbar-bulk.scss new file mode 100644 index 00000000000000..e93ab7003c193c --- /dev/null +++ b/assets/stylesheets/shared/_toolbar-bulk.scss @@ -0,0 +1,248 @@ +// ========================================================================== +// .toolbar-bulk +// +// The toolbar used for bulk actions including bulk selecting and deselecting. +// ========================================================================== + + +.toolbar-bulk { + display: none; + position: relative; + margin-bottom: 1px; + min-height: 55px; + background: $gray-light; + box-shadow: 0 0 0 1px transparentize( lighten( $gray, 20% ), .5 ), + 0 1px 2px lighten( $gray, 30 ); + transition: margin .15s ease-in-out; + z-index: 2; // so menus appear above items + + a { + cursor: pointer; + } + + &.is-bulk-editing { + display: block; + background: #fff; + + .toolbar-bulk__toggle { + background: lighten( $gray, 30% ); + background: $gray-light; + } + } +} + +.toolbar-bulk__toggle { + position: relative; + float:right; + display: block; + padding: 4px 10px; + background:#fff; + border-radius: 2px; + font-size: 10px; + color: $gray; + line-height: 1.5; + cursor: pointer; + z-index: 30; +} + +// Bulk options +.toolbar-bulk__actions { + @include clear-fix; + opacity: 0; + pointer-events: none; + transition: opacity .15s ease-in-out; + + .is-bulk-editing & { + opacity: 1; + pointer-events: auto; + } +} + +// Includes tristate checkbox and dropdown for partial selections +.toolbar-bulk__check-all { + float: left; + position: relative; + border-right: 1px solid transparentize( lighten( $gray, 20% ), .5 ); + z-index: 1; + display: flex; + align-items: center; + + .checkbox-tristate { + margin: 0 0 0 24px; + } + +} + +.toolbar-bulk__selection-options-toggle[type="checkbox"] { + display: none; +} + +.toolbar-bulk__selection-options-label.noticon { // TODO: remove .noticon + height: 55px; + padding: 0 8px; + color: $blue-wordpress; + line-height: 55px; + cursor: pointer; +} + +.toolbar-bulk__selection-options { + display: none; + position: absolute; + top: 100%; + left: 0; + z-index: 1; + border: 1px solid transparentize( lighten( $gray, 20% ), .5 ); + border-left: 0; + background: #fff; + line-height: 1.5; + z-index: 1; + + .toolbar-bulk__selection-options-toggle:checked ~ & { + display: block; + } +} + +.toolbar-bulk__selection-item { + display: block; + padding: 12px 20px; + font-size: 14px; + border-bottom: 1px solid transparentize( lighten( $gray, 20% ), .5 ); + white-space: pre; + + &:last-child { + border: 0; + } +} + + +// Bulk actions dropdown styles +.toolbar-bulk__action-options-toggle[type="checkbox"] { + display: none; +} + +// For mobile menu dropdown +.toolbar-bulk__action-options-label { + padding-left: 15px; + color: lighten( $gray, 30% ); + font-size: 14px; + line-height: 55px; + cursor: pointer; + pointer-events: none; + + .some-selected &, + .all-selected & { + color: $blue-wordpress; + pointer-events: auto; + } + .noticon { + margin-left: 4px; + line-height: 55px; + } + @include breakpoint( ">660px" ) { + display: none; + } +} + +// wrap everything in this +.toolbar-bulk__action-options { + @include clear-fix; + display: none; + clear: both; + border-top: 1px solid transparentize( lighten( $gray, 20% ), .5 ); + + a { + display: block; + padding: 12px 20px; + border-bottom: 1px solid transparentize( lighten( $gray, 20% ), .5 ); + font-size: 14px; + white-space: pre; + } + .toolbar-bulk__action-options-toggle:checked ~ & { + display: block; + } + @include breakpoint( ">660px" ) { + display: block; + border: 0; + opacity: 0; + clear: none; + + .some-selected &, + .all-selected & { + opacity: 1; + } + a { + display: inline-block; + padding: 0 10px; + line-height: 56px; + border: 0; + } + } +} + +.toolbar-bulk__action-group { + &:last-child { + a:last-child { + border: 0; + } + } + .noticon { + display: none; + } + @include breakpoint( ">660px" ) { + position: relative; + display: block; + float: left; + border-right: 1px solid transparentize( lighten( $gray, 20% ), .5 ); + + .noticon { + display: inline-block; + } + .toolbar-bulk__more-actions-toggle { + margin-left: -10px; + } + .noticon-trash { + font-size: 20px; + + a { + display: none; + } + } + } +} + +// Allows for dropdowns with more actions +.toolbar-bulk__more-actions { + @include breakpoint( ">660px" ) { + display: none; + position: absolute; + top: 100%; + left: 0; + margin: 0 0 0 -1px; + min-width: 200px; + width: 100%; + background: #fff; + border: 1px solid transparentize( lighten( $gray, 20% ), .5 ); + z-index: 1; + + &:before { + content: ''; + position: absolute; + top: -2px; // keeps hover state active despite 2px gap caused by borders + left: 0; + width: 100%; + height: 2px; + } + a { + display: block; + line-height: 44px; + border-bottom: 1px solid transparentize( lighten( $gray, 20% ), .5 ); + + &:last-child { + border: 0; + } + } + .toolbar-bulk__action-group:hover > &, + &:hover { + display: block; + } + } +} diff --git a/assets/stylesheets/shared/_typography.scss b/assets/stylesheets/shared/_typography.scss new file mode 100644 index 00000000000000..da33747201b66c --- /dev/null +++ b/assets/stylesheets/shared/_typography.scss @@ -0,0 +1,26 @@ +// Typeface Variables + +$monospace: "Courier 10 Pitch", Courier, monospace; +$code: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", $monospace; + +$serif-fallback: Georgia, "Times New Roman", Times, serif; +$serif: Merriweather, $serif-fallback; + +$sans-fallback: Helvetica, Arial, sans-serif; +$sans: "Open Sans", $sans-fallback; // 400 400i 600 700 700i + +$sans-rtl: Tahoma, $sans-fallback; + +%content-font { + font-family: $serif; + font-weight: 400; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + color: darken( $gray, 30 ); +} + + +// NOTE: +// If there are exceptions to these stacks, +// please mark them with a //typography-exception comment +// so we can easily search for them later. diff --git a/assets/stylesheets/shared/_utilities.scss b/assets/stylesheets/shared/_utilities.scss new file mode 100644 index 00000000000000..71fc30b6df334e --- /dev/null +++ b/assets/stylesheets/shared/_utilities.scss @@ -0,0 +1,26 @@ +// Text meant only for screen readers +.screen-reader-text { // TODO add _accessibility.scss + clip: rect(1px, 1px, 1px, 1px); + position: absolute !important; + + &:hover, + &:active, + &:focus { + background-color: #f1f1f1; + border-radius: 3px; + box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6); + clip: auto !important; + color: #21759b; + display: block; + font-size: 14px; + font-weight: bold; + height: auto; + left: 5px; + line-height: normal; + padding: 15px 23px 14px; + text-decoration: none; + top: 5px; + width: auto; + z-index: 100000; // Above WP toolbar + } +} diff --git a/assets/stylesheets/shared/_welcome.scss b/assets/stylesheets/shared/_welcome.scss new file mode 100644 index 00000000000000..530d0b99317a2c --- /dev/null +++ b/assets/stylesheets/shared/_welcome.scss @@ -0,0 +1,65 @@ +/** +* Welcome Messages (currently on stats and post pages) +*/ + +.welcome-message { + @extend %container; + position: relative; + background: $gray-light; + margin-bottom: 6%; + padding: 16px; + + .close-button { + position: absolute; + top: 0; + right: 0; + display: block; + padding: 14px 8px; + + .noticon { + font-size: 32px; + line-height: 32px; + } + + // Focus state + &:focus { + outline: none; + color: $link-highlight; + } + } + + .welcome-section-title { + @extend %heading; + + font-size: 21px; + line-height: 24px; + color: $gray; + + margin-top: 0; + margin-bottom: 20px; + padding-right: 20px; + } + + p:last-child { + margin-bottom: 0; + } + + .welcome-intro-illustration { + width: 160px; + height: 160px; + float: right; + margin: 0 0 1em 1em; + + @include breakpoint( "<480px" ) { + width: 120px; + height: 120px; + } + } + + @include breakpoint( ">660px" ) { + padding: 24px; + .close-button { + padding: 8px; + } + } +} diff --git a/assets/stylesheets/shared/mixins/_breakpoints.scss b/assets/stylesheets/shared/mixins/_breakpoints.scss new file mode 100644 index 00000000000000..035bf65054cc70 --- /dev/null +++ b/assets/stylesheets/shared/mixins/_breakpoints.scss @@ -0,0 +1,58 @@ +// ========================================================================== +// Breakpoint Mixin +// See https://wpcalypso.wordpress.com/devdocs/docs/coding-guidelines/css.md#media-queries +// ========================================================================== + +$breakpoints: 480px, 660px, 960px, 1040px; // Think very carefully before adding a new breakpoint + +@mixin breakpoint( $size ){ + @if type-of($size) == string { + $approved-value: 0; + @each $breakpoint in $breakpoints { + $and-larger: ">" + $breakpoint; + $and-smaller: "<" + $breakpoint; + + @if $size == $and-smaller { + $approved-value: 1; + @media ( max-width: $breakpoint ) { + @content; + } + } + @else { + @if $size == $and-larger { + $approved-value: 2; + @media ( min-width: $breakpoint + 1 ) { + @content; + } + } + @else { + @each $breakpoint-end in $breakpoints { + $range: $breakpoint + "-" + $breakpoint-end; + @if $size == $range { + $approved-value: 3; + @media ( min-width: $breakpoint + 1 ) and ( max-width: $breakpoint-end ) { + @content; + } + } + } + } + } + } + @if $approved-value == 0 { + $sizes: ""; + @each $breakpoint in $breakpoints { + $sizes: $sizes + " " + $breakpoint; + } + // TODO - change this to use @error, when it is supported by node-sass + @warn "ERROR in breakpoint( #{ $size } ): You can only use these sizes[ #{$sizes} ] using the following syntax [ <#{ nth( $breakpoints, 1 ) } >#{ nth( $breakpoints, 1 ) } #{ nth( $breakpoints, 1 ) }-#{ nth( $breakpoints, 2 ) } ]"; + } + } + @else { + $sizes: ""; + @each $breakpoint in $breakpoints { + $sizes: $sizes + " " + $breakpoint; + } + // TODO - change this to use @error, when it is supported by node-sass + @warn "ERROR in breakpoint( #{ $size } ): Please wrap the breakpoint $size in parenthesis. You can use these sizes[ #{$sizes} ] using the following syntax [ <#{ nth( $breakpoints, 1 ) } >#{ nth( $breakpoints, 1 ) } #{ nth( $breakpoints, 1 ) }-#{ nth( $breakpoints, 2 ) } ]"; + } +} diff --git a/assets/stylesheets/shared/mixins/_calc.scss b/assets/stylesheets/shared/mixins/_calc.scss new file mode 100644 index 00000000000000..343a891b51fc9c --- /dev/null +++ b/assets/stylesheets/shared/mixins/_calc.scss @@ -0,0 +1,6 @@ +@mixin calc($property, $expression) { + #{$property}: -moz-calc(#{$expression}); + #{$property}: -o-calc(#{$expression}); + #{$property}: -webkit-calc(#{$expression}); + #{$property}: calc(#{$expression}); +} diff --git a/assets/stylesheets/shared/mixins/_clear-fix.scss b/assets/stylesheets/shared/mixins/_clear-fix.scss new file mode 100644 index 00000000000000..5a69a1ef735868 --- /dev/null +++ b/assets/stylesheets/shared/mixins/_clear-fix.scss @@ -0,0 +1,13 @@ +// ========================================================================== +// Clear fix mixin (clearfix) +// ========================================================================== + +@mixin clear-fix { + &:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; + } +} diff --git a/assets/stylesheets/shared/mixins/_dropdown-menu.scss b/assets/stylesheets/shared/mixins/_dropdown-menu.scss new file mode 100644 index 00000000000000..ffaf038f226d5a --- /dev/null +++ b/assets/stylesheets/shared/mixins/_dropdown-menu.scss @@ -0,0 +1,62 @@ +// ========================================================================== +// Dropdown menu mixin +// Turn a list into a dropdown menu +// ========================================================================== + +@mixin dropdown-menu { + display: none; + background: $white; + float: none; + line-height: 46px; + min-width: 220px; + overflow: visible; + padding: 0; + position: absolute; + width: auto; + z-index: 1; + box-sizing: border-box; + box-shadow: 0 0 2px rgba(0,0,0,0.15), 0 3px 8px rgba(0,0,0,0.1); + + &:after { + border: 6px solid transparent; + border-bottom-color: $white; + content: ' '; + height: 0; + position: absolute; + top: -12px; + left: 73px; + width: 0; + } + + li { + display: block; + float: none; + + a, + a.selected { + border-bottom: 1px solid rgba(0,0,0,0.1); + color: $blue-wordpress; + display: block; + float: none; + height: auto; + margin: 0; + padding: 0 14px; + text-align: left; + + &:hover { + border-bottom: 1px solid rgba(0,0,0,0.1); + background: none; // Remove inherited background color + color: $link-highlight; + box-shadow: none; // Remove inherited box shadow + } + } + + a.selected { + color: $gray-dark; + } + + &:last-child a { + border-bottom: none; // Last child in the dropdown doesn't need a bottom border + } + } +} diff --git a/assets/stylesheets/shared/mixins/_hide-content-accessibly.scss b/assets/stylesheets/shared/mixins/_hide-content-accessibly.scss new file mode 100644 index 00000000000000..69b3155edf4110 --- /dev/null +++ b/assets/stylesheets/shared/mixins/_hide-content-accessibly.scss @@ -0,0 +1,12 @@ +// ========================================================================== +// Hide content accessibly mixin +// Hides content in a way that makes it still accessible to screen readers +// ========================================================================== + +@mixin hide-content-accessibly { + clip: rect( 1px, 1px, 1px, 1px ); + height: 1px; + overflow: hidden; + position: absolute; + width: 1px; +} diff --git a/assets/stylesheets/shared/mixins/_long-content-fade.scss b/assets/stylesheets/shared/mixins/_long-content-fade.scss new file mode 100644 index 00000000000000..f6b5919bdbd786 --- /dev/null +++ b/assets/stylesheets/shared/mixins/_long-content-fade.scss @@ -0,0 +1,61 @@ +// ========================================================================== +// Long content fade mixin +// +// Creates a fading overlay to signify that the content is longer +// than the space allows. +// ========================================================================== + +@mixin long-content-fade( $direction: right, $size: 20%, $color: #fff, $edge: 0px, $z-index: false) { + content: ''; + display: block; + position: absolute; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + pointer-events: none; + + @if $z-index { + z-index: $z-index; + } + + @if $direction == 'bottom' { + background: linear-gradient( to top, rgba( $color, 0 ), $color 90% ); + left: $edge; + right: $edge; + top: $edge; + bottom: calc(100% - $size); + width: auto; + } + + @if $direction == 'top' { + background: linear-gradient( to bottom, rgba( $color, 0 ), $color 90% ); + top: calc(100% - $size); + left: $edge; + right: $edge; + bottom: $edge; + width: auto; + } + + @if $direction == 'left' { + background: linear-gradient( to left, rgba( $color, 0 ), $color 90% ); + top: $edge; + left: $edge; + bottom: $edge; + right: auto; + width: $size; + height: auto; + } + + @if $direction == 'right' { + background: linear-gradient( to right, rgba( $color, 0 ), $color 90% ); + top: $edge; + bottom: $edge; + right: $edge; + left: auto; + width: $size; + height: auto; + } +} diff --git a/assets/stylesheets/shared/mixins/_mixins.scss b/assets/stylesheets/shared/mixins/_mixins.scss new file mode 100644 index 00000000000000..501d3774e2c9ae --- /dev/null +++ b/assets/stylesheets/shared/mixins/_mixins.scss @@ -0,0 +1,9 @@ +@import 'breakpoints'; +@import 'calc'; +@import 'clear-fix'; +@import 'dropdown-menu'; +@import 'hide-content-accessibly'; +@import 'long-content-fade'; +@import 'noticon'; +@import 'placeholder'; +@import 'stats-fade-text'; diff --git a/assets/stylesheets/shared/mixins/_noticon.scss b/assets/stylesheets/shared/mixins/_noticon.scss new file mode 100644 index 00000000000000..aa47adf9e81049 --- /dev/null +++ b/assets/stylesheets/shared/mixins/_noticon.scss @@ -0,0 +1,27 @@ +// ========================================================================== +// Noticon mixin (clearfix) +// See http://calypso.localhost:3000/devdocs/docs/coding-guidelines/css.md +// ========================================================================== + +@mixin noticon($char, $size: null) { + // This isn't very clean, but... we'll see ;) + @if $size != 0 { + font-size: $size; + } + content: $char; + + // Copied verbatim + vertical-align: top; + text-align: center; + display: inline-block; + font-family: Noticons; + font-style: normal; + font-weight: normal; + font-variant: normal; + line-height: 1; + text-decoration: inherit; + text-transform: none; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + speak: none; +} diff --git a/assets/stylesheets/shared/mixins/_placeholder.scss b/assets/stylesheets/shared/mixins/_placeholder.scss new file mode 100644 index 00000000000000..93328c884de075 --- /dev/null +++ b/assets/stylesheets/shared/mixins/_placeholder.scss @@ -0,0 +1,14 @@ +// ========================================================================== +// Placeholder mixin +// Adds animation to placeholder section +// ========================================================================== + +@mixin placeholder( $lighten-percentage: 30% ) { + animation: loading-fade 1.6s ease-in-out infinite; + background-color: lighten( $gray, $lighten-percentage ); + color: transparent; + + &:after { + content: '\00a0'; + } +} diff --git a/assets/stylesheets/shared/mixins/_stats-fade-text.scss b/assets/stylesheets/shared/mixins/_stats-fade-text.scss new file mode 100644 index 00000000000000..38245855b8083e --- /dev/null +++ b/assets/stylesheets/shared/mixins/_stats-fade-text.scss @@ -0,0 +1,17 @@ +// ========================================================================== +// Stats fade text mixin +// +// TODO: rename or bundle with stats +// ========================================================================== + +@mixin stats-fade-text($toColor) { + background-image: linear-gradient(to right, $transparent 0%, $toColor 90%); + position: absolute; + z-index: 1; + left: -48px; + top: 0; + bottom: 0; + content: ""; + display: block; + width: 48px; +} diff --git a/assets/stylesheets/style.scss b/assets/stylesheets/style.scss new file mode 100644 index 00000000000000..26d04b48567876 --- /dev/null +++ b/assets/stylesheets/style.scss @@ -0,0 +1,50 @@ +// Shared +@import 'shared/reset'; // css reset before the rest of the styles are defined +@import 'shared/functions'; // functions that we've used from Compass, ported over +@import 'shared/colors'; // import all of our wpcom colors +@import 'shared/utilities'; // Helper classes +@import 'shared/typography'; // all the typographic rules, variables, etc. +@import 'shared/mixins/mixins'; // sass mixins for gradients, bordius radii, etc. +@import 'shared/extends'; // sass extends for commonly used styles +@import 'shared/animation'; // all UI animation +@import 'shared/forms'; // form styling +@import 'shared/dropdowns'; // dropdown styling +@import 'shared/toolbar-bulk'; // The toolbar used for bulk actions including bulk selecting and deselecting +@import 'shared/livechat'; // styles for the popup livechat box +@import 'shared/welcome'; // welcome messages +@import 'shared/infinite-scroll-end'; // Last page marker once infinite scroll has reached end + +// Layouts +@import 'layout/main'; // global layout and responsive styles +@import 'layout/masterbar'; // masterbar styles +@import 'layout/sidebar'; // sidebar styles, shared across most pages +@import 'layout/overlay'; // overlay UX styling +@import 'layout/detail-page'; // detail page styles + +// Sections +@import 'sections/sites'; // sites section styles +@import 'sections/manage'; // manage section styles +@import 'sections/posts'; // posts section styles +@import 'sections/updated-confirmation'; // confirmation boxes for posts/pages +@import 'sections/posts-controls'; // posts controls styles +@import 'sections/post-relative-time-status'; // post relative time styles +@import 'sections/stats'; // stats page styles +@import 'sections/upgrades'; // upgrades page styles +@import 'sections/sharing'; // sharing page styles +@import 'sections/site-settings'; // blog setting styles +@import 'sections/notifications'; // notifications styles +@import 'sections/checkout'; // Checkout styles +@import 'sections/billing-history'; // Billing History styles +@import 'sections/domain-search'; // Domain Search styles +@import 'sections/menus'; // menus page styles +@import 'sections/keyboard-shortcuts'; // keyboard shortcuts menu +@import 'sections/plugins'; +@import 'sections/translator'; +@import 'sections/devdocs'; // developer documentation at /devdocs +@import 'sections/nux-welcome'; // persistent welcome for new users + +// Components +@import 'components'; + +// Devdocs +@import 'devdocs/design/style'; diff --git a/bin/bundler b/bin/bundler new file mode 120000 index 00000000000000..fd6c51b76dddfd --- /dev/null +++ b/bin/bundler @@ -0,0 +1 @@ +../server/bundler/bin/bundler.js \ No newline at end of file diff --git a/bin/generate-devdocs-index b/bin/generate-devdocs-index new file mode 120000 index 00000000000000..c1a548db21d116 --- /dev/null +++ b/bin/generate-devdocs-index @@ -0,0 +1 @@ +../server/devdocs/bin/generate-devdocs-index \ No newline at end of file diff --git a/bin/get-i18n b/bin/get-i18n new file mode 120000 index 00000000000000..e3af0c70808e54 --- /dev/null +++ b/bin/get-i18n @@ -0,0 +1 @@ +../server/i18n/bin/i18n-cli.js \ No newline at end of file diff --git a/bin/i18nlint b/bin/i18nlint new file mode 120000 index 00000000000000..b75bd16f9f4da1 --- /dev/null +++ b/bin/i18nlint @@ -0,0 +1 @@ +../server/i18nlint/bin/i18nlint-cli.js \ No newline at end of file diff --git a/bin/list-assets b/bin/list-assets new file mode 120000 index 00000000000000..ccb50f06dbf462 --- /dev/null +++ b/bin/list-assets @@ -0,0 +1 @@ +../server/bundler/bin/list-assets.js \ No newline at end of file diff --git a/bin/live-reload b/bin/live-reload new file mode 100755 index 00000000000000..9009eda5cbad5a --- /dev/null +++ b/bin/live-reload @@ -0,0 +1,13 @@ +#!/usr/bin/env node + +var livereload = require('livereload'), + server = livereload.createServer({ + exts: [ 'html', 'css', 'scss', 'js', 'jsx', 'png', 'gif', 'jpg', 'svg' ], + applyJSLive: false, + applyCSSLive: false, + exclusions: [ '.git', 'node_modules' ], + originalPath: 'http://calypso.localhost:3000', + debug: true + }); + +server.watch( __dirname + '/..' ); diff --git a/bin/pre-commit b/bin/pre-commit new file mode 100755 index 00000000000000..5bdab6c53deb39 --- /dev/null +++ b/bin/pre-commit @@ -0,0 +1,44 @@ +#!/bin/sh + +echo "\nBy contributing to this project, you license the materials you contribute under the GNU General Public License v2 (or later).\n\n" + +files=$(git diff --cached --name-only --diff-filter=ACM | grep ".jsx*$") +if [ "$files" = "" ]; then + exit 0 +fi + +pass=true + +# i18nlinting. Just have i18nlint issue warnings for now without failing +echo "\nValidating translatable strings:\n" +for file in ${files}; do + result=$(./bin/i18nlint --color ${file}) + if [ $? -ne 0 ]; then + echo "\033[31mi18nlint Failed: \033[0m$result" + echo "\n -----\n" + pass=false + else + echo "\033[32mi18nlint Passed: ${file}\033[0m" + fi +done + +echo "\nValidating .jsx and .js:\n" + +for file in ${files}; do + ./node_modules/.bin/eslint ${file} + if [ $? -ne 0 ]; then + echo "\033[31meslint Failed: ${file}\033[0m" + pass=false + else + echo "\033[32meslint Passed: ${file}\033[0m" + fi +done + +echo "\neslint validation complete\n" + +if ! $pass; then + echo "\033[41mCOMMIT FAILED:\033[0m Your commit contains files that should pass validation tests but do not. Please fix the errors and try again.\n" + exit 1 +else + echo "\033[42mCOMMIT SUCCEEDED\033[0m\n" +fi diff --git a/bin/pre-push b/bin/pre-push new file mode 100755 index 00000000000000..8690ffb9365b88 --- /dev/null +++ b/bin/pre-push @@ -0,0 +1,26 @@ +#!/bin/sh + +echo "\nBy contributing to this project, you license the materials you contribute under the GNU General Public License v2 (or later).\n\n" +echo "\nRunning tests ...\n" +make test +if [ $? -ne 0 ]; then + echo "\n\n\033[41mPUSH NOT ALLOWED:\033[0m The tests are broken! Please fix them and try again.\n" + echo "(If you want to push anyway, you can repeat the command using --no-verify to skip this check)\n" + exit 1 +fi + +echo "\n\n\033[42mPUSH READY TO GO\033[0m\n" + +current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,') +if [ 'master' = $current_branch ] +then + read -p "You're about to push ¡¡¡[ master ]!!!, is that what you intended? [y|n] " -r < /dev/tty + echo + if echo $REPLY | grep -E '^[Yy]$' > /dev/null + then + exit 0 # push will execute + fi + exit 1 # push will not execute +fi +exit 0 + diff --git a/bin/record-env b/bin/record-env new file mode 100755 index 00000000000000..60790671a83233 --- /dev/null +++ b/bin/record-env @@ -0,0 +1,19 @@ +#!/bin/sh + +FILE=$1 + +CURRENT_ENV=$CALYPSO_ENV +if [ "$ENABLE_FEATURES" ]; then + CURRENT_ENV="${CURRENT_ENV} with=\"${ENABLE_FEATURES}\"" +fi +if [ "$DISABLE_FEATURES" ]; then + CURRENT_ENV="${CURRENT_ENV} without=\"${DISABLE_FEATURES}\"" +fi + +if [ -e $FILE ]; then + PREVIOUS_ENV=`cat $FILE` +fi + +if [ ! -e $FILE ] || [ "$PREVIOUS_ENV" != "$CURRENT_ENV" ]; then + echo $CURRENT_ENV > $FILE +fi diff --git a/bin/run-all-tests b/bin/run-all-tests new file mode 100755 index 00000000000000..75b8b63bb8aab2 --- /dev/null +++ b/bin/run-all-tests @@ -0,0 +1,87 @@ +#!/bin/bash + +BASEDIR=$(dirname $0) +FAILED=0 +FAILED_ROUTES=() +RED='\033[0;31m' +BLUE='\033[0;34m' +NO_COLOR='\033[0m' + +if [ "${MULTICORE}" = 1 ]; then + CORES=${CORES:-} +else + CORES=1 +fi + + +# print as many equal signs as the terminal is wide +print_horizontal_rule() { + printf "%$(tput cols)s\n" | tr " " "=" +} + + +__count_core_items() { + echo $(cat /proc/cpuinfo | grep "$1" | sort -u | wc -l) +} + +get_cores__linux() { + local cpus=$(__count_core_items "physical id") + local cores=$(__count_core_items "core id") + echo $((cpus * cores)) +} + +get_core_count() { + if [ -z "${CORES}" ]; then + local cores=1 + # OSX + which sysctl &>/dev/null && cores=$(sysctl -n hw.physicalcpu) + # Unix + test -f /proc/cpuinfo && cores=$(get_cores__linux) + echo $cores + else + echo ${CORES} + fi +} + +__print_usage() { + printf "$BLUE" + echo " +*----------------------------------------------------------------------------------------* +| Experimental parallel testing available | +| Usage: | +| export MULTICORE=1 to enable experimental parallel testing. | +| export CORES=4 to control the number of cores used. Leave unset to utilize all cores. | +*----------------------------------------------------------------------------------------* +" + printf "$NO_COLOR" +} + +run_test_fast() { + echo > .test.log + local cores=$(get_core_count) + echo "Using $cores cores" 1>&2 + __print_usage + xargs -P"${cores}" -I % /bin/bash -c '"$1"/run-tests "$2" || (echo "$2" >> .test.log && false)' -- "${BASEDIR}" % + local exitcode=$? + if [ "$exitcode" -ne 0 ]; then + printf "$RED" + echo "These tests have failed:" + cat .test.log | xargs -I % dirname % | xargs /bin/bash -c 'echo $(cd $(dirname "$1") && pwd)/$(basename "$1")' -- + printf "$NO_COLOR" + echo + else + echo "ALL SYSTEMS GO" + fi + rm -f .test.log + exit "$exitcode" +} + +__cleanup() { + echo Cleaning up + rm -f .test.log +} + +trap __cleanup SIGINT SIGTERM + +# Run all tests +find {$BASEDIR/../client,$BASEDIR/../server} -name Makefile | run_test_fast diff --git a/bin/run-tests b/bin/run-tests new file mode 100755 index 00000000000000..711a048dbb9c74 --- /dev/null +++ b/bin/run-tests @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +NODE_ENV="test" + +for makefile in "$@"; do + cat "$makefile" | grep test: > /dev/null + if [[ $? -eq 0 ]]; then + make -C "$(dirname "$makefile")" --no-print-directory test 2>&1 + fi +done diff --git a/bin/update-dependency b/bin/update-dependency new file mode 100755 index 00000000000000..b87894c5ed0140 --- /dev/null +++ b/bin/update-dependency @@ -0,0 +1,77 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var path = require('path'); +var fs = require('fs'); +var join = path.join; +var read = fs.readFileSync; +var write = fs.writeFileSync; +var readdir = fs.readdirSync; + +var dep = process.argv[2]; +var version = process.argv[3]; +if (!dep || !version) { + console.log('usage:'); + console.log(' ' + process.argv.slice(0, 2).join(' ') + ' '); + return process.exit(2); +} + +console.log(); +console.log(' updating %s to %s', dep, version); +var dirs = [ + 'server', + 'client' +]; + +function visitPackageFiles(dir, callback) { + fs.readdir( dir, function( err, list ) { + if (err) { + callback( err ); + } + + list.forEach( function(file) { + + file = join( dir, file ); + + if ( /package\.json$/.test( file ) ) { + callback( null, file ); + } + + fs.stat(file, function( err, stat ) { + if ( stat && stat.isDirectory() ) { + visitPackageFiles( file, callback ); + } + }); + }); + }); +} + +dirs.forEach( function ( dir ) { + visitPackageFiles( dir, function( err, path ) { + if ( err ) { console.log( err ); } + var conf; + try { + conf = JSON.parse( read( path, 'utf8' ) ); + } catch (e) { + //console.error('skipping %j: %s', name, e); + return; + } + [ 'dependencies', 'devDependencies' ].forEach(function (dependencies) { + if (! conf[dependencies] ) { + return; + } + if (! conf[dependencies][dep] ) { + return; + } + var curr = conf[dependencies][dep]; + console.log(' updating %j %j %s v%s -> v%s', path, dependencies, dep, curr, version); + conf[dependencies][dep] = version; + }); + var json = JSON.stringify(conf, null, 2); + write(path, json + '\n'); + }); +}); +console.log(''); diff --git a/client/README.md b/client/README.md new file mode 100644 index 00000000000000..bf44ff8d8bacad --- /dev/null +++ b/client/README.md @@ -0,0 +1,31 @@ +Client +====== + +This is the heart of Calypso, the client side application. It's pieced together with webpack from different components — both external and internal. ([List of technologies used.](../docs/guide/tech-behind-calypso.md)) It only requires an HTML shell with a body to work with. + +### Main modules + +These are some of the key modules of the application, kept in `client`'s root for clarity: + +* `boot` - the booting file that sets up the application and requires the main sections. +* `config` - generated configuration settings. +* `layout` - handles the main React layout, including the masterbar. Notably, it sets #primary and #secondary used to render the different sections. +* `sections.js` - defines section groups, paths, and main modules. (Used by webpack to generate separate chunks.) + +### Components + +The `/components` folder holds all the internal React components used to build the Calypso UI across sections. Most of these are rendered in `/devdocs/design` for reference. + +### Lib + +The `/lib` folder holds internal modules and utilities that power Calypso. + +### Core Sections + +These represent the top section in the masterbar and handle the controllers for the entire app. Most React components live within their specific section. + +* `my-sites`: the site related admin functionality. Akin to wp-admin. +* `reader`: the home of all Reader sections. +* `notifications`: the notifications panel. +* `me`: the sections under the `/me` route. + diff --git a/client/accept-invite/actions.js b/client/accept-invite/actions.js new file mode 100644 index 00000000000000..ee7db65b72fec7 --- /dev/null +++ b/client/accept-invite/actions.js @@ -0,0 +1,23 @@ +/** + * Internal dependencies + */ +import wpcom from 'lib/wp' ; + +export function createAccount( userData, callback ) { + return wpcom.undocumented().usersNew( + Object.assign( {}, userData, { validate: false } ), + ( error, response ) => { + const bearerToken = response && response.bearer_token; + callback( error, bearerToken ); + } + ); +} + +export function acceptInvite( invite, bearerToken, callback ) { + wpcom.loadToken( bearerToken ); + return wpcom.undocumented().acceptInvite( + invite.blog_id, + invite.invite_slug, + callback + ); +} diff --git a/client/accept-invite/controller.js b/client/accept-invite/controller.js new file mode 100644 index 00000000000000..8cb4c1f839cd7d --- /dev/null +++ b/client/accept-invite/controller.js @@ -0,0 +1,24 @@ +/** + * External Dependencies + */ +import React from 'react'; + +/** + * Internal Dependencies + */ +import i18n from 'lib/mixins/i18n'; +import titleActions from 'lib/screen-title/actions'; +import Main from './main'; + +export default { + acceptInvite( context ) { + titleActions.setTitle( i18n.translate( 'Accept Invite', { textOnly: true } ) ); + + React.unmountComponentAtNode( document.getElementById( 'secondary' ) ); + + React.render( + React.createElement( Main, context.params ), + document.getElementById( 'primary' ) + ); + } +}; diff --git a/client/accept-invite/index.js b/client/accept-invite/index.js new file mode 100644 index 00000000000000..8984073e6c54e2 --- /dev/null +++ b/client/accept-invite/index.js @@ -0,0 +1,16 @@ +/** + * External dependencies + */ +import page from 'page'; + +/** + * Internal dependencies + */ +import controller from './controller'; + +export default () => { + page( + '/accept-invite/:site_id/:invitation_key', + controller.acceptInvite + ); +}; diff --git a/client/accept-invite/invite-form-header/index.jsx b/client/accept-invite/invite-form-header/index.jsx new file mode 100644 index 00000000000000..0522d212286cda --- /dev/null +++ b/client/accept-invite/invite-form-header/index.jsx @@ -0,0 +1,23 @@ +/** + * External dependencies + */ +import React from 'react' + +export default React.createClass( { + displayName: 'InviteFormHeader', + + render() { + return ( +
+

+ { this.props.title } +

+ { this.props.explanation && +

+ { this.props.explanation } +

+ } +
+ ) + } +} ); diff --git a/client/accept-invite/invite-form-header/style.scss b/client/accept-invite/invite-form-header/style.scss new file mode 100644 index 00000000000000..c2b0bb0d459d28 --- /dev/null +++ b/client/accept-invite/invite-form-header/style.scss @@ -0,0 +1,16 @@ +.invite-form-header__title { + color: darken( $gray, 30% ); + font-family: $sans; + font-size: 21px; + font-weight: 300; + line-height: 24px; + margin-bottom: 16px; +} + +.invite-form-header__explanation { + color: $gray-dark; + font-family: $sans; + font-size: 14px; + line-height: 21px; + margin-bottom: 16px; +} diff --git a/client/accept-invite/invite-header/index.jsx b/client/accept-invite/invite-header/index.jsx new file mode 100644 index 00000000000000..6a931b25da3cb6 --- /dev/null +++ b/client/accept-invite/invite-header/index.jsx @@ -0,0 +1,66 @@ +/** + * External dependencies + */ +import React from 'react'; +import classNames from 'classnames'; +import { get } from 'lodash'; + +/** + * Internal dependencies + */ +import CompactCard from 'components/card/compact'; +import Site from 'my-sites/site'; +import SitePlaceholder from 'my-sites/site/placeholder'; +import Gravatar from 'components/gravatar'; + +export default React.createClass( { + displayName: 'InviteHeader', + + getInvitationVerb() { + switch ( get( this.props, 'invite.meta' ) ) { + case 'viewer': + case 'follower': + return this.translate( 'view' ); + break; + default: + return this.translate( 'contribute to' ); + } + }, + + render() { + let classes = classNames( 'invite-header', { 'is-placeholder': ! this.props.invite } ); + return( +
+ +
+ +

+ { + this.translate( '{{strong}}%(user)s{{/strong}} invited you to %(verb)s:', { + args: { + user: get( + this.props, + 'inviter.name', + this.translate( 'User', { context: 'Placeholder text while loading an invitation.' } ) + ), + verb: this.getInvitationVerb() + }, + components: { + strong: + } + } ) + } +

+
+
+ + { + this.props.blog_details + ? + : + } + +
+ ); + } +} ); diff --git a/client/accept-invite/invite-header/mock-data.js b/client/accept-invite/invite-header/mock-data.js new file mode 100644 index 00000000000000..2660dd973cd274 --- /dev/null +++ b/client/accept-invite/invite-header/mock-data.js @@ -0,0 +1,33 @@ +module.exports = { + invite: { + invite_slug: 'asdf2345', + blog_id: 1234, + user_id: 1234, + invited_id: 5678, + signed_up: '0000-00-00 00:00:00', + invite_date: '2015-11-03 16:45:37', + meta: { + role: 'editor' + } + }, + inviter: { + ID: 1234, + login: 'testuser', + email: false, + name: 'Test User', + first_name: 'Test', + last_name: 'User', + URL: 'https://example.com', + avatar_URL: 'https://1.gravatar.com/avatar', + profile_URL: 'http://en.gravatar.com', + site_ID: 1234 + }, + blog_details: { + domain: 'example.com', + title: 'Example WordPress website', + icon: { + img: 'https://secure.gravatar.com/blavatar', + ico: 'https://secure.gravatar.com/blavatar' + } + } +} diff --git a/client/accept-invite/invite-header/style.scss b/client/accept-invite/invite-header/style.scss new file mode 100644 index 00000000000000..1db8861df80215 --- /dev/null +++ b/client/accept-invite/invite-header/style.scss @@ -0,0 +1,36 @@ +.invite-header { + .card { + &.is-compact { + padding: 0px; + + &.invite-header__site { + margin-bottom: 24px; + } + } + } + + .invite-header__inviter-info { + padding: 16px; + display: flex; + align-items: center; + + .gravatar { + width: 32px; + height: 32px; + margin-right: 12px; + } + + p { + margin-bottom: 0; + } + } +} + +.invite-header.is-placeholder { + .invite-header__invited-you-text { + @include placeholder(); + + // Overriding here to match site placeholder + animation: pulse-light 0.8s ease-in-out infinite; + } +} diff --git a/client/accept-invite/logged-in-accept/index.jsx b/client/accept-invite/logged-in-accept/index.jsx new file mode 100644 index 00000000000000..e3097b4ef98e1f --- /dev/null +++ b/client/accept-invite/logged-in-accept/index.jsx @@ -0,0 +1,107 @@ +/** + * External dependencies + */ +import React from 'react'; +import classNames from 'classnames'; + +/** + * Internal dependencies + */ +import Card from 'components/card'; +import Gravatar from 'components/gravatar'; +import Button from 'components/button'; +import config from 'config'; +import userModule from 'lib/user'; +import InviteFormHeader from '../invite-form-header'; + +const user = userModule(); + +const mockData = { + invite: { + invite_slug: 'asdf2345', + blog_id: 1234, + user_id: 1234, + invited_id: 5678, + signed_up: '0000-00-00 00:00:00', + invite_date: '2015-11-03 16:45:37', + meta: { + role: 'editor' + } + }, + blog_details: { + domain: 'example.com', + title: 'Example WordPress website', + icon: { + img: 'https://secure.gravatar.com/blavatar', + ico: 'https://secure.gravatar.com/blavatar' + } + } +}; + +export default React.createClass( { + + displayName: 'LoggedInAccept', + + getInviteRole() { + let meta = mockData.invite && mockData.invite.meta ? mockData.invite.meta : false; + return meta && meta.role ? meta.role : false; + }, + + render() { + let userObject = user.get(), + signInLink = config( 'login_url' ) + '?redirect_to=' + encodeURIComponent( window.location.href ); + + return ( +
+ + + } + } ) + } + explanation={ + this.translate( + 'As an %(siteRole)s you will be able to publish and edit your own posts as well as upload media.', { + args: { + siteRole: this.getInviteRole() + } + } + ) + } + /> +
+ + { + this.translate( 'Join as {{usernameWrap}}%(username)s{{/usernameWrap}}', { + components: { + usernameWrap: + }, + args: { + username: userObject && userObject.display_name + } + } ) + } +
+
+ + +
+
+ + { this.translate( 'Sign in as a different user' ) } + +
+ ); + } +} ); diff --git a/client/accept-invite/logged-in-accept/style.scss b/client/accept-invite/logged-in-accept/style.scss new file mode 100644 index 00000000000000..3117c759026c83 --- /dev/null +++ b/client/accept-invite/logged-in-accept/style.scss @@ -0,0 +1,37 @@ +.logged-in-accept__join-as { + color: darken( $gray, 30% ); + font-family: $sans; + font-size: 21px; + font-weight: 300; + line-height: 24px; + margin-bottom: 16px; + text-align: center; +} + +.logged-in-accept__join-as-username { + font-family: $serif; + font-weight: 600; +} + +.logged-in-accept__join-as .gravatar { + display: block; + margin: 0 auto 8px auto; +} + +.logged-in-accept__button-bar { + display: flex; +} + +.logged-in-accept__button-bar .button { + flex-basis: 0; + flex-grow: 1; + margin: 0 4px; + + &:first-child { + margin-left: 0; + } + + &:last-child { + margin-right: 0; + } +} diff --git a/client/accept-invite/logged-out-invite/index.jsx b/client/accept-invite/logged-out-invite/index.jsx new file mode 100644 index 00000000000000..41d3b049e05e48 --- /dev/null +++ b/client/accept-invite/logged-out-invite/index.jsx @@ -0,0 +1,15 @@ +/** + * External dependencies + */ +import React from 'react' + +/** + * Internal dependencies + */ +import SignupForm from './signup-form' + +export default class LoggedOutInvite extends React.Component { + render() { + return + } +} diff --git a/client/accept-invite/logged-out-invite/signup-form.jsx b/client/accept-invite/logged-out-invite/signup-form.jsx new file mode 100644 index 00000000000000..0c5a7630b567ab --- /dev/null +++ b/client/accept-invite/logged-out-invite/signup-form.jsx @@ -0,0 +1,123 @@ +/** + * External dependencies + */ +import React from 'react' +import debugModule from 'debug'; + +/** + * Internal dependencies + */ +import SignupForm from 'components/signup-form' +import InviteFormHeader from '../invite-form-header' +import { createAccount, acceptInvite } from '../actions' +import WpcomLoginForm from 'signup/wpcom-login-form' + +/** + * Module variables + */ +const debug = debugModule( 'calypso:accept-invite:logged-out' ); + +export default React.createClass( { + + displayName: 'LoggedOutInviteSignupForm', + + getInitialState() { + return { error: false, bearerToken: false, userData: false, submitting: false }; + }, + + getRedirectToAfterLoginUrl() { + return '/accept-invite'; + }, + + submitButtonText() { + return this.translate( 'Sign Up & Join' ); + }, + + submitForm( form, userData ) { + this.setState( { submitting: true } ); + createAccount( + userData, + ( error, bearerToken ) => + bearerToken && + acceptInvite( + this.props.invite, + bearerToken, + ( error, response ) => this.setState( { error, userData, bearerToken } ) + ) + ); + }, + + getInviteRole() { + let meta = this.props.invite && this.props.invite.meta ? this.props.invite.meta : false; + return meta && meta.role ? meta.role : false; + }, + + getFormHeader() { + return ( + + } + } ) + } + explanation={ + this.translate( + 'As an %(siteRole)s you will be able to publish and edit your own posts as well as upload media.', { + args: { + siteRole: this.getInviteRole() + } + } + ) + } + /> + ); + }, + + getRedirectTo() { + const redirectTo = window.location.origin, + { invite } = this.props; + switch ( invite.meta.role ) { + case 'viewer': + case 'follower': + return redirectTo; + break; + default: + return redirectTo + '/posts/' + invite.blog_id ; + } + }, + + loginUser() { + const { userData, bearerToken } = this.state; + return ( + + ) + }, + + render() { + return ( +
+ + { this.state.userData && this.loginUser() } +
+ ) + } + +} ); diff --git a/client/accept-invite/logged-out-invite/style.scss b/client/accept-invite/logged-out-invite/style.scss new file mode 100644 index 00000000000000..2fb39a8b13c0b8 --- /dev/null +++ b/client/accept-invite/logged-out-invite/style.scss @@ -0,0 +1,4 @@ +.logged-out-invite { + margin: 0 auto; + max-width: 400px; +} diff --git a/client/accept-invite/main.jsx b/client/accept-invite/main.jsx new file mode 100644 index 00000000000000..bbd08ab857c8ba --- /dev/null +++ b/client/accept-invite/main.jsx @@ -0,0 +1,96 @@ +/** + * External dependencies + */ +import React from 'react'; +import Debug from 'debug'; +import classNames from 'classnames'; + +/** + * Internal Dependencies + */ +import InviteHeader from './invite-header'; +import LoggedInAccept from './logged-in-accept'; +import LoggedOutInvite from './logged-out-invite'; +import userModule from 'lib/user'; +import InvitesActions from 'lib/invites/actions'; +import InvitesStore from 'lib/invites/stores/invites-validation'; +import EmptyContent from 'components/empty-content'; + +/** + * Module variables + */ +const debug = new Debug( 'calypso:accept-invite' ); +const user = userModule(); + +export default React.createClass( { + + displayName: 'AcceptInvite', + + getInitialState() { + return { + invite: false, + error: false + } + }, + + componentWillMount() { + InvitesActions.fetchInvite( this.props.site_id, this.props.invitation_key ); + InvitesStore.on( 'change', this.refreshInvite ); + }, + + componentWillUnmount() { + InvitesStore.off( 'change', this.refreshInvite ); + }, + + refreshInvite() { + const invite = InvitesStore.getInvite( this.props.site_id, this.props.invitation_key ); + const error = InvitesStore.getInviteError( this.props.site_id, this.props.invitation_key ); + this.setState( { invite, error } ); + }, + + getErrorTitle() { + return this.translate( + 'Oops, your invite is not valid', + { context: 'Title that is display to users when attempting to accept an invalid invite.' } + ); + }, + + getErrorMessage() { + return this.translate( + "We weren't able to verify that invitation.", + { context: 'Message that is displayed to users when an invitation is invalid.' } + ); + }, + + renderForm() { + if ( ! this.state.invite ) { + debug( 'Not rendering form - Invite not set' ); + return null; + } + debug( 'Rendering invite' ); + return user.get() + ? + : ; + }, + + renderError() { + debug( 'Rendering error: ' + JSON.stringify( this.state.error ) ); + return ( + + ); + }, + + render() { + let classes = classNames( 'accept-invite', { 'is-error': !! this.state.error } ); + return ( +
+ { ! this.state.error && } + { this.state.error ? this.renderError() : this.renderForm() } +
+ ); + } +} ); diff --git a/client/accept-invite/style.scss b/client/accept-invite/style.scss new file mode 100644 index 00000000000000..a828490324c1c9 --- /dev/null +++ b/client/accept-invite/style.scss @@ -0,0 +1,8 @@ +.accept-invite { + margin: 0 auto; + max-width: 400px; + + &.is-error { + max-width: none; + } +} diff --git a/client/analytics/Makefile b/client/analytics/Makefile new file mode 100644 index 00000000000000..69f8ac679ed978 --- /dev/null +++ b/client/analytics/Makefile @@ -0,0 +1,11 @@ +REPORTER ?= spec +MOCHA ?= ../../node_modules/.bin/mocha + +# In order to simply stub modules, add test to the NODE_PATH +test: + @NODE_ENV=test NODE_PATH=test:../../client $(MOCHA) --reporter $(REPORTER) + +test-w: + @NODE_ENV=test NODE_PATH=test:../../client $(MOCHA) --reporter min --watch --growl -b + +.PHONY: test diff --git a/client/analytics/README.md b/client/analytics/README.md new file mode 100644 index 00000000000000..475ef3f032c8c3 --- /dev/null +++ b/client/analytics/README.md @@ -0,0 +1,117 @@ +Analytics +========= + +This module includes functionality for interacting with analytics packages. + +Turn on debugging in the JavaScript developer console to view calls being made with the analytics module: + +`localStorage.setItem('debug', 'calypso:analytics');` + + +## Which analytics tool should I use? + +*Page Views* (`analytics.pageView.record`) should be used to record all page views (when the main content body completely changes). This will automatically record the pageview to both Google Analytics and Tracks. + +*Google Analytics* should be used to record all events the user performs on a page that *do not* trigger a page view (this will allow us to determine bounce rate on pages). + +We are using GA to monitor user flows through the user interface of Calypso in order learn where they succeed and fail, as well as determine usage of different sections. *Please do not ship anything that does not have GA tracking in place*, otherwise we will create big gaps in our understanding. + +Automatticians may refer to internal documentation for more information about MC/Tracks. + +# Usage + +```js +// require the module +var analytics = require( 'analytics' ); + +``` + +## PageView Wrapper + +### analytics#pageView#record( pageURL, pageTitle ) + +Record a pageview: + +```js +analytics.pageView.record( '/posts/draft', 'Posts > Drafts' ); +``` + + +## Google Analytics API + +### analytics#ga#recordPageView( pageURL, pageTitle ) + +Record a virtual pageview: + +```js +analytics.ga.recordPageView( '/posts/draft', 'Posts > Drafts' ); +``` + +*Note: Unless you have a strong reason to directly record a pageview to GA, you should use `analytics.pageView.record` instead* + +### analytics#ga#recordEvent( eventCategory, eventAction [, optionLabel, optionValue ] ) + +Record an event: + +```js +analytics.ga.recordEvent( 'Reader', 'Clicked Like' ); +analytics.ga.recordEvent( 'Reader', 'Loaded Next Page', 'page', 2 ); +``` + +For more information and examples about how and when to provide the optional `optionLabel` and `optionValue` parameters, refer to the [Google Analytics Event Tracking documentation](https://developers.google.com/analytics/devguides/collection/analyticsjs/events#overview). + +## Tracks API + +### analytics#tracks#recordEvent( eventName, eventProperties ) + +Record an event with optional properties: + +```js +analytics.tracks.recordEvent( 'calypso_checkout_coupon_apply', { + 'coupon_code': 'abc123' +} ); +``` + +## MC API + +### analytics#mc#bumpStat( group, name ) + +Bump a single WP.com stat. + +```js +analytics.mc.bumpStat( 'newdash_visits', 'sites' ); +``` + +### analytics#mc#bumpStat( obj ) + +Bump multiple WP.com stats: + +```js +analytics.mc.bumpStat( { + 'stat_name1': 'stat_value1', + 'statname2': 'stat_value2' +} ); +``` + +## Google Analytics Naming Conventions + +For page view tracking, you should never pass a dynamic URL, or anything including a specific domain e.g. (/posts/apeatling.wordpress.com). Always pass a placeholder in these instances (/posts/:site). If you do not do this, we cannot accurately track views for a specific page. Titles should always use a ` > ` to break up the hierarchy of the page title. Examples are `Posts > My > Drafts`, `Reader > Following > Edit`, `Sharing > Connections`. + +Events should be categorized by the section they are in. Examples are `Posts`, `Pages`, `Reader`, `Sharing`. Event actions should be written in readable form, and action centric. Good examples are `Clicked Save Button`, `Clicked Like`, `Activated Theme`. + +## Tracks Naming Conventions + +Event names should be prefixed by `calypso_` to make it easy to easy to identify when analyzing the data with our various analytics tools. + +Each token in the event and property names should be separated by an underscore (`_`), not spaces or dashes. + +In order to keep similar events grouped together when output in an alphabetized list (as is typical with ananlytics tools), put the verb at _the end_ of the event name: + +* `calypso_cart_product_add` +* `calypso_cart_product_remove` + +If we had instead used `calypso_add_cart_product` and `calypso_remove_cart_product` for example, then they'd likely be separated in a list of all the event names. + +Finally, for consistency, the verb at the end should not be in the form `add`, `remove`, `view`, `click`, etc and _not_ `adds`, `added`, `adding`, etc. + +With the exception of separating tokens with underscores, these rules do not apply to property names. `coupon_code` is perfectly fine. diff --git a/client/analytics/ad-tracking.js b/client/analytics/ad-tracking.js new file mode 100644 index 00000000000000..5158284d5a5ea7 --- /dev/null +++ b/client/analytics/ad-tracking.js @@ -0,0 +1,189 @@ +/** + * External dependencies + */ +const async = require( 'async' ), + noop = require( 'lodash/utility/noop' ), + map = require( 'lodash/collection/map' ), + some = require( 'lodash/collection/some' ), + debug = require( 'debug' )( 'calypso:ad-tracking' ); + +/** + * Internal dependencies + */ +const loadScript = require( 'lib/load-script' ), + config = require( 'config' ), + isPremium = require( 'lib/products-values' ).isPremium, + isBusiness = require( 'lib/products-values' ).isBusiness; + +/** + * Module variables + */ +let hasLoadedScripts = false, + retargetingInitialized = false; + +/** + * Constants + */ +const FACEBOOK_TRACKING_SCRIPT_URL = 'https://connect.facebook.net/en_US/fbds.js', + GOOGLE_TRACKING_SCRIPT_URL = 'https://www.googleadservices.com/pagead/conversion_async.js', + BING_TRACKING_SCRIPT_URL = 'https://bat.bing.com/bat.js', + GOOGLE_CONVERSION_ID = config( 'google_adwords_conversion_id' ), + TRACKING_IDS = { + freeSignup: { + facebook: '6024523283021', + google: 'd-fNCIe7m1wQ1uXz_AM' + }, + + premiumTrial: { + facebook: '6028365445821', + google: '_q3ECJ--m1wQ1uXz_AM' + }, + + premiumSignup: { + facebook: '6028365447021', + google: 'UMSeCIyYmFwQ1uXz_AM', + bing: '4074038' + }, + + businessTrial: { + facebook: '6028365448821', + google: 'm9zRCNO8m1wQ1uXz_AM' + }, + + businessSignup: { + facebook: '6028365461821', + google: 'JxKBCKK-m1wQ1uXz_AM', + bing: '4074039' + }, + + retargeting: '823166884443641' + }; + +/** + * Globals + */ +if ( ! window._fbq ) { + window._fbq = []; // Facebook global +} + +if ( ! window.uetq ) { + window.uetq = []; // Bing global +} + +function loadTrackingScripts( callback ) { + async.parallel( [ + function( onComplete ) { + loadScript.loadScript( FACEBOOK_TRACKING_SCRIPT_URL, onComplete ); + }, + function( onComplete ) { + loadScript.loadScript( GOOGLE_TRACKING_SCRIPT_URL, onComplete ); + }, + function( onComplete ) { + loadScript.loadScript( BING_TRACKING_SCRIPT_URL, onComplete ); + } + ], function( errors ) { + if ( ! some( errors ) ) { + hasLoadedScripts = true; + + // update Facebook's tracking global + window._fbq.loaded = true; + window._fbq.push( [ 'addPixelId', TRACKING_IDS.retargeting ] ); + + if ( typeof callback === 'function' ) { + callback(); + } + } else { + debug( 'Some scripts failed to load: ', errors ); + } + } ); +} + +function retarget() { + if ( ! hasLoadedScripts ) { + return loadTrackingScripts( retarget ); + } + + if ( ! retargetingInitialized ) { + debug( 'Retargeting initialized' ); + + window._fbq.push( [ 'track', 'PixelInitialized', {} ] ); + retargetingInitialized = true; + } +} + +function recordPurchase( product ) { + let type; + + if ( ! hasLoadedScripts ) { + return loadTrackingScripts( function() { + recordPurchase( type ); + } ); + } + + if ( isPremium( product ) ) { + if ( 0 === product.cost ) { + type = 'premiumTrial'; + } else { + type = 'premiumSignup'; + } + } + + if ( isBusiness( product ) ) { + if ( 0 === product.cost ) { + type = 'businessTrial'; + } else { + type = 'businessSignup'; + } + } + + if ( ! type ) { + return; + } + + debug( 'Recorded purchase', type ); + + // record the purchase w/ Facebook + window._fbq.push( [ + 'track', + TRACKING_IDS[ type ].facebook, + { + value: '0.00', + currency: 'USD' + } + ] ); + + // record the purchase w/ Google + window.google_trackConversion( { + google_conversion_id: GOOGLE_CONVERSION_ID, + google_conversion_label: TRACKING_IDS[ type ].google, + google_remarketing_only: false + } ); + + // record the purchase w/ Bing if a tracking ID is present + if ( TRACKING_IDS[ type ].bing ) { + window.uetq = new UET( { + ti: TRACKING_IDS[ type ].bing, + o: window.uetq + } ); + window.uetq.push( 'pageLoad' ); + window.uetq.push( { ec: 'conversion' } ); + } +} + +module.exports = { + retarget: function( context, next ) { + const nextFunction = typeof next === 'function' ? next : noop; + + if ( config.isEnabled( 'ad-tracking' ) ) { + retarget(); + } + + nextFunction(); + }, + + recordPurchases: function( products ) { + if ( config.isEnabled( 'ad-tracking' ) ) { + map( products, recordPurchase ); + } + } +}; diff --git a/client/analytics/index.js b/client/analytics/index.js new file mode 100644 index 00000000000000..9b14aeec4665ca --- /dev/null +++ b/client/analytics/index.js @@ -0,0 +1,199 @@ +/** + * External dependencies + */ +var debug = require( 'debug' )( 'calypso:analytics' ), + assign = require( 'lodash/object/assign' ); + +/** + * Internal dependencies + */ +var config = require( 'config' ), + loadScript = require( 'lib/load-script' ).loadScript, + _superProps, + _user; + +// Load tracking scripts +window._tkq = window._tkq || []; +window.ga = window.ga || function() { + ( window.ga.q = window.ga.q || [] ).push( arguments ); + }; +window.ga.l = +new Date(); + +loadScript( '//stats.wp.com/w.js?48' ); +loadScript( '//www.google-analytics.com/analytics.js' ); + +function buildQuerystring( group, name ) { + var uriComponent = ''; + + if ( 'object' === typeof group ) { + for ( var key in group ) { + uriComponent += '&x_' + encodeURIComponent( key ) + '=' + encodeURIComponent( group[ key ] ); + } + debug( 'Bumping stats %o', group ); + } else { + uriComponent = '&x_' + encodeURIComponent( group ) + '=' + encodeURIComponent( name ); + debug( 'Bumping stat "%s" in group "%s"', name, group ); + } + + return uriComponent; +} + +function buildQuerystringNoPrefix( group, name ) { + var uriComponent = ''; + + if ( 'object' === typeof group ) { + for ( var key in group ) { + uriComponent += '&' + encodeURIComponent( key ) + '=' + encodeURIComponent( group[ key ] ); + } + debug( 'Built stats %o', group ); + } else { + uriComponent = '&' + encodeURIComponent( group ) + '=' + encodeURIComponent( name ); + debug( 'Built stat "%s" in group "%s"', name, group ); + } + + return uriComponent; +} + +var analytics = { + + initialize: function( user, superProps ) { + analytics.setUser( user ); + analytics.setSuperProps( superProps ); + analytics.identifyUser(); + }, + + setUser: function( user ) { + _user = user; + }, + + setSuperProps: function( superProps ) { + _superProps = superProps; + }, + + mc: { + bumpStat: function( group, name ) { + var uriComponent = buildQuerystring( group, name ); // prints debug info + if ( config( 'mc_analytics_enabled' ) ) { + new Image().src = document.location.protocol + '//pixel.wp.com/g.gif?v=wpcom-no-pv' + uriComponent + '&t=' + Math.random(); + } + }, + + bumpStatWithPageView: function( group, name ) { + // this function is fairly dangerous, as it bumps page views for wpcom and should only be called in very specific cases. + var uriComponent = buildQuerystringNoPrefix( group, name ); // prints debug info + if ( config( 'mc_analytics_enabled' ) ) { + new Image().src = document.location.protocol + '//pixel.wp.com/g.gif?v=wpcom' + uriComponent + '&t=' + Math.random(); + } + } + }, + + // pageView is a wrapper for pageview events across Tracks and GA + pageView: { + record: function( urlPath, pageTitle ) { + analytics.tracks.recordPageView( urlPath ); + analytics.ga.recordPageView( urlPath, pageTitle ); + } + }, + + tracks: { + recordEvent: function( eventName, eventProperties ) { + var superProperties; + + eventProperties = eventProperties || {}; + + debug( 'Record event "%s" called with props %s', eventName, JSON.stringify( eventProperties ) ); + + if ( eventName.indexOf( 'calypso_' ) !== 0 ) { + debug( '- Event name must be prefixed by "calypso_"' ); + return; + } + + if ( _superProps ) { + superProperties = _superProps.getAll(); + debug( '- Super Props: %o', superProperties ); + eventProperties = assign( eventProperties, superProperties ); + } + + window._tkq.push( [ 'recordEvent', eventName, eventProperties ] ); + }, + + recordPageView: function( urlPath ) { + analytics.tracks.recordEvent( 'calypso_page_view', { + 'path': urlPath + } ); + } + }, + + // Google Analytics usage and event stat tracking + ga: { + + initialized: false, + + initialize: function() { + var parameters = {}; + if ( ! analytics.ga.initialized ) { + if ( _user && _user.get() ) { + parameters = { + 'userId': 'u-' + _user.get().ID + }; + } + window.ga( 'create', config( 'google_analytics_key' ), 'auto', parameters ); + analytics.ga.initialized = true; + } + }, + + recordPageView: function( urlPath, pageTitle ) { + analytics.ga.initialize(); + + debug( 'Recording Page View ~ [URL: ' + urlPath + '] [Title: ' + pageTitle + ']' ); + + if ( config( 'google_analytics_enabled' ) ) { + // Set the current page so all GA events are attached to it. + window.ga( 'set', 'page', urlPath ); + + window.ga( 'send', { + 'hitType': 'pageview', + 'page': urlPath, + 'title': pageTitle + } ); + } + }, + + recordEvent: function( category, action, label, value ) { + analytics.ga.initialize(); + + var debugText = 'Recording Event ~ [Category: ' + category + '] [Action: ' + action + ']'; + + if ( 'undefined' !== typeof label ) { + debugText += ' [Option Label: ' + label + ']'; + } + + if ( 'undefined' !== typeof value ) { + debugText += ' [Option Value: ' + value + ']'; + } + + debug( debugText ); + + if ( config( 'google_analytics_enabled' ) ) { + window.ga( 'send', 'event', category, action, label, value ); + } + } + }, + + identifyUser: function() { + // Don't identify the user if we don't have one + if ( _user && _user.initialized ) { + window._tkq.push( [ 'identifyUser', _user.get().ID, _user.get().username ] ); + } + }, + + setProperties: function( properties ) { + window._tkq.push( [ 'setProperties', properties ] ); + }, + + clearedIdentity: function() { + window._tkq.push( [ 'clearIdentity' ] ); + } +}; + +module.exports = analytics; diff --git a/client/analytics/super-props.js b/client/analytics/super-props.js new file mode 100644 index 00000000000000..eb45b4999a5806 --- /dev/null +++ b/client/analytics/super-props.js @@ -0,0 +1,38 @@ +/** + * External dependencies + */ +var config = require( 'config' ), + assign = require( 'lodash/object/assign' ); +/** + * Internal dependencies + */ +var sites = require( 'lib/sites-list' )(); + +module.exports = { + getAll: function() { + var selectedSite = sites.getSelectedSite(), + siteProps = {}, + defaultProps = { + environment: config( 'env' ), + site_count: sites.data.length, + site_id_label: 'wpcom', + client: config( 'tracks_client_prop' ) + }; + + if ( selectedSite ) { + siteProps = { + + // Tracks expects a blog_id property to identify the blog which is + // why we use it here instead of calling the property site_id + blog_id: selectedSite.ID, + + site_id_label: selectedSite.jetpack ? 'jetpack' : 'wpcom', + site_language: selectedSite.lang, + site_plan_id: selectedSite.plan ? selectedSite.plan.product_id : null, + site_post_count: selectedSite.post_count + }; + } + + return assign( defaultProps, siteProps ); + } +}; diff --git a/client/analytics/test/analytics-tests.js b/client/analytics/test/analytics-tests.js new file mode 100644 index 00000000000000..8b23baf282893b --- /dev/null +++ b/client/analytics/test/analytics-tests.js @@ -0,0 +1,68 @@ +var expect = require( 'chai' ).expect, + url = require( 'url' ); + +require( 'lib/react-test-env-setup' )(); + +var imagesLoaded = []; +global.Image = function() { + this._src = ''; +}; + +Object.defineProperty( global.Image.prototype, 'src', { + get: function() { + return this._src; + }, + set: function( value ) { + this._src = value; + imagesLoaded.push( url.parse( value, true, true ) ); + } +} ); + +var analytics = require( '../' ); + +describe( 'Analytics', function() { + + beforeEach( function() { + imagesLoaded = []; + } ); + + describe( 'mc', function() { + it( 'bumpStat with group and stat', function() { + analytics.mc.bumpStat( 'go', 'time' ); + expect( imagesLoaded[ 0 ].query.v ).to.eql( 'wpcom-no-pv' ); + expect( imagesLoaded[ 0 ].query.x_go ).to.eql( 'time' ); + expect( imagesLoaded[ 0 ].query.t ).to.be.ok; + } ); + + it( 'bumpStat with value object', function() { + analytics.mc.bumpStat( { + go: 'time', + another: 'one' + } ); + expect( imagesLoaded[ 0 ].query.v ).to.eql( 'wpcom-no-pv' ); + expect( imagesLoaded[ 0 ].query.x_go ).to.eql( 'time' ); + expect( imagesLoaded[ 0 ].query.x_another ).to.eql( 'one' ); + expect( imagesLoaded[ 0 ].query.t ).to.be.ok; + } ); + + it( 'bumpStatWithPageView with group and stat', function() { + analytics.mc.bumpStatWithPageView( 'go', 'time' ); + expect( imagesLoaded[ 0 ].query.v ).to.eql( 'wpcom' ); + expect( imagesLoaded[ 0 ].query.go ).to.eql( 'time' ); + expect( imagesLoaded[ 0 ].query.t ).to.be.ok; + } ); + + it( 'bumpStatWithPageView with value object', function() { + analytics.mc.bumpStatWithPageView( { + go: 'time', + another: 'one' + } ); + expect( imagesLoaded[ 0 ].query.v ).to.eql( 'wpcom' ); + expect( imagesLoaded[ 0 ].query.go ).to.eql( 'time' ); + expect( imagesLoaded[ 0 ].query.another ).to.eql( 'one' ); + expect( imagesLoaded[ 0 ].query.t ).to.be.ok; + } ); + + } ); + +} ); diff --git a/client/analytics/test/config.js b/client/analytics/test/config.js new file mode 100644 index 00000000000000..9243cace95851b --- /dev/null +++ b/client/analytics/test/config.js @@ -0,0 +1,7 @@ +module.exports = function( key ) { + if ( key === 'mc_analytics_enabled' ) { + return true; + } + + throw new Error( 'key ' + key + ' not expected to be needed' ); +}; diff --git a/client/analytics/test/load-script.js b/client/analytics/test/load-script.js new file mode 100644 index 00000000000000..1e7402b9400821 --- /dev/null +++ b/client/analytics/test/load-script.js @@ -0,0 +1,10 @@ +function fakeLoader( url, callback ) { + fakeLoader.urlsLoaded.push( url ); + if ( callback ) { + setTimeout( function() { callback(); }, 0 ); + } +} + +fakeLoader.urlsLoaded = []; + +module.exports = { loadScript: fakeLoader }; diff --git a/client/auth/Makefile b/client/auth/Makefile new file mode 100644 index 00000000000000..dc5bb4623e3f5c --- /dev/null +++ b/client/auth/Makefile @@ -0,0 +1,7 @@ +REPORTER ?= spec +MOCHA ?= ../../node_modules/.bin/mocha + +test: + @NODE_ENV=test NODE_PATH=test:../../client:../../shared $(MOCHA) --compilers jsx:babel/register --reporter $(REPORTER) + +.PHONY: test diff --git a/client/auth/controller.js b/client/auth/controller.js new file mode 100644 index 00000000000000..bc585935fe85b6 --- /dev/null +++ b/client/auth/controller.js @@ -0,0 +1,34 @@ +/** + * External dependencies + */ +import React from 'react'; +import startsWith from 'lodash/string/startsWith'; +import page from 'page'; + +/** + * Internal dependencies + */ +import LoginComponent from './login'; +import * as OAuthToken from 'lib/oauth-token'; + +module.exports = { + login: function() { + if ( OAuthToken.getToken() ) { + page( '/' ); + } else { + React.render( + React.createElement( LoginComponent, {} ), + document.getElementById( 'primary' ) + ); + } + }, + + checkToken: function( context, next ) { + // Check we have an OAuth token, otherwise redirect to login page + if ( OAuthToken.getToken() === false && ! startsWith( context.path, '/login' ) && ! startsWith( context.path, '/oauth' ) ) { + page( '/login' ); + } else { + next(); + } + } +}; diff --git a/client/auth/index.js b/client/auth/index.js new file mode 100644 index 00000000000000..40e202b11e3ba5 --- /dev/null +++ b/client/auth/index.js @@ -0,0 +1,13 @@ +/** + * External dependencies + */ +import page from 'page'; + +/** + * Internal dependencies + */ +import controller from './controller'; + +module.exports = function() { + page( '/login', controller.login ); +}; diff --git a/client/auth/login.jsx b/client/auth/login.jsx new file mode 100644 index 00000000000000..9f76e3d1ec6d23 --- /dev/null +++ b/client/auth/login.jsx @@ -0,0 +1,156 @@ +/** + * External dependencies + */ +import React from 'react'; + +/** + * Internal dependencies + */ +import Main from 'components/main'; +import FormTextInput from 'components/forms/form-text-input'; +import FormPasswordInput from 'components/forms/form-password-input'; +import FormFieldset from 'components/forms/form-fieldset'; +import FormButton from 'components/forms/form-button'; +import FormButtonsBar from 'components/forms/form-buttons-bar'; +import Notice from 'notices/notice'; +import AuthStore from 'lib/oauth-store'; +import * as AuthActions from 'lib/oauth-store/actions'; +import eventRecorder from 'me/event-recorder'; +import Gridicon from 'components/gridicon'; +import WordPressLogo from 'components/wordpress-logo'; + +const LostPassword = React.createClass( { + render: function() { + return ( +

+ + { this.translate( 'Lost your password?' ) } + +

+ ); + } +} ); + +module.exports = React.createClass( { + displayName: 'Auth', + + mixins: [ React.addons.LinkedStateMixin, eventRecorder ], + + componentDidMount: function() { + AuthStore.on( 'change', this.refreshData ); + }, + + componentWillUnmount: function() { + AuthStore.off( 'change', this.refreshData ); + }, + + refreshData: function() { + this.setState( AuthStore.get() ); + }, + + componentDidUpdate() { + if ( this.state.requires2fa && this.state.inProgress === false ) { + this.refs.auth_code.getDOMNode().focus(); + } + }, + + getInitialState: function() { + return Object.assign( { + login: '', + password: '', + auth_code: '' + }, AuthStore.get() ); + }, + + submitForm: function( event ) { + event.preventDefault(); + event.stopPropagation(); + + AuthActions.login( this.state.login, this.state.password, this.state.auth_code ); + }, + + hasLoginDetails: function() { + if ( this.state.login === '' || this.state.password === '' ) { + return false; + } + + return true; + }, + + canSubmitForm: function() { + // No submission until the ajax has finished + if ( this.state.inProgress ) { + return false; + } + + // If we have 2fa set then don't allow submission until a code is entered + if ( this.state.requires2fa ) { + return parseInt( this.state.auth_code, 10 ) > 0; + } + + // Don't allow submission until username+password is entered + return this.hasLoginDetails(); + }, + + render: function() { + const { requires2fa, inProgress, errorMessage, errorLevel } = this.state; + + return ( +
+ +
+ +
+ + +
+
+ + +
+ { requires2fa && + + + + } +
+ + + { requires2fa ? this.translate( 'Verify' ) : this.translate( 'Sign in' ) } + + + { ! requires2fa && } + { errorMessage && } + + + + + +
+ ); + } +} ); diff --git a/client/auth/style.scss b/client/auth/style.scss new file mode 100644 index 00000000000000..69da7939404984 --- /dev/null +++ b/client/auth/style.scss @@ -0,0 +1,161 @@ +/** + * Oauth login page, used in WordPress Desktop App + */ + +html.is-desktop { + .logged-out-auth { + background: $blue-wordpress; + + .wp-content { + margin: 0 auto; + overflow: hidden; + max-width: none; + padding-left: 0; + padding-right: 0; + } + + .wp-content:after { + content: none; + } + } +} + +.auth.main { + float: none; + height: 100%; + margin: 0 auto; + text-align: center; + display: flex; + flex-direction: column; + justify-content: center; + align-content: center; + background: none; + + .notice { + width: calc( 100% - 20px ); + margin: 20px auto 0 auto; + } + + .notice.is-info { + color: $gray-light; + padding: 0; + margin: 20px 0 0 0; + } + + .notice.is-info .notice__text { + padding: 0; + } + + .notice.is-info:before { + content: none; + } +} + +.auth__form { + width: 320px; + margin: 0 auto; + + .form-fieldset input { + position: relative; + z-index: 1; + } + + .form-fieldset input[type="text"], + .form-fieldset input[type="password"] { + padding-left: 36px; + } + + .form-fieldset input:focus { + z-index: 2; + } + + .form-password-input { + margin-top: -1px; + } + + .form-buttons-bar button { + float: none; + margin: 0; + width: calc( 100% - 20px ); + } + + .form-buttons-bar button, + .form-buttons-bar .button.is-primary[disabled] { + background: #00a8db; + border: #00a8db; + } + + .form-buttons-bar .button.is-primary[disabled], + .form-fieldset input[type="password"]:disabled, + .form-fieldset input[type="text"]:disabled { + opacity: .5; + } + + .form-fieldset input[type="text"]:disabled { + margin-bottom: 1px; + } + + .form-fieldset input[type="number"] { + text-align: center; + } + + .form-password-input__toggle-visibility { + z-index: 4; + .gridicon { + position: static; + } + } + + input[type="number"]::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } +} + +.auth__input-wrapper { + position: relative; + + .gridicon { + position: absolute; + z-index: 3; + left: 8px; + top: 7px; + fill: $gray; + } +} + +.auth__lost-password { + margin-top: 1.5em; + text-align: center; +} + +.auth__lost-password a { + color: lighten( $gray, 20% ); +} + +// should be a new component +.wordpress-logo { + fill: $white; + margin: 0 auto 20px auto; +} + +.auth__help { + position: absolute; + top: 16px; + right: 16px; + color: $white; +} + +.auth__links { + position: absolute; + bottom: 40px; + left: 0; + right: 0; +} + +.auth__links a { + text-decoration: none; + color: $white; + margin: 0 16px; + padding: 10px 0; +} diff --git a/client/auth/test/login.jsx b/client/auth/test/login.jsx new file mode 100644 index 00000000000000..ed46a791e697a7 --- /dev/null +++ b/client/auth/test/login.jsx @@ -0,0 +1,74 @@ +/* eslint-disable vars-on-top */ +require( 'lib/react-test-env-setup' )(); + +/** + * External dependencies + */ + +const React = require( 'react/addons' ), + i18n = require( 'lib/mixins/i18n' ), + expect = require( 'chai' ).expect, + sinon = require( 'sinon' ), + ReactInjection = require( 'react/lib/ReactInjection' ), + TestUtils = React.addons.TestUtils; + +/** + * Internal dependencies + */ +const AuthActions = require( 'lib/oauth-store/actions' ); + +// Handle initialization here instead of in `before()` to avoid timeouts. See client/post-editor/test/post-editor.jsx +i18n.initialize(); +ReactInjection.Class.injectMixin( i18n.mixin ); + +let Login = require( '../login.jsx' ); +const page = React.render( , document.body ); + +describe( 'LoginTest', function() { + it( 'OTP is not present on first render', function( done ) { + page.setState( { requires2fa: false }, function() { + expect( page.refs.auth_code ).to.be.undefined; + done(); + } ); + } ); + + it( 'cannot submit until login details entered', function( done ) { + var submit = TestUtils.findRenderedDOMComponentWithTag( page, 'button' ); + + page.setState( { login: 'test', password: 'test', inProgress: false }, function() { + expect( submit.props.disabled ).to.be.false; + done(); + } ); + } ); + + it( 'shows OTP box with valid login', function( done ) { + page.setState( { login: 'test', password: 'test', requires2fa: true }, function() { + expect( page.refs.auth_code ).to.not.be.undefined; + done(); + } ); + } ); + + it( 'prevents change of login when asking for OTP', function( done ) { + page.setState( { login: 'test', password: 'test', requires2fa: true }, function() { + expect( page.refs.login.props.disabled ).to.be.true; + expect( page.refs.password.props.disabled ).to.be.true; + done(); + } ); + } ); + + it( 'submits login form', function( done ) { + var submit = TestUtils.findRenderedDOMComponentWithTag( page, 'form' ); + + sinon.stub( AuthActions, 'login' ); + + page.setState( { login: 'user', password: 'pass', auth_code: 'otp' }, function() { + TestUtils.Simulate.submit( submit ); + + expect( AuthActions.login ).to.have.been.calledOnce; + expect( AuthActions.login.calledWith( 'user', 'pass', 'otp' ) ).to.be.true; + + AuthActions.login.restore(); + done(); + } ); + } ); +} ); diff --git a/client/boot/README.md b/client/boot/README.md new file mode 100644 index 00000000000000..5ad46c5f32495e --- /dev/null +++ b/client/boot/README.md @@ -0,0 +1,21 @@ +Boot +====== + +This module is where all the client-side magic starts. The core set of application modules that contain the client-side application routes, any additional application bootstrapping occurs, and the page.js router is started triggering the initial route handler. + +Boot is responsible for handling a lot of features we want to happen on every page. The major ones are (in roughly chronological order): + +- Initializing i18n +- Injecting the i18n mixin to React components +- Adding touch events +- Adding accessibility focus features +- Setting the document title +- Passing layout to all page handlers +- Passing the query and hash objects into the page.js context +- Boot strapping translation strings +- Setting up analytics +- Rendering the main layout template +- Focussing parts of the layout based on the query string +- Handling query strings +- Loading various helpers (olark, keyboard shortcuts, network connection) +- Starting page.js diff --git a/client/boot/index.js b/client/boot/index.js new file mode 100644 index 00000000000000..426325eccad02c --- /dev/null +++ b/client/boot/index.js @@ -0,0 +1,321 @@ +/** + * External dependencies + */ +var React = require( 'react' ), + store = require( 'store' ), + ReactInjection = require( 'react/lib/ReactInjection' ), + some = require( 'lodash/collection/some' ), + startsWith = require( 'lodash/string/startsWith' ), + classes = require( 'component-classes' ), + debug = require( 'debug' )( 'calypso' ), + page = require( 'page' ), + url = require( 'url' ), + qs = require( 'querystring' ), + injectTapEventPlugin = require( 'react-tap-event-plugin' ); + +/** + * Internal dependencies + */ +// lib/local-storage must be run before lib/user +var config = require( 'config' ), + localStoragePolyfill = require( 'lib/local-storage' )(), //eslint-disable-line + analytics = require( 'analytics' ), + route = require( 'lib/route' ), + user = require( 'lib/user' )(), + sites = require( 'lib/sites-list' )(), + superProps = require( 'analytics/super-props' ), + config = require( 'config' ), + i18n = require( 'lib/mixins/i18n' ), + translatorJumpstart = require( 'lib/translator-jumpstart' ), + translatorInvitation = require( 'layout/community-translator/invitation-utils' ), + layoutFocus = require( 'lib/layout-focus' ), + nuxWelcome = require( 'nux-welcome' ), + emailVerification = require( 'components/email-verification' ), + viewport = require( 'lib/viewport' ), + detectHistoryNavigation = require( 'lib/detect-history-navigation' ), + sections = require( 'sections' ), + touchDetect = require( 'lib/touch-detect' ), + accessibleFocus = require( 'lib/accessible-focus' ), + TitleStore = require( 'lib/screen-title/store' ), + // The following mixins require i18n content, so must be required after i18n is initialized + Layout, + LoggedOutLayout; + +function init() { + var i18nLocaleStringsObject = null; + + debug( 'Starting Calypso. Let\'s do this.' ); + + // Initialize i18n + if ( window.i18nLocaleStrings ) { + i18nLocaleStringsObject = JSON.parse( window.i18nLocaleStrings ); + } + i18n.initialize( i18nLocaleStringsObject ); + + ReactInjection.Class.injectMixin( i18n.mixin ); + + // Infer touch screen by checking if device supports touch events + // See touch-detect/README.md + if ( touchDetect.hasTouch() ) { + classes( document.documentElement ).add( 'touch' ); + } else { + classes( document.documentElement ).add( 'notouch' ); + } + + // Initialize touch + injectTapEventPlugin(); + + // Add accessible-focus listener + accessibleFocus(); + + // Set document title + TitleStore.on( 'change', function() { + var title = TitleStore.getState().formattedTitle; + if ( title && title !== document.title ) { + document.title = title; + } + } ); +} + +function setUpContext( layout ) { + // Pass the layout so that it is available to all page handlers + // and add query and hash objects onto context object + page( '*', function( context, next ) { + var parsed = url.parse( location.href, true ); + + context.layout = layout; + + // Break routing and do full page load for logout link in /me + if ( context.pathname === '/wp-login.php' ) { + window.location.href = context.path; + return; + } + + // set `context.query` + // debugger + const querystringStart = context.canonicalPath.indexOf( '?' ); + if ( querystringStart !== -1 ) { + context.query = qs.parse( context.canonicalPath.substring( querystringStart + 1 ) ); + } else { + context.query = {}; + } + context.prevPath = parsed.path === context.path ? false : parsed.path; + + // set `context.hash` (we have to parse manually) + if ( parsed.hash && parsed.hash.length > 1 ) { + try { + context.hash = qs.parse( parsed.hash.substring( 1 ) ); + } catch ( e ) { + debug( 'failed to query-string parse `location.hash`', e ); + context.hash = {}; + } + } else { + context.hash = {}; + } + next(); + } ); +} + +function loadDevModulesAndBoot() { + if ( config.isEnabled( 'render-visualizer' ) ) { + // Use Webpack's code splitting feature to put the render visualizer in a separate fragment. + // This way it won't get downloaded unless this feature is enabled. + // Since loading this fragment is asynchronous and we need to inject this mixin into all React classes, + // we have to wait for it to load before proceeding with the application's startup. + require.ensure( [], function() { + ReactInjection.Class.injectMixin( require( 'lib/mixins/render-visualizer' ) ); + boot(); + }, 'devmodules' ); + + return; + } + + boot(); +} + +function boot() { + var layoutSection, layout, validSections = []; + + init(); + + // When the user is bootstrapped, we also bootstrap the + // locale strings + if ( ! config( 'wpcom_user_bootstrap' ) ) { + i18n.setLocaleSlug( user.get().localeSlug ); + } + // Set the locale for the current user + user.on( 'change', function() { + i18n.setLocaleSlug( user.get().localeSlug ); + } ); + + translatorJumpstart.init(); + + if ( user.get() ) { + // When logged in the analytics module requires user and superProps objects + // Inject these here + analytics.initialize( user, superProps ); + + // Create layout instance with current user prop + Layout = require( 'layout' ); + layout = React.render( React.createElement( Layout, { + user: user, + sites: sites, + focus: layoutFocus, + nuxWelcome: nuxWelcome, + translatorInvitation: translatorInvitation + } ), document.getElementById( 'wpcom' ) ); + } else { + if ( config.isEnabled( 'oauth' ) ) { + LoggedOutLayout = require( 'layout/logged-out-oauth' ); + } else { + LoggedOutLayout = require( 'layout/logged-out' ); + } + + layout = React.render( + React.createElement( LoggedOutLayout ), + document.getElementById( 'wpcom' ) + ); + } + + debug( 'Main layout rendered.' ); + + // If `?sb` or `?sp` are present on the path set the focus of layout + // This needs to be done before the page.js router is started and can be removed when the legacy version is retired + if ( window && [ '?sb', '?sp' ].indexOf( window.location.search ) !== -1 ) { + layoutSection = ( window.location.search === '?sb' ) ? 'sidebar' : 'sites'; + layoutFocus.set( layoutSection ); + window.history.replaceState( null, document.title, window.location.pathname ); + } + + setUpContext( layout ); + + page( '*', require( 'lib/route/normalize' ) ); + + // warn against navigating from changed, unsaved forms + page( '*', require( 'lib/mixins/protect-form' ).checkFormHandler ); + + page( '*', function( context, next ) { + var path = context.pathname; + + // Bypass this global handler for legacy routes + // to avoid bumping stats and changing focus to the content + if ( /.php$/.test( path ) || + /^\/?$/.test( path ) && ! config.isEnabled( 'reader' ) || + /^\/my-stats/.test( path ) || + /^\/(post\b|page\b)/.test( path ) && ! config.isEnabled( 'post-editor' ) || + /^\/notifications/.test( path ) || + /^\/themes/.test( path ) || + /^\/manage/.test( path ) || + /^\/plans/.test( path ) && ! config.isEnabled( 'manage/plans' ) || + /^\/me/.test( path ) && ! /^\/me\/billing/.test( path ) && + ! /^\/me\/next/.test( path ) && ! config.isEnabled( 'me/my-profile' ) ) { + return next(); + } + + // Focus UI on the content on page navigation + if ( ! config.isEnabled( 'code-splitting' ) ) { + layoutFocus.next(); + } + + // If `?welcome` is present show the welcome message + if ( context.querystring === 'welcome' && context.pathname.indexOf( '/me/next' ) === -1 ) { + // show welcome message, persistent for full sized screens + nuxWelcome.setWelcome( viewport.isDesktop() ); + } else { + nuxWelcome.clearTempWelcome(); + } + + // Bump general stat tracking overall Newdash usage + analytics.mc.bumpStat( { newdash_pageviews: 'route' } ); + + next(); + } ); + + page( '*', function( context, next ) { + if ( '/me/account' !== context.path && user.get().phone_account ) { + page( '/me/account' ); + } + + next(); + } ); + + page( '*', function( context, next ) { + emailVerification.renderNotice( context ); + next(); + } ); + + // clear notices + page( '*', require( 'notices' ).clearNoticesOnNavigation ); + + if ( config.isEnabled( 'oauth' ) ) { + // Forces OAuth users to the /login page if no token is present + page( '*', require( 'auth/controller' ).checkToken ); + } + + // Load the application modules for the various sections and features + sections.load(); + + // delete any lingering local storage data from signup + if ( ! startsWith( window.location.pathname, '/start' ) ) { + [ 'signupProgress', 'signupDependencies' ].forEach( store.remove ); + } + + validSections = sections.get().reduce( function( acc, section ) { + return section.enableLoggedOut ? acc.concat( section.paths ) : acc; + }, [] ); + + if ( ! user.get() ) { + // Dead-end the sections the user can't access when logged out + page( '*', function( context, next ) { + var isValidSection = some( validSections, function( validPath ) { + return startsWith( context.path, validPath ); + } ); + + if ( isValidSection ) { + next(); + } + } ); + } + + page( '*', function( context, next ) { + // Reset the selected site before each route is executed. This needs to + // occur after the sections routes execute to avoid a brief flash where + // sites are reset but the next section is waiting to be loaded. + if ( ! route.getSiteFragment( context.path ) && sites.getSelectedSite() ) { + sites.resetSelectedSite(); + } + + next(); + } ); + + require( 'my-sites' )(); + + if ( config.isEnabled( 'olark' ) ) { + require( 'lib/olark' ); + } + + if ( config.isEnabled( 'keyboard-shortcuts' ) ) { + require( 'lib/keyboard-shortcuts/global' )( sites ); + } + + if ( config.isEnabled( 'network-connection' ) ) { + require( 'lib/network-connection' ).init(); + } + + if ( config.isEnabled( 'desktop' ) ) { + require( 'lib/desktop' ).init(); + } + + detectHistoryNavigation.start(); + page.start(); +} + +window.AppBoot = function() { + if ( user.initialized ) { + loadDevModulesAndBoot(); + } else { + user.once( 'change', function() { + loadDevModulesAndBoot(); + } ); + } +}; diff --git a/client/components/README.md b/client/components/README.md new file mode 100644 index 00000000000000..030d055205c844 --- /dev/null +++ b/client/components/README.md @@ -0,0 +1,6 @@ +Components +========== + +This place harbors shared React components used for composing the UI of Calypso. Components come with their own styles defined [according to our guidelines](https://github.com/Automattic/calypso-pre-oss/blob/master/docs/coding-guidelines/css.md), and manually loaded from the [styles assets folder](https://github.com/Automattic/calypso-pre-oss/blob/master/assets/stylesheets/_components.scss). Structuring the user interface with these building blocks has several benefits — like allowing to quickly construct a view that is visually consistent with the rest of Calypso, and easier to iterate on. + +Some of these components can be seen in action in our [DevDocs: Design](https://wpcalypso.wordpress.com/devdocs/design) section. \ No newline at end of file diff --git a/client/components/accordion/Makefile b/client/components/accordion/Makefile new file mode 100644 index 00000000000000..5fb42bb5b03d57 --- /dev/null +++ b/client/components/accordion/Makefile @@ -0,0 +1,7 @@ +REPORTER ?= spec +MOCHA ?= ../../../node_modules/.bin/mocha + +test: + @NODE_ENV=test NODE_PATH=test:../../ $(MOCHA) --compilers jsx:babel/register --reporter $(REPORTER) + +.PHONY: test diff --git a/client/components/accordion/README.md b/client/components/accordion/README.md new file mode 100644 index 00000000000000..3ac8c53f17f5df --- /dev/null +++ b/client/components/accordion/README.md @@ -0,0 +1,32 @@ +Accordion +========= + +Accordion is a React component to display collapsible content panels. + +## Usage + +At a minimum, you must provide a `title` for your Accordion, and a child or set of children to be shown in the panel. + +```jsx +var Accordion = require( 'components/accordion' ); + +module.exports = React.createClass( { + render: function() { + return ( + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris fermentum eget libero at pretium. Morbi hendrerit arcu mauris, laoreet dapibus est maximus nec. Sed volutpat, lorem semper porta efficitur, dui augue tempor ante, eget faucibus quam erat vitae velit. + + ); + } +} ); +``` + +## Props + +The following props are available to customize the accordion: + +- `initialExpanded`: Boolean indicating whether the panel should default to expanded with the content visible +- `onToggle`: Function handler to invoke when the user toggles the accordion. The function will be passed a boolean indicating the expanded state after the toggle. +- `title`: Main heading shown in the always-visible toggle button +- `subtitle`: Subheading shown in the always-visible toggle button +- `icon`: String or React element to be shown as an icon adjacent to the headings in the always-visible toggle button. A string will be assumed to be used as the Noticon class suffix for the icon element. diff --git a/client/components/accordion/docs/example.jsx b/client/components/accordion/docs/example.jsx new file mode 100644 index 00000000000000..34dd01ae469f43 --- /dev/null +++ b/client/components/accordion/docs/example.jsx @@ -0,0 +1,77 @@ +/** + * External dependencies + */ +var React = require( 'react' ); + +/** + * Internal dependencies + */ +var Accordion = require( 'components/accordion' ), + Gridicon = require( 'components/gridicon' ); + +module.exports = React.createClass( { + displayName: 'Accordions', + + mixins: [ React.addons.PureRenderMixin ], + + getInitialState: function() { + return { + showSubtitles: true + }; + }, + + _toggleShowSubtitles: function() { + this.setState( { + showSubtitles: ! this.state.showSubtitles + } ); + }, + + render: function() { + return ( +
+

+ Accordions +

+ +
+ +
+ +
+ + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris fermentum eget libero at pretium. Morbi hendrerit arcu mauris, laoreet dapibus est maximus nec. Sed volutpat, lorem semper porta efficitur, dui augue tempor ante, eget faucibus quam erat vitae velit. + + }> + In tempor orci sapien, non tempor risus suscipit ut. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris vitae volutpat nunc. Nunc at congue arcu. Proin non leo augue. Nulla dapibus laoreet ligula, nec varius sit amet. + + + Suspendisse pellentesque diam in nisi pulvinar maximus. Integer feugiat feugiat justo ac vehicula. Curabitur iaculis, risus suscipit sodales auctor, nisl urna elementum sem, non vestibulum mauris ante et purus. Duis iaculis nisl neque, eget rutrum erat imperdiet non. + + + Drumstick ham tongue flank doner pork chop picanha. Cow short ribs tail kevin capicola ball tip. Leberkas shankle landjaeger tenderloin, chuck cupim pastrami cow frankfurter. Kielbasa bacon capicola shoulder porchetta, frankfurter rump short loin pig cupim. Tri-tip spare ribs porchetta flank jerky bresaola bacon kevin shank cupim meatball ground round ham sirloin ball tip. Tail bresaola shank, beef ribs turkey tenderloin meatloaf frankfurter. + + } + > + Etiam dictum odio elit, id faucibus urna elementum ac. Mauris in est nec tortor luctus auctor ut a velit. Suspendisse vulputate lectus arcu, sed condimentum risus rutrum vitae. Nullam sagittis ultricies nisl. Duis accumsan libero vel arcu sodales venenatis. + +
+
+ ); + } +} ); diff --git a/client/components/accordion/index.jsx b/client/components/accordion/index.jsx new file mode 100644 index 00000000000000..4947efcbb47417 --- /dev/null +++ b/client/components/accordion/index.jsx @@ -0,0 +1,95 @@ +/** + * External dependencies + */ +var React = require( 'react/addons' ), + noop = require( 'lodash/utility/noop' ), + classNames = require( 'classnames' ); + +module.exports = React.createClass( { + displayName: 'Accordion', + + propTypes: { + initialExpanded: React.PropTypes.bool, + onToggle: React.PropTypes.func, + title: React.PropTypes.string.isRequired, + subtitle: React.PropTypes.string, + icon: React.PropTypes.oneOfType( [ + React.PropTypes.string, + React.PropTypes.element + ] ) + }, + + getInitialState: function() { + return { + isExpanded: this.props.initialExpanded + }; + }, + + getDefaultProps: function() { + return { + onToggle: noop + }; + }, + + toggleExpanded: function() { + var isExpanded = ! this.state.isExpanded; + + this.setState( { + isExpanded: isExpanded + } ); + + this.props.onToggle( isExpanded ); + }, + + renderIcon: function() { + if ( ! this.props.icon ) { + return; + } + + if ( 'string' === typeof this.props.icon ) { + return ; + } + + return { this.props.icon }; + }, + + renderSubtitle: function() { + if ( this.props.subtitle ) { + return { this.props.subtitle }; + } + }, + + renderHeader: function() { + var classes = classNames( 'accordion__header', { + 'has-icon': !! this.props.icon, + 'has-subtitle': !! this.props.subtitle + } ); + + return ( +
+ +
+ ); + }, + + render: function() { + var classes = classNames( 'accordion', this.props.className, { + 'is-expanded': this.state.isExpanded + } ); + + return ( +
+ { this.renderHeader() } +
+
+ { this.props.children } +
+
+
+ ); + } +} ); diff --git a/client/components/accordion/section.jsx b/client/components/accordion/section.jsx new file mode 100644 index 00000000000000..bf04b036917eba --- /dev/null +++ b/client/components/accordion/section.jsx @@ -0,0 +1,15 @@ +/** + * External dependencies + */ +import React from 'react'; +import classNames from 'classnames'; + +export default React.createClass( { + render() { + return ( +
+ { this.props.children } +
+ ); + }, +} ); diff --git a/client/components/accordion/style.scss b/client/components/accordion/style.scss new file mode 100644 index 00000000000000..778a959bc3fc15 --- /dev/null +++ b/client/components/accordion/style.scss @@ -0,0 +1,133 @@ +$accordion-padding: 16px; +$accordion-subtitle-height: 16px; +$accordion-background-collapsed: $gray-light; // same as body +$accordion-background-hover: lighten( $gray, 30% ); +$accordion-background-expanded: $white; + +.accordion { + box-shadow: 0 -1px 0 lighten( $gray, 26% ), + 0 1px 0 lighten( $gray, 26% ); + margin-top: 1px; + position: relative; +} + +.accordion__toggle { + display: block; + width: 100%; + cursor: pointer; + position: relative; + margin: 0; + padding: $accordion-padding; + padding-right: ( $accordion-padding + 22px ); + color: $gray-dark; + background-color: $accordion-background-collapsed; + text-align: left; + + &:hover { + background-color: $accordion-background-hover; + } + + &::after { + @include noticon( '\f431', 22px ); + position: absolute; + top: 50%; + right: $accordion-padding; + transform: translateY( -50% ); + color: lighten( $gray, 10% ); + } +} + +.accordion.is-expanded { + box-shadow: 0 0 0 1px lighten( $gray, 20% ); + + .accordion__toggle { + background-color: $accordion-background-expanded; + box-shadow: 0 0 0 1px lighten( $gray, 20% ); + + &::after { + content: '\f432'; + } + } + + .accordion__content { + overflow: visible; + } +} + +.accordion__header.has-subtitle .accordion__toggle { + padding-top: ( $accordion-padding - $accordion-subtitle-height / 2 ); + padding-bottom: ( $accordion-padding - $accordion-subtitle-height / 2 ); +} + +.accordion__icon { + position: absolute; + left: $accordion-padding; + top: 50%; + transform: translateY( -50% ); + margin-top: 3px; + + .gridicon { + width: 20px; + height: 20px; + } +} + +.accordion__title, +.accordion__subtitle { + display: block; +} + +.accordion__header.has-icon .accordion__title, +.accordion__header.has-icon .accordion__subtitle { + padding-left: 28px; +} + +.accordion__subtitle { + font-size: 0.8em; + font-style: italic; + color: $gray; + white-space: nowrap; + overflow-x: hidden; + position: relative; + height: $accordion-subtitle-height; +} + +.accordion:not( .is-expanded ) .accordion__toggle .accordion__subtitle { + &::after { + @include long-content-fade( $color: $accordion-background-collapsed ); + } +} + +.accordion:not( .is-expanded ) .accordion__toggle:hover .accordion__subtitle { + &::after { + @include long-content-fade( $color: $accordion-background-hover ); + } +} + +.accordion.is-expanded .accordion__subtitle { + &::after { + @include long-content-fade( $color: $accordion-background-expanded ); + } +} + +.accordion__content { + overflow: hidden; + height: 0; + background-color: $accordion-background-expanded; +} + +.accordion.is-expanded .accordion__content { + height: auto; +} + +.accordion__content-wrap { + padding: $accordion-padding; +} + +.accordion__section { + margin-bottom: 24px; +} + +.accordion__section:last-child { + margin-bottom: 0; +} diff --git a/client/components/accordion/test/index.jsx b/client/components/accordion/test/index.jsx new file mode 100644 index 00000000000000..63add168d4f1d2 --- /dev/null +++ b/client/components/accordion/test/index.jsx @@ -0,0 +1,89 @@ +/* eslint-disable vars-on-top */ +require( 'lib/react-test-env-setup' )(); + +/** + * External dependencies + */ +var expect = require( 'chai' ).expect, + React = require( 'react/addons' ), + TestUtils = React.addons.TestUtils; + +require( 'react-tap-event-plugin' )(); + +/** + * Internal dependencies + */ +var Accordion = require( '../' ); + +describe( 'Accordion', function() { + afterEach( function() { + React.unmountComponentAtNode( document.body ); + } ); + + it( 'should render as expected with a title and content', function() { + var tree = TestUtils.renderIntoDocument( Content ), + node = React.findDOMNode( tree ); + + expect( node.className ).to.equal( 'accordion' ); + expect( tree.state.isExpanded ).to.not.be.ok; + expect( node.querySelector( '.accordion__header:not( .has-icon ):not( .has-subtitle )' ) ).to.be.an.instanceof( window.Element ); + expect( node.querySelector( '.accordion__icon' ) ).to.be.null; + expect( node.querySelector( '.accordion__title' ).textContent ).to.equal( 'Section' ); + expect( node.querySelector( '.accordion__subtitle' ) ).to.be.null; + expect( React.findDOMNode( tree.refs.content ).textContent ).to.equal( 'Content' ); + } ); + + it( 'should accept an icon prop to be rendered as a noticon', function() { + var tree = TestUtils.renderIntoDocument( Content ), + node = React.findDOMNode( tree ); + + expect( node.querySelector( '.accordion__header.has-icon:not( .has-subtitle )' ) ).to.be.an.instanceof( window.Element ); + expect( node.querySelector( '.accordion__icon' ) ).to.be.an.instanceof( window.Element ); + } ); + + it( 'should accept a subtitle prop to be rendered aside the title', function() { + var tree = TestUtils.renderIntoDocument( Content ), + node = React.findDOMNode( tree ); + + expect( node.querySelector( '.accordion__header.has-subtitle:not( .has-icon )' ) ).to.be.an.instanceof( window.Element ); + expect( node.querySelector( '.accordion__subtitle' ).textContent ).to.equal( 'Subtitle' ); + } ); + + it( 'should toggle when clicked', function() { + var tree = TestUtils.renderIntoDocument( Content ); + + TestUtils.Simulate.touchTap( React.findDOMNode( TestUtils.findRenderedDOMComponentWithClass( tree, 'accordion__toggle' ) ) ); + + expect( tree.state.isExpanded ).to.be.ok; + } ); + + it( 'should accept an onToggle function handler to be invoked when toggled', function( done ) { + var tree = TestUtils.renderIntoDocument( Content ); + + TestUtils.Simulate.touchTap( React.findDOMNode( TestUtils.findRenderedDOMComponentWithClass( tree, 'accordion__toggle' ) ) ); + + function finishTest( isExpanded ) { + expect( isExpanded ).to.be.ok; + + process.nextTick( function() { + expect( tree.state.isExpanded ).to.be.ok; + done(); + } ); + } + } ); + + it( 'should always use the initialExpanded prop, if specified', function( done ) { + var tree = TestUtils.renderIntoDocument( Content ); + + TestUtils.Simulate.touchTap( React.findDOMNode( TestUtils.findRenderedDOMComponentWithClass( tree, 'accordion__toggle' ) ) ); + + function finishTest( isExpanded ) { + expect( isExpanded ).to.not.be.ok; + + process.nextTick( function() { + expect( tree.state.isExpanded ).to.not.be.ok; + done(); + } ); + } + } ); +} ); diff --git a/client/components/add-new-button/README.md b/client/components/add-new-button/README.md new file mode 100644 index 00000000000000..600079b684a68a --- /dev/null +++ b/client/components/add-new-button/README.md @@ -0,0 +1,23 @@ +Add new button +=========== + +This component implements a button styled to be used in 'add' actions. + +## Usage + +```jsx +import AddNewButton from 'components/add-new-button'; + +export default React.createClass( { + render: () => Link +} ); + +``` + +## Props + +- `href`: String with the destination url. +- `onClick`: Function to be executed when the button is clicked +- `isCompact`: Boolean indicating whether the button is in compact mode. Defaults to false. +- `outline`: Boolean indicating whether the button has an outline. Defaults to false. +- `icon`: String indicating which Gridicon we are going to use for the button. Defaults to `add` or `add-outline`, depending on `outline` value \ No newline at end of file diff --git a/client/components/add-new-button/docs/example.jsx b/client/components/add-new-button/docs/example.jsx new file mode 100644 index 00000000000000..17c94242f6241e --- /dev/null +++ b/client/components/add-new-button/docs/example.jsx @@ -0,0 +1,34 @@ +/** + * External dependencies + */ +var React = require( 'react' ); + +/** + * Internal dependencies + */ +var AddNewButton = require( 'components/add-new-button' ); + +var AddNewButtons = React.createClass( { + displayName: 'AddNewButton', + + mixins: [ React.addons.PureRenderMixin ], + + render: function() { + return ( +
+

+ Add New Buttons +

+ Unstyled Add New Button + Link-styled with outline +
+ Install Button + Link + Link + Link +
+ ); + } +} ); + +module.exports = AddNewButtons; diff --git a/client/components/add-new-button/index.jsx b/client/components/add-new-button/index.jsx new file mode 100644 index 00000000000000..ceee91c899fd43 --- /dev/null +++ b/client/components/add-new-button/index.jsx @@ -0,0 +1,57 @@ +/** + * External dependencies + */ +import React from 'react'; +import classnames from 'classnames'; +import assign from 'lodash/object/assign'; +import noop from 'lodash/utility/noop'; + +/** + * Internal dependencies + */ +import Gridicon from 'components/gridicon'; + +export default React.createClass( { + + displayName: 'AddNewButton', + + getDefaultProps() { + return { + isCompact: false, + onClick: noop, + outline: false, + icon: null, + }; + }, + + propTypes: { + className: React.PropTypes.string, + href: React.PropTypes.string, + icon: React.PropTypes.string, + isCompact: React.PropTypes.bool, + onClick: React.PropTypes.func, + outline: React.PropTypes.bool + }, + + render() { + // this component creates an anchor or a button + // depending on which props are passed + const element = this.props.href ? 'a' : 'button'; + + const classes = classnames( 'add-new-button', this.props.className, { + 'is-compact': this.props.isCompact, + 'has-icon': !! this.props.icon, + } ); + + const defaultIcon = ( this.props.outline ? 'add-outline' : 'add' ); + const icon = this.props.icon ? this.props.icon : defaultIcon; + const firstIcon = this.props.icon ? : null; + + return React.createElement( + element, + assign( {}, this.props, { className: classes } ), + [ firstIcon, ], + { this.props.children } + ); + } +} ); diff --git a/client/components/add-new-button/style.scss b/client/components/add-new-button/style.scss new file mode 100644 index 00000000000000..33f430f3bd2680 --- /dev/null +++ b/client/components/add-new-button/style.scss @@ -0,0 +1,46 @@ +// Add new category +a.add-new-button, +button.add-new-button { + cursor: pointer; + color: darken( $gray, 20% ); + margin: 0 0 8px; + padding: 8px 0; + font-size: 14px; + display: block; + text-align: left; + + &:hover { + color: $gray-dark; + } + + .gridicon { + float: left; + margin-top: 1px; + } + &.has-icon { + position: relative; + + &:hover { + color: $gray-dark; + } + + .gridicon { + margin-left: 8px; + } + + .gridicons-plus-small { + position: absolute; + top: 5px; + left: 0; + margin-left: 0; + } + } +} + +.add-new-button__text { + padding-left: 8px; + font-size: 11px; + font-weight: 400; + text-transform: uppercase; + line-height: 18px; +} diff --git a/client/components/author-selector/README.md b/client/components/author-selector/README.md new file mode 100644 index 00000000000000..c4a1d8dcec4957 --- /dev/null +++ b/client/components/author-selector/README.md @@ -0,0 +1,19 @@ +Author Selector +====================== + +This component allows an administrator with sufficient privileges to edit the author of a post. Use it by wrapping the element that you will use to toggle the menu open/closed. + +```js + + by William Shakespeare + +``` + +The component will retrieve site users and render the child span as a clickable element to expand the `author-selector` UX. If selecting other authors is not appropriate (i.e., only one available author, Users not loaded, or insufficient permission), it will simply display the span. + +### Props +* siteId - siteId for site from which to fetch authors +* onSelect - function to call when user is selected, selected `author` passed as parameter +* exclude - Optional array of users IDs to be excluded from the author selector +* allowSingleUser - Optional boolean for whether or not to display the author selector when there is only one user diff --git a/client/components/author-selector/index.jsx b/client/components/author-selector/index.jsx new file mode 100644 index 00000000000000..37f95f1bc292de --- /dev/null +++ b/client/components/author-selector/index.jsx @@ -0,0 +1,290 @@ +/** + * External dependencies + */ +var React = require( 'react' ), + debug = require( 'debug' )( 'calypso:author-selector' ), + trim = require( 'lodash/string/trim' ); + +/** + * Internal dependencies + */ +var Popover = require( 'components/popover' ), + PopoverMenuItem = require( 'components/popover/menu-item' ), + SiteUsersFetcher = require( 'components/site-users-fetcher' ), + UserItem = require( 'components/user' ), + Gridicon = require( 'components/gridicon' ), + InfiniteList = require( 'components/infinite-list' ), + UsersActions = require( 'lib/users/actions' ), + Search = require( 'components/search' ), + hasTouch = require( 'lib/touch-detect' ).hasTouch; + +/** + * Module variables + */ +var instance = 0, SwitcherShell; + +SwitcherShell = React.createClass( { + displayName: 'AuthorSwitcherShell', + propTypes: { + users: React.PropTypes.array, + fetchingUsers: React.PropTypes.bool, + numUsersFetched: React.PropTypes.number, + totalUsers: React.PropTypes.number, + usersCurrentOffset: React.PropTypes.number, + allowSingleUser: React.PropTypes.bool, + popoverPosition: React.PropTypes.string + }, + + getInitialState: function() { + return { + showAuthorMenu: false + }; + }, + + componentWillMount: function() { + this.instance = instance; + instance++; + }, + + componentWillReceiveProps: function( nextProps ) { + if ( ! nextProps.fetchOptions.siteId || nextProps.fetchOptions.siteId !== this.props.fetchOptions.siteId ) { + this.props.updateSearch( false ); + } + }, + + componentDidUpdate: function( prevProps, prevState ) { + if ( ! this.state.showAuthorMenu ) { + return; + } + + if ( ! prevState.showAuthorMenu && this.props.users.length > 10 && ! hasTouch() ) { + setTimeout( () => this.refs.authorSelectorSearch.focus(), 0 ); + } + }, + + render: function() { + var users = this.props.users, + infiniteListKey = this.props.fetchNameSpace + this.instance; + + if ( ! this._userCanSelectAuthor() ) { + return { this.props.children }; + } + + return ( + + + { this.props.children } + + + + { this.props.fetchOptions.search || users.length > 10 ? + : + null } + { this.props.fetchInitialized && ! users.length && this.props.fetchOptions.search && ! this.props.fetchingUsers ? + this._noUsersFound() : + + + } + + + ); + }, + + _isLastPage: function() { + var usersLength = this.props.users.length; + if ( this.props.exclude ) { + usersLength += this.props.excludedUsers.length; + } + + return this.props.totalUsers <= usersLength; + }, + + _setListContext: function( infiniteListInstance ) { + this.setState( { + listContext: React.findDOMNode( infiniteListInstance ) + } ); + }, + + _userCanSelectAuthor: function() { + var users = this.props.users; + + if ( this.props.fetchOptions.search ) { + return true; + } + + // no user choice + if ( ! users || ! users.length || ( ! this.props.allowSingleUser && users.length === 1 ) ) { + return false; + } + + return true; + }, + + _toggleShowAuthor: function() { + this.setState( { + showAuthorMenu: ! this.state.showAuthorMenu + } ); + }, + + _onClose: function( event ) { + var toggleElement = React.findDOMNode( this.refs[ 'author-selector-toggle' ] ); + + if ( event && toggleElement.contains( event.target ) ) { + // let _toggleShowAuthor() handle this case + return; + } + this.setState( { + showAuthorMenu: false + } ); + this.props.updateSearch( false ); + }, + + _renderAuthor: function( author ) { + var authorGUID = this._getAuthorItemGUID( author ); + return ( + + + + ); + }, + + _noUsersFound: function() { + return ( +
+ { this.translate( 'No matching users found.' ) } +
+ ); + }, + + _selectAuthor: function( author ) { + debug( 'assign author:', author ); + if ( this.props.onSelect ) { + this.props.onSelect( author ); + } + this.setState( { + showAuthorMenu: false + } ); + this.props.updateSearch( false ); + }, + + _fetchNextPage: function() { + var fetchOptions = Object.assign( {}, this.props.fetchOptions, { offset: this.props.users.length } ); + debug( 'fetching next batch of authors' ); + UsersActions.fetchUsers( fetchOptions ); + }, + + _getAuthorItemGUID: function( author ) { + return 'author-item-' + author.ID; + }, + + _renderLoadingAuthors: function() { + return ( + + + + ); + }, + + _onSearch: function( searchTerm ) { + this.props.updateSearch( searchTerm ); + } +} ); + +module.exports = React.createClass( { + displayName: 'AuthorSelector', + propTypes: { + siteId: React.PropTypes.number.isRequired, + onSelect: React.PropTypes.func, + exclude: React.PropTypes.arrayOf( React.PropTypes.number ), + allowSingleUser: React.PropTypes.bool, + popoverPosition: React.PropTypes.string + }, + + getInitialState: function() { + return { + search: '' + }; + }, + + getDefaultProps: function() { + return { + showAuthorMenu: false, + onClose: function() {}, + allowSingleUser: false, + popoverPosition: 'bottom left' + }; + }, + + componentDidMount: function() { + debug( 'AuthorSelector mounted' ); + }, + + render: function() { + var searchString = this.state.search || '', + fetchOptions; + + searchString = trim( searchString ); + + fetchOptions = { + siteId: this.props.siteId, + order: 'ASC', + order_by: 'display_name', + number: 50 + }; + + if ( searchString ) { + fetchOptions.number = 20; // make search a little faster + fetchOptions.search = searchString; + fetchOptions.search_columns = [ 'user_login', 'display_name' ]; + } + + Object.freeze( fetchOptions ); + return ( + + + + ); + }, + + _updateSearch: function( searchTerm ) { + searchTerm = searchTerm ? '*' + searchTerm + '*' : ''; + this.setState( { + search: searchTerm + } ); + } +} ); diff --git a/client/components/author-selector/style.scss b/client/components/author-selector/style.scss new file mode 100644 index 00000000000000..e9e2dddcbeeb3a --- /dev/null +++ b/client/components/author-selector/style.scss @@ -0,0 +1,79 @@ +.author-selector__author-toggle { + cursor: pointer; + + .gridicon { + display: inline; + vertical-align: middle; + color: darken( $gray, 10% ); + } + + &.is-open .gridicon { + transform: rotate( 180deg ); + } + + &:hover, + &.is-open { + .gridicon, + .editor-author__name { + color: darken( $gray, 30% ); + } + } +} + +.author-selector__author-toggle .editor-author__name { + margin: 0 3px 0 8px; +} + +.author-selector__infinite-list { + max-height: 280px; + overflow-y: auto; + padding: 4px 0; + width: 200px; + max-width: 200px; + white-space: nowrap; +} + +.author-selector__menu-item { + width: 100%; + + .user { + overflow: hidden; + text-overflow: ellipsis; + } +} + +.author-selector__popover.popover { + z-index: 100; +} + +.author-selector__popover { + .search { + border-bottom: 1px solid lighten( $gray, 30 ); + // .search should be cleaned up to not force height + height: 43px; + margin-bottom: 0; + + .is-open .noticon-search { + color: $gray; + } + + .search__input[type="search"] { + border-radius: 5px; + font-size: 14px; + height: 43px; + padding: 0 50px 0; + } + + & + .author-selector__infinite-list { + padding-top: 0; + } + } +} +.author-selector__no-users { + padding: 8px 16px; + line-height: 26px; + width: 168px; + font-size: 14px; + font-style: italic; + color: $gray; +} diff --git a/client/components/bulk-select/README.md b/client/components/bulk-select/README.md new file mode 100644 index 00000000000000..c0acb96d017776 --- /dev/null +++ b/client/components/bulk-select/README.md @@ -0,0 +1,22 @@ +Bulk Select +========= + +This component is used to implement a checkbox which you can use to bulk select a list of elements + +#### How to use: + +```js +var BulkSelect = require( 'components/bulk-select' ); + +render: function() { + return ( + + ); +} +``` + +#### Props + +* `selectedElements`: (number) The number of elements currently selected +* `totalElements`: (number) The number of all the elements that can be selected +* `onToggle`: (function) callback to be executed when the checkbox state is change. The callback receives a boolean indicating the state of the 'select all' checkbox, and normally you would want to apply it to the list of elements here. diff --git a/client/components/bulk-select/docs/example.jsx b/client/components/bulk-select/docs/example.jsx new file mode 100644 index 00000000000000..7a9e7f494cad6f --- /dev/null +++ b/client/components/bulk-select/docs/example.jsx @@ -0,0 +1,66 @@ +/** +* External dependencies +*/ +import React from 'react'; + +/** + * Internal dependencies + */ +import Card from 'components/card'; +import BulkSelect from 'components/bulk-select'; + +module.exports = React.createClass( { + displayName: 'BulkSelects', + + handleToggleAll( checkedState ) { + let newElements = []; + this.state.elements.forEach( element => { + if ( typeof checkedState !== 'undefined' ) { + element.selected = checkedState; + } else { + element.selected = ! element.selected; + } + newElements.push( element ); + } ); + this.setState( { elements: newElements } ); + }, + + getInitialState() { + return { elements: [ { title: 'Apples', selected: true }, { title: 'Oranges', selected: false } ] }; + }, + + getSelectedElementsNumber: function() { + return this.state.elements.filter( function( element ) { + return element.selected; + } ).length; + }, + + renderElements() { + return this.state.elements.map( element => { + const onClick = function() { + element.selected = ! element.selected; + this.forceUpdate(); + }.bind( this ); + return ( + + ); + } ); + }, + + render() { + return ( +
+

+ BulkSelects +

+ + + { this.renderElements() } + +
+ ); + } +} ); diff --git a/client/components/bulk-select/index.jsx b/client/components/bulk-select/index.jsx new file mode 100644 index 00000000000000..25a8164376c453 --- /dev/null +++ b/client/components/bulk-select/index.jsx @@ -0,0 +1,50 @@ +/** + * External dependencies + */ +import React from 'react'; + +/** + * Internal dependencies + */ +import Count from 'components/count'; +import Gridicon from 'components/gridicon'; + +export default React.createClass( { + + displayName: 'BulkSelect', + + propTypes: { + totalElements: React.PropTypes.number.isRequired, + selectedElements: React.PropTypes.number.isRequired, + onToggle: React.PropTypes.func.isRequired + }, + + getStateIcon() { + if ( this.hasSomeElementsSelected() ) { + return ; + } + }, + + hasAllElementsSelected() { + return this.props.selectedElements && this.props.selectedElements === this.props.totalElements; + }, + + hasSomeElementsSelected() { + return this.props.selectedElements && this.props.selectedElements < this.props.totalElements; + }, + + handleToggleAll() { + const newCheckedState = ! ( this.hasSomeElementsSelected() || this.hasAllElementsSelected() ); + this.props.onToggle( newCheckedState ); + }, + + render() { + return ( +
+ + + { this.getStateIcon() } +
+ ); + } +} ); diff --git a/client/components/bulk-select/style.scss b/client/components/bulk-select/style.scss new file mode 100644 index 00000000000000..021d685d76c71d --- /dev/null +++ b/client/components/bulk-select/style.scss @@ -0,0 +1,28 @@ +.bulk-select { + position: relative; + display: flex; + align-items: center; + cursor: pointer; + + .gridicon { + width: 16px; + height: 16px; + color: $blue-medium; + position: absolute; + left: 0px; + top: 0px; + } + + > .count { + margin-left: 8px; + } +} + +input[type=checkbox].bulk-select__box { + height: 16px; + margin: 0; + padding: 0; + width: 16px; + min-width: 16px; + appearance: none; +} diff --git a/client/components/button-group/README.md b/client/components/button-group/README.md new file mode 100644 index 00000000000000..ff31ca28c0227f --- /dev/null +++ b/client/components/button-group/README.md @@ -0,0 +1,20 @@ +Button Group +========= + +This component is used to group several semantically linked buttons under the same group + +#### How to use: + +```js +const ButtonGroup = require( 'components/button-group' ), + Button = require( 'components/button' ); + +render: function() { + return ( + + + + + ); +} +``` diff --git a/client/components/button-group/docs/example.jsx b/client/components/button-group/docs/example.jsx new file mode 100644 index 00000000000000..f9834c3b14f021 --- /dev/null +++ b/client/components/button-group/docs/example.jsx @@ -0,0 +1,69 @@ +/** +* External dependencies +*/ +var React = require( 'react' ); + +/** + * Internal dependencies + */ +var ButtonGroup = require( 'components/button-group' ), + Button = require( 'components/button' ), + Card = require( 'components/card' ), + Gridicon = require( 'components/gridicon' ); + +var Buttons = React.createClass( { + displayName: 'ButtonGroup', + + mixins: [ React.addons.PureRenderMixin ], + + render: function() { + return ( +
+

+ Button Group +

+ +
+ + + +
+
+ + + + +
+
+ + + + + +
+
+ + + + + +
+
+ + + + +
+
+ + + + +
+
+
+ ); + }, +} ); + +module.exports = Buttons; diff --git a/client/components/button-group/index.jsx b/client/components/button-group/index.jsx new file mode 100644 index 00000000000000..c7f026f3d7202d --- /dev/null +++ b/client/components/button-group/index.jsx @@ -0,0 +1,30 @@ +/** + * External dependencies + */ +import React from 'react'; +import classNames from 'classnames'; + +export default React.createClass( { + + displayName: 'ButtonGroup', + + propTypes: { + children( props ) { + let error = null; + React.Children.forEach( props.children, ( child ) => { + if ( ! child.props || child.props.type !== 'button' ) { + error = new Error( 'All children elements should be a Button.' ); + } + } ); + return error; + } + }, + + render() { + const buttonGroupClasses = classNames( 'button-group', this.props.className ); + + return ( + { this.props.children } + ); + } +} ); diff --git a/client/components/button-group/style.scss b/client/components/button-group/style.scss new file mode 100644 index 00000000000000..4af79b1444da93 --- /dev/null +++ b/client/components/button-group/style.scss @@ -0,0 +1,45 @@ +.button-group { + + .button { + border-left-width: 0; + border-radius: 0; + + &:focus { + // fixes focus styles in stacking context + position: relative; + z-index: 1; + box-shadow: inset 1px 0 0 $blue-medium, 0 0 0 2px $blue-light; + } + &.is-primary:focus { + box-shadow: inset 1px 0 0 $blue-dark, 0 0 0 2px $blue-light; + } + &.is-scary:focus { + box-shadow: inset 1px 0 0 $alert-red, 0 0 0 2px lighten( $alert-red, 20% ); + } + &.is-primary.is-scary:focus { + box-shadow: inset 1px 0 0 darken( $alert-red, 30% ), 0 0 0 2px lighten( $alert-red, 20% ); + } + &:first-child:focus { + box-shadow: 0 0 0 2px $blue-light; + } + &.is-scary:first-child:focus { + box-shadow: 0 0 0 2px lighten( $alert-red, 20% ); + } + } + + .button:first-child { + border-left-width: 1px; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + } + + .button:last-child { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + } + + &.example { + margin-bottom: 16px; + display: inline-block; + } +} diff --git a/client/components/button/README.md b/client/components/button/README.md new file mode 100644 index 00000000000000..9919060de8ea7f --- /dev/null +++ b/client/components/button/README.md @@ -0,0 +1,24 @@ +Button +========= + +This component is used to implement dang sweet buttons. + +#### How to use: + +```js +var Button = require( 'components/button' ); + +render: function() { + return ( + + ); +} +``` + +#### Props + +* `compact`: (bool) whether the button is compact or not. +* `primary`: (bool) whether the button is styled as a primary button. +* `scary`: (bool) whether the button has modified styling to warn users (delete, remove, etc). +* `href`: (string) if this property is added, it will use an `a` rather than a `button` element. +* `disabled`: (bool) whether the button should be in the disabled state. diff --git a/client/components/button/docs/example.jsx b/client/components/button/docs/example.jsx new file mode 100644 index 00000000000000..f56eacf7d77dc1 --- /dev/null +++ b/client/components/button/docs/example.jsx @@ -0,0 +1,105 @@ +/** +* External dependencies +*/ +var React = require( 'react' ); + +/** + * Internal dependencies + */ +var Button = require( 'components/button' ), + Gridicon = require( 'components/gridicon' ), + Card = require( 'components/card' ); + +var Buttons = React.createClass( { + displayName: 'Buttons', + + mixins: [ React.addons.PureRenderMixin ], + + getInitialState: function() { + return { + compactButtons: false + }; + }, + + render: function() { + var toggleButtonsText = this.state.compactButtons ? 'Normal Buttons' : 'Compact Buttons'; + + return ( +
+

+ Button + { toggleButtonsText } +

+ { this.renderButtons() } +
+ ); + }, + + renderButtons: function() { + if ( ! this.state.compactButtons ) { + return ( + +
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ ); + } else { + return ( + +
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ ); + } + }, + + toggleButtons: function() { + this.setState( { compactButtons: ! this.state.compactButtons } ); + } +} ); + +module.exports = Buttons; diff --git a/client/components/button/index.jsx b/client/components/button/index.jsx new file mode 100644 index 00000000000000..4d8352dd3643bd --- /dev/null +++ b/client/components/button/index.jsx @@ -0,0 +1,46 @@ +/** + * External dependencies + */ +import React from 'react'; +import assign from 'lodash/object/assign'; +import classNames from 'classnames'; +import noop from 'lodash/utility/noop'; + +export default React.createClass( { + + displayName: 'Button', + + propTypes: { + disabled: React.PropTypes.bool, + compact: React.PropTypes.bool, + primary: React.PropTypes.bool, + scary: React.PropTypes.bool, + type: React.PropTypes.string, + href: React.PropTypes.string, + onClick: React.PropTypes.func + }, + + getDefaultProps() { + return { + disabled: false, + type: 'button', + onClick: noop + }; + }, + + render() { + const element = this.props.href ? 'a' : 'button'; + const buttonClasses = classNames( { + button: true, + 'is-compact': this.props.compact, + 'is-primary': this.props.primary, + 'is-scary': this.props.scary + } ); + + const props = assign( {}, this.props, { + className: classNames( this.props.className, buttonClasses ) + } ); + + return React.createElement( element, props, this.props.children ); + } +} ); diff --git a/client/components/button/style.scss b/client/components/button/style.scss new file mode 100644 index 00000000000000..0ca09bfdeb3ca6 --- /dev/null +++ b/client/components/button/style.scss @@ -0,0 +1,216 @@ +// ========================================================================== +// Buttons +// ========================================================================== + +// resets button styles +button { + background: transparent; + border: none; + outline: 0; + padding: 0; + font-size: 14px; + -webkit-appearance: none; + appearance: none; + vertical-align: baseline; +} + +.button { + background: $white; + border-color: lighten( $gray, 20% ); + border-style: solid; + border-width: 1px 1px 2px; + color: $gray-dark; + cursor: pointer; + display: inline-block; + margin: 0; + outline: 0; + overflow: hidden; + font-weight: 600; + text-overflow: ellipsis; + text-decoration: none; + vertical-align: top; + box-sizing: border-box; + font-size: 14px; + line-height: 21px; + border-radius: 4px; + padding: 7px 14px 9px; + -webkit-appearance: none; + appearance: none; + + &:hover { + border-color: lighten( $gray, 10% ); + color: $gray-dark; + } + &:active { + border-width: 2px 1px 1px; + } + &:visited { + color: $gray-dark; + } + &[disabled], + &:disabled { + color: lighten( $gray, 30% ); + background: $white; + border-color: lighten( $gray, 30% ); + cursor: default; + + &:active { + border-width: 1px 1px 2px; + } + } + &:focus { + border-color: $blue-medium; + box-shadow: 0 0 0 2px $blue-light; + } + &.is-compact { + padding: 7px; + color: darken( $gray, 10% ); + font-size: 11px; + line-height: 1; + text-transform: uppercase; + + &:disabled { + color: lighten( $gray, 30% ); + } + .gridicon { + top: 4px; + margin-top: -8px; + } + } + &.hidden { + display: none; + } + .gridicon { + position: relative; + top: 4px; + margin-top: -2px; + width: 18px; + height: 18px; + } +} + +// Primary buttons +.button.is-primary { + background: $blue-medium; + border-color: $blue-wordpress; + color: $white; + + &:hover, + &:focus { + border-color: $blue-dark; + color: $white; + } + &[disabled] { + background: tint( $blue-light, 50% ); + border-color: tint( $blue-wordpress, 55% ); + color: $white; + } + &.is-compact { + color: $white; + } +} + +// Scary buttons +.button.is-scary, +.button.is-dangerous { + color: $alert-red; + + &[disabled] { + color: lighten( $alert-red, 30% ); + } + &:hover, + &:focus { + border-color: $alert-red; + } + &:focus { + box-shadow: 0 0 0 2px lighten( $alert-red, 20% ); + } +} + +.button.is-primary.is-scary, +.button.is-destructive { + background: $alert-red; + border-color: darken( $alert-red, 20% ); + color: $white; + + &:hover, + &:focus { + border-color: darken( $alert-red, 30% ); + } + &[disabled] { + background: lighten( $alert-red, 20% ); + border-color: tint( $alert-red, 30% ); + } +} + +// ========================================================================== +// Deprecated styles +// +// `button.is-destructive` and ``.button.is-dangerous` are also deprecated +// ========================================================================== + +.button.is-link { + background: transparent; + border: none; + border-radius: 0; + padding: 0; + color: $blue-medium; + font-weight: 400; + font-size: inherit; + line-height: 1.65; + + &:hover, + &:focus, + &:active { + color: $link-highlight; + box-shadow: none; + } +} + +// Positions and resets font styles of noticons applied to buttons +.button.noticon { + line-height: inherit; + + &:before { + display: inline-block; + vertical-align: middle; + margin-top: -2px; + font-size: 16px; + font-style: normal; + font-weight: normal; + } +} + +// ========================================================================== +// Resets +// ========================================================================== + +// Turn Reset 'buttons' into regular text links +.wp-content input { + &[type=reset], + &[type=reset]:hover, + &[type=reset]:active, + &[type=reset]:focus { + background: 0 0; + border: 0; + padding: 0 2px 1px; + width: auto; + box-shadow: none; + } +} + +// Buttons within sentences sit on the text baseline. +.wp-content p .button { + vertical-align: baseline +} + +// Firefox Junk +.wp-content button::-moz-focus-inner, +.wp-content input[type=reset]::-moz-focus-inner, +.wp-content input[type=button]::-moz-focus-inner, +.wp-content input[type=submit]::-moz-focus-inner { + border-width: 1px 0; + border-style: solid none; + border-color: transparent; + padding: 0 +} diff --git a/client/components/chart/README.md b/client/components/chart/README.md new file mode 100644 index 00000000000000..013006c94f86bf --- /dev/null +++ b/client/components/chart/README.md @@ -0,0 +1,50 @@ +Chart +===== + +This module renders a dataset as an HTML-based chart representing the data. + +## Usage + +```js + +// require the component +var ElementChart = require( 'my-sites/chart' ); + +// And use it inline inside the render method of another component +render: function() { + return( + } data={ } barClick={ } /> + ); +} + +// Example Data Array + +[ { + 'label': , // x-axis label + 'value': , // bar value + 'nestedValue': , // nested bar value or null if no nested bar + 'className': , // classname(s) applied to bar container + 'data': , // any data that you want to have access to in the barClick callback + 'tooltipData': [ + { + label: , + value: , + link: , + icon: , + className: + } + ] +} ] + + +``` + +## Required Props + +* loading — Any truthy value indicates the chart is loading +* data — An array of data objects using the format outlined above + +## Optional Props +* minTouchBarWidth — _default: 42_ The minimum bar width on touch devices +* minBarWidth — _default: 15_ The minimum bar width on non-touch devices +* barClick - The function to be called when a bar is clicked on the chart, it is passed the entire data object of the bar \ No newline at end of file diff --git a/client/components/chart/bar-container.jsx b/client/components/chart/bar-container.jsx new file mode 100644 index 00000000000000..6cd6db5f2381c7 --- /dev/null +++ b/client/components/chart/bar-container.jsx @@ -0,0 +1,65 @@ +/** + * External dependencies + */ +var React = require( 'react' ); + +/** + * Internal dependencies + */ +var Bar = require( './bar' ), + XAxis = require( './x-axis' ), + user = require( 'lib/user' )(); + +module.exports = React.createClass( { + displayName: 'ModuleChartBarContainer', + + propTypes: { + isTouch: React.PropTypes.bool, + data: React.PropTypes.array, + yAxisMax: React.PropTypes.number, + width: React.PropTypes.number, + barClick: React.PropTypes.func + }, + + buildBars: function( max ) { + var bars, + numberBars = this.props.data.length, + tooltipPosition = user.isRTL() ? 'bottom left' : 'bottom right', + width = this.props.chartWidth, + barWidth = ( width / numberBars ); + + bars = this.props.data.map( function ( item, index ) { + var barOffset = barWidth * ( index + 1 ); + + if ( + ( ( barOffset + 230 ) > width ) && + ( ( ( barOffset + barWidth ) - 230 ) > 0 ) + ) { + tooltipPosition = user.isRTL() ? 'bottom right' : 'bottom left'; + } + + return ; + }, this ); + + return bars; + }, + + render: function() { + return ( +
+
+ { this.buildBars( this.props.yAxisMax ) } +
+ +
+ ); + } +} ); \ No newline at end of file diff --git a/client/components/chart/bar.jsx b/client/components/chart/bar.jsx new file mode 100644 index 00000000000000..48c228964640b6 --- /dev/null +++ b/client/components/chart/bar.jsx @@ -0,0 +1,133 @@ +/** + * External dependencies + */ +var React = require( 'react' ), + classNames = require( 'classnames' ), + noop = require( 'lodash/utility/noop' ), + debug = require( 'debug' )( 'calypso:module-chart:bar' ); + +/** + * Internal dependencies + */ +var Popover = require( 'components/popover' ), + Tooltip = require( 'components/chart/tooltip' ); + +module.exports = React.createClass( { + displayName: 'ModuleChartBar', + + propTypes: { + isTouch: React.PropTypes.bool, + tooltipPosition: React.PropTypes.string, + className: React.PropTypes.string, + clickHandler: React.PropTypes.func, + data: React.PropTypes.object.isRequired, + max: React.PropTypes.number, + count: React.PropTypes.number + }, + + getInitialState: function() { + return { showPopover: false }; + }, + + buildSections: function() { + var value = this.props.data.value, + max = this.props.max, + percentage = max ? Math.ceil( ( value / max ) * 10000 ) / 100 : 0, + remain = 100 - percentage, + remainFloor = Math.max( 1, Math.floor( remain ) ), + sections = [], + remainStyle, + valueStyle, + nestedValue = this.props.data.nestedValue, + nestedBar, + nestedPercentage, + nestedStyle, + spacerClassOptions = { + 'chart__bar-section': true, + 'is-spacer': true, + 'is-ghost': ( 100 === remain ) && ! this.props.active + }; + + remainStyle = { + height: remainFloor + '%' + }; + + sections.push(
); + + valueStyle = { + top: remainFloor + '%' + }; + + if ( nestedValue ) { + nestedPercentage = value ? Math.ceil( ( nestedValue / value ) * 10000 ) / 100 : 0; + + nestedStyle = { height: nestedPercentage + '%' }; + + nestedBar = (
); + } + + sections.push(
{ nestedBar }
); + + sections.push(
{ this.props.label }
); + + return sections; + }, + + clickHandler: function(){ + if ( 'function' === typeof( this.props.clickHandler ) ) { + this.props.clickHandler( this.props.data ); + } + }, + + + mouseEnter: function(){ + this.setState( { showPopover: true } ); + }, + + mouseLeave: function() { + this.setState( { showPopover: false } ); + }, + + render: function() { + debug( 'Rendering bar', this.state ); + + var barStyle, + barClass, + count = this.props.count || 1, + tooltip; + + barClass = { chart__bar: true }; + + if ( this.props.className ){ + barClass[ this.props.className ] = true; + } + + barStyle = { + width: ( ( 1 / count ) * 100 ) + '%' + }; + + if ( this.props.data.tooltipData && this.props.data.tooltipData.length && ! this.props.isTouch ) { + tooltip = + + ; + } + + return ( +
+ { this.buildSections() } +
+
+
+ { tooltip } +
+ ); + } +} ); \ No newline at end of file diff --git a/client/components/chart/index.jsx b/client/components/chart/index.jsx new file mode 100644 index 00000000000000..96f3ccca4c4c5a --- /dev/null +++ b/client/components/chart/index.jsx @@ -0,0 +1,161 @@ +/** + * External dependencies + */ +var React = require( 'react' ), + debug = require( 'debug' )( 'calypso:chart' ), + noop = require( 'lodash/utility/noop' ), + throttle = require( 'lodash/function/throttle' ); + +/** + * Internal dependencies + */ +var BarContainer = require( './bar-container' ), + observe = require( 'lib/mixins/data-observe' ), + touchDetect = require( 'lib/touch-detect' ); + +module.exports = React.createClass( { + displayName: 'ModuleChart', + + mixins: [ observe( 'dataList' ) ], + + propTypes: { + loading: React.PropTypes.bool, + data: React.PropTypes.array, + minTouchBarWidth: React.PropTypes.number, + minBarWidth: React.PropTypes.number, + barClick: React.PropTypes.func + }, + + getInitialState: function() { + return { + maxBars: 100, // arbitrarily high number. This will be calculated by resize method + width: 650 + }; + }, + + getDefaultProps: function() { + return { + minTouchBarWidth: 42, + minBarWidth: 15, + barClick: noop + }; + }, + + // Add listener for window resize + componentDidMount: function() { + this.resize = throttle( this.resize, 400 ); + window.addEventListener( 'resize', this.resize ); + this.resize(); + }, + + // Remove listener + componentWillUnmount: function() { + window.removeEventListener( 'resize', this.resize ); + }, + + componentWillReceiveProps: function( nextProps ) { + if ( this.props.loading && ! nextProps.loading ) { + this.resize(); + } + }, + + resize: function() { + if ( this.isMounted() ) { + var node = this.getDOMNode(), + width = node.clientWidth - 82, + maxBars; + + if ( touchDetect.hasTouch() ) { + width = ( width <= 0 ) ? 350 : width; // mobile safari bug with zero width + maxBars = Math.floor( width / this.props.minTouchBarWidth ); + } else { + maxBars = Math.floor( width / this.props.minBarWidth ); + } + + this.setState( { + maxBars: maxBars, + width: width + } ); + } + }, + + getYAxisMax: function( values ) { + var max = Math.max.apply( null, values ), + operand = Math.pow( 10, ( max.toString().length - 1 ) ), + rounded = ( Math.ceil( ( max + 1 ) / operand ) * operand ); + + if ( rounded < 10 ) { + rounded = 10; + } + + return rounded; + }, + + getData: function() { + var data = this.props.data; + + data = data.slice( 0 - this.state.maxBars ); + + return data; + }, + + getValues: function() { + var data = this.getData(); + + data = data.map( function ( item ) { + return item.value; + }, this ); + + return data; + }, + + isEmptyChart: function( values ) { + values = values.filter( function( value ) { + return value > 0; + }, this ); + + return values.length === 0; + }, + + render: function() { + debug( 'Rendering chart with props: ', this.props ); + + var values = this.getValues(), + yAxisMax = this.getYAxisMax( values ), + data = this.getData(), + emptyChart; + + // If we have an empty chart, show a message + // @todo this message needs to either use a or make a custom "chart__notice" class + if ( values.length && this.isEmptyChart( values ) ) { + emptyChart = ( +
+ + { this.translate( 'No activity this period', { + context: 'Message on empty bar chart in Stats', + comment: 'Should be limited to 32 characters to prevent wrapping' + } ) } + +
+ ); + } + + return ( +
+
+
+
+
+
+
+
{ this.numberFormat( 100000 ) }
+
{ this.numberFormat( yAxisMax ) }
+
{ this.numberFormat( yAxisMax / 2 ) }
+
{ this.numberFormat( 0 ) }
+
+ + { emptyChart } +
+ ); + } +} ); diff --git a/client/components/chart/label.jsx b/client/components/chart/label.jsx new file mode 100644 index 00000000000000..9502fa6d13cf86 --- /dev/null +++ b/client/components/chart/label.jsx @@ -0,0 +1,35 @@ +/** + * External dependencies + */ +var React = require( 'react' ), + debug = require( 'debug' )( 'calypso:module-chart:label' ); + +/** + * Internal dependencies + */ +var user = require( 'lib/user' )(); + +module.exports = React.createClass( { + displayName: 'ModuleChartLabel', + + propTypes: { + width: React.PropTypes.number.isRequired, + x: React.PropTypes.number.isRequired, + label: React.PropTypes.string.isRequired + }, + + render: function() { + debug( 'Rendering label' ); + + var labelStyle, + dir = user.isRTL() ? 'right' : 'left'; + + labelStyle = { + width: this.props.width + 'px' + }; + + labelStyle[ dir ] = this.props.x + 'px'; + + return
{ this.props.label }
; + } +} ); \ No newline at end of file diff --git a/client/components/chart/legend.jsx b/client/components/chart/legend.jsx new file mode 100644 index 00000000000000..2f8000601095b5 --- /dev/null +++ b/client/components/chart/legend.jsx @@ -0,0 +1,86 @@ +/** + * External dependencies + */ +var React = require( 'react' ), + PureRenderMixin = React.addons.PureRenderMixin, + debug = require( 'debug' )( 'calypso:module-chart:legend' ); + +/** + * Internal dependencies + */ + +var LegendItem = React.createClass( { + displayName: 'ModuleChartLegendItem', + + mixins: [ PureRenderMixin ], + + propTypes: { + checked: React.PropTypes.bool.isRequired, + label: React.PropTypes.oneOfType( [ React.PropTypes.object, React.PropTypes.string ] ), + attr: React.PropTypes.string.isRequired, + changeHandler: React.PropTypes.func.isRequired + }, + + clickHandler: function() { + this.props.changeHandler( this.props.attr ); + }, + + render: function() { + return ( +
  • + +
  • + ); + } + +} ); + +var Legend = React.createClass( { + displayName: 'ModuleChartLegend', + + propTypes: { + activeTab: React.PropTypes.object.isRequired, + tabs: React.PropTypes.array.isRequired, + activeCharts: React.PropTypes.array.isRequired, + availableCharts: React.PropTypes.array.isRequired, + clickHandler: React.PropTypes.func.isRequired + }, + + onFilterChange: function( chartItem ) { + this.props.clickHandler( chartItem ); + }, + + render: function() { + debug( 'Rendering legend', this.props ); + var legendColors = [ 'chart__legend-color is-dark-blue' ], + tab = this.props.activeTab, + legendItems; + + legendItems = this.props.availableCharts.map( function( legendItem, index ) { + var colorClass = legendColors[ index ], + checked = ( -1 !== this.props.activeCharts.indexOf( legendItem ) ), + tab; + + tab = this.props.tabs.filter( function( tab ) { + return tab.attr === legendItem; + } ).shift(); + + return ; + }, this ); + + + return ( +
    +
      +
    • { tab.label }
    • + { legendItems } +
    +
    + ); + } +} ); + +module.exports = Legend; \ No newline at end of file diff --git a/client/components/chart/style.scss b/client/components/chart/style.scss new file mode 100644 index 00000000000000..bdf4174b121749 --- /dev/null +++ b/client/components/chart/style.scss @@ -0,0 +1,566 @@ +// Chart +// Life is a statistical anomaly + +.chart { + position: relative; + box-sizing: border-box; + background-color: $white; + padding: 8px 0 8px 20px; +} + +// Y-axis + +// Y-axis markers (lines) +// 1: Corresponds to padding of chart + +.chart .chart__y-axis-markers { + position: absolute; + top: 8px; // 1 + left: 0; + right: 0; + height: 200px; +} + +.chart .chart__y-axis-marker { + position: absolute; + top: 0; + width: 100%; + height: 1px; + border-top: 1px solid lighten( $gray, 30% ); +} + +// Y-axis marker lines inside each chart__bar +// (This is needed so that bars overlap correctly) +.chart__bar-marker { + z-index: 1; + position: absolute; + top: 0; + width: 100%; + height: 1px; + border-top: 1px solid rgba( lighten( $gray, 30% ), .1 ); +} + +.chart__bar-marker, +.chart__y-axis-label, +.chart .chart__y-axis-marker { + &.is-fifty { + top: 50%; + } + + &.is-zero { + top: 100%; + } +} + +// Y-axis labels +// 1: matches Y-axis padding + +.chart__y-axis { + position: relative; + float: right; + height: 200px; + padding: 0 20px 0 10px; + font-size: 11px; + color: darken( $gray, 10% ); + margin-bottom: 30px; +} + +.chart__y-axis-label { + position: absolute; + top: 0; + right: 20px; // 1 + text-align: right; +} + +// For forcing the width of y-axis to the width of the label +.chart__y-axis-width-fix { + color: $transparent; +} + +// X-axis +// 1: hides spaces between elements + +.chart__x-axis { + position: relative; + font-size: 0; // 1 + padding: 5px 0; + min-height: 18px; + color: darken( $gray, 30% ); +} + +.chart__x-axis-label { + position: absolute; + display: inline-block; + vertical-align: top; + font-size: 11px; + text-align: center; +} + +// X-axis label indicator +// (vertical thin grey bar) + +.chart__x-axis-label::before { + content: ''; + display: block; + position: absolute; + top: -4px; + left: 50%; + margin-left: -.5px; + width: 1px; + height: 5px; + background: $gray-light; + background-image: linear-gradient(to bottom, $gray-light 0%, lighten( $gray, 20% ) 100%); +} + +// Bar wrapper +// 1: hides spaces between elements + +.chart__bars { + position: relative; + font-size: 0; // 1 + height: 200px; + text-align: center; + overflow: hidden; + display: -ms-flex; + display: flex; +} + +// Individual bar +// 1: Needs to be relative so that the contained graphic bar has boundaries + +.chart__bar { + text-align: center; + display: inline-block; + position: relative; // 1 + height: 200px; + -ms-flex-grow: 1; + flex-grow: 1; + -ms-flex-shrink: 1; + flex-shrink: 1; + + + &.is-weekend { + background-color: rgba( lighten( $gray, 30% ), .5 ); + } + + &:hover { + cursor: pointer; + background-color: rgba( lighten( $gray, 30% ), .3 ); + } + + &.is-selected { + cursor: default; + background-color: rgba( $orange-jazzy, .1 ); + } +} + +// Individual bar wrapper & misc +// 1: Positions the bar in the space as defined by .bar +// 2: Default value for top so bars grow when they get a new value +// (doesn't function correctly for period switching right now, not sure why) +// (also doesn't work because updating the DOM is so heavy it stalls all animations) + +.chart__bar-section { + display: inline-block; + background-color: $blue-wordpress; + position: absolute; + top: 0; // 2 + right: 16%; // 1 + bottom: 0; // 1 + left: 16%; // 1 + z-index: 2; + transition: top .3s ease-out; // 2 + + .chart__bar:hover &.is-bar { + background-color: $blue-medium; + } + + .chart__bar.is-selected &.is-bar { + background-color: $orange-jazzy; + } + + &.is-spacer { + z-index: 0; + background-color: $transparent; + } + + &.is-ghost::after { + content: ""; + display: block; + position: absolute; + top: 160px; + bottom: 0; + left: 0; + z-index: 1; + width: 100%; + height: 40px; + background-image: linear-gradient(to bottom, $transparent, rgba( lighten( $gray, 30% ), .5 ) ); // TODO: needs to use default color for gradient + + .chart__bar:hover & { + display: none; + } + } +} + +.chart__bar-section-inner { + background: darken( $blue-dark, 5% ); + position: absolute; + right: 23.33%; + bottom: 0; + left: 23.33%; + + .chart__bar.is-selected & { + background-color: $orange-fire; + } +} + +// Chart legend (wrapper) +// 1: L/R matches padding of y-axis labels in chart + +.chart__legend { + @include clear-fix; + margin-bottom: -8px; +} + +// Chart legend options (list) + +.chart__legend .chart__legend-options { + float: right; + color: lighten( $gray-dark, 20% ); + list-style-type: none; + margin: 0; + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.1em; + + @include breakpoint( "<480px" ) { + width: 100%; + } + +} + +// Chart legend option (list item) + +.chart__legend-option { + display: inline; + text-align: left; + + // Expand labels to create bigger touch targets + @include breakpoint( "<480px") { + width: 50%; + display: inline-block; + } +} + +// Chart legend label +// 1: 19/10px instead of 20/12px because it aligns better optically + +.chart__legend-label { + display: inline-block; + padding: 12px 19px 10px 20px; // 1 + + &.is-selectable { + cursor: pointer; + + &:focus, + &:hover { + color: $link-highlight; + } + } + + @include breakpoint( "<480px" ) { + display: block; + } +} + +// Chart legend color +// 1: Needed to overvwrite form styles in main stylesheets +// 2: Make leftmost legend fit snugly up against the leftmost bars + +.chart__legend-option .chart__legend-color { + width: 10px; + height: 10px; + background: $blue-wordpress; + display: inline-block; + border-radius: 1px; + vertical-align: top; + margin: 3px 5px 3px 8px; // 1 +} + +@include breakpoint( "<480px" ) { + .chart__legend-option:first-child .chart__legend-color { + margin-left: 2px; // 2 + } +} + +.chart__legend-color.is-dark-blue { + background: darken( $blue-dark, 5% ); +} + +// Chart legend checkbox + +.chart__legend-option .chart__legend-checkbox { + margin: 0; + float: none; + vertical-align: top; +} + +// Chart empty (message) +// A message displayed when there's absolutely no data to chart + +.chart__empty { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + text-align: center; + font-size: 14px; + line-height: 24px; + clear: both; + z-index: 1; +} + +.chart__empty_notice { + position: relative; + top: 97px; + padding: 11px 24px; + margin-bottom: 24px; + border-radius: 1px; + background: #fff; + box-sizing: border-box; + font-size: 14px; + line-height: 1.4285; + animation: appear .3s ease-in-out; + box-shadow: 0 0 0 1px transparentize( lighten( $gray, 20% ), .5 ), + 0 1px 2px lighten( $gray, 30% ); + + @include breakpoint( ">660px" ) { + padding: 13px 48px; + font-size: inherit; + + &::before { + @extend %noticon; + content: '\f456'; + position: absolute; + top: 23px; + left: 20px; + margin: -12px 0px 0 -8px; + font-size: 24px; + line-height: 1; + } + } +} + +// Chart tooltip + +.chart__tooltip { + z-index: 1000; + position: absolute; + /* default offset for edge-cases: https://github.com/component/tip/pull/12 */ + top: 0; + left: 0 #{"/*rtl:ignore*/"}; + right: auto #{"/*rtl:ignore*/"}; + + &.tip-bottom-left { + .tip-arrow { + border-color: $transparent; + position: absolute; + + &::before { + content: ''; + border: 4px solid $transparent; + border-bottom-color: darken( $gray, 30% ); + position: absolute; + left: 231px #{"/*rtl:ignore*/"}; + top: -3px; + + .rtl & { + left: -18px #{"/*rtl:ignore*/"}; + top: -3px; + } + } + } + } + + &.tip-bottom-right, + &.tip-bottom { + .tip-arrow { + border-color: $transparent; + position: absolute; + + &::before { + content: ''; + border: 4px solid $transparent; + border-bottom-color: darken( $gray, 30% ); + position: absolute; + left: 11px #{"/*rtl:ignore*/"}; + top: -3px; + + .rtl & { + left: -238px #{"/*rtl:ignore*/"}; + top: -3px; + } + } + } + } + + &.tip-top { + .tip-arrow { + border-color: $transparent; + position: absolute; + + &::before { + content: ''; + border: 4px solid $transparent; + border-top-color: darken( $gray, 30% ); + position: absolute; + left: 118px #{"/*rtl:ignore*"}; + bottom: -40px; + } + } + } + + &.tip-bottom { + .tip-arrow { + &::before { + left: 86px #{"/*rtl:ignore*/"}; + top: -4px; + + .rtl & { + left: -93px #{"/*rtl:ignore*/"}; + } + } + } + } + + .tip-inner { + border: 0px; + box-shadow: none; + border-radius: 2px; + color: $white; + background: darken( $gray, 30% ); + font-size: 11px; + padding: 6px 10px; + margin-top: 5px; + width: 230px; + text-align: left; + + ul { + @include clear-fix; + list-style: none; + margin: 0; + padding: 0; + + li { + font-size: 11px; + text-transform: uppercase; + font-weight: 100; + height: 24px; + letter-spacing: 0.1em; + border: 0; + + .wrapper { + display: block; + line-height: inherit; + line-height: 24px; + clear: both; + } + + .value { + text-align: right; + float: right; + min-width: 22px; + color: lighten( $gray, 20% ); + } + + .label { + display: block; + overflow: hidden; + word-break: break-all; + vertical-align: baseline; + } + + .gridicon { + vertical-align: middle; + margin-right: 6px; + margin-top: -3px; + } + } + } + } + + &.is-streak { + .tip-arrow { + &::before { + left: 87px; + } + } + + .tip-inner { + width: 160px; + position: relative; + top: -10px; + + li { + height: 14px; + + .label { + width: 100%; + float: left; + text-align: center; + + .rtl & { + font-size: 11px; + } + + .post-count { + font-weight: bold; + } + } + .value { + float: none; + } + } + } + } +} + +.chart__tooltip .module-content-list-item { + + &.is-date-label { + font-size: 11px; + margin-bottom: 2px; + text-transform: uppercase; + font-weight: bold; + border-bottom: 1px solid darken( $gray, 27% ); + padding-bottom: 2px; + } + + &.is-published-item { + height: 19px; + + .label { + text-transform: none; + color: lighten( $gray, 20% ); + overflow: hidden; + letter-spacing: 0; + height: 19px; + } + + .value { + width: 0; + min-width: 0; + + &::before { + content: ''; + position: relative; + background-image: linear-gradient(to right, rgba(61, 89, 109, 0) 0%, rgba(61, 89, 109, 0.5), rgba(61, 89, 109, 1)); + left: -30px; + width: 30px; + height: 24px; + display: block; + } + } + } +} diff --git a/client/components/chart/tooltip.jsx b/client/components/chart/tooltip.jsx new file mode 100644 index 00000000000000..f9ac4761d2fec2 --- /dev/null +++ b/client/components/chart/tooltip.jsx @@ -0,0 +1,47 @@ +/** + * External dependencies + */ +var React = require( 'react' ); + +/** + * Internal dependencies + */ +var Gridicon = require( 'components/gridicon' ); + +module.exports = React.createClass( { + displayName: 'ChartTooltip', + + propTypes: { + data: React.PropTypes.array.isRequired + }, + + render: function() { + var listItemElements; + + listItemElements = this.props.data.map( function( options, i ) { + var wrapperClasses = [ 'module-content-list-item' ], + gridiconSpan; + + if ( options.icon ) { + gridiconSpan = ( ); + } + + wrapperClasses.push( options.className ); + + return ( +
  • + + { options.value } + { gridiconSpan }{ options.label } + +
  • + ); + } ); + + return ( +
      + { listItemElements } +
    + ); + } +} ); diff --git a/client/components/chart/x-axis.jsx b/client/components/chart/x-axis.jsx new file mode 100644 index 00000000000000..96f41f6b7b27b3 --- /dev/null +++ b/client/components/chart/x-axis.jsx @@ -0,0 +1,107 @@ +/** + * External dependencies + */ +var React = require( 'react' ), + debug = require( 'debug' )( 'calypso:module-chart:x-axis' ), + throttle = require( 'lodash/function/throttle' ); + +/** + * Internal dependencies + */ +var Label = require( './label' ); + +module.exports = React.createClass( { + displayName: 'ModuleChartXAxis', + + propTypes: { + labelWidth: React.PropTypes.number.isRequired, + data: React.PropTypes.array.isRequired + }, + + getInitialState: function() { + return { + divisor: 1, + spacing: this.props.labelWidth + }; + }, + + // Add listener for window resize + componentDidMount: function() { + this.resizeThrottled = throttle( this.resize, 400 ); + window.addEventListener( 'resize', this.resizeThrottled ); + this.resize(); + }, + + // Remove listener + componentWillUnmount: function() { + if( this.resizeThrottled.cancel ) { + this.resizeThrottled.cancel(); + } + window.removeEventListener( 'resize', this.resizeThrottled ); + }, + + componentWillReceiveProps: function( nextProps ) { + this.resize( nextProps ); + }, + + resize: function( nextProps ) { + if ( this.isMounted() ) { + var node, + props = this.props, + width, + dataCount, + spacing, + labelWidth, + divisor; + + node = this.getDOMNode(); + + if ( nextProps && ! ( nextProps instanceof Event ) ) { + props = nextProps; + } + + /** + * Overflow needs to be hidden to calculate the desired width, + * but visible to display each labels' overflow :/ + */ + + node.style.overflow = 'hidden'; + width = node.clientWidth; + node.style.overflow = 'visible'; + + dataCount = props.data.length || 1; + spacing = width / dataCount; + labelWidth = props.labelWidth; + divisor = Math.ceil( labelWidth / spacing ); + + this.setState( { + divisor: divisor, + spacing: spacing + } ); + } + }, + + render: function() { + debug( 'Rendering chart x-axis', this.props.data ); + + var labels, + data = this.props.data; + + labels = data.map( function ( item, index ) { + var x = ( index * this.state.spacing ) + ( ( this.state.spacing - this.props.labelWidth ) / 2 ), + rightIndex = data.length - index - 1, + label; + + if ( rightIndex % this.state.divisor === 0 ) { + label =