Plugin Directory

Changeset 3778841


Ignore:
Timestamp:
11/02/2026 02:28:51 AM (3 hours ago)
Author:
chiseiko
Message:

Chiseiko Essential Swatches for WooCommerce 1.1.0 (from GitHub release v1.1.0)

Location:
chiseiko-essential-swatches
Files:
122 added
22 edited

Legend:

Unmodified
Added
Removed
  • chiseiko-essential-swatches/trunk/assets/css/chiseikoessw-archive.css

    r3598460 r3778841  
    3838        align-self: stretch;
    3939        box-sizing: border-box;
     40        /* Swatches never widen the product card. Without this, a long label's
     41         * min-content widens its column in grid themes (Astra's
     42         * `repeat(4, 1fr)` went 479/280/205/479 px instead of 4 × 285 px). */
     43        contain: inline-size;
    4044}
    4145
    … …  
    146150}
    147151
     152/* A label wider than the card (Pro Pill/Square, or the chapter 25 CSS)
     153 * shrinks to the card and ends in an ellipsis; the button's accessible name
     154 * and tooltip keep the full term name. */
     155.chiseikoessw-swatch--loop {
     156        max-width: 100%;
     157}
     158
     159.chiseikoessw-swatch--loop .chiseikoessw-swatch__inner--text {
     160        min-width: 0;
     161        overflow: hidden;
     162        text-overflow: ellipsis;
     163}
     164
    148165/* Ensure light / white color swatches remain visible against white cards */
    149166.chiseikoessw-swatch--loop.chiseikoessw-swatch--color .chiseikoessw-swatch__inner {
  • chiseiko-essential-swatches/trunk/assets/css/chiseikoessw-archive.min.css

    r3598460 r3778841  
    1 .chiseikoessw-card-swatches{display:flex;flex-direction:column;align-items:var(--chiseikoessw-archive-align,center);gap:6px;margin:6px 0 0;padding:8px 16px 16px;border-top:1px solid rgba(0,0,0,.1);width:100%;align-self:stretch;box-sizing:border-box}.chiseikoessw-card-swatches__row--variable{display:flex;flex-wrap:wrap;gap:5px;align-items:center;justify-content:var(--chiseikoessw-archive-align,center);padding:4px;box-sizing:border-box;contain:layout style;max-height:calc(var(--chiseikoessw-swatch-size-sm) * 2 + 5px + 8px + 8px);overflow:hidden}.chiseikoessw-accordion__panel .chiseikoessw-card-swatches__row--variable,.chiseikoessw-card-swatches__row--variable.chiseikoessw-overflow-ready{max-height:none;overflow:visible}.chiseikoessw-swatch--loop{width:var(--chiseikoessw-swatch-size-sm)!important;height:var(--chiseikoessw-swatch-size-sm)!important;min-width:var(--chiseikoessw-swatch-size-sm)!important;min-height:var(--chiseikoessw-swatch-size-sm)!important;box-sizing:border-box;border-radius:50%;cursor:default;pointer-events:none;box-shadow:0 0 0 1px rgba(0,0,0,.12);border:var(--chiseikoessw-swatch-border-width) solid transparent;outline:transparent solid 2px;outline-offset:2px;transform:none!important;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.chiseikoessw-swatch--loop:hover{transform:none!important;box-shadow:0 0 0 1px rgba(0,0,0,.12)!important}.chiseikoessw-swatch--loop.chiseikoessw-swatch--label,.chiseikoessw-swatch--loop.chiseikoessw-swatch--none,.chiseikoessw-swatch--loop.chiseikoessw-swatch--text{background:#f5f5f5;color:#333;font-size:9px;font-weight:600;letter-spacing:.01em;white-space:nowrap;overflow:hidden;padding:0}.chiseikoessw-swatch--loop .chiseikoessw-swatch__inner{border-radius:inherit}.chiseikoessw-swatch--loop .chiseikoessw-swatch__inner--text{width:auto;height:auto;border-radius:0;font-size:inherit;line-height:1}.chiseikoessw-swatch--loop.chiseikoessw-swatch--color .chiseikoessw-swatch__inner{box-shadow:inset 0 0 0 1px rgba(0,0,0,.08)}.chiseikoessw-swatch--loop img{border-radius:inherit}.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio.chiseikoessw-selected{background:linear-gradient(180deg,#fff 0,#eef4ff 100%);box-shadow:0 1px 2px rgba(15,23,42,.12),inset 0 1px 0 rgba(255,255,255,.92)}.chiseikoessw-swatch-btn.chiseikoessw-selected .chiseikoessw-swatch__inner{box-shadow:var(--chiseikoessw-swatch-selected-inset)}.chiseikoessw-swatch-btn[data-chiseikoessw-interactive="1"]{cursor:pointer;pointer-events:auto}.chiseikoessw-swatch-btn[data-chiseikoessw-interactive="1"][aria-disabled=true]{cursor:not-allowed;pointer-events:none}.chiseikoessw-swatch-btn[data-chiseikoessw-interactive="1"]:focus-visible,.chiseikoessw-swatch-btn[data-chiseikoessw-interactive="1"]:hover{outline:currentColor solid 2px;outline-offset:2px}.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio[data-chiseikoessw-interactive="1"]:focus-visible,.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio[data-chiseikoessw-interactive="1"]:hover{background:rgba(15,23,42,.04);box-shadow:0 1px 2px rgba(15,23,42,.1),inset 0 1px 0 rgba(255,255,255,.92)}.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio[data-chiseikoessw-interactive="1"]:focus-visible .chiseikoessw-radio-dot,.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio[data-chiseikoessw-interactive="1"]:hover .chiseikoessw-radio-dot{border-color:var(--chiseikoessw-accent,currentColor)}.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio.chiseikoessw-selected[data-chiseikoessw-interactive="1"]:focus-visible,.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio.chiseikoessw-selected[data-chiseikoessw-interactive="1"]:hover{background:linear-gradient(180deg,#fff 0,#eef4ff 100%);box-shadow:0 1px 2px rgba(15,23,42,.12),inset 0 1px 0 rgba(255,255,255,.92)}@supports (color:color-mix(in srgb,red 50%,blue)){.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio[data-chiseikoessw-interactive="1"]:focus-visible,.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio[data-chiseikoessw-interactive="1"]:hover{background:color-mix(in srgb,var(--chiseikoessw-accent,currentColor) 10%,#fff)}.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio.chiseikoessw-selected[data-chiseikoessw-interactive="1"]:focus-visible,.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio.chiseikoessw-selected[data-chiseikoessw-interactive="1"]:hover{background:linear-gradient(180deg,#fff 0,#eef4ff 100%)}}.chiseikoessw-archive-cta{cursor:pointer;text-decoration:none}.chiseikoessw-archive-cta:hover{filter:brightness(.92);transform:translateY(-1px);box-shadow:0 4px 10px rgba(0,0,0,.2)}.chiseikoessw-archive-cta.is-loading,.chiseikoessw-archive-cta[disabled]{transform:none;filter:none;box-shadow:none}.chiseikoessw-archive-cta[disabled]{opacity:.55;cursor:not-allowed}.chiseikoessw-archive-cta.is-loading{opacity:.7;cursor:wait}.chiseikoessw-archive-view-cart{display:block;margin-top:6px;text-align:center;font-size:12px;letter-spacing:.04em;color:var(--chiseikoessw-accent,currentColor);text-decoration:underline;text-underline-offset:2px}.chiseikoessw-archive-view-cart:hover{color:var(--chiseikoessw-accent-dark,currentColor)}[data-chiseikoessw-hidden="1"]{display:none!important}.chiseikoessw-arch-updating img{opacity:.5;transition:opacity .15s}@media (prefers-reduced-motion:reduce){.chiseikoessw-arch-updating img,.chiseikoessw-archive-cta,.chiseikoessw-swatch-btn[data-chiseikoessw-interactive="1"]{transition:none;transform:none!important;filter:none!important}}@media (forced-colors:active){.chiseikoessw-archive-cta{border:2px solid ButtonText;background:ButtonFace;color:ButtonText;text-shadow:none}}.chiseikoessw-atc-error{color:var(--chiseikoessw-error,#a00);font-size:.85em;margin-top:4px}
     1.chiseikoessw-card-swatches{display:flex;flex-direction:column;align-items:var(--chiseikoessw-archive-align,center);gap:6px;margin:6px 0 0;padding:8px 16px 16px;border-top:1px solid rgba(0,0,0,.1);width:100%;align-self:stretch;box-sizing:border-box;contain:inline-size}.chiseikoessw-card-swatches__row--variable{display:flex;flex-wrap:wrap;gap:5px;align-items:center;justify-content:var(--chiseikoessw-archive-align,center);padding:4px;box-sizing:border-box;contain:layout style;max-height:calc(var(--chiseikoessw-swatch-size-sm) * 2 + 5px + 8px + 8px);overflow:hidden}.chiseikoessw-accordion__panel .chiseikoessw-card-swatches__row--variable,.chiseikoessw-card-swatches__row--variable.chiseikoessw-overflow-ready{max-height:none;overflow:visible}.chiseikoessw-swatch--loop{width:var(--chiseikoessw-swatch-size-sm)!important;height:var(--chiseikoessw-swatch-size-sm)!important;min-width:var(--chiseikoessw-swatch-size-sm)!important;min-height:var(--chiseikoessw-swatch-size-sm)!important;box-sizing:border-box;border-radius:50%;cursor:default;pointer-events:none;box-shadow:0 0 0 1px rgba(0,0,0,.12);border:var(--chiseikoessw-swatch-border-width) solid transparent;outline:transparent solid 2px;outline-offset:2px;transform:none!important;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;max-width:100%}.chiseikoessw-swatch--loop:hover{transform:none!important;box-shadow:0 0 0 1px rgba(0,0,0,.12)!important}.chiseikoessw-swatch--loop.chiseikoessw-swatch--label,.chiseikoessw-swatch--loop.chiseikoessw-swatch--none,.chiseikoessw-swatch--loop.chiseikoessw-swatch--text{background:#f5f5f5;color:#333;font-size:9px;font-weight:600;letter-spacing:.01em;white-space:nowrap;overflow:hidden;padding:0}.chiseikoessw-swatch--loop .chiseikoessw-swatch__inner{border-radius:inherit}.chiseikoessw-swatch--loop .chiseikoessw-swatch__inner--text{width:auto;height:auto;border-radius:0;font-size:inherit;line-height:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.chiseikoessw-swatch--loop.chiseikoessw-swatch--color .chiseikoessw-swatch__inner{box-shadow:inset 0 0 0 1px rgba(0,0,0,.08)}.chiseikoessw-swatch--loop img{border-radius:inherit}.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio.chiseikoessw-selected{background:linear-gradient(180deg,#fff 0,#eef4ff 100%);box-shadow:0 1px 2px rgba(15,23,42,.12),inset 0 1px 0 rgba(255,255,255,.92)}.chiseikoessw-swatch-btn.chiseikoessw-selected .chiseikoessw-swatch__inner{box-shadow:var(--chiseikoessw-swatch-selected-inset)}.chiseikoessw-swatch-btn[data-chiseikoessw-interactive="1"]{cursor:pointer;pointer-events:auto}.chiseikoessw-swatch-btn[data-chiseikoessw-interactive="1"][aria-disabled=true]{cursor:not-allowed;pointer-events:none}.chiseikoessw-swatch-btn[data-chiseikoessw-interactive="1"]:focus-visible,.chiseikoessw-swatch-btn[data-chiseikoessw-interactive="1"]:hover{outline:currentColor solid 2px;outline-offset:2px}.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio[data-chiseikoessw-interactive="1"]:focus-visible,.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio[data-chiseikoessw-interactive="1"]:hover{background:rgba(15,23,42,.04);box-shadow:0 1px 2px rgba(15,23,42,.1),inset 0 1px 0 rgba(255,255,255,.92)}.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio[data-chiseikoessw-interactive="1"]:focus-visible .chiseikoessw-radio-dot,.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio[data-chiseikoessw-interactive="1"]:hover .chiseikoessw-radio-dot{border-color:var(--chiseikoessw-accent,currentColor)}.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio.chiseikoessw-selected[data-chiseikoessw-interactive="1"]:focus-visible,.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio.chiseikoessw-selected[data-chiseikoessw-interactive="1"]:hover{background:linear-gradient(180deg,#fff 0,#eef4ff 100%);box-shadow:0 1px 2px rgba(15,23,42,.12),inset 0 1px 0 rgba(255,255,255,.92)}@supports (color:color-mix(in srgb,red 50%,blue)){.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio[data-chiseikoessw-interactive="1"]:focus-visible,.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio[data-chiseikoessw-interactive="1"]:hover{background:color-mix(in srgb,var(--chiseikoessw-accent,currentColor) 10%,#fff)}.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio.chiseikoessw-selected[data-chiseikoessw-interactive="1"]:focus-visible,.chiseikoessw-swatch-btn.chiseikoessw-swatch--radio.chiseikoessw-selected[data-chiseikoessw-interactive="1"]:hover{background:linear-gradient(180deg,#fff 0,#eef4ff 100%)}}.chiseikoessw-archive-cta{cursor:pointer;text-decoration:none}.chiseikoessw-archive-cta:hover{filter:brightness(.92);transform:translateY(-1px);box-shadow:0 4px 10px rgba(0,0,0,.2)}.chiseikoessw-archive-cta.is-loading,.chiseikoessw-archive-cta[disabled]{transform:none;filter:none;box-shadow:none}.chiseikoessw-archive-cta[disabled]{opacity:.55;cursor:not-allowed}.chiseikoessw-archive-cta.is-loading{opacity:.7;cursor:wait}.chiseikoessw-archive-view-cart{display:block;margin-top:6px;text-align:center;font-size:12px;letter-spacing:.04em;color:var(--chiseikoessw-accent,currentColor);text-decoration:underline;text-underline-offset:2px}.chiseikoessw-archive-view-cart:hover{color:var(--chiseikoessw-accent-dark,currentColor)}[data-chiseikoessw-hidden="1"]{display:none!important}.chiseikoessw-arch-updating img{opacity:.5;transition:opacity .15s}@media (prefers-reduced-motion:reduce){.chiseikoessw-arch-updating img,.chiseikoessw-archive-cta,.chiseikoessw-swatch-btn[data-chiseikoessw-interactive="1"]{transition:none;transform:none!important;filter:none!important}}@media (forced-colors:active){.chiseikoessw-archive-cta{border:2px solid ButtonText;background:ButtonFace;color:ButtonText;text-shadow:none}}.chiseikoessw-atc-error{color:var(--chiseikoessw-error,#a00);font-size:.85em;margin-top:4px}
  • chiseiko-essential-swatches/trunk/assets/css/chiseikoessw-frontend.css

    r3598460 r3778841  
    270270}
    271271
     272/* ── Free global shape ───────────────────────────────────────────────────────── */
     273/*
     274 * The one place the Free "Swatch shape" setting is styled. CHISEIKOESSW_Appearance
     275 * adds `chiseikoessw-free-shape-{shape}` to every swatch through
     276 * `chiseikoessw_swatch_button_classes`, so product pages, shop/category cards
     277 * and related cards all follow it. Circle is the default above and has no
     278 * class; radio swatches never get one. The class is never added while Pro
     279 * styling is active, so these rules cannot reach a licensed Pro store.
     280 * Two classes beat the archive's single-class `border-radius: 50%`; label
     281 * widths need !important to undo the archive's fixed-width loop rule.
     282 */
     283.chiseikoessw-swatch.chiseikoessw-free-shape-rounded {
     284        border-radius: 6px;
     285}
     286
     287.chiseikoessw-swatch.chiseikoessw-free-shape-square {
     288        border-radius: 0;
     289}
     290
     291/* Rounded / square label swatches widen to fit their text. */
     292.chiseikoessw-swatch[class*="chiseikoessw-free-shape-"]:is(.chiseikoessw-swatch--label, .chiseikoessw-swatch--none) {
     293        width: auto !important;
     294        padding: var(--chiseikoessw-text-padding) !important;
     295}
     296
     297.chiseikoessw-swatch--loop[class*="chiseikoessw-free-shape-"]:is(.chiseikoessw-swatch--label, .chiseikoessw-swatch--none) {
     298        padding: var(--chiseikoessw-text-padding-sm) !important;
     299}
     300
    272301/* ── Text / fallback swatch (full-size interactive) ────────────────────────── */
    273302/*
  • chiseiko-essential-swatches/trunk/assets/css/chiseikoessw-frontend.min.css

    r3598460 r3778841  
    1 :root{--chiseikoessw-swatch-size:32px;--chiseikoessw-swatch-size-sm:32px;--chiseikoessw-swatch-radius:50%;--chiseikoessw-swatch-gap:8px;--chiseikoessw-swatch-gap-sm:6px;--chiseikoessw-text-height:32px;--chiseikoessw-text-min-width:32px;--chiseikoessw-text-padding:0 12px;--chiseikoessw-text-height-sm:32px;--chiseikoessw-text-min-width-sm:32px;--chiseikoessw-text-padding-sm:0 8px;--chiseikoessw-text-font-size:0.75rem;--chiseikoessw-text-font-weight:600;--chiseikoessw-text-white-space:nowrap;--chiseikoessw-linked-justify:flex-start;--chiseikoessw-radio-dot:16px;--chiseikoessw-radio-min:32px;--chiseikoessw-radio-padding:0 14px;--chiseikoessw-swatch-border-width:1px;--chiseikoessw-swatch-border-color:rgba(0, 0, 0, 0.12);--chiseikoessw-transition-speed:0.2s;--chiseikoessw-transition-ease:cubic-bezier(0.22, 0.61, 0.36, 1);--chiseikoessw-swatch-shadow:0 1px 3px rgba(0, 0, 0, .08);--chiseikoessw-swatch-hover-scale:1.08;--chiseikoessw-swatch-hover-z:2;--chiseikoessw-swatch-selected-inset:inset 0 0 0 2px rgba(255, 255, 255, .55);--chiseikoessw-swatch-selected-shadow:0 0 0 2px var(--chiseikoessw-accent, currentColor);--chiseikoessw-swatch-disabled-opacity:0.45}@media (pointer:coarse),(max-width:768px){:root{--chiseikoessw-swatch-size:44px;--chiseikoessw-swatch-size-sm:44px;--chiseikoessw-text-height:48px;--chiseikoessw-text-min-width:48px;--chiseikoessw-text-padding:0 16px;--chiseikoessw-text-height-sm:48px;--chiseikoessw-text-min-width-sm:48px;--chiseikoessw-text-padding-sm:0 12px;--chiseikoessw-radio-dot:20px;--chiseikoessw-radio-min:48px;--chiseikoessw-radio-padding:0 16px}}.chiseikoessw-native-select{position:absolute!important;width:1px!important;height:1px!important;max-width:1px!important;max-height:1px!important;min-width:0!important;min-height:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;clip-path:inset(50%)!important;white-space:nowrap!important;border:0!important}.chiseikoessw-swatches{display:flex;flex-wrap:wrap;gap:var(--chiseikoessw-swatch-gap,8px);margin:4px 0;padding:0;list-style:none;contain:layout style}.chiseikoessw-swatch{appearance:none;background:0 0;border:var(--chiseikoessw-swatch-border-width) solid var(--chiseikoessw-swatch-border-color);padding:0;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;box-sizing:border-box;width:var(--chiseikoessw-swatch-size);height:var(--chiseikoessw-swatch-size);border-radius:var(--chiseikoessw-swatch-radius);transition:transform var(--chiseikoessw-transition-speed) var(--chiseikoessw-transition-ease, ease),opacity var(--chiseikoessw-transition-speed) var(--chiseikoessw-transition-ease, ease),box-shadow var(--chiseikoessw-transition-speed) var(--chiseikoessw-transition-ease, ease);box-shadow:var(--chiseikoessw-swatch-shadow);position:relative;overflow:hidden;outline:transparent solid 2px;outline-offset:2px}.chiseikoessw-swatch__inner{display:block;width:100%;height:100%;border-radius:inherit;overflow:hidden;pointer-events:none}.chiseikoessw-swatch--image .chiseikoessw-swatch__inner,.chiseikoessw-swatch--image img{display:block;width:100%;height:100%;object-fit:cover;border-radius:inherit}.chiseikoessw-swatch--disabled,.chiseikoessw-swatch[aria-disabled=true]{opacity:var(--chiseikoessw-swatch-disabled-opacity);cursor:not-allowed;transform:none!important}.chiseikoessw-swatch--disabled::after,.chiseikoessw-swatch[aria-disabled=true]::after{content:"";position:absolute;top:50%;left:-10%;width:120%;height:0;border-top:1.5px solid rgba(0,0,0,.45);transform:rotate(45deg);transform-origin:center;pointer-events:none}.variations_form .variations .label label,.variations_form table.variations th.label label{font-size:var( --chiseikoessw-label-font-size, .875rem );font-weight:var(--chiseikoessw-label-font-weight,600);line-height:1.3;text-transform:var(--chiseikoessw-label-text-transform,none);letter-spacing:var( --chiseikoessw-label-letter-spacing, normal );color:var(--chiseikoessw-label-color,currentColor)}body[class*=chiseikoessw-pdp-align-] .variations_form.cart table.variations td.value,body[class*=chiseikoessw-pdp-align-] .variations_form.cart table.variations th.label{vertical-align:var(--chiseikoessw-pdp-valign,top)}body[class*=chiseikoessw-pdp-align-] .variations_form.cart table.variations th.label{padding-top:var(--chiseikoessw-pdp-label-pad-top,6px)}body.chiseikoessw-pdp-align-middle{--chiseikoessw-pdp-valign:middle}.chiseikoessw-swatch--radio{width:auto;min-width:var(--chiseikoessw-radio-min);height:var(--chiseikoessw-radio-min);padding:var(--chiseikoessw-radio-padding);border-radius:calc(var(--chiseikoessw-radio-min)/ 2);border-color:rgba(15,23,42,.16);background:linear-gradient(180deg,#fff 0,#f6f8fb 100%);font-size:.8125rem;font-weight:500;color:#333;box-shadow:0 1px 2px rgba(15,23,42,.08),inset 0 1px 0 rgba(255,255,255,.92);gap:6px;overflow:visible}.chiseikoessw-swatch__inner--radio{display:inline-flex;align-items:center;gap:6px;width:auto;height:auto;border-radius:0;font-size:inherit;line-height:1}.chiseikoessw-radio-dot{display:inline-block;width:var(--chiseikoessw-radio-dot);height:var(--chiseikoessw-radio-dot);border-radius:50%;border:2px solid #7a828c;background:#fff;flex-shrink:0;transition:border-color .2s,background .2s;box-sizing:border-box}.chiseikoessw-swatch--radio.chiseikoessw-swatch--selected{border-color:var(--chiseikoessw-accent,currentColor);outline:2px solid var(--chiseikoessw-accent,currentColor);outline-offset:2px;background:linear-gradient(180deg,#fff 0,#eef4ff 100%);color:#333;box-shadow:0 1px 2px rgba(15,23,42,.12),inset 0 1px 0 rgba(255,255,255,.92)}.chiseikoessw-swatch--radio.chiseikoessw-selected .chiseikoessw-radio-dot,.chiseikoessw-swatch--radio.chiseikoessw-swatch--selected .chiseikoessw-radio-dot{border-color:var(--chiseikoessw-accent,currentColor);background:var(--chiseikoessw-accent,currentColor)}.chiseikoessw-swatch--radio.chiseikoessw-swatch--loop{width:auto!important;min-width:var(--chiseikoessw-swatch-size-sm)!important;height:var(--chiseikoessw-swatch-size-sm)!important;min-height:var(--chiseikoessw-swatch-size-sm)!important;padding:0 8px;border-radius:calc(var(--chiseikoessw-swatch-size-sm)/ 2);font-size:.6875rem;pointer-events:none;cursor:default}.chiseikoessw-swatch--radio.chiseikoessw-swatch--loop .chiseikoessw-radio-dot{width:10px;height:10px}.chiseikoessw-swatch .screen-reader-text{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}[dir=rtl] .chiseikoessw-card-swatches__row--variable,[dir=rtl] .chiseikoessw-swatches{flex-direction:row-reverse}#chiseikoessw-tooltip{position:fixed;z-index:9999;padding:4px 8px;background:rgba(24,24,24,.92);color:#fff;font-size:.75rem;line-height:1.3;border-radius:6px;box-shadow:0 2px 6px rgba(0,0,0,.18);pointer-events:none;opacity:0;transform:translateY(4px);transition:opacity .18s,transform .18s;white-space:nowrap;max-width:240px}#chiseikoessw-tooltip.is-visible{opacity:1;transform:translateY(0)}body.chiseikoessw-pro-tooltips-active #chiseikoessw-tooltip{display:none!important}@media (prefers-reduced-motion:reduce){.chiseikoessw-swatch,.chiseikoessw-swatch--loop{transition:none;transform:none!important}}@media (forced-colors:active){.chiseikoessw-swatch{border:1px solid ButtonText}.chiseikoessw-swatch--selected{border:1px solid ButtonText;outline:Highlight solid 2px;outline-offset:2px}.chiseikoessw-swatch:focus-visible{outline:Highlight solid 2px;outline-offset:3px}.chiseikoessw-swatch--disabled::after,.chiseikoessw-swatch[aria-disabled=true]::after{border-top-color:CanvasText;border-top-width:2px}}@media print{.chiseikoessw-card-swatches,.chiseikoessw-swatches{display:none}.chiseikoessw-native-select{position:static!important;width:auto!important;height:auto!important;max-width:none!important;max-height:none!important;min-width:auto!important;min-height:auto!important;overflow:visible!important;clip:auto!important;clip-path:none!important;white-space:normal!important;border:1px solid #999!important}}
     1:root{--chiseikoessw-swatch-size:32px;--chiseikoessw-swatch-size-sm:32px;--chiseikoessw-swatch-radius:50%;--chiseikoessw-swatch-gap:8px;--chiseikoessw-swatch-gap-sm:6px;--chiseikoessw-text-height:32px;--chiseikoessw-text-min-width:32px;--chiseikoessw-text-padding:0 12px;--chiseikoessw-text-height-sm:32px;--chiseikoessw-text-min-width-sm:32px;--chiseikoessw-text-padding-sm:0 8px;--chiseikoessw-text-font-size:0.75rem;--chiseikoessw-text-font-weight:600;--chiseikoessw-text-white-space:nowrap;--chiseikoessw-linked-justify:flex-start;--chiseikoessw-radio-dot:16px;--chiseikoessw-radio-min:32px;--chiseikoessw-radio-padding:0 14px;--chiseikoessw-swatch-border-width:1px;--chiseikoessw-swatch-border-color:rgba(0, 0, 0, 0.12);--chiseikoessw-transition-speed:0.2s;--chiseikoessw-transition-ease:cubic-bezier(0.22, 0.61, 0.36, 1);--chiseikoessw-swatch-shadow:0 1px 3px rgba(0, 0, 0, .08);--chiseikoessw-swatch-hover-scale:1.08;--chiseikoessw-swatch-hover-z:2;--chiseikoessw-swatch-selected-inset:inset 0 0 0 2px rgba(255, 255, 255, .55);--chiseikoessw-swatch-selected-shadow:0 0 0 2px var(--chiseikoessw-accent, currentColor);--chiseikoessw-swatch-disabled-opacity:0.45}@media (pointer:coarse),(max-width:768px){:root{--chiseikoessw-swatch-size:44px;--chiseikoessw-swatch-size-sm:44px;--chiseikoessw-text-height:48px;--chiseikoessw-text-min-width:48px;--chiseikoessw-text-padding:0 16px;--chiseikoessw-text-height-sm:48px;--chiseikoessw-text-min-width-sm:48px;--chiseikoessw-text-padding-sm:0 12px;--chiseikoessw-radio-dot:20px;--chiseikoessw-radio-min:48px;--chiseikoessw-radio-padding:0 16px}}.chiseikoessw-native-select{position:absolute!important;width:1px!important;height:1px!important;max-width:1px!important;max-height:1px!important;min-width:0!important;min-height:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;clip-path:inset(50%)!important;white-space:nowrap!important;border:0!important}.chiseikoessw-swatches{display:flex;flex-wrap:wrap;gap:var(--chiseikoessw-swatch-gap,8px);margin:4px 0;padding:0;list-style:none;contain:layout style}.chiseikoessw-swatch{appearance:none;background:0 0;border:var(--chiseikoessw-swatch-border-width) solid var(--chiseikoessw-swatch-border-color);padding:0;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;box-sizing:border-box;width:var(--chiseikoessw-swatch-size);height:var(--chiseikoessw-swatch-size);border-radius:var(--chiseikoessw-swatch-radius);transition:transform var(--chiseikoessw-transition-speed) var(--chiseikoessw-transition-ease, ease),opacity var(--chiseikoessw-transition-speed) var(--chiseikoessw-transition-ease, ease),box-shadow var(--chiseikoessw-transition-speed) var(--chiseikoessw-transition-ease, ease);box-shadow:var(--chiseikoessw-swatch-shadow);position:relative;overflow:hidden;outline:transparent solid 2px;outline-offset:2px}.chiseikoessw-swatch__inner{display:block;width:100%;height:100%;border-radius:inherit;overflow:hidden;pointer-events:none}.chiseikoessw-swatch--image .chiseikoessw-swatch__inner,.chiseikoessw-swatch--image img{display:block;width:100%;height:100%;object-fit:cover;border-radius:inherit}.chiseikoessw-swatch.chiseikoessw-free-shape-rounded{border-radius:6px}.chiseikoessw-swatch.chiseikoessw-free-shape-square{border-radius:0}.chiseikoessw-swatch[class*=chiseikoessw-free-shape-]:is(.chiseikoessw-swatch--label,.chiseikoessw-swatch--none){width:auto!important;padding:var(--chiseikoessw-text-padding)!important}.chiseikoessw-swatch--loop[class*=chiseikoessw-free-shape-]:is(.chiseikoessw-swatch--label,.chiseikoessw-swatch--none){padding:var(--chiseikoessw-text-padding-sm)!important}.chiseikoessw-swatch--disabled,.chiseikoessw-swatch[aria-disabled=true]{opacity:var(--chiseikoessw-swatch-disabled-opacity);cursor:not-allowed;transform:none!important}.chiseikoessw-swatch--disabled::after,.chiseikoessw-swatch[aria-disabled=true]::after{content:"";position:absolute;top:50%;left:-10%;width:120%;height:0;border-top:1.5px solid rgba(0,0,0,.45);transform:rotate(45deg);transform-origin:center;pointer-events:none}.variations_form .variations .label label,.variations_form table.variations th.label label{font-size:var( --chiseikoessw-label-font-size, .875rem );font-weight:var(--chiseikoessw-label-font-weight,600);line-height:1.3;text-transform:var(--chiseikoessw-label-text-transform,none);letter-spacing:var( --chiseikoessw-label-letter-spacing, normal );color:var(--chiseikoessw-label-color,currentColor)}body[class*=chiseikoessw-pdp-align-] .variations_form.cart table.variations td.value,body[class*=chiseikoessw-pdp-align-] .variations_form.cart table.variations th.label{vertical-align:var(--chiseikoessw-pdp-valign,top)}body[class*=chiseikoessw-pdp-align-] .variations_form.cart table.variations th.label{padding-top:var(--chiseikoessw-pdp-label-pad-top,6px)}body.chiseikoessw-pdp-align-middle{--chiseikoessw-pdp-valign:middle}.chiseikoessw-swatch--radio{width:auto;min-width:var(--chiseikoessw-radio-min);height:var(--chiseikoessw-radio-min);padding:var(--chiseikoessw-radio-padding);border-radius:calc(var(--chiseikoessw-radio-min)/ 2);border-color:rgba(15,23,42,.16);background:linear-gradient(180deg,#fff 0,#f6f8fb 100%);font-size:.8125rem;font-weight:500;color:#333;box-shadow:0 1px 2px rgba(15,23,42,.08),inset 0 1px 0 rgba(255,255,255,.92);gap:6px;overflow:visible}.chiseikoessw-swatch__inner--radio{display:inline-flex;align-items:center;gap:6px;width:auto;height:auto;border-radius:0;font-size:inherit;line-height:1}.chiseikoessw-radio-dot{display:inline-block;width:var(--chiseikoessw-radio-dot);height:var(--chiseikoessw-radio-dot);border-radius:50%;border:2px solid #7a828c;background:#fff;flex-shrink:0;transition:border-color .2s,background .2s;box-sizing:border-box}.chiseikoessw-swatch--radio.chiseikoessw-swatch--selected{border-color:var(--chiseikoessw-accent,currentColor);outline:2px solid var(--chiseikoessw-accent,currentColor);outline-offset:2px;background:linear-gradient(180deg,#fff 0,#eef4ff 100%);color:#333;box-shadow:0 1px 2px rgba(15,23,42,.12),inset 0 1px 0 rgba(255,255,255,.92)}.chiseikoessw-swatch--radio.chiseikoessw-selected .chiseikoessw-radio-dot,.chiseikoessw-swatch--radio.chiseikoessw-swatch--selected .chiseikoessw-radio-dot{border-color:var(--chiseikoessw-accent,currentColor);background:var(--chiseikoessw-accent,currentColor)}.chiseikoessw-swatch--radio.chiseikoessw-swatch--loop{width:auto!important;min-width:var(--chiseikoessw-swatch-size-sm)!important;height:var(--chiseikoessw-swatch-size-sm)!important;min-height:var(--chiseikoessw-swatch-size-sm)!important;padding:0 8px;border-radius:calc(var(--chiseikoessw-swatch-size-sm)/ 2);font-size:.6875rem;pointer-events:none;cursor:default}.chiseikoessw-swatch--radio.chiseikoessw-swatch--loop .chiseikoessw-radio-dot{width:10px;height:10px}.chiseikoessw-swatch .screen-reader-text{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}[dir=rtl] .chiseikoessw-card-swatches__row--variable,[dir=rtl] .chiseikoessw-swatches{flex-direction:row-reverse}#chiseikoessw-tooltip{position:fixed;z-index:9999;padding:4px 8px;background:rgba(24,24,24,.92);color:#fff;font-size:.75rem;line-height:1.3;border-radius:6px;box-shadow:0 2px 6px rgba(0,0,0,.18);pointer-events:none;opacity:0;transform:translateY(4px);transition:opacity .18s,transform .18s;white-space:nowrap;max-width:240px}#chiseikoessw-tooltip.is-visible{opacity:1;transform:translateY(0)}body.chiseikoessw-pro-tooltips-active #chiseikoessw-tooltip{display:none!important}@media (prefers-reduced-motion:reduce){.chiseikoessw-swatch,.chiseikoessw-swatch--loop{transition:none;transform:none!important}}@media (forced-colors:active){.chiseikoessw-swatch{border:1px solid ButtonText}.chiseikoessw-swatch--selected{border:1px solid ButtonText;outline:Highlight solid 2px;outline-offset:2px}.chiseikoessw-swatch:focus-visible{outline:Highlight solid 2px;outline-offset:3px}.chiseikoessw-swatch--disabled::after,.chiseikoessw-swatch[aria-disabled=true]::after{border-top-color:CanvasText;border-top-width:2px}}@media print{.chiseikoessw-card-swatches,.chiseikoessw-swatches{display:none}.chiseikoessw-native-select{position:static!important;width:auto!important;height:auto!important;max-width:none!important;max-height:none!important;min-width:auto!important;min-height:auto!important;overflow:visible!important;clip:auto!important;clip-path:none!important;white-space:normal!important;border:1px solid #999!important}}
  • chiseiko-essential-swatches/trunk/assets/js/chiseikoessw-frontend.js

    r3598460 r3778841  
    119119                        || swatches[ 0 ];
    120120
     121                // Write only on change: setting tabindex makes Chromium re-check the
     122                // element's focusability, which forces a synchronous style recalc —
     123                // rewriting every swatch on every click was the largest plugin-forced
     124                // layout cost in the swatch-interaction trace.
    121125                for ( var i = 0; i < swatches.length; i++ ) {
    122                         swatches[ i ].setAttribute( 'tabindex', swatches[ i ] === target ? '0' : '-1' );
     126                        var tabindex = swatches[ i ] === target ? '0' : '-1';
     127                        if ( swatches[ i ].getAttribute( 'tabindex' ) !== tabindex ) {
     128                                swatches[ i ].setAttribute( 'tabindex', tabindex );
     129                        }
    123130                }
    124131        }
  • chiseiko-essential-swatches/trunk/assets/js/chiseikoessw-frontend.min.js

    r3598460 r3778841  
    1 !function(){"use strict";function e(){document.addEventListener("click",function(e){var t=e.target.closest(".chiseikoessw-swatch");t&&(t.closest(".chiseikoessw-card-swatches")?e.preventDefault():"true"!==t.getAttribute("aria-disabled")?(e.preventDefault(),i(t)):e.preventDefault())}),document.addEventListener("keydown",s),function(){if(!document.querySelector(".chiseikoessw-sr-live-region")){var e=document.createElement("div");e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),e.className="chiseikoessw-sr-live-region",e.style.cssText="position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;",document.body.appendChild(e)}}(),document.querySelectorAll("form.variations_form").forEach(a),document.querySelectorAll(".chiseikoessw-swatches").forEach(r),function(){if(window.MutationObserver){var e=new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){1===e.nodeType&&(e.matches&&e.matches("form.variations_form")&&(a(e),e.querySelectorAll(".chiseikoessw-swatches").forEach(r)),e.querySelectorAll&&e.querySelectorAll("form.variations_form").forEach(function(e){a(e),e.querySelectorAll(".chiseikoessw-swatches").forEach(r)}))})})}),t=document.querySelector(".woocommerce, #content, #main")||document.body;e.observe(t,{childList:!0,subtree:!0})}}()}function t(e,t){e.querySelectorAll(".chiseikoessw-swatch").forEach(function(e){var r=e.dataset.value===t&&""!==t;e.classList.toggle("chiseikoessw-swatch--selected",r),e.setAttribute("aria-checked",r?"true":"false")})}function r(e){if(!e.closest(".chiseikoessw-card-swatches")){var t=Array.from(e.querySelectorAll(".chiseikoessw-swatch"));if(0!==t.length)for(var r=e.querySelector(".chiseikoessw-swatch--selected")||e.querySelector(".chiseikoessw-swatch:not(.chiseikoessw-swatch--disabled)")||t[0],s=0;s<t.length;s++)t[s].setAttribute("tabindex",t[s]===r?"0":"-1")}}function s(e){var t=e.target.closest(".chiseikoessw-swatch");if(t&&!t.closest(".chiseikoessw-card-swatches")){var r="ArrowLeft"===e.key||"Left"===e.key,s="ArrowRight"===e.key||"Right"===e.key,a="Home"===e.key,i="End"===e.key;if(r||s||a||i){e.preventDefault();var o=t.closest(".chiseikoessw-swatches");if(o){var c=Array.from(o.querySelectorAll(".chiseikoessw-swatch:not(.chiseikoessw-swatch--disabled)"));if(0!==c.length){var n=c.indexOf(t),l=c[a?0:i?c.length-1:s?n<c.length-1?n+1:0:n>0?n-1:c.length-1];t.setAttribute("tabindex","-1"),l.setAttribute("tabindex","0"),l.focus()}}}}}function a(e){n(e),function(e){var r=new URLSearchParams(window.location.search),s=!1;e.querySelectorAll(".chiseikoessw-swatches").forEach(function(a){var i=a.dataset.attribute_name;if(i){var o=r.get(i);if(o){var c=a.querySelector('.chiseikoessw-swatch[data-value="'+CSS.escape(o)+'"]');if(c&&"true"!==c.getAttribute("aria-disabled")){t(a,o);var n=e.querySelector('select[name="'+i+'"]');n&&(n.value=o,n.dispatchEvent(new Event("change",{bubbles:!0}))),s=!0}}}}),s&&n(e)}(e);var s=window.CHISEIKOESSW_Utils&&window.CHISEIKOESSW_Utils.WC;s&&(s.onVariationEvent(e,"found_variation.chiseikoessw",u),s.onVariationEvent(e,"reset_data.chiseikoessw",function(){!function(e){t(e,""),n(e),d(e),e.querySelectorAll(".chiseikoessw-swatches").forEach(r),e.querySelectorAll(".chiseikoessw-accordion__selected-value").forEach(function(e){e.textContent="",e.setAttribute("hidden","")})}(e)}),s.onVariationEvent(e,"reload_product_variations.chiseikoessw update_variation_values.chiseikoessw",function(){o.delete(e),c.delete(e),n(e)}))}function i(e){var s=e.closest(".chiseikoessw-swatches");if(s){var a=s.dataset.attribute_name,i=e.dataset.value,o=e.classList.contains("chiseikoessw-swatch--selected")?"":i;t(s,o),r(s);var c=s.getAttribute("aria-label")||"",l=e.getAttribute("aria-label")||e.getAttribute("title")||i;(function(e){var t=document.querySelector(".chiseikoessw-sr-live-region");t&&(t.textContent=e)})(""!==o?c+": "+l+" selected":c+": selection cleared"),setTimeout(function(){""!==o&&function(e){var t=e.dataset.chiseikoesswPreviewSrc;if(t){var r=e.closest("form.variations_form, .product");if(r)h(r,{src:t,srcset:e.dataset.chiseikoesswPreviewSrcset||"",sizes:e.dataset.chiseikoesswPreviewSizes||"",alt:e.dataset.chiseikoesswPreviewAlt||""})}}(e);var r=s.closest("form.variations_form, .product"),i=r&&r.querySelector('select[name="'+a+'"]'),c=[];""!==o&&r&&r.querySelectorAll(".chiseikoessw-swatches").forEach(function(e){if(e!==s){var t=e.dataset.attribute_name,a=r.querySelector('select[name="'+t+'"]');a&&a.value&&c.push({group:e,value:a.value,select:a})}}),i&&(i.value=o,i.dispatchEvent(new Event("change",{bubbles:!0}))),t(s,o);for(var l=0;l<c.length;l++){var u=c[l];t(u.group,u.value),u.select&&!u.select.value&&(u.select.value=u.value)}!function(e){e&&e.querySelectorAll(".chiseikoessw-accordion").forEach(function(e){var t=e.querySelector(".chiseikoessw-accordion__selected-value");if(t){var r=e.querySelector(".chiseikoessw-swatch--selected");if(r){var s=r.getAttribute("aria-label")||r.getAttribute("title")||"";if(s)return t.textContent=s,void t.removeAttribute("hidden")}t.textContent="",t.setAttribute("hidden","")}})}(s.closest("form.variations_form"));var f=s.closest("form.variations_form");f&&n(f),d(s.closest("form.variations_form"))},0)}}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e();var o=new WeakMap,c=new WeakMap;function n(e){var t=function(e){var t=e.dataset.product_variations;if(!t)return null;var r,s=o.get(e);if(s&&s._raw===t)return s;try{r=JSON.parse(t)}catch(e){return null}if(!Array.isArray(r)||0===r.length)return null;for(var a=r[0]&&r[0].attributes?Object.keys(r[0].attributes):[],i=[],c=0;c<r.length;c++){var n=r[c];n.variation_is_active&&n.is_purchasable&&n.is_in_stock&&i.push(n)}var l={variations:r,viableVars:i,attrKeys:a,_raw:t};return o.set(e,l),l}(e);if(t){var s={};e.querySelectorAll('select[name^="attribute_"]').forEach(function(e){s[e.name]=e.value});var a=JSON.stringify(s),n=c.get(e);if(!n||n.key!==a){var u=t.viableVars;e.querySelectorAll(".chiseikoessw-swatches").forEach(function(e){var t=e.dataset.attribute_name;e.querySelectorAll(".chiseikoessw-swatch").forEach(function(e){for(var r=e.dataset.value,a=!1,i=0;i<u.length;i++)if(l(u[i].attributes,s,t,r)){a=!0;break}e.classList.toggle("chiseikoessw-swatch--disabled",!a),e.setAttribute("aria-disabled",a?"false":"true")});var r=Array.from(e.querySelectorAll(".chiseikoessw-swatch:not(.chiseikoessw-swatch--disabled)")),a=e.querySelector(".chiseikoessw-swatch--selected");1!==r.length||a||i(r[0])}),e.querySelectorAll(".chiseikoessw-swatches").forEach(r),c.set(e,{key:a})}}}function l(e,t,r,s){for(var a=Object.keys(t),i=0;i<a.length;i++){var o=a[i],c=e[o]||"";if(""!==c){var n=o===r?s:t[o]||"";if(""!==n&&c!==n)return!1}}return!0}function u(e,t){var r=e.currentTarget;t&&t.image&&t.image.src&&h(r,t.image),n(r)}function h(e,t){var r=e.closest(".product");if(r){var s=r.querySelector(".woocommerce-product-gallery");if(s){var a=window.CHISEIKOESSW_Utils&&window.CHISEIKOESSW_Utils.WC;if(a&&a.hasClassicGalleryManager(s))return;var i=s.querySelector(".woocommerce-product-gallery__image a img, .flex-active-slide img, .woocommerce-product-gallery__image img");if(i)return void f(i,t)}var o=r.querySelector(".wp-block-woocommerce-product-image-gallery, .wc-block-product-image-gallery");if(o){var c=o.querySelector("img");if(c)return void f(c,t)}var n=r.querySelector("img.wp-post-image, img.attachment-woocommerce_thumbnail");n&&f(n,t)}}function f(e,t){t.src&&(e.src=t.src),t.srcset&&(e.srcset=t.srcset),t.sizes&&(e.sizes=t.sizes),t.alt&&(e.alt=t.alt)}function d(e){if(e&&window.history&&window.history.replaceState){var t=new URL(window.location.href),r=t.searchParams;e.querySelectorAll('select[name^="attribute_"]').forEach(function(e){e.value?r.set(e.name,e.value):r.delete(e.name)});var s=t.toString();s!==window.location.href&&window.history.replaceState(null,"",s)}}}();
     1!function(){"use strict";function e(){document.addEventListener("click",function(e){var t=e.target.closest(".chiseikoessw-swatch");t&&(t.closest(".chiseikoessw-card-swatches")?e.preventDefault():"true"!==t.getAttribute("aria-disabled")?(e.preventDefault(),i(t)):e.preventDefault())}),document.addEventListener("keydown",s),function(){if(!document.querySelector(".chiseikoessw-sr-live-region")){var e=document.createElement("div");e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),e.className="chiseikoessw-sr-live-region",e.style.cssText="position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;",document.body.appendChild(e)}}(),document.querySelectorAll("form.variations_form").forEach(a),document.querySelectorAll(".chiseikoessw-swatches").forEach(r),function(){if(window.MutationObserver){var e=new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){1===e.nodeType&&(e.matches&&e.matches("form.variations_form")&&(a(e),e.querySelectorAll(".chiseikoessw-swatches").forEach(r)),e.querySelectorAll&&e.querySelectorAll("form.variations_form").forEach(function(e){a(e),e.querySelectorAll(".chiseikoessw-swatches").forEach(r)}))})})}),t=document.querySelector(".woocommerce, #content, #main")||document.body;e.observe(t,{childList:!0,subtree:!0})}}()}function t(e,t){e.querySelectorAll(".chiseikoessw-swatch").forEach(function(e){var r=e.dataset.value===t&&""!==t;e.classList.toggle("chiseikoessw-swatch--selected",r),e.setAttribute("aria-checked",r?"true":"false")})}function r(e){if(!e.closest(".chiseikoessw-card-swatches")){var t=Array.from(e.querySelectorAll(".chiseikoessw-swatch"));if(0!==t.length)for(var r=e.querySelector(".chiseikoessw-swatch--selected")||e.querySelector(".chiseikoessw-swatch:not(.chiseikoessw-swatch--disabled)")||t[0],s=0;s<t.length;s++){var a=t[s]===r?"0":"-1";t[s].getAttribute("tabindex")!==a&&t[s].setAttribute("tabindex",a)}}}function s(e){var t=e.target.closest(".chiseikoessw-swatch");if(t&&!t.closest(".chiseikoessw-card-swatches")){var r="ArrowLeft"===e.key||"Left"===e.key,s="ArrowRight"===e.key||"Right"===e.key,a="Home"===e.key,i="End"===e.key;if(r||s||a||i){e.preventDefault();var o=t.closest(".chiseikoessw-swatches");if(o){var c=Array.from(o.querySelectorAll(".chiseikoessw-swatch:not(.chiseikoessw-swatch--disabled)"));if(0!==c.length){var n=c.indexOf(t),l=c[a?0:i?c.length-1:s?n<c.length-1?n+1:0:n>0?n-1:c.length-1];t.setAttribute("tabindex","-1"),l.setAttribute("tabindex","0"),l.focus()}}}}}function a(e){n(e),function(e){var r=new URLSearchParams(window.location.search),s=!1;e.querySelectorAll(".chiseikoessw-swatches").forEach(function(a){var i=a.dataset.attribute_name;if(i){var o=r.get(i);if(o){var c=a.querySelector('.chiseikoessw-swatch[data-value="'+CSS.escape(o)+'"]');if(c&&"true"!==c.getAttribute("aria-disabled")){t(a,o);var n=e.querySelector('select[name="'+i+'"]');n&&(n.value=o,n.dispatchEvent(new Event("change",{bubbles:!0}))),s=!0}}}}),s&&n(e)}(e);var s=window.CHISEIKOESSW_Utils&&window.CHISEIKOESSW_Utils.WC;s&&(s.onVariationEvent(e,"found_variation.chiseikoessw",u),s.onVariationEvent(e,"reset_data.chiseikoessw",function(){!function(e){t(e,""),n(e),f(e),e.querySelectorAll(".chiseikoessw-swatches").forEach(r),e.querySelectorAll(".chiseikoessw-accordion__selected-value").forEach(function(e){e.textContent="",e.setAttribute("hidden","")})}(e)}),s.onVariationEvent(e,"reload_product_variations.chiseikoessw update_variation_values.chiseikoessw",function(){o.delete(e),c.delete(e),n(e)}))}function i(e){var s=e.closest(".chiseikoessw-swatches");if(s){var a=s.dataset.attribute_name,i=e.dataset.value,o=e.classList.contains("chiseikoessw-swatch--selected")?"":i;t(s,o),r(s);var c=s.getAttribute("aria-label")||"",l=e.getAttribute("aria-label")||e.getAttribute("title")||i;(function(e){var t=document.querySelector(".chiseikoessw-sr-live-region");t&&(t.textContent=e)})(""!==o?c+": "+l+" selected":c+": selection cleared"),setTimeout(function(){""!==o&&function(e){var t=e.dataset.chiseikoesswPreviewSrc;if(t){var r=e.closest("form.variations_form, .product");if(r)h(r,{src:t,srcset:e.dataset.chiseikoesswPreviewSrcset||"",sizes:e.dataset.chiseikoesswPreviewSizes||"",alt:e.dataset.chiseikoesswPreviewAlt||""})}}(e);var r=s.closest("form.variations_form, .product"),i=r&&r.querySelector('select[name="'+a+'"]'),c=[];""!==o&&r&&r.querySelectorAll(".chiseikoessw-swatches").forEach(function(e){if(e!==s){var t=e.dataset.attribute_name,a=r.querySelector('select[name="'+t+'"]');a&&a.value&&c.push({group:e,value:a.value,select:a})}}),i&&(i.value=o,i.dispatchEvent(new Event("change",{bubbles:!0}))),t(s,o);for(var l=0;l<c.length;l++){var u=c[l];t(u.group,u.value),u.select&&!u.select.value&&(u.select.value=u.value)}!function(e){e&&e.querySelectorAll(".chiseikoessw-accordion").forEach(function(e){var t=e.querySelector(".chiseikoessw-accordion__selected-value");if(t){var r=e.querySelector(".chiseikoessw-swatch--selected");if(r){var s=r.getAttribute("aria-label")||r.getAttribute("title")||"";if(s)return t.textContent=s,void t.removeAttribute("hidden")}t.textContent="",t.setAttribute("hidden","")}})}(s.closest("form.variations_form"));var d=s.closest("form.variations_form");d&&n(d),f(s.closest("form.variations_form"))},0)}}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e();var o=new WeakMap,c=new WeakMap;function n(e){var t=function(e){var t=e.dataset.product_variations;if(!t)return null;var r,s=o.get(e);if(s&&s._raw===t)return s;try{r=JSON.parse(t)}catch(e){return null}if(!Array.isArray(r)||0===r.length)return null;for(var a=r[0]&&r[0].attributes?Object.keys(r[0].attributes):[],i=[],c=0;c<r.length;c++){var n=r[c];n.variation_is_active&&n.is_purchasable&&n.is_in_stock&&i.push(n)}var l={variations:r,viableVars:i,attrKeys:a,_raw:t};return o.set(e,l),l}(e);if(t){var s={};e.querySelectorAll('select[name^="attribute_"]').forEach(function(e){s[e.name]=e.value});var a=JSON.stringify(s),n=c.get(e);if(!n||n.key!==a){var u=t.viableVars;e.querySelectorAll(".chiseikoessw-swatches").forEach(function(e){var t=e.dataset.attribute_name;e.querySelectorAll(".chiseikoessw-swatch").forEach(function(e){for(var r=e.dataset.value,a=!1,i=0;i<u.length;i++)if(l(u[i].attributes,s,t,r)){a=!0;break}e.classList.toggle("chiseikoessw-swatch--disabled",!a),e.setAttribute("aria-disabled",a?"false":"true")});var r=Array.from(e.querySelectorAll(".chiseikoessw-swatch:not(.chiseikoessw-swatch--disabled)")),a=e.querySelector(".chiseikoessw-swatch--selected");1!==r.length||a||i(r[0])}),e.querySelectorAll(".chiseikoessw-swatches").forEach(r),c.set(e,{key:a})}}}function l(e,t,r,s){for(var a=Object.keys(t),i=0;i<a.length;i++){var o=a[i],c=e[o]||"";if(""!==c){var n=o===r?s:t[o]||"";if(""!==n&&c!==n)return!1}}return!0}function u(e,t){var r=e.currentTarget;t&&t.image&&t.image.src&&h(r,t.image),n(r)}function h(e,t){var r=e.closest(".product");if(r){var s=r.querySelector(".woocommerce-product-gallery");if(s){var a=window.CHISEIKOESSW_Utils&&window.CHISEIKOESSW_Utils.WC;if(a&&a.hasClassicGalleryManager(s))return;var i=s.querySelector(".woocommerce-product-gallery__image a img, .flex-active-slide img, .woocommerce-product-gallery__image img");if(i)return void d(i,t)}var o=r.querySelector(".wp-block-woocommerce-product-image-gallery, .wc-block-product-image-gallery");if(o){var c=o.querySelector("img");if(c)return void d(c,t)}var n=r.querySelector("img.wp-post-image, img.attachment-woocommerce_thumbnail");n&&d(n,t)}}function d(e,t){t.src&&(e.src=t.src),t.srcset&&(e.srcset=t.srcset),t.sizes&&(e.sizes=t.sizes),t.alt&&(e.alt=t.alt)}function f(e){if(e&&window.history&&window.history.replaceState){var t=new URL(window.location.href),r=t.searchParams;e.querySelectorAll('select[name^="attribute_"]').forEach(function(e){e.value?r.set(e.name,e.value):r.delete(e.name)});var s=t.toString();s!==window.location.href&&window.history.replaceState(null,"",s)}}}();
  • chiseiko-essential-swatches/trunk/assets/js/chiseikoessw-utils.js

    r3598460 r3778841  
    479479                $gallery.off( 'click', '.woocommerce-product-gallery__image a' );
    480480
    481                 $gallery.wc_product_gallery();
    482                 return true;
     481                // Unbind the handlers the PREVIOUS re-init added (see
     482                // REINIT_STACKED_EVENTS), then record the ones this init adds.
     483                var previous = galleryReinitHandlers ? galleryReinitHandlers.get( gallery ) : null;
     484                if ( previous ) {
     485                        for ( var p = 0; p < previous.jquery.length; p++ ) {
     486                                global.jQuery( previous.jquery[ p ].target ).off( previous.jquery[ p ].type, previous.jquery[ p ].handler );
     487                        }
     488                        for ( var n = 0; n < previous.native.length; n++ ) {
     489                                previous.native[ n ].target.removeEventListener( previous.native[ n ].type, previous.native[ n ].listener, previous.native[ n ].options );
     490                        }
     491                }
     492                var before = snapshotReinitHandlers( gallery );
     493
     494                var native = captureNativeListeners( gallery, function () {
     495                        $gallery.wc_product_gallery();
     496                } );
     497
     498                if ( galleryReinitHandlers ) {
     499                        galleryReinitHandlers.set( gallery, {
     500                                jquery: diffReinitHandlers( before, snapshotReinitHandlers( gallery ) ),
     501                                native: native,
     502                        } );
     503                }
     504                return true;
     505        }
     506
     507        /**
     508         * Events `wc_product_gallery()` binds on EVERY init and never unbinds:
     509         *  - Flexslider: window `resize`/`orientationchange`/`focus` (resize logic)
     510         *    and document `keyup` (keyboard nav);
     511         *  - WooCommerce's ProductGallery constructor: `woocommerce_gallery_init_zoom`
     512         *    and `woocommerce_gallery_reset_slide_position` on the gallery element.
     513         * Flexslider also adds ANONYMOUS native listeners — document
     514         * `visibilitychange` (`pauseInvisible`, on by default) and, on touch
     515         * devices, `touchstart`/`touchmove` on the gallery element —
     516         * which are captured during the synchronous init (captureNativeListeners).
     517         * Each re-init therefore stacked another set. Every stacked handler kept its
     518         * old slider / ProductGallery — and through `$images` the detached slides —
     519         * alive (≈35 DOM nodes and ≈20 listeners per variation gallery swap), and
     520         * every stacked init-zoom handler re-ran zoom setup on each zoom refresh.
     521         */
     522        var REINIT_STACKED_EVENTS = [
     523                [ 'window', 'resize' ],
     524                [ 'window', 'orientationchange' ],
     525                [ 'window', 'focus' ],
     526                [ 'document', 'keyup' ],
     527                [ 'gallery', 'woocommerce_gallery_init_zoom' ],
     528                [ 'gallery', 'woocommerce_gallery_reset_slide_position' ],
     529        ];
     530
     531        /** gallery element → handlers its last re-init added (see above). */
     532        var galleryReinitHandlers = typeof WeakMap === 'function' ? new WeakMap() : null;
     533
     534        /**
     535         * Lists the jQuery handlers currently bound for REINIT_STACKED_EVENTS.
     536         *
     537         * @param {Element} gallery The `.woocommerce-product-gallery` element.
     538         * @returns {Array<{target: Object, type: string, handler: Function}>}
     539         */
     540        function snapshotReinitHandlers( gallery ) {
     541                var out = [];
     542                var $   = global.jQuery;
     543                if ( ! $ || typeof $._data !== 'function' ) return out;
     544                var targets = { window: global, document: global.document, gallery: gallery };
     545                for ( var i = 0; i < REINIT_STACKED_EVENTS.length; i++ ) {
     546                        var target = targets[ REINIT_STACKED_EVENTS[ i ][ 0 ] ];
     547                        var type   = REINIT_STACKED_EVENTS[ i ][ 1 ];
     548                        var events = target ? $._data( target, 'events' ) : null;
     549                        var list   = events && events[ type ] ? events[ type ] : [];
     550                        for ( var j = 0; j < list.length; j++ ) {
     551                                out.push( { target: target, type: type, handler: list[ j ].handler } );
     552                        }
     553                }
     554                return out;
     555        }
     556
     557        /**
     558         * Runs `fn` while recording the anonymous native listeners Flexslider adds
     559         * on every init (document `visibilitychange`; gallery `touchstart` /
     560         * `touchmove`), so they can be removed later. Only those event types on
     561         * those targets are recorded: a listener a third party binds during the
     562         * init (e.g. from a `wc-product-gallery-after-init` callback) for any other
     563         * event or target is kept. jQuery's shared per-element dispatcher is
     564         * excluded: removing it would silence every jQuery handler of that type,
     565         * and jQuery-bound handlers are tracked separately (snapshotReinitHandlers).
     566         *
     567         * @param {Element}  gallery The `.woocommerce-product-gallery` element.
     568         * @param {Function} fn
     569         * @returns {Array<{target: EventTarget, type: string, listener: *, options: *}>}
     570         */
     571        function captureNativeListeners( gallery, fn ) {
     572                var proto = global.EventTarget && global.EventTarget.prototype;
     573                if ( ! proto ) {
     574                        fn();
     575                        return [];
     576                }
     577                var original = proto.addEventListener;
     578                var captured = [];
     579                proto.addEventListener = function ( type, listener, options ) {
     580                        if ( ( this === global.document && 'visibilitychange' === type ) || ( this === gallery && /^touch(start|move)$/.test( type ) ) ) {
     581                                captured.push( { target: this, type: type, listener: listener, options: options } );
     582                        }
     583                        return original.apply( this, arguments );
     584                };
     585                try {
     586                        fn();
     587                } finally {
     588                        proto.addEventListener = original;
     589                }
     590                var $ = global.jQuery;
     591                return captured.filter( function ( c ) {
     592                        var data = $ && typeof $._data === 'function' ? $._data( c.target ) : null;
     593                        return ! data || c.listener !== data.handle;
     594                } );
     595        }
     596
     597        /**
     598         * Returns the entries of `after` that were not present in `before`.
     599         *
     600         * @param {Array} before
     601         * @param {Array} after
     602         * @returns {Array}
     603         */
     604        function diffReinitHandlers( before, after ) {
     605                return after.filter( function ( a ) {
     606                        return ! before.some( function ( b ) {
     607                                return b.target === a.target && b.type === a.type && b.handler === a.handler;
     608                        } );
     609                } );
    483610        }
    484611
  • chiseiko-essential-swatches/trunk/assets/js/chiseikoessw-utils.min.js

    r3598460 r3778841  
    1 !function(e){"use strict";var r=new Set(["SCRIPT","IFRAME","OBJECT","EMBED","FORM","STYLE","LINK","SVG","MATH","TEMPLATE","BASE","APPLET","META","NOSCRIPT"]);function t(e){for(var o=e.firstChild;o;){var n=o.nextSibling;if(1===o.nodeType)if(r.has(o.tagName))e.removeChild(o);else{for(var c=o.attributes,i=c.length-1;i>=0;i--){var a=c[i].name.toLowerCase();0!==a.indexOf("on")&&"srcdoc"!==a&&"formaction"!==a||o.removeAttribute(c[i].name)}["href","src","action"].forEach(function(e){var r=o.getAttribute(e);r&&/^\s*javascript\s*:/i.test(r)&&o.removeAttribute(e)}),t(o)}o=n}}var o=[".related",".up-sells",".upsells",".cross-sells",".products",".woocommerce-grouped-product-list",".wc-block-product",".wc-block-grid",".wc-block-grid__product",".wc-block-grid__products",".wc-block-product-template",".wp-block-post-template",".wc-block-featured-products",".wc-block-handpicked-products",".wc-block-related-products",".wc-block-all-products",".wp-block-woocommerce-related-products",".wp-block-woocommerce-cross-sells",".wp-block-woocommerce-up-sells","#chiseikoessw-pro-sticky-bar",".chiseikoessw-linked-swatches",".chiseikoessw-card-swatches"].join(",");e.CHISEIKOESSW_Utils={debounce:function(e,r){var t;return function(){var o=this,n=arguments;clearTimeout(t),t=setTimeout(function(){e.apply(o,n)},r)}},throttle:function(e,r){var t=0;return function(){var o=Date.now();o-t>=r&&(t=o,e.apply(this,arguments))}},hasAnyInStock:function(e,r,t){return Object.values(e).some(function(e){var o=e.attributes||{};return(o[r]===t||""===o[r])&&e.is_in_stock})},hasAnyInStockFiltered:function(e,r,t,o){return Object.values(e).some(function(e){var n=e.attributes||{};if(n[r]!==t&&""!==n[r])return!1;for(var c in o)if(c!==r&&""!==n[c]&&n[c]!==o[c])return!1;return e.is_in_stock})},swapCardImage:function(e,r,t,o){var n=t(e);if(n&&r.image){var c=r.image;if(c.src){e.classList.add(o);var i=new Image;i.onload=function(){n.src=c.src,n.srcset=c.srcset||"",e.classList.remove(o)},i.onerror=function(){e.classList.remove(o)},i.src=c.src}}},applyRoving:function(e,r,t,o){var n=Array.from(e.querySelectorAll(r));if(0!==n.length)for(var c=e.querySelector("."+t)||e.querySelector(r+":not(."+o+")")||n[0],i=0;i<n.length;i++)n[i].setAttribute("tabindex",n[i]===c?"0":"-1")},handleRovingKeydown:function(e,r,t,o){var n=e.target.closest(r);if(!n)return!1;var c="ArrowLeft"===e.key||"Left"===e.key,i="ArrowRight"===e.key||"Right"===e.key,a="Home"===e.key,u="End"===e.key;if(!(c||i||a||u))return!1;var s=n.closest(t);if(!s)return!1;var l=Array.from(s.querySelectorAll(r+":not(."+o+")"));if(0===l.length)return!1;var f,d=l.indexOf(n);return f=a?0:u?l.length-1:i?d<l.length-1?d+1:0:d>0?d-1:l.length-1,n.setAttribute("tabindex","-1"),l[f].setAttribute("tabindex","0"),l[f].focus(),!0},sanitizePriceHtml:function(e){var r=document.createRange().createContextualFragment(e);return t(r),r},PDP:{EXCLUDE_PRODUCT_CONTAINERS:o,resolveMainEl:function(r,t){for(var n=(t||e.document).querySelectorAll(r),c=0;c<n.length;c++)if(!n[c].closest(o))return n[c];return null},isSwapActive:function(){var r=e.document&&e.document.documentElement;return!!(r&&r.classList&&r.classList.contains("chiseikoessw-swap-loading"))},onMemberSwap:function r(t){return!(!e.document||"function"!=typeof t||(r._bound||(r._bound=[]),-1!==r._bound.indexOf(t)||(r._bound.push(t),e.document.addEventListener("chiseikoessw:linked:selected",t)),0))}},WC:{isAvailable:function(){return!!e.jQuery},onVariationEvent:function(r,t,o){return!!e.jQuery&&(e.jQuery(r).on(t,o),!0)},hasClassicGalleryManager:function(r){return!(!e.jQuery||!r||!e.jQuery(r).data("product_gallery"))},applyCartFragments:function(r,t,o){if(!e.jQuery||!r)return!1;if(e.jQuery.each(r,function(r,t){e.jQuery(r).replaceWith(t)}),t)try{sessionStorage.setItem("wc_cart_hash",t)}catch(e){}return e.jQuery(document.body).trigger("added_to_cart",[r,t,o]),!0},setJqueryData:function(r,t,o){return!(!e.jQuery||!r||(e.jQuery(r).data(t,o),0))},clearClassicGalleryManager:function(r){if(!e.jQuery||!r)return!1;var t=e.jQuery(r);return t.data("flexslider")&&t.removeData("flexslider"),t.removeData("product_gallery"),!0},reinitClassicGallery:function(r){if(!e.jQuery||!r)return!1;var t=e.jQuery(r);return"function"==typeof t.wc_product_gallery&&(t.off("click",".woocommerce-product-gallery__trigger"),t.off("keydown",".woocommerce-product-gallery__trigger"),t.off("click",".woocommerce-product-gallery__image a"),t.wc_product_gallery(),!0)},refreshGalleryZoom:function(r){return!(!e.jQuery||!r||(e.jQuery(r).trigger("woocommerce_gallery_init_zoom"),0))},reinitProductTabs:function(r){if(!e.jQuery)return!1;var t=(r||e.document).querySelectorAll(".wc-tabs-wrapper, .woocommerce-tabs, #rating");return!!t.length&&(e.jQuery(t).trigger("init"),!0)},triggerZoomDestroy:function(r){if(!e.jQuery||!r)return!1;var t=e.jQuery(r);if(!t.length)return!1;try{t.trigger("zoom.destroy")}catch(e){}return!0},offZoomEvents:function(r){if(!e.jQuery||!r)return!1;var t=e.jQuery(r);return!!t.length&&(t.off("mouseenter.zoom mousemove.zoom mouseleave.zoom"),!0)},onZoomDestroy:function(r,t,o){if(!e.jQuery||!r)return!1;var n="zoom.destroy."+t;return e.jQuery(r).off(n).on(n,o),!0},reinitVariationForm:function(r,t){if(!e.jQuery||!r)return!1;var o=e.jQuery(r);return o.data("product_variations",t),o.find('select[name^="attribute_"]').val("").trigger("change"),o.find("input.variation_id").val("").trigger("change"),"function"==typeof o.wc_variation_form?o.wc_variation_form():o.trigger("check_variations"),!0}}}}(window);
     1!function(e){"use strict";var r=new Set(["SCRIPT","IFRAME","OBJECT","EMBED","FORM","STYLE","LINK","SVG","MATH","TEMPLATE","BASE","APPLET","META","NOSCRIPT"]);function t(e){for(var n=e.firstChild;n;){var o=n.nextSibling;if(1===n.nodeType)if(r.has(n.tagName))e.removeChild(n);else{for(var i=n.attributes,a=i.length-1;a>=0;a--){var u=i[a].name.toLowerCase();0!==u.indexOf("on")&&"srcdoc"!==u&&"formaction"!==u||n.removeAttribute(i[a].name)}["href","src","action"].forEach(function(e){var r=n.getAttribute(e);r&&/^\s*javascript\s*:/i.test(r)&&n.removeAttribute(e)}),t(n)}n=o}}var n=[["window","resize"],["window","orientationchange"],["window","focus"],["document","keyup"],["gallery","woocommerce_gallery_init_zoom"],["gallery","woocommerce_gallery_reset_slide_position"]],o="function"==typeof WeakMap?new WeakMap:null;function i(r){var t=[],o=e.jQuery;if(!o||"function"!=typeof o._data)return t;for(var i={window:e,document:e.document,gallery:r},a=0;a<n.length;a++)for(var u=i[n[a][0]],c=n[a][1],s=u?o._data(u,"events"):null,l=s&&s[c]?s[c]:[],f=0;f<l.length;f++)t.push({target:u,type:c,handler:l[f].handler});return t}function a(e,r){return r.filter(function(r){return!e.some(function(e){return e.target===r.target&&e.type===r.type&&e.handler===r.handler})})}var u=[".related",".up-sells",".upsells",".cross-sells",".products",".woocommerce-grouped-product-list",".wc-block-product",".wc-block-grid",".wc-block-grid__product",".wc-block-grid__products",".wc-block-product-template",".wp-block-post-template",".wc-block-featured-products",".wc-block-handpicked-products",".wc-block-related-products",".wc-block-all-products",".wp-block-woocommerce-related-products",".wp-block-woocommerce-cross-sells",".wp-block-woocommerce-up-sells","#chiseikoessw-pro-sticky-bar",".chiseikoessw-linked-swatches",".chiseikoessw-card-swatches"].join(",");e.CHISEIKOESSW_Utils={debounce:function(e,r){var t;return function(){var n=this,o=arguments;clearTimeout(t),t=setTimeout(function(){e.apply(n,o)},r)}},throttle:function(e,r){var t=0;return function(){var n=Date.now();n-t>=r&&(t=n,e.apply(this,arguments))}},hasAnyInStock:function(e,r,t){return Object.values(e).some(function(e){var n=e.attributes||{};return(n[r]===t||""===n[r])&&e.is_in_stock})},hasAnyInStockFiltered:function(e,r,t,n){return Object.values(e).some(function(e){var o=e.attributes||{};if(o[r]!==t&&""!==o[r])return!1;for(var i in n)if(i!==r&&""!==o[i]&&o[i]!==n[i])return!1;return e.is_in_stock})},swapCardImage:function(e,r,t,n){var o=t(e);if(o&&r.image){var i=r.image;if(i.src){e.classList.add(n);var a=new Image;a.onload=function(){o.src=i.src,o.srcset=i.srcset||"",e.classList.remove(n)},a.onerror=function(){e.classList.remove(n)},a.src=i.src}}},applyRoving:function(e,r,t,n){var o=Array.from(e.querySelectorAll(r));if(0!==o.length)for(var i=e.querySelector("."+t)||e.querySelector(r+":not(."+n+")")||o[0],a=0;a<o.length;a++)o[a].setAttribute("tabindex",o[a]===i?"0":"-1")},handleRovingKeydown:function(e,r,t,n){var o=e.target.closest(r);if(!o)return!1;var i="ArrowLeft"===e.key||"Left"===e.key,a="ArrowRight"===e.key||"Right"===e.key,u="Home"===e.key,c="End"===e.key;if(!(i||a||u||c))return!1;var s=o.closest(t);if(!s)return!1;var l=Array.from(s.querySelectorAll(r+":not(."+n+")"));if(0===l.length)return!1;var f,d=l.indexOf(o);return f=u?0:c?l.length-1:a?d<l.length-1?d+1:0:d>0?d-1:l.length-1,o.setAttribute("tabindex","-1"),l[f].setAttribute("tabindex","0"),l[f].focus(),!0},sanitizePriceHtml:function(e){var r=document.createRange().createContextualFragment(e);return t(r),r},PDP:{EXCLUDE_PRODUCT_CONTAINERS:u,resolveMainEl:function(r,t){for(var n=(t||e.document).querySelectorAll(r),o=0;o<n.length;o++)if(!n[o].closest(u))return n[o];return null},isSwapActive:function(){var r=e.document&&e.document.documentElement;return!!(r&&r.classList&&r.classList.contains("chiseikoessw-swap-loading"))},onMemberSwap:function r(t){return!(!e.document||"function"!=typeof t||(r._bound||(r._bound=[]),-1!==r._bound.indexOf(t)||(r._bound.push(t),e.document.addEventListener("chiseikoessw:linked:selected",t)),0))}},WC:{isAvailable:function(){return!!e.jQuery},onVariationEvent:function(r,t,n){return!!e.jQuery&&(e.jQuery(r).on(t,n),!0)},hasClassicGalleryManager:function(r){return!(!e.jQuery||!r||!e.jQuery(r).data("product_gallery"))},applyCartFragments:function(r,t,n){if(!e.jQuery||!r)return!1;if(e.jQuery.each(r,function(r,t){e.jQuery(r).replaceWith(t)}),t)try{sessionStorage.setItem("wc_cart_hash",t)}catch(e){}return e.jQuery(document.body).trigger("added_to_cart",[r,t,n]),!0},setJqueryData:function(r,t,n){return!(!e.jQuery||!r||(e.jQuery(r).data(t,n),0))},clearClassicGalleryManager:function(r){if(!e.jQuery||!r)return!1;var t=e.jQuery(r);return t.data("flexslider")&&t.removeData("flexslider"),t.removeData("product_gallery"),!0},reinitClassicGallery:function(r){if(!e.jQuery||!r)return!1;var t=e.jQuery(r);if("function"!=typeof t.wc_product_gallery)return!1;t.off("click",".woocommerce-product-gallery__trigger"),t.off("keydown",".woocommerce-product-gallery__trigger"),t.off("click",".woocommerce-product-gallery__image a");var n=o?o.get(r):null;if(n){for(var u=0;u<n.jquery.length;u++)e.jQuery(n.jquery[u].target).off(n.jquery[u].type,n.jquery[u].handler);for(var c=0;c<n.native.length;c++)n.native[c].target.removeEventListener(n.native[c].type,n.native[c].listener,n.native[c].options)}var s=i(r),l=function(r,t){var n=e.EventTarget&&e.EventTarget.prototype;if(!n)return t(),[];var o=n.addEventListener,i=[];n.addEventListener=function(t,n,a){return(this===e.document&&"visibilitychange"===t||this===r&&/^touch(start|move)$/.test(t))&&i.push({target:this,type:t,listener:n,options:a}),o.apply(this,arguments)};try{t()}finally{n.addEventListener=o}var a=e.jQuery;return i.filter(function(e){var r=a&&"function"==typeof a._data?a._data(e.target):null;return!r||e.listener!==r.handle})}(r,function(){t.wc_product_gallery()});return o&&o.set(r,{jquery:a(s,i(r)),native:l}),!0},refreshGalleryZoom:function(r){return!(!e.jQuery||!r||(e.jQuery(r).trigger("woocommerce_gallery_init_zoom"),0))},reinitProductTabs:function(r){if(!e.jQuery)return!1;var t=(r||e.document).querySelectorAll(".wc-tabs-wrapper, .woocommerce-tabs, #rating");return!!t.length&&(e.jQuery(t).trigger("init"),!0)},triggerZoomDestroy:function(r){if(!e.jQuery||!r)return!1;var t=e.jQuery(r);if(!t.length)return!1;try{t.trigger("zoom.destroy")}catch(e){}return!0},offZoomEvents:function(r){if(!e.jQuery||!r)return!1;var t=e.jQuery(r);return!!t.length&&(t.off("mouseenter.zoom mousemove.zoom mouseleave.zoom"),!0)},onZoomDestroy:function(r,t,n){if(!e.jQuery||!r)return!1;var o="zoom.destroy."+t;return e.jQuery(r).off(o).on(o,n),!0},reinitVariationForm:function(r,t){if(!e.jQuery||!r)return!1;var n=e.jQuery(r);return n.data("product_variations",t),n.find('select[name^="attribute_"]').val("").trigger("change"),n.find("input.variation_id").val("").trigger("change"),"function"==typeof n.wc_variation_form?n.wc_variation_form():n.trigger("check_variations"),!0}}}}(window);
  • chiseiko-essential-swatches/trunk/chiseiko-essential-swatches.php

    r3598460 r3778841  
    44 * Plugin URI:        https://chiseikotech.com/chiseiko-essential-swatches/
    55 * Description:       Turn WooCommerce variation dropdowns into clickable color, image, text, and button swatches on product and shop pages.
    6  * Version:           1.0.0
     6 * Version:           1.1.0
    77 * Author:            Chiseiko LLC
    88 * Author URI:        https://chiseikotech.com
    … …  
    1515 * Requires Plugins:  woocommerce
    1616 * WC requires at least: 8.0
    17  * WC tested up to:      10.5
     17 * WC tested up to:      11.2.1
    1818 *
    1919 * @package ChiseikoEssentialSwatches
    … …  
    2929// ── Plugin constants ──────────────────────────────────────────────────────────
    3030
    31 define( 'CHISEIKOESSW_VERSION', '1.0.0' );
     31define( 'CHISEIKOESSW_VERSION', '1.1.0' );
    3232define( 'CHISEIKOESSW_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
    3333define( 'CHISEIKOESSW_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
    … …  
    130130                        new CHISEIKOESSW_Settings();
    131131                        new CHISEIKOESSW_User_Guide();
     132                        new CHISEIKOESSW_Plugin_Links();
     133                        // Getting-started notice for stores with no swatches configured yet.
     134                        // The review notice stays silent while this one is showing.
     135                        new CHISEIKOESSW_Onboarding_Notice();
     136                        new CHISEIKOESSW_Review_Notice();
     137                        // Attribute-wide default swatch type (Products → Attributes).
     138                        new CHISEIKOESSW_Attribute_Defaults();
    132139                }
    133140
    134141                new CHISEIKOESSW_Frontend();
     142
     143                // Global swatch shape/size (inline CSS tokens). Self-disables at the
     144                // default values and when Pro's Advanced Styling owns appearance.
     145                new CHISEIKOESSW_Appearance();
    135146
    136147                // Batch variation-data AJAX endpoint (used by chiseikoessw-utils.js CHISEIKOESSW_Batch).
  • chiseiko-essential-swatches/trunk/docs/chapters.json

    r3598460 r3778841  
    33    "slug": "installation",
    44    "title": "Installation",
     5    "num": 1,
    56    "edition": "free"
    67  },
    … …  
    89    "slug": "creating-attributes",
    910    "title": "Creating Attributes & Swatches",
     11    "num": 2,
    1012    "edition": "free"
    1113  },
    … …  
    1315    "slug": "variable-products",
    1416    "title": "Setting Up Variable Products",
     17    "num": 3,
    1518    "edition": "free"
    1619  },
    … …  
    1821    "slug": "settings",
    1922    "title": "Chiseiko Essential Swatches Settings",
     23    "num": 4,
     24    "edition": "free"
     25  },
     26  {
     27    "slug": "customizing-swatches",
     28    "title": "Customizing Swatches",
     29    "num": 25,
    2030    "edition": "free"
    2131  }
  • chiseiko-essential-swatches/trunk/docs/creating-attributes.html

    r3598460 r3778841  
    169169<p>That is perfectly fine! If you leave <strong>Swatch Type</strong> set to &quot;— Select type —&quot;, the term will still appear as a button on your product pages — it just shows the term&#39;s name as a text label (called a <strong>text pill</strong>). This is useful for &quot;Size&quot; attributes where colors don&#39;t make sense.</p>
    170170<hr>
     171<h2 id="set-a-default-swatch-type-for-a-whole-attribute">Set a Default Swatch Type for a Whole Attribute</h2>
     172<p>For attributes like &quot;Size&quot; or &quot;Material&quot;, where every term should look the same, you don&#39;t have to edit each term. Set the type once for the whole attribute instead:</p>
     173<ol>
     174<li>Go to <strong>Products → Attributes</strong> and click <strong>Edit</strong> under the attribute name (or fill in the form to add a new attribute).</li>
     175<li>In <strong>Default swatch type</strong>, choose <strong>Label buttons</strong> or <strong>Radio buttons</strong>.</li>
     176<li>Click <strong>Update</strong> (or <strong>Add attribute</strong>).</li>
     177</ol>
     178<p>Every term of that attribute now shows as a label (or radio) swatch on your product pages, including terms you add later. A term that has its <strong>own</strong> Swatch Type set keeps it — the default only fills in for terms left on &quot;— Select type —&quot;. To go back, choose <strong>None (set per term)</strong> and update the attribute.</p>
     179<blockquote>
     180<p><strong>Why only labels and radio buttons?</strong> Color and image swatches need a color or picture for each term, so those are always set per term (Steps 4–5 above).</p>
     181</blockquote>
     182<hr>
    171183<h2 id="the-swatch-preview-column">The Swatch Preview Column</h2>
    172184<p>On the Terms list screen, notice the <strong>Swatch</strong> column. It shows:</p>
    … …  
    188200<li>The <strong>Swatch Tooltips</strong> module — add <strong>hover tooltips</strong> that show the color name when a customer mouses over a swatch</li>
    189201</ul>
    190 <p>These are configured per-term on the same edit screens you just used. See <a href="{{CH:advanced-styling}}">Chapter 9 — Advanced Styling</a> for step-by-step instructions.</p>
    191 <hr>
     202<p>These are configured per-term on the same edit screens you just used. See Chapter 9 — Advanced Styling in the Pro user guide for step-by-step instructions.</p>
     203<hr>
  • chiseiko-essential-swatches/trunk/docs/installation.html

    r3598460 r3778841  
    1616<h3 id="step-2--activate-the-plugin">Step 2 — Activate the plugin</h3>
    1717<p>After installation, click <strong>Activate Plugin</strong>.</p>
    18 <p>You should now see <strong>&quot;Chiseiko Essential Swatches&quot;</strong> listed in your <strong>Plugins</strong> screen with a green &quot;Active&quot; badge.</p>
     18<p>You should now see <strong>&quot;Chiseiko Essential Swatches&quot;</strong> listed in your <strong>Plugins</strong> screen with a green &quot;Active&quot; badge. Under its name are two shortcuts: <strong>Settings</strong> opens the plugin&#39;s settings tab and <strong>Guide</strong> opens this user guide.</p>
     19<p>Until you have set up your first swatch, a <strong>getting-started notice</strong> appears at the top of the Plugins screen, the <strong>Products → Attributes</strong> screen, and the plugin&#39;s settings tab. Its buttons take you straight to the attributes screen, this guide, and the display settings. It disappears on its own once any attribute term has a swatch type (or an attribute has a default swatch type), and you can also dismiss it permanently with <strong>Dismiss</strong> or the <strong>×</strong>.</p>
     20<p>Once the plugin has been working for a while — 3 days after installation if at least one swatch is set up, or 14 days otherwise — store managers see a short <strong>review request</strong> on the plugin&#39;s own screens — Plugins, <strong>Products → Attributes</strong> and its term screens, the plugin&#39;s settings tab, and the guide — never elsewhere in wp-admin. <strong>Leave a review</strong> opens the review page and hides the request for good; <strong>I already did</strong> hides it for good too; <strong>Maybe later</strong> or the <strong>×</strong> hides it for 30 days. With Chiseiko Essential Swatches Pro installed, the request asks for a review of Pro on chiseikotech.com instead of WordPress.org. Each store manager&#39;s choice is remembered for their own account.</p>
    1921<blockquote>
    2022<p><strong>Tip:</strong> If you see a red notice saying WooCommerce is missing or needs to be updated, make sure WooCommerce is installed and active first, then refresh the page.</p>
    … …  
    4648<hr>
    4749<h2 id="what-gets-installed">What Gets Installed</h2>
    48 <p>When you activate the Free plugin, no new top-level menu is added — most configuration happens directly on your <strong>product attribute</strong> pages (covered in the next chapter). The Free plugin does add an <strong>Chiseiko Essential Swatches Settings</strong> tab under <strong>WooCommerce → Settings</strong>, where you can adjust swatch layout and turn on the optional interactive archive swatches (see <a href="{{CH:interactive-archive-swatches}}">Chapter 7</a>).</p>
     50<p>When you activate the Free plugin, no new top-level menu is added — most configuration happens directly on your <strong>product attribute</strong> pages (covered in the next chapter). The Free plugin does add an <strong>Chiseiko Essential Swatches Settings</strong> tab under <strong>WooCommerce → Settings</strong>, where you can adjust swatch layout and turn on the optional interactive archive swatches (see Chapter 7 in the Pro user guide).</p>
    4951<p><img width="2400" height="3192" loading="lazy" decoding="async" src="images/free/settings.webp" alt="The free plugin&#39;s settings under WooCommerce → Settings → Chiseiko Essential Swatches Settings"></p>
    50 <p>When you activate the Pro add-on, a new settings page appears at <strong>WooCommerce → Chiseiko Essential Swatches Pro</strong>. This is where you manage your license and enable/disable the Pro modules. Until you enter a key, the License tab shows <strong>No license</strong> — enter and activate your key to unlock the Pro modules (see <a href="{{CH:pro-license-and-modules}}">Chapter 5</a>).</p>
     52<p>When you activate the Pro add-on, a new settings page appears at <strong>WooCommerce → Chiseiko Essential Swatches Pro</strong>. This is where you manage your license and enable/disable the Pro modules. Until you enter a key, the License tab shows <strong>No license</strong> — enter and activate your key to unlock the Pro modules (see Chapter 5 in the Pro user guide).</p>
    5153<p><img width="2400" height="981" loading="lazy" decoding="async" src="images/pro/license-no-license.webp" alt="Freshly installed: the License tab shows “No license” until you activate your key"></p>
    5254<hr>
  • chiseiko-essential-swatches/trunk/docs/settings.html

    r3598460 r3778841  
    44<p><strong>WooCommerce → Settings → Chiseiko Essential Swatches Settings</strong></p>
    55<p><img width="2400" height="3192" loading="lazy" decoding="async" src="images/free/settings.webp" alt="The Chiseiko Essential Swatches Settings tab under WooCommerce → Settings"></p>
    6 <p>The page has two sections: <strong>Product Page</strong> (how swatches behave on a single product) and <strong>Archive / Shop Page Swatches</strong> (how swatches behave on shop, category, and archive grids). After changing anything, scroll to the bottom and click <strong>Save changes</strong>.</p>
     6<p>The page has three sections: <strong>Product Page</strong> (how swatches behave on a single product), <strong>Archive / Shop Page Swatches</strong> (how swatches behave on shop, category, and archive grids), and <strong>Appearance</strong> (the shape and size of color, image, and label swatches everywhere). After changing anything, scroll to the bottom and click <strong>Save changes</strong>.</p>
    77<blockquote>
    88<p><strong>Already using Pro?</strong> Several of these options are taken over by Pro modules when Pro is active — each setting below notes when that happens. With Pro installed, the matching controls live under <strong>WooCommerce → Chiseiko Essential Swatches Pro</strong>.</p>
    … …  
    121121</ul>
    122122<blockquote>
    123 <p><strong>With Chiseiko Essential Swatches Pro active</strong>, the Pro tooltip engine (custom position, hover delay, per-term overrides) automatically takes over on single product pages while this setting is on. See <a href="{{CH:advanced-styling}}">Chapter 9 — Advanced Styling</a> and the Pro tooltips module.</p>
     123<p><strong>With Chiseiko Essential Swatches Pro active</strong>, the Pro tooltip engine (custom position, hover delay, per-term overrides) automatically takes over on single product pages while this setting is on. See Chapter 9 — Advanced Styling in the Pro user guide and the Pro tooltips module.</p>
    124124</blockquote>
    125125<h3 id="attribute-row-alignment">Attribute Row Alignment</h3>
    … …  
    143143<p>By default, swatches on archive pages are a <strong>read-only preview strip</strong> under each product card: customers see the available options at a glance but click through to the product page to choose. The settings below let you make that strip interactive.</p>
    144144<blockquote>
    145 <p><strong>Pro users:</strong> these options are managed in <strong>WooCommerce → Chiseiko Essential Swatches Pro → Archive Swatches</strong>, and the Pro module overrides the free settings here. See <a href="{{CH:interactive-archive-swatches}}">Chapter 7 — Interactive Archive Swatches</a>.</p>
     145<p><strong>Pro users:</strong> these options are managed in <strong>WooCommerce → Chiseiko Essential Swatches Pro → Archive Swatches</strong>, and the Pro module overrides the free settings here. See Chapter 7 — Interactive Archive Swatches in the Pro user guide.</p>
    146146</blockquote>
    147147<h3 id="interactive-archive-swatches">Interactive Archive Swatches</h3>
    … …  
    178178<blockquote>
    179179<p><strong>When Chiseiko Essential Swatches Pro is active</strong>, its matching setting takes precedence over this one.</p>
     180</blockquote>
     181<hr>
     182<h2 id="section-3--appearance">Section 3 — Appearance</h2>
     183<p>These options set the look of your swatches across the whole store — product pages, shop and category grids, and related products.</p>
     184<h3 id="swatch-shape">Swatch Shape</h3>
     185<p><strong>Default: Circle.</strong> Applies to color, image, and label swatches. Radio buttons keep their own shape.</p>
     186<ul>
     187<li><strong>Circle</strong> — every swatch is the same round size. Short labels such as S, M, or XL fit; longer labels are cut off (&quot;Medium&quot; shows as &quot;Medi&quot;).</li>
     188<li><strong>Rounded square</strong> — softly rounded corners. Label swatches widen to fit their text.</li>
     189<li><strong>Square</strong> — sharp corners. Label swatches widen to fit their text.</li>
     190</ul>
     191<blockquote>
     192<p><strong>Tip:</strong> If your labels are longer than two or three characters, choose <strong>Rounded square</strong> or <strong>Square</strong>. On a shop card, a label too long for the card ends in &quot;…&quot;; the full name still shows on hover and is read out by screen readers.</p>
     193</blockquote>
     194<p>For other looks — for example pill-shaped labels — see <a href="{{CH:customizing-swatches}}">Chapter 25 — Customizing Swatches</a>.</p>
     195<h3 id="swatch-size-px">Swatch Size (px)</h3>
     196<p><strong>Default: 32.</strong></p>
     197<p>The width and height of color and image swatches on desktop screens, from <strong>24</strong> to <strong>64</strong> pixels. Phones and tablets always keep <strong>44-pixel</strong> swatches so they stay comfortable to tap, whatever you choose here.</p>
     198<blockquote>
     199<p><strong>When Chiseiko Essential Swatches Pro is active with a valid license</strong>, this section is hidden: Pro&#39;s <strong>Advanced Styling</strong> module controls swatch shape and size instead (see Chapter 9 — Advanced Styling in the Pro user guide).</p>
    180200</blockquote>
    181201<hr>
    … …  
    190210</ul>
    191211</li>
    192 <li><strong>Pro takes the wheel where noted.</strong> Tooltips, attribute-row alignment, related-product swatches, and the whole archive section are handed to the equivalent Pro module when Pro is active — the free values act as the baseline until then.</li>
    193 </ul>
    194 <hr>
     212<li><strong>Pro takes the wheel where noted.</strong> Tooltips, attribute-row alignment, related-product swatches, the whole archive section, and swatch shape and size are handed to the equivalent Pro module when Pro is active with a valid license — the free values act as the baseline until then.</li>
     213</ul>
     214<hr>
  • chiseiko-essential-swatches/trunk/docs/variable-products.html

    r3598460 r3778841  
    9090<li>Only terms that have a swatch <strong>type</strong> set (color, image, text label, or radio) show in the loop preview. Terms left at &quot;— Select type —&quot; are skipped.</li>
    9191<li>Sizes and other terms with no swatch type set are hidden from the loop to keep things clean. (If you explicitly give a size term a Text Label or Radio Button swatch type, it <em>will</em> appear.)</li>
    92 <li>By default these loop swatches are <strong>read-only</strong>, but the Free plugin includes an optional <strong>Interactive Archive Swatches</strong> setting (under <strong>WooCommerce → Settings → Chiseiko Essential Swatches Settings</strong>, off by default) that makes them clickable, with optional AJAX add-to-cart. Pro extends this further — see <a href="{{CH:interactive-archive-swatches}}">Chapter 7</a>.</li>
     92<li>By default these loop swatches are <strong>read-only</strong>, but the Free plugin includes an optional <strong>Interactive Archive Swatches</strong> setting (under <strong>WooCommerce → Settings → Chiseiko Essential Swatches Settings</strong>, off by default) that makes them clickable, with optional AJAX add-to-cart. Pro extends this further — see Chapter 7 in the Pro user guide.</li>
    9393<li>Swatches are displayed in <strong>alphabetical order</strong> by the term name (A → Z). For example, if your colors are Ivory, Rose, and Sage, they will always appear in that order: Ivory, Rose, Sage — regardless of the order you created them in.</li>
    9494</ul>
    … …  
    102102<li>At least one variation has been created and has a price.</li>
    103103</ol>
    104 <p>Still not working? See <a href="{{CH:troubleshooting}}">Chapter 24 — Troubleshooting</a>.</p>
     104<p>Still not working? Ask in the <a href="https://wordpress.org/support/plugin/chiseiko-essential-swatches/">WordPress.org support forum</a>, or see Chapter 24 — Troubleshooting in the Pro user guide.</p>
    105105<hr>
    106106<h2 id="working-with-multiple-attributes">Working with Multiple Attributes</h2>
  • chiseiko-essential-swatches/trunk/includes/class-chiseikoessw-ajax-batch.php

    r3598460 r3778841  
    316316                }
    317317
    318                 /* @var \WC_Product_Variable $product */ // phpcs:ignore Squiz.PHP.CommentedOutCode.Found -- type narrowing for PHPStan after the is_type( 'variable' ) guard above; not commented-out code.
     318                /** @var \WC_Product_Variable $product */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort -- inline PHPStan type narrowing after the is_type( 'variable' ) guard above.
    319319                $data = $this->build_variation_map( $product );
    320320
  • chiseiko-essential-swatches/trunk/includes/class-chiseikoessw-frontend.php

    r3598460 r3778841  
    259259                }
    260260
     261                // Card-strip layout (row flex + gap, archive alignment, two-row clamp,
     262                // text/label treatment). The read-only strip renders on every card
     263                // surface, so its stylesheet must load there whether or not interactive
     264                // archive swatches are enabled; CHISEIKOESSW_Archive_Swatches enqueues
     265                // the same handle (a no-op repeat) and adds only the interactive script.
     266                if ( CHISEIKOESSW_Hooks::card_surface_active() ) {
     267                        wp_enqueue_style(
     268                                'chiseikoessw-archive',
     269                                CHISEIKOESSW_PLUGIN_URL . "assets/css/chiseikoessw-archive{$sfx}.css",
     270                                array( 'chiseikoessw-frontend', 'chiseikoessw-card-swatches' ),
     271                                CHISEIKOESSW_VERSION
     272                        );
     273                        $align_css = CHISEIKOESSW_Swatch_Layout::archive_align_css();
     274                        if ( '' !== $align_css ) {
     275                                wp_add_inline_style( 'chiseikoessw-frontend', $align_css );
     276                        }
     277                }
     278
    261279                // JS is only needed on single product pages (where the variation form lives).
    262280                // Declared dependencies:
  • chiseiko-essential-swatches/trunk/includes/class-chiseikoessw-settings.php

    r3598460 r3778841  
    8383         */
    8484        public function get_settings(): array {
    85                 return array(
     85                $settings = array(
    8686
    8787                        // ── Product page section ─────────────────────────────────────────
    … …  
    284284                        ),
    285285                );
     286
     287                // Global shape/size apply to product and shop swatches alike, so they
     288                // get their own section. Empty when Pro's Advanced Styling owns them.
     289                $appearance = CHISEIKOESSW_Appearance::settings_fields();
     290                if ( empty( $appearance ) ) {
     291                        return $settings;
     292                }
     293
     294                return array_merge(
     295                        $settings,
     296                        array(
     297                                array(
     298                                        'title' => __( 'Appearance', 'chiseiko-essential-swatches' ),
     299                                        'type'  => 'title',
     300                                        'desc'  => __( 'Shape and size of color and image swatches across the store.', 'chiseiko-essential-swatches' ),
     301                                        'id'    => 'chiseikoessw_appearance_section',
     302                                ),
     303                        ),
     304                        $appearance,
     305                        array(
     306                                array(
     307                                        'type' => 'sectionend',
     308                                        'id'   => 'chiseikoessw_appearance_section',
     309                                ),
     310                        )
     311                );
    286312        }
    287313
  • chiseiko-essential-swatches/trunk/includes/class-chiseikoessw-swatch-layout.php

    r3598460 r3778841  
    274274                ++$this->group_index;
    275275
    276                 $hidden_attr = 'false' === $expanded ? ' hidden' : '';
     276                // Groups always start collapsed, so the divider and panel start hidden.
     277                $hidden_attr = ' hidden';
    277278
    278279                return sprintf(
    … …  
    426427                        )
    427428                );
    428 
    429                 // Output alignment as a CSS custom property so archive swatch groups
    430                 // can reference it without class toggling.
     429        }
     430
     431        /**
     432         * The archive alignment setting as a CSS custom property, read by every
     433         * card-strip row (Free and Pro). Printed by CHISEIKOESSW_Frontend on card
     434         * surfaces — not from enqueue_assets() — so it also applies when the
     435         * layout is 'inline' and this module registers no hooks. Empty at the
     436         * default ('center'): every consumer falls back to `center`.
     437         */
     438        public static function archive_align_css(): string {
    431439                $align_map = array(
    432                         'left'   => 'flex-start',
    433                         'center' => 'center',
    434                         'right'  => 'flex-end',
    435                 );
    436                 $flex_val  = $align_map[ $alignment ] ?? 'center';
    437                 wp_add_inline_style(
    438                         'chiseikoessw-frontend',
    439                         ':root{--chiseikoessw-archive-align:' . $flex_val . ';}'
    440                 );
     440                        'left'  => 'flex-start',
     441                        'right' => 'flex-end',
     442                );
     443                $alignment = self::get_alignment();
     444                return isset( $align_map[ $alignment ] ) ? ':root{--chiseikoessw-archive-align:' . $align_map[ $alignment ] . ';}' : '';
    441445        }
    442446}
  • chiseiko-essential-swatches/trunk/includes/class-chiseikoessw-term-meta.php

    r3598460 r3778841  
    104104         *
    105105         * Reads the stored meta value and validates it against ALLOWED_TYPES.
    106          * Falls back to 'none' for:
     106         * A term without its own type inherits its attribute's default swatch
     107         * type (CHISEIKOESSW_Attribute_Defaults), when one is set.
     108         * Otherwise falls back to 'none' for:
    107109         *  - Terms with no meta set yet (new terms).
    108110         *  - Any stored value that is no longer in the allowlist.
    … …  
    115117        public static function get_type( int $term_id ): string {
    116118                $type = (string) get_term_meta( $term_id, self::META_TYPE, true );
     119                // No own swatch type ('' when never saved, 'none' when the term form was
     120                // saved without picking one): inherit the attribute's default swatch
     121                // type, if any. A real per-term type always wins. Stores without any
     122                // attribute defaults skip the get_term() lookup entirely.
     123                if ( ( '' === $type || 'none' === $type ) && class_exists( 'CHISEIKOESSW_Attribute_Defaults' ) && array() !== CHISEIKOESSW_Attribute_Defaults::all() ) {
     124                        $term = get_term( $term_id );
     125                        if ( $term && isset( $term->taxonomy ) ) {
     126                                $type = CHISEIKOESSW_Attribute_Defaults::get_default_type( (string) $term->taxonomy );
     127                        }
     128                }
    117129                // Legacy alias: pre-radio releases stored the text-pill swatch as
    118130                // 'text'. The current allowlist uses 'label' for that slot, so coerce
  • chiseiko-essential-swatches/trunk/includes/class-chiseikoessw-user-guide.php

    r3598460 r3778841  
    3434         */
    3535        private string $hook = '';
     36
     37        /**
     38         * Admin URL of the user guide, for links elsewhere in the plugin.
     39         *
     40         * The Free page is not registered when the Pro add-on is installed (Pro
     41         * ships the complete guide in its own settings tab), so Pro filters this
     42         * to that tab.
     43         */
     44        public static function url(): string {
     45                /**
     46                 * Filters the admin URL the plugin links to for its user guide.
     47                 *
     48                 * @param string $url URL of the Free guide page.
     49                 */
     50                return (string) apply_filters( 'chiseikoessw_user_guide_url', add_query_arg( 'page', self::SLUG, admin_url( 'admin.php' ) ) );
     51        }
    3652
    3753        /**
    … …  
    144160                                                                        class="<?php echo $current === $chapter['slug'] ? 'is-active' : ''; ?>"
    145161                                                                        <?php echo $current === $chapter['slug'] ? 'aria-current="page"' : ''; ?>>
    146                                                                         <span class="chiseikoessw-guide__num"><?php echo esc_html( (string) ( $i + 1 ) ); ?></span>
     162                                                                        <span class="chiseikoessw-guide__num"><?php echo esc_html( (string) ( $chapter['num'] ?? $i + 1 ) ); ?></span>
    147163                                                                        <?php echo esc_html( $chapter['title'] ); ?>
    148164                                                                </a>
    … …  
    150166                                                <?php endforeach; ?>
    151167                                        </ol>
    152                                         <p class="chiseikoessw-guide__note"><?php esc_html_e( 'Unlock 23 Pro modules and the full guide with Chiseiko Essential Swatches Pro.', 'chiseiko-essential-swatches' ); ?></p>
     168                                        <p class="chiseikoessw-guide__note"><?php esc_html_e( 'Unlock the Pro modules and the full guide with Chiseiko Essential Swatches Pro.', 'chiseiko-essential-swatches' ); ?></p>
    153169                                </nav>
    154170                                <article class="chiseikoessw-guide__content">
  • chiseiko-essential-swatches/trunk/readme.txt

    r3598460 r3778841  
    11=== Chiseiko Essential Swatches for WooCommerce ===
    22Contributors: chiseiko
     3Tags: variation swatches, color swatches, image swatches, product variations, woocommerce
    34Donate link: https://www.paypal.com/ncp/payment/GBS4FG84LUEMY
    4 Tags: woocommerce, variation swatches, color swatches, image swatches, product variations
    55Requires at least: 6.5
    6 Tested up to: 7.0
     6Tested up to: 7.1
     7Requires PHP: 8.1
    78WC requires at least: 8.0
    8 WC tested up to: 10.5
    9 Requires PHP: 8.1
    10 Stable tag: 1.0.0
    11 License: GPL-2.0-or-later
     9WC tested up to: 11.2.1
     10Stable tag: 1.1.0
     11License: GPLv2 or later
    1212License URI: https://www.gnu.org/licenses/gpl-2.0.html
    1313
    14 Turn WooCommerce variation dropdowns into clickable color, image, text & button swatches on product and shop pages. Sell more variations, fast.
     14Lightweight WooCommerce variation swatches. Replace plain dropdowns with fast, visual color, image, and text swatches on product and shop pages.
    1515
    1616== Description ==
    1717
    18 **Chiseiko Essential Swatches turns plain WooCommerce variation dropdowns into beautiful, clickable color, image, text, and button swatches** — on single product pages *and* shop, category, and tag archives. Shoppers see their options at a glance, pick the right variation in one click, and add to cart faster.
     18Chiseiko Essential Swatches turns plain WooCommerce variation dropdowns into beautiful, clickable color, image, text, and button swatches — on single product pages and shop, category, and tag archives. Shoppers see their options at a glance, pick the right variation in one click, and add to cart faster.
    1919
    20 Built from the ground up with a vanilla-first JavaScript architecture, conditional asset loading, and full accessibility. It works with any WooCommerce-compatible theme — Classic, FSE block themes, and page builders (Elementor, Divi, Beaver Builder) — with no template edits and no shortcodes.
     20= Lightweight & Fast =
     21Speed matters for conversions. Built for performance from day one:
     22* **Vanilla JavaScript Core:** Built in vanilla JS with no jQuery code of its own (only hooking into unavoidable WooCommerce core events).
     23* **Conditional Asset Loading:** Scripts and styles load *only* on product and shop pages.
     24* **Batch AJAX:** Archive swatch data is fetched via a single batched request per page, rather than punishing your server with one request per product.
    2125
    2226= The problem with default WooCommerce variations =
    23 
    2427Out of the box, WooCommerce hides every product variation behind a generic `<select>` dropdown. That quietly costs you sales:
    25 
    26 * Customers can't *see* the colors or styles you sell — they have to open a menu and read text.
     28* Customers can't see the colors or styles you sell — they have to open a menu and read text.
    2729* Available options stay hidden until the dropdown is opened, so shoppers miss variants.
    2830* There's no visual feedback on mobile, where dropdowns are slow and fiddly.
    2931* Shop and category pages show no variation choices at all, so every selection means an extra page load.
    3032
    31 = What Chiseiko Essential Swatches solves =
    32 
    33 * **Makes choices visual and instant.** Real color circles, product photos, and styled labels replace text dropdowns, so shoppers recognize what they want immediately.
    34 * **Shows options on the shop page, not just the product page.** Interactive archive swatches let customers preview and even add a variant to the cart straight from the product card.
    35 * **Reduces "out of stock" frustration.** Unavailable variants are dimmed (not hidden), so customers always see the full range and what's available.
    36 * **Speeds up the path to purchase.** Instant gallery preview, mobile auto-scroll, and one-click selection shorten the distance between landing and buying.
    37 * **Keeps your store fast.** Assets load only on the pages that need them, and archive data is fetched in a single batched request — not one request per product.
     33= How it works =
     34Go to Products > Attributes and edit any global attribute. For each term, choose a swatch type (color, image, label, or radio) and configure it — or set a default swatch type on the attribute itself to turn every term into label or radio buttons in one step. Swatches appear automatically on every product that uses that attribute — no shortcodes or template edits required. Local (custom per-product) attributes render as text pills automatically. A short getting-started notice after activation points you to the right screens.
    3835
    3936= Swatch types (all four included free) =
    40 
    4137* **Color Swatches** — Pick any hex color for each attribute term.
    4238* **Image Swatches** — Upload a thumbnail from the Media Library.
    4339* **Text Pills** — Styled labels for attributes without a visual representation.
    4440* **Radio Buttons** — Round radio indicators with label text for simple selections.
     41* **Attribute-wide Defaults** — Show every term of an attribute (such as Size) as label or radio buttons without editing each term; individual terms can still set their own type.
     42
     43= Look & feel =
     44* **Global Shape & Size** — Circle, rounded square, or square swatches at any size from 24 to 64 px. With rounded or square, label swatches widen to fit their text. Touch screens keep comfortable 44 px tap targets.
     45* **Tooltips** — Term names appear on hover and keyboard focus.
     46* **Attribute Row Alignment** — Keep each attribute name aligned with its row of swatches, whatever your theme does by default.
    4547
    4648= Single product page =
    47 
    48 * **Instant Gallery Preview** — The product gallery updates the moment a swatch is clicked, before all attributes are selected (Amazon/AliExpress-style image preview).
    49 * **Smart Inventory UX** — Out-of-stock swatches are visually dimmed (not hidden), so customers always see available options. The last viable variant is auto-selected.
    50 * **Layout Options** — Inline, accordion (collapsible), overflow ("Show more"), or slider layouts for products with many swatches. Accordion can be set to mobile-only.
    51 * **Mobile Auto-Scroll** — After selecting a variant on mobile, the viewport scrolls to the gallery so the customer sees the updated image. Configurable breakpoint and offset.
    52 * **Accessible** — Full ARIA support with `role="radiogroup"`, `aria-checked`, `aria-disabled`, `aria-label`, and roving-tabindex keyboard navigation.
     49* **Instant Gallery Preview** — The product gallery updates the moment a swatch is clicked.
     50* **Smart Inventory UX** — Out-of-stock swatches are visually dimmed (not hidden), so customers always see available options.
     51* **Layout Options** — Inline, accordion (collapsible), overflow (“Show more”), or slider layouts.
     52* **Mobile Auto-Scroll** — Auto-scrolls to the gallery after selection so mobile users see the updated image.
     53* **Accessible** — Full ARIA support for keyboard navigation and screen readers.
    5354
    5455= Shop & archive pages =
     56* **Interactive Archive Swatches** — Clickable swatches on product cards so customers can preview variants directly from the catalog.
     57* **AJAX Add to Cart** — An “Add to Cart” button appears right on the grid after selection.
     58* **Catalog Mode** — Show only one attribute (like Color) on archives for a cleaner layout.
     59* **Related & Upsell Products** — The same interactive swatches appear on related, upsell, and cross-sell product cards on product pages.
    5560
    56 * **Archive Swatch Strip** — Compact swatch previews on shop, category, and tag pages.
    57 * **Interactive Archive Swatches** — Clickable swatches on product cards so customers can preview variants without leaving the listing.
    58 * **AJAX Add to Cart** — After selecting a swatch on an archive page, an "Add to Cart" button appears on the card — no need to open the product page.
    59 * **Catalog Mode** — Show only one attribute on archive pages for a cleaner layout.
     61= Free vs Pro =
     62The free plugin is a complete swatch solution with no caps on the number of swatches, attributes, or products.
    6063
    61 = Performance & compatibility =
    62 
    63 * **Vanilla-first JavaScript** — plugin-owned behavior stays native. Any jQuery that remains is limited to unavoidable WooCommerce or WordPress bridge contracts.
    64 * **Conditional Loading** — CSS and JS load only on product and shop pages. Nothing loads on cart, checkout, or account pages.
    65 * **Batch AJAX** — Archive swatch data is fetched via a single batched request per page (up to 50 products), then cached.
    66 * **Theme-agnostic** — Uses WooCommerce's standard variation form hooks; no template overrides.
    67 
    68 = How it works =
    69 
    70 1. Go to **Products > Attributes** and edit any global attribute.
    71 2. For each term, choose a swatch type (color, image, label, or radio) and configure it.
    72 3. Swatches appear automatically on every product that uses that attribute — no shortcodes or template edits required.
    73 
    74 Local (custom per-product) attributes render as text pills automatically.
    75 
    76 = Free vs Pro — which problems does each solve? =
    77 
    78 **Chiseiko Essential Swatches (free) is a complete swatch solution.** If your goal is to replace variation dropdowns with visual swatches on product *and* shop pages, add interactive archive selection with AJAX add-to-cart, control layout, and keep everything fast and accessible — the free plugin does that, with no limits on the number of swatches, attributes, or products.
    79 
    80 **Upgrade to [Chiseiko Essential Swatches Pro](https://chiseikotech.com/chiseiko-essential-swatches-pro/) when you outgrow the basics** and need to solve store-growth problems the free plugin intentionally leaves out:
    81 
    82 * *"My 'variations' are actually separate products and I don't want to lose their SEO."* → **Linked Simple Products** ties standalone simple products together into one swatch strip while preserving an individual, indexable URL per variant — plus canonical consolidation, linked archive swatches, a multi-attribute matrix (e.g. color + size), an in-place product-page swap (no full reload), and a **shared review collection** with a combined rating across the group.
    83 * *"My swatches look generic and off-brand."* → **Advanced Styling** adds per-swatch shapes, a multi-stop gradient builder, custom radius, out-of-stock display modes (cross-out / blur / hide), and one-click style presets — plus configurable **tooltips**.
    84 * *"Shoppers can't filter by color or brand."* → A visual **Swatch Filter Widget** and **WooCommerce Brands** swatches (including on shop-archive cards).
    85 * *"I need to manage hundreds of products without clicking through every term."* → **CSV Import/Export**, **Auto-Assign Images** by slug, and a **Variable → Simple migration tool** that copies brands, custom fields, taxonomies, galleries, and reviews.
    86 * *"I want to lift average order value and mobile conversions."* → **Dynamic Price Sync**, **Attribute-Based Extra Fees**, and a mobile **Sticky Add-to-Cart Bar**.
    87 * *"My big variable products are slow, and quick-view breaks my swatches."* → **AJAX Variation Override** (raise the inline-variation limit), **Additional Variation Images**, **Swatch Grouping**, and **Quick View Compatibility**.
    88 * *"I run a multilingual store."* → **Multilingual Sync** keeps swatch metadata aligned across WPML and Polylang.
    89 
    90 Every Pro module is individually toggleable, loads conditionally, and follows the same vanilla-first architecture as the free plugin.
     64Upgrade to [Chiseiko Essential Swatches Pro](https://chiseikotech.com/chiseiko-essential-swatches-pro/) when you need advanced tools for a growing store:
     65* **Linked Simple Products:** Tie standalone simple products together into one swatch strip while keeping an indexable URL per variant.
     66* **Advanced Styling:** Custom shapes, gradients, tooltips, and out-of-stock display modes (cross-out / blur / hide).
     67* **Swatch Filter Widget:** Let shoppers filter your catalog by color or brand.
     68* **Bulk Management:** CSV Import/Export, Variable-to-Simple migration, and Auto-Assign Images.
     69* **Conversion Tools:** Dynamic Price Sync, Attribute-Based Extra Fees, and a Sticky Mobile Add-to-Cart bar.
     70* **Scale & Compatibility:** AJAX Variation Override for large catalogs, Multilingual Sync (WPML/Polylang), and Quick View support.
    9171
    9272== Installation ==
    9373
    94 1. Upload the `chiseiko-essential-swatches` folder to `wp-content/plugins/`, or install directly from the WordPress plugin screen.
     741. Upload the `chiseiko-essential-swatches` folder to `/wp-content/plugins/`, or install directly from the WordPress plugin screen.
    95752. Activate the plugin.
    96763. Ensure WooCommerce 8.0 or later is active.
    97 4. Go to **Products > Attributes**, edit an attribute, and configure swatch types for each term.
    98 5. Optionally configure settings at **WooCommerce > Settings > Chiseiko Essential Swatches Settings** (image preview, archive swatches, AJAX add-to-cart, layout mode, catalog mode, mobile auto-scroll).
     774. Go to Products > Attributes, edit an attribute, and configure swatch types for each term — or choose a default swatch type for the whole attribute.
     785. Optionally configure settings (layout, shape, size, tooltips) at WooCommerce > Settings > Chiseiko Essential Swatches Settings. The plugin's row on the Plugins screen links straight there and to the built-in guide.
    9979
    10080== Frequently Asked Questions ==
    10181
    10282= Do I need WooCommerce? =
    103 
    104 Yes. Chiseiko Essential Swatches requires WooCommerce 8.0 or later (tested up to WooCommerce 10.5).
     83Yes. Chiseiko Essential Swatches requires WooCommerce 8.0 or later (tested up to WooCommerce 11.2.1).
    10584
    10685= Is it really free? =
    107 
    10886Yes. The free plugin includes all four swatch types, single-product and archive swatches, interactive archive swatches with AJAX add-to-cart, every layout mode, catalog mode, and mobile auto-scroll — with no caps on swatches, attributes, or products. Pro is an optional add-on for advanced features.
    10987
     88= Does the plugin slow down my site? =
     89No. All plugin-owned JavaScript is vanilla. Assets load only on product and shop pages. Archive swatch data is cached and served via a single batched AJAX endpoint to protect server performance.
     90
    11091= Will it work with my theme? =
    111 
    11292Chiseiko Essential Swatches uses WooCommerce's standard variation form hooks and does not override templates, so it is compatible with any properly built WooCommerce theme — including Classic themes, FSE block themes, and page builders (Elementor, Divi, Beaver Builder).
    11393
    11494= Does it work with custom (local) product attributes? =
     95Yes. Local attributes automatically render as text-pill swatches. To use color or image swatches, convert them to global attributes under Products > Attributes.
    11596
    116 Yes. Local attributes automatically render as text-pill swatches. To use color or image swatches, convert them to global attributes under **Products > Attributes**.
    117 
    118 = Does the plugin slow down my site? =
    119 
    120 No. All plugin-owned JavaScript is vanilla (no jQuery runtime dependency). Assets load only on product and shop pages. Archive swatch data is cached and served via a single batched AJAX endpoint, and frontend scripts use the WP 6.3+ `defer` strategy for non-blocking loading.
    121 
    122 = What swatch types are available? =
    123 
    124 Four: Color (hex picker), Image (Media Library thumbnail), Label (text pill), and Radio Button. All four are in the free version.
     97= Can I show swatches on the shop and category pages? =
     98Yes. Enable archive swatches in settings. You can also make them interactive so customers preview variants and add to cart directly from product cards, or use Catalog Mode to show a single attribute for a cleaner grid.
    12599
    126100= Can I control the layout for products with many swatches? =
    127 
    128 Yes. Choose inline (default), accordion (collapsible panels per attribute), overflow ("Show N more" toggle), or slider. Accordion can be set to mobile-only, and the overflow limit is configurable.
    129 
    130 = Can I show swatches on the shop and category pages? =
    131 
    132 Yes. Enable archive swatches in settings. You can also make them interactive so customers preview variants and add to cart directly from product cards, or use Catalog Mode to show a single attribute for a cleaner grid.
     101Yes. Choose inline (default), accordion (collapsible panels per attribute), overflow (“Show N more” toggle), or slider. Accordion can be set to mobile-only, and the overflow limit is configurable.
    133102
    134103= Can I hide swatches on archive pages? =
    135 
    136104Yes. Disable archive swatches in settings, or return `false` from the `chiseikoessw_render_loop_swatches` filter to suppress per-product.
    137105
    138106= Is the plugin translatable? =
    139 
    140107Yes. All strings use the `chiseiko-essential-swatches` text domain and are translation-ready.
    141 
    142 = What is the difference between Free and Pro? =
    143 
    144 The free plugin is a complete swatch solution: four swatch types, instant gallery preview, interactive archive swatches with AJAX add-to-cart, layout options (inline / accordion / overflow / slider), catalog mode, and mobile auto-scroll. [Chiseiko Essential Swatches Pro](https://chiseikotech.com/chiseiko-essential-swatches-pro/) adds linked simple products (SEO-friendly swatches across separate listings) with grouping, canonical shield, archive swatches, multi-attribute matrix, in-place product-page swap, and shared reviews; advanced styling (gradients, shapes, tooltips, style presets, OOS display modes); a swatch filter widget; WooCommerce Brands swatches; variation-threshold management; additional variation images; swatch grouping; CSV bulk operations; auto-assign images; multilingual sync; quick-view compatibility; dynamic price sync; attribute-based extra fees; a sticky mobile add-to-cart bar; gallery zoom alignment; and a Variable → Simple migration tool. See the Free vs Pro section above for the specific problems each solves.
    145108
    146109== Screenshots ==
    … …  
    1531166. Catalog Mode — a single attribute (Color) shown per product card across shop and category archives.
    154117
     118== Upgrade Notice ==
     119
     120= 1.1.0 =
     121Adds an attribute-wide default swatch type, global swatch shape and size, and a short getting-started guide for new stores.
     122
     123= 1.0.0 =
     124Initial release.
     125
    155126== Changelog ==
     127
     128= 1.1.0 =
     129* New: Attribute-wide default swatch type — show every term of an attribute (such as Size) as label or radio buttons in one step. Individual terms can still choose their own type.
     130* New: Global swatch shape (circle, rounded square, square) for color, image, and label swatches on product pages and shop, category, and related-product cards — with rounded square or square, label swatches widen to fit their text. Global swatch size (24–64 px) on desktop; touch screens keep 44 px tap targets.
     131* New: Getting-started notice after activation that points to the attribute and settings screens.
     132* New: Settings and Guide links on the plugin's row in the Plugins screen.
     133* New: An occasional, dismissible review request, shown only on the plugin's own screens to store managers — for WordPress.org, or for Pro on chiseikotech.com when Pro is installed.
     134* New: "Customizing Swatches" chapter in the built-in guide — tested CSS and PHP examples, including how to let long labels fit their swatch.
     135* Fix: Shop and category swatch strips (and related-product cards) are laid out correctly — spaced, aligned, and limited to two rows — when interactive archive swatches are off, which is the default.
     136* Fix: The archive swatch alignment setting (left, center, right) now applies with the default inline layout.
     137* Fix: Long swatch labels no longer make one product card wider than the others in grid themes such as Astra. Labels too long for a card end in "…", and the full name stays in the tooltip and screen-reader label.
     138* Fix: Links in the built-in guide no longer point to chapters that only ship with Pro.
     139* Maintenance: tested with WordPress 7.1.4 and WooCommerce 11.2.1.
    156140
    157141= 1.0.0 =
    … …  
    169153* Variation direct links (URL query parameter pre-selection).
    170154* Developer hooks: `chiseikoessw_swatch_types`, `chiseikoessw_swatch_button_classes`, `chiseikoessw_swatch_button_html`, `chiseikoessw_swatch_group_html`, `chiseikoessw_render_loop_swatches`, plus action hooks.
    171 
    172 == Upgrade Notice ==
    173 
    174 = 1.0.0 =
    175 Initial release.
  • chiseiko-essential-swatches/trunk/uninstall.php

    r3598460 r3778841  
    7575                        'chiseikoessw_archive_swatch_alignment',
    7676                        'chiseikoessw_catalog_attribute',
     77                        // Review notice (CHISEIKOESSW_Review_Notice::OPTION_INSTALLED_AT).
     78                        'chiseikoessw_installed_at',
     79                        // Attribute-level default swatch types (CHISEIKOESSW_Attribute_Defaults::OPTION).
     80                        'chiseikoessw_attribute_default_types',
     81                        // Global swatch shape / size (CHISEIKOESSW_Appearance).
     82                        'chiseikoessw_swatch_shape',
     83                        'chiseikoessw_swatch_size',
    7784                );
    7885
    … …  
    8087                        delete_option( $option_key );
    8188                }
     89
     90                // ── Remove per-user admin notice state ───────────────────────────────
     91                // Mirrors CHISEIKOESSW_Review_Notice::META_DISMISSED / META_SNOOZED_UNTIL.
     92                delete_metadata( 'user', 0, 'chiseikoessw_review_dismissed', '', true );
     93                delete_metadata( 'user', 0, 'chiseikoessw_review_snoozed_until', '', true );
     94                // CHISEIKOESSW_Onboarding_Notice::META_DISMISSED.
     95                delete_metadata( 'user', 0, 'chiseikoessw_onboarding_dismissed', '', true );
     96                delete_transient( 'chiseikoessw_review_has_swatches' );
    8297
    8398                // ── Remove plugin transients ─────────────────────────────────────────
Note: See TracChangeset for help on using the changeset viewer.