Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c652cc3
Sync branch [skip ci]
pirate-bot Sep 10, 2025
5cb8f48
Sync branch [skip ci]
pirate-bot Sep 10, 2025
d720320
chore: Update Google fonts
pirate-bot Sep 15, 2025
1b521a8
Merge pull request #4426 from Codeinwp/ci/update-fonts
selul Sep 17, 2025
3b4c0fd
chore(deps): bump codeinwp/themeisle-sdk from 3.3.48 to 3.3.49
dependabot[bot] Sep 22, 2025
d48e9e5
refactor: header style link interface
girishpanchal30 Oct 29, 2025
fc32064
refactor: change link color
girishpanchal30 Oct 29, 2025
be0a9bd
feat: add obfx modules
girishpanchal30 Nov 4, 2025
ee0d0f7
refactor: update translation strings
girishpanchal30 Nov 4, 2025
ae5f6ff
feat: add new pot diff file
selul Nov 7, 2025
8d121bd
chore: remove redundant line
selul Nov 7, 2025
7f9dc65
Merge pull request #4447 from Codeinwp/feat/pro/3086
selul Nov 7, 2025
5fbdb49
chore: update GitHub Actions workflow for translation diffs
selul Nov 7, 2025
cb8c841
chore: add OpenRouter API key and model to translation diff workflow
selul Nov 7, 2025
1667e82
chore: update OpenRouter model in translation diff workflow
selul Nov 7, 2025
99e4630
refactor: update strings
girishpanchal30 Nov 10, 2025
3bc938a
fix: js lint
girishpanchal30 Nov 10, 2025
edb78a7
Merge pull request #4452 from Codeinwp/fix/translation-string
selul Nov 10, 2025
d52067f
Merge pull request #4443 from Codeinwp/bugfix/pro/3072
selul Nov 10, 2025
fbedfca
Merge pull request #4438 from Codeinwp/dependabot/composer/developmen…
HardeepAsrani Nov 10, 2025
42e00fc
refactor: update translation strings
girishpanchal30 Nov 11, 2025
87e89c9
Merge pull request #4455 from Codeinwp/fix/translation-string
selul Nov 11, 2025
6781306
Merge pull request #4458 from Codeinwp/fix/issue-3065
HardeepAsrani Nov 21, 2025
9075cee
feat: add option to preload fonts (#4457)
HardeepAsrani Nov 21, 2025
a5fd9b1
feat: improve customizer search visibility (#4456)
HardeepAsrani Nov 21, 2025
af90b12
feat: add HFB Pro components in Inserter (#4454)
HardeepAsrani Nov 21, 2025
77e0aba
feat: make Elementor's Page Content widget available to Custom Layout…
HardeepAsrani Nov 21, 2025
760834a
Merge pull request #4440 from Codeinwp/ci/update-fonts
pirate-bot Nov 21, 2025
2308e32
feat: add documentation links (#4442)
girishpanchal30 Nov 21, 2025
415b3d9
feat: improvements to upsell link positioning (#4450)
HardeepAsrani Nov 21, 2025
61eb945
feat: move scroll to top to free version (#4445)
HardeepAsrani Nov 21, 2025
5652e21
Display plan name (#4444)
girishpanchal30 Nov 21, 2025
8cd27f3
feat: add slider on gallery images (#4446)
girishpanchal30 Nov 21, 2025
4a1df3a
feat: add Style Book to Neve's Customizer (#4448)
HardeepAsrani Nov 21, 2025
8630a4c
chore: Update Google fonts (#4460)
pirate-bot Nov 24, 2025
3f8c0c1
feat: add New User Guide to Neve (#4461)
HardeepAsrani Nov 25, 2025
7c81d9f
fix: keep launch progress persistent between tabs
HardeepAsrani Nov 25, 2025
0f9cb92
feat: update themeisle-sdk to version 3.3.50 and enhance label filters
selul Nov 25, 2025
5aa7395
Merge pull request #4462 from Codeinwp/fix/labels
vytisbulkevicius Nov 26, 2025
1c238f6
chore: add Dashboard Customizer to free upsells
HardeepAsrani Nov 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 20 additions & 43 deletions .github/workflows/diff-translations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,71 +5,48 @@ on:
pull_request:
types: [opened, edited, synchronize, ready_for_review]
branches:
- "development"
- "new/**"
- development
- master

jobs:
translation:
runs-on: ubuntu-latest
steps:
- name: Checkout Ref Base
- name: Checkout Base Branch
uses: actions/checkout@v4
with:
path: neve-head
ref: ${{ github.base_ref }}
path: neve-base
- name: Setup node 16
uses: actions/setup-node@v4
with:
node-version: 16.x
- name: FRESH Makepot BASE
- name: Build POT for Base Branch
run: |
cd neve-head
cd neve-base
ls languages/
composer install --no-dev --prefer-dist --no-progress --no-suggest
yarn install --frozen-lockfile
yarn run build
ls languages/
- name: Checkout Ref Head
uses: actions/checkout@v2
- name: Checkout PR Branch (Head)
uses: actions/checkout@v4
with:
ref: development
path: neve-base
- name: FRESH Makepot HEAD
path: neve-head
- name: Build POT for PR Branch
run: |
cd neve-base
cd neve-head
ls languages/
composer install --no-dev --prefer-dist --no-progress --no-suggest
yarn install --frozen-lockfile
yarn run build
ls languages/
- name: Find Comment
uses: peter-evans/find-comment@v1
id: find_coomment
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: "pirate-bot"
body-includes: PR has POT difference
- name: Install PODiff
run: |
curl -o podiff.gz ftp://download.gnu.org.ua/pub/releases/podiff/podiff-1.3.tar.gz
tar -xf podiff.gz
cd podiff-1.3
make
mkdir -p $GITHUB_WORKSPACE/bin
mv ./podiff $GITHUB_WORKSPACE/bin
echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH
cd ..
- name: Run Podiff
id: translation_status
run: |
${GITHUB_WORKSPACE}/neve-head/bin/pot-diff.sh ./neve-base/languages/neve.pot ./neve-head/languages/neve.pot $PERCENT_TRESHOLD
- name: Step require review
if: steps.translation_status.outputs.has_pot_diff != 'success'
uses: Automattic/action-required-review@v2
- name: Compare POT files
uses: Codeinwp/action-i18n-string-reviewer@main
with:
requirements: |
- name: Everything else
paths: unmatched
teams:
- "admin-neve"
status: Has translation changes, a review admin-neve team is required
token: ${{ secrets.BOT_TOKEN }}
fail-on-changes: 'true'
openrouter-key: ${{ secrets.OPEN_ROUTER_API_KEY }}
openrouter-model: 'google/gemini-2.5-flash'
base-pot-file: 'neve-base/languages/neve.pot'
target-pot-file: 'neve-head/languages/neve.pot'
github-token: ${{ secrets.BOT_TOKEN }}
13 changes: 10 additions & 3 deletions assets/apps/components/src/Controls/ColorControl.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import classnames from 'classnames';
const ColorPickerFix = lazy(() => import('../Common/ColorPickerFix'));

const ColorControl = ({
slug = null,
label,
selectedColor,
onChange,
Expand Down Expand Up @@ -52,7 +53,8 @@ const ColorControl = ({
};

const isGlobal = selectedColor && selectedColor.indexOf('var') > -1;
const defaultGradient = 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)';
const defaultGradient =
'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)';

const handleClear = () => {
onChange(defaultValue || '');
Expand All @@ -63,7 +65,10 @@ const ColorControl = ({
const wrapClasses = classnames([
'neve-control-header',
'neve-color-component',
{ 'allows-global': !disableGlobal },
{
'allows-global': !disableGlobal,
[`neve-color-slug-${slug}`]: !!slug,
},
]);

const [gradient, setGradient] = useState(selectedColor);
Expand Down Expand Up @@ -159,7 +164,9 @@ const ColorControl = ({
<div
className="current-color-gradient"
style={{
background: selectedColor || defaultGradient,
background:
selectedColor ||
defaultGradient,
height: '177px',
border: '1px solid #eee',
minWidth: '215px',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useMemo } from 'react';

Check warning on line 1 in assets/apps/customizer-controls/src/builder/components/Builder.tsx

View workflow job for this annotation

GitHub Actions / npm (16.x)

'useMemo' is defined but never used
import { BuilderContentInterface, RowTypes } from '../../@types/utils';
import Row from './Row';
import ResponsiveSwitches from './ResponsiveSwitches';
Expand Down Expand Up @@ -138,7 +138,7 @@
setMobileOverlayDismissed(true);
}}
>
{__('Enable', 'neve-pro-addon')}
{__('Enable', 'neve')}
</Button>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ const ComponentsPopover: React.FC<Props> = ({
});
};

const getFilteredUpsells = () => {
if (!searchQuery) {
return upsells;
}

return upsells.filter(({ name }) => {
return name.toLowerCase().includes(searchQuery);
});
};

const renderItem = (item: ItemInterface, idx: number) => {
if (!item.id) {
return null;
Expand Down Expand Up @@ -113,10 +123,15 @@ const ComponentsPopover: React.FC<Props> = ({
const renderItems = () => {
const themeItems = getSidebarItems();
const boosterItems = getSidebarItems(true);
const filteredUpsells = getFilteredUpsells();

let noComponents = null;

if (themeItems.length === 0 && boosterItems.length === 0) {
if (
themeItems.length === 0 &&
boosterItems.length === 0 &&
filteredUpsells.length === 0
) {
noComponents = (
<div className="no-components">
<span>
Expand Down Expand Up @@ -156,13 +171,13 @@ const ComponentsPopover: React.FC<Props> = ({
)}
</>
)}
{boosterItems.length < 1 && upsells.length > 0 && (
{boosterItems.length < 1 && filteredUpsells.length > 0 && (
<>
<h4>
{__('PRO', 'neve')} {__('Components', 'neve')}
</h4>
<div className="items-popover-list upsell-list">
{upsells.map(({ name, icon }, idx) => {
{filteredUpsells.map(({ name, icon }, idx) => {
return renderUpsell(idx, icon, name);
})}
</div>
Expand Down
84 changes: 84 additions & 0 deletions assets/apps/customizer-controls/src/common/useKeyboardSorting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { useCallback, useRef, useEffect } from '@wordpress/element';

/**
* Custom hook for keyboard-based sorting of list items.
*
* @param {number} index - Current item index in the list
* @param {number} totalItems - Total number of items in the list
* @param {Function} onMove - Callback function to move item (receives fromIndex, toIndex)
* @param {boolean} isActive - External state for whether keyboard mode is active
* @param {Function} setIsActive - Function to set the active state
* @return {Object} Hook state and handlers
*/
const useKeyboardSorting = (
index,
totalItems,
onMove,
isActive,
setIsActive
) => {
const handleRef = useRef(null);
const previousIndexRef = useRef(index);

// Handle keyboard events
const handleKeyDown = useCallback(
(e) => {
if (e.key === ' ' || e.key === 'Spacebar') {
e.preventDefault();
setIsActive(!isActive);
return;
}

if (!isActive) {
return;
}

if (e.key === 'ArrowUp' && index > 0) {
e.preventDefault();
const newIndex = index - 1;
previousIndexRef.current = index;
onMove(index, newIndex);
}

if (e.key === 'ArrowDown' && index < totalItems - 1) {
e.preventDefault();
const newIndex = index + 1;
previousIndexRef.current = index;
onMove(index, newIndex);
}
if (e.key === 'Escape') {
e.preventDefault();
setIsActive(false);
}
},
[isActive, index, totalItems, onMove, setIsActive]
);

const handleBlur = useCallback(() => {
setIsActive(false);
}, [setIsActive]);

useEffect(() => {
if (
isActive &&
handleRef.current &&
previousIndexRef.current !== index
) {
// Small delay to ensure DOM has updated
window.requestAnimationFrame(() => {
if (handleRef.current) {
handleRef.current.focus();
}
});
}
previousIndexRef.current = index;
}, [index, isActive]);

return {
handleRef,
handleKeyDown,
handleBlur,
};
};

export default useKeyboardSorting;
99 changes: 99 additions & 0 deletions assets/apps/customizer-controls/src/controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,59 @@ const initSearchCustomizer = () => {
);
};

const initStyleBookButton = () => {
const headerContainer = document.getElementById('customize-header-actions');

if (!headerContainer) {
return;
}

// Initialize the Style Book state if it doesn't exist
if (!wp.customize.state.has('neveStyleBookOpen')) {
wp.customize.state.create('neveStyleBookOpen', false);
}

// Create the Style Book button
const button = document.createElement('button');
button.name = 'neve-style-book';
button.id = 'neve-style-book';
button.className = 'button-secondary button';
button.title = __('Style Book', 'neve');
button.innerHTML = `
<i class="dashicons dashicons-admin-appearance"></i>
<span class="screen-reader-text">${__('Style Book', 'neve')}</span>
`;

// Add click handler
button.addEventListener('click', (e) => {
e.preventDefault();

// Toggle the state in customizer
const currentState = wp.customize.state('neveStyleBookOpen').get();
const newState = !currentState;
wp.customize.state('neveStyleBookOpen').set(newState);

// Send message to preview
wp.customize.previewer.send('neve-toggle-style-book', newState);
});

// Append to header container
headerContainer.appendChild(button);

// Restore state when preview is ready
wp.customize.previewer.bind('ready', () => {
const currentState = wp.customize.state('neveStyleBookOpen').get();
if (currentState) {
wp.customize.previewer.send('neve-restore-style-book-state', true);
}
});

// Listen for state changes from preview
wp.customize.previewer.bind('neve-style-book-state-changed', (newState) => {
wp.customize.state('neveStyleBookOpen').set(newState);
});
};

const initCustomPagesFocus = () => {
const { sectionsFocus } = window.NeveReactCustomize;
if (sectionsFocus !== undefined) {
Expand Down Expand Up @@ -297,6 +350,50 @@ const checkHasElementorTemplates = () => {
}
};

/**
* Find the Scroll to top button within the customizer preview.
*/
function findScrollToTopBtn() {
const iframeElement = document.querySelector('#customize-preview iframe');

if (!iframeElement) {
return;
}

const scrollToTopBtn =
iframeElement.contentWindow.document.querySelector('#scroll-to-top');

return scrollToTopBtn;
}

/**
* Show the Scroll to Top button as soon as the user enters the section in Customizer.
*/
function previewScrollToTopChanges() {
wp.customize.section('neve_scroll_to_top', (section) => {
section.expanded.bind((isExpanded) => {
const scrollToTopBtn = findScrollToTopBtn();

if (!scrollToTopBtn) {
return;
}

// If Scroll to top customizer section is expanded
if (isExpanded) {
wp.customize.previewer.bind('ready', () => {
wp.customize.previewer.send('nv-opened-stt', true);
});
scrollToTopBtn.style.visibility = 'visible';
scrollToTopBtn.style.opacity = '1';
} else {
// Hide the button when we leave the section
scrollToTopBtn.style.visibility = 'hidden';
scrollToTopBtn.style.opacity = '0';
}
});
});
}

window.wp.customize.bind('ready', () => {
initStarterContentNotice();
initDocSection();
Expand All @@ -311,6 +408,8 @@ window.wp.customize.bind('ready', () => {
initBlogPageFocus();
initSearchCustomizer();
initLocalGoogleFonts();
initStyleBookButton();
previewScrollToTopChanges();
});

window.HFG = {
Expand Down
Loading
Loading