From 99d943643bc5128e87ab1a1e19d8e2dc1bd15b2d Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 17 Dec 2025 17:50:32 -0500 Subject: [PATCH] Use modal picker for organic and wall palettes --- organic.js | 113 ++++++++++++----------------------------------------- wall.js | 85 ++++++++-------------------------------- 2 files changed, 41 insertions(+), 157 deletions(-) diff --git a/organic.js b/organic.js index c0bd949..ff72725 100644 --- a/organic.js +++ b/organic.js @@ -143,6 +143,13 @@ const garlandAccentChip = document.getElementById('garland-accent-chip'); const garlandAccentClearBtn = document.getElementById('garland-accent-clear'); const garlandControls = document.getElementById('garland-controls'); + // Optional dropdowns (may not be present in current layout) + const garlandColorMain1Sel = document.getElementById('garland-color-main-1'); + const garlandColorMain2Sel = document.getElementById('garland-color-main-2'); + const garlandColorMain3Sel = document.getElementById('garland-color-main-3'); + const garlandColorMain4Sel = document.getElementById('garland-color-main-4'); + const garlandColorAccentSel = document.getElementById('garland-color-accent'); + const updateGarlandSwatches = () => {}; // stub for layouts without dropdown swatches const sizePresetGroup = document.getElementById('size-preset-group'); const toggleShineBtn = null; @@ -1112,45 +1119,25 @@ function renderAllowedPalette() { if (!paletteBox) return; paletteBox.innerHTML = ''; - (window.PALETTE || []).forEach(group => { - const title = document.createElement('div'); - title.className = 'family-title'; - title.textContent = group.family; - paletteBox.appendChild(title); - - const row = document.createElement('div'); - row.className = 'swatch-row'; - (group.colors || []).forEach(c => { - const idx = - FLAT_COLORS.find(fc => fc.name === c.name && fc.hex === c.hex && fc.family === group.family)?._idx - ?? HEX_TO_FIRST_IDX.get(normalizeHex(c.hex)); - const sw = document.createElement('button'); - sw.type = 'button'; - sw.className = 'swatch'; - sw.setAttribute('aria-label', c.name); - - if (c.image) { - const meta = FLAT_COLORS[idx] || {}; - sw.style.backgroundImage = `url("${c.image}")`; - sw.style.backgroundSize = `${100 * SWATCH_TEXTURE_ZOOM}%`; - sw.style.backgroundPosition = `${(meta.imageFocus?.x ?? 0.5) * 100}% ${(meta.imageFocus?.y ?? 0.5) * 100}%`; - } else { - sw.style.backgroundColor = c.hex; - } - - if (idx === selectedColorIdx) sw.classList.add('active'); - sw.title = c.name; - - sw.addEventListener('click', () => { - selectedColorIdx = idx ?? 0; - renderAllowedPalette(); + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'btn-dark w-full'; + btn.textContent = 'Choose color'; + btn.addEventListener('click', () => { + if (!window.openColorPicker) return; + window.openColorPicker({ + title: 'Choose active color', + subtitle: 'Applies to drawing and path tools', + items: (FLAT_COLORS || []).map((c, idx) => ({ label: c.name || c.hex, metaText: c.family || '', idx })), + onSelect: (item) => { + if (!Number.isInteger(item.idx)) return; + selectedColorIdx = item.idx; updateCurrentColorChip(); persist(); - }); - row.appendChild(sw); + } }); - paletteBox.appendChild(row); }); + paletteBox.appendChild(btn); } function getUsedColors() { @@ -1212,8 +1199,6 @@ onSelect: (item) => { if (!Number.isInteger(item.idx)) return; selectedColorIdx = item.idx; - renderAllowedPalette(); - renderUsedPalette(); updateCurrentColorChip(); persist(); } @@ -1238,58 +1223,8 @@ function renderUsedPalette() { if (!usedPaletteBox) return; - usedPaletteBox.innerHTML = ''; - const used = getUsedColors(); - if (used.length === 0) { - usedPaletteBox.innerHTML = '
No colors yet.
'; - if (replaceFromSel) replaceFromSel.innerHTML = ''; - return; - } - const row = document.createElement('div'); - row.className = 'swatch-row'; - used.forEach(item => { - const sw = document.createElement('button'); - sw.type = 'button'; - sw.className = 'swatch'; - const name = item.name || NAME_BY_HEX.get(item.hex) || item.hex; - sw.setAttribute('aria-label', `${name} - Count: ${item.count}`); - - if (item.image) { - const meta = FLAT_COLORS[HEX_TO_FIRST_IDX.get(item.hex)] || {}; - sw.style.backgroundImage = `url("${item.image}")`; - sw.style.backgroundSize = `${100 * SWATCH_TEXTURE_ZOOM}%`; - sw.style.backgroundPosition = `${(meta.imageFocus?.x ?? 0.5) * 100}% ${(meta.imageFocus?.y ?? 0.5) * 100}%`; - } else { - sw.style.backgroundColor = item.hex; - } - if (normalizeHex(FLAT_COLORS[selectedColorIdx]?.hex) === item.hex) sw.classList.add('active'); - sw.title = `${name} — ${item.count}`; - sw.addEventListener('click', () => { - selectedColorIdx = HEX_TO_FIRST_IDX.get(item.hex) ?? 0; - renderAllowedPalette(); - renderUsedPalette(); - }); - - const badge = document.createElement('div'); - badge.className = 'badge'; - badge.textContent = String(item.count); - sw.appendChild(badge); - row.appendChild(sw); - }); - usedPaletteBox.appendChild(row); - - // fill "replace from" - if (replaceFromSel) { - replaceFromSel.innerHTML = ''; - used.forEach(item => { - const opt = document.createElement('option'); - const name = item.name || NAME_BY_HEX.get(item.hex) || item.hex; - opt.value = item.hex; - opt.textContent = `${name} (${item.count})`; - replaceFromSel.appendChild(opt); - }); - updateReplaceChips(); - } + usedPaletteBox.innerHTML = '
Palette opens in modal.
'; + if (replaceFromSel) replaceFromSel.innerHTML = ''; } // ====== Balloon Ops & Data/Export ====== diff --git a/wall.js b/wall.js index 9aec76a..74596e2 100644 --- a/wall.js +++ b/wall.js @@ -623,36 +623,7 @@ function renderWallUsedPalette() { if (!wallUsedPaletteEl) return; - const used = wallUsedColors(); - wallUsedPaletteEl.innerHTML = ''; - if (!used.length) { - wallUsedPaletteEl.innerHTML = '
No colors yet.
'; - populateWallReplaceSelects(); - updateWallReplacePreview(); - return; - } - const row = document.createElement('div'); - row.className = 'swatch-row'; - used.forEach(item => { - const sw = document.createElement('button'); - sw.type = 'button'; - sw.className = 'swatch'; - if (item.image) { - sw.style.backgroundImage = `url("${item.image}")`; - sw.style.backgroundSize = `${100 * 2.5}%`; - } else { - sw.style.backgroundColor = item.hex; - } - sw.title = `${item.name || item.hex} (${item.count})`; - sw.addEventListener('click', () => { - if (!Number.isInteger(item.idx)) return; - setActiveColor(normalizeColorIdx(item.idx)); - renderWallPalette(); - renderWallUsedPalette(); - }); - row.appendChild(sw); - }); - wallUsedPaletteEl.appendChild(row); + wallUsedPaletteEl.innerHTML = '
Palette opens in modal.
'; populateWallReplaceSelects(); updateWallReplacePreview(); } @@ -1003,47 +974,25 @@ if (!wallPaletteEl) return; wallPaletteEl.innerHTML = ''; populateWallReplaceSelects(); - (window.PALETTE || []).forEach(group => { - const title = document.createElement('div'); - title.className = 'family-title'; - title.textContent = group.family; - wallPaletteEl.appendChild(title); - - const row = document.createElement('div'); - row.className = 'swatch-row'; - (group.colors || []).forEach(c => { - const normHex = (c.hex || '').toLowerCase(); - let idx = FLAT_COLORS.findIndex(fc => fc.name === c.name && fc.hex === c.hex && fc.family === group.family); - if (idx < 0 && window.shared?.HEX_TO_FIRST_IDX?.has(normHex)) { - idx = window.shared.HEX_TO_FIRST_IDX.get(normHex); + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'btn-dark w-full'; + btn.textContent = 'Choose color'; + btn.addEventListener('click', () => { + if (!window.openColorPicker) return; + window.openColorPicker({ + title: 'Choose active wall color', + subtitle: 'Applies to wall fill tools', + items: (FLAT_COLORS || []).map((c, idx) => ({ label: c.name || c.hex, metaText: c.family || '', idx })), + onSelect: (item) => { + if (!Number.isInteger(item.idx)) return; + setActiveColor(item.idx); + updateWallActiveChip(getActiveWallColorIdx()); + updateWallReplacePreview(); } - idx = normalizeColorIdx(idx); - const sw = document.createElement('button'); - sw.type = 'button'; - sw.className = 'swatch'; - if (c.image) { - const meta = FLAT_COLORS[idx] || {}; - sw.style.backgroundImage = `url("${c.image}")`; - sw.style.backgroundSize = `${100 * 2.5}%`; - sw.style.backgroundPosition = `${(meta.imageFocus?.x ?? 0.5) * 100}% ${(meta.imageFocus?.y ?? 0.5) * 100}%`; - } else { - sw.style.backgroundColor = c.hex; - } - if (idx === selectedColorIdx) sw.classList.add('active'); - sw.title = c.name; - sw.addEventListener('click', () => { - setActiveColor(idx); - window.organic?.updateCurrentColorChip?.(selectedColorIdx); - // Also update the global chip explicitly - if (window.organic?.updateCurrentColorChip) { - window.organic.updateCurrentColorChip(selectedColorIdx); - } - renderWallPalette(); - }); - row.appendChild(sw); }); - wallPaletteEl.appendChild(row); }); + wallPaletteEl.appendChild(btn); renderWallUsedPalette(); updateWallActiveChip(getActiveWallColorIdx()); updateWallReplacePreview();