@actview/floating-ui 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/FloatingDelayGroup.d.ts +3 -3
- package/dist/components/FloatingPortal.d.ts +1 -1
- package/dist/components/FloatingTree.d.ts +1 -0
- package/dist/floating-ui.actview.esm.js +106 -89
- package/dist/floating-ui.actview.mjs +106 -89
- package/dist/floating-ui.actview.umd.js +106 -89
- package/dist/floating-ui.actview.umd.min.js +1 -1
- package/package.json +3 -3
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type Ref } from '@actview/core';
|
|
2
1
|
import type { FloatingRootContext } from '../types';
|
|
3
2
|
/**
|
|
4
3
|
* actview 版(upstream 为 React 组件)。
|
|
@@ -28,8 +27,9 @@ interface GroupContext extends GroupState {
|
|
|
28
27
|
/**
|
|
29
28
|
* @deprecated
|
|
30
29
|
* Use the return value of `useDelayGroup()` instead.
|
|
30
|
+
* (store-as-is:use() 原样返回 payload——直读字段,不再 `.value`。)
|
|
31
31
|
*/
|
|
32
|
-
export declare const useDelayGroupContext: () =>
|
|
32
|
+
export declare const useDelayGroupContext: () => GroupContext;
|
|
33
33
|
export interface FloatingDelayGroupProps {
|
|
34
34
|
children?: any;
|
|
35
35
|
/**
|
|
@@ -66,5 +66,5 @@ interface UseGroupOptions {
|
|
|
66
66
|
* `FloatingDelayGroup`.
|
|
67
67
|
* @see https://floating-ui.com/docs/FloatingDelayGroup
|
|
68
68
|
*/
|
|
69
|
-
export declare function useDelayGroup(context: FloatingRootContext, options?: UseGroupOptions):
|
|
69
|
+
export declare function useDelayGroup(context: FloatingRootContext, options?: UseGroupOptions): GroupContext;
|
|
70
70
|
export {};
|
|
@@ -59,5 +59,5 @@ export declare const FloatingPortal: {
|
|
|
59
59
|
__setup: (props: FloatingPortalProps) => () => JSX.Element;
|
|
60
60
|
name?: string;
|
|
61
61
|
} & ((props: FloatingPortalProps) => () => JSX.Element);
|
|
62
|
-
export declare const usePortalContext: () =>
|
|
62
|
+
export declare const usePortalContext: () => PortalContextValue | null;
|
|
63
63
|
export {};
|
|
@@ -3,6 +3,7 @@ import type { FloatingTreeType, ReferenceType } from '../types';
|
|
|
3
3
|
/**
|
|
4
4
|
* Returns the parent node id for nested floating elements, if available.
|
|
5
5
|
* Returns `null` for top-level floating elements.
|
|
6
|
+
* (store-as-is:use() 原样返回 payload——直读字段,不再 `.value`。)
|
|
6
7
|
*/
|
|
7
8
|
export declare const useFloatingParentNodeId: () => string | null;
|
|
8
9
|
/**
|
|
@@ -802,15 +802,20 @@ const FloatingList = defineComponent(function (props) {
|
|
|
802
802
|
});
|
|
803
803
|
return newMap;
|
|
804
804
|
});
|
|
805
|
-
|
|
805
|
+
|
|
806
|
+
// store-as-is 载体:身份稳定的 getter 对象(provide 只在 Provider setup 执行
|
|
807
|
+
// 一次,computed 重建的新对象会冻结快照——map 变化时 use() 仍拿到首帧对象)。
|
|
808
|
+
const contextValue = {
|
|
806
809
|
register,
|
|
807
810
|
unregister,
|
|
808
|
-
map
|
|
811
|
+
get map() {
|
|
812
|
+
return map.value;
|
|
813
|
+
},
|
|
809
814
|
elementsRef,
|
|
810
815
|
labelsRef
|
|
811
|
-
}
|
|
816
|
+
};
|
|
812
817
|
return () => jsx(FloatingListContext.Provider, {
|
|
813
|
-
"value": contextValue
|
|
818
|
+
"value": contextValue,
|
|
814
819
|
"children": props.children
|
|
815
820
|
}, undefined);
|
|
816
821
|
});
|
|
@@ -837,15 +842,15 @@ function useListItem(props) {
|
|
|
837
842
|
// (register 幂等,Set 去重)并立即用重算后的 map 同步 index,保证
|
|
838
843
|
// 挂载后首个事件处理器读到正确的 index。
|
|
839
844
|
if (node) {
|
|
840
|
-
listContext.
|
|
841
|
-
const index = listContext.
|
|
845
|
+
listContext.register(node);
|
|
846
|
+
const index = listContext.map.get(node);
|
|
842
847
|
if (index != null) {
|
|
843
848
|
indexRef.value = index;
|
|
844
|
-
listContext.
|
|
845
|
-
if (listContext.
|
|
849
|
+
listContext.elementsRef.value[index] = node;
|
|
850
|
+
if (listContext.labelsRef) {
|
|
846
851
|
var _node$textContent;
|
|
847
852
|
const isLabelDefined = label !== undefined;
|
|
848
|
-
listContext.
|
|
853
|
+
listContext.labelsRef.value[index] = isLabelDefined ? label : (_node$textContent = node == null ? void 0 : node.textContent) != null ? _node$textContent : null;
|
|
849
854
|
}
|
|
850
855
|
}
|
|
851
856
|
}
|
|
@@ -858,13 +863,13 @@ function useListItem(props) {
|
|
|
858
863
|
watch(() => componentRef.value, () => {
|
|
859
864
|
const node = componentRef.value;
|
|
860
865
|
if (node) {
|
|
861
|
-
listContext.
|
|
866
|
+
listContext.register(node);
|
|
862
867
|
registeredNode = node;
|
|
863
868
|
}
|
|
864
869
|
});
|
|
865
870
|
onUnmounted(() => {
|
|
866
871
|
if (registeredNode) {
|
|
867
|
-
listContext.
|
|
872
|
+
listContext.unregister(registeredNode);
|
|
868
873
|
}
|
|
869
874
|
});
|
|
870
875
|
|
|
@@ -872,16 +877,16 @@ function useListItem(props) {
|
|
|
872
877
|
// React 版靠「ref 回调依赖 index state、依赖变化时 React 重新调用 ref(null)+ref(node)」
|
|
873
878
|
// 写入 elementsRef;actview 的 ref 回调是固定函数不会重建,这里在 index 就绪后
|
|
874
879
|
// 主动同步 elementsRef / labelsRef。
|
|
875
|
-
watch(() => listContext.
|
|
880
|
+
watch(() => listContext.map, () => {
|
|
876
881
|
const node = componentRef.value;
|
|
877
|
-
const index = node ? listContext.
|
|
882
|
+
const index = node ? listContext.map.get(node) : null;
|
|
878
883
|
if (index != null) {
|
|
879
884
|
indexRef.value = index;
|
|
880
|
-
listContext.
|
|
881
|
-
if (listContext.
|
|
885
|
+
listContext.elementsRef.value[index] = node;
|
|
886
|
+
if (listContext.labelsRef) {
|
|
882
887
|
var _node$textContent2;
|
|
883
888
|
const isLabelDefined = label !== undefined;
|
|
884
|
-
listContext.
|
|
889
|
+
listContext.labelsRef.value[index] = isLabelDefined ? label : (_node$textContent2 = node == null ? void 0 : node.textContent) != null ? _node$textContent2 : null;
|
|
885
890
|
}
|
|
886
891
|
}
|
|
887
892
|
});
|
|
@@ -965,10 +970,16 @@ const Composite = defineComponent(function (props) {
|
|
|
965
970
|
}
|
|
966
971
|
};
|
|
967
972
|
const elementsRef = ref([]);
|
|
968
|
-
|
|
969
|
-
|
|
973
|
+
|
|
974
|
+
// store-as-is 载体:身份稳定的 getter 对象(provide 只在 Provider setup 执行
|
|
975
|
+
// 一次,computed 重建的新对象会冻结快照——activeIndex 变化时 use() 仍拿到
|
|
976
|
+
// 首帧对象)。
|
|
977
|
+
const contextValue = {
|
|
978
|
+
get activeIndex() {
|
|
979
|
+
return activeIndex.value;
|
|
980
|
+
},
|
|
970
981
|
onNavigate
|
|
971
|
-
}
|
|
982
|
+
};
|
|
972
983
|
return () => {
|
|
973
984
|
const {
|
|
974
985
|
render,
|
|
@@ -1075,7 +1086,7 @@ const Composite = defineComponent(function (props) {
|
|
|
1075
1086
|
}
|
|
1076
1087
|
};
|
|
1077
1088
|
return jsx(CompositeContext.Provider, {
|
|
1078
|
-
"value": contextValue
|
|
1089
|
+
"value": contextValue,
|
|
1079
1090
|
"children": jsx(FloatingList, {
|
|
1080
1091
|
"elementsRef": rawRef(elementsRef),
|
|
1081
1092
|
"children": renderJsx(render, computedProps)
|
|
@@ -1093,7 +1104,7 @@ const CompositeItem = defineComponent(function (props) {
|
|
|
1093
1104
|
index
|
|
1094
1105
|
} = useListItem();
|
|
1095
1106
|
const mergedRef = useMergeRefs([itemRef, props.ref, renderElementRef()]);
|
|
1096
|
-
const isActive = computed(() => compositeContext.
|
|
1107
|
+
const isActive = computed(() => compositeContext.activeIndex === index.value);
|
|
1097
1108
|
function renderElementRef() {
|
|
1098
1109
|
const r = props.render;
|
|
1099
1110
|
return r && typeof r !== 'function' ? r.props.ref : undefined;
|
|
@@ -1113,7 +1124,7 @@ const CompositeItem = defineComponent(function (props) {
|
|
|
1113
1124
|
onFocus(e) {
|
|
1114
1125
|
domProps.onFocus == null || domProps.onFocus(e);
|
|
1115
1126
|
renderElementProps.onFocus == null || renderElementProps.onFocus(e);
|
|
1116
|
-
compositeContext.
|
|
1127
|
+
compositeContext.onNavigate(index.value);
|
|
1117
1128
|
}
|
|
1118
1129
|
};
|
|
1119
1130
|
return renderJsx(render, computedProps);
|
|
@@ -1348,16 +1359,17 @@ const FloatingTreeContext = createContext(null);
|
|
|
1348
1359
|
/**
|
|
1349
1360
|
* Returns the parent node id for nested floating elements, if available.
|
|
1350
1361
|
* Returns `null` for top-level floating elements.
|
|
1362
|
+
* (store-as-is:use() 原样返回 payload——直读字段,不再 `.value`。)
|
|
1351
1363
|
*/
|
|
1352
1364
|
const useFloatingParentNodeId = () => {
|
|
1353
1365
|
var _FloatingNodeContext$;
|
|
1354
|
-
return ((_FloatingNodeContext$ = FloatingNodeContext.use()
|
|
1366
|
+
return ((_FloatingNodeContext$ = FloatingNodeContext.use()) == null ? void 0 : _FloatingNodeContext$.id) || null;
|
|
1355
1367
|
};
|
|
1356
1368
|
|
|
1357
1369
|
/**
|
|
1358
1370
|
* Returns the nearest floating tree context, if available.
|
|
1359
1371
|
*/
|
|
1360
|
-
const useFloatingTree = () => FloatingTreeContext.use()
|
|
1372
|
+
const useFloatingTree = () => FloatingTreeContext.use();
|
|
1361
1373
|
|
|
1362
1374
|
/**
|
|
1363
1375
|
* Registers a node into the `FloatingTree`, returning its id.
|
|
@@ -1367,10 +1379,7 @@ function useFloatingNodeId(customParentId) {
|
|
|
1367
1379
|
const id = useId();
|
|
1368
1380
|
const tree = useFloatingTree();
|
|
1369
1381
|
const nodeContext = FloatingNodeContext.use();
|
|
1370
|
-
const parentId = computed(() =>
|
|
1371
|
-
var _nodeContext$value;
|
|
1372
|
-
return customParentId || ((_nodeContext$value = nodeContext.value) == null ? void 0 : _nodeContext$value.id) || null;
|
|
1373
|
-
});
|
|
1382
|
+
const parentId = computed(() => customParentId || (nodeContext == null ? void 0 : nodeContext.id) || null);
|
|
1374
1383
|
let added = false;
|
|
1375
1384
|
let node = null;
|
|
1376
1385
|
// immediate:id 由 useId 同步生成(不再变化),非 immediate 的 watch 不会触发;
|
|
@@ -1401,10 +1410,7 @@ function useFloatingNodeId(customParentId) {
|
|
|
1401
1410
|
*/
|
|
1402
1411
|
const FloatingNode = defineComponent(function (props) {
|
|
1403
1412
|
const nodeContext = FloatingNodeContext.use();
|
|
1404
|
-
const parentId = computed(() =>
|
|
1405
|
-
var _nodeContext$value2;
|
|
1406
|
-
return ((_nodeContext$value2 = nodeContext.value) == null ? void 0 : _nodeContext$value2.id) || null;
|
|
1407
|
-
});
|
|
1413
|
+
const parentId = computed(() => (nodeContext == null ? void 0 : nodeContext.id) || null);
|
|
1408
1414
|
return () => jsx(FloatingNodeContext.Provider, {
|
|
1409
1415
|
"value": {
|
|
1410
1416
|
id: props.id,
|
|
@@ -1857,6 +1863,7 @@ const FloatingDelayGroupContext = createContext({
|
|
|
1857
1863
|
/**
|
|
1858
1864
|
* @deprecated
|
|
1859
1865
|
* Use the return value of `useDelayGroup()` instead.
|
|
1866
|
+
* (store-as-is:use() 原样返回 payload——直读字段,不再 `.value`。)
|
|
1860
1867
|
*/
|
|
1861
1868
|
const useDelayGroupContext = () => FloatingDelayGroupContext.use();
|
|
1862
1869
|
/**
|
|
@@ -1909,13 +1916,30 @@ const FloatingDelayGroup = defineComponent(function (props) {
|
|
|
1909
1916
|
initialCurrentIdRef.value = null;
|
|
1910
1917
|
}
|
|
1911
1918
|
});
|
|
1912
|
-
|
|
1913
|
-
|
|
1919
|
+
|
|
1920
|
+
// store-as-is 载体:身份稳定的 getter 对象(provide 只在 Provider setup 执行
|
|
1921
|
+
// 一次,computed 重建的新对象会冻结快照——state 变化时 use() 仍拿到首帧对象)。
|
|
1922
|
+
const contextValue = {
|
|
1923
|
+
get delay() {
|
|
1924
|
+
return state.value.delay;
|
|
1925
|
+
},
|
|
1926
|
+
get initialDelay() {
|
|
1927
|
+
return state.value.initialDelay;
|
|
1928
|
+
},
|
|
1929
|
+
get currentId() {
|
|
1930
|
+
return state.value.currentId;
|
|
1931
|
+
},
|
|
1932
|
+
get timeoutMs() {
|
|
1933
|
+
return state.value.timeoutMs;
|
|
1934
|
+
},
|
|
1935
|
+
get isInstantPhase() {
|
|
1936
|
+
return state.value.isInstantPhase;
|
|
1937
|
+
},
|
|
1914
1938
|
setState,
|
|
1915
1939
|
setCurrentId
|
|
1916
|
-
}
|
|
1940
|
+
};
|
|
1917
1941
|
return () => jsx(FloatingDelayGroupContext.Provider, {
|
|
1918
|
-
"value": contextValue
|
|
1942
|
+
"value": contextValue,
|
|
1919
1943
|
"children": children
|
|
1920
1944
|
}, undefined);
|
|
1921
1945
|
});
|
|
@@ -1941,12 +1965,12 @@ function useDelayGroup(context, options) {
|
|
|
1941
1965
|
const groupContext = useDelayGroupContext();
|
|
1942
1966
|
|
|
1943
1967
|
// React 版 effect [enabled, id, onOpenChange, setState, currentId, initialDelay]
|
|
1944
|
-
watch(() => [enabled, id.value, groupContext.
|
|
1968
|
+
watch(() => [enabled, id.value, groupContext.currentId, groupContext.initialDelay], () => {
|
|
1945
1969
|
const {
|
|
1946
1970
|
currentId,
|
|
1947
1971
|
initialDelay,
|
|
1948
1972
|
setState
|
|
1949
|
-
} = groupContext
|
|
1973
|
+
} = groupContext;
|
|
1950
1974
|
if (!enabled) return;
|
|
1951
1975
|
if (!currentId) return;
|
|
1952
1976
|
setState({
|
|
@@ -1962,11 +1986,11 @@ function useDelayGroup(context, options) {
|
|
|
1962
1986
|
|
|
1963
1987
|
// React 版 effect [enabled, open, setState, currentId, id, onOpenChange,
|
|
1964
1988
|
// initialDelay, timeoutMs]
|
|
1965
|
-
watch(() => [enabled, open.value, groupContext.
|
|
1989
|
+
watch(() => [enabled, open.value, groupContext.currentId, groupContext.initialDelay, groupContext.timeoutMs], () => {
|
|
1966
1990
|
function unset() {
|
|
1967
1991
|
onOpenChange(false);
|
|
1968
|
-
groupContext.
|
|
1969
|
-
delay: groupContext.
|
|
1992
|
+
groupContext.setState({
|
|
1993
|
+
delay: groupContext.initialDelay,
|
|
1970
1994
|
currentId: null
|
|
1971
1995
|
});
|
|
1972
1996
|
}
|
|
@@ -1975,7 +1999,7 @@ function useDelayGroup(context, options) {
|
|
|
1975
1999
|
timeoutMs,
|
|
1976
2000
|
setState,
|
|
1977
2001
|
initialDelay
|
|
1978
|
-
} = groupContext
|
|
2002
|
+
} = groupContext;
|
|
1979
2003
|
if (!enabled) return;
|
|
1980
2004
|
if (!currentId) return;
|
|
1981
2005
|
if (!open.value && currentId === id.value) {
|
|
@@ -1993,8 +2017,8 @@ function useDelayGroup(context, options) {
|
|
|
1993
2017
|
// React 版 effect [enabled, open, setCurrentId, id]
|
|
1994
2018
|
watch(() => [enabled, open.value, id.value], () => {
|
|
1995
2019
|
if (!enabled) return;
|
|
1996
|
-
if (groupContext.
|
|
1997
|
-
groupContext.
|
|
2020
|
+
if (groupContext.setCurrentId === NOOP || !open.value) return;
|
|
2021
|
+
groupContext.setCurrentId(id.value);
|
|
1998
2022
|
});
|
|
1999
2023
|
return groupContext;
|
|
2000
2024
|
}
|
|
@@ -2039,7 +2063,10 @@ const NextFloatingDelayGroup = defineComponent(function (props) {
|
|
|
2039
2063
|
const currentIdRef = ref(null);
|
|
2040
2064
|
const currentContextRef = ref(null);
|
|
2041
2065
|
const timeoutIdRef = ref(-1);
|
|
2042
|
-
|
|
2066
|
+
|
|
2067
|
+
// store-as-is 载体:身份稳定的对象(字段全是 ref 容器,字段引用不变、
|
|
2068
|
+
// 消费方读 `.value` 实时;computed 重建的新对象会冻结快照)。
|
|
2069
|
+
const contextValue = {
|
|
2043
2070
|
hasProvider: true,
|
|
2044
2071
|
delayRef,
|
|
2045
2072
|
initialDelayRef,
|
|
@@ -2047,9 +2074,9 @@ const NextFloatingDelayGroup = defineComponent(function (props) {
|
|
|
2047
2074
|
timeoutMs,
|
|
2048
2075
|
currentContextRef,
|
|
2049
2076
|
timeoutIdRef
|
|
2050
|
-
}
|
|
2077
|
+
};
|
|
2051
2078
|
return () => jsx(NextFloatingDelayGroupContext.Provider, {
|
|
2052
|
-
"value": contextValue
|
|
2079
|
+
"value": contextValue,
|
|
2053
2080
|
"children": children
|
|
2054
2081
|
}, undefined);
|
|
2055
2082
|
});
|
|
@@ -2079,7 +2106,7 @@ function useNextDelayGroup(context, options) {
|
|
|
2079
2106
|
currentContextRef,
|
|
2080
2107
|
hasProvider,
|
|
2081
2108
|
timeoutIdRef
|
|
2082
|
-
} = groupContext
|
|
2109
|
+
} = groupContext;
|
|
2083
2110
|
const isInstantPhase = ref(false);
|
|
2084
2111
|
|
|
2085
2112
|
// React 版 effect [enabled, open, floatingId, ...]:unset / timeout
|
|
@@ -2404,11 +2431,7 @@ function useFloatingPortalNode(props) {
|
|
|
2404
2431
|
// React 版两个创建 effect(id 分支 + root 分支)。
|
|
2405
2432
|
// immediate:uniqueId 由 useId 同步生成(不再变化),非 immediate 的 watch
|
|
2406
2433
|
// 不会触发(依赖不变),portalNode 将永不创建。
|
|
2407
|
-
watch(() => {
|
|
2408
|
-
var _portalContext$value;
|
|
2409
|
-
return [id, uniqueId.value, toValue(root), (_portalContext$value = portalContext.value) == null ? void 0 : _portalContext$value.portalNode];
|
|
2410
|
-
}, () => {
|
|
2411
|
-
var _portalContext$value2;
|
|
2434
|
+
watch(() => [id, uniqueId.value, toValue(root), portalContext == null ? void 0 : portalContext.portalNode], () => {
|
|
2412
2435
|
// Wait for the uniqueId to be generated before creating the portal node
|
|
2413
2436
|
// (mirroring React <18 `useFloatingId` semantics).
|
|
2414
2437
|
// https://github.com/floating-ui/floating-ui/issues/2778
|
|
@@ -2430,7 +2453,7 @@ function useFloatingPortalNode(props) {
|
|
|
2430
2453
|
// `root` 分支:root / 父 portal 节点 / body
|
|
2431
2454
|
const rootValue = toValue(root);
|
|
2432
2455
|
if (rootValue === null) return;
|
|
2433
|
-
let container = rootValue || (
|
|
2456
|
+
let container = rootValue || (portalContext == null ? void 0 : portalContext.portalNode);
|
|
2434
2457
|
container = container || document.body;
|
|
2435
2458
|
let idWrapper = null;
|
|
2436
2459
|
if (id) {
|
|
@@ -2533,17 +2556,19 @@ const FloatingPortal = defineComponent(function (props) {
|
|
|
2533
2556
|
onUnmounted(() => {
|
|
2534
2557
|
cleanupFocusListeners == null || cleanupFocusListeners();
|
|
2535
2558
|
});
|
|
2536
|
-
const contextValue =
|
|
2559
|
+
const contextValue = {
|
|
2537
2560
|
preserveTabOrder,
|
|
2538
2561
|
beforeOutsideRef,
|
|
2539
2562
|
afterOutsideRef,
|
|
2540
2563
|
beforeInsideRef,
|
|
2541
2564
|
afterInsideRef,
|
|
2542
|
-
portalNode
|
|
2565
|
+
get portalNode() {
|
|
2566
|
+
return portalNode.value;
|
|
2567
|
+
},
|
|
2543
2568
|
setFocusManagerState
|
|
2544
|
-
}
|
|
2569
|
+
};
|
|
2545
2570
|
return () => jsx(PortalContext.Provider, {
|
|
2546
|
-
"value": contextValue
|
|
2571
|
+
"value": contextValue,
|
|
2547
2572
|
"children": [shouldRenderGuards.value && portalNode.value && jsx(FocusGuard, {
|
|
2548
2573
|
"data-type": "outside",
|
|
2549
2574
|
"ref": beforeOutsideRef,
|
|
@@ -2821,7 +2846,7 @@ const FloatingFocusManager = defineComponent(function (props) {
|
|
|
2821
2846
|
// disabled/open 变化会触发多次 watch 重跑,若为周期局部变量,后续周期的
|
|
2822
2847
|
// cleanup 会读到 ''(丢失 Escape 的 'keyboard'),returnFocus 函数参数错。
|
|
2823
2848
|
const closeTypeRef = ref('');
|
|
2824
|
-
const isInsidePortal = computed(() => portalContext
|
|
2849
|
+
const isInsidePortal = computed(() => portalContext != null);
|
|
2825
2850
|
const floatingFocusElement = computed(() => getFloatingFocusElement(floating.value));
|
|
2826
2851
|
const getTabbableContent = function (container) {
|
|
2827
2852
|
if (container === void 0) {
|
|
@@ -2905,7 +2930,7 @@ const FloatingFocusManager = defineComponent(function (props) {
|
|
|
2905
2930
|
// 依赖含 disabled:keepMounted 场景初始 disabled=true 时跳过注册,
|
|
2906
2931
|
// 打开(disabled=false)后需重新注册 focusout 监听。
|
|
2907
2932
|
let cleanupFocusOut;
|
|
2908
|
-
watch([domReference, floating, portalContext, disabled], () => {
|
|
2933
|
+
watch(() => [domReference.value, floating.value, portalContext == null ? void 0 : portalContext.portalNode, disabled.value], () => {
|
|
2909
2934
|
cleanupFocusOut == null || cleanupFocusOut();
|
|
2910
2935
|
cleanupFocusOut = undefined;
|
|
2911
2936
|
if (disabled.value) return;
|
|
@@ -2923,9 +2948,9 @@ const FloatingFocusManager = defineComponent(function (props) {
|
|
|
2923
2948
|
const currentTarget = event.currentTarget;
|
|
2924
2949
|
const target = getTarget(event);
|
|
2925
2950
|
queueMicrotask(() => {
|
|
2926
|
-
var _portalContext$
|
|
2951
|
+
var _portalContext$portal;
|
|
2927
2952
|
const nodeId = getNodeId();
|
|
2928
|
-
const movedToUnrelatedNode = !(contains(domReference.value, relatedTarget) || contains(floating.value, relatedTarget) || contains(relatedTarget, floating.value) || contains((_portalContext$
|
|
2953
|
+
const movedToUnrelatedNode = !(contains(domReference.value, relatedTarget) || contains(floating.value, relatedTarget) || contains(relatedTarget, floating.value) || contains((_portalContext$portal = portalContext == null ? void 0 : portalContext.portalNode) != null ? _portalContext$portal : null, relatedTarget) || relatedTarget != null && relatedTarget.hasAttribute(createAttribute('focus-guard')) || tree && (getNodeChildren(tree.nodesRef.value, nodeId).find(node => {
|
|
2929
2954
|
var _node$context, _node$context2;
|
|
2930
2955
|
return contains((_node$context = node.context) == null ? void 0 : _node$context.elements.floating.value, relatedTarget) || contains((_node$context2 = node.context) == null ? void 0 : _node$context2.elements.domReference.value, relatedTarget);
|
|
2931
2956
|
}) || getNodeAncestors(tree.nodesRef.value, nodeId).find(node => {
|
|
@@ -2978,7 +3003,7 @@ const FloatingFocusManager = defineComponent(function (props) {
|
|
|
2978
3003
|
}
|
|
2979
3004
|
});
|
|
2980
3005
|
}
|
|
2981
|
-
const shouldHandleBlurCapture = Boolean(!tree && portalContext
|
|
3006
|
+
const shouldHandleBlurCapture = Boolean(!tree && portalContext);
|
|
2982
3007
|
function markInsideReactTree() {
|
|
2983
3008
|
clearTimeoutIfSet(blurTimeoutRef);
|
|
2984
3009
|
dataRef.value.insideReactTree = true;
|
|
@@ -3008,32 +3033,26 @@ const FloatingFocusManager = defineComponent(function (props) {
|
|
|
3008
3033
|
});
|
|
3009
3034
|
const beforeGuardRef = ref(null);
|
|
3010
3035
|
const afterGuardRef = ref(null);
|
|
3011
|
-
const mergedBeforeGuardRef = useLiteMergeRefs([beforeGuardRef, () =>
|
|
3012
|
-
|
|
3013
|
-
return (_portalContext$value2 = portalContext.value) == null ? void 0 : _portalContext$value2.beforeInsideRef;
|
|
3014
|
-
}]);
|
|
3015
|
-
const mergedAfterGuardRef = useLiteMergeRefs([afterGuardRef, () => {
|
|
3016
|
-
var _portalContext$value3;
|
|
3017
|
-
return (_portalContext$value3 = portalContext.value) == null ? void 0 : _portalContext$value3.afterInsideRef;
|
|
3018
|
-
}]);
|
|
3036
|
+
const mergedBeforeGuardRef = useLiteMergeRefs([beforeGuardRef, () => portalContext == null ? void 0 : portalContext.beforeInsideRef]);
|
|
3037
|
+
const mergedAfterGuardRef = useLiteMergeRefs([afterGuardRef, () => portalContext == null ? void 0 : portalContext.afterInsideRef]);
|
|
3019
3038
|
|
|
3020
3039
|
// React 版 effect:markOthers(inert / aria-hidden)
|
|
3021
3040
|
let cleanupMarkOthers;
|
|
3022
|
-
watch([domReference, floating, portalContext], () => {
|
|
3023
|
-
var _portalContext$
|
|
3041
|
+
watch(() => [domReference.value, floating.value, portalContext == null ? void 0 : portalContext.portalNode], () => {
|
|
3042
|
+
var _portalContext$portal2, _ancestors$find;
|
|
3024
3043
|
cleanupMarkOthers == null || cleanupMarkOthers();
|
|
3025
3044
|
cleanupMarkOthers = undefined;
|
|
3026
3045
|
if (disabled.value) return;
|
|
3027
3046
|
if (!floating.value) return;
|
|
3028
3047
|
|
|
3029
3048
|
// Don't hide portals nested within the parent portal.
|
|
3030
|
-
const portalNodes = Array.from((
|
|
3049
|
+
const portalNodes = Array.from((portalContext == null || (_portalContext$portal2 = portalContext.portalNode) == null ? void 0 : _portalContext$portal2.querySelectorAll("[" + createAttribute('portal') + "]")) || []);
|
|
3031
3050
|
const ancestors = tree ? getNodeAncestors(tree.nodesRef.value, getNodeId()) : [];
|
|
3032
3051
|
const rootAncestorComboboxDomReference = (_ancestors$find = ancestors.find(node => {
|
|
3033
3052
|
var _node$context6;
|
|
3034
3053
|
return isTypeableCombobox(((_node$context6 = node.context) == null ? void 0 : _node$context6.elements.domReference.value) || null);
|
|
3035
3054
|
})) == null || (_ancestors$find = _ancestors$find.context) == null ? void 0 : _ancestors$find.elements.domReference.value;
|
|
3036
|
-
const insideElements = [floating.value, rootAncestorComboboxDomReference, ...portalNodes, ...getInsideElements(), startDismissButtonRef.value, endDismissButtonRef.value, beforeGuardRef.value, afterGuardRef.value,
|
|
3055
|
+
const insideElements = [floating.value, rootAncestorComboboxDomReference, ...portalNodes, ...getInsideElements(), startDismissButtonRef.value, endDismissButtonRef.value, beforeGuardRef.value, afterGuardRef.value, portalContext == null ? void 0 : portalContext.beforeOutsideRef.value, portalContext == null ? void 0 : portalContext.afterOutsideRef.value, orderRef.value.includes('reference') || isUntrappedTypeableCombobox.value ? domReference.value : null].filter(x => x != null);
|
|
3037
3056
|
cleanupMarkOthers = modal.value || isUntrappedTypeableCombobox.value ? markOthers(insideElements, !useInert.value, useInert.value) : markOthers(insideElements);
|
|
3038
3057
|
});
|
|
3039
3058
|
|
|
@@ -3216,9 +3235,9 @@ const FloatingFocusManager = defineComponent(function (props) {
|
|
|
3216
3235
|
// React 版 `useModernLayoutEffect`:同步 context & modal 到 FloatingPortal
|
|
3217
3236
|
// 注意:open 在 FFM 挂载前已为 true,watch 无 immediate 时首次不触发,
|
|
3218
3237
|
// FloatingPortal 的 focusManagerState 保持 null(owner/guard 不渲染)。
|
|
3219
|
-
watch([portalContext, open, domReference], () => {
|
|
3238
|
+
watch(() => [portalContext == null ? void 0 : portalContext.portalNode, open.value, domReference.value], () => {
|
|
3220
3239
|
if (disabled.value) return;
|
|
3221
|
-
const currentPortal = portalContext
|
|
3240
|
+
const currentPortal = portalContext;
|
|
3222
3241
|
if (!currentPortal) return;
|
|
3223
3242
|
currentPortal.setFocusManagerState({
|
|
3224
3243
|
modal: modal.value,
|
|
@@ -3268,19 +3287,18 @@ const FloatingFocusManager = defineComponent(function (props) {
|
|
|
3268
3287
|
"data-type": "inside",
|
|
3269
3288
|
"ref": mergedBeforeGuardRef,
|
|
3270
3289
|
"onFocus": event => {
|
|
3271
|
-
var _portalContext$value7;
|
|
3272
3290
|
if (modal.value) {
|
|
3273
3291
|
const els = getTabbableElements();
|
|
3274
3292
|
enqueueFocus(order.value[0] === 'reference' ? els[0] : els[els.length - 1]);
|
|
3275
|
-
} else if (
|
|
3276
|
-
var _portalContext$
|
|
3293
|
+
} else if (portalContext != null && portalContext.preserveTabOrder && portalContext.portalNode) {
|
|
3294
|
+
var _portalContext$portal3;
|
|
3277
3295
|
preventReturnFocusRef.value = false;
|
|
3278
|
-
if (isOutsideEvent(event, (_portalContext$
|
|
3296
|
+
if (isOutsideEvent(event, (_portalContext$portal3 = portalContext.portalNode) != null ? _portalContext$portal3 : undefined)) {
|
|
3279
3297
|
const nextTabbable = getNextTabbable(domReference.value);
|
|
3280
3298
|
nextTabbable == null || nextTabbable.focus();
|
|
3281
3299
|
} else {
|
|
3282
|
-
var _portalContext$
|
|
3283
|
-
(_portalContext$
|
|
3300
|
+
var _portalContext$before;
|
|
3301
|
+
(_portalContext$before = portalContext.beforeOutsideRef.value) == null || _portalContext$before.focus();
|
|
3284
3302
|
}
|
|
3285
3303
|
}
|
|
3286
3304
|
}
|
|
@@ -3288,20 +3306,19 @@ const FloatingFocusManager = defineComponent(function (props) {
|
|
|
3288
3306
|
"data-type": "inside",
|
|
3289
3307
|
"ref": mergedAfterGuardRef,
|
|
3290
3308
|
"onFocus": event => {
|
|
3291
|
-
var _portalContext$value8;
|
|
3292
3309
|
if (modal.value) {
|
|
3293
3310
|
enqueueFocus(getTabbableElements()[0]);
|
|
3294
|
-
} else if (
|
|
3295
|
-
var _portalContext$
|
|
3311
|
+
} else if (portalContext != null && portalContext.preserveTabOrder && portalContext.portalNode) {
|
|
3312
|
+
var _portalContext$portal4;
|
|
3296
3313
|
if (closeOnFocusOut.value) {
|
|
3297
3314
|
preventReturnFocusRef.value = true;
|
|
3298
3315
|
}
|
|
3299
|
-
if (isOutsideEvent(event, (_portalContext$
|
|
3316
|
+
if (isOutsideEvent(event, (_portalContext$portal4 = portalContext.portalNode) != null ? _portalContext$portal4 : undefined)) {
|
|
3300
3317
|
const prevTabbable = getPreviousTabbable(domReference.value);
|
|
3301
3318
|
prevTabbable == null || prevTabbable.focus();
|
|
3302
3319
|
} else {
|
|
3303
|
-
var _portalContext$
|
|
3304
|
-
(_portalContext$
|
|
3320
|
+
var _portalContext$afterO;
|
|
3321
|
+
(_portalContext$afterO = portalContext.afterOutsideRef.value) == null || _portalContext$afterO.focus();
|
|
3305
3322
|
}
|
|
3306
3323
|
}
|
|
3307
3324
|
}
|