refactor: entity selector full overhaul — Mar 2026

- Unified _setBadgeCount for ALL badge updates
- target-conditions-trait → entity-selector-trait
- target-* → es-* class rename (20+ classes)
- SCSS recompiled: zero duplicate selectors
- CSS transitions replace jQuery slideDown/slideUp
- Serialize cache, method swap cache
- Badge: no-matches gray, consistent hover, no blending
- Inline condition count always visible
- Preview popover refreshes in-place on sort change
- Categories add chips immediately
- Entity type icons on chips
- Consistent info_outline icons via buildHelpIcon
- Method dropdown text clipping fix (line-height)
- mpr-input-compact on all inputs
- Dropdown padding fixed in SCSS source
- Chips wrapper: same container always
- Reusable helpers: _buildEmptyState, _buildSearchBoxHtml, _buildInfoTooltip
- Asset path: uses $this->module->getPathUri() not reflection
- Debug logs removed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 18:05:43 +00:00
parent d2d4f96c5e
commit c6fd5cee13
38 changed files with 7670 additions and 8929 deletions

View File

@@ -7,7 +7,6 @@
@use '../variables' as *;
@use '../mixins' as *;
.target-conditions-trait,
.entity-selector-trait {
// Chips container wrapper with toolbar
@@ -332,7 +331,7 @@
color: darken($es-primary, 10%);
}
i {
i.material-icons {
font-size: 14px;
}
}
@@ -343,16 +342,6 @@
word-break: break-word;
}
.chip-attrs {
font-size: 0.85em;
opacity: 0.7;
margin-left: 2px;
&::before {
content: '';
}
}
.chip-remove {
@include button-reset;
display: flex;
@@ -831,7 +820,7 @@
color: $es-text-secondary;
}
i {
i.material-icons {
font-size: 18px;
}
}
@@ -853,7 +842,7 @@
color: $es-text-muted;
font-size: $es-font-size-sm;
i {
i.material-icons {
font-size: 20px;
}
@@ -868,7 +857,7 @@
padding: $es-spacing-xl 0;
color: $es-text-muted;
i {
i.material-icons {
font-size: 48px;
opacity: 0.4;
margin-bottom: $es-spacing-sm;
@@ -978,7 +967,7 @@
border-bottom: 1px solid $es-border-color;
background: $es-slate-50;
i {
i.material-icons {
font-size: 18px;
color: $es-text-muted;
}
@@ -1015,7 +1004,6 @@
#content.bootstrap,
#content .bootstrap,
.bootstrap #content {
.target-conditions-trait,
.entity-selector-trait {
.chips-wrapper .chips-toolbar {
// Double class for extra specificity

View File

@@ -7,7 +7,6 @@
@use '../variables' as *;
@use '../mixins' as *;
.target-conditions-trait,
.entity-selector-trait {
// Main container

View File

@@ -6,16 +6,15 @@
@use '../variables' as *;
@use '../mixins' as *;
.target-conditions-trait,
.entity-selector-trait {
// Search wrapper
.target-search-wrapper {
.es-search-wrapper {
position: relative;
}
// Search dropdown
.target-search-dropdown {
.es-search-dropdown {
@include dropdown-container;
display: none;
width: 600px;
@@ -117,7 +116,7 @@
// Results container
.dropdown-results {
padding: 0 $es-spacing-sm;
padding: 0;
}
// Results count text
@@ -159,12 +158,12 @@
}
// Result item (both class names for compatibility)
// Note: Main dropdown-item styling is in the global .target-search-dropdown section below
// Note: Main dropdown-item styling is in the global .es-search-dropdown section below
.dropdown-result-item {
display: flex;
align-items: center;
gap: $es-spacing-sm;
padding: $es-spacing-sm 0;
padding: $es-spacing-sm;
background: $es-white;
border: none;
border-bottom: 1px solid $es-border-color;
@@ -359,20 +358,6 @@
gap: $es-spacing-sm;
}
// Combination-level search results ('both' mode)
.dropdown-item.is-combination {
padding-left: 28px;
.result-name {
font-size: 0.9em;
}
}
.dropdown-item.is-parent-product {
background: $es-slate-50;
font-weight: $es-font-weight-medium;
}
// No results state
.no-results {
display: flex;
@@ -616,7 +601,6 @@
}
// Category tree view
.target-conditions-trait,
.entity-selector-trait {
.category-tree {
padding: $es-spacing-sm;
@@ -884,8 +868,8 @@
// Global dropdown styles (when appended to body instead of inside wrapper)
// Duplicates key styles for when dropdown is outside .entity-selector-trait
// =============================================================================
body > .target-search-dropdown,
.target-search-dropdown {
body > .es-search-dropdown,
.es-search-dropdown {
@include dropdown-container;
display: none;
width: 600px;
@@ -1304,9 +1288,50 @@ body > .target-search-dropdown,
font-weight: $es-font-weight-medium;
}
// Count with eye icon (like group-count-badge)
.toggle-count {
display: inline-flex;
align-items: center;
gap: 0.125rem;
color: $es-text-muted;
font-size: 0.65rem;
i {
font-size: 10px;
color: $es-primary;
}
// Clickable preview badge
&.clickable {
cursor: pointer;
padding: 0.125rem 0.25rem;
border-radius: $es-radius-sm;
transition: all $es-transition-fast;
&:hover {
background: rgba($es-primary, 0.1);
color: $es-primary;
i {
color: $es-primary;
}
}
&.popover-open {
background: $es-primary;
color: $es-white;
i {
color: $es-white;
}
}
&.loading {
i {
animation: spin 0.6s linear infinite;
}
}
}
}
}
@@ -1399,67 +1424,6 @@ body > .target-search-dropdown,
color: rgba(255, 255, 255, 0.8);
}
// Filter chip wrapper (chip/toggle + preview button)
.filter-chip-wrapper {
display: inline-flex;
align-items: stretch;
border-radius: $es-radius-sm;
overflow: hidden;
// Left element gets left-only border-radius
.filter-chip,
.filter-group-toggle {
border-radius: $es-radius-sm 0 0 $es-radius-sm;
}
// Preview eye button — unified for both value chips and group toggles
.chip-preview-btn {
@include button-reset;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0 0.375rem;
font-size: 10px;
color: $es-text-muted;
background: $es-slate-100;
border-left: 1px solid $es-border-color;
border-radius: 0 $es-radius-sm $es-radius-sm 0;
cursor: pointer;
transition: all $es-transition-fast;
&:hover {
background: rgba($es-primary, 0.1);
color: $es-primary;
}
&.popover-open {
background: $es-primary;
color: $es-white;
}
&.loading i {
animation: spin 0.6s linear infinite;
}
}
// When no preview button, restore full border-radius
.filter-chip:last-child,
.filter-group-toggle:last-child {
border-radius: $es-radius-sm;
}
// Group toggle active/has-selection states propagate to wrapper border
.filter-group-toggle.active + .chip-preview-btn {
border-left-color: $es-primary;
background: rgba($es-primary, 0.05);
}
.filter-group-toggle.has-selection + .chip-preview-btn {
border-left-color: $es-success;
background: rgba($es-success, 0.03);
}
}
// Dropdown content
.dropdown-content {
max-height: 400px;
@@ -1787,7 +1751,7 @@ body > .target-search-dropdown,
// Results container
.dropdown-results {
padding: 0 $es-spacing-sm;
padding: 0;
background: $es-white;
min-height: 200px;
}
@@ -1798,7 +1762,7 @@ body > .target-search-dropdown,
display: flex;
align-items: center;
gap: $es-spacing-sm;
padding: $es-spacing-sm 0;
padding: $es-spacing-sm;
background: $es-white;
border: none;
border-bottom: 1px solid $es-border-color;
@@ -2295,15 +2259,15 @@ body > .target-search-dropdown,
// ============================================================================
// Standalone dropdown styles (for when dropdown is appended to body)
// These selectors work because .target-search-dropdown is on the dropdown itself
// These selectors work because .es-search-dropdown is on the dropdown itself
// ============================================================================
.target-search-dropdown {
.es-search-dropdown {
// Results container - scrollable
.dropdown-results {
max-height: 400px;
overflow-y: auto;
padding: 0 $es-spacing-sm;
padding: 0;
@include custom-scrollbar;
}
@@ -2385,7 +2349,7 @@ body > .target-search-dropdown,
display: flex;
align-items: center;
gap: $es-spacing-sm;
padding: 0;
padding: $es-spacing-sm;
border: none;
border-bottom: 1px solid $es-border-color;
border-radius: 0;
@@ -2559,7 +2523,7 @@ body > .target-search-dropdown,
}
// Body-level dropdown (when appended to body for z-index)
body > .target-search-dropdown {
body > .es-search-dropdown {
// Override dropdown-item border when inside body-appended dropdown
.dropdown-item {
border: none;

View File

@@ -6,8 +6,7 @@
@use '../variables' as *;
@use '../mixins' as *;
// Main wrapper (supports both .target-conditions-trait and .entity-selector-trait)
.target-conditions-trait,
// Main wrapper (supports both .entity-selector-trait and .entity-selector-trait)
.entity-selector-trait {
position: relative;
overflow: visible;
@@ -174,7 +173,7 @@
}
// Block type tabs
.target-block-tabs {
.es-block-tabs {
display: flex;
flex-wrap: wrap;
gap: 0;
@@ -183,7 +182,7 @@
border-bottom: 1px solid $es-border-color;
}
.target-block-tab {
.es-block-tab {
position: relative;
display: flex;
align-items: center;
@@ -237,7 +236,7 @@
border-bottom: 1px solid $es-border-color;
border-radius: $es-radius-lg $es-radius-lg 0 0;
.target-block-tabs {
.es-block-tabs {
flex: 1;
border-bottom: 0;
border-radius: $es-radius-lg 0 0 0;
@@ -261,7 +260,7 @@
color: $es-primary;
}
> i {
.material-icons {
font-size: 20px !important;
}
}
@@ -279,7 +278,7 @@
}
// Block container
.target-block-container {
.es-block-container {
display: none;
&.active {
@@ -287,18 +286,18 @@
}
}
.target-block-content {
.es-block-content {
padding: $es-spacing-md;
}
.target-block-groups {
.es-block-groups {
display: flex;
flex-direction: column;
gap: $es-spacing-md;
}
// Block header (for standalone blocks)
.target-block-header {
.es-block-header {
display: flex;
align-items: center;
justify-content: space-between;
@@ -308,7 +307,7 @@
}
// Empty state
.target-block-empty {
.es-block-empty {
display: flex;
flex-direction: column;
align-items: center;
@@ -366,25 +365,18 @@
}
// Single mode specific styles
.target-conditions-trait.single-mode,
.entity-selector-trait.single-mode,
.entity-selector-trait.single-mode {
// Hide tabs in standalone layout (has separate header, 1 tab is redundant)
.target-block-tabs {
.es-block-tabs {
display: none;
}
.target-block-container {
.es-block-container {
display: block;
}
// In form-content layout, always show tabs — they serve as the block title
.entity-selector-tabs-row .target-block-tabs {
display: flex;
}
}
// Header action buttons
.target-conditions-trait,
.entity-selector-trait {
.header-actions {
display: flex;

View File

@@ -6,11 +6,10 @@
@use '../variables' as *;
@use '../mixins' as *;
.target-conditions-trait,
.entity-selector-trait {
// Group container
.target-group {
.es-group {
background: $es-white;
border: 1px solid $es-border-color;
border-radius: $es-radius-lg;
@@ -18,7 +17,7 @@
}
// Group header
.target-group-header {
.es-group-header {
display: flex;
align-items: center;
justify-content: space-between;
@@ -28,7 +27,7 @@
border-bottom: 1px solid $es-border-color;
}
.target-group-title {
.es-group-title {
display: flex;
align-items: center;
gap: $es-spacing-sm;
@@ -51,7 +50,7 @@
}
}
.target-group-actions {
.es-group-actions {
display: flex;
align-items: center;
gap: $es-spacing-xs;
@@ -80,7 +79,7 @@
}
// Group body
.target-group-body,
.es-group-body,
.group-body {
padding: $es-spacing-md;
}
@@ -931,36 +930,6 @@
background-size: 1.25em 1.25em;
}
// Single mode — strip padding, borders, backgrounds for clean single-selection UI
&[data-mode=single],
.mode-single {
.groups-container {
padding: 0;
}
.group-body {
padding: 0;
}
.group-include {
padding: 0.5rem;
margin-bottom: 0;
background: transparent;
border: none;
border-radius: 0;
}
.selection-group {
background: transparent;
border: none;
margin-bottom: 0;
}
.group-header {
display: none;
}
}
// Condition match count badge
.condition-match-count {
display: inline-flex;

View File

@@ -13,8 +13,8 @@
// Preview Popover Container
// =============================================================================
.target-preview-popover,
.target-list-preview-popover {
.es-preview-popover,
.es-list-preview-popover {
position: absolute;
z-index: 10000;
min-width: 320px;
@@ -66,23 +66,6 @@
transform: none;
}
}
// Positioned above trigger - arrow pointing down
&.position-above {
&::before {
top: auto;
bottom: -8px;
border-top: 8px solid $es-border-color;
border-bottom: 0;
}
&::after {
top: auto;
bottom: -6px;
border-top: 6px solid $es-white;
border-bottom: 0;
}
}
}
// =============================================================================
@@ -579,6 +562,7 @@
}
// Icon styles
> .material-icons,
> i:first-child {
flex-shrink: 0;
width: 16px;
@@ -638,7 +622,7 @@
opacity: 0.8;
}
> i {
.material-icons {
font-size: 12px;
line-height: 1;
}

View File

@@ -6,7 +6,6 @@
@use '../variables' as *;
@use '../mixins' as *;
.target-conditions-trait,
.entity-selector-trait {
// Method dropdown trigger button
@@ -14,8 +13,8 @@
display: inline-flex;
align-items: center;
gap: 0.5rem;
height: 36px;
padding: 0 $es-spacing-md;
min-height: 36px;
padding: 0.25rem $es-spacing-md;
border-radius: $es-radius-md;
background: $es-white;
color: $es-slate-800;
@@ -53,6 +52,7 @@
overflow: hidden;
text-overflow: ellipsis;
font-weight: $es-font-weight-medium;
line-height: 1.4;
}
.method-trigger-caret {

View File

@@ -1,488 +1,2 @@
/**
* Modal Component
* Preview modals, confirmation dialogs
*/
@use "sass:color";
@use '../variables' as *;
@use '../mixins' as *;
// Modal backdrop
.mpr-modal-backdrop {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: $es-z-modal;
opacity: 0;
transition: opacity $es-transition-normal;
&.show {
opacity: 1;
}
}
// Modal container (exclude Bootstrap .modal to prevent collision)
.mpr-modal:not(.modal) {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0.95);
z-index: $es-z-modal + 1;
width: 90%;
max-width: 600px;
max-height: 90vh;
background: $es-white;
border-radius: $es-radius-xl;
box-shadow: $es-shadow-xl;
opacity: 0;
transition: all $es-transition-normal;
overflow: hidden;
display: flex;
flex-direction: column;
&.show {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
&.modal-sm {
max-width: 400px;
}
&.modal-lg {
max-width: 800px;
}
&.modal-xl {
max-width: 1000px;
}
&.modal-fullscreen {
width: 95%;
max-width: none;
height: 90vh;
max-height: none;
}
}
// Modal header
.mpr-modal-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: $es-spacing-md;
padding: $es-spacing-md $es-spacing-lg;
background: $es-bg-header;
border-bottom: 1px solid $es-border-color;
flex-shrink: 0;
}
.mpr-modal-title {
font-size: $es-font-size-base;
font-weight: $es-font-weight-semibold;
color: $es-text-primary;
margin: 0;
}
.mpr-modal-close {
@include button-reset;
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
color: $es-text-muted;
border-radius: $es-radius-md;
transition: all $es-transition-fast;
&:hover {
background: $es-slate-200;
color: $es-text-secondary;
}
i {
font-size: $es-font-size-lg;
}
}
// Modal body
.mpr-modal-body {
flex: 1;
overflow-y: auto;
padding: $es-spacing-lg;
@include custom-scrollbar;
}
// Modal footer
.mpr-modal-footer {
display: flex;
align-items: center;
justify-content: flex-end;
gap: $es-spacing-sm;
padding: $es-spacing-md $es-spacing-lg;
background: $es-bg-header;
border-top: 1px solid $es-border-color;
flex-shrink: 0;
}
.mpr-modal-btn {
@include button-reset;
display: inline-flex;
align-items: center;
justify-content: center;
gap: $es-spacing-xs;
padding: $es-spacing-sm $es-spacing-md;
font-size: $es-font-size-sm;
font-weight: $es-font-weight-medium;
border-radius: $es-radius-md;
transition: all $es-transition-fast;
&.btn-secondary {
color: $es-text-secondary;
background: $es-slate-100;
&:hover {
background: $es-slate-200;
}
}
&.btn-primary {
color: $es-white;
background: $es-primary;
&:hover {
background: $es-primary-hover;
}
}
&.btn-danger {
color: $es-white;
background: $es-danger;
&:hover {
background: color.adjust($es-danger, $lightness: -10%);
}
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
// Preview popover styles moved to _list-preview.scss
.popover-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: $es-spacing-sm;
padding: $es-spacing-sm $es-spacing-md;
background: $es-bg-header;
border-bottom: 1px solid $es-border-color;
border-radius: $es-radius-lg $es-radius-lg 0 0;
}
.popover-title {
font-size: $es-font-size-sm;
font-weight: $es-font-weight-semibold;
color: $es-text-primary;
}
.popover-close {
@include button-reset;
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
color: $es-text-muted;
border-radius: $es-radius-sm;
transition: all $es-transition-fast;
&:hover {
background: $es-slate-200;
color: $es-text-secondary;
}
}
.popover-body {
max-height: 300px;
overflow-y: auto;
padding: $es-spacing-sm;
@include custom-scrollbar;
}
.popover-footer {
display: flex;
align-items: center;
justify-content: space-between;
gap: $es-spacing-sm;
padding: $es-spacing-sm $es-spacing-md;
background: $es-bg-header;
border-top: 1px solid $es-border-color;
border-radius: 0 0 $es-radius-lg $es-radius-lg;
}
.popover-info {
font-size: $es-font-size-xs;
color: $es-text-muted;
}
.popover-load-more {
@include button-reset;
display: inline-flex;
align-items: center;
gap: 0.25rem;
padding: 0.25rem 0.5rem;
font-size: $es-font-size-xs;
font-weight: $es-font-weight-medium;
color: $es-primary;
border-radius: $es-radius-sm;
transition: all $es-transition-fast;
&:hover {
background: $es-primary-light;
}
}
// Popover arrow
.popover-arrow {
position: absolute;
width: 12px;
height: 12px;
background: $es-white;
border: 1px solid $es-border-color;
transform: rotate(45deg);
&.arrow-top {
top: -7px;
left: 50%;
margin-left: -6px;
border-right: none;
border-bottom: none;
}
&.arrow-bottom {
bottom: -7px;
left: 50%;
margin-left: -6px;
border-left: none;
border-top: none;
}
}
// ==========================================================================
// Holiday Preview Modal
// ==========================================================================
#mpr-holiday-preview-modal {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: $es-z-modal;
&.show {
display: flex;
align-items: center;
justify-content: center;
}
.mpr-modal-backdrop {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
cursor: pointer;
}
.mpr-modal-dialog {
position: relative;
width: 90%;
max-width: 480px;
max-height: 80vh;
background: $es-white;
border-radius: $es-radius-lg;
box-shadow: $es-shadow-xl;
display: flex;
flex-direction: column;
overflow: hidden;
}
.mpr-modal-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: $es-spacing-md;
padding: $es-spacing-md $es-spacing-lg;
background: $es-bg-header;
border-bottom: 1px solid $es-border-color;
flex-shrink: 0;
}
.mpr-modal-title {
display: flex;
align-items: center;
gap: $es-spacing-sm;
font-size: $es-font-size-base;
font-weight: $es-font-weight-semibold;
color: $es-text-primary;
margin: 0;
i> i {
font-size: 20px;
color: $es-primary;
}
}
.mpr-modal-close {
@include button-reset;
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
color: $es-text-muted;
border-radius: $es-radius-md;
transition: all $es-transition-fast;
&:hover {
background: $es-slate-200;
color: $es-text-secondary;
}
i {
font-size: 18px;
}
}
.mpr-modal-body {
flex: 1;
overflow-y: auto;
padding: $es-spacing-lg;
@include custom-scrollbar;
}
// Loading state
.holiday-preview-loading {
display: flex;
align-items: center;
justify-content: center;
gap: $es-spacing-sm;
padding: $es-spacing-xl 0;
color: $es-text-muted;
font-size: $es-font-size-sm;
i {
font-size: $es-font-size-lg;
}
}
// Empty state
.holiday-preview-empty {
text-align: center;
padding: $es-spacing-xl 0;
color: $es-text-muted;
i> i {
font-size: 48px;
opacity: 0.5;
margin-bottom: $es-spacing-md;
}
p {
margin: 0 0 $es-spacing-xs;
}
.hint {
font-size: $es-font-size-xs;
color: $es-text-muted;
}
}
// Holiday list
.holiday-list {
display: flex;
flex-direction: column;
gap: $es-spacing-sm;
}
.holiday-item {
display: flex;
align-items: flex-start;
gap: $es-spacing-md;
padding: $es-spacing-sm $es-spacing-md;
background: $es-slate-50;
border-radius: $es-radius-md;
border-left: 3px solid $es-success;
&.holiday-type-bank {
border-left-color: $es-info;
}
&.holiday-type-observance {
border-left-color: $es-warning;
}
&.holiday-type-regional {
border-left-color: #8b5cf6;
}
}
.holiday-date {
flex-shrink: 0;
min-width: 100px;
.holiday-day {
display: block;
font-size: $es-font-size-sm;
font-weight: $es-font-weight-semibold;
color: $es-text-primary;
}
.holiday-weekday {
display: block;
font-size: $es-font-size-xs;
color: $es-text-muted;
}
}
.holiday-info {
flex: 1;
min-width: 0;
}
.holiday-name {
display: block;
font-size: $es-font-size-sm;
color: $es-text-primary;
word-wrap: break-word;
}
.holiday-type-badge {
display: inline-block;
margin-top: $es-spacing-xs;
padding: 0.125rem 0.375rem;
font-size: 10px;
font-weight: $es-font-weight-medium;
text-transform: capitalize;
background: $es-slate-200;
color: $es-text-secondary;
border-radius: $es-radius-sm;
}
.holiday-preview-note {
margin-top: $es-spacing-md;
font-size: $es-font-size-xs;
color: $es-text-muted;
text-align: center;
}
}
// Modal component removed - was dead code conflicting with Bootstrap .modal
// Modal functionality is provided by prestashop-admin package (mpr-admin-modal-* classes)

View File

@@ -0,0 +1,76 @@
// Replace confirmation modal for single-mode entity selectors
// Displayed when user tries to replace an already-selected item
@use '../variables' as *;
.mpr-replace-body {
padding: $es-spacing-sm 0;
}
.mpr-replace-message {
margin: 0 0 $es-spacing-md;
color: $es-text-secondary;
font-size: $es-font-size-sm;
line-height: $es-line-height-normal;
}
.mpr-replace-item {
display: flex;
align-items: center;
gap: $es-spacing-sm;
padding: $es-spacing-sm $es-spacing-md;
border-radius: $es-radius-md;
border: 1px solid $es-border-color;
background: $es-white;
}
.mpr-replace-current {
border-color: $es-danger;
background: $es-danger-light;
.mpr-replace-label {
color: $es-danger-dark;
background: rgba($es-danger, 0.12);
}
}
.mpr-replace-new {
border-color: $es-success;
background: $es-success-light;
.mpr-replace-label {
color: $es-success-dark;
background: rgba($es-success, 0.12);
}
}
.mpr-replace-label {
flex-shrink: 0;
padding: 2px $es-spacing-sm;
border-radius: $es-radius-sm;
font-size: $es-font-size-xs;
font-weight: $es-font-weight-semibold;
text-transform: uppercase;
letter-spacing: 0.03em;
}
.mpr-replace-value {
font-size: $es-font-size-sm;
font-weight: $es-font-weight-medium;
color: $es-text-primary;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
}
.mpr-replace-arrow {
display: flex;
justify-content: center;
padding: $es-spacing-xs 0;
color: $es-text-light;
.material-icons {
font-size: 20px;
}
}

View File

@@ -329,7 +329,7 @@
background: $es-slate-200;
}
> i {
.material-icons {
color: $es-slate-400;
font-size: 20px;
}
@@ -357,7 +357,7 @@
border-radius: $es-radius-full;
white-space: nowrap;
> i {
.material-icons {
font-size: 14px;
opacity: 0.7;
}

View File

@@ -6,11 +6,10 @@
@use '../variables' as *;
@use '../mixins' as *;
.target-conditions-trait,
.entity-selector-trait {
// Tips box container
.target-tips-box {
.es-tips-box {
margin: $es-spacing-lg $es-spacing-md $es-spacing-md;
border: 1px solid $es-border-color;
border-radius: $es-radius-lg;
@@ -55,7 +54,7 @@
}
// Expanded state
.target-tips-box.expanded {
.es-tips-box.expanded {
.tips-toggle {
transform: rotate(180deg);
}

View File

@@ -17,13 +17,13 @@
vertical-align: middle;
margin-left: 0.25rem;
> i {
font-size: 14px;
.material-icons {
font-size: 16px;
color: $es-text-muted;
transition: color 0.15s ease;
}
&:hover > i {
&:hover .material-icons {
color: $es-primary;
}
}
@@ -92,7 +92,7 @@
line-height: 1;
transition: background-color 0.15s ease;
> i {
.material-icons {
font-size: 16px;
color: $es-text-muted;
}
@@ -100,7 +100,7 @@
&:hover {
background: $es-slate-100;
> i {
.material-icons {
color: $es-slate-700;
}
}

View File

@@ -324,7 +324,7 @@
}
// Tree view mode in dropdown
.target-search-dropdown.view-tree {
.es-search-dropdown.view-tree {
.dropdown-results {
padding: 0;
}

View File

@@ -6,7 +6,6 @@
@use '../variables' as *;
@use '../mixins' as *;
.target-conditions-trait,
.entity-selector-trait {
// Value picker container

View File

@@ -6,14 +6,12 @@
@use '../variables' as *;
// Base border reset for all entity-selector elements
.target-conditions-trait,
.target-conditions-trait *,
.entity-selector-trait,
.entity-selector-trait *,
.method-dropdown-menu,
.method-dropdown-menu *,
.target-preview-popover,
.target-preview-popover * {
.es-preview-popover,
.es-preview-popover * {
border-style: solid;
border-width: 0;
border-color: $es-border-color;
@@ -22,7 +20,7 @@
// Full-width form group override using :has()
// Excludes .layout-form-group which uses standard PrestaShop form layout
.form-group:has(.entity-selector-trait:not(.layout-form-group)),
.form-group:has(.target-conditions-trait:not(.layout-form-group)),
.form-group:has(.entity-selector-trait:not(.layout-form-group)),
.form-group:has(.condition-trait:not(.layout-form-group)) {
display: block;
@@ -65,26 +63,26 @@
// Dropdown overflow fix
// When dropdown is open, parent containers must allow overflow
.panel:has(.target-search-dropdown.show),
.card:has(.target-search-dropdown.show),
.form-wrapper:has(.target-search-dropdown.show),
.panel-body:has(.target-search-dropdown.show),
.card-body:has(.target-search-dropdown.show),
.form-group:has(.target-search-dropdown.show),
.col-lg-8:has(.target-search-dropdown.show),
.col-lg-12:has(.target-search-dropdown.show) {
.panel:has(.es-search-dropdown.show),
.card:has(.es-search-dropdown.show),
.form-wrapper:has(.es-search-dropdown.show),
.panel-body:has(.es-search-dropdown.show),
.card-body:has(.es-search-dropdown.show),
.form-group:has(.es-search-dropdown.show),
.col-lg-8:has(.es-search-dropdown.show),
.col-lg-12:has(.es-search-dropdown.show) {
overflow: visible !important;
}
// Target conditions wrapper hierarchy overflow fix
.target-conditions-trait:has(.target-search-dropdown.show),
.entity-selector-trait:has(.target-search-dropdown.show),
.condition-trait-body:has(.target-search-dropdown.show),
.target-block-content:has(.target-search-dropdown.show),
.target-block-groups:has(.target-search-dropdown.show),
.target-group:has(.target-search-dropdown.show),
.target-group-body:has(.target-search-dropdown.show),
.target-search-wrapper:has(.target-search-dropdown.show) {
.entity-selector-trait:has(.es-search-dropdown.show),
.entity-selector-trait:has(.es-search-dropdown.show),
.condition-trait-body:has(.es-search-dropdown.show),
.es-block-content:has(.es-search-dropdown.show),
.es-block-groups:has(.es-search-dropdown.show),
.es-group:has(.es-search-dropdown.show),
.es-group-body:has(.es-search-dropdown.show),
.es-search-wrapper:has(.es-search-dropdown.show) {
overflow: visible !important;
}
@@ -94,7 +92,7 @@
// Use .layout-embedded for entity selectors nested inside other components
// Removes outer wrapper styling to avoid redundant borders/backgrounds
.target-conditions-trait.layout-embedded,
.entity-selector-trait.layout-embedded,
.entity-selector-trait.layout-embedded {
background: transparent;
border: none;

View File

@@ -7,7 +7,6 @@
// Tablet and below
@media (max-width: 991px) {
.target-conditions-trait,
.entity-selector-trait {
.condition-trait-header {
flex-direction: column;
@@ -20,7 +19,7 @@
justify-content: flex-end;
}
.target-block-tabs {
.es-block-tabs {
flex-wrap: wrap;
}
}
@@ -28,19 +27,18 @@
// Mobile
@media (max-width: 767px) {
.target-conditions-trait,
.entity-selector-trait {
.target-block-tab {
.es-block-tab {
padding: $es-spacing-sm;
font-size: $es-font-size-xs;
}
.target-group-header {
.es-group-header {
flex-direction: column;
align-items: flex-start;
}
.target-search-dropdown {
.es-search-dropdown {
width: 100% !important;
left: 0 !important;
right: 0 !important;
@@ -54,7 +52,6 @@
// High-resolution displays
@media (min-width: 1600px) {
.target-conditions-trait,
.entity-selector-trait {
.dropdown-results-grid.view-grid-3 {
grid-template-columns: repeat(4, 1fr);

View File

@@ -31,3 +31,44 @@
@use 'components/tooltip';
@use 'components/tree';
@use 'components/validation';
@use 'components/replace-modal';
// Refactor additions (Mar 2026)
// Loading state
.loading-count { opacity: 0.5; transition: opacity 0.15s; }
.tab-badge.loading { opacity: 0.5; transition: opacity 0.15s; }
// Expand/collapse CSS transitions (replaces jQuery slideDown/slideUp)
.entity-selector-blocks-content,
.condition-trait-body,
.group-modifiers-content {
transition: max-height 0.2s ease-out, opacity 0.2s ease-out;
overflow: hidden;
}
.entity-selector-blocks-content:not(.es-expanded),
.condition-trait-body:not(.es-expanded),
.group-modifiers-content:not(.es-expanded) {
max-height: 0 !important;
opacity: 0;
pointer-events: none;
}
.entity-selector-blocks-content.es-expanded,
.condition-trait-body.es-expanded,
.group-modifiers-content.es-expanded {
max-height: 2000px;
opacity: 1;
pointer-events: auto;
}
// Empty state component
.es-empty-state,
.chips-empty-state {
display: block;
padding: 0.75rem 1rem;
color: #94a3b8;
font-size: 0.8rem;
font-style: italic;
text-align: center;
}
// chips-wrapper, chips-toolbar, and chips-load-more are created by JS
// only when chips exist — not rendered in template when empty