1/** 2 * Spacing Picker Module 3 * Provides spacing picker functionality for OxyMade 4 */ 5 6window.OxyMade = window.OxyMade || {}; 7 8window.OxyMade.SpacingPicker = { 9 // Spacing values for the picker 10 spacingValues: { 11 's1': '4px', 12 's2': '8px', 13 's3': '12px', 14 's4': '16px', 15 's5': '20px', 16 's6': '24px', 17 's7': '28px', 18 's8': '32px', 19 's9': '36px', 20 's10': '40px', 21 's12': '48px', 22 's14': '56px', 23 's16': '64px', 24 's20': '80px', 25 's24': '96px', 26 's28': '112px', 27 's32': '128px', 28 's36': '144px', 29 's40': '160px', 30 's44': '176px', 31 's48': '192px', 32 's56': '224px', 33 's64': '256px', 34 's72': '288px', 35 }, 36 37 // Section spacing values for the picker 38 sectionSpacingValues: { 39 'ss-none': '0px', 40 'ss-xxs': '20px', 41 'ss-xs': '40px', 42 'ss-sm': '64px', 43 'ss-md': '80px', 44 'ss-lg': '128px', 45 'ss-xl': '160px', 46 'ss-xxl': '256px' 47 }, 48 49 // Border radius values for the picker 50 radiusValues: { 51 'radius-none': '0px', 52 'radius-sm': '2px', 53 'radius-md': '4px', 54 'radius-lg': '8px', 55 'radius-xl': '12px', 56 'radius-2xl': '16px', 57 'radius-3xl': '24px', 58 'radius-full': '9999px' 59 }, 60 61 init(parentWindow) { 62 if (!parentWindow || !parentWindow.jQuery) { 63 return; 64 } 65 66 // Use parent window's jQuery 67 const $ = parentWindow.jQuery; 68 69 // Create and append the popup HTML 70 const popupHtml = ` 71 <div class="oxymade-spacing-popup" id="oxymade-spacing-popup" style="display:none;"> 72 <div class="oxymade-spacing-popup-header"> 73 <div class="oxymade-spacing-popup-title"> 74 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="14" height="14" fill="currentColor"><path d="M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg> 75 <span>Spacing & Radius</span> 76 </div> 77 <div class="oxymade-spacing-popup-actions"> 78 <a href="https://oxymade.com" target="_blank" class="oxymade-branding">OXYMADE</a> 79 <button type="button" class="oxymade-spacing-popup-close"> 80 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" width="12" height="12" fill="currentColor"><path d="M310.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L160 210.7 54.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L114.7 256 9.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 301.3 265.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L205.3 256 310.6 150.6z"/></svg> 81 </button> 82 </div> 83 </div> 84 <div class="oxymade-spacing-popup-body"> 85 <!-- Options will be inserted here dynamically --> 86 </div> 87 </div> 88 `; 89 90 // Remove existing popup if any (to ensure fresh popup) 91 const existingPopup = parentWindow.document.getElementById('oxymade-spacing-popup'); 92 if (existingPopup) { 93 existingPopup.remove(); 94 } 95 96 // Append popup to parent window body 97 $(parentWindow.document.body).append(popupHtml); 98 99 // Populate spacing options 100 const $popupBody = $('#oxymade-spacing-popup .oxymade-spacing-popup-body', parentWindow.document); 101 102 // Clear existing options 103 $popupBody.empty(); 104 105 // Add a heading for spacing 106 $popupBody.append(`<h3>Spacing</h3>`); 107 108 // Add spacing options 109 Object.entries(this.spacingValues).forEach(([key, label]) => { 110 const $option = $(` 111 <div class="oxymade-spacing-option" data-spacing-key="${key}"> 112 <div class="oxymade-spacing-button">
113 <span class="oxymade-spacing-var">${key}</span> 114 </div> 115 <span class="oxymade-spacing-label">${label}</span> 116 </div> 117 `); 118 $popupBody.append($option); 119 }); 120 121 // Add a heading for section spacing 122 $popupBody.append(`<h3>Section Spacing</h3>`); 123 124 // Add spacing options 125 Object.entries(this.sectionSpacingValues).forEach(([key, label]) => { 126 const $option = $(` 127 <div class="oxymade-section-spacing-option" data-spacing-key="${key}"> 128 <div class="oxymade-section-spacing-button"> 129 <span class="oxymade-section-spacing-var">${key.startsWith('ss-') ? key.substring(3) : key}</span> 130 </div> 131 <span class="oxymade-spacing-label">${label}</span> 132 </div> 133 `); 134 $popupBody.append($option); 135 }); 136 137 // Add a heading for Border Radius 138 $popupBody.append(`<h3>Border Radius</h3>`); 139 140 // Add spacing options 141 Object.entries(this.radiusValues).forEach(([key, label]) => { 142 const $option = $(` 143 <div class="oxymade-section-spacing-option" data-spacing-key="${key}"> 144 <div class="oxymade-section-spacing-button"> 145 <span class="oxymade-section-spacing-var">${key.startsWith('radius-') ? key.substring(7) : key}</span> 146 </div> 147 <span class="oxymade-spacing-label">${label}</span> 148 </div> 149 `); 150 $popupBody.append($option); 151 }); 152 153 // Add CSS for the spacing popup 154 const spacingPickerCSS = ` 155 .oxymade-spacing-popup { 156 position: fixed; 157 z-index: 999999; 158 background: #1e1e1e; 159 border: 1px solid #333; 160 border-radius: 8px; 161 box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4); 162 width: 340px; 163 max-height: 480px; 164 overflow: hidden; 165 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 166 display: flex; 167 flex-direction: column; 168 } 169 170 .oxymade-spacing-popup-header { 171 display: flex !important; 172 align-items: center; 173 justify-content: space-between; 174 background: #2a2a2a !important; 175 padding: 12px 14px !important; 176 border-bottom: 1px solid #333; 177 flex-shrink: 0; 178 } 179 180 .oxymade-spacing-popup-title { 181 display: flex; 182 align-items: center; 183 gap: 8px; 184 font-weight: 600; 185 font-size: 13px; 186 color: #fff; 187 } 188 189 .oxymade-spacing-popup-title svg { 190 color: #888; 191 } 192 193 .oxymade-spacing-popup-actions { 194 display: flex; 195 align-items: center; 196 gap: 12px; 197 } 198 199 .oxymade-spacing-popup-header .oxymade-branding { 200 font-size: 9px; 201 color: #666; 202 text-decoration: none; 203 font-weight: 700; 204 letter-spacing: 0.5px; 205 transition: color 0.2s; 206 } 207 208 .oxymade-spacing-popup-header .oxymade-branding:hover { 209 color: #888; 210 } 211 212 .oxymade-spacing-popup-close { 213 background: none; 214 border: none; 215 cursor: pointer; 216 padding: 4px; 217 border-radius: 4px; 218 color: #666; 219 display: flex; 220 align-items: center; 221 justify-content: center; 222 transition: all 0.2s; 223 } 224 225 .oxymade-spacing-popup-close:hover { 226 background: #333; 227 color: #fff; 228 } 229 230 .oxymade-spacing-popup-body { 231 padding: 12px; 232 overflow-y: auto; 233 display: flex; 234 flex-wrap: wrap; 235 gap: 6px; 236 flex: 1; 237 min-height: 0; 238 } 239 240 .oxymade-spacing-popup-body h3 { 241 width: 100%; 242 font-size: 10px; 243 font-weight: 600; 244 color: #888; 245 text-transform: uppercase; 246 letter-spacing: 0.8px; 247 margin: 12px 0 6px 0; 248 padding: 0; 249 } 250 251 .oxymade-spacing-popup-body h3:first-child { 252 margin-top: 0; 253 } 254 255 .oxymade-spacing-option, .oxymade-section-spacing-option { 256 display: flex; 257 flex-direction: column; 258 align-items: center; 259 justify-content: center; 260 width: calc(25% - 5px); 261 padding: 10px 4px; 262 border: 1px solid #333; 263 border-radius: 6px; 264 cursor: pointer; 265 transition: all 0.15s ease; 266 background: #252525; 267 box-sizing: border-box; 268 } 269 270 .oxymade-spacing-option:hover, .oxymade-section-spacing-option:hover { 271 background: #333; 272 border-color: #444; 273 transform: translateY(-1px); 274 } 275 276 .oxymade-spacing-button, .oxymade-section-spacing-button { 277 background: transparent; 278 color: #fff; 279 padding: 0; 280 font-size: 12px; 281 font-weight: 600; 282 } 283 284 .oxymade-spacing-label { 285 font-size: 9px; 286 color: #666; 287 margin-top: 3px; 288 } 289 `; 290 291 // Inject CSS into parent window (remove old styles first to ensure fresh styles) 292 const existingStyle = parentWindow.document.getElementById('oxymade-spacing-picker-styles'); 293 if (existingStyle) { 294 existingStyle.remove(); 295 } 296 const styleElement = parentWindow.document.createElement('style'); 297 styleElement.id = 'oxymade-spacing-picker-styles'; 298 styleElement.textContent = spacingPickerCSS; 299 parentWindow.document.head.appendChild(styleElement); 300 301 // Close button handler 302 $(parentWindow.document).on('click', '.oxymade-spacing-popup-close', function () { 303 $('#oxymade-spacing-popup', parentWindow.document).hide(); 304 }); 305 306 // Note: Right-click context menu is now handled by InputPicker module 307 // This module only handles the popup UI and option click events 308 309 // Click on spacing option to select it 310 $(parentWindow.document).on('click', '.oxymade-spacing-option, .oxymade-section-spacing-option', function () { 311 const spacingKey = $(this).data('spacing-key'); 312 313 // Get current input from InputPicker module 314 const currentInput = window.OxyMade.InputPicker && window.OxyMade.InputPicker.spacingPickerInput; 315 316 if (currentInput) { 317 const value = `var(--${spacingKey})`; 318 const inputEl = currentInput; 319 320 // Use InputPicker's helper to set value with custom unit 321 if (window.OxyMade.InputPicker && window.OxyMade.InputPicker.setValueWithCustomUnit) { 322 window.OxyMade.InputPicker.setValueWithCustomUnit(inputEl, value, parentWindow); 323 } else { 324 // Fallback: just set value directly using native setter 325 const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set; 326 nativeInputValueSetter.call(inputEl, value); 327 inputEl.dispatchEvent(new Event('input', { bubbles: true })); 328 inputEl.dispatchEvent(new Event('change', { bubbles: true })); 329 } 330 331 // Clear the stored input reference 332 if (window.OxyMade.InputPicker) { 333 window.OxyMade.InputPicker.spacingPickerInput = null; 334 } 335 336 // Hide the popup 337 $('#oxymade-spacing-popup', parentWindow.document).hide(); 338 } 339 }); 340 341 // Close popup when clicking outside 342 $(parentWindow.document).on('click', function (e) { 343 if (!$(e.target).closest('.oxymade-spacing-popup').length && 344 !$(e.target).closest('.breakdance-unit-input input').length) { 345 $('#oxymade-spacing-popup', parentWindow.document).hide(); 346 } 347 }); 348 349 // Close popup when pressing Escape 350 $(parentWindow.document).on('keydown', function (e) { 351 if (e.key === 'Escape') { 352 $('#oxymade-spacing-popup', parentWindow.document).hide(); 353 } 354 }); 355 }, 356 357 // function to handle popup positioning 358 positionPopup($popup, clickX, clickY) { 359 const parentWindow = window.parent; 360 // Get window dimensions 361 const windowHeight = parentWindow.jQuery(parentWindow).height(); 362 const windowWidth = parentWindow.jQuery(parentWindow).width(); 363 364 // Get popup dimensions 365 const popupHeight = $popup.outerHeight(); 366 const popupWidth = $popup.outerWidth(); 367 368 // Calculate if popup would go off screen 369 let top = clickY; 370 let left = clickX; 371 372 // Check bottom edge 373 if (top + popupHeight > windowHeight) { 374 top = clickY - popupHeight; 375 } 376 377 // Check right edge 378 if (left + popupWidth > windowWidth) { 379 left = clickX - popupWidth; 380 } 381 382 // Ensure popup stays within viewport (minimum position) 383 top = Math.max(10, top); 384 left = Math.max(10, left); 385 386 // Set position 387 $popup.css({ 388 top: top + 'px', 389 left: left + 'px', 390 display: 'block' 391 }); 392 } 393};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.