@uniai-fe/uds-templates 0.12.2 → 0.12.3
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 +12 -6
- package/package.json +7 -7
- package/src/cctv/hooks/useFullscreen.ts +25 -23
- package/src/cctv/types/hook.ts +3 -3
package/README.md
CHANGED
|
@@ -45,13 +45,19 @@ import { Frame, Modal } from "@uniai-fe/uds-templates";
|
|
|
45
45
|
화면 방향 API를 지원하면 전체화면 동안 `landscape`를 요청하며, 종료·대상 제거 시
|
|
46
46
|
고정을 해제해 기본 방향 정책으로 돌아간다. 세로 방향 복귀를 강제하지 않는다.
|
|
47
47
|
방향 API 미지원·요청 거부는 전체화면 시청을 차단하지 않는다.
|
|
48
|
-
진입 요청 대기 중 대상이 교체·제거되면
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
`useCctvFullscreen({ fallback: "viewport" })`는 표준 Fullscreen API
|
|
52
|
-
페이지 안 전체창
|
|
48
|
+
표준 API 요청 성공 여부를 반환하며, 진입 요청 대기 중 대상이 교체·제거되면
|
|
49
|
+
해당 대상의 가로 방향 고정을 추가로 요청하지 않는다.
|
|
50
|
+
|
|
51
|
+
`useCctvFullscreen({ fallback: "viewport" })`는 iPhone·iPad에서 표준 Fullscreen API를
|
|
52
|
+
호출하지 않고 페이지 안 전체창 확대로 바로 진입한다. Mac·Windows·Android와 그 외 환경은
|
|
53
|
+
표준 API를 사용하며, 미지원·요청 거부 시 전체창 확대로 전환하지 않는다.
|
|
54
|
+
기기 판정은 기존 `checkAppleDevice`와 iPhone·iPad UA를 사용하고, Macintosh UA의 iPad는
|
|
55
|
+
`maxTouchPoints > 1`로 보완한다. UA·터치 정보에 기반한 판정이므로 위장된 UA까지 보장하지 않는다.
|
|
56
|
+
`isFullscreenSupported`와 `isFullscreen`은
|
|
53
57
|
표준 API의 의미를 유지하며, 전체창 확대는 `isViewportExpanded`로 구분한다.
|
|
54
|
-
옵션을 생략하면
|
|
58
|
+
옵션을 생략하면 iPhone·iPad도 표준 API만 사용한다.
|
|
59
|
+
전체창 확대는 현재 연결된 대상만 허용하며, 다른 viewer가 전체화면·전체창 확대를 소유하면
|
|
60
|
+
진입하지 않는다.
|
|
55
61
|
|
|
56
62
|
서비스는 같은 `targetRef` container에 `isViewportExpanded`에 따른 viewport 고정,
|
|
57
63
|
크기·안전 영역·반응형 스타일을 적용한다. 브라우저 UI를 숨기거나 기기 방향을 강제하지 않는다.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniai-fe/uds-templates",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"description": "UNIAI Design System; UI Templates Package",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -67,17 +67,17 @@
|
|
|
67
67
|
"react-hook-form": "^7.84.0",
|
|
68
68
|
"sass": "^1.101.7",
|
|
69
69
|
"typescript": "6.0.3",
|
|
70
|
+
"@uniai-fe/next-devkit": "0.4.0",
|
|
70
71
|
"@uniai-fe/react-hooks": "0.3.0",
|
|
71
|
-
"@uniai-fe/eslint-config": "0.4.2",
|
|
72
72
|
"@uniai-fe/tsconfig": "0.2.0",
|
|
73
|
+
"@uniai-fe/eslint-config": "0.4.2",
|
|
73
74
|
"@uniai-fe/uds-foundation": "0.6.0",
|
|
74
75
|
"@uniai-fe/uds-primitives": "0.12.5",
|
|
75
|
-
"@uniai-fe/util-jotai": "0.3.0",
|
|
76
|
-
"@uniai-fe/util-api": "0.2.1",
|
|
77
76
|
"@uniai-fe/util-next": "0.5.0",
|
|
78
|
-
"@uniai-fe/
|
|
79
|
-
"@uniai-fe/util-
|
|
80
|
-
"@uniai-fe/util-rtc": "0.2.1"
|
|
77
|
+
"@uniai-fe/util-api": "0.2.1",
|
|
78
|
+
"@uniai-fe/util-jotai": "0.3.0",
|
|
79
|
+
"@uniai-fe/util-rtc": "0.2.1",
|
|
80
|
+
"@uniai-fe/util-functions": "0.4.3"
|
|
81
81
|
},
|
|
82
82
|
"scripts": {
|
|
83
83
|
"check:pre-commit": "pnpm --dir ../../.. run check:pre-commit",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
import { checkAppleDevice } from "@uniai-fe/util-functions/runtime-env";
|
|
4
5
|
import type {
|
|
5
6
|
UseCctvFullscreenParams,
|
|
6
7
|
UseCctvFullscreenReturn,
|
|
@@ -13,14 +14,14 @@ const viewportOwners = new WeakMap<Document, HTMLElement>();
|
|
|
13
14
|
* CCTV; service-owned viewer container fullscreen state
|
|
14
15
|
* @hook
|
|
15
16
|
* @desc 대상 element의 표준 Fullscreen API 지원 여부와 실제 document 상태를 동기화한다.
|
|
16
|
-
*
|
|
17
|
+
* 외부 종료 후에는 진입 전 focus를 복원하며, 표준 API 요청 실패는 기존 viewer를 유지한다.
|
|
17
18
|
* 지원 환경에서는 진입 후 가로 방향을 요청하고 종료·대상 제거 시 기본 방향 정책으로 돌려준다.
|
|
18
19
|
* 방향 요청 실패는 전체화면 성공에 영향을 주지 않으며 종료 후 세로 방향을 강제하지 않는다.
|
|
19
|
-
* fallback이 "viewport"이면 표준 API
|
|
20
|
+
* fallback이 "viewport"이면 iPhone·iPad에서 표준 API 대신 전체창 확대와 배경 scroll·focus를 관리한다.
|
|
21
|
+
* 그 외 환경과 옵션을 생략한 호출은 표준 API를 사용한다.
|
|
20
22
|
* 실제 확대 layout은 서비스가 isViewportExpanded로 적용하며 영상 DOM을 이동하거나 다시 만들지 않는다.
|
|
21
|
-
*
|
|
22
|
-
* @
|
|
23
|
-
* @property {"viewport"} [options.fallback] "viewport"는 전체창 확대를 허용한다. 생략하면 표준 API만 사용한다.
|
|
23
|
+
* @param {UseCctvFullscreenParams} options iPhone·iPad의 확대 정책
|
|
24
|
+
* @property {"viewport"} [options.fallback] "viewport"는 iPhone·iPad에서 전체창 확대를 사용한다. 생략하면 표준 API만 사용한다.
|
|
24
25
|
* @return {UseCctvFullscreenReturn} 대상 ref callback과 전체화면 상태·action
|
|
25
26
|
*/
|
|
26
27
|
export function useCctvFullscreen({
|
|
@@ -148,7 +149,7 @@ export function useCctvFullscreen({
|
|
|
148
149
|
]);
|
|
149
150
|
|
|
150
151
|
/**
|
|
151
|
-
*
|
|
152
|
+
* iPhone·iPad의 선택한 전체창 확대와 나머지 환경의 표준 전체화면을 구분한다.
|
|
152
153
|
*/
|
|
153
154
|
const enterFullscreen = useCallback(async () => {
|
|
154
155
|
const target = targetElementRef.current;
|
|
@@ -163,18 +164,19 @@ export function useCctvFullscreen({
|
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
const ownerDocument = target.ownerDocument;
|
|
166
|
-
|
|
167
|
+
const deviceNavigator = ownerDocument.defaultView?.navigator;
|
|
168
|
+
const userAgent = deviceNavigator?.userAgent ?? "";
|
|
169
|
+
// iPad의 데스크톱 UA는 Mac과 같으므로 Macintosh UA에 한해 다중 터치 정보를 보완한다.
|
|
170
|
+
const isIPhoneOrIPad: boolean =
|
|
171
|
+
checkAppleDevice(userAgent) &&
|
|
172
|
+
(/\((?:iPhone|iPad)(?:;|\))/i.test(userAgent) ||
|
|
173
|
+
(/Macintosh/i.test(userAgent) &&
|
|
174
|
+
(deviceNavigator?.maxTouchPoints ?? 0) > 1));
|
|
175
|
+
const useViewport: boolean = fallback === "viewport" && isIPhoneOrIPad;
|
|
167
176
|
const isNativeSupported =
|
|
168
177
|
ownerDocument.fullscreenEnabled &&
|
|
169
178
|
typeof target.requestFullscreen === "function";
|
|
170
|
-
if (
|
|
171
|
-
!isNativeSupported &&
|
|
172
|
-
(fallback !== "viewport" ||
|
|
173
|
-
!target.isConnected ||
|
|
174
|
-
ownerDocument.fullscreenElement)
|
|
175
|
-
) {
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
179
|
+
if (!useViewport && !isNativeSupported) return false;
|
|
178
180
|
const activeElement = ownerDocument.activeElement;
|
|
179
181
|
const ElementConstructor = ownerDocument.defaultView?.HTMLElement;
|
|
180
182
|
entryFocusRef.current =
|
|
@@ -182,7 +184,13 @@ export function useCctvFullscreen({
|
|
|
182
184
|
? activeElement
|
|
183
185
|
: null;
|
|
184
186
|
|
|
185
|
-
if (
|
|
187
|
+
if (useViewport) {
|
|
188
|
+
if (
|
|
189
|
+
!target.isConnected ||
|
|
190
|
+
ownerDocument.fullscreenElement ||
|
|
191
|
+
viewportOwners.has(ownerDocument)
|
|
192
|
+
)
|
|
193
|
+
return false;
|
|
186
194
|
const restores: (() => void)[] = [];
|
|
187
195
|
viewportOwners.set(ownerDocument, target);
|
|
188
196
|
|
|
@@ -279,15 +287,9 @@ export function useCctvFullscreen({
|
|
|
279
287
|
|
|
280
288
|
try {
|
|
281
289
|
await target.requestFullscreen();
|
|
282
|
-
// 대상 정리 뒤 완료된 요청은 이전 화면을 남기지 않되 새 대상의 전체화면은 보존한다.
|
|
283
|
-
if (targetElementRef.current !== target) {
|
|
284
|
-
if (ownerDocument.fullscreenElement === target) {
|
|
285
|
-
await ownerDocument.exitFullscreen().catch(() => undefined);
|
|
286
|
-
}
|
|
287
|
-
return false;
|
|
288
|
-
}
|
|
289
290
|
const orientation = target.ownerDocument.defaultView?.screen.orientation;
|
|
290
291
|
if (
|
|
292
|
+
targetElementRef.current === target &&
|
|
291
293
|
target.ownerDocument.fullscreenElement === target &&
|
|
292
294
|
typeof orientation?.lock === "function" &&
|
|
293
295
|
typeof orientation.unlock === "function"
|
package/src/cctv/types/hook.ts
CHANGED
|
@@ -14,12 +14,12 @@ import type { UseFormReturn } from "react-hook-form";
|
|
|
14
14
|
import type { CctvBaseContext } from "./context";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* CCTV;
|
|
18
|
-
* @property {"viewport"} [fallback] "viewport"는 표준 API
|
|
17
|
+
* CCTV; iPhone·iPad의 확대 정책
|
|
18
|
+
* @property {"viewport"} [fallback] "viewport"는 iPhone·iPad에서 표준 API 대신 서비스의 전체창 확대 스타일을 사용한다. 그 외 환경과 생략한 호출은 표준 API만 사용한다.
|
|
19
19
|
*/
|
|
20
20
|
export interface UseCctvFullscreenParams {
|
|
21
21
|
/**
|
|
22
|
-
* "viewport"는
|
|
22
|
+
* "viewport"는 iPhone·iPad에서 전체창 확대로 바로 진입한다. 그 외 환경과 생략한 호출은 표준 API만 사용한다.
|
|
23
23
|
*/
|
|
24
24
|
fallback?: "viewport";
|
|
25
25
|
}
|