0 }, get firstVideoIndex() { return this.hasVideos ? this.images.length : -1 }, get total() { return this.images.length + this.productVideos.length }, modalOpen: false, modalActive: 0, // Drag/swipe state isDragging: false, wasDragging: false, startX: 0, currentX: 0, dragOffset: 0, containerWidth: 0, startY: 0, directionLocked: null, isRtl: false, imageLoading: false, // Zoom state zoomScale: 1, zoomPanX: 0, zoomPanY: 0, zoomPinching: false, zoomPanning: false, zoomInitialDistance: 0, zoomInitialScale: 1, zoomPanStartX: 0, zoomPanStartY: 0, zoomPanOffsetX: 0, zoomPanOffsetY: 0, zoomLastTap: 0, zoomLastTouchX: 0, zoomLastTouchY: 0, zoomAnimating: false, lastInputWasTouch: false, init() { this.isRtl = document.documentElement.dir === 'rtl'; this.$nextTick(() => { this.containerWidth = this.$refs.carouselContainer?.offsetWidth || 0; // Handle already-cached images where x-on:load won't fire this.$el.querySelectorAll('img.lqip-placeholder').forEach(lqip => { const realImg = lqip.nextElementSibling; if (realImg && realImg.complete && realImg.naturalWidth > 0) { realImg.dataset.lqipDone = '1'; lqip.style.display = 'none'; } }); }); window.addEventListener('resize', () => { this.containerWidth = this.$refs.carouselContainer?.offsetWidth || 0; }); // Preload first image of each variant for instant switching Object.values(this.variationImagesMap).forEach(variant => { if (variant.images && variant.images[0]) { new Image().src = variant.images[0]; } }); // Only the active slide may play. Clearing startedVideo also // drops the bound src, so swiping away stops the download and // not just the playback. this.$watch('active', () => { this.startedVideo = null; this.$el.querySelectorAll('video[data-product-video]').forEach(v => v.pause()); }); }, handleDragStart(e) { if (this.total <= 1) return; this.isDragging = true; this.directionLocked = null; this.startX = e.type.includes('mouse') ? e.clientX : e.touches[0].clientX; this.startY = e.type.includes('mouse') ? e.clientY : e.touches[0].clientY; this.currentX = this.startX; this.containerWidth = this.$refs.carouselContainer?.offsetWidth || 0; }, handleDragMove(e) { if (!this.isDragging) return; const clientX = e.type.includes('mouse') ? e.clientX : e.touches[0].clientX; const clientY = e.type.includes('mouse') ? e.clientY : e.touches[0].clientY; if (this.directionLocked === null) { const deltaX = Math.abs(clientX - this.startX); const deltaY = Math.abs(clientY - this.startY); if (deltaX < 5 && deltaY < 5) return; if (deltaY > deltaX) { this.directionLocked = 'vertical'; this.isDragging = false; this.dragOffset = 0; return; } this.directionLocked = 'horizontal'; } if (this.directionLocked === 'vertical') return; e.preventDefault(); this.currentX = clientX; let diff = this.currentX - this.startX; // Limit drag at edges const atFirst = this.active === 0; const atLast = this.active === this.total - 1; const isAtEdge = this.isRtl ? (atFirst && diff < 0) || (atLast && diff > 0) : (atFirst && diff > 0) || (atLast && diff < 0); if (isAtEdge) { diff = diff * 0.3; // Resistance at edges } this.dragOffset = diff; }, handleDragEnd() { this.directionLocked = null; if (!this.isDragging) return; this.isDragging = false; // Mark that we just finished dragging to prevent click from opening modal if (Math.abs(this.dragOffset) > 5) { this.wasDragging = true; setTimeout(() => { this.wasDragging = false; }, 100); } const threshold = this.containerWidth * 0.2; if (Math.abs(this.dragOffset) > threshold) { if (this.isRtl) { // RTL: drag left (negative) = prev, drag right (positive) = next if (this.dragOffset < 0) { this.prev(); } else { this.next(); } } else { // LTR: drag right (positive) = prev, drag left (negative) = next if (this.dragOffset > 0) { this.prev(); } else { this.next(); } } } this.dragOffset = 0; }, getSlideTransform() { // RTL: images flow right-to-left, so we use positive offset // LTR: images flow left-to-right, so we use negative offset const baseOffset = this.isRtl ? this.active * 100 : -this.active * 100; const dragPercent = this.containerWidth > 0 ? (this.dragOffset / this.containerWidth) * 100 : 0; return `translateX(${baseOffset + dragPercent}%)`; }, next() { if (this.active < this.total - 1) { this.active = this.active + 1; } }, prev() { if (this.active > 0) { this.active = this.active - 1; } }, goTo(idx) { this.active = idx }, openModal(idx) { if (this.isDragging || this.wasDragging) return; // The lightbox is images only. Its surface is touch-action:none // with modalDragStart calling preventDefault() on every touch, // which would swallow the native video control bar - and // native fullscreen is one tap away from the inline player // anyway. Video slides simply never open it. if (this.hasVideos && idx >= this.firstVideoIndex) return; this.modalActive = idx; this.modalOpen = true; document.body.style.overflow = 'hidden'; }, closeModal() { this.resetZoom(); this.modalOpen = false; document.body.style.overflow = 'auto'; }, // Wrap on the image count, not `total`: the modal never shows a // video, so paging must not land on a video index. get modalTotal() { return Math.max(1, this.images.length) }, modalNext() { this.resetZoom(); this.modalActive = (this.modalActive + 1) % this.modalTotal }, modalPrev() { this.resetZoom(); this.modalActive = (this.modalActive - 1 + this.modalTotal) % this.modalTotal }, modalGoTo(idx) { this.resetZoom(); this.modalActive = idx }, // Modal drag/swipe modalDragging: false, modalWasDragging: false, modalStartX: 0, modalDragOffset: 0, // Zoom helpers resetZoom() { this.zoomScale = 1; this.zoomPanX = 0; this.zoomPanY = 0; this.zoomPinching = false; this.zoomPanning = false; }, getTouchDistance(touches) { return Math.hypot( touches[0].clientX - touches[1].clientX, touches[0].clientY - touches[1].clientY ); }, clampPan() { const maxPanX = Math.max(0, (this.zoomScale - 1) * window.innerWidth / 2); const maxPanY = Math.max(0, (this.zoomScale - 1) * window.innerHeight / 2); this.zoomPanX = Math.max(-maxPanX, Math.min(maxPanX, this.zoomPanX)); this.zoomPanY = Math.max(-maxPanY, Math.min(maxPanY, this.zoomPanY)); }, modalDragStart(e) { const isTouch = e.type.includes('touch'); this.lastInputWasTouch = isTouch; // Store touch position for double-tap zoom center if (isTouch && e.touches[0]) { this.zoomLastTouchX = e.touches[0].clientX; this.zoomLastTouchY = e.touches[0].clientY; } // Two fingers: start pinch-to-zoom if (isTouch && e.touches.length === 2) { this.zoomPinching = true; this.zoomInitialDistance = this.getTouchDistance(e.touches); this.zoomInitialScale = this.zoomScale; this.modalDragging = false; this.zoomPanning = false; e.preventDefault(); return; } // Single finger/mouse while zoomed: start panning if (this.zoomScale > 1) { this.zoomPanning = true; this.zoomPanStartX = isTouch ? e.touches[0].clientX : e.clientX; this.zoomPanStartY = isTouch ? e.touches[0].clientY : e.clientY; this.zoomPanOffsetX = this.zoomPanX; this.zoomPanOffsetY = this.zoomPanY; e.preventDefault(); return; } // Single finger not zoomed or mouse: existing swipe // Prevent browser double-tap-to-zoom so our custom handler works if (isTouch) { e.preventDefault(); } if (this.total <= 1) return; this.modalDragging = true; this.modalStartX = isTouch ? e.touches[0].clientX : e.clientX; this.modalDragOffset = 0; }, modalDragMove(e) { const isTouch = e.type.includes('touch'); // Pinch-to-zoom if (this.zoomPinching && isTouch && e.touches.length >= 2) { e.preventDefault(); const newDist = this.getTouchDistance(e.touches); let newScale = this.zoomInitialScale * (newDist / this.zoomInitialDistance); this.zoomScale = Math.max(1, Math.min(4, newScale)); this.clampPan(); return; } // Panning while zoomed if (this.zoomPanning) { e.preventDefault(); const px = isTouch ? e.touches[0].clientX : e.clientX; const py = isTouch ? e.touches[0].clientY : e.clientY; const dx = px - this.zoomPanStartX; const dy = py - this.zoomPanStartY; this.zoomPanX = this.zoomPanOffsetX + dx; this.zoomPanY = this.zoomPanOffsetY + dy; this.clampPan(); return; } // Existing swipe logic if (!this.modalDragging) return; e.preventDefault(); const x = isTouch ? e.touches[0].clientX : e.clientX; this.modalDragOffset = x - this.modalStartX; }, modalDragEnd(e) { const isTouch = e && e.type && e.type.includes('touch'); // End pinch if (this.zoomPinching) { this.zoomPinching = false; // Snap to 1 if nearly unzoomed if (this.zoomScale < 1.1) { this.resetZoom(); } this.modalWasDragging = true; setTimeout(() => { this.modalWasDragging = false; }, 100); // If one finger remains after pinch, start panning if (isTouch && e.touches && e.touches.length === 1 && this.zoomScale > 1) { this.zoomPanning = true; this.zoomPanStartX = e.touches[0].clientX; this.zoomPanStartY = e.touches[0].clientY; this.zoomPanOffsetX = this.zoomPanX; this.zoomPanOffsetY = this.zoomPanY; } return; } // End pan if (this.zoomPanning) { this.zoomPanning = false; this.modalWasDragging = true; setTimeout(() => { this.modalWasDragging = false; }, 100); // Double-tap to zoom out while panned if (isTouch) { const now = Date.now(); if (now - this.zoomLastTap < 300) { this.zoomAnimating = true; setTimeout(() => { this.zoomAnimating = false; }, 300); this.resetZoom(); this.zoomLastTap = 0; } else { this.zoomLastTap = now; } } return; } // Existing swipe end logic const wasDragging = this.modalDragging; if (this.modalDragging) { this.modalDragging = false; const absDrag = Math.abs(this.modalDragOffset); if (absDrag > 5) { this.modalWasDragging = true; setTimeout(() => { this.modalWasDragging = false; }, 100); } const threshold = 80; if (absDrag > threshold) { if (this.isRtl) { this.modalDragOffset < 0 ? this.modalPrev() : this.modalNext(); } else { this.modalDragOffset > 0 ? this.modalPrev() : this.modalNext(); } this.modalDragOffset = 0; this.zoomLastTap = 0; return; } this.modalDragOffset = 0; } // Double-tap detection (works for both zoomed and not zoomed) if (isTouch) { const now = Date.now(); if (now - this.zoomLastTap < 300) { this.zoomAnimating = true; setTimeout(() => { this.zoomAnimating = false; }, 300); this.modalWasDragging = true; setTimeout(() => { this.modalWasDragging = false; }, 200); if (this.zoomScale > 1) { this.resetZoom(); } else { const cx = this.zoomLastTouchX - window.innerWidth / 2; const cy = this.zoomLastTouchY - window.innerHeight / 2; this.zoomScale = 2.5; this.zoomPanX = -cx * (this.zoomScale - 1) / this.zoomScale; this.zoomPanY = -cy * (this.zoomScale - 1) / this.zoomScale; this.clampPan(); } this.zoomLastTap = 0; return; } this.zoomLastTap = now; // Single tap on backdrop: close modal (touch equivalent of @click.self) if (e.target === e.currentTarget) { this.closeModal(); } } }, switchToVariation(attrValueId) { const varImages = this.variationImagesMap[attrValueId]; let newImages, newLargeImages, newLqipImages; if (varImages && varImages.images && varImages.images.length > 0) { newImages = varImages.images; newLargeImages = varImages.largeImages || varImages.images; newLqipImages = varImages.lqipImages || []; } else { newImages = this.defaultImages; newLargeImages = this.defaultLargeImages; newLqipImages = this.defaultLqipImages; } // Show loading state while first image loads this.imageLoading = true; const firstImg = new Image(); firstImg.onload = () => { this.localImages = newImages; this.localLargeImages = newLargeImages; this.localLqipImages = newLqipImages; this.active = 0; this.modalActive = 0; this.imageLoading = false; }; firstImg.onerror = () => { this.localImages = newImages; this.localLargeImages = newLargeImages; this.localLqipImages = newLqipImages; this.active = 0; this.modalActive = 0; this.imageLoading = false; }; firstImg.src = newImages[0]; // If already cached, onload fires synchronously or near-instantly } }" x-on:keydown.escape.window="closeModal()" x-on:keydown.arrow-left.window="modalOpen && modalPrev()" x-on:keydown.arrow-right.window="modalOpen && modalNext()" x-on:switch-variation-images.window="switchToVariation($event.detail.attrValueId ?? $event.detail[0]?.attrValueId)">
/

مكواة نورفا البخارية المنزلية

أجهزة المنزل
#AFKPQ
IQD 61,000
مكواة نورفا البخارية المنزلية

مكواة نورفا البخارية المنزلية الاحترافية بالة A

 

الاستخدامات:

 

كي وفرد فائق السلاسة للتجاعيد العميقة والكسرات الصعبة في الأقمشة الثقيلة والخفيفة (البدلات الرسمية، فساتين السهرة، العبايات، والستائر).

 

مثالية لجلسات الكي المطولة والكميات الكبيرة بفضل المرجل المنفصل الذي يوفر ضخاً مستمراً ومستقراً للبخار دون انقطاع.

 

تعقيم وتحديث الأنسجة والتخلص من البكتيريا والروائح الكريهة العالقة بالملابس بفضل حرارة وقوة دفع البخار المكثف.

 

المميزات:

 

مقبض فلين طبيعي عازل (Cork Handle): مقبض كلاسيكي فاخر مصنوع من الفلين الطبيعي بالكامل، يوفر عزلاً تاماً لحرارة البخار، ويمنحك ملمساً مريحاً مانعاً لتعرق اليد أثناء الكي الطويل.

 

لوح كي فولاذي بفتحات أمامية دقيقة: قاعدة المكواة مصنوعة من الفولاذ المقاوم للصدأ (Stainless Steel) المصقول عالي الجودة، مجهزة بمجموعة فتحات بخار هندسية مركزة عند مقدمة اللوح (الرأس المدبب) لضمان تغلغل البخار في الزوايا الحرجة والياقات بكل دقة.

 

قاعدة دعم بـ 8 وسادات حماية مضادة للانزلاق: سطح محطة قاعدة البخار مجهز بـ 8 قطع جكامات (وسادات) مطاطية سوداء بارزة ومقاومة للحرارة العالية، لتثبيت المكواة بأمان ومنع خدشها أو انزلاقها أثناء الراحة.

 

مفاتيح تشغيل ثنائية مستقلة (Dual Switch): تحتوي خلفية المنظومة على مفتاحين تشغيل منفصلين ومضيئين (مفتاح لتشغيل تسخين المرجل ومفتاح لتشغيل تسخين المكواة)، مما يتيح لك مرونة فائقة في التحكم مع لمبة إشارة مركزية لمراقبة استقرار الضغط.

 

صمام غلق وضغط شديد الأمان: مجهزة بغطاء لولبي سميك ومحكم الإغلاق للمرجل (صمام أمان النفاث)، يعمل على حبس الضغط العالي الذي يصل إلى 3.5 بار ويمنع تسرب البخار الساخن نهائياً لحماية المستخدم.

 

تحكم ميكانيكي دقيق بالحرارة: قرص دوار مدمج أسفل المقبض يسمح بالتنقل الدقيق بين درجات الحرارة المخصصة لكل نسيج (نايلون، حرير، صوف، قطن، كتان).

 

الملاحظات:

 

صمام الأمان والضغط (هام جداً): يُمنع منعاً باتاً فتح غطاء صمام الأمان الأزرق البارز أعلى القاعدة أثناء تشغيل المنظومة أو عندما يكون الجهاز ساخناً وتحت ضغط (3.5 بار)؛ انتظر حتى يبرد الجهاز تماماً لتفريغ الضغط قبل إعادة الملء.

 

مفاتيح التحكم الثنائية: للحصول على بخار جاف وكثيف، يرجى تشغيل المفتاحين معاً (المرجل والمكواة) وانتظر حوالي 3 دقائق حتى تستقر لمبة البيان قبل الضغط على زناد البخار العلوي الأبيض.

 

حماية لوح الكي: فتحات البخار مركزة هندسياً في مقدمة اللوح الفولاذي لتركيز الضغط؛ تجنب تمرير اللوح فوق الأزرار المعدنية الحادة أو السحابات (السوستة) لحماية السطح المصقول من الخدوش.

 

محتويات الصندوق:

 

مكواة مع القاعدة متصلة.

 

كوب قياس اضافة الماء.

 

كتيب التعليمات.

 

القياسات:

 

قدرة الطاقة الحقيقية: 2000 واط.

 

سعة مرجل المياه الداخلي: 850 مل.

 

معدل ضخ البخار المستمر: 30 - 50 غرام في الدقيقة.

 

أبعاد المنتج الكلية: طول 30 سم × عرض 22 سم × ارتفاع 30 سم.

 

طول سلك الكهرباء الأساسي: 165 سم | طول سلكخرطوم البخار المعزول: 140 سم.

 

أبعاد كرتون التغليف: 38 × 18 × 38 سم.

 

لا يمكن استبدال او استرجاع منتجات البالة

Category أجهزة المنزل
SKU AFKPQ
0 (0 reviews)

No reviews yet. Be the first to review this product!

Login to write a review

Related Products

IQD 61,000
About Us
  • نحن نقدم منتجات عالية الجودة بأسعار منافسة. هدفنا هو جعل التسوق عبر الإنترنت سهلاً وممتعًا.
Categories
Contact Us
  • يرجى الاتصال بنا لأي أستفسارات أو دعم. 07779934493 9647779934493

© 2026 كلشي سيل. جميع الحقوق محفوظة.

Online store designed and built by Trinavo

Kulshisell

Add our store to your home screen

  1. 1 Tap the Share button in the browser bar
  2. 2 Choose Add to Home Screen