├── .cache └── .gitkeep ├── .editorconfig ├── .eslintrc.js ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE ├── setup-node │ └── action.yml └── workflows │ ├── deploy.yml │ ├── tests-e2e.yml │ └── tests.yml ├── .gitignore ├── .husky └── pre-commit ├── .nvmrc ├── .prettierignore ├── .prettierrc.js ├── .stylelintignore ├── .stylelintrc.js ├── .vscode ├── extensions.json └── settings.json ├── .wordpress-org ├── banner-1544x500.png ├── banner-772x250.png ├── icon-128x128.png ├── icon-256x256.png ├── screenshot-1.png ├── screenshot-2.png └── screenshot-3.png ├── .wp-env.json ├── CHANGELOG.md ├── LICENSE.txt ├── README.md ├── assets ├── _variables.scss ├── admin │ ├── index.scss │ ├── templates │ │ ├── index.js │ │ └── index.scss │ └── tools │ │ ├── index.js │ │ ├── index.scss │ │ └── tools.js ├── block-builder │ ├── 3rd │ │ └── astra.scss │ ├── block │ │ ├── edit.js │ │ ├── index.js │ │ └── save.js │ ├── boxes │ │ ├── code-preview │ │ │ ├── editor.scss │ │ │ └── index.js │ │ ├── code │ │ │ ├── component-react-ace │ │ │ │ ├── editor.scss │ │ │ │ └── index.js │ │ │ ├── editor.scss │ │ │ ├── fix-css-frame.js │ │ │ └── index.js │ │ ├── condition │ │ │ └── index.js │ │ ├── controls │ │ │ ├── control.js │ │ │ ├── deselect-active-on-click-outside.js │ │ │ ├── editor.scss │ │ │ └── index.js │ │ ├── general │ │ │ └── index.js │ │ ├── selected-control-settings │ │ │ ├── editor.scss │ │ │ ├── index.js │ │ │ └── settings-rows │ │ │ │ ├── control-specific-rows.js │ │ │ │ ├── default.js │ │ │ │ ├── group.js │ │ │ │ ├── help.js │ │ │ │ ├── hide-if-not-selected.js │ │ │ │ ├── index.js │ │ │ │ ├── label.js │ │ │ │ ├── name.js │ │ │ │ ├── placement.js │ │ │ │ ├── required.js │ │ │ │ ├── save-in-meta.js │ │ │ │ ├── translate.js │ │ │ │ ├── type.js │ │ │ │ └── width.js │ │ ├── style-variations │ │ │ └── index.js │ │ ├── supports-ghost-kit │ │ │ └── index.js │ │ ├── supports │ │ │ └── index.js │ │ ├── title │ │ │ ├── editor.scss │ │ │ └── index.js │ │ └── wizard │ │ │ ├── editor.scss │ │ │ ├── icons.js │ │ │ ├── index.js │ │ │ └── templates.js │ ├── index.js │ ├── index.scss │ ├── plugin │ │ └── index.js │ └── store │ │ ├── block-data │ │ ├── actions.js │ │ ├── controls.js │ │ ├── index.js │ │ ├── reducer.js │ │ ├── resolvers.js │ │ └── selectors.js │ │ └── index.js ├── components │ ├── base-control │ │ ├── editor.scss │ │ └── index.js │ ├── block-slug │ │ ├── editor.scss │ │ └── index.js │ ├── box │ │ ├── editor.scss │ │ └── index.js │ ├── copied │ │ ├── editor.scss │ │ └── index.js │ ├── document-tabs │ │ ├── editor.scss │ │ └── index.js │ ├── icon-picker │ │ ├── editor.scss │ │ └── index.js │ ├── modal │ │ ├── editor.scss │ │ └── index.js │ ├── preview-error-boundary │ │ └── index.js │ ├── preview-server-callback │ │ ├── editor.scss │ │ ├── index.js │ │ └── render-block-content.js │ ├── pro-notice │ │ ├── editor.scss │ │ └── index.js │ ├── render-controls │ │ └── index.js │ ├── select │ │ ├── editor.scss │ │ ├── index.js │ │ └── style-provider.js │ ├── tab-panel │ │ ├── editor.scss │ │ └── index.js │ └── tabs │ │ ├── editor.scss │ │ └── index.js ├── editor │ ├── blocks │ │ ├── free │ │ │ ├── edit.js │ │ │ ├── index.js │ │ │ └── save.js │ │ └── main │ │ │ ├── edit.js │ │ │ ├── index.js │ │ │ └── save.js │ ├── extensions │ │ └── block-id.js │ ├── index.js │ ├── index.scss │ ├── plugins │ │ ├── index.js │ │ └── remove-block-with-saved-post-meta │ │ │ ├── index.js │ │ │ └── index.scss │ ├── store │ │ ├── components │ │ │ ├── index.js │ │ │ └── selectors.js │ │ ├── hooks │ │ │ ├── index.js │ │ │ └── selectors.js │ │ ├── index.js │ │ └── utils │ │ │ ├── index.js │ │ │ └── selectors.js │ └── translation.js ├── hooks │ ├── use-all-blocks │ │ └── index.js │ └── use-block-control-props │ │ └── index.js ├── svg │ ├── icon-lazyblocks-black.svg │ └── icon-lazyblocks.svg └── utils │ ├── check-control-validity │ └── index.js │ ├── dnd-kit-custom-pointer-sensor │ └── index.js │ ├── get-control-type-data │ └── index.js │ ├── get-control-value │ └── index.js │ └── get-uid │ └── index.js ├── babel.config.js ├── build ├── admin-style-rtl.css ├── admin-style.css ├── admin-templates-rtl.css ├── admin-templates.asset.php ├── admin-templates.css ├── admin-templates.js ├── admin-tools-rtl.css ├── admin-tools.asset.php ├── admin-tools.css ├── admin-tools.js ├── block-builder-astra-style-rtl.css ├── block-builder-astra-style.css ├── block-builder-rtl.css ├── block-builder.asset.php ├── block-builder.css ├── block-builder.js ├── control-checkbox-rtl.css ├── control-checkbox.asset.php ├── control-checkbox.css ├── control-checkbox.js ├── control-classic-editor-rtl.css ├── control-classic-editor.asset.php ├── control-classic-editor.css ├── control-classic-editor.js ├── control-code-editor-rtl.css ├── control-code-editor.asset.php ├── control-code-editor.css ├── control-code-editor.js ├── control-color-rtl.css ├── control-color.asset.php ├── control-color.css ├── control-color.js ├── control-date-time-rtl.css ├── control-date-time.asset.php ├── control-date-time.css ├── control-date-time.js ├── control-email-rtl.css ├── control-email.asset.php ├── control-email.css ├── control-email.js ├── control-file-rtl.css ├── control-file.asset.php ├── control-file.css ├── control-file.js ├── control-gallery-rtl.css ├── control-gallery.asset.php ├── control-gallery.css ├── control-gallery.js ├── control-image-rtl.css ├── control-image.asset.php ├── control-image.css ├── control-image.js ├── control-inner-blocks-rtl.css ├── control-inner-blocks.asset.php ├── control-inner-blocks.css ├── control-inner-blocks.js ├── control-number-rtl.css ├── control-number.asset.php ├── control-number.css ├── control-number.js ├── control-password-rtl.css ├── control-password.asset.php ├── control-password.css ├── control-password.js ├── control-radio-rtl.css ├── control-radio.asset.php ├── control-radio.css ├── control-radio.js ├── control-range-rtl.css ├── control-range.asset.php ├── control-range.css ├── control-range.js ├── control-repeater-rtl.css ├── control-repeater.asset.php ├── control-repeater.css ├── control-repeater.js ├── control-rich-text-rtl.css ├── control-rich-text.asset.php ├── control-rich-text.css ├── control-rich-text.js ├── control-select-rtl.css ├── control-select.asset.php ├── control-select.css ├── control-select.js ├── control-text-rtl.css ├── control-text.asset.php ├── control-text.css ├── control-text.js ├── control-textarea-rtl.css ├── control-textarea.asset.php ├── control-textarea.css ├── control-textarea.js ├── control-toggle-rtl.css ├── control-toggle.asset.php ├── control-toggle.css ├── control-toggle.js ├── control-undefined-rtl.css ├── control-undefined.asset.php ├── control-undefined.css ├── control-undefined.js ├── control-url-rtl.css ├── control-url.asset.php ├── control-url.css ├── control-url.js ├── editor-rtl.css ├── editor-translation.asset.php ├── editor-translation.js ├── editor.asset.php ├── editor.css └── editor.js ├── classes ├── 3rd │ └── class-astra.php ├── class-admin.php ├── class-assets.php ├── class-blocks.php ├── class-controls.php ├── class-deactivate-duplicate-plugin.php ├── class-deprecated.php ├── class-dummy.php ├── class-force-gutenberg.php ├── class-handlebars.php ├── class-icons.php ├── class-migration.php ├── class-rest.php ├── class-templates.php ├── class-tools.php └── class-wpml.php ├── composer.json ├── composer.lock ├── controls ├── _base │ └── index.php ├── checkbox │ ├── index.php │ └── script.js ├── classic_editor │ ├── index.php │ ├── script.js │ └── tmce.js ├── code_editor │ ├── index.php │ └── script.js ├── color │ ├── color-control.js │ ├── color-palette │ │ └── index.js │ ├── index.php │ └── script.js ├── date_time │ ├── index.php │ └── script.js ├── email │ ├── index.php │ └── script.js ├── file │ ├── file-control.js │ ├── index.php │ └── script.js ├── gallery │ ├── gallery-control.js │ ├── index.php │ └── script.js ├── image │ ├── image-control.js │ ├── index.php │ └── script.js ├── inner_blocks │ ├── index.php │ └── script.js ├── number │ ├── index.php │ └── script.js ├── password │ ├── index.php │ └── script.js ├── radio │ ├── index.php │ └── script.js ├── range │ ├── index.php │ └── script.js ├── repeater │ ├── index.php │ ├── repeater-control.js │ └── script.js ├── rich_text │ ├── index.php │ └── script.js ├── select │ ├── component-choices.js │ ├── index.php │ └── script.js ├── text │ ├── index.php │ └── script.js ├── textarea │ ├── index.php │ └── script.js ├── toggle │ ├── index.php │ └── script.js ├── undefined │ ├── index.php │ └── script.js └── url │ ├── index.php │ └── script.js ├── gulpfile.js ├── index.php ├── languages ├── lazy-blocks.json ├── lazy-blocks.pot └── readme.md ├── lazy-blocks.php ├── lint-staged.config.js ├── package-lock.json ├── package.json ├── phpcs.xml.dist ├── phpunit.xml.dist ├── readme.txt ├── templates └── template-not-found.php ├── tests ├── e2e │ ├── config │ │ ├── flaky-tests-reporter.js │ │ └── global-setup.js │ ├── playwright.config.js │ ├── specs │ │ ├── block-builder-create-block.spec.js │ │ ├── editor-block-attribute-useBlockProps.spec.js │ │ ├── editor-block-base-controls.spec.js │ │ ├── editor-block-component-inner-blocks.spec.js │ │ ├── editor-block-rendering.spec.js │ │ ├── editor-block-repeater-control.spec.js │ │ ├── editor-block-with-frame.spec.js │ │ ├── initial-loading.spec.js │ │ └── widgets-editor-blocks.spec.js │ └── utils │ │ ├── create-block.js │ │ ├── create-control.js │ │ ├── remove-all-blocks.js │ │ └── remove-reusable-blocks.js ├── phpunit │ ├── block-registration-test.php │ ├── block-render-test.php │ ├── bootstrap.php │ └── controls │ │ └── select-control-test.php ├── plugins │ └── gutenberg-test-plugin-disables-the-css-animations │ │ └── gutenberg-test-plugin-disables-the-css-animations.php └── themes │ ├── empty-theme-php │ ├── footer.php │ ├── functions.php │ ├── header.php │ ├── index.php │ ├── sidebar.php │ └── style.css │ └── empty-theme │ ├── functions.php │ ├── index.php │ ├── parts │ └── header.html │ ├── style.css │ ├── templates │ ├── category.html │ ├── index.html │ ├── singular.html │ └── tag.html │ └── theme.json ├── vendors ├── Handlebars │ ├── Arguments.php │ ├── Autoloader.php │ ├── BaseString.php │ ├── Cache.php │ ├── Cache │ │ ├── APC.php │ │ ├── Disk.php │ │ └── Dummy.php │ ├── ChildContext.php │ ├── Context.php │ ├── Handlebars.php │ ├── Helper.php │ ├── Helper │ │ ├── BindAttrHelper.php │ │ ├── EachHelper.php │ │ ├── IfHelper.php │ │ ├── UnlessHelper.php │ │ └── WithHelper.php │ ├── Helpers.php │ ├── Loader.php │ ├── Loader │ │ ├── ArrayLoader.php │ │ ├── FilesystemLoader.php │ │ ├── InlineLoader.php │ │ └── StringLoader.php │ ├── Parser.php │ ├── SafeString.php │ ├── StringWrapper.php │ ├── Template.php │ └── Tokenizer.php └── date_i18n │ └── date_i18n.js └── webpack.config.js /.cache/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nk-crew/lazy-blocks/61d439b600924a29fc41623c879aed23276e7c77/.cache/.gitkeep -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | indent_style = tab 11 | 12 | [*.yml] 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [*.md] 17 | trim_trailing_whitespace = false 18 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['plugin:@wordpress/eslint-plugin/recommended'], 3 | rules: { 4 | '@wordpress/no-unsafe-wp-apis': 0, 5 | }, 6 | settings: { 7 | 'import/core-modules': ['jquery'], 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Enforce Unix newlines 2 | *.css text eol=lf 3 | *.html text eol=lf 4 | *.js text eol=lf 5 | *.jsx text eol=lf 6 | *.json text eol=lf 7 | *.md text eol=lf 8 | *.php text eol=lf 9 | *.rb text eol=lf 10 | *.scss text eol=lf 11 | *.svg text eol=lf 12 | *.txt text eol=lf 13 | *.yml text eol=lf 14 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: [https://www.lazyblocks.com/pro/] 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE: -------------------------------------------------------------------------------- 1 | ### Issue description: 2 | 3 | 4 | ### Lazy Blocks Version: 5 | 6 | 7 | ### WordPress Version: 8 | 9 | 10 | ### Any helpful information to reproduce the issue (screenshots, code parts) 11 | 12 | -------------------------------------------------------------------------------- /.github/setup-node/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Setup Node.js and install npm dependencies' 2 | description: 'Configure Node.js and install npm dependencies while managing all aspects of caching.' 3 | inputs: 4 | node-version: 5 | description: 'Optional. The Node.js version to use. When not specified, the version specified in .nvmrc will be used.' 6 | required: false 7 | type: string 8 | 9 | runs: 10 | using: 'composite' 11 | steps: 12 | - name: Use desired version of Node.js 13 | uses: actions/setup-node@v4 14 | with: 15 | node-version-file: '.nvmrc' 16 | node-version: ${{ inputs.node-version }} 17 | cache: npm 18 | 19 | - name: Get Node.js and npm version 20 | id: node-version 21 | run: | 22 | echo "NODE_VERSION=$(node -v)" >> $GITHUB_OUTPUT 23 | shell: bash 24 | 25 | - name: Cache node_modules 26 | id: cache-node_modules 27 | uses: actions/cache@v4 28 | with: 29 | path: '**/node_modules' 30 | key: node_modules-${{ runner.os }}-${{ steps.node-version.outputs.NODE_VERSION }}-${{ hashFiles('package-lock.json') }} 31 | 32 | - name: Install npm dependencies 33 | if: ${{ steps.cache-node_modules.outputs.cache-hit != 'true' }} 34 | run: npm ci 35 | shell: bash 36 | 37 | # On cache hit, we run the post-install script to match the native `npm ci` behavior. 38 | # An example of this is to patch `node_modules` using patch-package. 39 | - name: Post-install 40 | if: ${{ steps.cache-node_modules.outputs.cache-hit == 'true' }} 41 | run: | 42 | # Run the post-install script for the root project. 43 | npm run postinstall 44 | shell: bash 45 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to WordPress.org 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - 'v*' 8 | 9 | jobs: 10 | deploy: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - name: Disable xDebug - fixes PHP Fatal Error for `i18n make-pot` 16 | uses: shivammathur/setup-php@v2 17 | with: 18 | php-version: '8.1' 19 | coverage: none 20 | 21 | - name: Setup Node.js and install dependencies 22 | uses: ./.github/setup-node 23 | 24 | - name: Run Production Task 25 | run: npm run build:prod 26 | 27 | - name: Install SVN 28 | run: | 29 | sudo apt-get update 30 | sudo apt-get install subversion 31 | 32 | - name: WordPress Plugin Deploy 33 | uses: nk-o/action-wordpress-plugin-deploy@master 34 | env: 35 | SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} 36 | SVN_USERNAME: ${{ secrets.SVN_USERNAME }} 37 | SOURCE_DIR: dist-zip/lazy-blocks/ 38 | SLUG: lazy-blocks 39 | -------------------------------------------------------------------------------- /.github/workflows/tests-e2e.yml: -------------------------------------------------------------------------------- 1 | name: End-to-End Tests 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | # Allow manually triggering the workflow. 9 | workflow_dispatch: 10 | 11 | # Cancels all previous workflow runs for pull requests that have not completed. 12 | concurrency: 13 | # The concurrency group contains the workflow name and the branch name for pull requests 14 | # or the commit hash for any other events. 15 | group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} 16 | cancel-in-progress: true 17 | 18 | jobs: 19 | playwright: 20 | name: Playwright 21 | runs-on: ubuntu-latest 22 | if: ${{ github.repository == 'nk-crew/lazy-blocks' || github.event_name == 'pull_request' }} 23 | 24 | steps: 25 | - uses: actions/checkout@v4 26 | 27 | - name: Setup Node.js and install dependencies 28 | uses: ./.github/setup-node 29 | 30 | - name: Npm build 31 | run: npm run build 32 | 33 | - name: Install Playwright dependencies 34 | run: | 35 | npx playwright install chromium firefox webkit --with-deps 36 | 37 | - name: Install WordPress and start the server 38 | run: | 39 | npm run wp-env start 40 | 41 | - name: Run the tests 42 | run: | 43 | xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test:e2e 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | .phpunit.result.cache 8 | /artifacts 9 | /tests/e2e/artifacts 10 | 11 | # The /.cache folder is needed for phpcs to cache results between runs, while other .cache folders must be ignored 12 | # It is not possible to re-include a file if a parent directory of that file is excluded 13 | # So, both /.cache and /.cache./.gitkeep must be re-included 14 | .cache 15 | !/.cache/ 16 | /.cache/** 17 | !/.cache/.gitkeep 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # Plugin ZIP production build 23 | dist-zip 24 | 25 | # Webpack dev build 26 | build/runtime* 27 | build/*.hot-update.json 28 | build/*.hot-update.js 29 | build/*.hot-update.js.map 30 | 31 | # Compiled binary addons (https://nodejs.org/api/addons.html) 32 | build/Release 33 | 34 | # Composer directories 35 | vendor 36 | 37 | # Custom PHPCS configs 38 | .phpcs.xml 39 | phpcs.xml 40 | 41 | # Dependency directories 42 | node_modules/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Output of `npm pack` 51 | *.tgz 52 | 53 | # Output of `wp-scripts plugin-zip` 54 | *.zip 55 | 56 | # dotenv environment variables file 57 | .env 58 | 59 | # system files 60 | .DS_Store 61 | Thumbs.db 62 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/*.css 2 | **/*.scss 3 | **/*.html 4 | **/*.php 5 | **/*.yml 6 | node_modules 7 | dist 8 | build 9 | vendor 10 | vendors 11 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@wordpress/prettier-config'); 2 | -------------------------------------------------------------------------------- /.stylelintignore: -------------------------------------------------------------------------------- 1 | **/*.js 2 | **/*.jsx 3 | **/*.min.css 4 | **/*.build.css 5 | node_modules 6 | dist 7 | build 8 | vendor 9 | vendors 10 | -------------------------------------------------------------------------------- /.stylelintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: '@wordpress/stylelint-config/scss', 3 | rules: { 4 | 'at-rule-empty-line-before': null, 5 | 'at-rule-no-unknown': null, 6 | 'comment-empty-line-before': null, 7 | 'font-weight-notation': null, 8 | 'max-line-length': null, 9 | 'no-descending-specificity': null, 10 | 'rule-empty-line-before': null, 11 | 'selector-class-pattern': null, 12 | 'value-keyword-case': null, 13 | 'scss/operator-no-unspaced': null, 14 | 'scss/selector-no-redundant-nesting-selector': null, 15 | 'scss/at-import-partial-extension': null, 16 | 'scss/no-global-function-names': null, 17 | 'scss/comment-no-empty': null, 18 | 'scss/at-extend-no-missing-placeholder': null, 19 | 'scss/operator-no-newline-after': null, 20 | 'scss/at-if-closing-brace-newline-after': null, 21 | 'scss/at-else-empty-line-before': null, 22 | 'scss/at-if-closing-brace-space-after': null, 23 | 'no-invalid-position-at-import-rule': null, 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "esbenp.prettier-vscode", 4 | "streetsidesoftware.code-spell-checker", 5 | "editorconfig.editorconfig", 6 | "dbaeumer.vscode-eslint", 7 | "stylelint.vscode-stylelint" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": null, 3 | "[javascript]": { 4 | "editor.defaultFormatter": "esbenp.prettier-vscode" 5 | }, 6 | "[php]": { 7 | "editor.formatOnSave": false, 8 | "editor.defaultFormatter": null 9 | }, 10 | "editor.formatOnSave": true, 11 | "scss.validate": false, 12 | "css.validate": false, 13 | "less.validate": false, 14 | "editor.codeActionsOnSave": { 15 | "source.fixAll.stylelint": "explicit" 16 | }, 17 | "stylelint.validate": [ 18 | "css", 19 | "scss" 20 | ], 21 | "stylelint.snippet": [ 22 | "css", 23 | "scss" 24 | ], 25 | "[json]": { 26 | "editor.defaultFormatter": "esbenp.prettier-vscode" 27 | }, 28 | "search.exclude": { 29 | "**/.git": true, 30 | "**/node_modules": true, 31 | "**/build": true 32 | }, 33 | } -------------------------------------------------------------------------------- /.wordpress-org/banner-1544x500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nk-crew/lazy-blocks/61d439b600924a29fc41623c879aed23276e7c77/.wordpress-org/banner-1544x500.png -------------------------------------------------------------------------------- /.wordpress-org/banner-772x250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nk-crew/lazy-blocks/61d439b600924a29fc41623c879aed23276e7c77/.wordpress-org/banner-772x250.png -------------------------------------------------------------------------------- /.wordpress-org/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nk-crew/lazy-blocks/61d439b600924a29fc41623c879aed23276e7c77/.wordpress-org/icon-128x128.png -------------------------------------------------------------------------------- /.wordpress-org/icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nk-crew/lazy-blocks/61d439b600924a29fc41623c879aed23276e7c77/.wordpress-org/icon-256x256.png -------------------------------------------------------------------------------- /.wordpress-org/screenshot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nk-crew/lazy-blocks/61d439b600924a29fc41623c879aed23276e7c77/.wordpress-org/screenshot-1.png -------------------------------------------------------------------------------- /.wordpress-org/screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nk-crew/lazy-blocks/61d439b600924a29fc41623c879aed23276e7c77/.wordpress-org/screenshot-2.png -------------------------------------------------------------------------------- /.wordpress-org/screenshot-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nk-crew/lazy-blocks/61d439b600924a29fc41623c879aed23276e7c77/.wordpress-org/screenshot-3.png -------------------------------------------------------------------------------- /.wp-env.json: -------------------------------------------------------------------------------- 1 | { 2 | "core": null, 3 | "themes": ["./tests/themes/empty-theme"], 4 | "plugins": [ 5 | ".", 6 | "./tests/plugins/gutenberg-test-plugin-disables-the-css-animations" 7 | ], 8 | "env": { 9 | "tests": { 10 | "mappings": { 11 | "wp-content/themes/empty-theme-php": "./tests/themes/empty-theme-php" 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /assets/_variables.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress. 3 | */ 4 | /* stylelint-disable-next-line scss/at-import-partial-extension */ 5 | @import "../node_modules/@wordpress/base-styles/colors.native"; 6 | @import "../node_modules/@wordpress/base-styles/variables"; 7 | 8 | $radius: 3px !default; 9 | $radius_large: 4px !default; 10 | $radius_box: 8px !default; 11 | 12 | $color_gray_lighten_2: #fbfbfb !default; 13 | $color_gray_lighten: #f4f5f7 !default; 14 | $color_gray: #e6e8eb !default; 15 | $color_gray_darken: #dadbdd !default; 16 | 17 | $color_dark_lighten_2: #a3a5a7 !default; 18 | $color_dark_lighten: #6b6c6e !default; 19 | $color_dark: #515764 !default; 20 | $color_dark_darken: #343536 !default; 21 | 22 | $shadow: 0 5px 10px 0 rgba(0, 0, 0, 4%) !default; 23 | $shadow_small: 0 5px 10px 0 rgba(0, 0, 0, 2%) !default; 24 | -------------------------------------------------------------------------------- /assets/admin/templates/index.scss: -------------------------------------------------------------------------------- 1 | .lzb-template-settings-panel .components-select-control select[multiple] { 2 | height: auto; 3 | padding-right: 8px; 4 | 5 | ~ .components-input-control__suffix { 6 | display: none; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /assets/admin/tools/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Styles. 3 | */ 4 | import './index.scss'; 5 | 6 | /** 7 | * WordPress dependencies. 8 | */ 9 | import { render } from '@wordpress/element'; 10 | 11 | /** 12 | * Internal dependencies 13 | */ 14 | import Tools from './tools'; 15 | 16 | window.addEventListener('load', () => { 17 | render(, document.querySelector('.lazyblocks-tools-page')); 18 | }); 19 | -------------------------------------------------------------------------------- /assets/admin/tools/index.scss: -------------------------------------------------------------------------------- 1 | .lazyblocks-tools-page { 2 | #normal-sortables { 3 | display: flex; 4 | flex-wrap: wrap; 5 | align-items: flex-start; 6 | justify-content: space-between; 7 | 8 | > .postbox-container { 9 | width: calc(50% - 15px); 10 | 11 | @media screen and (max-width: 782px) { 12 | width: 100%; 13 | } 14 | } 15 | } 16 | 17 | .lzb-export-select-items { 18 | padding: 12px; 19 | background-color: #f1f1f1; 20 | border: 1px solid #ccd0d4; 21 | border-radius: 4px; 22 | 23 | .components-toggle-control__label { 24 | padding-top: 3px; 25 | margin-left: 0 !important; 26 | 27 | > span { 28 | margin-top: -3px; 29 | } 30 | } 31 | 32 | .components-toggle-control > .components-base-control__field > .components-flex { 33 | align-items: start; 34 | } 35 | } 36 | 37 | .lzb-export-textarea { 38 | margin-top: 12px; 39 | } 40 | 41 | .lzb-export-textarea textarea { 42 | width: 100%; 43 | min-height: 500px; 44 | } 45 | 46 | .lzb-export-buttons { 47 | margin-top: 12px; 48 | 49 | .button { 50 | position: relative; 51 | } 52 | 53 | .button + .button { 54 | margin-left: 10px; 55 | } 56 | } 57 | 58 | .components-base-control + .components-base-control { 59 | margin-top: 10px; 60 | } 61 | 62 | .components-base-control > .components-base-control__field > .components-base-control__label { 63 | display: block; 64 | margin-bottom: 10px; 65 | font-weight: 600; 66 | } 67 | 68 | .components-toggle-control { 69 | > .components-base-control__field { 70 | display: flex; 71 | } 72 | 73 | .components-form-toggle { 74 | padding-top: 3px; 75 | } 76 | 77 | .components-form-toggle__on, 78 | .components-form-toggle__off { 79 | display: none; 80 | } 81 | 82 | .components-toggle-control__label { 83 | display: inline-flex; 84 | align-items: flex-start; 85 | margin-left: 5px; 86 | word-break: break-word; 87 | 88 | .dashicons, 89 | svg { 90 | display: flex; 91 | align-items: center; 92 | justify-content: center; 93 | width: 24px; 94 | height: 24px; 95 | margin-right: 5px; 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /assets/block-builder/3rd/astra.scss: -------------------------------------------------------------------------------- 1 | .post-type-lazyblocks { 2 | &.ast-highlight-wpblock-onhover .block-editor-block-list__layout .block-editor-block-list__block.is-highlighted, 3 | &.ast-highlight-wpblock-onhover .block-editor-block-list__layout .block-editor-block-list__block:hover { 4 | box-shadow: none; 5 | } 6 | 7 | &.ast-separate-container .edit-post-visual-editor__content-area { 8 | padding: 0 !important; 9 | } 10 | 11 | .edit-post-visual-editor .editor-styles-wrapper > .is-root-container { 12 | padding-top: 0; 13 | } 14 | 15 | .components-panel__body .components-base-control__field { 16 | padding-top: 0; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /assets/block-builder/block/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies. 3 | */ 4 | import { __ } from '@wordpress/i18n'; 5 | import { registerBlockType } from '@wordpress/blocks'; 6 | 7 | /** 8 | * Internal dependencies 9 | */ 10 | import BlockEdit from './edit'; 11 | import BlockSave from './save'; 12 | 13 | /** 14 | * Block Builder 15 | */ 16 | registerBlockType('lzb-block-builder/main', { 17 | apiVersion: 3, 18 | title: __('Block Builder', 'lazy-blocks'), 19 | category: 'design', 20 | supports: { 21 | html: false, 22 | className: false, 23 | customClassName: false, 24 | anchor: false, 25 | inserter: false, 26 | }, 27 | edit: BlockEdit, 28 | save: BlockSave, 29 | }); 30 | -------------------------------------------------------------------------------- /assets/block-builder/block/save.js: -------------------------------------------------------------------------------- 1 | export default function BlockSave() { 2 | return null; 3 | } 4 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/code-preview/editor.scss: -------------------------------------------------------------------------------- 1 | @import "../../../variables"; 2 | 3 | .lzb-block-builder .lzb-block-builder-code-preview { 4 | .lzb-block-builder-code-preview-frame { 5 | padding: 4px; 6 | border: 1px solid #ddd; 7 | border-radius: 4px; 8 | background-color: #fff; 9 | margin-bottom: 8px; 10 | } 11 | 12 | iframe { 13 | width: 100%; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/code/component-react-ace/editor.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../variables"; 2 | 3 | .lazyblocks-component-code-editor, 4 | .ace_autocomplete { 5 | border: 1px solid $color_gray; 6 | border-radius: 8px; 7 | 8 | // fix editor height jumping after init 9 | .ace_text-input, 10 | .ace_gutter-cell, 11 | .ace_gutter-active-line { 12 | min-height: 17px; 13 | } 14 | .ace_gutter-cell { 15 | padding-left: 10px; 16 | } 17 | .ace_gutter, 18 | .ace_gutter-layer, 19 | .ace_gutter-cell { 20 | min-width: 39px !important; 21 | } 22 | 23 | &.ace_editor { 24 | font-family: monospace !important; 25 | line-height: 1.6; 26 | border: 1px solid rgba(0, 0, 0, 7%); 27 | background-color: #fbfbfb; 28 | 29 | .ace_tooltip { 30 | padding: 6px 10px; 31 | background: none; 32 | background-color: #fff; 33 | border: 1px solid $color_gray_lighten; 34 | border-radius: $radius; 35 | box-shadow: $shadow; 36 | } 37 | 38 | // Active line. 39 | .ace_marker-layer .ace_active-line { 40 | border: none; 41 | background: #f2f2f2; 42 | } 43 | 44 | .ace_gutter { 45 | background: #f4f4f4; 46 | 47 | .ace_gutter-active-line { 48 | background-color: #e7e7e7; 49 | } 50 | } 51 | 52 | // Hide print margin line. 53 | .ace_print-margin { 54 | display: none; 55 | } 56 | } 57 | } 58 | 59 | .lazyblocks-component-code-editor { 60 | &.ace_editor { 61 | width: 100%; 62 | } 63 | } 64 | 65 | // For some reason autocompletion popover does not position correctly. 66 | // This is a workaround to fix it. 67 | .ace_autocomplete { 68 | margin-top: 65px; 69 | 70 | &[style*="bottom"] { 71 | margin-top: 0; 72 | margin-bottom: -60px; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/code/editor.scss: -------------------------------------------------------------------------------- 1 | @import "../../../variables"; 2 | 3 | .lzb-block-builder .lzb-block-builder-custom-code-settings { 4 | .components-base-control__field { 5 | margin-bottom: 0; 6 | } 7 | 8 | p.description { 9 | margin-top: 0; 10 | margin-bottom: 10px; 11 | font-family: inherit; 12 | font-size: 1em; 13 | 14 | &:last-child { 15 | margin-bottom: 0; 16 | } 17 | } 18 | } 19 | 20 | .lzb-block-builder-custom-code-dropdown-content > div { 21 | width: 276px; 22 | } 23 | .lzb-block-builder-output-code-toolbar, 24 | .lzb-block-builder-theme-template-toolbar { 25 | display: flex; 26 | align-items: center; 27 | margin-bottom: 4px; 28 | 29 | > div:first-of-type + * { 30 | margin-left: auto; 31 | } 32 | .components-button { 33 | padding: 0 7px; 34 | } 35 | } 36 | 37 | .lzb-block-builder-output-code-wrapper, 38 | .lzb-block-builder-theme-template-wrapper { 39 | padding: 4px; 40 | border: 1px solid #ddd; 41 | border-radius: 4px; 42 | background-color: #fff; 43 | margin-bottom: 8px; 44 | 45 | .components-custom-select-control { 46 | display: inline-flex; 47 | margin-bottom: 5px; 48 | 49 | .components-input-control__container, 50 | .components-input-control__container > button { 51 | background-color: transparent; 52 | } 53 | div.components-input-control__backdrop { 54 | border: none; 55 | } 56 | .components-input-control__container > button { 57 | height: 21px; 58 | padding-left: 12px; 59 | font-weight: 500; 60 | 61 | + div { 62 | min-width: 170px; 63 | } 64 | 65 | .components-custom-select-control__item { 66 | padding: 3px 10px; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/code/fix-css-frame.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies 3 | */ 4 | import { useEffect, useRef } from '@wordpress/element'; 5 | 6 | const STYLE_IDS = [ 7 | 'autocompletion.css', 8 | 'snippets.css', 9 | 'error_marker.css', 10 | 'ace-tm', 11 | 'ace_editor.css', 12 | 'ace_scrollbar.css', 13 | ]; 14 | 15 | export default function FixCssFrame() { 16 | const codeWrapper = useRef(); 17 | 18 | // Find available styles and save it to the state. 19 | useEffect(() => { 20 | const element = codeWrapper.current; 21 | 22 | if (!element) { 23 | return; 24 | } 25 | 26 | // Don't run this fix if not inside iframe. 27 | if (element.ownerDocument === document) { 28 | return; 29 | } 30 | 31 | const documentFrame = element.ownerDocument; 32 | 33 | STYLE_IDS.forEach((id) => { 34 | const styleTag = document.getElementById(id); 35 | 36 | if (!styleTag) { 37 | return; 38 | } 39 | 40 | const frameStyleTag = documentFrame.getElementById(id); 41 | 42 | if (frameStyleTag) { 43 | return; 44 | } 45 | 46 | documentFrame.head.appendChild(styleTag.cloneNode(true)); 47 | }); 48 | }, [codeWrapper]); 49 | 50 | return ; 51 | } 52 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/controls/deselect-active-on-click-outside.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies. 3 | */ 4 | import { useEffect, useRef } from '@wordpress/element'; 5 | import { select, dispatch } from '@wordpress/data'; 6 | 7 | export default function DeselectActiveControlOnClickOutside() { 8 | const ref = useRef(); 9 | 10 | useEffect(() => { 11 | const element = ref.current; 12 | 13 | if (!element) { 14 | return; 15 | } 16 | 17 | const doc = element.ownerDocument; 18 | 19 | if (!doc) { 20 | return; 21 | } 22 | 23 | const maybeDeselect = (e) => { 24 | const selectedControlId = select( 25 | 'lazy-blocks/block-data' 26 | ).getSelectedControlId(); 27 | 28 | if (!selectedControlId) { 29 | return; 30 | } 31 | 32 | // click outside of content. 33 | if ( 34 | !e.target.closest( 35 | '.edit-post-layout__content, .editor-styles-wrapper' 36 | ) 37 | ) { 38 | return; 39 | } 40 | 41 | // click on notice. 42 | if (e.target.closest('.components-notice-list')) { 43 | return; 44 | } 45 | 46 | // click on control. 47 | if (e.target.closest('.lzb-block-builder-controls-item')) { 48 | return; 49 | } 50 | 51 | // click on code box. 52 | if (e.target.closest('.lazyblocks-component-box')) { 53 | return; 54 | } 55 | 56 | // click on add control button. 57 | if ( 58 | e.target.classList.contains( 59 | 'lzb-block-builder-controls-item-appender' 60 | ) 61 | ) { 62 | return; 63 | } 64 | 65 | const { clearSelectedControl } = dispatch('lazy-blocks/block-data'); 66 | 67 | // clear selected control. 68 | clearSelectedControl(); 69 | }; 70 | 71 | doc.addEventListener('click', maybeDeselect); 72 | 73 | return () => { 74 | doc.removeEventListener('click', maybeDeselect); 75 | }; 76 | }, [ref]); 77 | 78 | return ; 79 | } 80 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/selected-control-settings/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Styles. 3 | */ 4 | import './editor.scss'; 5 | 6 | /** 7 | * WordPress dependencies. 8 | */ 9 | import { __ } from '@wordpress/i18n'; 10 | import { PanelBody } from '@wordpress/components'; 11 | import { useSelect, useDispatch } from '@wordpress/data'; 12 | 13 | /** 14 | * Internal dependencies. 15 | */ 16 | import SettingsRows from './settings-rows'; 17 | 18 | export default function SelectedControlSettings() { 19 | const { id, data } = useSelect((select) => { 20 | const { getSelectedControlId, getSelectedControl } = select( 21 | 'lazy-blocks/block-data' 22 | ); 23 | 24 | return { 25 | id: getSelectedControlId(), 26 | data: getSelectedControl(), 27 | }; 28 | }, []); 29 | 30 | const { updateControlData } = useDispatch('lazy-blocks/block-data'); 31 | 32 | return ( 33 |
34 | {id && data ? ( 35 | { 37 | updateControlData(optionalId || id, newData); 38 | }} 39 | data={data} 40 | id={id} 41 | /> 42 | ) : ( 43 | 44 | {__('Select control to see settings.', 'lazy-blocks')} 45 | 46 | )} 47 |
48 | ); 49 | } 50 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/selected-control-settings/settings-rows/control-specific-rows.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies. 3 | */ 4 | import { applyFilters } from '@wordpress/hooks'; 5 | 6 | export default function ControlSpecificRows(props) { 7 | const result = applyFilters( 8 | `lzb.constructor.control.${props.data.type}.settings`, 9 | '', 10 | props 11 | ); 12 | 13 | return applyFilters('lzb.constructor.control.settings', result, props); 14 | } 15 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/selected-control-settings/settings-rows/default.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies. 3 | */ 4 | import { __ } from '@wordpress/i18n'; 5 | import { PanelBody, TextControl, TextareaControl } from '@wordpress/components'; 6 | 7 | export default function DefaultRow(props) { 8 | const { updateData, data } = props; 9 | 10 | let ControlType = TextControl; 11 | 12 | switch (data.type) { 13 | case 'classic_editor': 14 | case 'code_editor': 15 | case 'rich_text': 16 | case 'textarea': 17 | ControlType = TextareaControl; 18 | break; 19 | // no default 20 | } 21 | 22 | return ( 23 | 24 | updateData({ default: value })} 29 | __next40pxDefaultSize 30 | __nextHasNoMarginBottom 31 | /> 32 | 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/selected-control-settings/settings-rows/group.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies. 3 | */ 4 | import { __ } from '@wordpress/i18n'; 5 | import { PanelBody, BaseControl, SelectControl } from '@wordpress/components'; 6 | 7 | export default function GroupRow(props) { 8 | const { updateData, data } = props; 9 | 10 | return ( 11 | 12 | 17 | 26 | updateData({ 27 | group: value, 28 | }) 29 | } 30 | __next40pxDefaultSize 31 | __nextHasNoMarginBottom 32 | /> 33 | 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/selected-control-settings/settings-rows/help.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies. 3 | */ 4 | import { __ } from '@wordpress/i18n'; 5 | import { PanelBody, TextareaControl } from '@wordpress/components'; 6 | 7 | export default function HelpRow(props) { 8 | const { updateData, data } = props; 9 | 10 | return ( 11 | 12 | updateData({ help: value })} 17 | __nextHasNoMarginBottom 18 | /> 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/selected-control-settings/settings-rows/hide-if-not-selected.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies. 3 | */ 4 | import { __ } from '@wordpress/i18n'; 5 | import { PanelBody, BaseControl, ToggleControl } from '@wordpress/components'; 6 | 7 | export default function HideIfNotSelectedRow(props) { 8 | const { updateData, data } = props; 9 | 10 | return ( 11 | 12 | 17 | 22 | updateData({ 23 | hide_if_not_selected: value ? 'true' : 'false', 24 | }) 25 | } 26 | __nextHasNoMarginBottom 27 | /> 28 | 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/selected-control-settings/settings-rows/label.js: -------------------------------------------------------------------------------- 1 | /** 2 | * External dependencies. 3 | */ 4 | import slugify from 'slugify'; 5 | 6 | /** 7 | * WordPress dependencies. 8 | */ 9 | import { __ } from '@wordpress/i18n'; 10 | import { PanelBody, TextControl } from '@wordpress/components'; 11 | 12 | /** 13 | * Internal dependencies. 14 | */ 15 | import getControlTypeData from '../../../../utils/get-control-type-data'; 16 | 17 | export default function LabelRow(props) { 18 | const { updateData, data } = props; 19 | 20 | function generateUniqueName() { 21 | const { label = '', name = '' } = data; 22 | 23 | if (!label || name) { 24 | return; 25 | } 26 | 27 | updateData({ 28 | name: slugify(label, { 29 | replacement: '-', 30 | lower: true, 31 | remove: /[^\w\s$0-9-*+~.$(_)#&|'"!:;@/\\]/g, 32 | }), 33 | }); 34 | } 35 | 36 | const { label = '', placeholder, alongside_text: alongsideText } = data; 37 | 38 | const controlTypeData = getControlTypeData(data.type); 39 | const allowNameUpdate = controlTypeData.restrictions.name_settings; 40 | 41 | return ( 42 | 43 | updateData({ label: value })} 56 | onBlur={allowNameUpdate ? generateUniqueName : () => {}} 57 | // eslint-disable-next-line jsx-a11y/no-autofocus 58 | autoFocus 59 | __next40pxDefaultSize 60 | __nextHasNoMarginBottom 61 | /> 62 | 63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/selected-control-settings/settings-rows/name.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies. 3 | */ 4 | import { __ } from '@wordpress/i18n'; 5 | import { useState, useEffect } from '@wordpress/element'; 6 | import { PanelBody, TextControl, Notice } from '@wordpress/components'; 7 | 8 | function checkNameSlug(slug) { 9 | return /^[A-Za-z0-9-_]*$/.test(slug); 10 | } 11 | 12 | export default function NameRow(props) { 13 | const [isNameValid, setIsNameValid] = useState(true); 14 | 15 | const { updateData, data } = props; 16 | 17 | const { name = '' } = data; 18 | 19 | useEffect(() => { 20 | const isValid = checkNameSlug(name); 21 | 22 | if (isValid !== isNameValid) { 23 | setIsNameValid(isValid); 24 | } 25 | }, [isNameValid, name]); 26 | 27 | return ( 28 | 29 | updateData({ name: value })} 33 | __next40pxDefaultSize 34 | __nextHasNoMarginBottom 35 | /> 36 | {!isNameValid ? ( 37 | 42 | {__( 43 | 'Control name must include only alphanumeric characters, dashes or underscores. Example: my-control-name', 44 | 'lazy-blocks' 45 | )} 46 | 47 | ) : ( 48 | '' 49 | )} 50 | 51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/selected-control-settings/settings-rows/required.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies. 3 | */ 4 | import { __ } from '@wordpress/i18n'; 5 | import { PanelBody, BaseControl, ToggleControl } from '@wordpress/components'; 6 | 7 | export default function RequiredRow(props) { 8 | const { updateData, data } = props; 9 | 10 | return ( 11 | 12 | 17 | 22 | updateData({ required: value ? 'true' : 'false' }) 23 | } 24 | __nextHasNoMarginBottom 25 | /> 26 | 27 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/selected-control-settings/settings-rows/save-in-meta.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies. 3 | */ 4 | import { __ } from '@wordpress/i18n'; 5 | import { 6 | PanelBody, 7 | BaseControl, 8 | Button, 9 | ToggleControl, 10 | TextControl, 11 | } from '@wordpress/components'; 12 | 13 | const { plugin_version: pluginVersion } = window.lazyblocksBlockBuilderData; 14 | 15 | export default function SaveInMetaRow(props) { 16 | const { updateData, data } = props; 17 | 18 | return ( 19 | 20 | 33 | {__('How to use?', 'lazy-blocks')} 34 | 35 | } 36 | __nextHasNoMarginBottom 37 | > 38 | 42 | updateData({ save_in_meta: value ? 'true' : 'false' }) 43 | } 44 | __nextHasNoMarginBottom 45 | /> 46 | 47 | {data.save_in_meta === 'true' ? ( 48 | 52 | updateData({ save_in_meta_name: value }) 53 | } 54 | placeholder={ 55 | data.name || __('Unique metabox name', 'lazy-blocks') 56 | } 57 | __next40pxDefaultSize 58 | __nextHasNoMarginBottom 59 | /> 60 | ) : ( 61 | '' 62 | )} 63 | 64 | ); 65 | } 66 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/selected-control-settings/settings-rows/translate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies. 3 | */ 4 | import { __ } from '@wordpress/i18n'; 5 | import { PanelBody, BaseControl, ToggleControl } from '@wordpress/components'; 6 | 7 | export default function WPMLRow(props) { 8 | const { updateData, data } = props; 9 | 10 | return ( 11 | 12 | 17 | 22 | updateData({ translate: value ? 'true' : 'false' }) 23 | } 24 | __nextHasNoMarginBottom 25 | /> 26 | 27 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/selected-control-settings/settings-rows/width.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies. 3 | */ 4 | import { __ } from '@wordpress/i18n'; 5 | import { 6 | PanelBody, 7 | BaseControl, 8 | ButtonGroup, 9 | Button, 10 | } from '@wordpress/components'; 11 | 12 | export default function WidthRow(props) { 13 | const { updateData, data } = props; 14 | 15 | const widths = { 16 | 25: __('25%', 'lazy-blocks'), 17 | 50: __('50%', 'lazy-blocks'), 18 | 75: __('75%', 'lazy-blocks'), 19 | 100: __('100%', 'lazy-blocks'), 20 | }; 21 | let thereIsActive = false; 22 | 23 | return ( 24 | 25 | updateData({ width: value })} 30 | __nextHasNoMarginBottom 31 | > 32 |
33 | 34 | {Object.keys(widths).map((w) => { 35 | let isActive = w === data.width; 36 | 37 | if (!thereIsActive && isActive) { 38 | thereIsActive = isActive; 39 | } 40 | 41 | if (!thereIsActive && w === '100') { 42 | isActive = true; 43 | } 44 | 45 | return ( 46 | 56 | ); 57 | })} 58 | 59 | 60 | 61 | ); 62 | } 63 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/style-variations/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * WordPress dependencies. 3 | */ 4 | import { __ } from '@wordpress/i18n'; 5 | 6 | /** 7 | * Internal dependencies. 8 | */ 9 | import ComponentChoices from '../../../../controls/select/component-choices'; 10 | 11 | export default function StyleVariationsSettings(props) { 12 | const { data, updateData } = props; 13 | const { styles } = data; 14 | 15 | return ( 16 | updateData({ styles: val })} 28 | options={[ 29 | { 30 | name: 'name', 31 | label: __('Name', 'lazy-blocks'), 32 | }, 33 | { 34 | name: 'label', 35 | label: __('Label', 'lazy-blocks'), 36 | }, 37 | ]} 38 | /> 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/title/editor.scss: -------------------------------------------------------------------------------- 1 | @import "../../../variables"; 2 | 3 | .lzb-block-builder .lzb-block-builder-title { 4 | // block title. 5 | max-width: 800px; 6 | padding: 20px 0; 7 | margin-right: auto; 8 | margin-bottom: 10px; 9 | margin-left: auto; 10 | overflow: hidden; 11 | 12 | textarea { 13 | display: block; 14 | width: 100%; 15 | font: inherit; 16 | font-size: 18px !important; 17 | font-weight: 500; 18 | border: none; 19 | outline: none; 20 | box-shadow: none; 21 | resize: none; 22 | 23 | &::placeholder { 24 | color: #ccc; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /assets/block-builder/boxes/title/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Styles. 3 | */ 4 | import './editor.scss'; 5 | 6 | /** 7 | * External dependencies. 8 | */ 9 | import slugify from 'slugify'; 10 | 11 | /** 12 | * WordPress dependencies. 13 | */ 14 | import { __ } from '@wordpress/i18n'; 15 | import { useRef, useEffect } from '@wordpress/element'; 16 | import { useSelect } from '@wordpress/data'; 17 | import { useEntityProp } from '@wordpress/core-data'; 18 | 19 | const REGEXP_NEWLINES = /[\r\n]+/g; 20 | 21 | export default function TitleSettings(props) { 22 | const textareaRef = useRef(); 23 | 24 | const { data, updateData } = props; 25 | const { slug } = data; 26 | 27 | const { postType } = useSelect((select) => { 28 | const { getCurrentPostType } = select('core/editor'); 29 | 30 | return { 31 | postType: getCurrentPostType(), 32 | }; 33 | }, []); 34 | 35 | const [postTitle, setPostTitle] = useEntityProp( 36 | 'postType', 37 | postType, 38 | 'title' 39 | ); 40 | 41 | function maybeAddSlug() { 42 | if (slug || !postTitle) { 43 | return; 44 | } 45 | 46 | const newSlug = slugify(postTitle, { 47 | replacement: '-', 48 | lower: true, 49 | remove: /[^\w\s$0-9-*+~.$(_)#&|'"!:;@/\\]/g, 50 | }); 51 | 52 | updateData({ 53 | slug: newSlug, 54 | }); 55 | } 56 | 57 | // Set automatic height. 58 | useEffect(() => { 59 | if (textareaRef.current) { 60 | // We need to reset the height momentarily to get the correct scrollHeight for the textarea 61 | textareaRef.current.style.height = '0px'; 62 | const scrollHeight = textareaRef.current.scrollHeight; 63 | 64 | // We then set the height directly, outside of the render loop 65 | // Trying to set this with state or a ref will product an incorrect value. 66 | textareaRef.current.style.height = `${scrollHeight}px`; 67 | } 68 | }, [textareaRef, postTitle]); 69 | 70 | return ( 71 |
72 |