@dimina-kit/devtools 0.4.0-dev.20260828161241 → 0.4.0-dev.20260907055341
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/README.md +52 -729
- package/dist/main/app/app.d.ts +27 -7
- package/dist/main/app/app.js +285 -681
- package/dist/main/app/editor-view.d.ts +21 -0
- package/dist/main/app/editor-view.js +71 -0
- package/dist/main/app/global-mirrors.d.ts +23 -0
- package/dist/main/app/global-mirrors.js +37 -0
- package/dist/main/app/host-sidebar-default.d.ts +19 -0
- package/dist/main/app/host-sidebar-default.js +44 -0
- package/dist/main/app/menu-setup.d.ts +13 -0
- package/dist/main/app/menu-setup.js +49 -0
- package/dist/main/app/open-project-ipc.d.ts +13 -0
- package/dist/main/app/open-project-ipc.js +21 -0
- package/dist/main/app/project-list-surface.d.ts +31 -0
- package/dist/main/app/project-list-surface.js +20 -0
- package/dist/main/app/project-window.d.ts +36 -0
- package/dist/main/app/project-window.js +93 -0
- package/dist/main/app/servers.d.ts +17 -0
- package/dist/main/app/servers.js +60 -0
- package/dist/main/app/ui-extension-targets.d.ts +42 -0
- package/dist/main/app/ui-extension-targets.js +101 -0
- package/dist/main/app/window-close-reveal.harness.d.ts +34 -0
- package/dist/main/app/window-close-reveal.harness.js +65 -0
- package/dist/main/app/window-events.d.ts +15 -0
- package/dist/main/app/window-events.js +45 -0
- package/dist/main/app/window-runtime-services.d.ts +41 -0
- package/dist/main/app/window-runtime-services.js +178 -0
- package/dist/main/app/workbench-modules.d.ts +24 -0
- package/dist/main/app/workbench-modules.js +51 -0
- package/dist/main/app/workbench-window.d.ts +85 -0
- package/dist/main/app/workbench-window.js +310 -0
- package/dist/main/index.bundle.js +10669 -9096
- package/dist/main/ipc/app.d.ts +4 -1
- package/dist/main/ipc/app.js +4 -3
- package/dist/main/ipc/device-picker.d.ts +16 -0
- package/dist/main/ipc/device-picker.js +27 -0
- package/dist/main/ipc/index.d.ts +1 -0
- package/dist/main/ipc/index.js +1 -0
- package/dist/main/ipc/internal-devtools.d.ts +2 -1
- package/dist/main/ipc/internal-devtools.js +4 -3
- package/dist/main/ipc/popover.d.ts +4 -1
- package/dist/main/ipc/popover.js +25 -9
- package/dist/main/ipc/project-create.d.ts +2 -1
- package/dist/main/ipc/project-create.js +6 -5
- package/dist/main/ipc/project-fs.d.ts +3 -1
- package/dist/main/ipc/project-fs.js +17 -17
- package/dist/main/ipc/projects.d.ts +3 -3
- package/dist/main/ipc/projects.js +13 -12
- package/dist/main/ipc/session.d.ts +4 -1
- package/dist/main/ipc/session.js +16 -11
- package/dist/main/ipc/settings.d.ts +4 -1
- package/dist/main/ipc/settings.js +12 -19
- package/dist/main/ipc/simulator-module.d.ts +5 -0
- package/dist/main/ipc/simulator-module.js +9 -5
- package/dist/main/ipc/simulator.d.ts +4 -1
- package/dist/main/ipc/simulator.js +12 -18
- package/dist/main/ipc/tooltip.d.ts +2 -1
- package/dist/main/ipc/tooltip.js +8 -7
- package/dist/main/ipc/views.d.ts +4 -1
- package/dist/main/ipc/views.js +20 -9
- package/dist/main/runtime/devtools-backend-before-quit.harness.d.ts +2 -20
- package/dist/main/runtime/devtools-backend-before-quit.harness.js +14 -283
- package/dist/main/runtime/devtools-backend.js +14 -3
- package/dist/main/runtime/devtools-runtime-mock.harness.d.ts +21 -0
- package/dist/main/runtime/devtools-runtime-mock.harness.js +313 -0
- package/dist/main/services/app-services.d.ts +62 -0
- package/dist/main/services/app-services.js +64 -0
- package/dist/main/services/automation/connection-target.d.ts +36 -0
- package/dist/main/services/automation/connection-target.js +29 -0
- package/dist/main/services/automation/console-bridge.d.ts +28 -0
- package/dist/main/services/automation/console-bridge.js +91 -0
- package/dist/main/services/automation/handlers/app.js +4 -4
- package/dist/main/services/automation/handlers/element.js +55 -21
- package/dist/main/services/automation/index.d.ts +12 -1
- package/dist/main/services/automation/index.js +54 -133
- package/dist/main/services/default-adapter.js +1 -1
- package/dist/main/services/fs-bridge-protocol.d.ts +61 -0
- package/dist/main/services/fs-bridge-protocol.js +34 -0
- package/dist/main/services/fs-watch-sse.d.ts +8 -1
- package/dist/main/services/fs-watch-sse.js +19 -5
- package/dist/main/services/mcp/connection-owner.d.ts +38 -0
- package/dist/main/services/mcp/connection-owner.js +79 -0
- package/dist/main/services/mcp/index.d.ts +3 -1
- package/dist/main/services/mcp/index.js +4 -3
- package/dist/main/services/mcp/opened-project.d.ts +88 -0
- package/dist/main/services/mcp/opened-project.js +60 -0
- package/dist/main/services/mcp/target-manager.d.ts +71 -23
- package/dist/main/services/mcp/target-manager.js +269 -142
- package/dist/main/services/mcp/target-selection.d.ts +47 -0
- package/dist/main/services/mcp/target-selection.js +71 -0
- package/dist/main/services/mcp/tools/context-tools.js +20 -5
- package/dist/main/services/mcp/tools/project-tools.d.ts +29 -6
- package/dist/main/services/mcp/tools/project-tools.js +37 -25
- package/dist/main/services/module.d.ts +13 -5
- package/dist/main/services/notifications/renderer-notifier.d.ts +28 -4
- package/dist/main/services/notifications/renderer-notifier.js +15 -3
- package/dist/main/services/projects/local-provider.js +2 -0
- package/dist/main/services/projects/project-repository.d.ts +31 -1
- package/dist/main/services/projects/project-repository.js +144 -20
- package/dist/main/services/projects/types.d.ts +31 -8
- package/dist/main/services/safe-area/index.d.ts +19 -5
- package/dist/main/services/safe-area/index.js +38 -13
- package/dist/main/services/simulator/ui-extensions.d.ts +8 -0
- package/dist/main/services/simulator/ui-extensions.js +16 -6
- package/dist/main/services/simulator-storage/index.d.ts +12 -1
- package/dist/main/services/simulator-storage/index.js +22 -7
- package/dist/main/services/simulator-storage/window-scope.d.ts +20 -0
- package/dist/main/services/simulator-storage/window-scope.js +20 -0
- package/dist/main/services/views/host-slot-port-channel.d.ts +20 -3
- package/dist/main/services/views/host-slot-port-channel.js +33 -5
- package/dist/main/services/views/managed-web-contents-view.js +21 -1
- package/dist/main/services/views/native-simulator-view.js +13 -16
- package/dist/main/services/views/overlay-panels-view.d.ts +13 -0
- package/dist/main/services/views/overlay-panels-view.js +31 -0
- package/dist/main/services/views/view-manager.d.ts +1 -1
- package/dist/main/services/views/view-manager.js +3 -0
- package/dist/main/services/window-contexts/context-router.d.ts +36 -0
- package/dist/main/services/window-contexts/context-router.js +55 -0
- package/dist/main/services/workbench-coi-host.d.ts +52 -0
- package/dist/main/services/workbench-coi-host.js +227 -0
- package/dist/main/services/workbench-coi-server.js +75 -133
- package/dist/main/services/workbench-coi-shutdown.d.ts +40 -0
- package/dist/main/services/workbench-coi-shutdown.js +69 -0
- package/dist/main/services/workbench-coi-static.d.ts +23 -0
- package/dist/main/services/workbench-coi-static.js +87 -0
- package/dist/main/services/workbench-context.d.ts +27 -3
- package/dist/main/services/workbench-context.js +10 -5
- package/dist/main/services/workspace/compile-mode-adapter.d.ts +18 -0
- package/dist/main/services/workspace/compile-mode-adapter.js +57 -0
- package/dist/main/services/workspace/compile-mode-store.d.ts +25 -0
- package/dist/main/services/workspace/compile-mode-store.js +71 -0
- package/dist/main/services/workspace/workspace-compile-modes.d.ts +59 -0
- package/dist/main/services/workspace/workspace-compile-modes.js +93 -0
- package/dist/main/services/workspace/workspace-referer.d.ts +17 -0
- package/dist/main/services/workspace/workspace-referer.js +26 -0
- package/dist/main/services/workspace/workspace-service.d.ts +4 -0
- package/dist/main/services/workspace/workspace-service.js +51 -84
- package/dist/main/services/workspace/workspace-thumbnails.d.ts +22 -0
- package/dist/main/services/workspace/workspace-thumbnails.js +67 -0
- package/dist/main/utils/ipc-context-source.d.ts +40 -0
- package/dist/main/utils/ipc-context-source.js +23 -0
- package/dist/main/utils/ipc-registry.d.ts +42 -36
- package/dist/main/utils/ipc-registry.js +117 -50
- package/dist/main/utils/sender-policy.d.ts +9 -0
- package/dist/main/utils/sender-policy.js +26 -3
- package/dist/main/utils/theme.d.ts +3 -2
- package/dist/main/utils/theme.js +3 -2
- package/dist/main/windows/main-window/create.d.ts +16 -0
- package/dist/main/windows/main-window/create.js +19 -11
- package/dist/main/windows/main-window/events.d.ts +1 -1
- package/dist/main/windows/main-window/events.js +26 -13
- package/dist/main/windows/main-window/index.d.ts +1 -1
- package/dist/main/windows/main-window/index.js +1 -1
- package/dist/native-host/common/common.js +94 -73
- package/dist/native-host/render/render.js +4079 -3171
- package/dist/native-host/service/service.js +2 -2
- package/dist/preload/runtime/native-host.d.ts +4 -0
- package/dist/preload/runtime/temp-files.js +9 -2
- package/dist/preload/runtime/wait-for-slot-root.d.ts +7 -4
- package/dist/preload/runtime/wait-for-slot-root.js +36 -8
- package/dist/preload/windows/host-dialog-runtime.cjs +10 -3
- package/dist/preload/windows/host-dialog-runtime.cjs.map +2 -2
- package/dist/preload/windows/host-sidebar-runtime.cjs +10 -3
- package/dist/preload/windows/host-sidebar-runtime.cjs.map +2 -2
- package/dist/preload/windows/host-toolbar-runtime.cjs +10 -3
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
- package/dist/preload/windows/main.cjs +181 -4
- package/dist/preload/windows/main.cjs.map +4 -4
- package/dist/preload/windows/simulator.cjs +10 -0
- package/dist/preload/windows/simulator.cjs.map +2 -2
- package/dist/preload/windows/simulator.js +10 -0
- package/dist/render-host/pageFrame.html +1 -1
- package/dist/render-host/preload.cjs +16 -4
- package/dist/renderer/assets/button-CB2MWjHY.js +2 -0
- package/dist/renderer/assets/constants-CkoGPQTS.js +2 -0
- package/dist/renderer/assets/constants-zQZ2-y21.js +2 -0
- package/dist/renderer/assets/{createLucideIcon-Bqi8hpdi.js → createLucideIcon-cZ9FlZZw.js} +2 -2
- package/dist/renderer/assets/devicePicker-H2eIO4e1.js +2 -0
- package/dist/renderer/assets/dialog-pHzEA8Vx.js +46 -0
- package/dist/renderer/assets/dist-B5HADirS.js +2 -0
- package/dist/renderer/assets/{dist-DKWdE1TK.js → dist-DIFlRMKe.js} +2 -2
- package/dist/renderer/assets/hostSidebarDefault-DRWh6OCt.js +2 -0
- package/dist/renderer/assets/index-CEL_XFge.js +2 -0
- package/dist/renderer/assets/{input-Ct3alvkq.js → input-CAObw95L.js} +2 -2
- package/dist/renderer/assets/ipc-channels-overlays-gIPUFnqc.js +2 -0
- package/dist/renderer/assets/jsx-runtime-DICEQH_0.css +1 -0
- package/dist/renderer/assets/{jsx-runtime-DGLHmmOq.js → jsx-runtime-DIw5wnYl.js} +1 -1
- package/dist/renderer/assets/plus-BQ9u5EbL.js +2 -0
- package/dist/renderer/assets/popover-Cw7G2Ctp.js +2 -0
- package/dist/renderer/assets/presets-DMZOb9ay.js +2 -0
- package/dist/renderer/assets/project-api-YTOr_Yvo.js +2 -0
- package/dist/renderer/assets/{projectCreateDialog-Bbjz75bP.js → projectCreateDialog-BmLqiYxn.js} +2 -2
- package/dist/renderer/assets/search-BMvuYF48.js +2 -0
- package/dist/renderer/assets/select-nFP95TxM.js +2 -0
- package/dist/renderer/assets/settings-CnpVfSWt.js +2 -0
- package/dist/renderer/assets/settings-api-Ccsf-Nsj.js +2 -0
- package/dist/renderer/assets/settings-tab-bar-CAzrv32m.js +2 -0
- package/dist/renderer/assets/smartphone-Bb2GdIKy.js +2 -0
- package/dist/renderer/assets/tabs-CPKN3Mmq.js +2 -0
- package/dist/renderer/assets/{tooltip-B_-_YVbw.js → tooltip-D6AxXRk5.js} +2 -2
- package/dist/renderer/assets/types-Bh0hA7El.js +2 -0
- package/dist/renderer/assets/updateDialog-CwndJ0Bl.js +2 -0
- package/dist/renderer/assets/{utils-kfQov6Pa.js → utils-sEB5OZEQ.js} +2 -2
- package/dist/renderer/assets/view-api-B-2zPBR5.js +2 -0
- package/dist/renderer/assets/view-ids-BfaDVV5P.js +2 -0
- package/dist/renderer/assets/workbench-BLJ0wKsg.js +5 -0
- package/dist/renderer/assets/{workbenchSettings-CV4LVA9b.js → workbenchSettings-YD0Ctbm_.js} +3 -3
- package/dist/renderer/entries/device-picker/index.html +28 -0
- package/dist/renderer/entries/host-sidebar-default/index.html +6 -5
- package/dist/renderer/entries/main/index.html +16 -17
- package/dist/renderer/entries/popover/index.html +16 -10
- package/dist/renderer/entries/project-create-dialog/index.html +12 -12
- package/dist/renderer/entries/settings/index.html +10 -10
- package/dist/renderer/entries/tooltip/index.html +5 -5
- package/dist/renderer/entries/update-dialog/index.html +10 -10
- package/dist/renderer/entries/workbench/index.html +49 -0
- package/dist/renderer/entries/workbench-settings/index.html +12 -11
- package/dist/service-host/host-env-update.cjs +23 -0
- package/dist/service-host/preload.cjs +24 -49
- package/dist/service-host/service-message-queue.cjs +71 -0
- package/dist/service-host/sync-impls/system-info.js +31 -9
- package/dist/shared/compile-mode-state.d.ts +73 -0
- package/dist/shared/compile-mode-state.js +100 -0
- package/dist/shared/compile-modes.d.ts +152 -0
- package/dist/shared/compile-modes.js +237 -0
- package/dist/shared/ipc-channels-overlays.d.ts +8 -2
- package/dist/shared/ipc-channels-overlays.js +19 -2
- package/dist/shared/ipc-channels.d.ts +5 -10
- package/dist/shared/ipc-channels.js +17 -14
- package/dist/shared/ipc-schemas.d.ts +76 -24
- package/dist/shared/ipc-schemas.js +55 -10
- package/dist/shared/project-window-types.d.ts +42 -0
- package/dist/shared/project-window-types.js +2 -0
- package/dist/shared/types.d.ts +43 -17
- package/dist/shared/view-ids.d.ts +1 -0
- package/dist/shared/view-ids.js +3 -1
- package/dist/simulator/assets/bridge-channels-B3JAmRfl.js +2 -0
- package/dist/simulator/assets/device-shell-ATEhHV2_.css +1 -0
- package/dist/simulator/assets/device-shell-pxnZZp10.js +431 -0
- package/dist/simulator/assets/simulator-Dwp7lnvu.js +10 -0
- package/dist/simulator/assets/simulator-mini-app-DFo7fhi5.js +2 -0
- package/dist/simulator/assets/simulator-ui-B2ddJB1R.js +2 -0
- package/dist/simulator/simulator.html +3 -3
- package/dist/simulator/temp-files.d.ts +6 -0
- package/dist/simulator/temp-files.js +46 -4
- package/dist/simulator/types.d.ts +7 -0
- package/dist/vscode-workbench/assets/__vite-browser-external-JIkWewFf.js +1 -0
- package/dist/vscode-workbench/assets/{dist-CMfmHflW.js → dist-CXG-u1VB.js} +3 -3
- package/dist/vscode-workbench/assets/{iconv-lite-umd-Bx8CgaZq.js → iconv-lite-umd-Dxx9Qyb4.js} +1 -1
- package/dist/vscode-workbench/assets/{index-CdG6YWhW.js → index-6VJMsaWj.js} +460 -460
- package/dist/vscode-workbench/assets/{jschardet-M0qgd2lN.js → jschardet-Ba3D16vt.js} +1 -1
- package/dist/vscode-workbench/index.html +1 -1
- package/package.json +11 -8
- package/dist/renderer/assets/button-D5Q2wkXq.js +0 -2
- package/dist/renderer/assets/constants-D7DfVqMp.js +0 -2
- package/dist/renderer/assets/constants-D8zsejFq.js +0 -2
- package/dist/renderer/assets/dialog-e1TecTOY.js +0 -46
- package/dist/renderer/assets/hostSidebarDefault-B3yLfy8j.js +0 -2
- package/dist/renderer/assets/index-CsPD68N_.js +0 -5
- package/dist/renderer/assets/ipc-channels-overlays-LsDzGAtV.js +0 -2
- package/dist/renderer/assets/jsx-runtime-2vXHouwr.css +0 -1
- package/dist/renderer/assets/popover-Dix5cm_b.js +0 -2
- package/dist/renderer/assets/project-api-k7Oq9iaq.js +0 -2
- package/dist/renderer/assets/select-acGb0AmJ.js +0 -2
- package/dist/renderer/assets/settings-CQrTMr43.js +0 -2
- package/dist/renderer/assets/settings-api-CrUQ9rYV.js +0 -2
- package/dist/renderer/assets/settings-tab-bar-Cw1kVIf2.js +0 -2
- package/dist/renderer/assets/types-CsEKtFyr.js +0 -2
- package/dist/renderer/assets/updateDialog-NsF8223A.js +0 -2
- package/dist/renderer/assets/view-api-CLn3rcQE.js +0 -2
- package/dist/simulator/assets/bridge-channels-zhsumfky.js +0 -2
- package/dist/simulator/assets/device-shell-CmtM1QxP.js +0 -2
- package/dist/simulator/assets/device-shell-iFZo1igL.css +0 -1
- package/dist/simulator/assets/simulator-CIobn3Mh.js +0 -10
- package/dist/simulator/assets/simulator-mini-app-CRe6n9br.js +0 -2
- package/dist/simulator/assets/simulator-ui-C_cP602X.js +0 -2
- package/dist/vscode-workbench/assets/__vite-browser-external-Bc1vizTf.js +0 -1
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
import{c as e,d as t,o as n,r,s as i,t as a}from"./simulator-ui-B2ddJB1R.js";import{t as o}from"./bridge-channels-B3JAmRfl.js";var s=`149.0.7827.55`,c=`ArkWeb/4.1.6.1 Mobile`,l=`AppleWebKit/605.1.15 (KHTML, like Gecko)`,u=`AppleWebKit/537.36 (KHTML, like Gecko)`,d={ios:`18.0`,android:`13`,harmony:`5.0`};function f(e){return/(\d[\d.]*)/.exec(e.system??``)?.[1]??d[e.os]??``}function p(e){if(e.userAgent)return e.userAgent;let t=f(e),n=e.formFactor===`tablet`;switch(e.os){case`ios`:{let e=Number.parseInt(t,10)>=26?`18_6`:t.replace(/\./g,`_`);return n?`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ${l} Version/${t} Safari/605.1.15`:`Mozilla/5.0 (iPhone; CPU iPhone OS ${e} like Mac OS X) ${l} Version/${t} Mobile/15E148 Safari/604.1`}case`harmony`:return`Mozilla/5.0 (${n?`Tablet`:`Phone`}; OpenHarmony ${t}) ${u} Chrome/114.0.0.0 Safari/537.36 ${c}`;default:return n?`Mozilla/5.0 (Linux; Android ${t}; ${e.name}) ${u} Chrome/${s} Safari/537.36`:`Mozilla/5.0 (Linux; Android ${t}; ${e.name}) ${u} Chrome/${s} Mobile Safari/537.36`}}function m(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function h(e,t,n,r){if(!(typeof t==`number`&&Number.isFinite(t)&&(r?t>n:t>=n))){let i=r?`greater than ${n}`:`>= ${n}`;throw TypeError(`${e} must be a finite number ${i}, got ${t}`)}}function g(e,t,n,r){if(!(typeof t==`number`&&Number.isFinite(t)&&t>=n&&t<=r))throw TypeError(`${e} must be a finite number between ${n} and ${r}, got ${t}`)}function _(e,t){if(typeof t!=`string`)throw TypeError(`${e} must be a string, got ${JSON.stringify(t)}`)}var v=[`top`,`right`,`bottom`,`left`],y=[`statusBarHeight`,`statusBarHeightLandscape`,`navigationBarHeight`,`navigationBarHeightLandscape`],b=[`system`,`userAgent`],x=[`safeAreaInsets`,`safeAreaInsetsLandscape`],S=[`screenRadius`,`bezel`,`bodyRadius`],C=[`notch`,`pill`,`circle`];function w(e,t=`deviceProfile`){if(!m(e))throw TypeError(`${t} must be an object, got ${e===null?`null`:typeof e}`);let n=e.os;if(n!==`ios`&&n!==`android`&&n!==`harmony`)throw TypeError(`${t}.os must be one of "ios", "android", "harmony", got ${JSON.stringify(n)}`);if(e.formFactor!==void 0){let n=e.formFactor;if(n!==`phone`&&n!==`tablet`)throw TypeError(`${t}.formFactor must be one of "phone", "tablet", got ${JSON.stringify(n)}`)}let r=e.screen;if(!m(r))throw TypeError(`${t}.screen must be an object, got ${r===null?`null`:typeof r}`);h(`${t}.screen.width`,r.width,0,!0),h(`${t}.screen.height`,r.height,0,!0),_(`${t}.name`,e.name),h(`${t}.pixelRatio`,e.pixelRatio,0,!0);for(let n of y)e[n]!==void 0&&h(`${t}.${n}`,e[n],0,!1);for(let n of x){let r=e[n];if(r!==void 0){if(!m(r))throw TypeError(`${t}.${n} must be an object, got ${r===null?`null`:typeof r}`);for(let e of v)r[e]!==void 0&&h(`${t}.${n}.${e}`,r[e],0,!1)}}for(let n of b)e[n]!==void 0&&_(`${t}.${n}`,e[n]);if(e.cutout!==void 0){let n=e.cutout;if(!m(n))throw TypeError(`${t}.cutout must be an object, got ${n===null?`null`:typeof n}`);let r=n.shape;if(!C.includes(r))throw TypeError(`${t}.cutout.shape must be one of "notch", "pill", "circle", got ${JSON.stringify(r)}`);h(`${t}.cutout.width`,n.width,0,!1),h(`${t}.cutout.height`,n.height,0,!1),h(`${t}.cutout.top`,n.top,0,!1),n.centerX!==void 0&&g(`${t}.cutout.centerX`,n.centerX,0,1)}if(e.shell!==void 0){let n=e.shell;if(!m(n))throw TypeError(`${t}.shell must be an object, got ${n===null?`null`:typeof n}`);for(let e of S)n[e]!==void 0&&h(`${t}.shell.${e}`,n[e],0,!1)}}var T={ios:{statusBarHeight:44,statusBarHeightLandscape:0,navigationBarHeight:44,navigationBarHeightLandscape:32,shell:{screenRadius:38,bezel:6}},android:{statusBarHeight:24,statusBarHeightLandscape:24,navigationBarHeight:48,navigationBarHeightLandscape:48,shell:{screenRadius:16,bezel:4}},harmony:{statusBarHeight:36,statusBarHeightLandscape:36,navigationBarHeight:28,navigationBarHeightLandscape:28,shell:{screenRadius:34,bezel:4}}},E={top:0,right:0,bottom:0,left:0};function D(e,t){return e?{top:e.top??t.top,right:e.right??t.right,bottom:e.bottom??t.bottom,left:e.left??t.left}:t}function O(e){w(e,`device`);let t=T[e.os],n=e.statusBarHeight??t.statusBarHeight,r=e.statusBarHeightLandscape??t.statusBarHeightLandscape,i=e.shell?.screenRadius??t.shell.screenRadius,a=e.shell?.bezel??t.shell.bezel;return{name:e.name,os:e.os,screen:e.screen,pixelRatio:e.pixelRatio,formFactor:e.formFactor??`phone`,system:e.system??``,userAgent:e.userAgent??p(e),statusBarHeight:n,statusBarHeightLandscape:r,navigationBarHeight:e.navigationBarHeight??t.navigationBarHeight,navigationBarHeightLandscape:e.navigationBarHeightLandscape??t.navigationBarHeightLandscape,safeAreaInsets:D(e.safeAreaInsets,{...E,top:n}),safeAreaInsetsLandscape:D(e.safeAreaInsetsLandscape,{...E,top:r}),cutout:e.cutout??null,shell:{screenRadius:i,bezel:a,bodyRadius:e.shell?.bodyRadius??i+a}}}function k(e,t){return t===`landscape`?e.statusBarHeightLandscape:e.statusBarHeight}function A(e,t){return t===`landscape`?e.navigationBarHeightLandscape:e.navigationBarHeight}function j(e,t){return t===`landscape`?e.safeAreaInsetsLandscape:e.safeAreaInsets}var M=[{name:`Pixel 7`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 13`,statusBarHeight:52,safeAreaInsets:{top:52},safeAreaInsetsLandscape:{right:52},cutout:{shape:`circle`,width:26,height:26,top:13},userAgent:`Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 8`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 14`,statusBarHeight:50,safeAreaInsets:{top:50},safeAreaInsetsLandscape:{right:50},cutout:{shape:`circle`,width:28,height:28,top:11},userAgent:`Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 8 Pro`,os:`android`,screen:{width:448,height:997},pixelRatio:3,system:`Android 14`,statusBarHeight:50,safeAreaInsets:{top:50},safeAreaInsetsLandscape:{right:50},cutout:{shape:`circle`,width:28,height:28,top:11},userAgent:`Mozilla/5.0 (Linux; Android 14; Pixel 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 8a`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 14`,statusBarHeight:46,safeAreaInsets:{top:46},safeAreaInsetsLandscape:{right:46},cutout:{shape:`circle`,width:26,height:26,top:13},userAgent:`Mozilla/5.0 (Linux; Android 14; Pixel 8a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 9`,os:`android`,screen:{width:412,height:924},pixelRatio:2.625,system:`Android 14`,statusBarHeight:58,safeAreaInsets:{top:58},safeAreaInsetsLandscape:{right:58},cutout:{shape:`circle`,width:28,height:28,top:15},userAgent:`Mozilla/5.0 (Linux; Android 14; Pixel 9) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 9 Pro`,os:`android`,screen:{width:427,height:952},pixelRatio:3,system:`Android 14`,statusBarHeight:68,safeAreaInsets:{top:68},safeAreaInsetsLandscape:{right:68},cutout:{shape:`circle`,width:32,height:32,top:18},userAgent:`Mozilla/5.0 (Linux; Android 14; Pixel 9 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 9 Pro XL`,os:`android`,screen:{width:448,height:997},pixelRatio:3,system:`Android 14`,statusBarHeight:66,safeAreaInsets:{top:66},safeAreaInsetsLandscape:{right:66},cutout:{shape:`circle`,width:32,height:32,top:17},userAgent:`Mozilla/5.0 (Linux; Android 14; Pixel 9 Pro XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 10`,os:`android`,screen:{width:412,height:924},pixelRatio:2.625,system:`Android 16`,statusBarHeight:58,safeAreaInsets:{top:58},safeAreaInsetsLandscape:{right:58},cutout:{shape:`circle`,width:28,height:28,top:15},userAgent:`Mozilla/5.0 (Linux; Android 16; Pixel 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Samsung Galaxy S8+`,os:`android`,screen:{width:360,height:740},pixelRatio:4,system:`Android 7.0`,userAgent:`Mozilla/5.0 (Linux; Android 7.0; SM-G955U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Samsung Galaxy S20 Ultra`,os:`android`,screen:{width:412,height:915},pixelRatio:3.5,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 10; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Mobile Safari/537.36`},{name:`Surface Duo`,os:`android`,screen:{width:540,height:720},pixelRatio:2.5,system:`Android 11.0`},{name:`Surface Duo (inner)`,os:`android`,screen:{width:720,height:1114},pixelRatio:2.5,system:`Android 11.0`},{name:`Samsung Galaxy A55`,os:`android`,screen:{width:360,height:800},pixelRatio:2.25,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; SM-A556B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 9 Pro Fold`,os:`android`,screen:{width:412,height:922},pixelRatio:2.625,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 15; Pixel 9 Pro Fold) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Mobile Safari/537.36`},{name:`Pixel 9 Pro Fold (inner)`,os:`android`,screen:{width:836,height:842},pixelRatio:2.625,system:`Android 14`},{name:`Galaxy Z Fold 6`,os:`android`,screen:{width:412,height:968},pixelRatio:2.625,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; SM-F956U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Galaxy Z Fold 6 (inner)`,os:`android`,screen:{width:707,height:823},pixelRatio:2.625,system:`Android 14`},{name:`Galaxy Z Fold 5`,os:`android`,screen:{width:344,height:882},pixelRatio:2.625,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; SM-F946B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.131 Mobile Safari/537.36`},{name:`Galaxy Z Fold 5 (inner)`,os:`android`,screen:{width:690,height:829},pixelRatio:2.625,system:`Android 13`},{name:`Samsung Galaxy A51/71`,os:`android`,screen:{width:412,height:914},pixelRatio:2.625,system:`Android 10`,userAgent:`Mozilla/5.0 (Linux; Android 10; SM-A515F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36`},{name:`Galaxy Tab S4`,os:`android`,formFactor:`tablet`,screen:{width:712,height:1138},pixelRatio:2.25,system:`Android 8.1`,userAgent:`Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Safari/537.36`},{name:`Moto G4`,os:`android`,screen:{width:360,height:640},pixelRatio:3,system:`Android 6.0`,userAgent:`Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Moto G Power`,os:`android`,screen:{width:412,height:823},pixelRatio:1.75,system:`Android 11`},{name:`Nexus 5`,os:`android`,screen:{width:360,height:640},pixelRatio:3,system:`Android 6.0`,shell:{screenRadius:2},userAgent:`Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Mobile Safari/537.36`},{name:`Nexus 5X`,os:`android`,screen:{width:411,height:731},pixelRatio:2.625,system:`Android 8.0`,shell:{screenRadius:2},userAgent:`Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Mobile Safari/537.36`},{name:`Nexus 6`,os:`android`,screen:{width:412,height:732},pixelRatio:3.5,system:`Android 7.1`,shell:{screenRadius:2},userAgent:`Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Mobile Safari/537.36`},{name:`Galaxy Note 3`,os:`android`,screen:{width:360,height:640},pixelRatio:3,system:`Android 4.3`,userAgent:`Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`},{name:`Galaxy Note II`,os:`android`,screen:{width:360,height:640},pixelRatio:2,system:`Android 4.1`,userAgent:`Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`},{name:`Galaxy S III`,os:`android`,screen:{width:360,height:640},pixelRatio:2,system:`Android 4.0`,userAgent:`Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`},{name:`Galaxy S5`,os:`android`,screen:{width:360,height:640},pixelRatio:3,system:`Android 5.0`,userAgent:`Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Galaxy S9+`,os:`android`,screen:{width:320,height:658},pixelRatio:4.5,system:`Android 8.0`,userAgent:`Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Galaxy S24`,os:`android`,screen:{width:360,height:780},pixelRatio:3,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; SM-S921U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Galaxy Tab S9`,os:`android`,formFactor:`tablet`,screen:{width:640,height:1024},pixelRatio:2.5,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; SM-X710) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Safari/537.36`},{name:`Galaxy Z Fold 6 Cover`,os:`android`,screen:{width:484,height:1188},pixelRatio:2,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; SM-F956U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Galaxy Z Fold 7`,os:`android`,screen:{width:984,height:1092},pixelRatio:2,system:`Android 16`,userAgent:`Mozilla/5.0 (Linux; Android 16; SM-F966U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Galaxy Z Fold 7 Cover`,os:`android`,screen:{width:360,height:840},pixelRatio:3,system:`Android 16`,userAgent:`Mozilla/5.0 (Linux; Android 16; SM-F966U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Galaxy Z Flip 6`,os:`android`,screen:{width:360,height:880},pixelRatio:3,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; SM-F741U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Galaxy Z Flip 6 Cover`,os:`android`,screen:{width:360,height:374},pixelRatio:2,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; SM-F741U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Galaxy Z Flip 7`,os:`android`,screen:{width:360,height:840},pixelRatio:3,system:`Android 16`,userAgent:`Mozilla/5.0 (Linux; Android 16; SM-F761U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Galaxy Z Flip 7 Cover`,os:`android`,screen:{width:474,height:524},pixelRatio:2,system:`Android 16`,userAgent:`Mozilla/5.0 (Linux; Android 16; SM-F761U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`LG Optimus L70`,os:`android`,screen:{width:384,height:640},pixelRatio:1.25,system:`Android 4.4`,userAgent:`Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Nexus 10`,os:`android`,formFactor:`tablet`,screen:{width:800,height:1280},pixelRatio:2,system:`Android 5.1`,userAgent:`Mozilla/5.0 (Linux; Android 5.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Safari/537.36`},{name:`Nexus 4`,os:`android`,screen:{width:384,height:640},pixelRatio:2,system:`Android 4.4`,userAgent:`Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Nexus 6P`,os:`android`,screen:{width:412,height:732},pixelRatio:3.5,system:`Android 8.0`,userAgent:`Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Nexus 7`,os:`android`,formFactor:`tablet`,screen:{width:600,height:960},pixelRatio:2,system:`Android 6.0`,userAgent:`Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Safari/537.36`},{name:`Pixel 2`,os:`android`,screen:{width:411,height:731},pixelRatio:2.625,system:`Android 8.0`,userAgent:`Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 2 XL`,os:`android`,screen:{width:411,height:823},pixelRatio:3.5,system:`Android 8.0`,userAgent:`Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 3`,os:`android`,screen:{width:393,height:786},pixelRatio:2.75,system:`Android 9`,userAgent:`Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 4`,os:`android`,screen:{width:353,height:745},pixelRatio:3,system:`Android 10`,userAgent:`Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 4a (5G)`,os:`android`,screen:{width:412,height:892},pixelRatio:2.63,system:`Android 11`,userAgent:`Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 5`,os:`android`,screen:{width:393,height:851},pixelRatio:2.75,system:`Android 11`,userAgent:`Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 6`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 12`,userAgent:`Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 6 Pro`,os:`android`,screen:{width:412,height:892},pixelRatio:3.5,system:`Android 12`,userAgent:`Mozilla/5.0 (Linux; Android 12; Pixel 6 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 6a`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 12`,userAgent:`Mozilla/5.0 (Linux; Android 12; Pixel 6a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 7 Pro`,os:`android`,screen:{width:412,height:892},pixelRatio:3.5,system:`Android 13`,statusBarHeight:41,cutout:{shape:`circle`,width:25,height:25,top:8},userAgent:`Mozilla/5.0 (Linux; Android 13; Pixel 7 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 7a`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; Pixel 7a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 10 Pro`,os:`android`,screen:{width:427,height:952},pixelRatio:3,system:`Android 16`,statusBarHeight:68,safeAreaInsets:{top:68},safeAreaInsetsLandscape:{right:68},cutout:{shape:`circle`,width:32,height:32,top:18},userAgent:`Mozilla/5.0 (Linux; Android 16; Pixel 10 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 10 Pro XL`,os:`android`,screen:{width:448,height:997},pixelRatio:3,system:`Android 16`,userAgent:`Mozilla/5.0 (Linux; Android 16; Pixel 10 Pro XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.7827.55 Mobile Safari/537.36`},{name:`Pixel 3 XL`,os:`android`,screen:{width:393,height:786},pixelRatio:2.75,system:`Android 11`,userAgent:`Mozilla/5.0 (Linux; Android 11; Pixel 3 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36`},{name:`Pixel Fold`,os:`android`,screen:{width:734,height:1014},pixelRatio:2.8,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; Pixel Fold) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Mobile Safari/537.36`},{name:`Pixel Tablet`,os:`android`,formFactor:`tablet`,screen:{width:800,height:1280},pixelRatio:2,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; Pixel Tablet) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36`},{name:`Pixel 9a`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 15`,userAgent:`Mozilla/5.0 (Linux; Android 15; Pixel 9a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Mobile Safari/537.36`},{name:`Galaxy Fold`,os:`android`,screen:{width:280,height:653},pixelRatio:3,system:`Android 9.0`},{name:`Galaxy S21`,os:`android`,screen:{width:360,height:800},pixelRatio:3,system:`Android 11`},{name:`Galaxy S21 Plus`,os:`android`,screen:{width:384,height:854},pixelRatio:2.8125,system:`Android 11`},{name:`Galaxy S21 Ultra`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 11`},{name:`Galaxy S20`,os:`android`,screen:{width:360,height:800},pixelRatio:3,system:`Android 10`},{name:`Galaxy S20 Plus`,os:`android`,screen:{width:384,height:854},pixelRatio:3,system:`Android 10`},{name:`Samsung S21 FE`,os:`android`,screen:{width:360,height:800},pixelRatio:3,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; SAMSUNG SM-G990B) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/20.0 Chrome/106.0.5249.126 Mobile Safari/537.36`},{name:`Galaxy Fold3 (Folded)`,os:`android`,screen:{width:320,height:872},pixelRatio:3,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; SM-F926U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.131 Mobile Safari/537.36`},{name:`Galaxy Fold3 (Unfolded)`,os:`android`,screen:{width:590,height:736},pixelRatio:3,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; SM-F926U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.131 Mobile Safari/537.36`},{name:`Galaxy S22`,os:`android`,screen:{width:360,height:800},pixelRatio:3,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; SM-S901B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36`},{name:`Galaxy S22 Plus`,os:`android`,screen:{width:384,height:854},pixelRatio:3,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; SM-S906B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36`},{name:`Galaxy S22 Ultra`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; SM-S908B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36`},{name:`Galaxy S23`,os:`android`,screen:{width:360,height:800},pixelRatio:3,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36`},{name:`Galaxy S23 Plus`,os:`android`,screen:{width:384,height:854},pixelRatio:3,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; SM-S916B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36`},{name:`Galaxy S23 Ultra`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; SM-S918B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36`},{name:`Galaxy S24 Plus`,os:`android`,screen:{width:384,height:854},pixelRatio:3,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; SM-S926B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36`},{name:`Galaxy S24 Ultra`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; SM-S928B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36`},{name:`Galaxy Z Flip 5`,os:`android`,screen:{width:264,height:844},pixelRatio:2.8,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; SM-F731B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.131 Mobile Safari/537.36`},{name:`Galaxy Z Fold 4`,os:`android`,screen:{width:344,height:882},pixelRatio:2.8,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; SM-F936B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.131 Mobile Safari/537.36`},{name:`OnePlus 12`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; CPH2581) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36`},{name:`Nothing Phone 2`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; A065) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36`},{name:`Xiaomi 14`,os:`android`,screen:{width:412,height:915},pixelRatio:2.625,system:`Android 14`,userAgent:`Mozilla/5.0 (Linux; Android 14; 23127PN0CC) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36`},{name:`Motorola Razr+`,os:`android`,screen:{width:264,height:844},pixelRatio:2.8,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; XT2321-1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.131 Mobile Safari/537.36`},{name:`OnePlus Open`,os:`android`,screen:{width:734,height:1014},pixelRatio:2.8,system:`Android 13`,userAgent:`Mozilla/5.0 (Linux; Android 13; CPH2551) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.131 Mobile Safari/537.36`}],N=[{name:`HUAWEI Mate 80`,os:`harmony`,screen:{width:366,height:809},pixelRatio:3.5,system:`HarmonyOS 5.0`,statusBarHeight:39,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:39}},{name:`HUAWEI Mate 70`,os:`harmony`,screen:{width:374,height:827},pixelRatio:3.25,system:`HarmonyOS 5.0`,statusBarHeight:34,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:34}},{name:`HUAWEI Mate 70 Pro`,os:`harmony`,screen:{width:376,height:809},pixelRatio:3.5,system:`HarmonyOS 5.0`,statusBarHeight:39,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:39}},{name:`HUAWEI Mate 60`,os:`harmony`,screen:{width:374,height:827},pixelRatio:3.25,system:`HarmonyOS 5.0`,statusBarHeight:33,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:33}},{name:`HUAWEI Mate 60 Pro`,os:`harmony`,screen:{width:388,height:837},pixelRatio:3.25,system:`HarmonyOS 5.0`,statusBarHeight:38,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:38}},{name:`HUAWEI Pura 80 Pro`,os:`harmony`,screen:{width:365,height:814},pixelRatio:3.5,system:`HarmonyOS 5.0`,statusBarHeight:38,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:38}},{name:`HUAWEI nova 14 Ultra`,os:`harmony`,screen:{width:363,height:817},pixelRatio:3.5,system:`HarmonyOS 5.0`,statusBarHeight:48,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:48}},{name:`HUAWEI Pura X (inner)`,os:`harmony`,screen:{width:440,height:707},pixelRatio:3,system:`HarmonyOS 5.0`,statusBarHeight:39,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:39}},{name:`HUAWEI Pura X (outer)`,os:`harmony`,screen:{width:327,height:327},pixelRatio:3,system:`HarmonyOS 5.0`,statusBarHeight:0,navigationBarHeight:0,navigationBarHeightLandscape:0},{name:`HUAWEI Mate X6 (inner)`,os:`harmony`,screen:{width:717,height:781},pixelRatio:3.125,system:`HarmonyOS 5.0`,statusBarHeight:39,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:39}},{name:`HUAWEI Mate X6 (outer)`,os:`harmony`,screen:{width:346,height:781},pixelRatio:3.125,system:`HarmonyOS 5.0`,statusBarHeight:39,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:39}},{name:`HUAWEI Pura 70`,os:`harmony`,screen:{width:372,height:818},pixelRatio:3.375,system:`HarmonyOS 5.0`,statusBarHeight:36,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:36}},{name:`HUAWEI Pura 70 Pro`,os:`harmony`,screen:{width:373,height:843},pixelRatio:3.375,system:`HarmonyOS 5.0`,statusBarHeight:38,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:38}},{name:`HUAWEI Mate X5 (inner)`,os:`harmony`,screen:{width:712,height:799},pixelRatio:3.125,system:`HarmonyOS 5.0`,statusBarHeight:36,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:36}},{name:`HUAWEI Mate X5 (outer)`,os:`harmony`,screen:{width:346,height:801},pixelRatio:3.125,system:`HarmonyOS 5.0`,statusBarHeight:36,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:36}},{name:`HUAWEI Pocket 2`,os:`harmony`,screen:{width:364,height:861},pixelRatio:3.125,system:`HarmonyOS 5.0`,statusBarHeight:34,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:34}},{name:`HUAWEI nova 13`,os:`harmony`,screen:{width:361,height:804},pixelRatio:3,system:`HarmonyOS 5.0`,statusBarHeight:35,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:35}},{name:`HUAWEI nova 13 Pro`,os:`harmony`,screen:{width:363,height:823},pixelRatio:3.375,system:`HarmonyOS 5.0`,statusBarHeight:44,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:44}},{name:`HUAWEI nova 12`,os:`harmony`,screen:{width:361,height:804},pixelRatio:3,system:`HarmonyOS 5.0`,statusBarHeight:35,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:35}},{name:`HUAWEI nova 12 Pro`,os:`harmony`,screen:{width:363,height:823},pixelRatio:3.375,system:`HarmonyOS 5.0`,statusBarHeight:44,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:44}},{name:`HUAWEI Pura X Max (outer)`,os:`harmony`,screen:{width:460,height:672},pixelRatio:2.75,system:`HarmonyOS 5.0`,statusBarHeight:66,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:66}},{name:`HUAWEI Pura X Max (inner)`,os:`harmony`,screen:{width:665,height:940},pixelRatio:2.75,system:`HarmonyOS 5.0`,statusBarHeight:72,navigationBarHeight:28,navigationBarHeightLandscape:28,safeAreaInsets:{top:72}}],P=[...[{name:`iPhone SE`,os:`ios`,screen:{width:375,height:667},pixelRatio:2,system:`iOS 15.0`,statusBarHeight:20,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:20},shell:{screenRadius:0,bodyRadius:38}},{name:`iPhone XR`,os:`ios`,screen:{width:414,height:896},pixelRatio:2,system:`iOS 18.5`,statusBarHeight:48,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:48,bottom:34},safeAreaInsetsLandscape:{left:48,right:48,bottom:21},cutout:{shape:`notch`,width:231,height:33,top:0}},{name:`iPhone 12 Pro`,os:`ios`,screen:{width:390,height:844},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:47,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:47,bottom:34},safeAreaInsetsLandscape:{left:47,right:47,bottom:21},cutout:{shape:`notch`,width:210,height:32,top:0}},{name:`iPhone 14`,os:`ios`,screen:{width:390,height:844},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:47,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:47,bottom:34},safeAreaInsetsLandscape:{left:47,right:47,bottom:21},cutout:{shape:`notch`,width:162,height:34,top:0},shell:{screenRadius:47}},{name:`iPhone 14 Plus`,os:`ios`,screen:{width:428,height:926},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:47,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:47,bottom:34},safeAreaInsetsLandscape:{left:47,right:47,bottom:21},cutout:{shape:`notch`,width:161,height:34,top:0}},{name:`iPhone 14 Pro`,os:`ios`,screen:{width:393,height:852},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:54,safeAreaInsets:{top:59,bottom:34},safeAreaInsetsLandscape:{left:59,right:59,bottom:21},cutout:{shape:`pill`,width:125,height:37,top:11},shell:{screenRadius:55}},{name:`iPhone 14 Pro Max`,os:`ios`,screen:{width:430,height:932},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:54,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:59,bottom:34},safeAreaInsetsLandscape:{left:59,right:59,bottom:21},cutout:{shape:`pill`,width:125,height:37,top:11}},{name:`iPhone 15`,os:`ios`,screen:{width:393,height:852},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:54,safeAreaInsets:{top:59,bottom:34},safeAreaInsetsLandscape:{left:59,right:59,bottom:21},cutout:{shape:`pill`,width:125,height:37,top:11}},{name:`iPhone 15 Plus`,os:`ios`,screen:{width:430,height:932},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:54,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:59,bottom:34},safeAreaInsetsLandscape:{left:59,right:59,bottom:21},cutout:{shape:`pill`,width:125,height:37,top:11}},{name:`iPhone 15 Pro`,os:`ios`,screen:{width:393,height:852},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:54,safeAreaInsets:{top:59,bottom:34},safeAreaInsetsLandscape:{left:59,right:59,bottom:21},cutout:{shape:`pill`,width:125,height:37,top:11}},{name:`iPhone 15 Pro Max`,os:`ios`,screen:{width:430,height:932},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:54,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:59,bottom:34},safeAreaInsetsLandscape:{left:59,right:59,bottom:21},cutout:{shape:`pill`,width:125,height:37,top:11}},{name:`iPhone 16e`,os:`ios`,screen:{width:390,height:844},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:47,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:47,bottom:34},safeAreaInsetsLandscape:{left:47,right:47,bottom:21},cutout:{shape:`notch`,width:162,height:34,top:0}},{name:`iPhone 16`,os:`ios`,screen:{width:393,height:852},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:54,safeAreaInsets:{top:59,bottom:34},safeAreaInsetsLandscape:{left:59,right:59,bottom:21},cutout:{shape:`pill`,width:125,height:37,top:11}},{name:`iPhone 16 Plus`,os:`ios`,screen:{width:430,height:932},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:54,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:59,bottom:34},safeAreaInsetsLandscape:{left:59,right:59,bottom:21},cutout:{shape:`pill`,width:125,height:37,top:11}},{name:`iPhone 16 Pro`,os:`ios`,screen:{width:402,height:874},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:54,safeAreaInsets:{top:62,bottom:34},safeAreaInsetsLandscape:{left:62,right:62,bottom:21},cutout:{shape:`pill`,width:125,height:37,top:14},shell:{screenRadius:62}},{name:`iPhone 16 Pro Max`,os:`ios`,screen:{width:440,height:956},pixelRatio:3,system:`iOS 18.5`,statusBarHeight:54,safeAreaInsets:{top:62,bottom:34},safeAreaInsetsLandscape:{left:62,right:62,bottom:21},cutout:{shape:`pill`,width:125,height:37,top:14},shell:{screenRadius:62}},{name:`iPad Mini`,os:`ios`,formFactor:`tablet`,screen:{width:744,height:1133},pixelRatio:2,system:`iOS 18.5`,statusBarHeight:24,statusBarHeightLandscape:24,safeAreaInsets:{top:24,bottom:25},safeAreaInsetsLandscape:{top:24,bottom:25},shell:{screenRadius:18}},{name:`iPad Pro 13`,os:`ios`,formFactor:`tablet`,screen:{width:1032,height:1376},pixelRatio:2,system:`iPadOS 18.5`,statusBarHeight:24,statusBarHeightLandscape:24,safeAreaInsets:{top:24,bottom:25},safeAreaInsetsLandscape:{top:24,bottom:25},shell:{screenRadius:18}},{name:`iPhone 5`,os:`ios`,screen:{width:320,height:568},pixelRatio:2,system:`iOS 10.3`,statusBarHeight:20,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:20},shell:{screenRadius:0,bodyRadius:38}},{name:`iPhone 6/7/8`,os:`ios`,screen:{width:375,height:667},pixelRatio:2,system:`iOS 11.0`,statusBarHeight:20,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:20},shell:{screenRadius:0,bodyRadius:38}},{name:`iPhone 6/7/8 Plus`,os:`ios`,screen:{width:414,height:736},pixelRatio:3,system:`iOS 11.0`,statusBarHeight:20,navigationBarHeight:44,navigationBarHeightLandscape:44,safeAreaInsets:{top:20},shell:{screenRadius:0,bodyRadius:38}},{name:`iPhone X`,os:`ios`,screen:{width:375,height:812},pixelRatio:3,system:`iOS 16.0`,statusBarHeight:44,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:44,bottom:34},safeAreaInsetsLandscape:{left:44,right:44,bottom:21},cutout:{shape:`notch`,width:209,height:30,top:0},shell:{screenRadius:39}},{name:`iPhone XS Max`,os:`ios`,screen:{width:414,height:896},pixelRatio:3,system:`iOS 11.0`,statusBarHeight:44,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:44,bottom:34},safeAreaInsetsLandscape:{left:44,right:44,bottom:21},cutout:{shape:`notch`,width:209,height:30,top:0}},{name:`iPhone 12/13 mini`,os:`ios`,screen:{width:375,height:812},pixelRatio:3,system:`iOS 15.0`,statusBarHeight:50,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:50,bottom:34},safeAreaInsetsLandscape:{left:50,right:50,bottom:21},cutout:{shape:`notch`,width:192,height:30,top:0}},{name:`iPhone 12/13 (Pro)`,os:`ios`,screen:{width:390,height:844},pixelRatio:3,system:`iOS 15.0`,statusBarHeight:47,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:47,bottom:34},safeAreaInsetsLandscape:{left:47,right:47,bottom:21},cutout:{shape:`notch`,width:162,height:34,top:0}},{name:`iPhone 12/13 Pro Max`,os:`ios`,screen:{width:428,height:926},pixelRatio:3,system:`iOS 15.0`,statusBarHeight:47,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:47,bottom:34},safeAreaInsetsLandscape:{left:47,right:47,bottom:21},cutout:{shape:`notch`,width:161,height:34,top:0}},{name:`iPad`,os:`ios`,formFactor:`tablet`,screen:{width:768,height:1024},pixelRatio:2,system:`iOS 11.0`,statusBarHeight:20,statusBarHeightLandscape:20,safeAreaInsets:{top:20},safeAreaInsetsLandscape:{top:20},shell:{screenRadius:0}},{name:`iPad Pro 10.5-inch`,os:`ios`,formFactor:`tablet`,screen:{width:834,height:1112},pixelRatio:2,system:`iOS 11.0`,statusBarHeight:20,statusBarHeightLandscape:20,safeAreaInsets:{top:20},safeAreaInsetsLandscape:{top:20},shell:{screenRadius:0}},{name:`iPad Pro 12.9-inch`,os:`ios`,formFactor:`tablet`,screen:{width:1024,height:1366},pixelRatio:2,system:`iOS 11.0`,statusBarHeight:24,statusBarHeightLandscape:24,safeAreaInsets:{top:24,bottom:25},safeAreaInsetsLandscape:{top:24,bottom:25},shell:{screenRadius:18}},{name:`iPad (gen 5)`,os:`ios`,formFactor:`tablet`,screen:{width:768,height:1024},pixelRatio:2,system:`iOS 12.2`,statusBarHeight:20,statusBarHeightLandscape:20,safeAreaInsets:{top:20},safeAreaInsetsLandscape:{top:20},shell:{screenRadius:0}},{name:`iPad (gen 6)`,os:`ios`,formFactor:`tablet`,screen:{width:768,height:1024},pixelRatio:2,system:`iOS 12.2`,statusBarHeight:20,statusBarHeightLandscape:20,safeAreaInsets:{top:20},safeAreaInsetsLandscape:{top:20},shell:{screenRadius:0}},{name:`iPad (gen 7)`,os:`ios`,formFactor:`tablet`,screen:{width:810,height:1080},pixelRatio:2,system:`iOS 12.2`,statusBarHeight:20,statusBarHeightLandscape:20,safeAreaInsets:{top:20},safeAreaInsetsLandscape:{top:20},shell:{screenRadius:0}},{name:`iPad (gen 11)`,os:`ios`,formFactor:`tablet`,screen:{width:820,height:1180},pixelRatio:2,system:`iOS 18.5`,statusBarHeight:24,statusBarHeightLandscape:24,safeAreaInsets:{top:24,bottom:25},safeAreaInsetsLandscape:{top:24,bottom:25},shell:{screenRadius:18}},{name:`iPad Pro 11`,os:`ios`,formFactor:`tablet`,screen:{width:834,height:1194},pixelRatio:2,system:`iOS 12.2`,statusBarHeight:24,statusBarHeightLandscape:24,safeAreaInsets:{top:24,bottom:25},safeAreaInsetsLandscape:{top:24,bottom:25},shell:{screenRadius:18}},{name:`iPhone 6`,os:`ios`,screen:{width:375,height:667},pixelRatio:2,system:`iOS 11.0`,statusBarHeight:20,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:20},shell:{screenRadius:0,bodyRadius:38}},{name:`iPhone 6 Plus`,os:`ios`,screen:{width:414,height:736},pixelRatio:3,system:`iOS 11.0`,statusBarHeight:20,navigationBarHeight:44,navigationBarHeightLandscape:44,safeAreaInsets:{top:20},shell:{screenRadius:0,bodyRadius:38}},{name:`iPhone 7`,os:`ios`,screen:{width:375,height:667},pixelRatio:2,system:`iOS 11.0`,statusBarHeight:20,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:20},shell:{screenRadius:0,bodyRadius:38}},{name:`iPhone 7 Plus`,os:`ios`,screen:{width:414,height:736},pixelRatio:3,system:`iOS 11.0`,statusBarHeight:20,navigationBarHeight:44,navigationBarHeightLandscape:44,safeAreaInsets:{top:20},shell:{screenRadius:0,bodyRadius:38}},{name:`iPhone 8`,os:`ios`,screen:{width:375,height:667},pixelRatio:2,system:`iOS 11.0`,statusBarHeight:20,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:20},shell:{screenRadius:0,bodyRadius:38}},{name:`iPhone 8 Plus`,os:`ios`,screen:{width:414,height:736},pixelRatio:3,system:`iOS 11.0`,statusBarHeight:20,navigationBarHeight:44,navigationBarHeightLandscape:44,safeAreaInsets:{top:20},shell:{screenRadius:0,bodyRadius:38}},{name:`iPhone SE (3rd gen)`,os:`ios`,screen:{width:375,height:667},pixelRatio:2,system:`iOS 18.5`,statusBarHeight:20,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:20},shell:{screenRadius:0,bodyRadius:38}},{name:`iPhone 11`,os:`ios`,screen:{width:414,height:896},pixelRatio:2,system:`iOS 12.2`,statusBarHeight:48,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:48,bottom:34},safeAreaInsetsLandscape:{left:48,right:48,bottom:21},cutout:{shape:`notch`,width:231,height:33,top:0}},{name:`iPhone 11 Pro`,os:`ios`,screen:{width:375,height:812},pixelRatio:3,system:`iOS 12.2`,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:44,bottom:34},safeAreaInsetsLandscape:{left:44,right:44,bottom:21},cutout:{shape:`notch`,width:209,height:30,top:0}},{name:`iPhone 11 Pro Max`,os:`ios`,screen:{width:414,height:896},pixelRatio:3,system:`iOS 12.2`,statusBarHeight:44,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:44,bottom:34},safeAreaInsetsLandscape:{left:44,right:44,bottom:21},cutout:{shape:`notch`,width:209,height:30,top:0}},{name:`iPhone 12`,os:`ios`,screen:{width:390,height:844},pixelRatio:3,system:`iOS 14.4`,statusBarHeight:47,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:47,bottom:34},safeAreaInsetsLandscape:{left:47,right:47,bottom:21},cutout:{shape:`notch`,width:210,height:32,top:0}},{name:`iPhone 12 Pro Max`,os:`ios`,screen:{width:428,height:926},pixelRatio:3,system:`iOS 14.4`,statusBarHeight:47,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:47,bottom:34},safeAreaInsetsLandscape:{left:47,right:47,bottom:21},cutout:{shape:`notch`,width:210,height:32,top:0}},{name:`iPhone 12 Mini`,os:`ios`,screen:{width:375,height:812},pixelRatio:3,system:`iOS 14.4`,statusBarHeight:50,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:50,bottom:34},safeAreaInsetsLandscape:{left:50,right:50,bottom:21},cutout:{shape:`notch`,width:192,height:30,top:0}},{name:`iPhone 13`,os:`ios`,screen:{width:390,height:844},pixelRatio:3,system:`iOS 15.0`,statusBarHeight:47,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:47,bottom:34},safeAreaInsetsLandscape:{left:47,right:47,bottom:21},cutout:{shape:`notch`,width:162,height:34,top:0}},{name:`iPhone 13 Pro`,os:`ios`,screen:{width:390,height:844},pixelRatio:3,system:`iOS 15.0`,statusBarHeight:47,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:47,bottom:34},safeAreaInsetsLandscape:{left:47,right:47,bottom:21},cutout:{shape:`notch`,width:162,height:34,top:0}},{name:`iPhone 13 Pro Max`,os:`ios`,screen:{width:428,height:926},pixelRatio:3,system:`iOS 15.0`,statusBarHeight:47,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:47,bottom:34},safeAreaInsetsLandscape:{left:47,right:47,bottom:21},cutout:{shape:`notch`,width:161,height:34,top:0}},{name:`iPhone 13 Mini`,os:`ios`,screen:{width:375,height:812},pixelRatio:3,system:`iOS 15.0`,statusBarHeight:50,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:50,bottom:34},safeAreaInsetsLandscape:{left:50,right:50,bottom:21},cutout:{shape:`notch`,width:192,height:30,top:0}},{name:`iPhone 17`,os:`ios`,screen:{width:402,height:874},pixelRatio:3,system:`iOS 18.7`,statusBarHeight:54,safeAreaInsets:{top:62,bottom:34},safeAreaInsetsLandscape:{left:62,right:62,bottom:20},cutout:{shape:`pill`,width:125,height:37,top:14}},{name:`iPhone Air`,os:`ios`,screen:{width:420,height:912},pixelRatio:3,system:`iOS 18.7`,statusBarHeight:54,safeAreaInsets:{top:68,bottom:34},safeAreaInsetsLandscape:{left:68,right:68,bottom:20},cutout:{shape:`pill`,width:125,height:37,top:20}},{name:`iPhone 17 Pro`,os:`ios`,screen:{width:402,height:874},pixelRatio:3,system:`iOS 26.0`,statusBarHeight:54,safeAreaInsets:{top:62,bottom:34},safeAreaInsetsLandscape:{top:0,left:62,right:62,bottom:20},cutout:{shape:`pill`,width:125,height:37,top:14},shell:{screenRadius:62}},{name:`iPhone 17 Pro Max`,os:`ios`,screen:{width:440,height:956},pixelRatio:3,system:`iOS 18.7`,statusBarHeight:54,safeAreaInsets:{top:62,bottom:34},safeAreaInsetsLandscape:{left:62,right:62,bottom:20},cutout:{shape:`pill`,width:125,height:37,top:14}},{name:`iPhone 17e`,os:`ios`,screen:{width:390,height:844},pixelRatio:3,system:`iOS 18.7`,statusBarHeight:47,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:47,bottom:34},safeAreaInsetsLandscape:{left:47,right:47,bottom:20},cutout:{shape:`notch`,width:162,height:34,top:0}},{name:`iPhone 4`,os:`ios`,screen:{width:320,height:480},pixelRatio:2,system:`iOS 7.1`,statusBarHeight:20,safeAreaInsets:{top:20},shell:{screenRadius:0,bodyRadius:38}},{name:`iPhone 5/SE`,os:`ios`,screen:{width:320,height:568},pixelRatio:2,system:`iOS 10.3`,statusBarHeight:20,navigationBarHeight:44,navigationBarHeightLandscape:32,safeAreaInsets:{top:20},shell:{screenRadius:0,bodyRadius:38}},{name:`iPad Air`,os:`ios`,formFactor:`tablet`,screen:{width:820,height:1180},pixelRatio:2,system:`iOS 13.3`,statusBarHeight:24,statusBarHeightLandscape:24,safeAreaInsets:{top:24,bottom:25},safeAreaInsetsLandscape:{top:24,bottom:25},shell:{screenRadius:18}},{name:`iPad Pro`,os:`ios`,formFactor:`tablet`,screen:{width:1024,height:1366},pixelRatio:2,system:`iOS 11.0`,statusBarHeight:24,statusBarHeightLandscape:24,safeAreaInsets:{top:24,bottom:25},safeAreaInsetsLandscape:{top:24,bottom:25},shell:{screenRadius:18}},{name:`iPhone 17 Air`,os:`ios`,screen:{width:420,height:912},pixelRatio:3,system:`iOS 18.0`,statusBarHeight:54,safeAreaInsets:{top:68,bottom:34},safeAreaInsetsLandscape:{left:68,right:68,bottom:20},cutout:{shape:`pill`,width:125,height:37,top:20}},{name:`iPad Pro M4`,os:`ios`,formFactor:`tablet`,screen:{width:834,height:1210},pixelRatio:2,system:`iOS 17.5`,statusBarHeight:24,statusBarHeightLandscape:24,safeAreaInsets:{top:24,bottom:25},safeAreaInsetsLandscape:{top:24,bottom:25},shell:{screenRadius:18}},{name:`iPad Air M2`,os:`ios`,formFactor:`tablet`,screen:{width:820,height:1180},pixelRatio:2,system:`iOS 17.4`,statusBarHeight:24,statusBarHeightLandscape:24,safeAreaInsets:{top:24,bottom:25},safeAreaInsetsLandscape:{top:24,bottom:25},shell:{screenRadius:18}}],...M,...N],F=new Map(P.map(e=>[e.name,e])),ee=F.get(`iPhone X`);function I(e){if(e)return F.get(e)}function L(e,t=`portrait`){let{screen:n}=e;return t===`landscape`?{width:n.height,height:n.width}:{width:n.width,height:n.height}}function te(e,t=`portrait`){return j(O(e),t)}function ne(e,t=`portrait`){let n=L(e,t),r=te(e,t),i=r.top,a=r.left,o=n.width-r.right,s=n.height-r.bottom;return{top:i,left:a,right:o,bottom:s,width:o-a,height:s-i}}function re(e){let{navigationBar:t,tabBarHeight:n}=e;if(t!==void 0&&typeof t!=`boolean`&&(typeof t!=`number`||!Number.isFinite(t)||t<0))throw RangeError(`resolveWindowSize: options.navigationBar must be a boolean or a finite number >= 0, got ${t}`);if(n!==void 0&&(typeof n!=`number`||!Number.isFinite(n)||n<0))throw RangeError(`resolveWindowSize: options.tabBarHeight must be a finite number >= 0, got ${n}`)}function ie(e,t={}){re(t);let{orientation:n=`portrait`,navigationBar:r=!0,tabBarHeight:i=0}=t,a=O(e),o=L(e,n),s=k(a,n),c=r===!0?A(a,n):r===!1?0:r;return{width:o.width,height:Math.max(0,o.height-s-c-i)}}var R=t(e(),1),z={notch:{shape:`notch`,width:164,height:30,top:0},pill:{shape:`pill`,width:125,height:37,top:11},circle:{shape:`circle`,width:11,height:11,top:13}};function ae(e){switch(e.shape){case`notch`:{let t=Math.round(e.height*.6);return`0 0 ${t}px ${t}px`}case`circle`:return`50%`;default:return`${e.height/2}px`}}function oe(e,t){return(e.centerX??.5)*t-e.width/2}function B(e){if(e===null)return;let t=Number(e);return Number.isFinite(t)&&t>=0?t:void 0}function se(e){return e===`ios`||e===`android`||e===`harmony`?e:void 0}function ce(e){return e===`landscape`?`landscape`:`portrait`}function le(e){if(e!==null)return e===`none`?null:e in z?z[e]:void 0}function ue(e){let t={top:B(e.getAttribute(`safe-area-top`)),right:B(e.getAttribute(`safe-area-right`)),bottom:B(e.getAttribute(`safe-area-bottom`)),left:B(e.getAttribute(`safe-area-left`))},n=Object.entries(t).filter(([,e])=>e!==void 0);return n.length>0?Object.fromEntries(n):void 0}function de(e,t,n){let r=ue(e),i=le(e.getAttribute(`cutout`)),a=B(e.getAttribute(`status-bar-height`));return fe({name:t?.name??``,os:se(e.getAttribute(`os`))??t?.os??`ios`,screen:{width:B(e.getAttribute(`width`))??t?.screen.width??n.width,height:B(e.getAttribute(`height`))??t?.screen.height??n.height},pixelRatio:B(e.getAttribute(`pixel-ratio`))??t?.pixelRatio??1,formFactor:t?.formFactor,system:t?.system,userAgent:e.getAttribute(`user-agent`)??t?.userAgent,statusBarHeight:a??t?.statusBarHeight,statusBarHeightLandscape:a??t?.statusBarHeightLandscape,navigationBarHeight:B(e.getAttribute(`navigation-bar-height`))??t?.navigationBarHeight,navigationBarHeightLandscape:t?.navigationBarHeightLandscape,safeAreaInsets:r??t?.safeAreaInsets,safeAreaInsetsLandscape:r??t?.safeAreaInsetsLandscape,cutout:i===void 0?t?.cutout:i??void 0,shell:t?.shell})}function fe(e){let t={};for(let n of Object.keys(e))e[n]!==void 0&&(t[n]=e[n]);return t}var pe={x:0,y:0,width:0,height:0};function me(e,t,n,r){let i=t>0&&n>0&&!(r.width===0&&r.height===0),a=i?r.width/t:1,o=i?r.height/n:1;return{x:r.left+e.x*a,y:r.top+e.y*o,width:e.width*a,height:e.height*o,scale:a}}function V(e,t){return e!==null&&Math.abs(e.x-t.x)<.001&&Math.abs(e.y-t.y)<.001&&Math.abs(e.width-t.width)<.001&&Math.abs(e.height-t.height)<.001&&Math.abs(e.scale-t.scale)<.001}function he(e,t){return e.reduce((e,n)=>V(n,t)?e+1:e,0)}var ge=`<device-frame> stopped publishing contentrectchange: the content rect is oscillating between a small set of values, most likely because two or more listeners keep mutating attributes in response to the event they just received. The element has stopped re-measuring; call refreshContentRect() once the listeners settle to resync.`,H=`contentrectchange`,_e={top:0,left:0,right:0,bottom:0,width:0,height:0},ve={top:0,right:0,bottom:0,left:0},U={width:0,height:0};function ye(e,t,n,r,i,a){let o=O(e);if(n)return{screen:U,orientation:t,pixelRatio:o.pixelRatio,userAgent:o.userAgent,statusBarHeight:0,navigationBarHeight:0,tabBarHeight:0,safeArea:_e,safeAreaInsets:ve,window:U,content:pe,cutout:null,shell:o.shell};let s=L(e,t),c=k(o,t),l=r?s:ie(e,{orientation:t,navigationBar:i,tabBarHeight:a});return{screen:s,orientation:t,pixelRatio:o.pixelRatio,userAgent:o.userAgent,statusBarHeight:c,navigationBarHeight:i,tabBarHeight:a,safeArea:ne(e,t),safeAreaInsets:j(o,t),window:l,content:{x:0,y:r?0:c+i,width:l.width,height:l.height},cutout:o.cutout,shell:o.shell}}function W(e,t,n){n==null?e.removeAttribute(t):e.setAttribute(t,n)}function G(e,t,n){e.toggleAttribute(t,!!n)}function be(e,t,n){n?(e.removeProperty(`--device-width`),e.removeProperty(`--device-height`)):(e.setProperty(`--device-width`,`${t.screen.width}px`),e.setProperty(`--device-height`,`${t.screen.height}px`));let{safeAreaInsets:r,shell:i}=t;e.setProperty(`--device-pixel-ratio`,`${t.pixelRatio}`),e.setProperty(`--device-status-bar-height`,`${t.statusBarHeight}px`),e.setProperty(`--device-navigation-bar-height`,`${t.navigationBarHeight}px`),e.setProperty(`--device-tab-bar-height`,`${t.tabBarHeight}px`),e.setProperty(`--device-window-width`,`${t.window.width}px`),e.setProperty(`--device-window-height`,`${t.window.height}px`),e.setProperty(`--device-safe-area-top`,`${r.top}px`),e.setProperty(`--device-safe-area-right`,`${r.right}px`),e.setProperty(`--device-safe-area-bottom`,`${r.bottom}px`),e.setProperty(`--device-safe-area-left`,`${r.left}px`),e.setProperty(`--device-screen-radius`,`${i.screenRadius}px`),e.setProperty(`--device-bezel`,`${i.bezel}px`),e.setProperty(`--device-body-radius`,`${i.bodyRadius}px`)}function xe(e,t){return t===`landscape`?e.screen.height:e.screen.width}var Se=744,Ce=375,we=1.17;function Te(e){return e.os===`ios`?Math.min(e.screen.width,e.screen.height)>=Se?`ipad`:e.cutout?`ios-cutout`:`ios-classic`:`android`}var Ee=[{width:375,statusBarHeight:44,timeLeft:31.3,trailing:14.3,scale:1,centerY:23},{width:375,statusBarHeight:50,timeLeft:26.7,trailing:24.5,scale:.95,centerY:26.3},{width:390,statusBarHeight:47,timeLeft:36,trailing:18.3,scale:1.02,centerY:24.8},{width:414,statusBarHeight:48,timeLeft:35,trailing:17,scale:1.05,centerY:25},{width:414,statusBarHeight:44,timeLeft:40.7,trailing:21.4,scale:1.05,centerY:22.7},{width:428,statusBarHeight:47,timeLeft:45.3,trailing:27.4,scale:1.11,centerY:24.3},{width:393,statusBarHeight:54,timeLeft:54.3,trailing:32.7,scale:1.11},{width:402,statusBarHeight:54,timeLeft:56.7,trailing:35.4,scale:1.11},{width:420,statusBarHeight:54,timeLeft:59.3,trailing:34.7,scale:1.17},{width:430,statusBarHeight:54,timeLeft:62.3,trailing:42.6,scale:1.17},{width:440,statusBarHeight:54,timeLeft:65.3,trailing:40.7,scale:1.17}];function De(e,t,n){let r=e.cutout,i=xe(e,t),a=r.shape===`pill`,o=r.top+r.height/2,s=Ee.find(e=>e.width===i&&e.statusBarHeight===n);if(s)return{timeLeft:s.timeLeft,trailing:s.trailing,scale:s.scale,centerY:a?o:s.centerY,leadingIcons:null};let c=(i-r.width)/2,l=Math.min(Math.max(i/Ce,1),we);return a?{timeLeft:c/2-13,trailing:c/2,centerY:o,scale:l,leadingIcons:null}:{timeLeft:c/2-10,trailing:Math.max(c/2-27,10),centerY:n/2+1,scale:l,leadingIcons:null}}function Oe(e){return{timeLeft:null,leadingIcons:6,trailing:14,centerY:e/2,scale:1}}function ke(e){let t=e>=24;return{timeLeft:t?17:7,trailing:t?15.5:5.5,centerY:e/2,scale:1,leadingIcons:null}}function Ae(e){return{timeLeft:31,trailing:28,centerY:e/2,scale:1,leadingIcons:null}}function je(e,t){let n=Te(e),r=k(e,t);switch(n){case`ios-cutout`:return{mode:n,height:r,...De(e,t,r)};case`ios-classic`:return{mode:n,height:r,...Oe(r)};case`ipad`:return{mode:n,height:r,...ke(r)};case`android`:return{mode:n,height:r,...Ae(r)}}}var Me=`9:41`,K=6e4;function Ne(e){return`${e.getHours().toString().padStart(2,`0`)}:${e.getMinutes().toString().padStart(2,`0`)}`}function q(e){return e===`white`?`#ffffff`:`#000000`}var Pe=class{element;#e;#t;#n=null;#r=null;#i=()=>{this.element.ownerDocument.hidden||(this.#l(),this.#s(),this.#c())};constructor(){this.element=document.createElement(`div`),this.element.className=`status-bar`,this.element.setAttribute(`aria-hidden`,`true`),this.#e=document.createElement(`span`),this.#e.className=`status-bar__time`,this.#t=document.createElement(`div`),this.#t.className=`status-bar__notch`;let e=document.createElement(`div`);e.className=`status-bar__icons`;for(let t of[`signal`,`wifi`,`battery`]){let n=document.createElement(`span`);n.className=`status-bar__${t}`,e.append(n)}this.element.append(this.#e,this.#t,e)}render(e,t){let{device:n,orientation:r}=e,{visible:i,mode:a,textStyle:o,background:s}=t;this.element.hidden=!i,s?this.element.style.backgroundColor=s:this.element.style.removeProperty(`background-color`),this.#o(n,r);let c=je(n,r);if(this.#a(c),!i){this.stop(),this.#e.textContent=``,this.element.style.removeProperty(`height`),this.element.style.removeProperty(`color`);return}if(this.element.style.height=`${c.height}px`,this.element.style.color=q(o),a===`live`){this.#u();return}this.stop(),this.#e.textContent=a??Me}#a(e){this.element.dataset.layout=e.mode,this.element.style.setProperty(`--sb-trailing`,`${e.trailing}px`),this.element.style.setProperty(`--sb-center-y`,`${e.centerY}px`),this.element.style.setProperty(`--sb-scale`,`${e.scale}`),e.timeLeft===null?this.element.style.removeProperty(`--sb-time-left`):this.element.style.setProperty(`--sb-time-left`,`${e.timeLeft}px`),e.leadingIcons===null?this.element.style.removeProperty(`--sb-leading-icons`):this.element.style.setProperty(`--sb-leading-icons`,`${e.leadingIcons}px`)}#o(e,t){let n=t===`portrait`?e.cutout:null;if(this.#t.hidden=n===null,!n){delete this.#t.dataset.shape,this.#t.style.removeProperty(`width`),this.#t.style.removeProperty(`height`),this.#t.style.removeProperty(`top`),this.#t.style.removeProperty(`left`),this.#t.style.removeProperty(`border-radius`);return}this.#t.dataset.shape=n.shape,this.#t.style.width=`${n.width}px`,this.#t.style.height=`${n.height}px`,this.#t.style.top=`${n.top}px`,this.#t.style.left=`${oe(n,e.screen.width)}px`,this.#t.style.borderRadius=ae(n)}#s(){this.#e.textContent=Ne(new Date)}#c(){if(this.#n!==null)return;let e=K-Date.now()%K;this.#n=setTimeout(()=>{this.#s(),this.#n=setInterval(()=>this.#s(),K)},e)}#l(){this.#n!==null&&(clearTimeout(this.#n),clearInterval(this.#n),this.#n=null)}#u(){this.#s(),this.#c(),this.#r===null&&(this.#r=this.element.ownerDocument,this.#r.addEventListener(`visibilitychange`,this.#i))}stop(){this.#l(),this.#r!==null&&(this.#r.removeEventListener(`visibilitychange`,this.#i),this.#r=null)}},J=`
|
|
2
|
+
:host {
|
|
3
|
+
/* Reflected from the resolved device so slotted content can lay itself out
|
|
4
|
+
against the same numbers the frame drew — see reflectMetrics(). */
|
|
5
|
+
--device-width: 0px;
|
|
6
|
+
--device-height: 0px;
|
|
7
|
+
--device-pixel-ratio: 1;
|
|
8
|
+
--device-status-bar-height: 0px;
|
|
9
|
+
--device-navigation-bar-height: 0px;
|
|
10
|
+
--device-tab-bar-height: 0px;
|
|
11
|
+
--device-window-width: 0px;
|
|
12
|
+
--device-window-height: 0px;
|
|
13
|
+
--device-safe-area-top: 0px;
|
|
14
|
+
--device-safe-area-right: 0px;
|
|
15
|
+
--device-safe-area-bottom: 0px;
|
|
16
|
+
--device-safe-area-left: 0px;
|
|
17
|
+
--device-screen-radius: 38px;
|
|
18
|
+
--device-bezel: 0px;
|
|
19
|
+
--device-body-radius: 38px;
|
|
20
|
+
--device-frame-border-width: 1px;
|
|
21
|
+
|
|
22
|
+
/* Host-overridable skin. --device-frame-radius overrides the body radius the
|
|
23
|
+
device itself resolved, for a host that wants one shape for every phone —
|
|
24
|
+
.screen derives its own radius from it below, so the two stay concentric.
|
|
25
|
+
The body defaults to near-black with a hairline border — a real phone's
|
|
26
|
+
bezel is never the same shade as the page it's showing. A host that widens
|
|
27
|
+
--device-frame-border must also update --device-frame-border-width, or the
|
|
28
|
+
radius math below stays sized for the old, thinner border. */
|
|
29
|
+
--device-frame-border: var(--device-frame-border-width) solid rgba(255, 255, 255, 0.08);
|
|
30
|
+
--device-frame-background: #0b0b0c;
|
|
31
|
+
--device-frame-shadow: 0 18px 50px rgba(16, 20, 24, 0.22);
|
|
32
|
+
--device-cutout-color: #000;
|
|
33
|
+
/* The status bar is transparent by default, so without a navigation-bar slot
|
|
34
|
+
this is what shows behind the clock — a real screen is never the bezel
|
|
35
|
+
color. A dark page sets it to its own background so white status-bar text
|
|
36
|
+
keeps its contrast. */
|
|
37
|
+
--device-screen-background: #ffffff;
|
|
38
|
+
|
|
39
|
+
position: relative;
|
|
40
|
+
display: inline-flex;
|
|
41
|
+
flex: none;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/*
|
|
45
|
+
* The phone body: content box = the screen at exactly the device size, bezel as
|
|
46
|
+
* padding, hairline border outside both. It is a shadow-tree element rather
|
|
47
|
+
* than :host so a light-DOM \`* { box-sizing: border-box }\` reset cannot fold
|
|
48
|
+
* the border into the width and leave .screen narrower than the metrics say.
|
|
49
|
+
*/
|
|
50
|
+
.body {
|
|
51
|
+
position: relative;
|
|
52
|
+
display: flex;
|
|
53
|
+
flex-direction: column;
|
|
54
|
+
flex: none;
|
|
55
|
+
box-sizing: content-box;
|
|
56
|
+
width: var(--device-width);
|
|
57
|
+
height: var(--device-height);
|
|
58
|
+
padding: var(--device-bezel);
|
|
59
|
+
min-height: 0;
|
|
60
|
+
overflow: hidden;
|
|
61
|
+
border: var(--device-frame-border);
|
|
62
|
+
border-radius: var(--device-frame-radius, calc(var(--device-body-radius) + var(--device-frame-border-width)));
|
|
63
|
+
background: var(--device-frame-background);
|
|
64
|
+
box-shadow: var(--device-frame-shadow);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Fills its container with no phone pretense: no bezel, no status bar, no home
|
|
68
|
+
indicator. The same element, drawn as a plain screen. */
|
|
69
|
+
:host([embedded]) {
|
|
70
|
+
display: block;
|
|
71
|
+
width: 100%;
|
|
72
|
+
height: 100%;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
:host([embedded]) .body {
|
|
76
|
+
box-sizing: border-box;
|
|
77
|
+
width: 100%;
|
|
78
|
+
height: 100%;
|
|
79
|
+
padding: 0;
|
|
80
|
+
border: 0;
|
|
81
|
+
border-radius: 0;
|
|
82
|
+
box-shadow: none;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
:host([embedded]) .screen {
|
|
86
|
+
border-radius: 0;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
:host([hidden]) {
|
|
90
|
+
display: none;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.screen {
|
|
94
|
+
position: relative;
|
|
95
|
+
display: flex;
|
|
96
|
+
flex-direction: column;
|
|
97
|
+
flex: 1;
|
|
98
|
+
min-height: 0;
|
|
99
|
+
overflow: hidden;
|
|
100
|
+
background: var(--device-screen-background);
|
|
101
|
+
/* The screen sits inside both the bezel and the border, so staying concentric
|
|
102
|
+
with the body needs both subtracted back out — floored at 0 so a small
|
|
103
|
+
--device-frame-radius override never asks for a negative radius. */
|
|
104
|
+
border-radius: max(0px, calc(var(--device-frame-radius, calc(var(--device-screen-radius) + var(--device-bezel) + var(--device-frame-border-width))) - var(--device-bezel) - var(--device-frame-border-width)));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/*
|
|
108
|
+
* Where the default slot's content goes. The screen is a flex column but every
|
|
109
|
+
* bar on it is absolutely positioned, so content left in flow would start at
|
|
110
|
+
* y=0, behind the status and navigation bars. These offsets are the CSS half of
|
|
111
|
+
* metrics.content: the same status-bar + navigation-bar top and tab-bar bottom
|
|
112
|
+
* the element reports, taken from the custom properties it reflects. Embedded
|
|
113
|
+
* mode needs no special case — every one of those variables is 0px there.
|
|
114
|
+
*/
|
|
115
|
+
.content {
|
|
116
|
+
position: absolute;
|
|
117
|
+
left: 0;
|
|
118
|
+
right: 0;
|
|
119
|
+
top: calc(var(--device-status-bar-height) + var(--device-navigation-bar-height));
|
|
120
|
+
bottom: var(--device-tab-bar-height);
|
|
121
|
+
overflow: hidden;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Immersive is the page running the full screen height behind the bars, which
|
|
125
|
+
is what metrics.content already reports — the wrapper has to match it. */
|
|
126
|
+
:host([immersive]) .content {
|
|
127
|
+
top: 0;
|
|
128
|
+
bottom: 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/*
|
|
132
|
+
* The host's own navigation bar. On a real phone the nav bar view starts at
|
|
133
|
+
* y=0 and is status-bar-height + nav-bar-height tall — navigationBarBackgroundColor
|
|
134
|
+
* paints the whole thing, status bar included, which is why this wrapper covers
|
|
135
|
+
* the status bar too instead of stopping below it. Unlike the status bar it DOES
|
|
136
|
+
* take pointer events: what a host slots in here is a real title bar with real
|
|
137
|
+
* buttons.
|
|
138
|
+
*/
|
|
139
|
+
.navigation-bar {
|
|
140
|
+
position: absolute;
|
|
141
|
+
top: 0;
|
|
142
|
+
left: 0;
|
|
143
|
+
right: 0;
|
|
144
|
+
height: calc(var(--device-status-bar-height) + var(--device-navigation-bar-height));
|
|
145
|
+
z-index: 250;
|
|
146
|
+
box-sizing: border-box;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/*
|
|
150
|
+
* The frame owns the slotted bar's vertical geometry, the way a real app's
|
|
151
|
+
* navigation bar view always lays its content out below the status bar: the
|
|
152
|
+
* element spans both bars and its content starts under the status bar, so its
|
|
153
|
+
* own background is what the status bar is painted on. These are !important on
|
|
154
|
+
* purpose — a light-DOM rule of equal specificity beats a shadow-tree one, and
|
|
155
|
+
* a host's ordinary padding: 0 12px would otherwise silently zero the top
|
|
156
|
+
* inset and put the title under the status bar. Horizontal padding, colors
|
|
157
|
+
* and content stay the host's.
|
|
158
|
+
*/
|
|
159
|
+
::slotted([slot="navigation-bar"]) {
|
|
160
|
+
box-sizing: border-box !important;
|
|
161
|
+
height: 100% !important;
|
|
162
|
+
padding-top: var(--device-status-bar-height) !important;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/*
|
|
166
|
+
* The host's own tab bar, occupying the foot of the screen — exactly the strip
|
|
167
|
+
* the reported window size gives up for it. On a gesture-bar phone a real tab
|
|
168
|
+
* bar also covers the home indicator, and its height includes that inset; a
|
|
169
|
+
* host with such a bar says so through tab-bar-height.
|
|
170
|
+
*/
|
|
171
|
+
.tab-bar {
|
|
172
|
+
position: absolute;
|
|
173
|
+
bottom: 0;
|
|
174
|
+
left: 0;
|
|
175
|
+
right: 0;
|
|
176
|
+
height: var(--device-tab-bar-height);
|
|
177
|
+
z-index: 250;
|
|
178
|
+
box-sizing: border-box;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
/*
|
|
183
|
+
* Status bar: pinned to the device top, above whatever the screen slot renders.
|
|
184
|
+
* pointer-events:none so it never steals taps from the content beneath it. It
|
|
185
|
+
* is itself \`position: absolute\`, which is what makes it the positioning
|
|
186
|
+
* context .status-bar__time and .status-bar__icons place themselves against.
|
|
187
|
+
*/
|
|
188
|
+
.status-bar {
|
|
189
|
+
position: absolute;
|
|
190
|
+
top: 0;
|
|
191
|
+
left: 0;
|
|
192
|
+
right: 0;
|
|
193
|
+
z-index: 300;
|
|
194
|
+
pointer-events: none;
|
|
195
|
+
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', sans-serif;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/* An author \`display\` outranks the UA sheet's \`[hidden] { display: none }\`, so
|
|
199
|
+
any element styled with one needs its own hidden rule or the property does
|
|
200
|
+
nothing. This is the bar that iOS landscape, status-bar="hidden" and embedded
|
|
201
|
+
all switch off. */
|
|
202
|
+
.status-bar[hidden] {
|
|
203
|
+
display: none;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* Left-anchored at --sb-time-left; ios-classic leaves that variable unset, so
|
|
207
|
+
the var() fallback (50%) plus the translateX below centers it instead. */
|
|
208
|
+
.status-bar__time {
|
|
209
|
+
position: absolute;
|
|
210
|
+
top: var(--sb-center-y, 50%);
|
|
211
|
+
left: var(--sb-time-left, 50%);
|
|
212
|
+
transform: translateY(-50%);
|
|
213
|
+
font-size: calc(16px * var(--sb-scale, 1));
|
|
214
|
+
font-weight: 600;
|
|
215
|
+
letter-spacing: 0.2px;
|
|
216
|
+
white-space: nowrap;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.status-bar[data-layout="ios-classic"] .status-bar__time {
|
|
220
|
+
transform: translate(-50%, -50%);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/* iPad's own time ink runs narrower than an iPhone's at the same nominal
|
|
224
|
+
size (measured: 22.5px vs 28.7px wide), so its font-size is cut on top of
|
|
225
|
+
the ordinary scale rather than folded into it. */
|
|
226
|
+
.status-bar[data-layout="ipad"] .status-bar__time {
|
|
227
|
+
font-size: calc(16px * var(--sb-scale, 1) * 0.8);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.status-bar[data-layout="android"] .status-bar__time {
|
|
231
|
+
font-size: 14px;
|
|
232
|
+
font-weight: 400;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* Size, corner radius and both offsets are written inline from the resolved
|
|
236
|
+
cutout — a cutout is not always centered, so nothing here may place it. */
|
|
237
|
+
.status-bar__notch {
|
|
238
|
+
position: absolute;
|
|
239
|
+
background: var(--device-cutout-color);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/*
|
|
243
|
+
* A notch's bottom corners are rounded (cutoutBorderRadius), but where it meets
|
|
244
|
+
* the screen's top edge a real phone curves the OTHER way — the edge sweeps
|
|
245
|
+
* outward around the notch rather than cutting a straight corner. Two 6px
|
|
246
|
+
* squares astride the top corners, each a radial gradient centered on the
|
|
247
|
+
* corner nearest the notch, draw that outward curve; a pill or punch-hole
|
|
248
|
+
* floats clear of the edge and needs none of this.
|
|
249
|
+
*/
|
|
250
|
+
.status-bar__notch[data-shape="notch"]::before,
|
|
251
|
+
.status-bar__notch[data-shape="notch"]::after {
|
|
252
|
+
content: "";
|
|
253
|
+
position: absolute;
|
|
254
|
+
top: 0;
|
|
255
|
+
width: 6px;
|
|
256
|
+
height: 6px;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.status-bar__notch[data-shape="notch"]::before {
|
|
260
|
+
left: -6px;
|
|
261
|
+
background: radial-gradient(circle at bottom left, transparent 6px, var(--device-cutout-color) 6.5px);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.status-bar__notch[data-shape="notch"]::after {
|
|
265
|
+
right: -6px;
|
|
266
|
+
background: radial-gradient(circle at bottom right, transparent 6px, var(--device-cutout-color) 6.5px);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/* Right-anchored at --sb-trailing — the battery's own outline, not counting
|
|
270
|
+
the nub pseudo-element that floats past it (see .status-bar__battery::after). */
|
|
271
|
+
.status-bar__icons {
|
|
272
|
+
position: absolute;
|
|
273
|
+
top: var(--sb-center-y, 50%);
|
|
274
|
+
right: var(--sb-trailing, 14px);
|
|
275
|
+
transform: translateY(-50%);
|
|
276
|
+
display: inline-flex;
|
|
277
|
+
align-items: center;
|
|
278
|
+
gap: calc(5.5px * var(--sb-scale, 1));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/*
|
|
282
|
+
* ios-classic splits this cluster the way a real pre-notch status bar does:
|
|
283
|
+
* signal+Wi-Fi sit next to the carrier name on the left, battery on the
|
|
284
|
+
* right. Both --sb-leading-icons and --sb-trailing bound the row, so
|
|
285
|
+
* \`margin-left: auto\` on the battery alone is enough to push just it to the
|
|
286
|
+
* row's right edge while signal/wifi keep their ordinary left-packed gap.
|
|
287
|
+
*/
|
|
288
|
+
.status-bar[data-layout="ios-classic"] .status-bar__icons {
|
|
289
|
+
left: var(--sb-leading-icons);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.status-bar[data-layout="ios-classic"] .status-bar__battery {
|
|
293
|
+
margin-left: auto;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.status-bar[data-layout="android"] .status-bar__icons {
|
|
297
|
+
gap: 7.5px;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* Glyph stand-ins drawn from the current foreground color, which follows the
|
|
301
|
+
active page's navigation-bar text style. */
|
|
302
|
+
.status-bar__signal,
|
|
303
|
+
.status-bar__wifi,
|
|
304
|
+
.status-bar__battery {
|
|
305
|
+
display: block;
|
|
306
|
+
background: currentColor;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.status-bar__signal {
|
|
310
|
+
width: calc(17px * var(--sb-scale, 1));
|
|
311
|
+
height: calc(10.7px * var(--sb-scale, 1));
|
|
312
|
+
-webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 11'><rect x='0' y='8' width='3' height='3' rx='1'/><rect x='4.5' y='6' width='3' height='5' rx='1'/><rect x='9' y='3' width='3' height='8' rx='1'/><rect x='13.5' y='0' width='3' height='11' rx='1'/></svg>") no-repeat center / contain;
|
|
313
|
+
mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 11'><rect x='0' y='8' width='3' height='3' rx='1'/><rect x='4.5' y='6' width='3' height='5' rx='1'/><rect x='9' y='3' width='3' height='8' rx='1'/><rect x='13.5' y='0' width='3' height='11' rx='1'/></svg>") no-repeat center / contain;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.status-bar__wifi {
|
|
317
|
+
width: calc(15.3px * var(--sb-scale, 1));
|
|
318
|
+
height: calc(11px * var(--sb-scale, 1));
|
|
319
|
+
border-radius: 1px;
|
|
320
|
+
-webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 11'><path d='M8 2.2c2.3 0 4.4.9 6 2.4l-1.4 1.5C11.4 4.9 9.8 4.2 8 4.2S4.6 4.9 3.4 6.1L2 4.6C3.6 3.1 5.7 2.2 8 2.2zm0 3.5c1.3 0 2.5.5 3.4 1.4L10 8.6c-.5-.5-1.2-.8-2-.8s-1.5.3-2 .8L4.6 7.1C5.5 6.2 6.7 5.7 8 5.7zm0 3.3l1.4 1.4c-.4.4-.9.6-1.4.6s-1-.2-1.4-.6L8 9z'/></svg>") no-repeat center / contain;
|
|
321
|
+
mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 11'><path d='M8 2.2c2.3 0 4.4.9 6 2.4l-1.4 1.5C11.4 4.9 9.8 4.2 8 4.2S4.6 4.9 3.4 6.1L2 4.6C3.6 3.1 5.7 2.2 8 2.2zm0 3.5c1.3 0 2.5.5 3.4 1.4L10 8.6c-.5-.5-1.2-.8-2-.8s-1.5.3-2 .8L4.6 7.1C5.5 6.2 6.7 5.7 8 5.7zm0 3.3l1.4 1.4c-.4.4-.9.6-1.4.6s-1-.2-1.4-.6L8 9z'/></svg>") no-repeat center / contain;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.status-bar[data-layout="android"] .status-bar__signal,
|
|
325
|
+
.status-bar[data-layout="android"] .status-bar__wifi {
|
|
326
|
+
width: 13px;
|
|
327
|
+
height: 12.6px;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.status-bar__battery {
|
|
331
|
+
/* Outline measured 24.5×11.5 including the stroke, so the border must not add to it. */
|
|
332
|
+
box-sizing: border-box;
|
|
333
|
+
width: calc(24.5px * var(--sb-scale, 1));
|
|
334
|
+
height: calc(11.5px * var(--sb-scale, 1));
|
|
335
|
+
border: 1px solid currentColor;
|
|
336
|
+
border-radius: 3px;
|
|
337
|
+
background: transparent;
|
|
338
|
+
position: relative;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.status-bar__battery::before {
|
|
342
|
+
content: "";
|
|
343
|
+
position: absolute;
|
|
344
|
+
inset: calc(2px * var(--sb-scale, 1));
|
|
345
|
+
right: calc(8px * var(--sb-scale, 1));
|
|
346
|
+
border-radius: 1px;
|
|
347
|
+
background: currentColor;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/* The nub: absolutely positioned past the element's own right edge, so it
|
|
351
|
+
never widens .status-bar__battery's own bounding box — the outline alone
|
|
352
|
+
is what --sb-trailing is measured to. */
|
|
353
|
+
.status-bar__battery::after {
|
|
354
|
+
content: "";
|
|
355
|
+
position: absolute;
|
|
356
|
+
top: calc(3px * var(--sb-scale, 1));
|
|
357
|
+
bottom: calc(3px * var(--sb-scale, 1));
|
|
358
|
+
right: calc(-3px * var(--sb-scale, 1));
|
|
359
|
+
width: calc(2px * var(--sb-scale, 1));
|
|
360
|
+
border-radius: 0 1px 1px 0;
|
|
361
|
+
background: currentColor;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/* Android draws its battery standing up rather than lying down; the nub and
|
|
365
|
+
fill insets follow the same swap. */
|
|
366
|
+
.status-bar[data-layout="android"] .status-bar__battery {
|
|
367
|
+
width: 7.6px;
|
|
368
|
+
height: 13px;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.status-bar[data-layout="android"] .status-bar__battery::before {
|
|
372
|
+
inset: 2px;
|
|
373
|
+
right: 2px;
|
|
374
|
+
bottom: 4px;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.status-bar[data-layout="android"] .status-bar__battery::after {
|
|
378
|
+
top: -3px;
|
|
379
|
+
bottom: auto;
|
|
380
|
+
left: 2px;
|
|
381
|
+
right: 2px;
|
|
382
|
+
width: auto;
|
|
383
|
+
height: 2px;
|
|
384
|
+
border-radius: 1px 1px 0 0;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
/*
|
|
389
|
+
* Home-indicator pill — an absolute overlay at the device bottom, present only
|
|
390
|
+
* on gesture-bar devices (the home-button class has bottom inset 0). It is NOT
|
|
391
|
+
* in flow and is transparent, so whatever the screen renders behind it shows
|
|
392
|
+
* through; content reserves bottom space via its own safe-area handling.
|
|
393
|
+
*/
|
|
394
|
+
.home-indicator {
|
|
395
|
+
position: absolute;
|
|
396
|
+
left: 0;
|
|
397
|
+
right: 0;
|
|
398
|
+
bottom: 0;
|
|
399
|
+
height: var(--device-safe-area-bottom);
|
|
400
|
+
pointer-events: none;
|
|
401
|
+
/* Above the slotted tab bar: on a gesture-bar phone the pill floats over the
|
|
402
|
+
app's own bottom bar rather than being tucked under it. */
|
|
403
|
+
z-index: 300;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.home-indicator::before {
|
|
407
|
+
content: "";
|
|
408
|
+
position: absolute;
|
|
409
|
+
left: 50%;
|
|
410
|
+
bottom: 8px;
|
|
411
|
+
width: 118px;
|
|
412
|
+
height: 4px;
|
|
413
|
+
transform: translateX(-50%);
|
|
414
|
+
border-radius: 999px;
|
|
415
|
+
/* currentColor, not a fixed shade — the pill follows the inline color the
|
|
416
|
+
element sets from status-bar-text-style, same switch the status bar uses. */
|
|
417
|
+
background: currentColor;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/* Host-owned layers that ride above the screen (extension mount points, chrome
|
|
421
|
+
affordances). The frame owns the stacking; slotted children opt themselves
|
|
422
|
+
back into pointer events. */
|
|
423
|
+
.overlay {
|
|
424
|
+
position: absolute;
|
|
425
|
+
inset: 0;
|
|
426
|
+
z-index: 400;
|
|
427
|
+
overflow: hidden;
|
|
428
|
+
pointer-events: none;
|
|
429
|
+
}
|
|
430
|
+
`,Y=new WeakMap,X=new WeakSet,Fe=`data-device-frame-styles`;function Ie(e){let t=e.ownerDocument,n=t.defaultView?.CSSStyleSheet;if(typeof n==`function`&&`adoptedStyleSheets`in e){let r=Y.get(t);if(!r||r.ctor!==n){let e=new n;e.replaceSync(J),r={sheet:e,ctor:n},Y.set(t,r),X.add(e)}let{sheet:i}=r;if(e.adoptedStyleSheets.includes(i))return;e.adoptedStyleSheets=[...e.adoptedStyleSheets.filter(e=>!X.has(e)),i];return}if(e.querySelector(`style[${Fe}]`))return;let r=t.createElement(`style`);r.setAttribute(Fe,``),r.textContent=J,e.append(r)}function Le(e,t){for(let n of t){if(!Object.prototype.hasOwnProperty.call(e,n))continue;let t=e[n];delete e[n],e[n]=t}}var Re=`device-frame`,Z=!1;function ze(e=Re){if(typeof customElements>`u`)return;let t=customElements.get(e);if(!t){customElements.define(e,Z?class extends Q{}:Q),Z=!0;return}if(t===Q&&(Z=!0),t[Ve]!==!0)throw Error(`<${e}> is already defined by an unrelated element class; pick another tag via defineDeviceFrame(tag)`)}var Be=typeof HTMLElement>`u`?class{}:HTMLElement,Ve=Symbol.for(`@devicekit/frame`),Q=class extends Be{static[Ve]=!0;static get observedAttributes(){return[`device`,`os`,`orientation`,`embedded`,`immersive`,`width`,`height`,`pixel-ratio`,`user-agent`,`cutout`,`status-bar-height`,`navigation-bar-height`,`tab-bar-height`,`safe-area-top`,`safe-area-right`,`safe-area-bottom`,`safe-area-left`,`status-bar`,`status-bar-text-style`,`status-bar-background`]}get deviceProfile(){return this.#e}set deviceProfile(e){e!=null&&w(e),this.#e=e,this.#p&&this.#v()}#e=null;#t=null;#n=null;#r=null;#i=null;#a=null;#o=null;#s=null;#c=null;#l=null;#u=!1;#d=!1;#f=!1;#p=!1;constructor(){super();let e=this.attachShadow({mode:`open`});Ie(e);let t=document.createElement(`div`);t.className=`body`,t.append(this.#g()),e.append(t),Le(this,[`device`,`deviceProfile`,`orientation`,`embedded`,`immersive`])}connectedCallback(){this.#p=!0,this.shadowRoot&&Ie(this.shadowRoot),this.#v(),!(typeof ResizeObserver>`u`)&&(this.#l??=new ResizeObserver(()=>this.#y()),this.#l.observe(this))}disconnectedCallback(){this.#t?.stop(),this.#l?.disconnect()}attributeChangedCallback(){this.#p&&this.#v()}get device(){return this.#e??I(this.getAttribute(`device`))??null}set device(e){W(this,`device`,e)}get orientation(){return ce(this.getAttribute(`orientation`))}set orientation(e){W(this,`orientation`,e)}get embedded(){return this.hasAttribute(`embedded`)}set embedded(e){G(this,`embedded`,e)}get immersive(){return this.hasAttribute(`immersive`)}set immersive(e){G(this,`immersive`,e)}get profile(){return de(this,this.device,ee.screen)}get metrics(){return ye(this.profile,this.orientation,this.embedded,this.immersive,this.#m(),this.#h())}get contentRect(){let{content:e,screen:t}=this.metrics,n=(this.#s??this).getBoundingClientRect();return me(e,t.width,t.height,n)}#m(){if((this.#i?.assignedNodes({flatten:!0})??[]).length===0)return 0;let e=B(this.getAttribute(`navigation-bar-height`));return e===void 0?A(O(this.profile),this.orientation):e}#h(){if((this.#o?.assignedNodes({flatten:!0})??[]).length===0)return 0;let e=B(this.getAttribute(`tab-bar-height`));return e!==void 0&&e>0?e:50}#g(){let e=document.createElement(`div`);e.className=`screen`;let t=document.createElement(`div`);t.className=`content`,t.append(document.createElement(`slot`)),this.#n=document.createElement(`div`),this.#n.className=`home-indicator`,this.#n.setAttribute(`aria-hidden`,`true`),this.#t=new Pe,this.#r=this.#_(`navigation-bar`),this.#i=this.#r.firstElementChild,this.#a=this.#_(`tab-bar`),this.#o=this.#a.firstElementChild;let n=document.createElement(`div`);n.className=`overlay`;let r=document.createElement(`slot`);return r.name=`overlay`,n.append(r),e.append(t,this.#n,this.#a,this.#r,this.#t.element,n),this.#s=e,e}#_(e){let t=document.createElement(`div`);t.className=e;let n=document.createElement(`slot`);return n.name=e,n.addEventListener(`slotchange`,()=>this.#v()),t.append(n),t}#v(){if(!this.#t||!this.#n)return;let e=this.metrics;be(this.style,e,this.embedded);let t=this.getAttribute(`status-bar`),n=!this.embedded&&t!==`hidden`&&e.statusBarHeight>0,r=t===`live`&&!this.isConnected?null:t;this.#t.render({device:O(this.profile),orientation:e.orientation},{visible:n,mode:r,textStyle:this.getAttribute(`status-bar-text-style`),background:this.getAttribute(`status-bar-background`)}),this.#n.style.color=q(this.getAttribute(`status-bar-text-style`)),this.#n.hidden=this.embedded||e.safeAreaInsets.bottom<=0,this.#r&&(this.#r.hidden=e.navigationBarHeight<=0),this.#a&&(this.#a.hidden=e.tabBarHeight<=0),this.#y()}addEventListener(e,t,n){super.addEventListener(e,t,n)}removeEventListener(e,t,n){super.removeEventListener(e,t,n)}refreshContentRect(){this.#y()}#y(){if(!(!this.#p||!this.isConnected)){if(this.#u){this.#d=!0;return}this.#u=!0;try{let e=[],t=!1;do{this.#d=!1;let n=this.contentRect;if(V(this.#c,n))break;if(he(e,n)>=2){t=!0,this.#f||console.error(ge),this.#f=!0;break}e.push(n),this.#c=n,this.dispatchEvent(new CustomEvent(H,{detail:n}))}while(this.#d);t||(this.#f=!1)}finally{this.#u=!1}}}};if(typeof customElements<`u`)try{ze()}catch{}function He(e=Re){let t=R.forwardRef(function(t,n){let{device:r,deviceProfile:i,os:a,orientation:o,embedded:s,immersive:c,cutout:l,width:u,height:d,pixelRatio:f,userAgent:p,statusBarHeight:m,safeAreaTop:h,safeAreaRight:g,safeAreaBottom:_,safeAreaLeft:v,statusBar:y,statusBarTextStyle:b,statusBarBackground:x,navigationBarHeight:S,tabBarHeight:C,onContentRectChange:w,children:T,className:E,...D}=t,O=(0,R.useRef)(null);(0,R.useImperativeHandle)(n,()=>O.current,[]);let k=(0,R.useRef)(w);k.current=w;let A=(0,R.useRef)(null),j=(0,R.useRef)(null);(0,R.useLayoutEffect)(()=>{ze(e)},[]),(0,R.useLayoutEffect)(()=>{O.current&&(O.current.deviceProfile=i??null)},[i]),(0,R.useLayoutEffect)(()=>{let e=O.current;if(!e)return;let t=e=>{let t=k.current;t&&(j.current=e.detail,t(e))};return e.addEventListener(H,t),(A.current!==e||!V(j.current,e.contentRect))&&(A.current=e,e.dispatchEvent(new CustomEvent(H,{detail:e.contentRect}))),()=>e.removeEventListener(H,t)},[]);let M=w!==void 0;(0,R.useLayoutEffect)(()=>{let e=O.current;!e||!M||V(j.current,e.contentRect)||e.dispatchEvent(new CustomEvent(H,{detail:e.contentRect}))},[M]);let N={},P=(e,t)=>{t!==void 0&&(N[e]=String(t))};return P(`class`,E),P(`device`,r),P(`os`,a),P(`orientation`,o),P(`cutout`,l),P(`width`,u),P(`height`,d),P(`pixel-ratio`,f),P(`user-agent`,p),P(`status-bar-height`,m),P(`safe-area-top`,h),P(`safe-area-right`,g),P(`safe-area-bottom`,_),P(`safe-area-left`,v),P(`status-bar-text-style`,b),P(`status-bar-background`,x),P(`navigation-bar-height`,S),P(`tab-bar-height`,C),s&&(N.embedded=!0),c&&(N.immersive=!0),y===!1?N[`status-bar`]=`hidden`:typeof y==`string`&&(N[`status-bar`]=y),R.createElement(e,{...D,...N,ref:O},T)});return t.displayName=e===`device-frame`?`DeviceFrame`:`DeviceFrame(${e})`,t}var Ue=He(),We=new Set([`audioListen`]);function Ge(e){return We.has(e)}function Ke(e,t,n,r){let i=e.apiRegistry[t];if(!i)return r({ok:!1,errMsg:`${t}:fail no handler`}),Promise.resolve();let a=Ge(t)||(n&&typeof n==`object`&&!Array.isArray(n)?n.keep===!0:!1);return new Promise(o=>{let s=!1,c=e=>{if(s){a&&e.ok&&r({...e,keep:!0});return}s=!0,r(a&&e.ok?{...e,keep:!0}:e),o()},l=Symbol(`sim-cb-success`),u=Symbol(`sim-cb-fail`),d=Symbol(`sim-cb-complete`),f=!1,p=Object.create(e);p.createCallbackFunction=e=>{if(e!=null)return(e===l||e===u)&&(f=!0),(...n)=>{let r=n[0];e===l?c({ok:!0,result:r}):e===u?c({ok:!1,errMsg:r&&typeof r==`object`&&`errMsg`in r?String(r.errMsg):`${t}:fail`,result:r}):e===d&&!a&&c({ok:!0,result:r})}};let m=n&&typeof n==`object`&&!Array.isArray(n)?{...n}:{};m.success=l,m.fail=u,m.complete=d;try{let e=i.call(p,m);if(e&&typeof e.then==`function`){Promise.resolve(e).then(e=>c({ok:!0,result:e}),e=>{c({ok:!1,errMsg:`${t}:fail ${e instanceof Error?e.message:String(e)}`})});return}if(s)return;if(a){o();return}if(f){o();return}c({ok:!0,result:e})}catch(e){c({ok:!1,errMsg:`${t}:fail ${e instanceof Error?e.message:String(e)}`})}})}function qe(e){return e.onSessionEvent(o.API_CALL,t=>{e.apiRegistry[t.name]&&e.notifyApiResponse({requestId:t.requestId,ok:!1,ack:!0}),Ke(e,t.name,t.params,n=>{e.notifyApiResponse({requestId:t.requestId,ok:n.ok,result:n.result,errMsg:n.errMsg,keep:n.keep})})})}var $=r();function Je({active:e,appId:t}){let r=(0,R.useRef)(null);return(0,R.useEffect)(()=>{let i=r.current;if(!(!e||!i))return n(i,t)},[e,t]),(0,$.jsx)(`div`,{ref:r,className:`device-shell__extension-layer`,"data-dimina-simulator-overlay-root":!0})}function Ye(e,t,n){i({name:`capsule.more`,appId:e,appName:t||e,pagePath:n})}function Xe(e){let t=e.orientation===`landscape`?{width:e.screenHeight,height:e.screenWidth}:{width:e.screenWidth,height:e.screenHeight};return{name:e.device??e.model,os:e.platform,screen:t,pixelRatio:e.pixelRatio,system:e.system,statusBarHeight:e.statusBarHeight,...e.orientation===`landscape`?{safeAreaInsetsLandscape:e.safeAreaInsets}:{safeAreaInsets:e.safeAreaInsets}}}function Ze({textStyle:e,onChange:t}){return(0,R.useEffect)(()=>{t(e)},[e,t]),null}function Qe({miniApp:e,bridgeId:t,active:n=!0}){let r=new URLSearchParams(window.location.search).get(`embedded`)===`1`,[i,s]=(0,R.useState)(()=>e.getInitialDevice());(0,R.useEffect)(()=>e.onSimulatorEvent(o.DEVICE_CHANGE,s),[e]);let[c,l]=(0,R.useState)(`black`),u=r?0:i?.safeAreaInsets.top??T[e.platform].statusBarHeight,d=r?0:i?.safeAreaInsets.bottom??0,f=i?i.platform===`ios`?`ios`:`android`:e.platform,p=i&&!I(i.device)?Xe(i):null;(0,R.useEffect)(()=>qe(e),[e]);let m=(0,R.useCallback)(e=>{Ye(e.appId,e.appName,e.pagePath)},[]);return(0,$.jsx)(`main`,{className:`device-shell-root${r?` device-shell-root--embedded`:``}`,children:(0,$.jsx)(Ue,{device:i?.device,deviceProfile:p,orientation:i?.orientation??`portrait`,embedded:r,immersive:!0,statusBarTextStyle:c,className:`device-shell${r?` device-shell--embedded`:``}`,"aria-label":`Dimina simulator`,children:(0,$.jsx)(`div`,{className:`device-shell__screen`,children:(0,$.jsx)(a,{host:e,bridgeId:t,platform:f,active:n,statusBarHeight:u,bottomInset:d,onMore:m,statusBar:r?void 0:({textStyle:e})=>(0,$.jsx)(Ze,{textStyle:e,onChange:l}),deviceOverlay:(0,$.jsx)(Je,{active:n,appId:e.appId})})})})})}export{Qe as DeviceShell};
|
|
431
|
+
//# sourceMappingURL=device-shell-pxnZZp10.js.map
|