UNPKG

@oxyhq/services

Version:

Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀

161 lines (154 loc) • 7.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } // Using plain React Native styles (nativewind not installed in this repo) /** * Responsive justified photo grid that stretches to the provided containerWidth. * Uses flex rows with proportional children widths instead of absolute pixel widths so it always fills. */ const JustifiedPhotoGrid = ({ photos, photoDimensions, loadPhotoDimensions, createJustifiedRows, renderJustifiedPhotoItem, textColor, containerWidth: explicitWidth, gap = 4, minRowHeight = 100, maxRowHeight = 300, dateFormatLocale = 'en-US' }) => { // Responsive width measurement if not explicitly provided const [measuredWidth, setMeasuredWidth] = (0, _react.useState)(null); const effectiveWidth = explicitWidth ?? measuredWidth ?? 0; // 0 until measured const onLayoutContainer = (0, _react.useCallback)(e => { if (explicitWidth) return; // ignore if controlled const w = e.nativeEvent.layout.width; setMeasuredWidth(prev => prev === w ? prev : w); }, [explicitWidth]); // Ensure dimensions are loaded for displayed photos (0, _react.useEffect)(() => { loadPhotoDimensions(photos); // eslint-disable-next-line react-hooks/exhaustive-deps }, [photos.map(p => p.id).join(',')]); // Group photos by date first const photosByDate = (0, _react.useMemo)(() => { return photos.reduce((groups, photo) => { const date = new Date(photo.uploadDate).toDateString(); if (!groups[date]) groups[date] = []; groups[date].push(photo); return groups; }, {}); }, [photos]); const sortedDates = (0, _react.useMemo)(() => Object.keys(photosByDate).sort((a, b) => new Date(b).getTime() - new Date(a).getTime()), [photosByDate]); // Track measured width of each date section (may differ if parent applies horizontal padding/margins) const [dateWidths, setDateWidths] = (0, _react.useState)({}); const onLayoutDate = (0, _react.useCallback)((date, width) => { setDateWidths(prev => prev[date] === width ? prev : { ...prev, [date]: width }); }, []); return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: { width: '100%' }, onLayout: onLayoutContainer, children: effectiveWidth === 0 && !explicitWidth ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, { children: sortedDates.map(date => { const dayPhotos = photosByDate[date]; // createJustifiedRows should build rows such that the "ideal" height (availableWidth / totalAspect) stays within min/max. // We pass the effective container width. const dateWidth = dateWidths[date] ?? effectiveWidth; // fallback to overall width until measured const rows = dateWidth > 0 ? createJustifiedRows(dayPhotos, dateWidth) : []; return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: { marginBottom: 24, width: '100%' }, onLayout: e => onLayoutDate(date, e.nativeEvent.layout.width), children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: { fontSize: 14, fontWeight: '600', marginBottom: 12, color: textColor }, children: new Date(date).toLocaleDateString(dateFormatLocale, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: { width: '100%' }, children: rows.map((row, rowIndex) => { // Compute total aspect ratios using loaded dimensions (fallback 4/3) const aspects = row.map(p => { const dims = photoDimensions[p.id]; return dims ? dims.width / dims.height : 4 / 3; }); const totalAspect = aspects.reduce((a, b) => a + b, 0); const gapsTotal = gap * (row.length - 1); const availableWidth = dateWidth - gapsTotal; // Ideal height that perfectly fills width when preserving aspect ratios const idealHeight = availableWidth / totalAspect; // We rely on row construction keeping idealHeight within min/max bounds; if not, clamp but then distribute leftover/overflow. let rowHeight = idealHeight; let widthAdjustment = 0; // difference to distribute if clamped if (idealHeight < minRowHeight) { rowHeight = minRowHeight; widthAdjustment = availableWidth - rowHeight * totalAspect; // negative means overflow } else if (idealHeight > maxRowHeight) { rowHeight = maxRowHeight; widthAdjustment = availableWidth - rowHeight * totalAspect; } // Pre-compute widths maintaining aspect ratios let widths = aspects.map(ar => ar * rowHeight); // If we have widthAdjustment (due to clamping) distribute proportionally so row still fills exactly if (widthAdjustment !== 0) { const widthSum = widths.reduce((a, b) => a + b, 0); widths = widths.map(w => w + w / widthSum * widthAdjustment); } // To combat rounding issues, adjust last item width to fill precisely const widthSumRounded = widths.reduce((a, b) => a + b, 0); const roundingDiff = availableWidth - widthSumRounded; if (Math.abs(roundingDiff) > 0.5) { widths[widths.length - 1] += roundingDiff; // minimal correction } return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: { flexDirection: 'row', width: '100%', marginBottom: 4 }, children: row.map((p, i) => { const photoWidth = widths[i]; return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: { width: photoWidth, height: rowHeight, marginRight: i === row.length - 1 ? 0 : gap }, children: renderJustifiedPhotoItem(p, photoWidth, rowHeight, i === row.length - 1) }, p.id); }) }, rowIndex); }) })] }, date); }) }) }); }; var _default = exports.default = /*#__PURE__*/_react.default.memo(JustifiedPhotoGrid); //# sourceMappingURL=JustifiedPhotoGrid.js.map