@biela.dev/devices 1.6.3 → 1.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/android/index.cjs +69 -21
- package/dist/android/index.d.cts +120 -58
- package/dist/android/index.d.ts +120 -58
- package/dist/android/index.js +1 -1
- package/dist/{chunk-DYKZBZRY.cjs → chunk-2EFRCHF7.cjs} +606 -218
- package/dist/chunk-2EFRCHF7.cjs.map +1 -0
- package/dist/{chunk-DLT4UL35.js → chunk-DF2YDUHR.js} +606 -219
- package/dist/chunk-DF2YDUHR.js.map +1 -0
- package/dist/chunk-LNEWMNRU.js +3437 -0
- package/dist/chunk-LNEWMNRU.js.map +1 -0
- package/dist/chunk-W6W7WIY5.cjs +3470 -0
- package/dist/chunk-W6W7WIY5.cjs.map +1 -0
- package/dist/index.cjs +206 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +87 -6
- package/dist/index.js.map +1 -1
- package/dist/ios/index.cjs +32 -28
- package/dist/ios/index.d.cts +19 -26
- package/dist/ios/index.d.ts +19 -26
- package/dist/ios/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-76PRN3YN.js +0 -1281
- package/dist/chunk-76PRN3YN.js.map +0 -1
- package/dist/chunk-DLT4UL35.js.map +0 -1
- package/dist/chunk-DYKZBZRY.cjs.map +0 -1
- package/dist/chunk-FOTZN6UL.cjs +0 -1302
- package/dist/chunk-FOTZN6UL.cjs.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { D as DeviceMeta, a as DeviceLayoutData, b as DeviceLayoutContract, S as SafeAreaInsets, C as ContentRect, H as HardwareOverlayType, O as OverlayRect, R as RegisteredDevice } from './contract-types-Cw1rmF3b.cjs';
|
|
2
2
|
export { c as DeviceCSSVariables, d as DeviceFrameInfo, e as SVGCropRect, f as SVGScreenRect } from './contract-types-Cw1rmF3b.cjs';
|
|
3
|
-
export { IPHONE_16E_FRAME, IPHONE_16E_LAYOUT, IPHONE_16E_META, IPHONE_16_FRAME, IPHONE_16_LAYOUT, IPHONE_16_META, IPHONE_16_SCREEN_RECT, IPHONE_17_PRO_FRAME, IPHONE_17_PRO_LAYOUT, IPHONE_17_PRO_MAX_FRAME, IPHONE_17_PRO_MAX_LAYOUT, IPHONE_17_PRO_MAX_META, IPHONE_17_PRO_MAX_SCREEN_RECT, IPHONE_17_PRO_META, IPHONE_17_PRO_SCREEN_RECT, IPHONE_AIR_FRAME, IPHONE_AIR_LAYOUT, IPHONE_AIR_META, IPHONE_SE_3_FRAME, IPHONE_SE_3_LAYOUT, IPHONE_SE_3_META, IPhone16SVG, IPhone16eSVG, IPhone17ProMaxSVG, IPhone17ProSVG, IPhoneAirSVG, IPhoneSE3SVG } from './ios/index.cjs';
|
|
4
|
-
export { GALAXY_S25_EDGE_FRAME, GALAXY_S25_EDGE_LAYOUT, GALAXY_S25_EDGE_META, GALAXY_S25_FRAME, GALAXY_S25_LAYOUT, GALAXY_S25_META, GALAXY_S25_ULTRA_FRAME, GALAXY_S25_ULTRA_LAYOUT, GALAXY_S25_ULTRA_META, GalaxyS25EdgeSVG, GalaxyS25SVG, GalaxyS25UltraSVG, PIXEL_9_PRO_FRAME, PIXEL_9_PRO_LAYOUT, PIXEL_9_PRO_META, PIXEL_9_PRO_XL_FRAME, PIXEL_9_PRO_XL_LAYOUT, PIXEL_9_PRO_XL_META, Pixel9ProSVG, Pixel9ProXLSVG } from './android/index.cjs';
|
|
3
|
+
export { IPHONE_16E_FRAME, IPHONE_16E_LAYOUT, IPHONE_16E_META, IPHONE_16_FRAME, IPHONE_16_LAYOUT, IPHONE_16_META, IPHONE_16_SCREEN_RECT, IPHONE_17_PRO_FRAME, IPHONE_17_PRO_LAYOUT, IPHONE_17_PRO_MAX_FRAME, IPHONE_17_PRO_MAX_LAYOUT, IPHONE_17_PRO_MAX_META, IPHONE_17_PRO_MAX_SCREEN_RECT, IPHONE_17_PRO_META, IPHONE_17_PRO_SCREEN_RECT, IPHONE_AIR_FRAME, IPHONE_AIR_LAYOUT, IPHONE_AIR_META, IPHONE_AIR_SCREEN_RECT, IPHONE_SE_3_FRAME, IPHONE_SE_3_LAYOUT, IPHONE_SE_3_META, IPhone16SVG, IPhone16eSVG, IPhone17ProMaxSVG, IPhone17ProSVG, IPhoneAirSVG, IPhoneSE3SVG } from './ios/index.cjs';
|
|
4
|
+
export { GALAXY_S25_EDGE_FRAME, GALAXY_S25_EDGE_LAYOUT, GALAXY_S25_EDGE_META, GALAXY_S25_FRAME, GALAXY_S25_LAYOUT, GALAXY_S25_META, GALAXY_S25_SCREEN_RECT, GALAXY_S25_ULTRA_FRAME, GALAXY_S25_ULTRA_LAYOUT, GALAXY_S25_ULTRA_META, GALAXY_S25_ULTRA_SCREEN_RECT, GALAXY_Z_FOLD_7_FRAME, GALAXY_Z_FOLD_7_LAYOUT, GALAXY_Z_FOLD_7_META, GALAXY_Z_FOLD_7_OPEN_FRAME, GALAXY_Z_FOLD_7_OPEN_LAYOUT, GALAXY_Z_FOLD_7_OPEN_META, GALAXY_Z_FOLD_7_OPEN_SCREEN_RECT, GALAXY_Z_FOLD_7_SCREEN_RECT, GalaxyS25EdgeSVG, GalaxyS25SVG, GalaxyS25UltraSVG, GalaxyZFold7OpenSVG, GalaxyZFold7SVG, PIXEL_9_PRO_FRAME, PIXEL_9_PRO_LAYOUT, PIXEL_9_PRO_META, PIXEL_9_PRO_XL_FRAME, PIXEL_9_PRO_XL_LAYOUT, PIXEL_9_PRO_XL_META, Pixel9ProSVG, Pixel9ProXLSVG } from './android/index.cjs';
|
|
5
5
|
import 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Built-in device metadata registry —
|
|
8
|
+
* Built-in device metadata registry — 13 devices.
|
|
9
9
|
*
|
|
10
10
|
* Curated to cover every unique screen class (logical resolution).
|
|
11
11
|
* Duplicate resolutions across generations are represented by the latest model.
|
|
@@ -21,6 +21,8 @@ import 'react/jsx-runtime';
|
|
|
21
21
|
* Galaxy S25 Ultra: 384×824dp @3.75x (covers S24 Ultra)
|
|
22
22
|
* Galaxy S25: 360×780dp @3x (covers S24)
|
|
23
23
|
* Galaxy S25 Edge: 382×824dp @3.75x (unique narrow form factor)
|
|
24
|
+
* Galaxy Z Fold 7: 374×870dp @2.89x (foldable cover display)
|
|
25
|
+
* Galaxy Z Fold 7 Open: 771×855dp @2.86x (foldable inner display)
|
|
24
26
|
* Pixel 9 Pro: 393×851dp @3x (covers Pixel 9, S25+)
|
|
25
27
|
* Pixel 9 Pro XL: 448×968dp @3x (largest Android)
|
|
26
28
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { D as DeviceMeta, a as DeviceLayoutData, b as DeviceLayoutContract, S as SafeAreaInsets, C as ContentRect, H as HardwareOverlayType, O as OverlayRect, R as RegisteredDevice } from './contract-types-Cw1rmF3b.js';
|
|
2
2
|
export { c as DeviceCSSVariables, d as DeviceFrameInfo, e as SVGCropRect, f as SVGScreenRect } from './contract-types-Cw1rmF3b.js';
|
|
3
|
-
export { IPHONE_16E_FRAME, IPHONE_16E_LAYOUT, IPHONE_16E_META, IPHONE_16_FRAME, IPHONE_16_LAYOUT, IPHONE_16_META, IPHONE_16_SCREEN_RECT, IPHONE_17_PRO_FRAME, IPHONE_17_PRO_LAYOUT, IPHONE_17_PRO_MAX_FRAME, IPHONE_17_PRO_MAX_LAYOUT, IPHONE_17_PRO_MAX_META, IPHONE_17_PRO_MAX_SCREEN_RECT, IPHONE_17_PRO_META, IPHONE_17_PRO_SCREEN_RECT, IPHONE_AIR_FRAME, IPHONE_AIR_LAYOUT, IPHONE_AIR_META, IPHONE_SE_3_FRAME, IPHONE_SE_3_LAYOUT, IPHONE_SE_3_META, IPhone16SVG, IPhone16eSVG, IPhone17ProMaxSVG, IPhone17ProSVG, IPhoneAirSVG, IPhoneSE3SVG } from './ios/index.js';
|
|
4
|
-
export { GALAXY_S25_EDGE_FRAME, GALAXY_S25_EDGE_LAYOUT, GALAXY_S25_EDGE_META, GALAXY_S25_FRAME, GALAXY_S25_LAYOUT, GALAXY_S25_META, GALAXY_S25_ULTRA_FRAME, GALAXY_S25_ULTRA_LAYOUT, GALAXY_S25_ULTRA_META, GalaxyS25EdgeSVG, GalaxyS25SVG, GalaxyS25UltraSVG, PIXEL_9_PRO_FRAME, PIXEL_9_PRO_LAYOUT, PIXEL_9_PRO_META, PIXEL_9_PRO_XL_FRAME, PIXEL_9_PRO_XL_LAYOUT, PIXEL_9_PRO_XL_META, Pixel9ProSVG, Pixel9ProXLSVG } from './android/index.js';
|
|
3
|
+
export { IPHONE_16E_FRAME, IPHONE_16E_LAYOUT, IPHONE_16E_META, IPHONE_16_FRAME, IPHONE_16_LAYOUT, IPHONE_16_META, IPHONE_16_SCREEN_RECT, IPHONE_17_PRO_FRAME, IPHONE_17_PRO_LAYOUT, IPHONE_17_PRO_MAX_FRAME, IPHONE_17_PRO_MAX_LAYOUT, IPHONE_17_PRO_MAX_META, IPHONE_17_PRO_MAX_SCREEN_RECT, IPHONE_17_PRO_META, IPHONE_17_PRO_SCREEN_RECT, IPHONE_AIR_FRAME, IPHONE_AIR_LAYOUT, IPHONE_AIR_META, IPHONE_AIR_SCREEN_RECT, IPHONE_SE_3_FRAME, IPHONE_SE_3_LAYOUT, IPHONE_SE_3_META, IPhone16SVG, IPhone16eSVG, IPhone17ProMaxSVG, IPhone17ProSVG, IPhoneAirSVG, IPhoneSE3SVG } from './ios/index.js';
|
|
4
|
+
export { GALAXY_S25_EDGE_FRAME, GALAXY_S25_EDGE_LAYOUT, GALAXY_S25_EDGE_META, GALAXY_S25_FRAME, GALAXY_S25_LAYOUT, GALAXY_S25_META, GALAXY_S25_SCREEN_RECT, GALAXY_S25_ULTRA_FRAME, GALAXY_S25_ULTRA_LAYOUT, GALAXY_S25_ULTRA_META, GALAXY_S25_ULTRA_SCREEN_RECT, GALAXY_Z_FOLD_7_FRAME, GALAXY_Z_FOLD_7_LAYOUT, GALAXY_Z_FOLD_7_META, GALAXY_Z_FOLD_7_OPEN_FRAME, GALAXY_Z_FOLD_7_OPEN_LAYOUT, GALAXY_Z_FOLD_7_OPEN_META, GALAXY_Z_FOLD_7_OPEN_SCREEN_RECT, GALAXY_Z_FOLD_7_SCREEN_RECT, GalaxyS25EdgeSVG, GalaxyS25SVG, GalaxyS25UltraSVG, GalaxyZFold7OpenSVG, GalaxyZFold7SVG, PIXEL_9_PRO_FRAME, PIXEL_9_PRO_LAYOUT, PIXEL_9_PRO_META, PIXEL_9_PRO_XL_FRAME, PIXEL_9_PRO_XL_LAYOUT, PIXEL_9_PRO_XL_META, Pixel9ProSVG, Pixel9ProXLSVG } from './android/index.js';
|
|
5
5
|
import 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Built-in device metadata registry —
|
|
8
|
+
* Built-in device metadata registry — 13 devices.
|
|
9
9
|
*
|
|
10
10
|
* Curated to cover every unique screen class (logical resolution).
|
|
11
11
|
* Duplicate resolutions across generations are represented by the latest model.
|
|
@@ -21,6 +21,8 @@ import 'react/jsx-runtime';
|
|
|
21
21
|
* Galaxy S25 Ultra: 384×824dp @3.75x (covers S24 Ultra)
|
|
22
22
|
* Galaxy S25: 360×780dp @3x (covers S24)
|
|
23
23
|
* Galaxy S25 Edge: 382×824dp @3.75x (unique narrow form factor)
|
|
24
|
+
* Galaxy Z Fold 7: 374×870dp @2.89x (foldable cover display)
|
|
25
|
+
* Galaxy Z Fold 7 Open: 771×855dp @2.86x (foldable inner display)
|
|
24
26
|
* Pixel 9 Pro: 393×851dp @3x (covers Pixel 9, S25+)
|
|
25
27
|
* Pixel 9 Pro XL: 448×968dp @3x (largest Android)
|
|
26
28
|
*/
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { PIXEL_9_PRO_META, PIXEL_9_PRO_XL_META, GALAXY_S25_EDGE_META, GALAXY_S25_META, GALAXY_S25_ULTRA_META, PIXEL_9_PRO_LAYOUT, PIXEL_9_PRO_XL_LAYOUT, GALAXY_S25_EDGE_LAYOUT, GALAXY_S25_LAYOUT, GALAXY_S25_ULTRA_LAYOUT } from './chunk-
|
|
2
|
-
export { GALAXY_S25_EDGE_FRAME, GALAXY_S25_EDGE_LAYOUT, GALAXY_S25_EDGE_META, GALAXY_S25_FRAME, GALAXY_S25_LAYOUT, GALAXY_S25_META, GALAXY_S25_ULTRA_FRAME, GALAXY_S25_ULTRA_LAYOUT, GALAXY_S25_ULTRA_META, GalaxyS25EdgeSVG, GalaxyS25SVG, GalaxyS25UltraSVG, PIXEL_9_PRO_FRAME, PIXEL_9_PRO_LAYOUT, PIXEL_9_PRO_META, PIXEL_9_PRO_XL_FRAME, PIXEL_9_PRO_XL_LAYOUT, PIXEL_9_PRO_XL_META, Pixel9ProSVG, Pixel9ProXLSVG } from './chunk-
|
|
3
|
-
import { IPHONE_SE_3_META, IPHONE_16E_META, IPHONE_16_META, IPHONE_AIR_META, IPHONE_17_PRO_META, IPHONE_17_PRO_MAX_META, IPHONE_SE_3_LAYOUT, IPHONE_16E_LAYOUT, IPHONE_16_LAYOUT, IPHONE_AIR_LAYOUT, IPHONE_17_PRO_LAYOUT, IPHONE_17_PRO_MAX_LAYOUT } from './chunk-
|
|
4
|
-
export { IPHONE_16E_FRAME, IPHONE_16E_LAYOUT, IPHONE_16E_META, IPHONE_16_FRAME, IPHONE_16_LAYOUT, IPHONE_16_META, IPHONE_16_SCREEN_RECT, IPHONE_17_PRO_FRAME, IPHONE_17_PRO_LAYOUT, IPHONE_17_PRO_MAX_FRAME, IPHONE_17_PRO_MAX_LAYOUT, IPHONE_17_PRO_MAX_META, IPHONE_17_PRO_MAX_SCREEN_RECT, IPHONE_17_PRO_META, IPHONE_17_PRO_SCREEN_RECT, IPHONE_AIR_FRAME, IPHONE_AIR_LAYOUT, IPHONE_AIR_META, IPHONE_SE_3_FRAME, IPHONE_SE_3_LAYOUT, IPHONE_SE_3_META, IPhone16SVG, IPhone16eSVG, IPhone17ProMaxSVG, IPhone17ProSVG, IPhoneAirSVG, IPhoneSE3SVG } from './chunk-
|
|
1
|
+
import { PIXEL_9_PRO_META, PIXEL_9_PRO_XL_META, GALAXY_Z_FOLD_7_OPEN_META, GALAXY_Z_FOLD_7_META, GALAXY_S25_EDGE_META, GALAXY_S25_META, GALAXY_S25_ULTRA_META, PIXEL_9_PRO_LAYOUT, PIXEL_9_PRO_XL_LAYOUT, GALAXY_Z_FOLD_7_OPEN_LAYOUT, GALAXY_Z_FOLD_7_LAYOUT, GALAXY_S25_EDGE_LAYOUT, GALAXY_S25_LAYOUT, GALAXY_S25_ULTRA_LAYOUT } from './chunk-LNEWMNRU.js';
|
|
2
|
+
export { GALAXY_S25_EDGE_FRAME, GALAXY_S25_EDGE_LAYOUT, GALAXY_S25_EDGE_META, GALAXY_S25_FRAME, GALAXY_S25_LAYOUT, GALAXY_S25_META, GALAXY_S25_SCREEN_RECT, GALAXY_S25_ULTRA_FRAME, GALAXY_S25_ULTRA_LAYOUT, GALAXY_S25_ULTRA_META, GALAXY_S25_ULTRA_SCREEN_RECT, GALAXY_Z_FOLD_7_FRAME, GALAXY_Z_FOLD_7_LAYOUT, GALAXY_Z_FOLD_7_META, GALAXY_Z_FOLD_7_OPEN_FRAME, GALAXY_Z_FOLD_7_OPEN_LAYOUT, GALAXY_Z_FOLD_7_OPEN_META, GALAXY_Z_FOLD_7_OPEN_SCREEN_RECT, GALAXY_Z_FOLD_7_SCREEN_RECT, GalaxyS25EdgeSVG, GalaxyS25SVG, GalaxyS25UltraSVG, GalaxyZFold7OpenSVG, GalaxyZFold7SVG, PIXEL_9_PRO_FRAME, PIXEL_9_PRO_LAYOUT, PIXEL_9_PRO_META, PIXEL_9_PRO_XL_FRAME, PIXEL_9_PRO_XL_LAYOUT, PIXEL_9_PRO_XL_META, Pixel9ProSVG, Pixel9ProXLSVG } from './chunk-LNEWMNRU.js';
|
|
3
|
+
import { IPHONE_SE_3_META, IPHONE_16E_META, IPHONE_16_META, IPHONE_AIR_META, IPHONE_17_PRO_META, IPHONE_17_PRO_MAX_META, IPHONE_SE_3_LAYOUT, IPHONE_16E_LAYOUT, IPHONE_16_LAYOUT, IPHONE_AIR_LAYOUT, IPHONE_17_PRO_LAYOUT, IPHONE_17_PRO_MAX_LAYOUT } from './chunk-DF2YDUHR.js';
|
|
4
|
+
export { IPHONE_16E_FRAME, IPHONE_16E_LAYOUT, IPHONE_16E_META, IPHONE_16_FRAME, IPHONE_16_LAYOUT, IPHONE_16_META, IPHONE_16_SCREEN_RECT, IPHONE_17_PRO_FRAME, IPHONE_17_PRO_LAYOUT, IPHONE_17_PRO_MAX_FRAME, IPHONE_17_PRO_MAX_LAYOUT, IPHONE_17_PRO_MAX_META, IPHONE_17_PRO_MAX_SCREEN_RECT, IPHONE_17_PRO_META, IPHONE_17_PRO_SCREEN_RECT, IPHONE_AIR_FRAME, IPHONE_AIR_LAYOUT, IPHONE_AIR_META, IPHONE_AIR_SCREEN_RECT, IPHONE_SE_3_FRAME, IPHONE_SE_3_LAYOUT, IPHONE_SE_3_META, IPhone16SVG, IPhone16eSVG, IPhone17ProMaxSVG, IPhone17ProSVG, IPhoneAirSVG, IPhoneSE3SVG } from './chunk-DF2YDUHR.js';
|
|
5
5
|
|
|
6
6
|
// src/custom/device-registry.ts
|
|
7
7
|
var STORAGE_KEY = "bielaframe-custom-devices";
|
|
@@ -145,6 +145,8 @@ var BUILTIN_DEVICES = {
|
|
|
145
145
|
"galaxy-s25-ultra": GALAXY_S25_ULTRA_META,
|
|
146
146
|
"galaxy-s25": GALAXY_S25_META,
|
|
147
147
|
"galaxy-s25-edge": GALAXY_S25_EDGE_META,
|
|
148
|
+
"galaxy-z-fold-7": GALAXY_Z_FOLD_7_META,
|
|
149
|
+
"galaxy-z-fold-7-open": GALAXY_Z_FOLD_7_OPEN_META,
|
|
148
150
|
"pixel-9-pro-xl": PIXEL_9_PRO_XL_META,
|
|
149
151
|
"pixel-9-pro": PIXEL_9_PRO_META
|
|
150
152
|
};
|
|
@@ -160,6 +162,8 @@ var DEVICE_LAYOUTS = {
|
|
|
160
162
|
"galaxy-s25-ultra": GALAXY_S25_ULTRA_LAYOUT,
|
|
161
163
|
"galaxy-s25": GALAXY_S25_LAYOUT,
|
|
162
164
|
"galaxy-s25-edge": GALAXY_S25_EDGE_LAYOUT,
|
|
165
|
+
"galaxy-z-fold-7": GALAXY_Z_FOLD_7_LAYOUT,
|
|
166
|
+
"galaxy-z-fold-7-open": GALAXY_Z_FOLD_7_OPEN_LAYOUT,
|
|
163
167
|
"pixel-9-pro-xl": PIXEL_9_PRO_XL_LAYOUT,
|
|
164
168
|
"pixel-9-pro": PIXEL_9_PRO_LAYOUT
|
|
165
169
|
};
|
|
@@ -713,6 +717,12 @@ function analyzeSVGGeometry(svgString) {
|
|
|
713
717
|
id: null
|
|
714
718
|
};
|
|
715
719
|
}
|
|
720
|
+
if (screenRect) {
|
|
721
|
+
const maskScreen = findMaskBasedScreen(svgString, screenRect);
|
|
722
|
+
if (maskScreen) {
|
|
723
|
+
screenRect = maskScreen;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
716
726
|
const islandRect = findDynamicIsland(rects, screenRect);
|
|
717
727
|
const sideButtons = findSideButtons(rects, phoneBody);
|
|
718
728
|
const zones = [];
|
|
@@ -782,10 +792,10 @@ function findScreenArea(rects, phoneBody, svgW, svgH) {
|
|
|
782
792
|
const area = r.width * r.height;
|
|
783
793
|
if (area < bodyArea * 0.5) return false;
|
|
784
794
|
if (area >= bodyArea * 0.98) return false;
|
|
785
|
-
if (r.rx < 10) return false;
|
|
795
|
+
if (!phoneBody && r.rx < 10) return false;
|
|
786
796
|
if (!r.fill || r.fill === "none") return false;
|
|
787
797
|
if (r.fill.startsWith("url(")) return false;
|
|
788
|
-
if (
|
|
798
|
+
if (isPureBlackFill(r.fill)) return false;
|
|
789
799
|
return true;
|
|
790
800
|
}).sort((a, b) => b.width * b.height - a.width * a.height);
|
|
791
801
|
return fallbackCandidates[0] ?? null;
|
|
@@ -894,6 +904,55 @@ function classifySideButtons(sideButtons, phoneBody) {
|
|
|
894
904
|
}
|
|
895
905
|
return classified;
|
|
896
906
|
}
|
|
907
|
+
function findMaskBasedScreen(svgString, detectedScreen, _svgW, _svgH) {
|
|
908
|
+
const maskRegex = /<mask\b[^>]*>([\s\S]*?)<\/mask>/gi;
|
|
909
|
+
let maskMatch;
|
|
910
|
+
const candidates = [];
|
|
911
|
+
while ((maskMatch = maskRegex.exec(svgString)) !== null) {
|
|
912
|
+
const maskBody = maskMatch[1];
|
|
913
|
+
const pathRegex = /<path\b([^>]*?)\/>/gi;
|
|
914
|
+
let pathMatch;
|
|
915
|
+
while ((pathMatch = pathRegex.exec(maskBody)) !== null) {
|
|
916
|
+
const attrs = pathMatch[1];
|
|
917
|
+
const d = getAttrValue(attrs, "d");
|
|
918
|
+
if (!d) continue;
|
|
919
|
+
const bb = subpathBBox(d);
|
|
920
|
+
if (!bb || bb.w < 10 || bb.h < 10) continue;
|
|
921
|
+
if (bb.h < bb.w * 1.3) continue;
|
|
922
|
+
const overlapX = Math.max(0, Math.min(bb.x + bb.w, detectedScreen.x + detectedScreen.width) - Math.max(bb.x, detectedScreen.x));
|
|
923
|
+
const overlapY = Math.max(0, Math.min(bb.y + bb.h, detectedScreen.y + detectedScreen.height) - Math.max(bb.y, detectedScreen.y));
|
|
924
|
+
const overlapArea = overlapX * overlapY;
|
|
925
|
+
const detectedArea = detectedScreen.width * detectedScreen.height;
|
|
926
|
+
if (overlapArea < detectedArea * 0.8) continue;
|
|
927
|
+
const mMatch = d.match(/M\s*(-?[\d.]+)[\s,]+(-?[\d.]+)/i);
|
|
928
|
+
let rx = 0;
|
|
929
|
+
if (mMatch) {
|
|
930
|
+
const mx = parseFloat(mMatch[1]);
|
|
931
|
+
const my = parseFloat(mMatch[2]);
|
|
932
|
+
const rxFromY = Math.abs(my - bb.y);
|
|
933
|
+
const rxFromX = Math.abs(mx - bb.x);
|
|
934
|
+
rx = Math.max(rxFromY, rxFromX);
|
|
935
|
+
if (rx < 5) rx = 0;
|
|
936
|
+
}
|
|
937
|
+
candidates.push({
|
|
938
|
+
x: bb.x,
|
|
939
|
+
y: bb.y,
|
|
940
|
+
width: bb.w,
|
|
941
|
+
height: bb.h,
|
|
942
|
+
rx,
|
|
943
|
+
fill: "mask-path",
|
|
944
|
+
id: null
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
if (candidates.length === 0) return null;
|
|
949
|
+
candidates.sort((a, b) => {
|
|
950
|
+
const aDiff = Math.abs(a.width * a.height - detectedScreen.width * detectedScreen.height);
|
|
951
|
+
const bDiff = Math.abs(b.width * b.height - detectedScreen.width * detectedScreen.height);
|
|
952
|
+
return aDiff - bDiff;
|
|
953
|
+
});
|
|
954
|
+
return candidates[0];
|
|
955
|
+
}
|
|
897
956
|
function findPathCutoutScreen(svgString, svgW, svgH) {
|
|
898
957
|
const svgArea = svgW * svgH;
|
|
899
958
|
const pathRegex = /<path\b([^>]*?)\/>/gi;
|
|
@@ -1057,6 +1116,20 @@ function isLightFill(fill) {
|
|
|
1057
1116
|
}
|
|
1058
1117
|
return false;
|
|
1059
1118
|
}
|
|
1119
|
+
function isPureBlackFill(fill) {
|
|
1120
|
+
if (!fill) return false;
|
|
1121
|
+
const f = fill.toLowerCase().trim();
|
|
1122
|
+
if (f === "black" || f === "#000" || f === "#000000") return true;
|
|
1123
|
+
if (f === "rgb(0,0,0)" || f === "rgb(0, 0, 0)") return true;
|
|
1124
|
+
const hex6 = f.match(/^#([0-9a-f]{6})$/);
|
|
1125
|
+
if (hex6) {
|
|
1126
|
+
const r = parseInt(hex6[1].slice(0, 2), 16);
|
|
1127
|
+
const g = parseInt(hex6[1].slice(2, 4), 16);
|
|
1128
|
+
const b = parseInt(hex6[1].slice(4, 6), 16);
|
|
1129
|
+
return r < 10 && g < 10 && b < 10;
|
|
1130
|
+
}
|
|
1131
|
+
return false;
|
|
1132
|
+
}
|
|
1060
1133
|
function isDarkFill(fill) {
|
|
1061
1134
|
if (!fill) return false;
|
|
1062
1135
|
const f = fill.toLowerCase().trim();
|
|
@@ -1141,6 +1214,14 @@ function countOccurrences(str, substr) {
|
|
|
1141
1214
|
function applyTransformToRect(attrs, x, y, width, height) {
|
|
1142
1215
|
const transformAttr = getAttrValue(attrs, "transform");
|
|
1143
1216
|
if (!transformAttr) return { x, y, width, height };
|
|
1217
|
+
const translateMatch = transformAttr.match(
|
|
1218
|
+
/translate\(\s*(-?[\d.]+)[\s,]+(-?[\d.]+)\s*\)/
|
|
1219
|
+
);
|
|
1220
|
+
if (translateMatch) {
|
|
1221
|
+
const tx = parseFloat(translateMatch[1]);
|
|
1222
|
+
const ty = parseFloat(translateMatch[2]);
|
|
1223
|
+
return { x: x + tx, y: y + ty, width, height };
|
|
1224
|
+
}
|
|
1144
1225
|
const matrixMatch = transformAttr.match(
|
|
1145
1226
|
/matrix\(\s*(-?[\d.]+)\s+(-?[\d.]+)\s+(-?[\d.]+)\s+(-?[\d.]+)\s+(-?[\d.]+)\s+(-?[\d.]+)\s*\)/
|
|
1146
1227
|
);
|