├── .prettierrc
├── .prettierignore
├── babel.config.js
├── src
├── blocks
│ ├── i18n.js
│ ├── block-toggles
│ │ ├── attributes.js
│ │ ├── components
│ │ │ └── inspector.js
│ │ └── save.js
│ ├── block-sharing
│ │ ├── styles
│ │ │ └── editor.scss
│ │ ├── components
│ │ │ └── sharing.js
│ │ └── index.js
│ ├── block-posts-grid
│ │ ├── deprecated
│ │ │ ├── index.js
│ │ │ └── save.deprecated.js
│ │ ├── save.js
│ │ ├── edit.js
│ │ └── index.js
│ ├── block-grid-container
│ │ ├── deprecated
│ │ │ ├── index.js
│ │ │ └── save.deprecated.js
│ │ ├── save.js
│ │ └── attributes.js
│ ├── block-image-carousel
│ │ ├── deprecated
│ │ │ └── index.js
│ │ ├── attributes.js
│ │ ├── components
│ │ │ └── swap-slide-toolbar.js
│ │ └── index.js
│ ├── block-horizontal-tabs
│ │ ├── attributes.js
│ │ ├── styles
│ │ │ └── style.scss
│ │ ├── components
│ │ │ └── horizontal-tab
│ │ │ │ └── index.php
│ │ ├── save.js
│ │ └── index.js
│ ├── block-vertical-tabs
│ │ ├── attributes.js
│ │ ├── components
│ │ │ ├── vertical-align-toolbar.js
│ │ │ ├── vertical-tab
│ │ │ │ └── index.php
│ │ │ └── inspector.js
│ │ ├── styles
│ │ │ ├── style.scss
│ │ │ └── editor.scss
│ │ ├── save.js
│ │ └── index.js
│ ├── block-carousel
│ │ ├── deprecated
│ │ │ ├── index.js
│ │ │ ├── 2.0
│ │ │ │ └── save.deprecated.js
│ │ │ ├── 3.0
│ │ │ │ └── save.deprecated.js
│ │ │ └── 1.0
│ │ │ │ └── save.deprecated.js
│ │ ├── attributes.js
│ │ ├── save.js
│ │ └── components
│ │ │ └── swap-slide-toolbar.js
│ ├── block-column-container
│ │ ├── save.js
│ │ └── attributes.js
│ ├── block-heading
│ │ ├── attributes.js
│ │ ├── components
│ │ │ ├── heading-toolbar.js
│ │ │ ├── custom-heading.js
│ │ │ └── subheading-toolbar.js
│ │ ├── index.js
│ │ └── save.js
│ ├── block-cta
│ │ ├── attributes.js
│ │ ├── save.js
│ │ └── index.js
│ └── block-post-grid
│ │ └── index.js
├── update-category
│ ├── register-stores.js
│ ├── register-filters.js
│ ├── index.js
│ ├── deregister-blocks.js
│ └── register-styles.js
├── vendor.js
├── register.js
├── webfonts
│ ├── fa-brands-400.eot
│ ├── fa-brands-400.ttf
│ ├── fa-brands-400.woff
│ ├── fa-regular-400.eot
│ ├── fa-regular-400.ttf
│ ├── fa-solid-900.eot
│ ├── fa-solid-900.ttf
│ ├── fa-solid-900.woff
│ ├── fa-solid-900.woff2
│ ├── fa-brands-400.woff2
│ ├── fa-regular-400.woff
│ └── fa-regular-400.woff2
├── block-colors.scss
├── extend
│ ├── index.js
│ ├── font-colors
│ │ └── editor.scss
│ ├── space-settings-inspector
│ │ ├── editor.scss
│ │ ├── index.test.js
│ │ └── utils.js
│ ├── check-core-block.js
│ ├── show-hide-inspector
│ │ └── editor.scss
│ └── width-settings
│ │ ├── index.test.js
│ │ └── utils.js
├── components
│ ├── block-selector
│ │ ├── editor.scss
│ │ └── index.js
│ ├── large-modal
│ │ ├── index.js
│ │ └── editor.scss
│ ├── settings-spacer
│ │ └── index.js
│ ├── templates-modal
│ │ ├── page-templates
│ │ │ ├── page-types.js
│ │ │ └── page-templates.js
│ │ ├── reusable-button.js
│ │ ├── section-button.js
│ │ ├── page-layout-button.js
│ │ └── section-templates
│ │ │ └── templates
│ │ │ ├── inform-map-embed-focus.js
│ │ │ ├── introduce-page-title.js
│ │ │ └── watch-embedded-video.js
│ ├── color-appender
│ │ └── editor.scss
│ ├── custom-palette
│ │ └── editor.scss
│ ├── pause-toolbar
│ │ └── index.js
│ ├── show-hide-toolbar
│ │ └── index.js
│ ├── width-toolbar
│ │ └── index.js
│ ├── preview-panel
│ │ └── index.js
│ ├── vertical-alignment-toolbar
│ │ └── index.js
│ ├── youtube-api-toggle
│ │ └── index.js
│ ├── remove-button
│ │ └── index.js
│ └── resizable-box
│ │ └── index.js
├── stores
│ └── twitter
│ │ ├── controls.js
│ │ ├── prepare-query.js
│ │ ├── selectors.js
│ │ ├── index.js
│ │ ├── actions.js
│ │ ├── reducer.js
│ │ └── resolvers.js
├── frontend.js
├── editor.js
└── blocks.js
├── composer.json
├── languages
└── en.mo
├── .husky
├── pre-push
└── pre-commit
├── assets
├── c9-logo.png
├── wood-tile.jpg
├── screenshot-1.jpg
├── screenshot-2.jpg
├── screenshot-3.jpg
├── screenshot-4.jpg
├── screenshot-5.jpg
├── screenshot-6.jpg
├── device-previews.png
├── grid-screenshot.jpg
├── hero-screenshot.jpg
├── using-templates.jpg
├── drag-drop-section.jpg
├── reusable-layouts.jpg
├── change-number-rows.jpg
├── change-overall-width.jpg
├── pick-column-layout.png
├── building-from-scratch.jpg
├── c9-grid-block-preview.jpg
├── change-number-columns.jpg
├── building-from-templates.jpg
├── c9-admin-dashboard-preview.jpg
├── c9-admin-plugin-screenshot.jpg
├── c9-blocks-netflix-tutorial.jpg
├── responsive-landing-2020-theme.jpg
├── awareness-consideration-conversion.jpg
├── page-template-icons
│ └── hero-screenshot.jpg
├── section-template-icons
│ ├── 1882E2F807C6F8D2.png
│ ├── 1882E2F807C6F8D6.jpg
│ ├── 8BB68308AC383C1E.jpg
│ ├── about-picture-contact-card.svg
│ ├── single-profile.svg
│ └── classic-header-statement-logo.svg
├── icon-c9-heading.svg
├── c9-trash.svg
├── fa-icons
│ ├── facebook-square-brands.svg
│ ├── chevron-circle-right-solid.svg
│ ├── linkedin-in-brands.svg
│ ├── twitter-square-brands.svg
│ ├── instagram-brands.svg
│ └── tiktok.svg
├── icon-carousel-next.svg
├── icon-carousel-prev.svg
├── icon-c9-subheading-enable-toolbar-icon.js
├── icon-c9-grid.svg
├── toggle-icon.svg
├── icon-c9-tabs-horizontal.svg
├── icon-c9-cta-bar.svg
├── icon-c9-tabs-vertical-tabs.svg
├── toggle-open.js
├── c9-feather-logo-gray.svg
├── icon-c9-toggles.svg
├── icon-c9-anything-carousel.svg
├── c9-feather-logo-icon.js
├── icon-c9-image-carousel.svg
├── icon-c9-post-grid.svg
├── tab-icons.js
├── icon-c9-social-share.svg
└── c9-feather-logo-gradient.svg
├── jest.setup.js
├── .distignore
├── .eslintignore
├── CHANGELOG.md
├── phpunit.xml.dist
├── jest.config.js
├── .editorconfig
├── phpcs.xml.dist
├── config
├── babel-preset.js
├── externals.js
└── paths.js
├── tests
├── test-class-check-dist-files-exist.php
├── bootstrap.php
└── test-class-layout-endpoints.php
├── .eslintrc.json
├── .travis.yml
├── plugin.php
└── dist
└── blocks.frontend.build.js
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true
3 | }
4 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules/**/*.js
2 | dist/*.js
3 | dist/*.css
4 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = { presets: ['@babel/preset-env'] };
2 |
--------------------------------------------------------------------------------
/src/blocks/i18n.js:
--------------------------------------------------------------------------------
1 | wp.i18n.setLocaleData({ '': {} }, 'c9-blocks');
2 |
--------------------------------------------------------------------------------
/src/update-category/register-stores.js:
--------------------------------------------------------------------------------
1 | // import "../stores/twitter";
2 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "require": {
3 | "wp-cli/i18n-command": "^2.4"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/languages/en.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/languages/en.mo
--------------------------------------------------------------------------------
/.husky/pre-push:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | npm test
5 |
--------------------------------------------------------------------------------
/assets/c9-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/c9-logo.png
--------------------------------------------------------------------------------
/assets/wood-tile.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/wood-tile.jpg
--------------------------------------------------------------------------------
/jest.setup.js:
--------------------------------------------------------------------------------
1 | global.wp = {
2 | i18n: {
3 | __: jest.fn((text) => text),
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/.distignore:
--------------------------------------------------------------------------------
1 | /.wordpress-org
2 | /.git
3 | /.github
4 | /node_modules
5 |
6 | .distignore
7 | .gitignore
--------------------------------------------------------------------------------
/assets/screenshot-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/screenshot-1.jpg
--------------------------------------------------------------------------------
/assets/screenshot-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/screenshot-2.jpg
--------------------------------------------------------------------------------
/assets/screenshot-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/screenshot-3.jpg
--------------------------------------------------------------------------------
/assets/screenshot-4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/screenshot-4.jpg
--------------------------------------------------------------------------------
/assets/screenshot-5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/screenshot-5.jpg
--------------------------------------------------------------------------------
/assets/screenshot-6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/screenshot-6.jpg
--------------------------------------------------------------------------------
/src/vendor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Import bootstrap styles.
3 | */
4 | import './vendor/c9-bootstrap.css';
5 |
--------------------------------------------------------------------------------
/assets/device-previews.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/device-previews.png
--------------------------------------------------------------------------------
/assets/grid-screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/grid-screenshot.jpg
--------------------------------------------------------------------------------
/assets/hero-screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/hero-screenshot.jpg
--------------------------------------------------------------------------------
/assets/using-templates.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/using-templates.jpg
--------------------------------------------------------------------------------
/src/register.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Register block category + side menu.
3 | */
4 | import './update-category';
5 |
--------------------------------------------------------------------------------
/assets/drag-drop-section.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/drag-drop-section.jpg
--------------------------------------------------------------------------------
/assets/reusable-layouts.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/reusable-layouts.jpg
--------------------------------------------------------------------------------
/assets/change-number-rows.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/change-number-rows.jpg
--------------------------------------------------------------------------------
/assets/change-overall-width.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/change-overall-width.jpg
--------------------------------------------------------------------------------
/assets/pick-column-layout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/pick-column-layout.png
--------------------------------------------------------------------------------
/src/webfonts/fa-brands-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/src/webfonts/fa-brands-400.eot
--------------------------------------------------------------------------------
/src/webfonts/fa-brands-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/src/webfonts/fa-brands-400.ttf
--------------------------------------------------------------------------------
/src/webfonts/fa-brands-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/src/webfonts/fa-brands-400.woff
--------------------------------------------------------------------------------
/src/webfonts/fa-regular-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/src/webfonts/fa-regular-400.eot
--------------------------------------------------------------------------------
/src/webfonts/fa-regular-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/src/webfonts/fa-regular-400.ttf
--------------------------------------------------------------------------------
/src/webfonts/fa-solid-900.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/src/webfonts/fa-solid-900.eot
--------------------------------------------------------------------------------
/src/webfonts/fa-solid-900.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/src/webfonts/fa-solid-900.ttf
--------------------------------------------------------------------------------
/src/webfonts/fa-solid-900.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/src/webfonts/fa-solid-900.woff
--------------------------------------------------------------------------------
/src/webfonts/fa-solid-900.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/src/webfonts/fa-solid-900.woff2
--------------------------------------------------------------------------------
/assets/building-from-scratch.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/building-from-scratch.jpg
--------------------------------------------------------------------------------
/assets/c9-grid-block-preview.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/c9-grid-block-preview.jpg
--------------------------------------------------------------------------------
/assets/change-number-columns.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/change-number-columns.jpg
--------------------------------------------------------------------------------
/src/webfonts/fa-brands-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/src/webfonts/fa-brands-400.woff2
--------------------------------------------------------------------------------
/src/webfonts/fa-regular-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/src/webfonts/fa-regular-400.woff
--------------------------------------------------------------------------------
/src/webfonts/fa-regular-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/src/webfonts/fa-regular-400.woff2
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | **/*.min.js
2 | **/node_modules/**
3 | **/vendor/**
4 | build
5 | coverage
6 | cypress
7 | node_modules
8 | vendor
--------------------------------------------------------------------------------
/assets/building-from-templates.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/building-from-templates.jpg
--------------------------------------------------------------------------------
/assets/c9-admin-dashboard-preview.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/c9-admin-dashboard-preview.jpg
--------------------------------------------------------------------------------
/assets/c9-admin-plugin-screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/c9-admin-plugin-screenshot.jpg
--------------------------------------------------------------------------------
/assets/c9-blocks-netflix-tutorial.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/c9-blocks-netflix-tutorial.jpg
--------------------------------------------------------------------------------
/assets/responsive-landing-2020-theme.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/responsive-landing-2020-theme.jpg
--------------------------------------------------------------------------------
/assets/awareness-consideration-conversion.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/awareness-consideration-conversion.jpg
--------------------------------------------------------------------------------
/assets/page-template-icons/hero-screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/page-template-icons/hero-screenshot.jpg
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | Based on https://keepachangelog.com/en/0.3.0/
3 |
4 | ## [Unreleased]
5 |
6 | Just added changelog. No version numbers yet.
--------------------------------------------------------------------------------
/assets/section-template-icons/1882E2F807C6F8D2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/section-template-icons/1882E2F807C6F8D2.png
--------------------------------------------------------------------------------
/assets/section-template-icons/1882E2F807C6F8D6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/section-template-icons/1882E2F807C6F8D6.jpg
--------------------------------------------------------------------------------
/assets/section-template-icons/8BB68308AC383C1E.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/covertnine/c9-blocks/HEAD/assets/section-template-icons/8BB68308AC383C1E.jpg
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | npx pretty-quick --staged && npm run lint:fix
5 | npm run build
6 | git add .
--------------------------------------------------------------------------------
/src/block-colors.scss:
--------------------------------------------------------------------------------
1 | // Colors.
2 |
3 | $black: rgba(41, 41, 41, 0.15);
4 | $white: #f4f4f4;
5 | $gray: #dedede;
6 | $green: #bada55;
7 | $red: orangered;
8 |
--------------------------------------------------------------------------------
/src/extend/index.js:
--------------------------------------------------------------------------------
1 | //import "./font-colors";
2 | import './show-hide-inspector';
3 | import './space-settings-inspector';
4 | //import './width-settings';
5 |
--------------------------------------------------------------------------------
/src/components/block-selector/editor.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Editor Styles
3 | */
4 | .is-hovered .block-selector,
5 | .is-selected .block-selector {
6 | visibility: visible;
7 | opacity: 1;
8 | }
9 |
--------------------------------------------------------------------------------
/src/blocks/block-toggles/attributes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Block Attributes
3 | */
4 | const attributes = {
5 | toggleCount: {
6 | type: 'number',
7 | default: 2,
8 | },
9 | instanceId: {
10 | type: 'number',
11 | },
12 | };
13 |
14 | export default attributes;
15 |
--------------------------------------------------------------------------------
/src/stores/twitter/controls.js:
--------------------------------------------------------------------------------
1 | const { apiFetch } = wp;
2 |
3 | export function API_FETCH({ request }) {
4 | return apiFetch(request).then((fetchedData) => {
5 | if (fetchedData && fetchedData.success && fetchedData.response) {
6 | return fetchedData.response;
7 | }
8 | return false;
9 | });
10 | }
11 |
--------------------------------------------------------------------------------
/src/components/large-modal/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { Modal } = wp.components;
5 |
6 | const LargeModal = (props) => (
7 |
8 | {props.children}
9 |
10 | );
11 |
12 | export default LargeModal;
13 |
--------------------------------------------------------------------------------
/src/stores/twitter/prepare-query.js:
--------------------------------------------------------------------------------
1 | import qs from 'qs';
2 |
3 | export default function prepareQuery(type, data) {
4 | const additionalData = qs.stringify(data, { encode: false });
5 | const query = `/c9-blocks/get_twitter_${type}/${
6 | additionalData ? `?${additionalData}` : ''
7 | }`;
8 |
9 | return query;
10 | }
11 |
--------------------------------------------------------------------------------
/src/extend/font-colors/editor.scss:
--------------------------------------------------------------------------------
1 | .c9-ext-badge {
2 | position: relative;
3 | left: 8px;
4 | padding: 1px 3px;
5 | font-size: 8px;
6 | font-weight: 700;
7 | color: #a9a9a9;
8 | text-transform: uppercase;
9 | background-color: #f3f3f3;
10 | border-radius: 2px;
11 | transition: 0.15s background-color, 0.15s color;
12 | }
13 |
--------------------------------------------------------------------------------
/src/components/settings-spacer/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Styles
3 | */
4 | import styled from 'styled-components';
5 |
6 | const StyledSpacer = styled.div`
7 | height: 15px;
8 | border-top: 1px solid #e2e4e7;
9 | margin: 0 -16px;
10 | `;
11 |
12 | const SettingsSpacer = () => ;
13 |
14 | export default SettingsSpacer;
15 |
--------------------------------------------------------------------------------
/src/extend/space-settings-inspector/editor.scss:
--------------------------------------------------------------------------------
1 | .c9-ext-badge {
2 | position: relative;
3 | left: 8px;
4 | padding: 1px 3px;
5 | font-size: 8px;
6 | font-weight: 700;
7 | color: #a9a9a9;
8 | text-transform: uppercase;
9 | background-color: #f3f3f3;
10 | border-radius: 2px;
11 | transition: 0.15s background-color, 0.15s color;
12 | }
13 |
--------------------------------------------------------------------------------
/src/blocks/block-sharing/styles/editor.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Editor styles for the admin
3 | */
4 | /* compatibility with wp 6.4.3 */
5 | .wp-block[data-type='c9-blocks/social-share'] .fa-facebook-f:before {
6 | content: '\f09a';
7 | }
8 |
9 | .c9-block-sharing {
10 | margin-bottom: 0;
11 | }
12 |
13 | .c9-block-sharing .c9-share-list a:hover {
14 | color: #fff;
15 | }
16 |
--------------------------------------------------------------------------------
/src/stores/twitter/selectors.js:
--------------------------------------------------------------------------------
1 | import prepareQuery from './prepare-query';
2 |
3 | export function getTwitterFeed(state, data) {
4 | const query = prepareQuery('feed', data);
5 |
6 | return state.feeds[query];
7 | }
8 |
9 | export function getTwitterProfile(state, data) {
10 | const query = prepareQuery('profile', data);
11 |
12 | return state.profiles[query];
13 | }
14 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 | ./tests/
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/blocks/block-posts-grid/deprecated/index.js:
--------------------------------------------------------------------------------
1 | import SaveDeprecated from './save.deprecated';
2 | import attributes from '../attributes';
3 |
4 | export const BlockPostsGridDeprecated = (props) => (
5 |
6 | );
7 |
8 | const Deprecated = [
9 | {
10 | attributes: attributes,
11 | save: BlockPostsGridDeprecated,
12 | },
13 | ];
14 |
15 | export default Deprecated;
16 |
--------------------------------------------------------------------------------
/assets/icon-c9-heading.svg:
--------------------------------------------------------------------------------
1 | Artboard 1 copy 23 1
--------------------------------------------------------------------------------
/src/stores/twitter/index.js:
--------------------------------------------------------------------------------
1 | import reducer from './reducer';
2 | import * as selectors from './selectors';
3 | import * as actions from './actions';
4 | import * as controls from './controls';
5 | import * as resolvers from './resolvers';
6 |
7 | const { registerStore } = wp.data;
8 |
9 | registerStore('c9-blocks/twitter', {
10 | reducer,
11 | selectors,
12 | actions,
13 | controls,
14 | resolvers,
15 | });
16 |
--------------------------------------------------------------------------------
/src/stores/twitter/actions.js:
--------------------------------------------------------------------------------
1 | export function apiFetch(request) {
2 | return {
3 | type: 'API_FETCH',
4 | request,
5 | };
6 | }
7 |
8 | export function setTwitterFeed(query, feed) {
9 | return {
10 | type: 'SET_TWITTER_FEED',
11 | query,
12 | feed,
13 | };
14 | }
15 |
16 | export function setTwitterProfile(query, profile) {
17 | return {
18 | type: 'SET_TWITTER_PROFILE',
19 | query,
20 | profile,
21 | };
22 | }
23 |
--------------------------------------------------------------------------------
/src/frontend.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Gutenberg Blocks Frontend JS
3 | *
4 | * All blocks frontend related JavaScript files should be imported here.
5 | * You can create a new block folder in this dir and include code
6 | * for that block here as well.
7 | *
8 | * All blocks should be included here since this is the file that
9 | * Webpack is compiling as the input file.
10 | */
11 |
12 | import './blocks/block-grid-container/frontend.js';
13 |
--------------------------------------------------------------------------------
/src/extend/check-core-block.js:
--------------------------------------------------------------------------------
1 | const supportedBlocks = [
2 | 'core/heading',
3 | 'core/quote',
4 | 'core/list',
5 | 'core/table',
6 | ];
7 |
8 | /**
9 | * Check if core block may be extended.
10 | *
11 | * @param {String} name - block name.
12 | *
13 | * @return {Boolean} block supported.
14 | */
15 | export default function checkCoreBlock(name) {
16 | return name && /^core/.test(name) && -1 !== supportedBlocks.indexOf(name);
17 | }
18 |
--------------------------------------------------------------------------------
/src/update-category/register-filters.js:
--------------------------------------------------------------------------------
1 | const { addFilter } = wp.hooks;
2 |
3 | function formatClassName(className) {
4 | const result = className.replace('wp-block-c9-blocks', 'c9');
5 | return result;
6 | }
7 |
8 | addFilter(
9 | 'c9-blocks.editor.className',
10 | 'c9-blocks/format-classname',
11 | formatClassName
12 | );
13 | addFilter(
14 | 'c9-blocks.blocks.className',
15 | 'c9-blocks/format-classname',
16 | formatClassName
17 | );
18 |
--------------------------------------------------------------------------------
/src/blocks/block-toggles/components/inspector.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { Component } = wp.element;
5 | const { InspectorControls } = wp.blockEditor;
6 |
7 | /**
8 | * Create an Inspector Controls wrapper Component
9 | */
10 | export default class Inspector extends Component {
11 | constructor() {
12 | super(...arguments);
13 | }
14 |
15 | render() {
16 | return ;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/blocks/block-grid-container/deprecated/index.js:
--------------------------------------------------------------------------------
1 | import SaveDeprecated from './save.deprecated';
2 | import attributes from '../attributes';
3 |
4 | export const BlockGridContainerDeprecated = (props) => (
5 |
6 | );
7 |
8 | const Deprecated = [
9 | {
10 | attributes: attributes,
11 | save: BlockGridContainerDeprecated,
12 | supports: {
13 | anchor: true,
14 | },
15 | },
16 | ];
17 |
18 | export default Deprecated;
19 |
--------------------------------------------------------------------------------
/src/extend/show-hide-inspector/editor.scss:
--------------------------------------------------------------------------------
1 | .c9-ext-badge {
2 | position: relative;
3 | left: 8px;
4 | padding: 1px 3px;
5 | font-size: 8px;
6 | font-weight: 700;
7 | color: #a9a9a9;
8 | text-transform: uppercase;
9 | background-color: #f3f3f3;
10 | border-radius: 2px;
11 | transition: 0.15s background-color, 0.15s color;
12 | }
13 |
14 | .components-toolbar>div>.components-toolbar__control.components-button.has-icon .dashicon {
15 | margin-right: 2px;
16 | }
17 |
--------------------------------------------------------------------------------
/src/update-category/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { updateCategory } = wp.blocks;
5 |
6 | /**
7 | * Icon
8 | */
9 | import Icon from '../../assets/c9-feather-logo-icon';
10 |
11 | if (updateCategory) {
12 | updateCategory('c9-blocks', { icon: Icon });
13 | }
14 |
15 | import './deregister-blocks';
16 | import './register-filters';
17 | import './register-styles';
18 | import './register-stores';
19 | import '../components/sidebar';
20 |
--------------------------------------------------------------------------------
/src/extend/width-settings/index.test.js:
--------------------------------------------------------------------------------
1 | import { c9AlignConfig } from './utils';
2 |
3 | describe('width settings extension should work correctly', () => {
4 | it('returns no alignment when align is unset', () => {
5 | expect(c9AlignConfig('container', '')).toStrictEqual('');
6 | });
7 |
8 | it('returns alignfull if all align is full and container is fluid', () => {
9 | expect(c9AlignConfig('container-fluid', 'full')).toStrictEqual('alignfull');
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | /*
2 | * For a detailed explanation regarding each configuration property, visit:
3 | * https://jestjs.io/docs/configuration
4 | */
5 |
6 | module.exports = {
7 | // Indicates whether the coverage information should be collected while executing the test
8 | collectCoverage: true,
9 | coverageDirectory: 'coverage',
10 | preset: '@wordpress/jest-preset-default',
11 | transform: {
12 | '\\.[jt]sx?$': 'babel-jest',
13 | },
14 | setupFiles: ['./jest.setup.js'],
15 | };
16 |
--------------------------------------------------------------------------------
/src/extend/width-settings/utils.js:
--------------------------------------------------------------------------------
1 | export const c9AlignConfig = (containerWidth, align) => {
2 | let containerAlign = '';
3 | if (align !== undefined && 0 != align.length) {
4 | if ('container' == containerWidth) {
5 | containerAlign = 'alignwide';
6 | } else if ('container-fluid' == containerWidth) {
7 | containerAlign = 'alignfull';
8 | } else if ('container-narrow' == containerWidth) {
9 | containerAlign = 'alignnarrow';
10 | }
11 | }
12 |
13 | return containerAlign;
14 | };
15 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # This file is for unifying the coding style for different editors and IDEs
2 | # editorconfig.org
3 |
4 | # WordPress Coding Standards
5 | # https://make.wordpress.org/core/handbook/coding-standards/
6 |
7 | root = true
8 |
9 | [*]
10 | charset = utf-8
11 | end_of_line = lf
12 | insert_final_newline = true
13 | trim_trailing_whitespace = true
14 | indent_style = tab
15 |
16 | [*.yml]
17 | indent_style = space
18 | indent_size = 2
19 |
20 | [*.md]
21 | trim_trailing_whitespace = false
22 |
--------------------------------------------------------------------------------
/assets/c9-trash.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/fa-icons/facebook-square-brands.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/fa-icons/chevron-circle-right-solid.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/templates-modal/page-templates/page-types.js:
--------------------------------------------------------------------------------
1 | export default {
2 | awareness:
3 | 'Page templates for potential fans learning about your product, service, event for the first time. Give them the most information they need right upfront.',
4 | consideration:
5 | 'Page templates for likely fans that are somewhat familiar with you, but need some information or convincing.',
6 | conversion:
7 | 'Page templates for fans familiar with your product doing research before purchase or informed users ready to convert to customers.',
8 | };
9 |
--------------------------------------------------------------------------------
/src/blocks/block-posts-grid/deprecated/save.deprecated.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import Container from './container.deprecated';
5 |
6 | /**
7 | * WordPress dependencies
8 | */
9 | const { Component } = wp.element;
10 | const { InnerBlocks } = wp.blockEditor;
11 |
12 | export default class Save extends Component {
13 | constructor() {
14 | super(...arguments);
15 | }
16 |
17 | render() {
18 | return (
19 |
20 |
21 |
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/stores/twitter/reducer.js:
--------------------------------------------------------------------------------
1 | function reducer(state = { feeds: {}, profiles: {} }, action) {
2 | switch (action.type) {
3 | case 'SET_TWITTER_FEED':
4 | if (!state.feeds[action.query] && action.feed) {
5 | state.feeds[action.query] = action.feed;
6 | }
7 | break;
8 | case 'SET_TWITTER_PROFILE':
9 | if (!state.profiles[action.query] && action.profile) {
10 | state.profiles[action.query] = action.profile;
11 | }
12 | break;
13 | // no default
14 | }
15 |
16 | return state;
17 | }
18 |
19 | export default reducer;
20 |
--------------------------------------------------------------------------------
/assets/icon-carousel-next.svg:
--------------------------------------------------------------------------------
1 | icon-carousel-next
--------------------------------------------------------------------------------
/assets/icon-carousel-prev.svg:
--------------------------------------------------------------------------------
1 | icon-carousel-prev
--------------------------------------------------------------------------------
/src/blocks/block-grid-container/deprecated/save.deprecated.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import Container from './container.deprecated';
5 |
6 | /**
7 | * WordPress dependencies
8 | */
9 | const { Component } = wp.element;
10 | const { InnerBlocks } = wp.blockEditor;
11 |
12 | export default class Save extends Component {
13 | constructor() {
14 | super(...arguments);
15 | }
16 |
17 | render() {
18 | return (
19 |
20 |
21 |
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/assets/fa-icons/linkedin-in-brands.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/stores/twitter/resolvers.js:
--------------------------------------------------------------------------------
1 | import * as actions from './actions';
2 | import prepareQuery from './prepare-query';
3 |
4 | export function* getTwitterFeed(data) {
5 | const query = prepareQuery('feed', data);
6 | const feed = yield actions.apiFetch({ path: query });
7 |
8 | return actions.setTwitterFeed(query, feed);
9 | }
10 |
11 | export function* getTwitterProfile(data) {
12 | const query = prepareQuery('profile', data);
13 | const profile = yield actions.apiFetch({ path: query });
14 |
15 | return actions.setTwitterProfile(query, profile);
16 | }
17 |
--------------------------------------------------------------------------------
/src/blocks/block-grid-container/save.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import ResizableContainer from './components/resizable-container';
5 |
6 | /**
7 | * WordPress dependencies
8 | */
9 | const { Component } = wp.element;
10 | const { InnerBlocks } = wp.blockEditor;
11 |
12 | export default class Save extends Component {
13 | constructor() {
14 | super(...arguments);
15 | }
16 |
17 | render() {
18 | return (
19 |
20 |
21 |
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/components/block-selector/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Styles
3 | */
4 | import styled from 'styled-components';
5 |
6 | const StyledSelector = styled.div`
7 | visibility: hidden;
8 | border: 2px dashed #aaa;
9 | font-size: 12px;
10 | text-align: center;
11 | cursor: pointer;
12 | text-transform: uppercase;
13 | font-weight: bold;
14 | color: #999;
15 | opacity: 0;
16 | transition: opacity 1s;
17 | `;
18 |
19 | const BlockSelector = ({ text }) => (
20 | {text}
21 | );
22 |
23 | export default BlockSelector;
24 |
--------------------------------------------------------------------------------
/assets/icon-c9-subheading-enable-toolbar-icon.js:
--------------------------------------------------------------------------------
1 | export default (
2 |
8 |
9 |
10 |
11 | Artboard 1 copy 10
12 |
16 |
20 |
21 | );
22 |
--------------------------------------------------------------------------------
/phpcs.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 | Generally-applicable sniffs for WordPress plugins
4 |
5 |
6 |
7 |
8 |
9 |
10 | .
11 |
12 |
13 |
14 |
15 | */node_modules/*
16 | */vendor/*
17 |
18 |
--------------------------------------------------------------------------------
/src/update-category/deregister-blocks.js:
--------------------------------------------------------------------------------
1 | const { unregisterBlockType } = wp.blocks;
2 |
3 | let loadBlocksEditor = null;
4 |
5 | if ('undefined' !== typeof window._wpLoadBlockEditor) {
6 | // Using Gutenberg plugin
7 | loadBlocksEditor = window._wpLoadBlockEditor;
8 | } else if ('undefined' !== typeof window._wpLoadGutenbergEditor) {
9 | // Using WP core Gutenberg
10 | loadBlocksEditor = window._wpLoadGutenbergEditor;
11 | }
12 |
13 | if (loadBlocksEditor) {
14 | loadBlocksEditor.then(() => {
15 | unregisterBlockType('core/verse');
16 | // unregisterBlockType("core/columns");
17 | });
18 | }
19 |
--------------------------------------------------------------------------------
/src/update-category/register-styles.js:
--------------------------------------------------------------------------------
1 | // const { registerBlockStyle } = wp.blocks;
2 |
3 | let loadBlocksEditor = null;
4 |
5 | if ('undefined' !== typeof window._wpLoadBlockEditor) {
6 | // Using Gutenberg plugin
7 | loadBlocksEditor = window._wpLoadBlockEditor;
8 | } else if ('undefined' !== typeof window._wpLoadGutenbergEditor) {
9 | // Using WP core Gutenberg
10 | loadBlocksEditor = window._wpLoadGutenbergEditor;
11 | }
12 |
13 | if (loadBlocksEditor) {
14 | loadBlocksEditor.then(() => {
15 | // registerBlockStyle("core/button", {
16 | // name: "custom-button-style",
17 | // label: "My Button Style"
18 | // });
19 | });
20 | }
21 |
--------------------------------------------------------------------------------
/assets/icon-c9-grid.svg:
--------------------------------------------------------------------------------
1 | Artboard 1 copy 19
--------------------------------------------------------------------------------
/assets/toggle-icon.svg:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/blocks/block-image-carousel/deprecated/index.js:
--------------------------------------------------------------------------------
1 | import SaveDeprecatedV1 from './1.0/save.deprecated';
2 | import SaveDeprecatedV2 from './2.0/save.deprecated';
3 | import attributes from '../attributes';
4 |
5 | const Deprecated = [
6 | {
7 | attributes: {
8 | ...attributes,
9 | slideMaxHeight: {
10 | type: 'number',
11 | default: -1,
12 | },
13 | slideEqualHeight: {
14 | type: 'boolean',
15 | default: false,
16 | },
17 | },
18 | save: (props) => {
19 | return ;
20 | },
21 | },
22 | {
23 | attributes,
24 | save: (props) => {
25 | return ;
26 | },
27 | },
28 | ];
29 |
30 | export default Deprecated;
31 |
--------------------------------------------------------------------------------
/assets/icon-c9-tabs-horizontal.svg:
--------------------------------------------------------------------------------
1 | Artboard 1 copy 20
--------------------------------------------------------------------------------
/src/blocks/block-horizontal-tabs/attributes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Block Attributes
3 | */
4 | const attributes = {
5 | tabActive: {
6 | type: 'string',
7 | default: 'tab-1',
8 | },
9 | buttonsAlign: {
10 | type: 'string',
11 | },
12 | tabsData: {
13 | type: 'array',
14 | default: [
15 | {
16 | slug: 'tab-1',
17 | title: 'Tab 1',
18 | },
19 | {
20 | slug: 'tab-2',
21 | title: 'Tab 2',
22 | },
23 | ],
24 | },
25 | instanceId: {
26 | type: 'number',
27 | },
28 | tabBackgroundColor: {
29 | type: 'string',
30 | },
31 | tabTextColor: {
32 | type: 'string',
33 | },
34 | tabContentBackgroundColor: {
35 | type: 'string',
36 | },
37 | blockBackgroundColor: {
38 | type: 'string',
39 | },
40 | };
41 |
42 | export default attributes;
43 |
--------------------------------------------------------------------------------
/assets/icon-c9-cta-bar.svg:
--------------------------------------------------------------------------------
1 | Artboard 1 copy 13
--------------------------------------------------------------------------------
/src/blocks/block-vertical-tabs/attributes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Block Attributes
3 | */
4 | const attributes = {
5 | tabActive: {
6 | type: 'string',
7 | default: 'tab-1',
8 | },
9 | tabsData: {
10 | type: 'array',
11 | default: [
12 | {
13 | slug: 'tab-1',
14 | title: 'Tab 1',
15 | },
16 | {
17 | slug: 'tab-2',
18 | title: 'Tab 2',
19 | },
20 | ],
21 | },
22 | instanceId: {
23 | type: 'number',
24 | },
25 | tabBackgroundColor: {
26 | type: 'string',
27 | },
28 | tabTextColor: {
29 | type: 'string',
30 | },
31 | tabContentBackgroundColor: {
32 | type: 'string',
33 | },
34 | blockBackgroundColor: {
35 | type: 'string',
36 | },
37 | verticalAlign: {
38 | type: 'string',
39 | },
40 | textAlign: {
41 | type: 'string',
42 | },
43 | };
44 |
45 | export default attributes;
46 |
--------------------------------------------------------------------------------
/src/blocks/block-posts-grid/save.js:
--------------------------------------------------------------------------------
1 | import Container from './components/container';
2 |
3 | const { Component } = wp.element;
4 | const { InnerBlocks } = wp.blockEditor;
5 |
6 | export default class Save extends Component {
7 | constructor() {
8 | super(...arguments);
9 | }
10 |
11 | render() {
12 | const { attributes } = this.props;
13 | const sanitizedAttributes = {
14 | ...attributes,
15 | containerVideoID: attributes.containerVideoID
16 | ? String(attributes.containerVideoID).replace(/[^a-zA-Z0-9-_]/g, '')
17 | : '',
18 | };
19 |
20 | return (
21 |
22 |
23 |
24 | );
25 | }
26 | }
--------------------------------------------------------------------------------
/assets/fa-icons/twitter-square-brands.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/icon-c9-tabs-vertical-tabs.svg:
--------------------------------------------------------------------------------
1 | Artboard 1 copy 21
--------------------------------------------------------------------------------
/config/babel-preset.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | [
4 | // 'env',
5 | '@babel/preset-env',
6 | {
7 | // Do not transform modules to CJS.
8 | modules: false,
9 | targets: {
10 | browsers: [
11 | 'last 2 Chrome versions',
12 | 'last 2 Edge versions',
13 | 'last 2 Firefox versions',
14 | 'last 2 Safari versions',
15 | 'last 2 iOS versions',
16 | 'last 1 Android version',
17 | 'last 1 ChromeAndroid version',
18 | ],
19 | },
20 | },
21 | ],
22 | ],
23 | plugins: [
24 | ['@babel/plugin-proposal-class-properties'],
25 | [
26 | '@babel/plugin-transform-react-jsx',
27 | {
28 | pragma: 'wp.element.createElement',
29 | },
30 | ],
31 | // Polyfills the runtime needed for async/await and generators.
32 | ['@babel/plugin-transform-runtime'],
33 | ],
34 | };
35 |
--------------------------------------------------------------------------------
/src/blocks/block-carousel/deprecated/index.js:
--------------------------------------------------------------------------------
1 | import SaveDeprecatedV1 from './1.0/save.deprecated';
2 | import SaveDeprecatedV2 from './2.0/save.deprecated';
3 | import SaveDeprecatedV3 from './3.0/save.deprecated';
4 | import attributes from '../attributes';
5 |
6 | const Deprecated = [
7 | {
8 | attributes: {
9 | ...attributes,
10 | slideMaxHeight: {
11 | type: 'number',
12 | default: -1,
13 | },
14 | slideEqualHeight: {
15 | type: 'boolean',
16 | default: false,
17 | },
18 | },
19 | save: (props) => {
20 | return ;
21 | },
22 | },
23 | {
24 | attributes,
25 | save: (props) => {
26 | return ;
27 | },
28 | },
29 | {
30 | attributes,
31 | save: (props) => {
32 | return ;
33 | },
34 | },
35 | ];
36 |
37 | export default Deprecated;
38 |
--------------------------------------------------------------------------------
/tests/test-class-check-dist-files-exist.php:
--------------------------------------------------------------------------------
1 | assertTrue(
32 | $check
33 | );
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/components/color-appender/editor.scss:
--------------------------------------------------------------------------------
1 | .c9-block-default-palette {
2 | .components-color-palette__item {
3 | display: flex;
4 | align-items: center;
5 | justify-content: center;
6 | }
7 |
8 | .components-color-palette__item-wrapper {
9 | transform: scale(1.1);
10 | }
11 |
12 | .components-color-palette__item-wrapper:hover {
13 | transform: scale(1.1);
14 | }
15 |
16 | .components-color-palette__item svg {
17 | color: rgba(100, 100, 100, 1);
18 | }
19 | }
20 |
21 | .c9-colors-remove-last {
22 | display: inline-block;
23 | height: 28px;
24 | width: 28px;
25 | margin-right: 14px;
26 | margin-bottom: 14px;
27 |
28 | .components-button {
29 | border-radius: 50%;
30 | height: 100%;
31 | width: 100%;
32 | padding: 0;
33 | display: flex;
34 | align-items: center;
35 | justify-content: center;
36 | }
37 | }
38 |
39 | .c9-colors-add-new {
40 | margin-bottom: 16px;
41 | }
42 |
--------------------------------------------------------------------------------
/src/blocks/block-toggles/save.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { Component } = wp.element;
5 | const { applyFilters } = wp.hooks;
6 | const { InnerBlocks } = wp.blockEditor;
7 |
8 | /**
9 | * External Dependencies.
10 | */
11 | import classnames from 'classnames';
12 |
13 | export default class Save extends Component {
14 | constructor() {
15 | super(...arguments);
16 | }
17 |
18 | render() {
19 | const {
20 | attributes: { reverseToggle },
21 | className = '',
22 | ...otherProps
23 | } = this.props;
24 |
25 | return (
26 |
35 |
36 |
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 | {
13 | return (
14 | {
16 | open();
17 | setTimeout(() => {
18 | insertBlocks(reusable);
19 | close();
20 | }, 0);
21 | onHover(null);
22 | }}
23 | onFocus={() => onHover(reusable)}
24 | onMouseEnter={() => onHover(reusable)}
25 | onMouseLeave={() => onHover(null)}
26 | onBlur={() => onHover(null)}
27 | >
28 |
29 | {label}
30 |
31 | );
32 | };
33 |
34 | export default withDispatch((dispatch) => {
35 | const { insertBlocks } = dispatch('core/block-editor');
36 |
37 | return {
38 | insertBlocks,
39 | };
40 | })(ReusableButton);
41 |
--------------------------------------------------------------------------------
/src/components/custom-palette/editor.scss:
--------------------------------------------------------------------------------
1 | .c9-custom-color-settings-container .c9-color-icon-indicate {
2 | position: relative;
3 | transform: scale(1);
4 | transition: transform 0.1s ease;
5 | border-radius: 50%;
6 | padding: 0;
7 | }
8 |
9 | .c9-block-default-palette .components-color-palette__item-wrapper {
10 | padding: 2px;
11 | }
12 |
13 | .c9-custom-color-settings-container .c9-color-icon-indicate:hover {
14 | transform: scale(1);
15 | height: auto;
16 | }
17 |
18 | .c9-custom-color-settings-container
19 | .c9-color-icon-indicate
20 | .component-color-indicator.c9-advanced-color-indicate {
21 | width: 28px;
22 | height: 28px;
23 | border-radius: 50%;
24 | margin: 0;
25 | }
26 |
27 | .components-popover.popover-color
28 | .components-popover__content
29 | > div
30 | > .components-base-control {
31 | padding: 16px 16px 12px;
32 | }
33 |
34 | .components-popover.popover-color
35 | > .components-popover__content
36 | > .components-base-control {
37 | padding: 0 10px;
38 | }
39 |
--------------------------------------------------------------------------------
/src/extend/space-settings-inspector/index.test.js:
--------------------------------------------------------------------------------
1 | import { c9SpacingConfig } from './utils';
2 |
3 | describe('space settings extension should work correctly', () => {
4 | const defaultConfig = {
5 | linked: true,
6 | icon: 'admin-links',
7 | top: '-1',
8 | bottom: '-1',
9 | left: '-1',
10 | right: '-1',
11 | };
12 | const sameValueConfig = {
13 | linked: true,
14 | icon: 'admin-links',
15 | top: '3',
16 | bottom: '3',
17 | left: '3',
18 | right: '3',
19 | };
20 |
21 | it('returns no padding when in unset state', () => {
22 | expect(c9SpacingConfig(defaultConfig, defaultConfig)).toStrictEqual([]);
23 | });
24 |
25 | it('returns one padding name if all values are the same', () => {
26 | expect(c9SpacingConfig(sameValueConfig, defaultConfig)).toStrictEqual([
27 | 'p-3',
28 | ]);
29 | });
30 |
31 | it('returns one margin name if all values are the same', () => {
32 | expect(c9SpacingConfig(defaultConfig, sameValueConfig)).toStrictEqual([
33 | 'my-3',
34 | ]);
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/src/blocks/block-carousel/attributes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Block Attributes
3 | */
4 | const attributes = {
5 | instanceId: {
6 | type: 'number',
7 | },
8 | slides: {
9 | type: 'number',
10 | default: 3,
11 | },
12 | showControls: {
13 | type: 'boolean',
14 | default: true,
15 | },
16 | showIndicators: {
17 | type: 'boolean',
18 | default: true,
19 | },
20 | autoSlide: {
21 | type: 'boolean',
22 | default: true,
23 | },
24 | wrapAround: {
25 | type: 'boolean',
26 | default: true,
27 | },
28 | slideTime: {
29 | type: 'number',
30 | default: 5000,
31 | },
32 | slideMaxHeight: {
33 | type: 'number',
34 | default: 250,
35 | },
36 | slideSizes: {
37 | type: 'array',
38 | default: [],
39 | },
40 | verticalAlign: {
41 | type: 'string',
42 | },
43 | align: {
44 | type: 'string',
45 | default: '',
46 | },
47 | containerWidth: {
48 | type: 'string',
49 | default: 'container',
50 | },
51 | transitionType: {
52 | type: 'string',
53 | default: 'slide',
54 | },
55 | };
56 |
57 | export default attributes;
58 |
--------------------------------------------------------------------------------
/src/blocks/block-sharing/components/sharing.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { Component } = wp.element;
5 | const { applyFilters } = wp.hooks;
6 |
7 | /**
8 | * External Dependencies.
9 | */
10 | import classnames from 'classnames';
11 |
12 | /**
13 | * Create a ShareLinks wrapper Component
14 | */
15 | export default class ShareLinks extends Component {
16 | constructor() {
17 | super(...arguments);
18 | }
19 |
20 | render() {
21 | const {
22 | attributes: {
23 | shareButtonStyle,
24 | shareButtonShape,
25 | shareButtonSize,
26 | shareButtonColor,
27 | shareAlignment,
28 | },
29 | className = '',
30 | } = this.props;
31 |
32 | return (
33 |
44 | {this.props.children}
45 |
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/assets/toggle-open.js:
--------------------------------------------------------------------------------
1 | export default (
2 |
10 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | );
44 |
--------------------------------------------------------------------------------
/src/components/pause-toolbar/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { __ } = wp.i18n;
5 | const { ToolbarGroup, ToolbarButton } = wp.components;
6 |
7 | /**
8 | * Control Settings
9 | */
10 | const DEFAULT_PAUSE_CONTROLS = [
11 | {
12 | icon: 'controls-pause',
13 | title: __('Pause', 'c9-blocks'),
14 | pause: true,
15 | },
16 | ];
17 |
18 | /**
19 | * Create a Width Toolbar Component
20 | */
21 | export function PauseToolbar({
22 | value,
23 | onChange,
24 | PauseControls = DEFAULT_PAUSE_CONTROLS,
25 | }) {
26 | function applyOrUnset(pause) {
27 | return () => onChange(value === pause ? false : pause);
28 | }
29 |
30 | return (
31 |
32 | {PauseControls.map((control) => {
33 | const { pause } = control;
34 | return (
35 |
41 | );
42 | })}
43 |
44 | );
45 | }
46 |
47 | export default PauseToolbar;
48 |
--------------------------------------------------------------------------------
/src/blocks/block-sharing/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import Edit from './edit';
5 |
6 | /**
7 | * Styles
8 | */
9 | import './styles/style.scss';
10 |
11 | import Icon from '../../../assets/icon-c9-social-share.svg';
12 |
13 | /**
14 | * WordPress dependencies
15 | */
16 | const { __ } = wp.i18n;
17 | const { registerBlockType } = wp.blocks;
18 |
19 | registerBlockType('c9-blocks/social-share', {
20 | title: __('C9 Social Share', 'c9-blocks'),
21 | icon: Icon,
22 | category: 'c9-blocks',
23 | description: __(
24 | 'Add buttons for social media share links to any page or post with custom color and shape settings.',
25 | 'c9-blocks'
26 | ),
27 | example: {
28 | viewportWidth: '280',
29 | attributes: {
30 | linkedin: true,
31 | email: true,
32 | shareAlignment: 'center',
33 | shareButtonColor: 'c9-share-color-social',
34 | },
35 | },
36 | keywords: [__('share', 'c9-blocks'), __('social', 'c9-blocks')],
37 |
38 | // Render the block components
39 | edit: Edit,
40 |
41 | // Render via PHP
42 | save() {
43 | return null;
44 | },
45 | });
46 |
--------------------------------------------------------------------------------
/assets/c9-feather-logo-gray.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | c9-feather-logo-gray
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/config/externals.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Converts dash-separated strings to camelCase.
3 | *
4 | * @param {string} string Input dash-delimited string.
5 | * @return {string} Camel-cased string.
6 | */
7 | const camelCaseDash = (string) =>
8 | string.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
9 |
10 | /**
11 | * Define externals to load components through the wp global.
12 | */
13 | const externals = [
14 | 'components',
15 | 'edit-post',
16 | 'element',
17 | 'plugins',
18 | 'editor',
19 | 'blocks',
20 | 'hooks',
21 | 'utils',
22 | 'date',
23 | 'data',
24 | 'i18n',
25 | 'block-editor',
26 | 'compose',
27 | 'keycodes',
28 | 'rich-text',
29 | 'shortcode',
30 | 'viewport',
31 | 'server-side-render',
32 | ].reduce(
33 | (externals, name) => ({
34 | ...externals,
35 | [`@wordpress/${name}`]: `wp.${camelCaseDash(name)}`,
36 | }),
37 | {
38 | wp: 'wp',
39 | react: 'React',
40 | 'react-dom': 'ReactDOM',
41 | lodash: 'lodash',
42 | jquery: 'jQuery',
43 | ga: 'ga',
44 | gtag: 'gtag',
45 | // Add other global libraries or localized data as needed.
46 | }
47 | );
48 |
49 | module.exports = externals;
--------------------------------------------------------------------------------
/assets/fa-icons/instagram-brands.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/icon-c9-toggles.svg:
--------------------------------------------------------------------------------
1 | Artboard 1 copy 18
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "node": true,
5 | "es6": true,
6 | "jest": true
7 | },
8 | "extends": [
9 | "eslint:recommended",
10 | "plugin:react/recommended",
11 | "plugin:prettier/recommended",
12 | "plugin:jsx-a11y/recommended"
13 | ],
14 | "globals": {
15 | "Atomics": "readonly",
16 | "SharedArrayBuffer": "readonly",
17 | "wp": "readonly",
18 | "c9_blocks_params": "readonly",
19 | "c9_blocks_assets": "readonly"
20 | },
21 | "parser": "@babel/eslint-parser",
22 | "parserOptions": {
23 | "ecmaFeatures": {
24 | "jsx": true
25 | },
26 | "ecmaVersion": 2018,
27 | "sourceType": "module",
28 | "requireConfigFile": false,
29 | "babelOptions": {
30 | "presets": ["@babel/preset-react"]
31 | }
32 | },
33 | "settings": {
34 | "react": {
35 | "version": "detect"
36 | }
37 | },
38 | "plugins": ["react", "jsx-a11y"],
39 | "rules": {
40 | "react/react-in-jsx-scope": "off",
41 | "react/display-name": "off",
42 | "react/prop-types": "off",
43 | "prettier/prettier": ["error", { "singleQuote": true }]
44 | },
45 | "ignorePatterns": ["node_modules/**/*.js", "dist/*.js", "**/templates/*.js"]
46 | }
47 |
--------------------------------------------------------------------------------
/config/paths.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Paths
3 | *
4 | * Project-related paths for Webpack and other tooling.
5 | */
6 |
7 | const path = require('path');
8 | const fs = require('fs');
9 |
10 | // Resolve the real project directory (resolving symlinks if any).
11 | const pluginDir = fs.realpathSync(process.cwd());
12 | const resolvePlugin = (relativePath) => path.resolve(pluginDir, relativePath);
13 |
14 | // Export paths.
15 | module.exports = {
16 | // Environment variables.
17 | dotenv: resolvePlugin('.env'),
18 |
19 | // Plugin source folder.
20 | pluginSrc: resolvePlugin('src'),
21 |
22 | // Entry points for Webpack.
23 | pluginBlocksJs: resolvePlugin('src/blocks.js'),
24 | pluginBlocksRegisterJs: resolvePlugin('src/register.js'),
25 | pluginBlocksFrontendJs: resolvePlugin('src/frontend.js'),
26 | pluginBlocksBootstrapJs: resolvePlugin('src/vendor.js'),
27 | pluginBlocksEditorJs: resolvePlugin('src/editor.js'),
28 |
29 | // Output folder for the built assets.
30 | pluginDist: resolvePlugin('dist'),
31 |
32 | // Lockfile for dependency management.
33 | yarnLockFile: resolvePlugin('yarn.lock'),
34 |
35 | // Root project path.
36 | appPath: resolvePlugin('.'),
37 | };
--------------------------------------------------------------------------------
/src/blocks/block-column-container/save.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import ResizableContainer from './components/resizable-container';
5 |
6 | /**
7 | * WordPress dependencies
8 | */
9 | const { Component } = wp.element;
10 | const { InnerBlocks } = wp.blockEditor;
11 |
12 | /**
13 | * External dependencies
14 | */
15 | import classnames from 'classnames';
16 |
17 | export default class Save extends Component {
18 | constructor() {
19 | super(...arguments);
20 | }
21 |
22 | render() {
23 | const {
24 | attributes: {
25 | columnsGap,
26 | responsiveToggle,
27 | flipColumnsMobile,
28 | columnMaxWidth,
29 | },
30 | } = this.props;
31 |
32 | return (
33 |
34 |
45 |
46 |
47 |
48 | );
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/blocks/block-heading/attributes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Block Attributes
3 | */
4 | const attributes = {
5 | isCollapsed: {
6 | type: 'boolean',
7 | default: false,
8 | },
9 | heading: {
10 | type: 'string',
11 | default: '',
12 | },
13 | subheading: {
14 | type: 'string',
15 | default: '',
16 | },
17 | addSubheading: {
18 | type: 'boolean',
19 | default: false,
20 | },
21 | wrapper: {
22 | type: 'array',
23 | source: 'query',
24 | selector: '.section-heading',
25 | query: {
26 | class: {
27 | type: 'string',
28 | source: 'attribute',
29 | attribute: 'class',
30 | },
31 | },
32 | },
33 | tagLevel: {
34 | type: 'number',
35 | default: 1,
36 | },
37 | displayLevel: {
38 | type: 'string',
39 | default: '',
40 | },
41 | type: {
42 | type: 'string',
43 | default: 'c9-h h',
44 | },
45 | backgroundColor: {
46 | type: 'string',
47 | },
48 | textColor: {
49 | type: 'string',
50 | },
51 | subTextColor: {
52 | type: 'string',
53 | },
54 | textAlign: {
55 | type: 'string',
56 | default: 'left',
57 | },
58 | weight: {
59 | type: 'string',
60 | },
61 | overrideStyle: {
62 | type: 'boolean',
63 | default: false,
64 | },
65 | };
66 |
67 | export default attributes;
68 |
--------------------------------------------------------------------------------
/src/editor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Import global styles.
3 | */
4 | import './block-globals.editor.scss';
5 |
6 | /**
7 | * Import blocks editor styles.
8 | */
9 | import './blocks/block-carousel/styles/editor.scss';
10 | import './blocks/block-column-container/styles/editor.scss';
11 | import './blocks/block-cta/styles/editor.scss';
12 | import './blocks/block-grid-container/styles/editor.scss';
13 | import './blocks/block-heading/styles/editor.scss';
14 | import './blocks/block-horizontal-tabs/styles/editor.scss';
15 | import './blocks/block-image-carousel/styles/editor.scss';
16 | import './blocks/block-post-grid/styles/editor.scss';
17 | import './blocks/block-posts-grid/styles/editor.scss';
18 | import './blocks/block-sharing/styles/editor.scss';
19 | import './blocks/block-toggles/styles/editor.scss';
20 | import './blocks/block-vertical-tabs/styles/editor.scss';
21 |
22 | /**
23 | * Import side menu / inspector styles.
24 | */
25 | import './components/block-selector/editor.scss';
26 | import './components/color-appender/editor.scss';
27 | import './components/custom-palette/editor.scss';
28 | import './components/large-modal/editor.scss';
29 | import './components/sidebar/editor.scss';
30 | import './components/templates-modal/editor.scss';
31 |
--------------------------------------------------------------------------------
/src/components/show-hide-toolbar/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { __ } = wp.i18n;
5 | const { ToolbarGroup, ToolbarButton } = wp.components;
6 |
7 | /**
8 | * Control Settings
9 | */
10 | const DEFAULT_DISPLAY_CONTROLS = [
11 | {
12 | icon: 'smartphone',
13 | title: __('Mobile', 'c9-blocks'),
14 | },
15 | {
16 | icon: 'tablet',
17 | title: __('Tablet', 'c9-blocks'),
18 | },
19 | {
20 | icon: 'desktop',
21 | title: __('Desktop', 'c9-blocks'),
22 | },
23 | ];
24 |
25 | /**
26 | * Create a Show/Hide Toolbar Component
27 | */
28 | export function ShowHideToolbar({
29 | value,
30 | onChange,
31 | displayControls = DEFAULT_DISPLAY_CONTROLS,
32 | }) {
33 | function applyOrUnset(display, i) {
34 | return () => onChange(value[i] === display ? [false, i] : [display, i]);
35 | }
36 |
37 | return (
38 |
39 | {displayControls.map((control, i) => {
40 | return (
41 |
47 | );
48 | })}
49 |
50 | );
51 | }
52 |
53 | export default ShowHideToolbar;
54 |
--------------------------------------------------------------------------------
/src/components/templates-modal/section-button.js:
--------------------------------------------------------------------------------
1 | const { Icon } = wp.components;
2 | const { withDispatch } = wp.data;
3 | const { decodeEntities } = wp.htmlEntities;
4 |
5 | const SectionButton = ({
6 | label,
7 | icon,
8 | description,
9 | preview,
10 | section,
11 | insertBlocks,
12 | open,
13 | close,
14 | onHover,
15 | }) => {
16 | return (
17 | {
19 | open();
20 | setTimeout(() => {
21 | insertBlocks(section);
22 | close();
23 | }, 0);
24 | onHover(null);
25 | }}
26 | onFocus={() => onHover(section)}
27 | onMouseEnter={() => onHover(section)}
28 | onMouseLeave={() => onHover(null)}
29 | onBlur={() => onHover(null)}
30 | >
31 | {preview ? (
32 |
33 |
34 |
35 | ) : (
36 |
37 | )}
38 | {decodeEntities(label)}
39 | {decodeEntities(description)}
40 |
41 | );
42 | };
43 |
44 | export default withDispatch((dispatch) => {
45 | const { insertBlocks } = dispatch('core/block-editor');
46 |
47 | return {
48 | insertBlocks,
49 | };
50 | })(SectionButton);
51 |
--------------------------------------------------------------------------------
/src/blocks/block-heading/components/heading-toolbar.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { __, sprintf } = wp.i18n;
5 | const { Component } = wp.element;
6 | const { ToolbarGroup, ToolbarButton } = wp.components;
7 |
8 | /**
9 | * External dependencies
10 | */
11 | import range from 'lodash/range';
12 |
13 | /**
14 | * Create a HeadingToolbar wrapper Component
15 | */
16 | class HeadingToolbar extends Component {
17 | createLevelControl(targetLevel, selectedLevel, onChange) {
18 | return (
19 | onChange(targetLevel)}
26 | subscript={String(targetLevel)}
27 | />
28 | );
29 | }
30 |
31 | render() {
32 | const { minLevel, maxLevel, selectedLevel, onChange } = this.props;
33 |
34 | return (
35 |
36 | {range(minLevel, maxLevel).map((index) =>
37 | this.createLevelControl(index, selectedLevel, onChange)
38 | )}
39 |
40 | );
41 | }
42 | }
43 |
44 | export default HeadingToolbar;
45 |
--------------------------------------------------------------------------------
/src/components/width-toolbar/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { __ } = wp.i18n;
5 | const { ToolbarGroup, ToolbarButton } = wp.components;
6 |
7 | /**
8 | * Control Settings
9 | */
10 | const DEFAULT_WIDTH_CONTROLS = [
11 | {
12 | icon: 'align-center',
13 | title: __('Narrow Width', 'c9-blocks'),
14 | width: 'narrow',
15 | },
16 | {
17 | icon: 'align-wide',
18 | title: __('Wide Width', 'c9-blocks'),
19 | width: 'wide',
20 | },
21 | {
22 | icon: 'align-full-width',
23 | title: __('Full Width', 'c9-blocks'),
24 | width: 'full',
25 | },
26 | ];
27 |
28 | /**
29 | * Create a Width Toolbar Component
30 | */
31 | export function WidthToolbar({
32 | value,
33 | onChange,
34 | widthControls = DEFAULT_WIDTH_CONTROLS,
35 | }) {
36 | function applyOrUnset(width) {
37 | return () => onChange(value === width ? undefined : width);
38 | }
39 |
40 | return (
41 |
42 | {widthControls.map((control) => {
43 | const { width } = control;
44 | return (
45 |
51 | );
52 | })}
53 |
54 | );
55 | }
56 |
57 | export default WidthToolbar;
58 |
--------------------------------------------------------------------------------
/src/blocks.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Gutenberg Blocks
3 | *
4 | * All blocks related JavaScript files should be imported here.
5 | * You can create a new block folder in this dir and include code
6 | * for that block here as well.
7 | *
8 | * All blocks should be included here since this is the file that
9 | * Webpack is compiling as the input file.
10 | */
11 |
12 | /**
13 | * Block extensions.
14 | */
15 | import './extend';
16 |
17 | // set locale
18 | import './blocks/i18n.js';
19 |
20 | // main blocks
21 | import './blocks/block-sharing';
22 | import './blocks/block-cta';
23 | import './blocks/block-heading';
24 | import './blocks/block-image-carousel';
25 | import './blocks/block-grid-container';
26 | import './blocks/block-horizontal-tabs';
27 | import './blocks/block-vertical-tabs';
28 | import './blocks/block-toggles';
29 | import './blocks/block-posts-grid';
30 | import './blocks/block-carousel';
31 |
32 | // child blocks
33 | import './blocks/block-column-container';
34 | import './blocks/block-column-container/components/column.js';
35 | import './blocks/block-horizontal-tabs/components/horizontal-tab';
36 | import './blocks/block-vertical-tabs/components/vertical-tab';
37 | import './blocks/block-toggles/components/toggle.js';
38 | import './blocks/block-carousel/components/slide.js';
39 | import './blocks/block-post-grid';
40 |
--------------------------------------------------------------------------------
/src/blocks/block-heading/components/custom-heading.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { Component } = wp.element;
5 | const { applyFilters } = wp.hooks;
6 | const { useBlockProps } = wp.blockEditor;
7 | const { getBlockType } = wp.blocks;
8 |
9 | /**
10 | * External Dependencies.
11 | */
12 | import classnames from 'classnames';
13 | /**
14 | * Create a C9CustomHeading wrapper Component
15 | */
16 | export default class C9CustomHeading extends Component {
17 | constructor() {
18 | super(...arguments);
19 | }
20 |
21 | render() {
22 | const {
23 | attributes: { textAlign, anchor },
24 | className = '',
25 | } = this.props;
26 |
27 | const extraProps = useBlockProps
28 | ? useBlockProps.save()
29 | : applyFilters(
30 | 'blocks.getSaveContent.extraProps',
31 | this.props,
32 | getBlockType('c9-blocks/heading'),
33 | this.props.attributes
34 | );
35 |
36 | return (
37 |
47 | {this.props.children}
48 |
49 | );
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/assets/fa-icons/tiktok.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | tiktok
5 |
6 |
--------------------------------------------------------------------------------
/src/blocks/block-heading/components/subheading-toolbar.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { __ } = wp.i18n;
5 | const { ToolbarGroup, ToolbarButton } = wp.components;
6 |
7 | import Icon from '../../../../assets/icon-c9-subheading-enable-toolbar-icon';
8 |
9 | /**
10 | * Control Settings
11 | */
12 | const DEFAULT_ENABLE_CONTROLS = [
13 | {
14 | icon: Icon,
15 | title: __('Enable Subheading', 'c9-blocks'),
16 | enabled: true,
17 | },
18 | ];
19 |
20 | /**
21 | * Create an Subheading Toolbar wrapper Component
22 | */
23 | export function SubheadingToolbar({
24 | value,
25 | onChange,
26 | enableControls = DEFAULT_ENABLE_CONTROLS,
27 | }) {
28 | function applyOrUnset(enabled) {
29 | return () => onChange(value === enabled ? false : enabled);
30 | }
31 |
32 | return (
33 |
34 | {enableControls.map((control, index) => {
35 | //destructure to remove 'enabled' from the rest of the control props
36 | const { enabled, ...buttonProps } = control;
37 | return (
38 |
44 | );
45 | })}
46 |
47 | );
48 | }
49 |
50 | export default SubheadingToolbar;
51 |
--------------------------------------------------------------------------------
/assets/icon-c9-anything-carousel.svg:
--------------------------------------------------------------------------------
1 | Artboard 1 copy 14
--------------------------------------------------------------------------------
/src/components/preview-panel/index.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | const StyledDiv = styled.div`
4 | top: 0;
5 | left: calc(100% + 16px);
6 | width: 450px;
7 | border: 1px solid #ddd;
8 | border-radius: 0px;
9 | position: absolute;
10 | padding: 0;
11 | background-color: #fff;
12 | `;
13 |
14 | /**
15 | * WordPress dependencies
16 | */
17 | const { BlockPreview } = wp.blockEditor;
18 |
19 | function PreviewPanel({ item }) {
20 | return (
21 |
22 |
23 |
24 | .c9-grid .block-editor-block-list__block:not(.wp-block-separator):not(.rich-text) {margin-top: 0px; margin-bottom: 0px;}',
32 | },
33 | ]}
34 | blocks={item}
35 | />
36 |
37 |
38 |
39 | );
40 | }
41 |
42 | export default PreviewPanel;
43 |
--------------------------------------------------------------------------------
/src/blocks/block-horizontal-tabs/styles/style.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * #.# Styles
3 | *
4 | * CSS for both Frontend+Backend.
5 | */
6 |
7 | .entry-content .c9-horizontal-tabs>.nav.nav-tabs,
8 | .editor-styles-wrapper .c9-horizontal-tabs>.nav.nav-tabs {
9 | font-size: inherit;
10 | list-style: none;
11 | padding: 0px;
12 | margin: 30px 0 0 0;
13 | }
14 |
15 | .c9-horizontal-tabs .nav-tabs .nav-link {
16 | display: block;
17 | border: none;
18 | border-radius: 0px;
19 | color: #979797;
20 | text-transform: uppercase;
21 | font-size: 16px;
22 | padding: 13px 35px;
23 | font-weight: 700;
24 | letter-spacing: .09em;
25 | text-decoration: none;
26 | }
27 |
28 | .c9-horizontal-tabs .nav-tabs .nav-link.active {
29 | color: #2b2b2b;
30 | background-color: #fff;
31 | text-decoration: none;
32 | }
33 |
34 | .c9-horizontal-tabs .nav-tabs .nav-link:focus,
35 | .c9-horizontal-tabs .nav-tabs .nav-link:focus-within,
36 | .c9-horizontal-tabs .nav-tabs .nav-link:active {
37 | outline-style: solid;
38 | outline-color: #fff;
39 | }
40 |
41 | .c9-horizontal-tabs .tab-content {
42 | padding: 25px;
43 | }
44 |
45 | .c9-horizontal-tabs p:last-child:last-of-type {
46 | margin-bottom: 0px;
47 | }
48 |
49 | @media only screen and (max-width: 812px) {
50 | .c9-horizontal-tabs>.nav.nav-tabs {
51 | flex-wrap: wrap;
52 | }
53 |
54 | .c9-horizontal-tabs>.nav.nav-tabs .nav-link {
55 | font-size: 12px;
56 | padding: 10px 15px;
57 | }
58 | }
--------------------------------------------------------------------------------
/src/components/vertical-alignment-toolbar/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import icons from '../../../assets/c9-vertical-alignment-icons';
5 |
6 | /**
7 | * WordPress dependencies
8 | */
9 | const { __ } = wp.i18n;
10 | const { ToolbarGroup, ToolbarButton } = wp.components;
11 |
12 | /**
13 | * Control Settings
14 | */
15 | const DEFAULT_ALIGN_CONTROLS = [
16 | {
17 | icon: icons.top,
18 | title: __('Vertical Align Top', 'c9-blocks'),
19 | align: 'top',
20 | },
21 | {
22 | icon: icons.center,
23 | title: __('Vertical Align Middle', 'c9-blocks'),
24 | align: 'center',
25 | },
26 | {
27 | icon: icons.bottom,
28 | title: __('Vertical Align Bottom', 'c9-blocks'),
29 | align: 'bottom',
30 | },
31 | ];
32 |
33 | /**
34 | * Create a Vertical Alignment Toolbar Component
35 | */
36 | export function VerticalAlignmentToolbar({
37 | value,
38 | onChange,
39 | alignControls = DEFAULT_ALIGN_CONTROLS,
40 | }) {
41 | function applyOrUnset(align) {
42 | return () => onChange(value === align ? undefined : align);
43 | }
44 |
45 | return (
46 |
47 | {alignControls.map((control) => {
48 | const { align } = control;
49 | return (
50 |
56 | );
57 | })}
58 |
59 | );
60 | }
61 |
62 | export default VerticalAlignmentToolbar;
63 |
--------------------------------------------------------------------------------
/src/blocks/block-vertical-tabs/components/vertical-align-toolbar.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import icons from '../../../../assets/c9-vertical-alignment-icons';
5 |
6 | /**
7 | * WordPress dependencies
8 | */
9 | const { __ } = wp.i18n;
10 | const { ToolbarGroup, ToolbarButton } = wp.components;
11 |
12 | /**
13 | * Control Settings
14 | */
15 | const DEFAULT_ALIGN_CONTROLS = [
16 | {
17 | icon: icons.top,
18 | title: __('Vertical Align Top', 'c9-blocks'),
19 | align: 'start',
20 | },
21 | {
22 | icon: icons.center,
23 | title: __('Vertical Align Middle', 'c9-blocks'),
24 | align: 'center',
25 | },
26 | {
27 | icon: icons.bottom,
28 | title: __('Vertical Align Bottom', 'c9-blocks'),
29 | align: 'end',
30 | },
31 | ];
32 |
33 | /**
34 | * Create a Vertical Alignment Toolbar Component
35 | */
36 | export function VerticalAlignmentToolbar({
37 | value,
38 | onChange,
39 | alignControls = DEFAULT_ALIGN_CONTROLS,
40 | }) {
41 | function applyOrUnset(align) {
42 | return () => onChange(value === align ? undefined : align);
43 | }
44 |
45 | return (
46 |
47 | {alignControls.map((control) => {
48 | const { align } = control;
49 | return (
50 |
56 | );
57 | })}
58 |
59 | );
60 | }
61 |
62 | export default VerticalAlignmentToolbar;
63 |
--------------------------------------------------------------------------------
/src/components/templates-modal/page-templates/page-templates.js:
--------------------------------------------------------------------------------
1 | import lpAboutCorporate from './templates/about-corporate';
2 | import lpAboutCreative from './templates/about-creative';
3 | import lpContactShort from './templates/contact-short';
4 | import lpContact from './templates/contact';
5 | import lpEvent from './templates/event';
6 | import lpLaunchRelease from './templates/launch-release';
7 | import lpMedia from './templates/media';
8 | import lpPortfolio from './templates/portfolio';
9 | import lpPriceMenu from './templates/price-menu';
10 | import lpResources from './templates/resources';
11 | import lpService from './templates/service';
12 | import lpPricing from './templates/pricing';
13 | import lpStyle from './templates/style-guide';
14 | import leadGen1 from './templates/lead-generation-1';
15 | import leadGen2 from './templates/lead-generation-2';
16 | import leadGen3 from './templates/lead-generation-3';
17 | import lpVideos from './templates/videos';
18 | import lpStory1200 from './templates/story-article-1200';
19 | import lpStory1600 from './templates/story-article-1600';
20 | import lpStory2000 from './templates/story-article-2000';
21 |
22 | const pageTemplates = {
23 | lpAboutCorporate,
24 | lpAboutCreative,
25 | lpContactShort,
26 | lpContact,
27 | lpEvent,
28 | lpLaunchRelease,
29 | lpMedia,
30 | lpVideos,
31 | lpPortfolio,
32 | lpPriceMenu,
33 | lpResources,
34 | lpService,
35 | lpPricing,
36 | lpStyle,
37 | leadGen1,
38 | leadGen2,
39 | leadGen3,
40 | lpStory1200,
41 | lpStory1600,
42 | lpStory2000,
43 | };
44 |
45 | export default pageTemplates;
46 |
--------------------------------------------------------------------------------
/src/components/youtube-api-toggle/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable camelcase */
2 |
3 | /**
4 | * WordPress dependencies
5 | */
6 | const { Component } = wp.element;
7 | const { ToggleControl } = wp.components;
8 | const { withDispatch } = wp.data;
9 |
10 | class YoutubeAPIToggle extends Component {
11 | constructor() {
12 | super(...arguments);
13 | this.saveConfig = this.saveConfig.bind(this);
14 | this.state = {
15 | isSaving: false,
16 | youtubeAPIDisabled: c9_blocks_params.disable_youtube_api === 'true',
17 | };
18 | }
19 |
20 | /**
21 | * Stores current color configuration to plugin settings.
22 | */
23 | saveConfig(value) {
24 | if (false === this.state.isSaving) {
25 | this.setState({ isSaving: true });
26 | const settingModel = new wp.api.models.Settings({
27 | c9_blocks_disable_youtube_api: JSON.stringify(value),
28 | });
29 | // eslint-disable-next-line no-unused-vars
30 | settingModel.save().then((response) => {
31 | this.setState({ isSaving: false, youtubeAPIDisabled: value });
32 | c9_blocks_params.c9_blocks_disable_youtube_api = JSON.stringify(value);
33 | });
34 | }
35 | }
36 |
37 | render() {
38 | const { youtubeAPIDisabled } = this.state;
39 |
40 | return (
41 | {
44 | this.saveConfig(value);
45 | }}
46 | />
47 | );
48 | }
49 | }
50 |
51 | export default withDispatch((dispatch) => {
52 | const { updateSettings } = dispatch('core/block-editor');
53 | return {
54 | updateSettings,
55 | };
56 | })(YoutubeAPIToggle);
57 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | dist: trusty
3 |
4 | language: php
5 |
6 | notifications:
7 | email:
8 | on_success: never
9 | on_failure: change
10 |
11 | branches:
12 | only:
13 | - master
14 | - develop
15 |
16 | cache:
17 | directories:
18 | - vendor
19 | - $HOME/.composer/cache
20 |
21 | matrix:
22 | include:
23 | - php: 7.1
24 | env: WP_VERSION=latest
25 | - php: 7.0
26 | env: WP_VERSION=latest
27 | - php: 5.6
28 | env: WP_VERSION=5.0
29 | - php: 5.6
30 | env: WP_VERSION=latest
31 | - php: 5.6
32 | env: WP_VERSION=trunk
33 | - php: 5.6
34 | env: WP_TRAVISCI=phpcs
35 |
36 | before_script:
37 | - export PATH="$HOME/.composer/vendor/bin:$PATH"
38 | - |
39 | if [ -f ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini ]; then
40 | phpenv config-rm xdebug.ini
41 | else
42 | echo "xdebug.ini does not exist"
43 | fi
44 | - |
45 | if [[ ! -z "$WP_VERSION" ]] ; then
46 | bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION
47 | composer global require "phpunit/phpunit=4.8.*|5.7.*"
48 | fi
49 | - |
50 | if [[ "$WP_TRAVISCI" == "phpcs" ]] ; then
51 | composer global require wp-coding-standards/wpcs
52 | phpcs --config-set installed_paths $HOME/.composer/vendor/wp-coding-standards/wpcs
53 | fi
54 | script:
55 | - |
56 | if [[ ! -z "$WP_VERSION" ]] ; then
57 | phpunit
58 | WP_MULTISITE=1 phpunit
59 | fi
60 | - |
61 | if [[ "$WP_TRAVISCI" == "phpcs" ]] ; then
62 | phpcs
63 | fi
64 |
--------------------------------------------------------------------------------
/src/components/large-modal/editor.scss:
--------------------------------------------------------------------------------
1 | .c9-templates-modal {
2 | .components-modal__header {
3 | border-bottom: none;
4 | }
5 |
6 | .c9-component-modal-tab-panel .components-tab-panel__tabs {
7 | display: flex;
8 | align-items: center;
9 | margin-top: -24px;
10 | margin-bottom: 9px;
11 | }
12 |
13 | @media (min-width: 600px) {
14 | min-width: 50vw;
15 | max-width: calc(100vw - 496px); // fix for Ace editor tooltips
16 | transform: translateX(-50%);
17 | left: calc(50% - 150px);
18 |
19 | // position
20 | top: 65px;
21 | }
22 |
23 | @media (min-width: 768px) {
24 | left: calc(50% - 180px);
25 | }
26 |
27 | @media (min-width: 992px) {
28 | left: 40px;
29 | position: absolute;
30 | }
31 |
32 | @media (max-width: 1199px) {
33 | min-width: 50vw;
34 | }
35 |
36 | @media (min-width: 1200px) {
37 | min-width: calc(100vw - 520px);
38 | max-width: calc(100vw - 520px);
39 | }
40 |
41 | // header
42 | .components-modal__header {
43 | .components-modal__icon-container svg {
44 | display: block;
45 | margin-right: 10px;
46 | }
47 |
48 | .components-modal__header-heading {
49 | font-weight: 600;
50 | text-transform: uppercase;
51 | font-size: 16px;
52 | color: #576d7b;
53 | letter-spacing: 0.5px;
54 | }
55 | }
56 | }
57 |
58 | /* block preview updates */
59 | .c9-modal-preview
60 | .block-editor-block-preview__container
61 | .block-editor-block-preview__content {
62 | width: 100vw;
63 | min-width: 100vw;
64 | }
65 | .block-editor-block-patterns-list
66 | .block-editor-block-preview__container
67 | > .block-editor-block-preview__content
68 | iframe {
69 | max-width: none;
70 | }
71 |
--------------------------------------------------------------------------------
/plugin.php:
--------------------------------------------------------------------------------
1 | div {
7 | box-sizing: border-box;
8 | }
9 |
10 | .c9-vertical-tabs {
11 | > .nav.nav-tabs {
12 | list-style: none;
13 | }
14 |
15 | .c9-tabs-content-wrapper {
16 | display: grid;
17 | }
18 | }
19 |
20 | .c9-vertical-tabs .nav-pills .nav-link {
21 | display: block;
22 | border: none;
23 | border-radius: 0px;
24 | color: #979797;
25 | text-transform: uppercase;
26 | font-size: 16px;
27 | padding: 13px 20px;
28 | font-weight: 700;
29 | letter-spacing: 0.005em;
30 | text-decoration: none;
31 | }
32 |
33 | .c9-vertical-tabs .tab-content {
34 | padding: 0px 25px;
35 | }
36 |
37 | .c9 .c9-vertical-tabs p:only-child {
38 | margin-bottom: 0px;
39 | }
40 |
41 | @media only screen and (max-width: 1024px) {
42 | .c9-layout-columns-6
43 | .c9-is-responsive-column
44 | .c9-vertical-tabs
45 | .nav-pills
46 | .nav-link,
47 | .c9-layout-columns-5
48 | .c9-is-responsive-column
49 | .c9-vertical-tabs
50 | .nav-pills
51 | .nav-link,
52 | .c9-layout-columns-4
53 | .c9-is-responsive-column
54 | .c9-vertical-tabs
55 | .nav-pills
56 | .nav-link,
57 | .c9-layout-columns-3
58 | .c9-is-responsive-column
59 | .c9-vertical-tabs
60 | .nav-pills
61 | .nav-link {
62 | font-size: 1em;
63 | }
64 | }
65 |
66 | .c9-vertical-tabs .nav-pills .nav-link.active,
67 | .c9-vertical-tabs .nav-pills .show > .nav-link,
68 | .c9-vertical-tabs .nav-pills .nav-link.active {
69 | color: #2b2b2b;
70 | background-color: #ccc;
71 | text-decoration: none;
72 | }
73 |
74 | @media only screen and (max-width: 568px) {
75 | .c9-vertical-tabs .nav {
76 | margin-bottom: 20px;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/blocks/block-image-carousel/attributes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Block Attributes
3 | */
4 | const attributes = {
5 | instanceId: {
6 | type: 'number',
7 | },
8 | slides: {
9 | type: 'number',
10 | default: 3,
11 | },
12 | showControls: {
13 | type: 'boolean',
14 | default: true,
15 | },
16 | showIndicators: {
17 | type: 'boolean',
18 | default: true,
19 | },
20 | autoSlide: {
21 | type: 'boolean',
22 | default: true,
23 | },
24 | wrapAround: {
25 | type: 'boolean',
26 | default: true,
27 | },
28 | url: {
29 | type: 'array',
30 | default: [null, null, null],
31 | },
32 | link: {
33 | type: 'array',
34 | default: [null, null, null],
35 | },
36 | id: {
37 | type: 'array',
38 | default: [null, null, null],
39 | },
40 | captionTitle: {
41 | type: 'array',
42 | default: [null, null, null],
43 | },
44 | captionContent: {
45 | type: 'array',
46 | default: [null, null, null],
47 | },
48 | slideTime: {
49 | type: 'number',
50 | default: 5000,
51 | },
52 | isResponsive: {
53 | type: 'boolean',
54 | default: false,
55 | },
56 | slideMaxHeight: {
57 | type: 'number',
58 | default: 250,
59 | },
60 | slideCustomHeight: {
61 | type: 'boolean',
62 | default: false,
63 | },
64 | verticalAlign: {
65 | type: 'string',
66 | },
67 | align: {
68 | type: 'string',
69 | default: '',
70 | },
71 | containerWidth: {
72 | type: 'string',
73 | default: 'container',
74 | },
75 | transitionType: {
76 | type: 'string',
77 | default: 'slide',
78 | },
79 | linkTarget: {
80 | type: 'string',
81 | source: 'attribute',
82 | selector: 'a',
83 | attribute: 'target',
84 | },
85 | rel: {
86 | type: 'string',
87 | source: 'attribute',
88 | selector: 'a',
89 | attribute: 'rel',
90 | },
91 | };
92 |
93 | export default attributes;
94 |
--------------------------------------------------------------------------------
/assets/c9-feather-logo-icon.js:
--------------------------------------------------------------------------------
1 | const { G, Path, SVG } = wp.components;
2 |
3 | const Icon = (
4 |
5 |
6 |
7 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | c9-feather-logo-icon
26 |
27 |
28 |
32 |
33 |
34 |
35 | );
36 |
37 | export default Icon;
38 |
--------------------------------------------------------------------------------
/assets/icon-c9-image-carousel.svg:
--------------------------------------------------------------------------------
1 | Artboard 1 copy 11
--------------------------------------------------------------------------------
/tests/test-class-layout-endpoints.php:
--------------------------------------------------------------------------------
1 | server = $wp_rest_server;
43 | // do_action( 'rest_api_init' );
44 | // $this->routes = $this->server->get_routes();
45 | // }
46 | // /**
47 | // * Tests that the gutenberg namespace exists in the REST API.
48 | // */
49 | // public function test_namespace_exists() {
50 | // $this->assertArrayHasKey( $this->namespace, $this->routes );
51 | // }
52 | // /**
53 | // * Tests the retrieval of favorite layouts.
54 | // */
55 | // public function test_saved_block_exists() {
56 | // $request = new \WP_REST_Request( 'GET', '/wp/v2/types/wp_block' );
57 | // $response = $this->server->dispatch( $request );
58 | // $this->assertNotNull( $response->get_data() );
59 | // }
60 | // /**
61 | // * Tests the retrieval of posts.
62 | // */
63 | // public function test_saved_post_categories_exists() {
64 | // $request = new \WP_REST_Request( 'GET', '/wp/v2/categories' );
65 | // $response = $this->server->dispatch( $request );
66 | // $this->assertNotNull( $response->get_data() );
67 | // }.
68 | }
69 |
--------------------------------------------------------------------------------
/src/blocks/block-vertical-tabs/components/vertical-tab/index.php:
--------------------------------------------------------------------------------
1 | ',
28 | $classes,
29 | esc_attr($id),
30 | esc_attr($aria_label)
31 | );
32 |
33 | $tab_markup .= $content . '';
34 |
35 | return $tab_markup;
36 | }
37 |
38 | /**
39 | * Registers the vertical tab component block on server
40 | */
41 | function covertnine_blocks_register_vertical_tabs()
42 | {
43 | /* Check if the register function exists */
44 | if (!function_exists( 'register_block_type' )) {
45 | return;
46 | }
47 |
48 | /* Block attributes */
49 | register_block_type( 'c9-blocks/vertical-tabs-tab', array(
50 | 'title' => __('C9 Vertical Tab', 'c9-blocks'),
51 | 'category' => 'common',
52 | 'parent' => 'c9-blocks/vertical-tabs',
53 | 'attributes' => array(
54 | 'slug' => array(
55 | 'type' => 'string',
56 | ),
57 | 'tabActive' => array(
58 | 'type' => 'string',
59 | ),
60 | 'id' => array(
61 | 'type' => 'number',
62 | ),
63 | ),
64 | 'render_callback' => 'covertnine_blocks_render_vertical_tabs'
65 | ) );
66 | }
67 | add_action( 'init', 'covertnine_blocks_register_vertical_tabs' );
68 |
--------------------------------------------------------------------------------
/src/blocks/block-horizontal-tabs/components/horizontal-tab/index.php:
--------------------------------------------------------------------------------
1 | ',
28 | $classes,
29 | esc_attr($id),
30 | esc_attr($aria_label)
31 | );
32 |
33 | $tab_markup .= $content . '';
34 |
35 | return $tab_markup;
36 | }
37 |
38 | /**
39 | * Registers the horizontal tab component block on server
40 | */
41 | function covertnine_blocks_register_horizontal_tabs()
42 | {
43 | /* Check if the register function exists */
44 | if (!function_exists( 'register_block_type' )) {
45 | return;
46 | }
47 |
48 | /* Block attributes */
49 | register_block_type( 'c9-blocks/horizontal-tabs-tab', array(
50 | 'title' => __('C9 Horizontal Tab', 'c9-blocks'),
51 | 'category' => 'common',
52 | 'parent' => 'c9-blocks/horizontal-tabs',
53 | 'attributes' => array(
54 | 'slug' => array(
55 | 'type' => 'string',
56 | ),
57 | 'tabActive' => array(
58 | 'type' => 'string',
59 | ),
60 | 'id' => array(
61 | 'type' => 'number',
62 | ),
63 | ),
64 | 'render_callback' => 'covertnine_blocks_render_horizontal_tabs'
65 | ) );
66 | }
67 | add_action( 'init', 'covertnine_blocks_register_horizontal_tabs' );
68 |
--------------------------------------------------------------------------------
/src/components/templates-modal/page-layout-button.js:
--------------------------------------------------------------------------------
1 | const { Icon } = wp.components;
2 | const { withDispatch } = wp.data;
3 | const { useState } = wp.element;
4 | import HoverIntent from 'react-hoverintent';
5 |
6 | const LayoutButton = ({
7 | label,
8 | icon,
9 | description,
10 | preview,
11 | recommended,
12 | layout,
13 | resetBlocks,
14 | insertBlocks,
15 | open,
16 | close,
17 | onHover,
18 | }) => {
19 | const [hovered, setHovered] = useState(false);
20 | const toggleHover = () => setHovered(!hovered);
21 | return (
22 | {
25 | open();
26 | resetBlocks([]);
27 | setTimeout(() => {
28 | insertBlocks(layout);
29 | close();
30 | }, 0);
31 | onHover(null);
32 | }}
33 | onFocus={() => onHover(layout)}
34 | onMouseEnter={() => onHover(layout)}
35 | onMouseLeave={() => onHover(null)}
36 | onBlur={() => onHover(null)}
37 | >
38 |
47 |
48 | {preview ? (
49 |
50 | ) : (
51 |
52 | )}
53 |
54 |
{label}
55 |
{description}
56 |
57 |
58 |
59 |
60 | {recommended && (
61 |
62 | includes:
63 | {recommended}
64 |
65 | )}
66 |
67 |
68 | );
69 | };
70 |
71 | export default withDispatch((dispatch) => {
72 | const { resetBlocks, insertBlocks } = dispatch('core/block-editor');
73 |
74 | return {
75 | resetBlocks,
76 | insertBlocks,
77 | };
78 | })(LayoutButton);
79 |
--------------------------------------------------------------------------------
/src/blocks/block-heading/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import Edit from './edit';
5 | import Save from './save';
6 | import attributes from './attributes';
7 |
8 | /**
9 | * Styles
10 | */
11 | import './styles/style.scss';
12 |
13 | import Icon from '../../../assets/icon-c9-heading.svg';
14 |
15 | /**
16 | * WordPress dependencies
17 | */
18 | const { __ } = wp.i18n;
19 | const { registerBlockType } = wp.blocks;
20 | const { compose } = wp.compose;
21 | const { withSelect } = wp.data;
22 | const { withViewportMatch } = wp.viewport;
23 |
24 | registerBlockType('c9-blocks/heading', {
25 | title: __('C9 Heading', 'c9-blocks'),
26 | icon: Icon,
27 | category: 'c9-blocks',
28 | supports: {
29 | anchor: true,
30 | },
31 | keywords: [
32 | __('heading', 'c9-blocks'),
33 | __('c9', 'c9-blocks'),
34 | __('covertnine', 'c9-blocks'),
35 | ],
36 |
37 | description: __(
38 | 'An advanced heading block with inline subheading font, custom colors, and style settings.',
39 | 'c9-blocks'
40 | ),
41 |
42 | example: {
43 | viewportWidth: '280',
44 | attributes: {
45 | heading: 'Headlines H1-H6',
46 | subheading: 'Subheading H1-H6',
47 | addSubheading: true,
48 | tagLevel: 3,
49 | },
50 | },
51 |
52 | attributes: attributes,
53 |
54 | // Render the block components
55 | edit: compose(
56 | withViewportMatch({ isLargeViewport: 'medium' }),
57 | withSelect((select, { clientId, isLargeViewport, isCollapsed }) => {
58 | const {
59 | getBlockRootClientId,
60 | getSettings,
61 | isBlockSelected,
62 | hasSelectedInnerBlock,
63 | } = select('core/block-editor');
64 | const settings = getSettings();
65 | return {
66 | isCollapsed:
67 | isCollapsed ||
68 | !isLargeViewport ||
69 | (!settings.hasFixedToolbar && !!getBlockRootClientId(clientId)),
70 | isSelectedBlockInRoot:
71 | isBlockSelected(clientId) || hasSelectedInnerBlock(clientId, true),
72 | };
73 | })
74 | )(Edit),
75 |
76 | // Save the attributes and markup
77 | save: Save,
78 | });
79 |
--------------------------------------------------------------------------------
/assets/icon-c9-post-grid.svg:
--------------------------------------------------------------------------------
1 | Artboard 1 copy 2
--------------------------------------------------------------------------------
/src/blocks/block-horizontal-tabs/save.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { Component } = wp.element;
5 | const { RichText, InnerBlocks } = wp.blockEditor;
6 | const { applyFilters } = wp.hooks;
7 |
8 | /**
9 | * External Dependencies.
10 | */
11 | import classnames from 'classnames';
12 |
13 | export default class Save extends Component {
14 | constructor() {
15 | super(...arguments);
16 | }
17 |
18 | render() {
19 | const {
20 | tabActive,
21 | buttonsAlign,
22 | tabsData = [],
23 | tabBackgroundColor,
24 | tabTextColor,
25 | tabContentBackgroundColor,
26 | blockBackgroundColor,
27 | instanceId,
28 | } = this.props.attributes;
29 |
30 | const { className = '', ...otherProps } = this.props;
31 |
32 | return (
33 |
41 |
48 | {tabsData.map((tabData) => {
49 | const { slug, title } = tabData;
50 | const selected = tabActive === slug;
51 | return (
52 |
53 |
66 |
67 | );
68 | })}
69 |
70 |
76 |
77 |
78 |
79 | );
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/dist/blocks.frontend.build.js:
--------------------------------------------------------------------------------
1 | /*! For license information please see blocks.frontend.build.js.LICENSE.txt */
2 | !function(){var e={1198:function(){function e(e,t,o){var a=o("#".concat(e)),r=a.attr("style"),n=o('VIDEO '));n.on("load",(function(){this.parentNode.parentNode.style.opacity=1})),a.replaceWith(n)}function t(e,r){if(YT&&YT.Player)new YT.Player(e,{playerVars:{autoplay:1,controls:0,disablekb:0,autohide:1,wmode:"opaque",hd:1,enablejsapi:1,loop:1,showinfo:0,iv_load_policy:3,rel:0,modestbranding:1,playlist:r},videoId:r,events:{onReady:o,onError:a}});else setTimeout((function(){t(e,r)}),100)}function o(e){e.target.mute(),e.target.playVideo(),e.target.getIframe().parentNode.parentNode.style.opacity=1}function a(e){console.log("The YouTube IFrame Player API fired an onError event with error code: "+e.data);var t=e.target.getIframe();t.parentNode.parentNode.style.opacity=0,t.parentNode.parentNode.style.transition="300ms",t.parentNode.parentNode.dataset.c9VideoContainerError=e.data}document.addEventListener("DOMContentLoaded",(function(){for(var o="true"===c9_blocks_params.disable_youtube_api,a=window.jQuery,r=document.getElementsByClassName("c9-video"),n=0;n {
26 | let classes = [];
27 | // abstract side class assignment
28 | function assignSideClasses(sideClass, level) {
29 | if (-1 != level) {
30 | classes.push(`${sideClass}-${level}`);
31 | }
32 | }
33 |
34 | // padding
35 | if (
36 | padding.top === padding.left &&
37 | padding.top === padding.bottom &&
38 | padding.top === padding.right &&
39 | -1 != padding.top
40 | ) {
41 | classes.push(`p-${padding.top}`);
42 | } else if (padding.top === padding.bottom && 0 <= padding.top) {
43 | classes.push(`py-${padding.top}`);
44 | assignSideClasses('pl', padding.left);
45 | assignSideClasses('pr', padding.right);
46 | } else if (padding.left === padding.right && 0 <= padding.left) {
47 | classes.push(`px-${padding.left}`);
48 | assignSideClasses('pt', padding.top);
49 | assignSideClasses('pb', padding.bottom);
50 | } else {
51 | ['top', 'bottom', 'left', 'right'].map((s) =>
52 | assignSideClasses(`p${s[0]}`, padding[s])
53 | );
54 | }
55 |
56 | // margin
57 | if (margin.top === margin.bottom && -1 != margin.top) {
58 | classes.push(`my-${margin.top}`);
59 | } else {
60 | ['top', 'bottom'].map((s) => assignSideClasses(`m${s[0]}`, margin[s]));
61 | }
62 |
63 | return classes;
64 | };
65 |
--------------------------------------------------------------------------------
/src/blocks/block-vertical-tabs/save.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { Component } = wp.element;
5 | const { RichText, InnerBlocks } = wp.blockEditor;
6 | const { applyFilters } = wp.hooks;
7 |
8 | /**
9 | * WordPress dependencies
10 | */
11 | import classnames from 'classnames';
12 |
13 | export default class Save extends Component {
14 | constructor() {
15 | super(...arguments);
16 | }
17 |
18 | render() {
19 | const {
20 | tabActive,
21 | textAlign,
22 | tabsData = [],
23 | tabBackgroundColor,
24 | tabTextColor,
25 | tabContentBackgroundColor,
26 | blockBackgroundColor,
27 | verticalAlign,
28 | instanceId,
29 | } = this.props.attributes;
30 |
31 | const { className = '', ...otherProps } = this.props;
32 |
33 | return (
34 |
45 |
46 |
53 | {tabsData.map((tabData) => {
54 | const { slug, title } = tabData;
55 | const selected = tabActive === slug;
56 | return (
57 |
71 | );
72 | })}
73 |
74 |
75 |
88 |
89 | );
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/assets/tab-icons.js:
--------------------------------------------------------------------------------
1 | const tabIcons = {
2 | horizontal: (
3 |
12 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | ),
37 | vertical: (
38 |
47 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | ),
79 | };
80 |
81 | export default tabIcons;
82 |
--------------------------------------------------------------------------------
/src/blocks/block-carousel/save.js:
--------------------------------------------------------------------------------
1 | import ResizableCarouselContainer from './components/resizable-carousel-container';
2 |
3 | /**
4 | * External Dependencies.
5 | */
6 | import classnames from 'classnames';
7 |
8 | /**
9 | * WordPress dependencies
10 | */
11 | const { Component, Fragment } = wp.element;
12 | const { InnerBlocks } = wp.blockEditor;
13 |
14 | export default class Save extends Component {
15 | constructor() {
16 | super(...arguments);
17 | }
18 |
19 | /**
20 | * Returns the indicators layout configuration for a given amount of tabs.
21 | *
22 | * @param {number} slides Amount of indicators to create.
23 | * @param {number} id Instance Id of this carousel block.
24 | *
25 | * @return {Object[]} Indicators layout configuration.
26 | */
27 | createIndicators(slides, id) {
28 | let indicators = [];
29 | for (let i = 0; i < slides; i++) {
30 | indicators.push(
31 |
37 | );
38 | }
39 |
40 | return indicators;
41 | }
42 |
43 | render() {
44 | const { showIndicators, slides, showControls, instanceId, verticalAlign } =
45 | this.props.attributes;
46 |
47 | return (
48 |
49 | {showIndicators && (
50 |
51 | {this.createIndicators(slides, instanceId)}
52 |
53 | )}
54 |
60 |
61 |
62 | {showControls && (
63 |
64 |
70 |
71 | Previous
72 |
73 |
79 |
80 | Next
81 |
82 |
83 | )}
84 |
85 | );
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/blocks/block-carousel/deprecated/2.0/save.deprecated.js:
--------------------------------------------------------------------------------
1 | import ResizableCarouselContainer from './resizable-carousel-container.deprecated';
2 |
3 | /**
4 | * External Dependencies.
5 | */
6 | import classnames from 'classnames';
7 |
8 | /**
9 | * WordPress dependencies
10 | */
11 | const { Component, Fragment } = wp.element;
12 | const { InnerBlocks } = wp.blockEditor;
13 |
14 | export default class Save extends Component {
15 | constructor() {
16 | super(...arguments);
17 | }
18 |
19 | /**
20 | * Returns the indicators layout configuration for a given amount of tabs.
21 | *
22 | * @param {number} slides Amount of indicators to create.
23 | * @param {number} id Instance Id of this carousel block.
24 | *
25 | * @return {Object[]} Indicators layout configuration.
26 | */
27 | createIndicators(slides, id) {
28 | let indicators = [];
29 | for (let i = 0; i < slides; i++) {
30 | indicators.push(
31 |
37 | );
38 | }
39 |
40 | return indicators;
41 | }
42 |
43 | render() {
44 | const { showIndicators, slides, showControls, instanceId, verticalAlign } =
45 | this.props.attributes;
46 |
47 | return (
48 |
49 | {showIndicators && (
50 |
51 | {this.createIndicators(slides, instanceId)}
52 |
53 | )}
54 |
60 |
61 |
62 | {showControls && (
63 |
64 |
70 |
71 | Previous
72 |
73 |
79 |
80 | Next
81 |
82 |
83 | )}
84 |
85 | );
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/blocks/block-carousel/deprecated/3.0/save.deprecated.js:
--------------------------------------------------------------------------------
1 | import ResizableCarouselContainer from './resizable-carousel-container.deprecated';
2 |
3 | /**
4 | * External Dependencies.
5 | */
6 | import classnames from 'classnames';
7 |
8 | /**
9 | * WordPress dependencies
10 | */
11 | const { Component, Fragment } = wp.element;
12 | const { InnerBlocks } = wp.blockEditor;
13 |
14 | export default class Save extends Component {
15 | constructor() {
16 | super(...arguments);
17 | }
18 |
19 | /**
20 | * Returns the indicators layout configuration for a given amount of tabs.
21 | *
22 | * @param {number} slides Amount of indicators to create.
23 | * @param {number} id Instance Id of this carousel block.
24 | *
25 | * @return {Object[]} Indicators layout configuration.
26 | */
27 | createIndicators(slides, id) {
28 | let indicators = [];
29 | for (let i = 0; i < slides; i++) {
30 | indicators.push(
31 |
37 | );
38 | }
39 |
40 | return indicators;
41 | }
42 |
43 | render() {
44 | const { showIndicators, slides, showControls, instanceId, verticalAlign } =
45 | this.props.attributes;
46 |
47 | return (
48 |
49 | {showIndicators && (
50 |
51 | {this.createIndicators(slides, instanceId)}
52 |
53 | )}
54 |
60 |
61 |
62 | {showControls && (
63 |
64 |
70 |
71 | Previous
72 |
73 |
79 |
80 | Next
81 |
82 |
83 | )}
84 |
85 | );
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/blocks/block-heading/save.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import CustomHeading from './components/custom-heading';
5 |
6 | /**
7 | * WordPress dependencies
8 | */
9 | const { Component } = wp.element;
10 | const { RichText } = wp.blockEditor;
11 |
12 | /**
13 | * External Dependencies.
14 | */
15 | import classnames from 'classnames';
16 |
17 | export default class Save extends Component {
18 | constructor() {
19 | super(...arguments);
20 | }
21 |
22 | /**
23 | * Returns appropriate css class for given type, displayLevel, tagLevel, override values.
24 | *
25 | * @param {string} type Type of text - Heading, Subheading, Text-XL
26 | * @param {number} displayLevel Custom tag level.
27 | * @param {string} tagLevel Base tag level by default.
28 | * @param {boolean} override Toggle between using just the base class or overriding the style.
29 | *
30 | * @return {string} Appropriate css class based on configuration.
31 | */
32 | c9TextStyleConfig(type, display, tag, override) {
33 | if (!override && 'c9-txl display-' != type) {
34 | return type.split(' ')[0];
35 | } else if (0 == display) {
36 | return `${type}${tag}`;
37 | } else {
38 | return `${type}${display}`;
39 | }
40 | }
41 |
42 | render() {
43 | // Setup the attributes
44 | const {
45 | attributes: {
46 | heading,
47 | subheading,
48 | textColor,
49 | subTextColor,
50 | tagLevel,
51 | type,
52 | displayLevel,
53 | weight,
54 | overrideStyle,
55 | addSubheading,
56 | },
57 | } = this.props;
58 |
59 | // Save the block markup for the front end
60 | return (
61 |
62 |
73 |
74 | {addSubheading && (
75 | {
77 | if (0 == display) {
78 | return `${type}${tag}`;
79 | } else {
80 | return `${type}${display}`;
81 | }
82 | })(type, displayLevel, tagLevel)}
83 | >
84 |
85 | {subheading.startsWith(' ')
86 | ? subheading
87 | : ' ' + subheading}
88 |
89 |
90 | )}
91 |
92 | );
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/assets/section-template-icons/about-picture-contact-card.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/assets/icon-c9-social-share.svg:
--------------------------------------------------------------------------------
1 | Artboard 1 copy 18
--------------------------------------------------------------------------------
/src/blocks/block-posts-grid/edit.js:
--------------------------------------------------------------------------------
1 | import Inspector from './components/inspector';
2 | import Container from './components/container';
3 | import cryptoRandomString from 'crypto-random-string';
4 |
5 | const { Component, Fragment } = wp.element;
6 | const { InnerBlocks, BlockControls } = wp.blockEditor;
7 |
8 | const ALLOWED_BLOCKS = ['c9-blocks/post-grid'];
9 |
10 | class Edit extends Component {
11 | constructor() {
12 | super(...arguments);
13 | }
14 |
15 | componentDidMount() {
16 | this.initializeInstanceId();
17 | }
18 |
19 | componentDidUpdate(prevProps) {
20 | this.checkBlockIdAndUpdate();
21 | this.initializeInstanceId(prevProps);
22 | }
23 |
24 | initializeInstanceId(prevProps = {}) {
25 | const { instanceId } = this.props.attributes;
26 | if (
27 | instanceId === undefined &&
28 | (!prevProps.attributes || instanceId !== prevProps.attributes.instanceId)
29 | ) {
30 | const newInstanceId =
31 | this.props.instanceId ||
32 | parseInt(cryptoRandomString({ length: 4, type: 'numeric' }));
33 | this.props.setAttributes({ instanceId: newInstanceId });
34 | }
35 | }
36 |
37 | checkBlockIdAndUpdate = () => {
38 | const { attributes, setAttributes } = this.props;
39 | const { instanceId, containerVideoID } = attributes;
40 |
41 | const sanitizedInstanceId = instanceId && String(instanceId).replace(/[^a-zA-Z0-9-_]/g, '');
42 | const sanitizedContainerVideoID =
43 | containerVideoID && String(containerVideoID).replace(/[^a-zA-Z0-9-_]/g, '');
44 |
45 | if (
46 | sanitizedInstanceId !== undefined &&
47 | document.querySelectorAll(`#player-${sanitizedContainerVideoID}-${sanitizedInstanceId}`)
48 | .length > 1
49 | ) {
50 | const newInstanceId = parseInt(
51 | cryptoRandomString({ length: 4, type: 'numeric' })
52 | );
53 | setAttributes({ instanceId: newInstanceId });
54 | }
55 | };
56 |
57 | render() {
58 | return (
59 |
60 |
61 |
62 |
63 |
64 |
69 |
70 |
71 | );
72 | }
73 | }
74 |
75 | export default Edit;
--------------------------------------------------------------------------------
/src/blocks/block-vertical-tabs/styles/editor.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * #.# Editor Styles
3 | *
4 | * CSS for just Backend enqueued after style.scss
5 | * which makes it higher in priority.
6 | */
7 |
8 | div[data-type="c9-blocks/vertical-tabs"] .c9-vertical-tabs {
9 | .tab-content [data-tab] {
10 | display: none;
11 | }
12 |
13 | .nav-item {
14 | transition: 0.15s border-color, 0.15s background-color, 0.15s opacity;
15 | }
16 |
17 | .c9-tab-admin-wrapper {
18 | position: relative;
19 |
20 | // show remove button on hover.
21 | &:not(:hover)>.c9-component-remove-button {
22 | opacity: 0;
23 | }
24 | }
25 | }
26 |
27 | .c9-component-remove-button {
28 | position: absolute;
29 | align-items: center;
30 | justify-content: center;
31 | top: 0;
32 | right: 0;
33 | width: 20px;
34 | height: 20px;
35 | padding: 0 !important;
36 | margin-top: -10px;
37 | margin-right: -10px;
38 | color: #fff;
39 | background-color: #4f5969;
40 | border-radius: 50%;
41 | opacity: 0.7;
42 | transition: 0.2s opacity, 0.2s background-color;
43 |
44 | &:hover {
45 | background-color: #c9586c;
46 | opacity: 1;
47 | }
48 |
49 | svg {
50 | width: auto;
51 | height: 0.8em;
52 | }
53 | }
54 |
55 | .c9-component-remove-button-confirm {
56 |
57 | .c9-component-remove-button-confirm-yep,
58 | .c9-component-remove-button-confirm-nope {
59 | padding: 0;
60 | margin-left: 5px;
61 |
62 | &:hover,
63 | &:focus {
64 | text-decoration: underline;
65 | }
66 |
67 | &,
68 | &:focus {
69 | background: none;
70 | box-shadow: none;
71 | }
72 | }
73 |
74 | .c9-component-remove-button-confirm-yep,
75 | .c9-component-remove-button-confirm-yep:focus {
76 | color: #c9586c;
77 | }
78 |
79 | .c9-component-remove-button-confirm-nope,
80 | .c9-component-remove-button-confirm-nope:focus {
81 | color: #999;
82 | }
83 |
84 | &.components-popover {
85 | &::before {
86 | border-color: transparent;
87 | }
88 |
89 | &.is-top::after {
90 | border-top-color: #191e23;
91 | }
92 |
93 | &.is-bottom::after {
94 | border-bottom-color: #191e23;
95 | }
96 | }
97 |
98 | .components-popover__content {
99 | padding: 4px 12px;
100 | color: $white;
101 | white-space: nowrap;
102 | background: #191e23;
103 | border-width: 0;
104 | }
105 |
106 | &:not(.is-mobile) .components-popover__content {
107 | min-width: 0;
108 | }
109 |
110 | .components-tooltip__shortcut {
111 | display: block;
112 | color: #7e8993;
113 | text-align: center;
114 | }
115 | }
116 |
117 | .editor-styles-wrapper div[data-type="c9-blocks/vertical-tabs"] {
118 | margin-top: 32px;
119 | margin-bottom: 32px;
120 | }
121 |
--------------------------------------------------------------------------------
/src/components/remove-button/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { Component } = wp.element;
5 | const { Path, SVG } = wp.components;
6 | const { __ } = wp.i18n;
7 | const { Button, Popover } = wp.components;
8 |
9 | /**
10 | * Create an RemoveButton wrapper Component
11 | */
12 | export default class RemoveButton extends Component {
13 | constructor() {
14 | super(...arguments);
15 |
16 | this.state = {
17 | confirmed: -1,
18 | };
19 | }
20 |
21 | render() {
22 | const {
23 | onRemove,
24 | show,
25 | style,
26 | tooltipText = __('Remove block?', 'c9-blocks'),
27 | tooltipRemoveText = __('Remove', 'c9-blocks'),
28 | tooltipCancelText = __('Cancel', 'c9-blocks'),
29 | } = this.props;
30 |
31 | const { confirmed } = this.state;
32 |
33 | if (!show) {
34 | return '';
35 | }
36 |
37 | return (
38 | {
41 | if (-1 === confirmed) {
42 | this.setState({
43 | confirmed: 0,
44 | });
45 | }
46 | }}
47 | style={style}
48 | >
49 | {0 === confirmed ? (
50 | {
53 | this.setState({
54 | confirmed: -1,
55 | });
56 | }}
57 | onFocusOutside={() => {
58 | this.setState({
59 | confirmed: -1,
60 | });
61 | }}
62 | >
63 | {tooltipText}
64 |
68 | {tooltipRemoveText}
69 |
70 | {
73 | this.setState({
74 | confirmed: -1,
75 | });
76 | }}
77 | >
78 | {tooltipCancelText}
79 |
80 |
81 | ) : (
82 | ''
83 | )}
84 |
98 |
102 |
103 |
104 | );
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/components/resizable-box/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * External dependencies
3 | */
4 | import classnames from 'classnames';
5 | import { Resizable } from 're-resizable';
6 |
7 | function ResizableBox({ className, refHandle, showHandle = false, ...props }) {
8 | // Removes the inline styles in the drag handles.
9 | const handleStylesOverrides = {
10 | width: null,
11 | height: null,
12 | top: null,
13 | right: null,
14 | bottom: null,
15 | left: null,
16 | };
17 |
18 | const handleClassName = 'components-resizable-box__handle';
19 | const sideHandleClassName = 'components-resizable-box__side-handle';
20 | const cornerHandleClassName = 'components-resizable-box__corner-handle';
21 |
22 | return (
23 |
88 | );
89 | }
90 |
91 | export default ResizableBox;
92 |
--------------------------------------------------------------------------------
/src/blocks/block-posts-grid/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import Edit from './edit';
5 | import Save from './save';
6 | import attributes from './attributes';
7 | import Deprecated from './deprecated';
8 |
9 | import Icon from '../../../assets/icon-c9-post-grid.svg';
10 |
11 | /**
12 | * Styles
13 | */
14 | import './styles/style.scss';
15 |
16 | /**
17 | * WordPress dependencies
18 | */
19 | const { __ } = wp.i18n;
20 | const { compose } = wp.compose;
21 | const { withSelect } = wp.data;
22 | const { registerBlockType } = wp.blocks;
23 |
24 | import cryptoRandomString from 'crypto-random-string';
25 |
26 | // JavaScript sanitization for text
27 | const sanitizeText = (text) => {
28 | // Safely encode the text and remove any special characters
29 | return encodeURIComponent(text);
30 | };
31 |
32 | registerBlockType('c9-blocks/posts-grid', {
33 | title: __('C9 Posts Grid', 'c9-blocks'),
34 | icon: Icon,
35 | category: 'c9-blocks',
36 | supports: {
37 | // fill in features
38 | },
39 | keywords: [__('responsive', 'c9-blocks')],
40 | description: __(
41 | 'Display responsive grids with post content of any kind with filtering, sorting, and flexible layout settings. (Includes customizable outer container)',
42 | 'c9-blocks'
43 | ),
44 | example: {
45 | viewportWidth: '280',
46 | attributes: {},
47 | innerBlocks: [
48 | {
49 | name: 'c9-blocks/post-grid',
50 | attributes: {
51 | displayPostDate: true,
52 | displayPostExcerpt: true,
53 | displayPostAuthor: true,
54 | displayPostLink: true,
55 | displaySectionTitle: true,
56 | columns: 3,
57 | excerptLength: 20,
58 | sectionTitle: 'The Latest News', // Example sanitized content
59 | imageSize: 'c9-feature-medium-crop',
60 | },
61 | },
62 | ],
63 | },
64 | attributes,
65 |
66 | // Render the block components
67 | edit: compose([
68 | withSelect((select, ownProps) => {
69 | const { isBlockSelected, hasSelectedInnerBlock } =
70 | select('core/block-editor');
71 |
72 | const { clientId } = ownProps;
73 |
74 | return {
75 | isSelectedBlockInRoot:
76 | isBlockSelected(clientId) || hasSelectedInnerBlock(clientId, true),
77 | instanceId: parseInt(
78 | cryptoRandomString({ length: 4, type: 'numeric' })
79 | ),
80 | };
81 | }),
82 | ])(Edit),
83 |
84 | // Save the attributes and markup
85 | save: (props) => {
86 | const { attributes } = props;
87 |
88 | // Example of sanitizing before save
89 | const sanitizedSectionTitle = sanitizeText(attributes.sectionTitle);
90 |
91 | return ;
92 | },
93 |
94 | deprecated: Deprecated,
95 | });
--------------------------------------------------------------------------------
/src/blocks/block-grid-container/attributes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Block Attributes
3 | */
4 | const attributes = {
5 | instanceId: {
6 | type: 'number',
7 | },
8 | lockMovement: {
9 | type: 'boolean',
10 | default: true,
11 | },
12 | rows: {
13 | type: 'number',
14 | default: 1,
15 | },
16 | align: {
17 | type: 'string',
18 | default: 'full',
19 | },
20 | containerImgURL: {
21 | type: 'string',
22 | },
23 | containerHue: {
24 | type: 'string',
25 | default: undefined,
26 | },
27 | containerOpacity: {
28 | type: 'number',
29 | default: 10,
30 | },
31 | bgImgSize: {
32 | type: 'string',
33 | default: 'cover',
34 | },
35 | bgCustomX: {
36 | type: 'object',
37 | default: {
38 | size: 'auto',
39 | unit: 'px',
40 | },
41 | },
42 | bgCustomY: {
43 | type: 'object',
44 | default: {
45 | size: 'auto',
46 | unit: 'px',
47 | },
48 | },
49 | bgImgRepeat: {
50 | type: 'string',
51 | default: 'no-repeat',
52 | },
53 | // true evaluates to backgroundAttachment fixed, false to scroll
54 | bgImgAttach: {
55 | type: 'boolean',
56 | default: false,
57 | },
58 | overlayHue: {
59 | type: 'string',
60 | default: undefined,
61 | },
62 | overlayOpacity: {
63 | type: 'number',
64 | default: 10,
65 | },
66 | blendMode: {
67 | type: 'string',
68 | default: 'normal',
69 | },
70 | linkedValToggle: {
71 | type: 'boolean',
72 | default: true,
73 | },
74 | minScreenHeight: {
75 | type: 'number',
76 | default: 20,
77 | },
78 | containerMargin: {
79 | type: 'object',
80 | default: {
81 | linked: true,
82 | icon: 'admin-links',
83 | unit: 'px',
84 | top: '-1',
85 | bottom: '-1',
86 | },
87 | },
88 | containerPadding: {
89 | type: 'object',
90 | default: {
91 | linked: true,
92 | icon: 'admin-links',
93 | top: '3',
94 | bottom: '3',
95 | left: '3',
96 | right: '3',
97 | },
98 | },
99 | focalPoint: {
100 | type: 'object',
101 | default: {
102 | x: 0.5,
103 | y: 0.5,
104 | },
105 | },
106 | videoType: {
107 | type: 'string',
108 | default: 'upload',
109 | },
110 | containerVideoURL: {
111 | type: 'string',
112 | default: '',
113 | },
114 | containerVideoID: {
115 | type: 'string',
116 | default: '',
117 | },
118 | cannotEmbed: {
119 | type: 'boolean',
120 | default: false,
121 | },
122 | bgImgSizeMobile: {
123 | type: 'string',
124 | default: 'cover',
125 | },
126 | focalPointMobile: {
127 | type: 'object',
128 | default: {
129 | x: 0.5,
130 | y: 0.5,
131 | },
132 | },
133 | overrideMobile: {
134 | type: 'boolean',
135 | default: false,
136 | },
137 | bgCustomXMobile: {
138 | type: 'object',
139 | default: {
140 | size: 'auto',
141 | unit: 'px',
142 | },
143 | },
144 | bgCustomYMobile: {
145 | type: 'object',
146 | default: {
147 | size: 'auto',
148 | unit: 'px',
149 | },
150 | },
151 | };
152 |
153 | export default attributes;
154 |
--------------------------------------------------------------------------------
/src/components/templates-modal/section-templates/templates/inform-map-embed-focus.js:
--------------------------------------------------------------------------------
1 | export default {
2 | icon: (
3 |
7 | ),
8 | title: 'Inform Map Embed Focus',
9 | description: 'Address • Map Embed Code • Button Link',
10 | markup: `
11 |
36 | `,
37 | };
38 |
--------------------------------------------------------------------------------
/src/blocks/block-column-container/attributes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Block Attributes
3 | */
4 | const attributes = {
5 | align: {
6 | type: 'string',
7 | default: '',
8 | },
9 | columns: {
10 | type: 'number',
11 | },
12 | columnMaxWidth: {
13 | type: 'number',
14 | },
15 | centerColumns: {
16 | type: 'boolean',
17 | default: true,
18 | },
19 | columnsGap: {
20 | type: 'number',
21 | default: 2,
22 | },
23 | responsiveToggle: {
24 | type: 'boolean',
25 | default: true,
26 | },
27 | layout: {
28 | type: 'string',
29 | },
30 | containerWidth: {
31 | type: 'string',
32 | default: 'container',
33 | },
34 | verticalAlign: {
35 | type: 'string',
36 | },
37 | containerImgURL: {
38 | type: 'string',
39 | },
40 | bgImgSize: {
41 | type: 'string',
42 | default: 'cover',
43 | },
44 | bgCustomX: {
45 | type: 'object',
46 | default: {
47 | size: 'auto',
48 | unit: 'px',
49 | },
50 | },
51 | bgCustomY: {
52 | type: 'object',
53 | default: {
54 | size: 'auto',
55 | unit: 'px',
56 | },
57 | },
58 | bgImgRepeat: {
59 | type: 'string',
60 | default: 'no-repeat',
61 | },
62 | // true evaluates to backgroundAttachment scroll, false to fixed
63 | bgImgAttach: {
64 | type: 'boolean',
65 | default: false,
66 | },
67 | overlayHue: {
68 | type: 'string',
69 | default: undefined,
70 | },
71 | overlayOpacity: {
72 | type: 'number',
73 | default: 10,
74 | },
75 | blendMode: {
76 | type: 'string',
77 | default: 'normal',
78 | },
79 | linkedValToggle: {
80 | type: 'boolean',
81 | default: true,
82 | },
83 | minScreenHeight: {
84 | type: 'number',
85 | default: 10,
86 | },
87 | containerMargin: {
88 | type: 'object',
89 | default: {
90 | linked: true,
91 | icon: 'admin-links',
92 | top: '-1',
93 | bottom: '-1',
94 | },
95 | },
96 | containerPadding: {
97 | type: 'object',
98 | default: {
99 | linked: true,
100 | icon: 'admin-links',
101 | top: '-1',
102 | bottom: '-1',
103 | left: '-1',
104 | right: '-1',
105 | },
106 | },
107 | containerHue: {
108 | type: 'string',
109 | default: undefined,
110 | },
111 | containerOpacity: {
112 | type: 'number',
113 | default: 10,
114 | },
115 | focalPoint: {
116 | type: 'object',
117 | default: {
118 | x: 0.5,
119 | y: 0.5,
120 | },
121 | },
122 | bgImgSizeMobile: {
123 | type: 'string',
124 | default: 'cover',
125 | },
126 | focalPointMobile: {
127 | type: 'object',
128 | default: {
129 | x: 0.5,
130 | y: 0.5,
131 | },
132 | },
133 | overrideMobile: {
134 | type: 'boolean',
135 | default: false,
136 | },
137 | bgCustomXMobile: {
138 | type: 'object',
139 | default: {
140 | size: 'auto',
141 | unit: 'px',
142 | },
143 | },
144 | bgCustomYMobile: {
145 | type: 'object',
146 | default: {
147 | size: 'auto',
148 | unit: 'px',
149 | },
150 | },
151 | flipColumnsMobile: {
152 | type: 'boolean',
153 | default: false,
154 | },
155 | };
156 |
157 | export default attributes;
158 |
--------------------------------------------------------------------------------
/src/blocks/block-cta/attributes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Block Attributes
3 | */
4 |
5 | const attributes = {
6 | type: {
7 | type: 'string',
8 | value: 'c9-p',
9 | },
10 | buttonText: {
11 | type: 'string',
12 | },
13 | buttonUrl: {
14 | type: 'string',
15 | source: 'attribute',
16 | selector: 'a',
17 | attribute: 'href',
18 | },
19 | buttonAlignment: {
20 | type: 'string',
21 | default: 'left',
22 | },
23 | buttonBackgroundColor: {
24 | type: 'string',
25 | },
26 | buttonTextColor: {
27 | type: 'string',
28 | default: '#ffffff',
29 | },
30 | buttonSize: {
31 | type: 'string',
32 | default: 'c9-button-size-medium',
33 | },
34 | buttonShape: {
35 | type: 'string',
36 | default: 'square',
37 | },
38 | buttonTarget: {
39 | type: 'boolean',
40 | default: false,
41 | },
42 | blendMode: {
43 | type: 'string',
44 | default: 'normal',
45 | },
46 | ctaTitle: {
47 | type: 'array',
48 | selector: '.c9-cta-title',
49 | source: 'children',
50 | },
51 | ctaLayout: {
52 | type: 'string',
53 | default: 'two-thirds',
54 | },
55 | ctaMargin: {
56 | type: 'object',
57 | default: {
58 | linked: true,
59 | icon: 'admin-links',
60 | unit: 'px',
61 | top: '-1',
62 | bottom: '-1',
63 | },
64 | },
65 | ctaPadding: {
66 | type: 'object',
67 | default: {
68 | linked: true,
69 | icon: 'admin-links',
70 | top: '5',
71 | bottom: '5',
72 | left: '5',
73 | right: '5',
74 | },
75 | },
76 | ctaTextFontSize: {
77 | type: 'number',
78 | },
79 | ctaText: {
80 | type: 'array',
81 | selector: '.c9-cta-text',
82 | source: 'children',
83 | },
84 | ctaWidth: {
85 | type: 'string',
86 | default: 'container',
87 | },
88 | ctaBackgroundColor: {
89 | type: 'string',
90 | },
91 | ctaBackgroundOpacity: {
92 | type: 'number',
93 | default: 10,
94 | },
95 | ctaTextColor: {
96 | type: 'string',
97 | },
98 | imgURL: {
99 | type: 'string',
100 | source: 'attribute',
101 | attribute: 'src',
102 | selector: 'img',
103 | },
104 | imgID: {
105 | type: 'number',
106 | },
107 | imgAlt: {
108 | type: 'string',
109 | source: 'attribute',
110 | attribute: 'alt',
111 | selector: 'img',
112 | },
113 | imgSize: {
114 | type: 'string',
115 | default: 'cover',
116 | },
117 | focalPoint: {
118 | type: 'object',
119 | default: {
120 | x: 0.5,
121 | y: 0.5,
122 | },
123 | },
124 | // true evaluates to backgroundAttachment fixed, false to scroll
125 | imgAttach: {
126 | type: 'boolean',
127 | default: false,
128 | },
129 | // Deprecated
130 | ctaTitleFontSize: {
131 | type: 'string',
132 | default: '32',
133 | },
134 | align: {
135 | type: 'string',
136 | default: '',
137 | },
138 | disableToolbar: {
139 | type: 'boolean',
140 | default: false,
141 | },
142 | fontSize: {
143 | type: 'string',
144 | },
145 | customFontSize: {
146 | type: 'string',
147 | },
148 | dropCap: {
149 | type: 'boolean',
150 | default: false,
151 | },
152 | };
153 |
154 | export default attributes;
155 |
--------------------------------------------------------------------------------
/src/blocks/block-post-grid/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import Edit from './edit';
5 |
6 | /**
7 | * Styles
8 | */
9 | import './styles/style.scss';
10 |
11 | import Icon from '../../../assets/icon-c9-post-grid.svg';
12 |
13 | /**
14 | * WordPress dependencies
15 | */
16 | const { registerBlockType } = wp.blocks;
17 | const { compose } = wp.compose;
18 | const { withSelect } = wp.data;
19 |
20 | /**
21 | * External Dependencies.
22 | */
23 | import classnames from 'classnames';
24 | import isUndefined from 'lodash/isUndefined';
25 | import pickBy from 'lodash/pickBy';
26 |
27 | registerBlockType('c9-blocks/post-grid', {
28 | icon: Icon,
29 | parent: ['c9-blocks/post-container'],
30 | /* Add alignment to block wrapper. */
31 | supports: {
32 | inserter: false,
33 | reusable: false,
34 | },
35 | getEditWrapperProps({ align }) {
36 | if (
37 | 'full' === align ||
38 | 'wide' === align ||
39 | 'narrow' === align ||
40 | '' === align
41 | ) {
42 | return { 'data-align': align };
43 | }
44 | },
45 |
46 | edit: compose([
47 | withSelect((select, props) => {
48 | const { order, categories, tags, filterByCategory, filterByTag } =
49 | props.attributes;
50 |
51 | const { getEntityRecords, getMedia } = select('core', 'c9-blocks');
52 |
53 | const setCategories = filterByCategory ? categories : undefined;
54 | const setTags = filterByTag ? tags : undefined;
55 |
56 | const latestPostsQuery = pickBy(
57 | {
58 | categories: setCategories,
59 | tags: setTags,
60 | order,
61 | orderby: props.attributes.orderBy,
62 | // eslint-disable-next-line camelcase
63 | per_page: props.attributes.postsToShow,
64 | offset: props.attributes.offset,
65 | },
66 | (value) => !isUndefined(value)
67 | );
68 |
69 | return {
70 | latestPosts: getEntityRecords(
71 | 'postType',
72 | props.attributes.postType,
73 | latestPostsQuery
74 | ),
75 | getMedia,
76 | };
77 | }),
78 | ])(Edit),
79 |
80 | // Render via PHP
81 | save() {
82 | return null;
83 | },
84 | });
85 |
86 | /* Add the vertical column alignment class to the column container block. */
87 | const withClientIdClassName = wp.compose.createHigherOrderComponent(
88 | (BlockListBlock) => {
89 | return (props) => {
90 | const blockName = props.block.name;
91 |
92 | if ('c9-blocks/post-grid' === blockName) {
93 | return (
94 |
103 | );
104 | } else {
105 | return ;
106 | }
107 | };
108 | },
109 | 'withClientIdClassName'
110 | );
111 |
112 | wp.hooks.addFilter(
113 | 'editor.BlockListBlock',
114 | 'c9-blocks/add-vertical-align-class',
115 | withClientIdClassName
116 | );
117 |
--------------------------------------------------------------------------------
/src/blocks/block-carousel/components/swap-slide-toolbar.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { __ } = wp.i18n;
5 | const { ToolbarGroup, ToolbarButton } = wp.components;
6 | const { dispatch } = wp.data;
7 | const { createSuccessNotice } = dispatch('core/notices');
8 |
9 | /**
10 | * Control Settings
11 | */
12 | const DEFAULT_WIDTH_CONTROLS = [
13 | {
14 | icon: 'arrow-left-alt',
15 | title: __('Swap Slide toward Left', 'c9-blocks'),
16 | isLeft: true,
17 | },
18 | {
19 | icon: 'arrow-right-alt',
20 | title: __('Swap Slide toward Right', 'c9-blocks'),
21 | isLeft: false,
22 | },
23 | ];
24 |
25 | const TIMEOUT_DELAY = 250;
26 |
27 | /**
28 | * Create a Width Toolbar Component
29 | */
30 | export function SwapSlideToolbar({
31 | swapSlide,
32 | activeSlide,
33 | slides,
34 | carouselRef,
35 | widthControls = DEFAULT_WIDTH_CONTROLS,
36 | }) {
37 | return (
38 |
39 | {widthControls.map((control) => {
40 | const { isLeft, ...buttonProps } = control;
41 | return (
42 | {
46 | const $ = window.jQuery;
47 | let config = { opacity: 0, marginLeft: '200px' };
48 | if (isLeft) {
49 | config.marginLeft = '-200px';
50 | }
51 | $('.carousel-inner', carouselRef.current).animate(
52 | config,
53 | 400,
54 | 'swing',
55 | () => {
56 | if (isLeft) {
57 | const targetSlide =
58 | -1 < activeSlide - 1 ? activeSlide - 1 : slides - 1;
59 | swapSlide(activeSlide, targetSlide);
60 | setTimeout(() => {
61 | $(carouselRef.current).carousel('prev');
62 | $('.carousel-inner', carouselRef.current).animate({
63 | opacity: 100,
64 | marginLeft: 0,
65 | });
66 | createSuccessNotice(
67 | `c9-blocks/carousel: #${
68 | activeSlide + 1
69 | } is swapped with Slide #${targetSlide + 1}`,
70 | { id: 'swapBlockSlideNotice' }
71 | );
72 | }, TIMEOUT_DELAY);
73 | } else {
74 | const targetSlide =
75 | slides > activeSlide + 1 ? activeSlide + 1 : 0;
76 | swapSlide(activeSlide, targetSlide);
77 | setTimeout(() => {
78 | $(carouselRef.current).carousel('next');
79 | $('.carousel-inner', carouselRef.current).animate({
80 | opacity: 100,
81 | marginLeft: 0,
82 | });
83 | createSuccessNotice(
84 | `c9-blocks/carousel: #${
85 | activeSlide + 1
86 | } is swapped with Slide #${targetSlide + 1}`,
87 | { id: 'swapBlockSlideNotice' }
88 | );
89 | }, TIMEOUT_DELAY);
90 | }
91 | }
92 | );
93 | }}
94 | />
95 | );
96 | })}
97 |
98 | );
99 | }
100 |
101 | export default SwapSlideToolbar;
102 |
--------------------------------------------------------------------------------
/src/components/templates-modal/section-templates/templates/introduce-page-title.js:
--------------------------------------------------------------------------------
1 | export default {
2 | icon: (
3 |
7 | ),
8 | title: 'Introduce Page Title',
9 | description: '50 Words • Page Title • Logo',
10 | markup: `
11 |
32 | `,
33 | };
34 |
--------------------------------------------------------------------------------
/src/blocks/block-carousel/deprecated/1.0/save.deprecated.js:
--------------------------------------------------------------------------------
1 | /**
2 | * External Dependencies.
3 | */
4 | import classnames from 'classnames';
5 |
6 | /**
7 | * WordPress dependencies
8 | */
9 | const { Component, Fragment } = wp.element;
10 | const { InnerBlocks } = wp.blockEditor;
11 | const { applyFilters } = wp.hooks;
12 |
13 | export default class Save extends Component {
14 | constructor() {
15 | super(...arguments);
16 | }
17 |
18 | /**
19 | * Returns the indicators layout configuration for a given amount of tabs.
20 | *
21 | * @param {number} slides Amount of indicators to create.
22 | * @param {number} id Instance Id of this carousel block.
23 | *
24 | * @return {Object[]} Indicators layout configuration.
25 | */
26 | createIndicators(slides, id) {
27 | let indicators = [];
28 | for (let i = 0; i < slides; i++) {
29 | indicators.push(
30 |
36 | );
37 | }
38 |
39 | return indicators;
40 | }
41 |
42 | render() {
43 | const {
44 | showIndicators,
45 | autoSlide,
46 | slides,
47 | showControls,
48 | instanceId,
49 | wrapAround,
50 | slideTime,
51 | slideMaxHeight,
52 | slideEqualHeight,
53 | verticalAlign,
54 | } = this.props.attributes;
55 |
56 | const { className = '' } = this.props;
57 |
58 | return (
59 |
110 | );
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/assets/c9-feather-logo-gradient.svg:
--------------------------------------------------------------------------------
1 |
4 | feather gradient logo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/blocks/block-vertical-tabs/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import Edit from './edit';
5 | import Save from './save';
6 | import attributes from './attributes';
7 |
8 | /**
9 | * Styles
10 | */
11 | import './styles/style.scss';
12 |
13 | import Icon from '../../../assets/icon-c9-tabs-vertical-tabs.svg';
14 |
15 | /**
16 | * WordPress dependencies
17 | */
18 | const { __ } = wp.i18n;
19 | const { compose } = wp.compose;
20 | const { withSelect, withDispatch } = wp.data;
21 | const { registerBlockType } = wp.blocks;
22 |
23 | registerBlockType('c9-blocks/vertical-tabs', {
24 | title: __('C9 Vertical Tabs', 'c9-blocks'),
25 | icon: Icon,
26 | category: 'c9-blocks',
27 | supports: {
28 | // fill in features
29 | },
30 | keywords: [
31 | __('tabs', 'c9-blocks'),
32 | __('container', 'c9-blocks'),
33 | __('responsive', 'c9-blocks'),
34 | ],
35 | description: __(
36 | 'Display tabbed content with a vertical button interface for switching between multiple types of content.',
37 | 'c9-blocks'
38 | ),
39 | example: {
40 | viewportWidth: '300',
41 | attributes: {
42 | tabsData: [
43 | { slug: 'tab-1', title: 'Tab 1' },
44 | { slug: 'tab-2', title: 'Tab 2' },
45 | { slug: 'tab-3', title: 'Tab 3' },
46 | ],
47 | },
48 | innerBlocks: [
49 | {
50 | name: 'c9-blocks/vertical-tabs-tab',
51 | attributes: {
52 | slug: 'tab-1',
53 | tabActive: 'tab-1',
54 | },
55 | innerBlocks: [
56 | {
57 | name: 'c9-blocks/heading',
58 | attributes: {
59 | heading: 'Tab Headline',
60 | tagLevel: 3,
61 | },
62 | },
63 | {
64 | name: 'core/paragraph',
65 | attributes: {
66 | content:
67 | 'Vertical tabs can be aligned horizontally and vertically inside of the tab container. Almost any block can go inside of tabs including buttons, text, videos, and image galleries.',
68 | },
69 | },
70 | ],
71 | },
72 | {
73 | name: 'c9-blocks/vertical-tabs-tab',
74 | attributes: {
75 | slug: 'tab-2',
76 | tabActive: 'tab-1',
77 | },
78 | },
79 | {
80 | name: 'c9-blocks/vertical-tabs-tab',
81 | attributes: {
82 | slug: 'tab-3',
83 | tabActive: 'tab-1',
84 | },
85 | },
86 | ],
87 | },
88 | attributes,
89 | // Render the block components
90 | edit: compose([
91 | withSelect((select, ownProps) => {
92 | const { getBlock, isBlockSelected, hasSelectedInnerBlock } =
93 | select('core/block-editor');
94 |
95 | const { clientId } = ownProps;
96 |
97 | return {
98 | block: getBlock(clientId),
99 | isSelectedBlockInRoot:
100 | isBlockSelected(clientId) || hasSelectedInnerBlock(clientId, true),
101 | };
102 | }),
103 | withDispatch((dispatch) => {
104 | const { updateBlockAttributes, removeBlock } =
105 | dispatch('core/block-editor');
106 |
107 | return {
108 | updateBlockAttributes,
109 | removeBlock,
110 | };
111 | }),
112 | ])(Edit),
113 |
114 | // Save the attributes and markup
115 | save: (props) => {
116 | return ;
117 | },
118 | });
119 |
--------------------------------------------------------------------------------
/src/blocks/block-horizontal-tabs/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import Edit from './edit';
5 | import Save from './save';
6 | import attributes from './attributes';
7 |
8 | /**
9 | * Styles
10 | */
11 | import './styles/style.scss';
12 |
13 | import Icon from '../../../assets/icon-c9-tabs-horizontal.svg';
14 |
15 | /**
16 | * WordPress dependencies
17 | */
18 | const { __ } = wp.i18n;
19 | const { compose } = wp.compose;
20 | const { withSelect, withDispatch } = wp.data;
21 | const { registerBlockType } = wp.blocks;
22 |
23 | registerBlockType('c9-blocks/horizontal-tabs', {
24 | title: __('C9 Horizontal Tabs', 'c9-blocks'),
25 | icon: Icon,
26 | category: 'c9-blocks',
27 | supports: {
28 | // fill in features
29 | },
30 | keywords: [
31 | __('tabs', 'c9-blocks'),
32 | __('container', 'c9-blocks'),
33 | __('responsive', 'c9-blocks'),
34 | ],
35 | description: __(
36 | 'Display tabbed content with a horizontal button interface for switching between multiple types of content.',
37 | 'c9-blocks'
38 | ),
39 | example: {
40 | viewportWidth: '280',
41 | attributes: {
42 | buttonsAlign: 'center',
43 | tabsData: [
44 | { slug: 'tab-1', title: 'Tab 1' },
45 | { slug: 'tab-2', title: 'Tab 2' },
46 | { slug: 'tab-3', title: 'Tab 3' },
47 | ],
48 | },
49 | innerBlocks: [
50 | {
51 | name: 'c9-blocks/horizontal-tabs-tab',
52 | attributes: { slug: 'tab-1', tabActive: 'tab-1' },
53 | innerBlocks: [
54 | {
55 | name: 'c9-blocks/heading',
56 | attributes: {
57 | heading: 'Tab Number One',
58 | tagLevel: 3,
59 | },
60 | },
61 | {
62 | name: 'core/paragraph',
63 | attributes: {
64 | content:
65 | 'Horizontal tabs can be aligned vertically inside of the tab container, and colors for tabs can be customized with labels, colors, and alignments. Almost any block can go inside of tabs themselves including buttons, text, videos, and image galleries.',
66 | },
67 | },
68 | ],
69 | },
70 | {
71 | name: 'c9-blocks/horizontal-tabs-tab',
72 | attributes: { slug: 'tab-2', tabActive: 'tab-1' },
73 | },
74 | {
75 | name: 'c9-blocks/horizontal-tabs-tab',
76 | attributes: { slug: 'tab-3', tabActive: 'tab-1' },
77 | },
78 | ],
79 | },
80 | attributes,
81 | // Render the block components
82 | edit: compose([
83 | withSelect((select, ownProps) => {
84 | const { getBlock, isBlockSelected, hasSelectedInnerBlock } =
85 | select('core/block-editor');
86 |
87 | const { clientId } = ownProps;
88 |
89 | return {
90 | block: getBlock(clientId),
91 | isSelectedBlockInRoot:
92 | isBlockSelected(clientId) || hasSelectedInnerBlock(clientId, true),
93 | };
94 | }),
95 | withDispatch((dispatch) => {
96 | const { updateBlockAttributes, removeBlock } =
97 | dispatch('core/block-editor');
98 |
99 | return {
100 | updateBlockAttributes,
101 | removeBlock,
102 | };
103 | }),
104 | ])(Edit),
105 |
106 | // Save the attributes and markup
107 | save: (props) => {
108 | return ;
109 | },
110 | });
111 |
--------------------------------------------------------------------------------
/src/blocks/block-vertical-tabs/components/inspector.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { __ } = wp.i18n;
5 | const { Component } = wp.element;
6 | const { InspectorControls, AlignmentToolbar, PanelColorSettings } =
7 | wp.blockEditor;
8 | const { BaseControl } = wp.components;
9 | const { ContrastChecker } = wp.blockEditor;
10 |
11 | /**
12 | * Create an Inspector Controls wrapper Component
13 | */
14 | export default class Inspector extends Component {
15 | constructor() {
16 | super(...arguments);
17 | }
18 |
19 | render() {
20 | const { attributes, setAttributes } = this.props;
21 |
22 | const {
23 | textAlign,
24 | tabBackgroundColor,
25 | tabTextColor,
26 | tabContentBackgroundColor,
27 | blockBackgroundColor,
28 | } = attributes;
29 |
30 | return (
31 |
32 |
33 | setAttributes({ textAlign: value })}
36 | controls={['left', 'center', 'right']}
37 | />
38 |
39 |
46 | setAttributes({ blockBackgroundColor: value }),
47 | label: __('Background Color', 'c9-blocks'),
48 | },
49 | ]}
50 | >
51 |
57 |
58 | setAttributes({ tabBackgroundColor: value }),
65 | label: __('Background Color', 'c9-blocks'),
66 | },
67 | {
68 | value: tabTextColor,
69 | onChange: (value) => setAttributes({ tabTextColor: value }),
70 | label: __('Text Color', 'c9-blocks'),
71 | },
72 | ]}
73 | >
74 |
82 |
83 |
90 | setAttributes({ tabContentBackgroundColor: value }),
91 | label: __('Background Color', 'c9-blocks'),
92 | },
93 | ]}
94 | >
95 |
101 |
102 |
103 | );
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/blocks/block-image-carousel/components/swap-slide-toolbar.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WordPress dependencies
3 | */
4 | const { __ } = wp.i18n;
5 | const { ToolbarGroup, ToolbarButton } = wp.components;
6 | const { dispatch } = wp.data;
7 | const { createSuccessNotice } = dispatch('core/notices');
8 |
9 | /**
10 | * Control Settings
11 | */
12 | const DEFAULT_WIDTH_CONTROLS = [
13 | {
14 | icon: 'arrow-left-alt',
15 | title: __('Swap Slide toward Left', 'c9-blocks'),
16 | isLeft: true,
17 | },
18 | {
19 | icon: 'arrow-right-alt',
20 | title: __('Swap Slide toward Right', 'c9-blocks'),
21 | isLeft: false,
22 | },
23 | ];
24 |
25 | const TIMEOUT_DELAY = 250;
26 |
27 | /**
28 | * Create a Width Toolbar Component
29 | */
30 | export function SwapSlideToolbar({
31 | swapSlide,
32 | slides,
33 | carouselRef,
34 | widthControls = DEFAULT_WIDTH_CONTROLS,
35 | }) {
36 | return (
37 |
38 | {widthControls.map((control, index) => {
39 | const { isLeft, ...buttonProps } = control;
40 | const key = control.title || index;
41 | return (
42 | {
46 | const $ = window.jQuery;
47 | const activeSlide = $('div.active', carouselRef.current).index();
48 | let config = { opacity: 0, marginLeft: '200px' };
49 | if (isLeft) {
50 | config.marginLeft = '-200px';
51 | }
52 | $('.carousel-inner', carouselRef.current).animate(
53 | config,
54 | 400,
55 | 'swing',
56 | () => {
57 | if (isLeft) {
58 | const targetSlide =
59 | -1 < activeSlide - 1 ? activeSlide - 1 : slides - 1;
60 | swapSlide(activeSlide, targetSlide);
61 | setTimeout(() => {
62 | $(carouselRef.current).carousel('prev');
63 | $('.carousel-inner', carouselRef.current).animate({
64 | opacity: 100,
65 | marginLeft: 0,
66 | });
67 | createSuccessNotice(
68 | `c9-blocks/image-carousel: #${
69 | activeSlide + 1
70 | } is swapped with Slide #${targetSlide + 1}`,
71 | { id: 'swapBlockSlideNotice' }
72 | );
73 | }, TIMEOUT_DELAY);
74 | } else {
75 | const targetSlide =
76 | slides > activeSlide + 1 ? activeSlide + 1 : 0;
77 | swapSlide(activeSlide, targetSlide);
78 | setTimeout(() => {
79 | $(carouselRef.current).carousel('next');
80 | $('.carousel-inner', carouselRef.current).animate({
81 | opacity: 100,
82 | marginLeft: 0,
83 | });
84 | createSuccessNotice(
85 | `c9-blocks/image-carousel: #${
86 | activeSlide + 1
87 | } is swapped with Slide #${targetSlide + 1}`,
88 | { id: 'swapBlockSlideNotice' }
89 | );
90 | }, TIMEOUT_DELAY);
91 | }
92 | }
93 | );
94 | }}
95 | />
96 | );
97 | })}
98 |
99 | );
100 | }
101 |
102 | export default SwapSlideToolbar;
103 |
--------------------------------------------------------------------------------
/assets/section-template-icons/single-profile.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Single Bio
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/blocks/block-cta/save.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import CallToAction from './components/cta';
5 |
6 | /**
7 | * WordPress dependencies
8 | */
9 | const { Component } = wp.element;
10 | const { RichText } = wp.blockEditor;
11 |
12 | /**
13 | * External Dependencies.
14 | */
15 | import classnames from 'classnames';
16 |
17 | export default class Save extends Component {
18 | constructor() {
19 | super(...arguments);
20 | }
21 |
22 | /**
23 | * Returns appropriate css class for given width and text/button option.
24 | *
25 | * @param {string} ctaWidth Wideness of given field.
26 | * @param {string} textOrButton Choice of text or button.
27 | *
28 | * @return {string} Appropriate css class based on configuration.
29 | */
30 | layoutClass(ctaWidth, textOrButton) {
31 | if ('two-thirds' == ctaWidth) {
32 | if ('text' == textOrButton) {
33 | return 'col-md-8';
34 | }
35 | return 'col-md-4';
36 | } else if ('three-quarters' == ctaWidth) {
37 | if ('text' == textOrButton) {
38 | return 'col-md-9';
39 | }
40 | return 'col-md-3';
41 | }
42 | }
43 |
44 | render() {
45 | // Setup the attributes
46 | const {
47 | attributes: {
48 | buttonText,
49 | buttonUrl,
50 | buttonBackgroundColor,
51 | buttonTextColor,
52 | buttonSize,
53 | buttonShape,
54 | buttonTarget,
55 | ctaText,
56 | ctaTextColor,
57 | imgURL,
58 | imgAlt,
59 | ctaLayout,
60 | type,
61 | customFontSize,
62 | },
63 | } = this.props;
64 |
65 | return (
66 |
67 | {imgURL && !!imgURL.length && (
68 |
69 |
74 |
75 | )}
76 |
77 |
82 | {ctaText && (
83 |
92 | )}
93 |
94 | {buttonText && (
95 |
120 | )}
121 |
122 | );
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/components/templates-modal/section-templates/templates/watch-embedded-video.js:
--------------------------------------------------------------------------------
1 | export default {
2 | icon: (
3 |
7 | ),
8 | title: 'Watch Embedded Video',
9 | description: '50 Words • Button Link • Video Embed',
10 | markup: `
11 |
44 | `,
45 | };
46 |
--------------------------------------------------------------------------------
/src/blocks/block-image-carousel/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import Edit from './edit';
5 | import Save from './save';
6 | import attributes from './attributes';
7 | import Deprecated from './deprecated';
8 |
9 | /**
10 | * Styles
11 | */
12 | import './styles/style.scss';
13 |
14 | import Icon from '../../../assets/icon-c9-image-carousel.svg';
15 |
16 | import cryptoRandomString from 'crypto-random-string';
17 |
18 | /**
19 | * WordPress dependencies
20 | */
21 | const { __ } = wp.i18n;
22 | const { compose } = wp.compose;
23 | const { withSelect, withDispatch } = wp.data;
24 | const { registerBlockType } = wp.blocks;
25 |
26 | registerBlockType('c9-blocks/image-carousel', {
27 | title: __('C9 Image Carousel', 'c9-blocks'),
28 | icon: Icon,
29 | category: 'c9-blocks',
30 | supports: {
31 | // fill in features
32 | },
33 | keywords: [__('carousel', 'c9-blocks'), __('responsive', 'c9-blocks')],
34 | description: __(
35 | 'Display an animated carousel of images with captions with custom settings for navigation.',
36 | 'c9-blocks'
37 | ),
38 | example: {
39 | viewportWidth: '280',
40 | attributes: {
41 | autoSlide: false,
42 | url: [
43 | 'https://work.covertnine.com/wp-content/uploads/2020/07/clark-young-fQxMGkYXqFU-unsplash-55.jpg',
44 | 'https://work.covertnine.com/wp-content/uploads/2020/07/jezael-melgoza-HYQvV8wWX18-unsplash-55.jpg',
45 | 'https://work.covertnine.com/wp-content/uploads/2020/07/set-of-tool-wrench-162553-55.jpg',
46 | ],
47 | id: [null, null, null],
48 | captionTitle: [
49 | 'Slide Caption Top',
50 | 'Slide Caption Top',
51 | 'Slide Caption Top',
52 | ],
53 | captionContent: [
54 | 'Slide Caption Bottom',
55 | 'Slide Caption Bottom',
56 | 'Slide Caption Bottom',
57 | ],
58 | isResponsive: true,
59 | slideMaxHeight: 640,
60 | slideEqualHeight: true,
61 | },
62 | },
63 | attributes,
64 |
65 | /* Add alignment to block wrapper. */
66 | getEditWrapperProps({ align }) {
67 | if (
68 | 'full' === align ||
69 | 'wide' === align ||
70 | 'narrow' === align ||
71 | '' === align
72 | ) {
73 | return { 'data-align': align };
74 | }
75 | },
76 |
77 | // Render the block components
78 | edit: compose([
79 | withSelect((select, ownProps) => {
80 | const { getBlock, isBlockSelected, hasSelectedInnerBlock } =
81 | select('core/block-editor');
82 |
83 | const { clientId } = ownProps;
84 |
85 | return {
86 | block: getBlock(clientId),
87 | isSelectedBlockInRoot:
88 | isBlockSelected(clientId) || hasSelectedInnerBlock(clientId, true),
89 | instanceId: parseInt(
90 | cryptoRandomString({ length: 4, type: 'numeric' })
91 | ),
92 | };
93 | }),
94 | withDispatch((dispatch) => {
95 | const { updateBlockAttributes, removeBlock, toggleSelection } =
96 | dispatch('core/block-editor');
97 |
98 | return {
99 | updateBlockAttributes,
100 | removeBlock,
101 | onResizeStart: () => toggleSelection(false),
102 | onResizeStop: () => toggleSelection(true),
103 | };
104 | }),
105 | ])(Edit),
106 |
107 | // Save the attributes and markup
108 | save: (props) => {
109 | return ;
110 | },
111 |
112 | deprecated: Deprecated,
113 | });
114 |
--------------------------------------------------------------------------------
/assets/section-template-icons/classic-header-statement-logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/blocks/block-cta/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Internal dependencies
3 | */
4 | import Edit from './edit';
5 | import Save from './save';
6 | import attributes from './attributes';
7 |
8 | /**
9 | * Styles
10 | */
11 | import './styles/style.scss';
12 |
13 | import Icon from '../../../assets/icon-c9-cta-bar.svg';
14 |
15 | /**
16 | * WordPress dependencies
17 | */
18 | const { __ } = wp.i18n;
19 | const { compose } = wp.compose;
20 | const { withSelect } = wp.data;
21 | const { registerBlockType } = wp.blocks;
22 |
23 | registerBlockType('c9-blocks/cta', {
24 | title: __('C9 Call To Action', 'c9-blocks'),
25 | icon: Icon,
26 | category: 'c9-blocks',
27 | keywords: [__('call to action', 'c9-blocks'), __('cta', 'c9-blocks')],
28 |
29 | description: __(
30 | 'Get users to action with stylized text, colors, and buttons in one responsive block.',
31 | 'c9-blocks'
32 | ),
33 |
34 | example: {
35 | viewportWidth: '280',
36 | attributes: {
37 | type: 'c9-h',
38 | buttonText: 'Sign Up Now',
39 | ctaBackgroundColor: '#ededed',
40 | fontSize: 'larger',
41 | customFontSize: 20,
42 | align: 'full',
43 | ctaWidth: 'container-fluid',
44 | ctaText: [
45 | {
46 | type: 'p',
47 | props: {
48 | children: [
49 | 'Use the call to action to entice a user to sign up, navigate to another page, or call attention to what you want them to do next.',
50 | ],
51 | },
52 | },
53 | ],
54 | buttonUrl: '#',
55 | },
56 | },
57 |
58 | attributes: attributes,
59 |
60 | /* Add alignment to block wrapper. */
61 | getEditWrapperProps({ align }) {
62 | if (
63 | 'full' === align ||
64 | 'wide' === align ||
65 | 'narrow' === align ||
66 | '' === align
67 | ) {
68 | return { 'data-align': align };
69 | }
70 | },
71 |
72 | edit: compose([
73 | withSelect((select, ownProps) => {
74 | const { isBlockSelected, hasSelectedInnerBlock } =
75 | select('core/block-editor');
76 |
77 | const { clientId } = ownProps;
78 |
79 | return {
80 | isSelectedBlockInRoot:
81 | isBlockSelected(clientId) || hasSelectedInnerBlock(clientId, true),
82 | };
83 | }),
84 | ])(Edit),
85 |
86 | // Save the attributes and markup
87 | save: Save,
88 |
89 | deprecated: [
90 | {
91 | attributes: {
92 | ...attributes,
93 | ctaPadding: {
94 | type: 'object',
95 | default: {
96 | linked: true,
97 | icon: 'admin-links',
98 | top: '3',
99 | bottom: '3',
100 | left: '3',
101 | right: '3',
102 | },
103 | },
104 | },
105 | save: (props) => {
106 | return ;
107 | },
108 | },
109 | ],
110 | });
111 |
112 | /* Add the container class to the cta block. */
113 | const withClientIdClassName = wp.compose.createHigherOrderComponent(
114 | (BlockListBlock) => {
115 | return (props) => {
116 | const blockName = props.block.name;
117 |
118 | if ('c9-blocks/cta' === blockName) {
119 | return (
120 |
121 | );
122 | } else {
123 | return ;
124 | }
125 | };
126 | },
127 | 'withClientIdClassName'
128 | );
129 |
130 | wp.hooks.addFilter(
131 | 'editor.BlockListBlock',
132 | 'c9-blocks/add-container-class',
133 | withClientIdClassName
134 | );
135 |
--------------------------------------------------------------------------------