Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
80c9947
Feat: What's New — featured item hero + also-new accordion
avivu Jun 27, 2026
e87078c
fix(notifications): use MUI Badge component for unread count indicator
avivu Jun 27, 2026
14c943d
fix(notifications): revert is_unread usage and fix RTL chip positioning
avivu Jun 27, 2026
71f273e
feat(notifications): show description preview and increase item spacing
avivu Jul 1, 2026
ed0e087
refactor(notifications): code review fixes — PropTypes, hooks, PHP he…
avivu Jul 1, 2026
4347924
fix(admin-top-bar): remove orphaned defaultIsRead prop from BarButton…
avivu Jul 1, 2026
6b1becb
feat(notifications): make divider label configurable via listLabel field
avivu Jul 1, 2026
3fe9d9d
fix(notifications): parse unread_count as integer to fix zero badge d…
avivu Jul 1, 2026
5a1c499
Internal: Bump packages [ED-24759] (#36369)
hein-obox Jul 1, 2026
68ab55c
chore(notifications): remove stale TODO comment
avivu Jul 1, 2026
757d2de
Merge branch 'main' into feature/whats-new-featured-item
avivu Jul 1, 2026
de68c17
fix(notifications): make handleSeen idempotent and guard onSeen with …
avivu Jul 1, 2026
1eb487c
fix(notifications): prevent description preview jump during collapse …
avivu Jul 2, 2026
1535cba
fix(notifications): eliminate collapse animation jump using opacity t…
avivu Jul 2, 2026
3003f6d
fix(notifications): collapse description preview height when expanded
avivu Jul 2, 2026
7ac384a
fix(notifications): remove description preview from collapsed header
avivu Jul 2, 2026
7c752aa
fix(notifications): close drawer on internal CTA in collapsed items
avivu Jul 2, 2026
52f2fc6
Fix: Replace stale WP Admin upgrade UTM with upgrade-one-wp-menu [ED-…
Ntnelbaba Jul 1, 2026
f1dee31
Remove per-event app_type in favor of events-manager super property […
Ntnelbaba Jul 1, 2026
7d9f59b
Internal: Make Format_Component_Elements_Id a common util in AtomicWi…
ronros-elementor Jul 1, 2026
a5b7ff0
Internal: Remove stale branches [ED-18592] (#30874)
Svitlana-Dykun Jul 1, 2026
668b82b
Fix: Defer elementor-kit-mcp schema fetch to avoid 404 on boot [ED-24…
Ntnelbaba Jul 1, 2026
3904487
Feature: Add disabled class state to atomic style states [ED-24827] (…
IshayMaya Jul 2, 2026
2b5bdcb
Fix: composer dependencies (#36408)
mykytamurzin Jul 2, 2026
28f9b08
Fix: Add missing unit to size zod schema [ED-24800] (#36402)
IshayMaya Jul 2, 2026
9215248
tweak(notifications): show description preview in collapsed item header
avivu Jul 7, 2026
ab4d3ac
tweak(notifications): hide description preview when collapsed item is…
avivu Jul 7, 2026
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
131 changes: 131 additions & 0 deletions .github/workflows/remove-stale-branches.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
name: Remove stale branches

on:
schedule:
- cron: '0 3 * * 1'
workflow_dispatch:
inputs:
dry_run:
type: boolean
description: 'Preview only (no stale comments or branch deletions)'
required: false
default: true

permissions:
contents: write
pull-requests: read
actions: read

jobs:
remove-stale-branches:
name: Remove Stale Branches
runs-on: ubuntu-22.04
steps:
- name: Build exempt branches regex
id: pr-list
run: |
set -euo pipefail

pr_branches=$(gh pr list --repo "${{ github.repository }}" --state open --limit 1000 \
--json headRefName -q '.[].headRefName' \
| while IFS= read -r branch; do
[ -n "$branch" ] && printf '%s\n' "$branch" | sed 's/[][\\.^$*+?()|{}]/\\&/g'
done \
| paste -sd '|' -)

version_branch_pattern='main|master|[0-9]+(\.[0-9]+)+([._-].*)?'

if [ -n "$pr_branches" ]; then
exempt_branches_regex="^(${version_branch_pattern}|${pr_branches})$"
else
exempt_branches_regex="^(${version_branch_pattern})$"
fi

echo "exempt_branches_regex=${exempt_branches_regex}" >> "$GITHUB_ENV"
env:
GH_TOKEN: ${{ github.token }}

- name: Remove stale branches except PR branches
uses: fpicalausa/remove-stale-branches@v1.6.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
dry-run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run }}
exempt-branches-regex: ${{ env.exempt_branches_regex }}
exempt-protected-branches: true
stale-branch-message: "@{author} Your branch [{branchName}]({branchUrl}) hasn't been updated in the last {daysBeforeBranchStale} days and is marked as stale. It will be removed in {daysBeforeBranchDelete} days.\r\nIf you want to keep this branch around, delete this comment or add new commits to this branch."
default-recipient: "elementorbot"
days-before-branch-stale: ${{ vars.DAYS_BEFORE_BRANCH_STALE || '90' }}
days-before-branch-delete: ${{ vars.DAYS_BEFORE_STALE_BRANCH_DELETE || '7' }}
operations-per-run: ${{ vars.REMOVE_STALE_BRANCHES_PER_RUN || '10' }}
ignore-unknown-authors: true

- name: Publish stale branch job summary
if: always()
env:
GH_TOKEN: ${{ github.token }}
DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run }}
run: |
set -euo pipefail

JOB_ID="$(gh api "/repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}/jobs" \
--jq '.jobs[] | select(.name == "Remove Stale Branches") | .id')"

gh api "/repos/${GITHUB_REPOSITORY}/actions/jobs/${JOB_ID}/logs" > job-logs.zip
unzip -p job-logs.zip '*Remove stale branches except PR branches*' > action.log 2>/dev/null || true

PARSED="$(mktemp)"
if [ -s action.log ]; then
awk '
function flush() {
if (branch == "") return
if (detail == "") detail = "see workflow logs"
printf "%s\t%s\t%s\n", bucket, branch, detail
branch = bucket = detail = ""
}
/##\[group\]/ {
flush()
header = $0
sub(/^.*##\[group\]/, "", header)
if (sub(/^❌ branch /, "", header)) { bucket = "deleted"; branch = header }
else if (sub(/^✏ branch /, "", header)) { bucket = "marked_stale"; branch = header }
else if (sub(/^😐 branch /, "", header)) { bucket = "kept_stale"; branch = header }
else if (sub(/^✅ branch /, "", header)) { bucket = "skipped"; branch = header }
next
}
/##\[endgroup\]/ { flush(); next }
bucket != "" && $0 !~ /##\[/ {
line = $0
sub(/^[^Z]*Z /, "", line)
if (line ~ /^-> /) detail = substr(line, 4)
else if (bucket == "skipped" && detail == "") detail = line
}
END { flush() }
' action.log > "${PARSED}"
fi

DELETED_COUNT=$(awk -F '\t' '$1 == "deleted" { c++ } END { print c + 0 }' "${PARSED}")
MARKED_STALE_COUNT=$(awk -F '\t' '$1 == "marked_stale" { c++ } END { print c + 0 }' "${PARSED}")
KEPT_STALE_COUNT=$(awk -F '\t' '$1 == "kept_stale" { c++ } END { print c + 0 }' "${PARSED}")
SKIPPED_COUNT=$(awk -F '\t' '$1 == "skipped" { c++ } END { print c + 0 }' "${PARSED}")

{
echo "## Stale branch cleanup"
echo ""
echo "- **Repository:** ${GITHUB_REPOSITORY}"
echo "- **Run ID:** ${GITHUB_RUN_ID}"
echo "- **Dry run:** ${DRY_RUN}"
echo "- **Deleted:** ${DELETED_COUNT}"
echo "- **Marked stale:** ${MARKED_STALE_COUNT}"
echo "- **Kept stale:** ${KEPT_STALE_COUNT}"
echo "- **Skipped:** ${SKIPPED_COUNT}"
echo ""
if [ ! -s action.log ]; then
echo "_Could not parse action logs. Expand the **Remove stale branches except PR branches** step for details._"
else
echo "_Parsed from action step logs. Expand that step for full per-branch output._"
echo ""
echo "| Action | Branch | Detail |"
echo "| --- | --- | --- |"
awk -F '\t' '$1 != "skipped" { printf "| %s | %s | %s |\n", $1, $2, $3 }' "${PARSED}"
fi
} >> "${GITHUB_STEP_SUMMARY}"
1 change: 1 addition & 0 deletions app/assets/js/event-track/dashboard/menu-promotion.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import BaseTracking from './base-tracking';

const PROMO_MENU_ITEMS = {
go_elementor_pro: 'Upgrade',
'elementor-one-upgrade': 'Upgrade',
};

class MenuPromotionTracking extends BaseTracking {
Expand Down
2 changes: 1 addition & 1 deletion assets/dev/js/admin/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import 'elementor-app/event-track/wp-dashboard-tracking';
$importFormFileInput: $( '#elementor-import-template-form input[type="file"]' ),
$settingsForm: $( '#elementor-settings-form' ),
$settingsTabsWrapper: $( '#elementor-settings-tabs-wrapper' ),
$menuGoProLink: $( 'a[href="admin.php?page=go_elementor_pro"]' ),
$menuGoProLink: $( 'a[href="admin.php?page=go_elementor_pro"], a[href*="admin.php?page=elementor-one-upgrade"]' ),
$reMigrateGlobalsButton: $( '.elementor-re-migrate-globals-button' ),
};

Expand Down
1 change: 0 additions & 1 deletion assets/dev/js/editor/document/elements/commands/delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ export class Delete extends $e.modules.editor.document.CommandHistoryBase {
const parentType = parentWidgetType || container.parent?.type || '';

const eventData = {
app_type: 'editor',
window_name: 'editor',
interaction_type: 'click',
target_type: elType,
Expand Down
1 change: 0 additions & 1 deletion assets/dev/js/editor/utils/editor-one-events.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ export class EditorOneEventManager {
static createBasePayload( overrides = {} ) {
const config = this.getConfig();
return {
app_type: config?.appTypes?.editor ?? 'editor',
window_name: config?.appTypes?.editor ?? 'editor',
...overrides,
};
Expand Down
20 changes: 19 additions & 1 deletion assets/dev/scss/admin/_global.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
margin-block-start: 1px;
}

// Menu Go Pro
a[href="admin.php?page=go_elementor_pro"] {
font-weight: 600;
background-color: $wp-admin-brand-color;
Expand All @@ -30,6 +29,25 @@
}
}

#toplevel_page_elementor-home {
a[href*="elementor-one-upgrade"] {
font-weight: 600;
background-color: $wp-admin-brand-color;
color: $white;
margin: 3px 10px 0;
display: block;
text-align: center;
border-radius: $default-border-radius;
transition: $transition-hover;

&:hover,
&:focus {
background-color: lighten($wp-admin-brand-color, 10%);
box-shadow: none;
}
}
}

#menu-posts-elementor_library {

.wp-menu-image {
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"minimum-stability": "stable",
"require": {
"php": ">=7.4",
"elementor/wp-one-package": "1.0.65"
"elementor/wp-one-package": "1.0.66"
},
"repositories": [
{
Expand Down Expand Up @@ -66,6 +66,7 @@
},
"audit": {
"ignore": {
"PKSA-8zx5-v2nz-58pb": "CVE-2026-49981 (sandbox filter, tag and function allow-list bypass when sandbox state changes between renders for a cached template) - we don't enable sandbox.",
"PKSA-sjvz-tbbr-vwth": "CVE-2026-46628 (spaceless filter implicitly marks output as safe) - we only render our twig templates and don't allow users to upload their own templates. Our templates do not use the spaceless filter.",
"PKSA-h8hf-ytnd-5t9q": "CVE-2026-46633 (PHP code injection via {% use %} template name) - template names passed to Twig are hardcoded. No user can inject twig source.",
"PKSA-wwb1-81rc-pd65": "CVE-2026-47730 (XSS in profiler HtmlDumper via unescaped template/profile names) - we don't use Twig's profiler/HtmlDumper.",
Expand Down
8 changes: 4 additions & 4 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion modules/admin-top-bar/assets/js/admin-top-bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default function AdminTopBar() {
{ window.elementorAdminTopBarConfig.is_administrator ? <BarButton onClick={ finderAction } dataInfo={ finderTooltipText } icon="eicon-search-bold">{ __( 'Finder', 'elementor' ) }</BarButton> : '' }
{ window.elementorCloudAdmin ? window.elementorCloudAdmin() : '' }
{ BarButtonNotification
? <BarButtonNotification defaultIsRead={ ! elementorNotifications?.is_unread }>{ __( 'What\'s New', 'elementor' ) }</BarButtonNotification>
? <BarButtonNotification>{ __( 'What\'s New', 'elementor' ) }</BarButtonNotification>
: ''
}
</div>
Expand Down
6 changes: 6 additions & 0 deletions modules/atomic-widgets/styles/style-states.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Style_States {
const CHECKED = 'checked';

const SELECTED = 'e--selected';
const DISABLED = 'e--disabled';

private static function get_pseudo_states(): array {
return [
Expand All @@ -24,6 +25,7 @@ private static function get_pseudo_states(): array {
private static function get_class_states(): array {
return [
self::SELECTED,
self::DISABLED,
];
}

Expand Down Expand Up @@ -93,6 +95,10 @@ public static function get_class_states_map(): array {
'name' => 'selected',
'value' => self::SELECTED,
],
'disabled' => [
'name' => 'disabled',
'value' => self::DISABLED,
],
];
}

Expand Down
52 changes: 52 additions & 0 deletions modules/atomic-widgets/utils/format-element-ids.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Elementor\Modules\AtomicWidgets\Utils;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class Format_Element_Ids {
public static function format( array $elements, array $path ): array {
return array_map( function( $element ) use ( $path ) {
$origin_id = $element['id'];
$nesting_path = [ ...$path, $origin_id ];

$element['id'] = self::hash_string( implode( '_', $nesting_path ), 7 );
$element['origin_id'] = $origin_id;
$element['elements'] = self::format( $element['elements'] ?? [], $nesting_path );

return $element;
}, $elements );
}

/**
* Deterministic djb2-based hash kept in sync with the TypeScript implementation
* in @elementor/utils (packages/packages/libs/utils/src/hash.ts) so that inner
* element ids are consistent between the PHP render and the editor's JS layer.
*
* @param string $str String to hash.
* @param int|null $length Optional desired output length.
* @return string Base-36, lowercase, padded to $length when provided.
*/
public static function hash_string( string $str, ?int $length ): string {
$hash_basis = 5381;

$i = strlen( $str );
while ( $i > 0 ) {
--$i;
$hash_basis = ( $hash_basis * 33 ) ^ ord( $str[ $i ] );
// Keep hash within 32-bit range to match JavaScript bitwise operations.
$hash_basis = $hash_basis & 0xFFFFFFFF;
}

$result = base_convert( (string) $hash_basis, 10, 36 );

if ( ! isset( $length ) ) {
return $result;
}

$sliced = substr( $result, -$length );
return str_pad( $sliced, $length, '0', STR_PAD_LEFT );
}
}
Loading