@undefineds.co/xpod 0.4.17 → 0.4.18
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/config/xpod.base.json +3 -0
- package/dist/components/context.jsonld +14 -0
- package/dist/identity/ValidatingIdentityProviderHttpHandler.d.ts +32 -1
- package/dist/identity/ValidatingIdentityProviderHttpHandler.js +53 -1
- package/dist/identity/ValidatingIdentityProviderHttpHandler.jsonld +53 -0
- package/node_modules/@undefineds.co/ai-connections/dist/AiClientConfigurationSection.js +39 -10
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsList.js +15 -4
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.d.ts +1 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiConnectionsPanel.js +4 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeyRow.d.ts +5 -1
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeyRow.js +2 -2
- package/node_modules/@undefineds.co/ai-connections/dist/AiGatewayKeysSection.js +5 -1
- package/node_modules/@undefineds.co/ai-connections/dist/controller.d.ts +4 -0
- package/node_modules/@undefineds.co/ai-connections/dist/controller.js +3 -1
- package/node_modules/@undefineds.co/extension-sdk/dist/layout.d.ts +39 -0
- package/node_modules/@undefineds.co/extension-sdk/dist/layout.js +40 -0
- package/node_modules/@undefineds.co/extension-sdk/dist/react/app-layout.d.ts +13 -1
- package/node_modules/@undefineds.co/extension-sdk/dist/react/app-layout.js +11 -3
- package/node_modules/@undefineds.co/extension-sdk/dist/react/workspace-layout.d.ts +13 -4
- package/node_modules/@undefineds.co/extension-sdk/dist/react/workspace-layout.js +68 -11
- package/node_modules/@undefineds.co/shared-ui/dist/auth-surface.js +6 -6
- package/node_modules/@undefineds.co/shared-ui/dist/dialog.js +4 -4
- package/node_modules/@undefineds.co/shared-ui/dist/login.js +1 -1
- package/node_modules/@undefineds.co/shared-ui/dist/theme.css +128 -79
- package/node_modules/@undefineds.co/shared-ui/dist/toast.js +1 -1
- package/node_modules/@undefineds.co/shared-ui/dist/tooltip.js +1 -1
- package/node_modules/@undefineds.co/solid-sdk/dist/access-route.cjs +87 -9
- package/node_modules/@undefineds.co/solid-sdk/dist/access-route.d.ts +31 -3
- package/node_modules/@undefineds.co/solid-sdk/dist/access-route.js +156 -14
- package/node_modules/@undefineds.co/solid-sdk/dist/index.cjs +86 -8
- package/package.json +2 -2
- package/static/app/assets/global.css +1 -0
- package/static/app/assets/{index-BCZVzMpj.js → index-BeAi28iA.js} +1 -1
- package/static/app/assets/inrupt-smoke.js +37 -36
- package/static/app/assets/main.js +3 -3
- package/static/app/index.html +2 -2
- package/static/app/inrupt-smoke.html +2 -1
- package/static/dashboard/assets/{AiConfigContext-BedwuLTE.js → AiConfigContext-DelSqO6L.js} +1 -1
- package/static/dashboard/assets/{AiConfigPage-hNTayf8G.js → AiConfigPage-dbg0aDvd.js} +1 -1
- package/static/dashboard/assets/DocumentProcessingPanel-0-3nlwQf.js +1 -0
- package/static/dashboard/assets/IndexLifecyclePanel-DOI3IxOD.js +1 -0
- package/static/dashboard/assets/{IndexSubjectPanel-Bv97-ouZ.js → IndexSubjectPanel-ClDgj0SY.js} +1 -1
- package/static/dashboard/assets/ModelAssignmentsPanel-BSWH19oT.js +1 -0
- package/static/dashboard/assets/ModelsPage-BrzxCkEl.js +11 -0
- package/static/{settings/assets/NetworkPage-D50kdbEu.js → dashboard/assets/NetworkPage-CxEKeaPz.js} +2 -2
- package/static/dashboard/assets/{PaneListHeader-ByqK_C6i.js → PaneListHeader-xEjcBu9g.js} +1 -1
- package/static/dashboard/assets/SearchIndexingPanel-BGlSvEl5.js +1 -0
- package/static/dashboard/assets/{StatusSubjectPanel-DPegcFpA.js → StatusSubjectPanel-6s3JXbOd.js} +1 -1
- package/static/dashboard/assets/StatusWorkspace-LYMDa4b0.js +1 -0
- package/static/dashboard/assets/{SystemSettingsPage-LyXmd6uP.js → SystemSettingsPage-CF_vH-qe.js} +1 -1
- package/static/dashboard/assets/SystemSettingsSubjectPanel-hsfHcJRV.js +33 -0
- package/static/dashboard/assets/{XpodAiConnectionsPodStore-DXNERI2-.js → XpodAiConnectionsPodStore-CHM-ZwI3.js} +1 -1
- package/static/dashboard/assets/{activity-BwRbcTha.js → activity-B7UdTZ1N.js} +1 -1
- package/static/dashboard/assets/{badge-BbRb9MsQ.js → badge-B6RuxNt1.js} +1 -1
- package/static/dashboard/assets/collection-runtime-CKBQm3Fl.js +1 -0
- package/static/dashboard/assets/dashboard-1zrtbMhM.css +1 -0
- package/static/dashboard/assets/{dashboard-D2ozrATv.js → dashboard-Dm_h60lA.js} +175 -135
- package/static/dashboard/assets/{download-SIHe8Y5t.js → download-BW035kpj.js} +1 -1
- package/static/dashboard/assets/{external-link-CiYw5Q4U.js → external-link-BMrNvf3c.js} +1 -1
- package/static/dashboard/assets/{index-DC1jRaVA.js → index-2jlFzexm.js} +1 -1
- package/static/dashboard/assets/index-CQDQ8WVr.js +4 -0
- package/static/dashboard/assets/{key-round-nKtxP6pb.js → key-round-C9vxhn7T.js} +1 -1
- package/static/dashboard/assets/{rotate-ccw-CQm5hHMN.js → rotate-ccw-8Vm0-INc.js} +1 -1
- package/static/dashboard/assets/{skeleton-TKyLbiPs.js → skeleton-CY_602wn.js} +1 -1
- package/static/dashboard/assets/{waypoints-BQS9t0ky.js → waypoints-DdEdgkxD.js} +1 -1
- package/static/dashboard/assets/workspace-layout-Wed840qR.js +1 -0
- package/static/dashboard/dashboard.html +2 -2
- package/static/settings/assets/{AiConfigContext-eLRkXFtH.js → AiConfigContext-CR3YhTA-.js} +1 -1
- package/static/settings/assets/AiConfigPage-DnOvX2Kx.js +1 -0
- package/static/settings/assets/DocumentProcessingPanel-CccpHBs3.js +1 -0
- package/static/settings/assets/IndexLifecyclePanel-BrECzBoM.js +1 -0
- package/static/settings/assets/{IndexSubjectPanel-DT0c11VQ.js → IndexSubjectPanel-CP84xXye.js} +1 -1
- package/static/settings/assets/ModelAssignmentsPanel-DbFi67Kk.js +1 -0
- package/static/settings/assets/ModelsPage-xjHA88qy.js +11 -0
- package/static/settings/assets/NetworkPage-Bj4wc0bh.js +2 -0
- package/static/settings/assets/{PaneListHeader-Da5jZFvG.js → PaneListHeader-Bz0UAhZr.js} +1 -1
- package/static/settings/assets/SearchIndexingPanel-ykhvw1Vl.js +1 -0
- package/static/settings/assets/{StatusSubjectPanel-Upqqlvon.js → StatusSubjectPanel-B2Y6ib3d.js} +1 -1
- package/static/settings/assets/StatusWorkspace-tx3Xg56J.js +1 -0
- package/static/settings/assets/SystemSettingsPage-BbFkv_Wn.js +1 -0
- package/static/settings/assets/SystemSettingsSubjectPanel-CcbpQmTc.js +33 -0
- package/static/settings/assets/{XpodAiConnectionsPodStore-nFgD_usD.js → XpodAiConnectionsPodStore-B11u0BOi.js} +2 -2
- package/static/settings/assets/{activity-CWy1W2W0.js → activity-BE8Hz8WF.js} +1 -1
- package/static/settings/assets/auth-callback-5waKJF0n.js +1 -0
- package/static/settings/assets/{badge-v30yFaaj.js → badge-xeRbYBMf.js} +1 -1
- package/static/settings/assets/collection-runtime-DIBObcT5.js +1 -0
- package/static/settings/assets/{download-C3Dzb60R.js → download-xI5yyfk7.js} +1 -1
- package/static/settings/assets/{external-link-DnkJGKNc.js → external-link-DmbiCMuc.js} +1 -1
- package/static/settings/assets/global-1zrtbMhM.css +1 -0
- package/static/settings/assets/{global-B_WO-aYY.js → global-BOl78fr8.js} +160 -120
- package/static/settings/assets/index-CFVXiUnV.js +4 -0
- package/static/settings/assets/index-DK6qlahe.js +1 -0
- package/static/settings/assets/{index-browser-DzhsXZHm.js → index-browser-Bk7jaLCd.js} +1 -1
- package/static/settings/assets/{key-round-DoDbsLae.js → key-round-B3VIp8oI.js} +1 -1
- package/static/settings/assets/{rotate-ccw-DNR_R3oT.js → rotate-ccw-DRzTN49Z.js} +1 -1
- package/static/settings/assets/{settings-BOznrBjy.js → settings-CCM17CMX.js} +1 -1
- package/static/settings/assets/{skeleton-BjHhu9qI.js → skeleton-Ckhw5HG7.js} +1 -1
- package/static/settings/assets/{waypoints-BXNph9Fd.js → waypoints-BFMI-qS6.js} +1 -1
- package/static/settings/assets/workspace-layout-Co0KpMKd.js +1 -0
- package/static/settings/auth-callback.html +3 -3
- package/static/settings/settings.html +3 -3
- package/static/app/assets/main.css +0 -1
- package/static/dashboard/assets/DocumentProcessingPanel-BSb_vOj7.js +0 -1
- package/static/dashboard/assets/IndexLifecyclePanel-DAHx-PBG.js +0 -1
- package/static/dashboard/assets/ModelAssignmentsPanel-CEJZs9At.js +0 -1
- package/static/dashboard/assets/ModelsPage-DkBVXmKT.js +0 -11
- package/static/dashboard/assets/NetworkPage-BDqKgRZQ.js +0 -2
- package/static/dashboard/assets/SearchIndexingPanel-M-WYaQP3.js +0 -1
- package/static/dashboard/assets/StatusWorkspace-CPIkjO9S.js +0 -1
- package/static/dashboard/assets/SystemSettingsSubjectPanel-CYHqNIn2.js +0 -33
- package/static/dashboard/assets/collection-runtime-BRfZD5oS.js +0 -1
- package/static/dashboard/assets/dashboard-rk080mvG.css +0 -1
- package/static/dashboard/assets/dialog-BbRbILBP.js +0 -1
- package/static/dashboard/assets/index-CExLoewO.js +0 -41
- package/static/dashboard/assets/index-CTgU8YW1.js +0 -4
- package/static/dashboard/assets/workspace-layout-Csbbr3vZ.js +0 -1
- package/static/settings/assets/AiConfigPage-BMO-ytdK.js +0 -1
- package/static/settings/assets/DocumentProcessingPanel-CH-HBRzQ.js +0 -1
- package/static/settings/assets/IndexLifecyclePanel-ChEMn9D8.js +0 -1
- package/static/settings/assets/ModelAssignmentsPanel-T59L_wOk.js +0 -1
- package/static/settings/assets/ModelsPage-m_SP4PdE.js +0 -11
- package/static/settings/assets/SearchIndexingPanel-DQQd3-Jw.js +0 -1
- package/static/settings/assets/StatusWorkspace-CPB49bGd.js +0 -1
- package/static/settings/assets/SystemSettingsPage-C0wrxcNw.js +0 -1
- package/static/settings/assets/SystemSettingsSubjectPanel-BOm7tUH1.js +0 -33
- package/static/settings/assets/auth-callback-HhgEuohz.js +0 -1
- package/static/settings/assets/collection-runtime-B7oomxic.js +0 -1
- package/static/settings/assets/dialog-BAe7moyL.js +0 -1
- package/static/settings/assets/global-rk080mvG.css +0 -1
- package/static/settings/assets/index-B51ot_m_.js +0 -1
- package/static/settings/assets/index-CHBQVfuZ.js +0 -41
- package/static/settings/assets/index-DbqRFton.js +0 -4
- package/static/settings/assets/workspace-layout-TZ7fteel.js +0 -1
- /package/static/app/assets/{_commonjsHelpers-B-UnjaXt.js → global-BGMlqT2c.js} +0 -0
|
@@ -14,3 +14,42 @@ export type ThreePaneAppletLayoutDescriptor = {
|
|
|
14
14
|
};
|
|
15
15
|
export type AppletLayoutDescriptor = SinglePaneAppletLayoutDescriptor | TwoPaneAppletLayoutDescriptor | ThreePaneAppletLayoutDescriptor;
|
|
16
16
|
export declare function defineAppletLayout<T extends AppletLayoutDescriptor>(descriptor: T): T;
|
|
17
|
+
/**
|
|
18
|
+
* §8.3 的四种页型。与上面的 pane 描述符并存:既有 applet 仍可用 three-pane,新页面按页型声明,
|
|
19
|
+
* 由 {@link resolveAppletPanePlan} 结合实际宽度与"是否真有对象集合"决定是否出现对象列。
|
|
20
|
+
*/
|
|
21
|
+
export type AppletPageType = 'overview' | 'collection' | 'configuration' | 'diagnostics';
|
|
22
|
+
/**
|
|
23
|
+
* §8.3 断点的唯一来源,单位是内容视口 CSS px。页面不得自选断点。
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* 宽窗口导航列宽度(§8.3)。`AppLayout` 的 Tailwind 类必须与它一致
|
|
27
|
+
* (`md:grid-cols-[184px_minmax(0,1fr)]`),`packages/extension-sdk/test/app-layout.test.tsx` 两边都断言。
|
|
28
|
+
*/
|
|
29
|
+
export declare const XPOD_LAYOUT_RAIL_WIDTH = 184;
|
|
30
|
+
export declare const XPOD_LAYOUT_BREAKPOINTS: {
|
|
31
|
+
/** 低于此宽度使用任务栏 + 导航抽屉,不强制底部 Tab。 */
|
|
32
|
+
readonly narrow: 768;
|
|
33
|
+
/** 只有达到此宽度且确有对象集合,才增加对象列。 */
|
|
34
|
+
readonly wideObjects: 1100;
|
|
35
|
+
};
|
|
36
|
+
export interface AppletPanePlanInput {
|
|
37
|
+
readonly pageType: AppletPageType;
|
|
38
|
+
/** 当前内容视口宽度(CSS px),不含原生标题栏与安全区。 */
|
|
39
|
+
readonly contentWidth: number;
|
|
40
|
+
/** 该页是否真有需要持续比较/切换的对象集合;概览、固定配置、诊断恒为 false。 */
|
|
41
|
+
readonly hasObjectCollection?: boolean;
|
|
42
|
+
}
|
|
43
|
+
export interface AppletPanePlan {
|
|
44
|
+
readonly pageType: AppletPageType;
|
|
45
|
+
readonly navigation: 'rail' | 'task-bar';
|
|
46
|
+
readonly panes: 'single' | 'stack' | 'list-detail';
|
|
47
|
+
readonly showObjectColumn: boolean;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* 把页型、宽度与集合事实映射成布局计划(spec §8.3):
|
|
51
|
+
* - <768px:任务栏 + 导航抽屉,单面板;
|
|
52
|
+
* - 768–1099px:184px 文字导航,集合页用堆叠;
|
|
53
|
+
* - ≥1100px:只有真正集合才额外出现对象列。
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveAppletPanePlan(input: AppletPanePlanInput): AppletPanePlan;
|
|
@@ -34,3 +34,43 @@ function assertValidLayoutContext(context) {
|
|
|
34
34
|
throw new Error('Applet layout descriptor context.initiallyCollapsed must be a boolean');
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* §8.3 断点的唯一来源,单位是内容视口 CSS px。页面不得自选断点。
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* 宽窗口导航列宽度(§8.3)。`AppLayout` 的 Tailwind 类必须与它一致
|
|
42
|
+
* (`md:grid-cols-[184px_minmax(0,1fr)]`),`packages/extension-sdk/test/app-layout.test.tsx` 两边都断言。
|
|
43
|
+
*/
|
|
44
|
+
export const XPOD_LAYOUT_RAIL_WIDTH = 184;
|
|
45
|
+
export const XPOD_LAYOUT_BREAKPOINTS = {
|
|
46
|
+
/** 低于此宽度使用任务栏 + 导航抽屉,不强制底部 Tab。 */
|
|
47
|
+
narrow: 768,
|
|
48
|
+
/** 只有达到此宽度且确有对象集合,才增加对象列。 */
|
|
49
|
+
wideObjects: 1100,
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* 把页型、宽度与集合事实映射成布局计划(spec §8.3):
|
|
53
|
+
* - <768px:任务栏 + 导航抽屉,单面板;
|
|
54
|
+
* - 768–1099px:184px 文字导航,集合页用堆叠;
|
|
55
|
+
* - ≥1100px:只有真正集合才额外出现对象列。
|
|
56
|
+
*/
|
|
57
|
+
export function resolveAppletPanePlan(input) {
|
|
58
|
+
const { pageType, contentWidth } = input;
|
|
59
|
+
const hasCollection = input.hasObjectCollection === true;
|
|
60
|
+
if (!Number.isFinite(contentWidth) || contentWidth <= 0) {
|
|
61
|
+
throw new Error('Applet pane plan needs a positive contentWidth');
|
|
62
|
+
}
|
|
63
|
+
if (contentWidth < XPOD_LAYOUT_BREAKPOINTS.narrow) {
|
|
64
|
+
return { pageType, navigation: 'task-bar', panes: 'single', showObjectColumn: false };
|
|
65
|
+
}
|
|
66
|
+
const showObjectColumn = contentWidth >= XPOD_LAYOUT_BREAKPOINTS.wideObjects && pageType === 'collection' && hasCollection;
|
|
67
|
+
if (showObjectColumn) {
|
|
68
|
+
return { pageType, navigation: 'rail', panes: 'list-detail', showObjectColumn: true };
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
pageType,
|
|
72
|
+
navigation: 'rail',
|
|
73
|
+
panes: pageType === 'collection' && contentWidth < XPOD_LAYOUT_BREAKPOINTS.wideObjects ? 'stack' : 'single',
|
|
74
|
+
showObjectColumn: false,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
@@ -3,5 +3,17 @@ export interface AppLayoutProps {
|
|
|
3
3
|
navigation: ReactNode;
|
|
4
4
|
children: ReactNode;
|
|
5
5
|
className?: string;
|
|
6
|
+
/** 窄窗任务栏的标题(spec §8.3)。宽窗由页面自己的标题承担。 */
|
|
7
|
+
narrowTitle?: ReactNode;
|
|
8
|
+
/** 提供时,窄窗任务栏显示返回按钮。 */
|
|
9
|
+
onNarrowBack?: () => void;
|
|
10
|
+
narrowBackLabel?: string;
|
|
11
|
+
/** 导航按钮与抽屉的名字;抽屉复用同一棵导航树。 */
|
|
12
|
+
navigationLabel?: string;
|
|
6
13
|
}
|
|
7
|
-
|
|
14
|
+
/**
|
|
15
|
+
* 工作区布局(spec §8.3):
|
|
16
|
+
* - ≥768px(Tailwind `md`,与 `XPOD_LAYOUT_BREAKPOINTS.narrow` 对齐):184px 文字导航 + 内容;
|
|
17
|
+
* - <768px:48px 顶部任务栏(返回、标题、有名称的导航按钮)+ 单面板,导航树放进抽屉,不强制底部 Tab。
|
|
18
|
+
*/
|
|
19
|
+
export declare function AppLayout({ navigation, children, className, narrowTitle, onNarrowBack, narrowBackLabel, navigationLabel, }: AppLayoutProps): import("react").JSX.Element;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { ArrowLeft, Menu } from 'lucide-react';
|
|
4
|
+
import { cn, Dialog, DialogContent, DialogTitle, DialogTrigger, } from '@undefineds.co/shared-ui';
|
|
5
|
+
/**
|
|
6
|
+
* 工作区布局(spec §8.3):
|
|
7
|
+
* - ≥768px(Tailwind `md`,与 `XPOD_LAYOUT_BREAKPOINTS.narrow` 对齐):184px 文字导航 + 内容;
|
|
8
|
+
* - <768px:48px 顶部任务栏(返回、标题、有名称的导航按钮)+ 单面板,导航树放进抽屉,不强制底部 Tab。
|
|
9
|
+
*/
|
|
10
|
+
export function AppLayout({ navigation, children, className, narrowTitle, onNarrowBack, narrowBackLabel = '返回', navigationLabel = '导航', }) {
|
|
11
|
+
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
12
|
+
return (_jsxs("section", { className: cn('grid h-screen min-h-0 grid-cols-[minmax(0,1fr)] grid-rows-[48px_minmax(0,1fr)] bg-background md:grid-cols-[184px_minmax(0,1fr)] md:grid-rows-[minmax(0,1fr)]', className), "data-app-layout": "workspace", children: [_jsxs("header", { className: "col-start-1 row-start-1 flex h-12 min-w-0 items-center gap-1 border-b border-border/50 bg-layout-sidebar px-1 md:hidden", "data-app-layout-header": true, children: [onNarrowBack ? (_jsx("button", { type: "button", onClick: onNarrowBack, "aria-label": narrowBackLabel, className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg text-foreground hover:bg-accent focus:outline-none focus-visible:bg-accent", children: _jsx(ArrowLeft, { className: "h-5 w-5", "aria-hidden": "true" }) })) : null, _jsx("div", { className: "min-w-0 flex-1 truncate px-1 text-sm font-medium", "data-app-layout-title": true, children: narrowTitle }), _jsxs(Dialog, { open: drawerOpen, onOpenChange: setDrawerOpen, children: [_jsx(DialogTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "flex h-9 shrink-0 items-center gap-2 rounded-lg px-3 text-sm text-foreground hover:bg-accent focus:outline-none focus-visible:bg-accent", children: [_jsx(Menu, { className: "h-5 w-5", "aria-hidden": "true" }), navigationLabel] }) }), _jsxs(DialogContent, { variant: "sheet-left", "aria-describedby": undefined, children: [_jsx(DialogTitle, { className: "sr-only", children: navigationLabel }), navigation] })] })] }), _jsx("aside", { className: "row-start-2 hidden min-h-0 overflow-hidden border-border/50 bg-layout-sidebar md:row-start-1 md:block md:border-r", "data-app-layout-navigation": true, children: navigation }), _jsx("div", { className: "col-start-1 row-start-2 min-h-0 min-w-0 overflow-hidden bg-layout-content md:col-start-2 md:row-start-1", "data-app-layout-content": true, children: children })] }));
|
|
5
13
|
}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
+
import { type AppletPageType } from '../layout';
|
|
2
3
|
import { type WorkspaceLayoutMode, type WorkspaceLayoutPane } from './layout-context';
|
|
3
4
|
export type TwoPaneLayoutMode = 'auto' | WorkspaceLayoutMode;
|
|
4
|
-
export interface
|
|
5
|
+
export interface WorkspacePageTypeProps {
|
|
6
|
+
/**
|
|
7
|
+
* §8.3 页型。概览、固定配置、诊断不会渲染对象列;只有 `collection` 且确有集合才在宽断点出现。
|
|
8
|
+
* 默认保持旧行为(集合页 + 有集合),新页面应显式声明。
|
|
9
|
+
*/
|
|
10
|
+
pageType?: AppletPageType;
|
|
11
|
+
hasObjectCollection?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface TwoPaneLayoutProps extends WorkspacePageTypeProps {
|
|
5
14
|
listHeader: ReactNode;
|
|
6
15
|
list: ReactNode;
|
|
7
16
|
mainHeader: ReactNode;
|
|
@@ -19,7 +28,7 @@ export interface ThreePaneLayoutContextConfig {
|
|
|
19
28
|
collapsible?: boolean;
|
|
20
29
|
initiallyCollapsed?: boolean;
|
|
21
30
|
}
|
|
22
|
-
export interface ThreePaneLayoutProps {
|
|
31
|
+
export interface ThreePaneLayoutProps extends WorkspacePageTypeProps {
|
|
23
32
|
header?: ReactNode;
|
|
24
33
|
list: ReactNode;
|
|
25
34
|
main: ReactNode;
|
|
@@ -33,6 +42,6 @@ export interface WorkspaceLayoutHistoryAdapter {
|
|
|
33
42
|
push(pane: WorkspaceLayoutPane): void;
|
|
34
43
|
subscribe(listener: (pane: WorkspaceLayoutPane) => void): () => void;
|
|
35
44
|
}
|
|
36
|
-
export declare function TwoPaneLayout({ listHeader, list, mainHeader, main, mode, history, className, }: TwoPaneLayoutProps): import("react").JSX.Element;
|
|
45
|
+
export declare function TwoPaneLayout({ listHeader, list, mainHeader, main, mode, history, className, pageType, hasObjectCollection, }: TwoPaneLayoutProps): import("react").JSX.Element;
|
|
37
46
|
export declare function SinglePaneLayout({ header, main, className, }: SinglePaneLayoutProps): import("react").JSX.Element;
|
|
38
|
-
export declare function ThreePaneLayout({ header, list, main, context, mode, history, contextConfig, className, }: ThreePaneLayoutProps): import("react").JSX.Element;
|
|
47
|
+
export declare function ThreePaneLayout({ header, list, main, context, mode, history, contextConfig, className, pageType, hasObjectCollection, }: ThreePaneLayoutProps): import("react").JSX.Element;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore, } from 'react';
|
|
3
3
|
import { cn } from '@undefineds.co/shared-ui';
|
|
4
|
+
import { resolveAppletPanePlan, XPOD_LAYOUT_BREAKPOINTS, XPOD_LAYOUT_RAIL_WIDTH, } from '../layout.js';
|
|
4
5
|
import { WorkspaceLayoutContext, } from './layout-context.js';
|
|
5
6
|
const stackMediaQuery = '(max-width: 767px)';
|
|
6
7
|
const twoPaneGridStyle = {
|
|
@@ -33,6 +34,54 @@ function useResolvedMode(mode) {
|
|
|
33
34
|
const autoMode = useSyncExternalStore(subscribeToStackModeChange, getAutoModeSnapshot, getServerAutoModeSnapshot);
|
|
34
35
|
return mode === 'auto' ? autoMode : mode;
|
|
35
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* 对象列的可用宽度媒体查询:§8.3 的 1100px 是**内容**宽度,宽窗口还有一个 184px 导航列,
|
|
39
|
+
* 所以视口阈值要加上它。
|
|
40
|
+
*/
|
|
41
|
+
const objectColumnMediaQuery = `(min-width: ${XPOD_LAYOUT_BREAKPOINTS.wideObjects + XPOD_LAYOUT_RAIL_WIDTH}px)`;
|
|
42
|
+
/**
|
|
43
|
+
* 是否够放对象列。
|
|
44
|
+
*
|
|
45
|
+
* 没有 `matchMedia` 的环境(服务端渲染、旧测试环境)按宽窗口处理——与 `getServerAutoModeSnapshot`
|
|
46
|
+
* 的既有默认一致:产品主要跑在桌面壳里,未知环境不应把已有的两栏布局变成堆叠。
|
|
47
|
+
*/
|
|
48
|
+
function useRoomForObjectColumn() {
|
|
49
|
+
return useSyncExternalStore((onStoreChange) => {
|
|
50
|
+
if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
|
|
51
|
+
return () => undefined;
|
|
52
|
+
}
|
|
53
|
+
const media = window.matchMedia(objectColumnMediaQuery);
|
|
54
|
+
media.addEventListener('change', onStoreChange);
|
|
55
|
+
return () => media.removeEventListener('change', onStoreChange);
|
|
56
|
+
}, () => (typeof window === 'undefined' || typeof window.matchMedia !== 'function'
|
|
57
|
+
? true
|
|
58
|
+
: window.matchMedia(objectColumnMediaQuery).matches), () => true);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 把 §8.3 的页型、宽度与集合事实落到布局上:复用 `resolveAppletPanePlan` 作为唯一判断处,
|
|
62
|
+
* 概览/固定配置/诊断在任何宽度都不出现对象列,集合页在 1100px 以下改为堆叠。
|
|
63
|
+
*/
|
|
64
|
+
function useObjectColumn(input) {
|
|
65
|
+
const narrow = useSyncExternalStore(subscribeToStackModeChange, getAutoModeSnapshot, getServerAutoModeSnapshot) === 'stack';
|
|
66
|
+
const roomForObjects = useRoomForObjectColumn();
|
|
67
|
+
// 只需要区分三个区间,因此给 plan 一个能代表当前区间的宽度
|
|
68
|
+
const contentWidth = roomForObjects
|
|
69
|
+
? XPOD_LAYOUT_BREAKPOINTS.wideObjects
|
|
70
|
+
: narrow
|
|
71
|
+
? XPOD_LAYOUT_BREAKPOINTS.narrow - 1
|
|
72
|
+
: XPOD_LAYOUT_BREAKPOINTS.narrow;
|
|
73
|
+
const plan = resolveAppletPanePlan({
|
|
74
|
+
pageType: input.pageType,
|
|
75
|
+
contentWidth,
|
|
76
|
+
hasObjectCollection: input.hasObjectCollection,
|
|
77
|
+
});
|
|
78
|
+
// §8.3:只有真正的集合列出现时才是并排;其余(含窄窗的集合页)都走 list→detail 的堆叠
|
|
79
|
+
const autoMode = plan.panes === 'list-detail' ? 'split' : 'stack';
|
|
80
|
+
return {
|
|
81
|
+
resolvedMode: input.mode === 'auto' ? autoMode : input.mode,
|
|
82
|
+
showObjectColumn: plan.showObjectColumn,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
36
85
|
function useStackNavigation({ resolvedMode, history, resolvePane, }) {
|
|
37
86
|
const [activePane, setActivePane] = useState('list');
|
|
38
87
|
const focusPaneRef = useRef(null);
|
|
@@ -86,8 +135,11 @@ function useStackNavigation({ resolvedMode, history, resolvePane, }) {
|
|
|
86
135
|
openContext,
|
|
87
136
|
};
|
|
88
137
|
}
|
|
89
|
-
export function TwoPaneLayout({ listHeader, list, mainHeader, main, mode = 'auto', history, className, }) {
|
|
90
|
-
const resolvedMode =
|
|
138
|
+
export function TwoPaneLayout({ listHeader, list, mainHeader, main, mode = 'auto', history, className, pageType = 'collection', hasObjectCollection = true, }) {
|
|
139
|
+
const { resolvedMode } = useObjectColumn({ mode, pageType, hasObjectCollection });
|
|
140
|
+
// §8.3:非集合页不渲染对象列;集合页只有宽断点才显示
|
|
141
|
+
// §8.3:只有集合页才有对象列表;宽度决定它是并排的对象列还是堆叠的第一屏
|
|
142
|
+
const showList = pageType === 'collection' && hasObjectCollection;
|
|
91
143
|
const { activePane, paneRefs, openList, openMain, openContext, } = useStackNavigation({
|
|
92
144
|
resolvedMode,
|
|
93
145
|
history,
|
|
@@ -101,15 +153,19 @@ export function TwoPaneLayout({ listHeader, list, mainHeader, main, mode = 'auto
|
|
|
101
153
|
openContext,
|
|
102
154
|
}), [activePane, openContext, openList, openMain, resolvedMode]);
|
|
103
155
|
const isStack = resolvedMode === 'stack';
|
|
104
|
-
const
|
|
105
|
-
const
|
|
106
|
-
|
|
156
|
+
const stacked = showList && isStack;
|
|
157
|
+
const listHidden = !showList || (stacked && activePane !== 'list');
|
|
158
|
+
const mainHidden = stacked && activePane !== 'main';
|
|
159
|
+
return (_jsx(WorkspaceLayoutContext.Provider, { value: navigation, children: _jsx("section", { className: cn('flex min-h-0 flex-1 flex-col bg-background', className), "data-workspace-layout": "two-pane", "data-workspace-mode": resolvedMode, children: _jsxs("div", { className: cn('grid min-h-0 flex-1', stacked || !showList ? 'grid-cols-1' : null), style: stacked || !showList ? undefined : twoPaneGridStyle, "data-workspace-layout-mode": mode, "data-workspace-object-column": showList && resolvedMode === 'split' ? 'shown' : 'hidden', "data-workspace-active-pane": activePane, children: [_jsxs("aside", { ref: paneRefs.list, className: cn('min-h-0 flex-col overflow-hidden bg-layout-list-item @container', listHidden ? 'hidden' : 'flex', stacked ? 'border-r-0' : 'border-r border-border'), "data-testid": "workspace-list-pane", "data-workspace-pane": "list", hidden: listHidden, tabIndex: stacked ? -1 : undefined, children: [_jsx("header", { className: "h-12 shrink-0 border-b border-border bg-layout-list-header", "data-workspace-list-header": "true", children: listHeader }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", children: list })] }), _jsxs("main", { ref: paneRefs.main, className: cn('min-h-0 flex-col overflow-hidden bg-layout-content @container', mainHidden ? 'hidden' : 'flex'), "data-testid": "workspace-main-pane", "data-workspace-pane": "main", hidden: mainHidden, tabIndex: stacked ? -1 : undefined, children: [_jsx("header", { className: "h-12 shrink-0 border-b border-border bg-layout-content", "data-workspace-main-header": "true", children: mainHeader }), _jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto", children: [stacked ? (_jsx("button", { type: "button", className: "inline-flex items-center px-4 py-3 text-sm text-muted-foreground hover:text-foreground", onClick: openList, children: "\u8FD4\u56DE\u5217\u8868" })) : null, main] })] })] }) }) }));
|
|
107
160
|
}
|
|
108
161
|
export function SinglePaneLayout({ header, main, className, }) {
|
|
109
162
|
return (_jsxs("section", { className: cn('flex min-h-0 flex-1 flex-col bg-background', className), "data-workspace-layout": "single-pane", children: [header ? (_jsx("header", { className: "h-16 shrink-0 border-b border-border bg-layout-content", children: header })) : null, _jsx("main", { className: "min-h-0 flex-1 overflow-y-auto bg-layout-content @container", "data-testid": "workspace-content-pane", "data-workspace-pane": "content", children: main })] }));
|
|
110
163
|
}
|
|
111
|
-
export function ThreePaneLayout({ header, list, main, context, mode = 'auto', history, contextConfig, className, }) {
|
|
112
|
-
const resolvedMode =
|
|
164
|
+
export function ThreePaneLayout({ header, list, main, context, mode = 'auto', history, contextConfig, className, pageType = 'collection', hasObjectCollection = true, }) {
|
|
165
|
+
const { resolvedMode } = useObjectColumn({ mode, pageType, hasObjectCollection });
|
|
166
|
+
// §8.3:非集合页不渲染对象列
|
|
167
|
+
// §8.3:只有集合页才有对象列表;宽度决定它是并排的对象列还是堆叠的第一屏
|
|
168
|
+
const showList = pageType === 'collection' && hasObjectCollection;
|
|
113
169
|
const [contextCollapsed, setContextCollapsed] = useState(contextConfig?.initiallyCollapsed ?? false);
|
|
114
170
|
const { activePane, paneRefs, openList, openMain, openContext, } = useStackNavigation({ resolvedMode, history });
|
|
115
171
|
const toggleContextCollapsed = useCallback(() => {
|
|
@@ -123,10 +179,11 @@ export function ThreePaneLayout({ header, list, main, context, mode = 'auto', hi
|
|
|
123
179
|
openContext,
|
|
124
180
|
}), [activePane, openContext, openList, openMain, resolvedMode]);
|
|
125
181
|
const isStack = resolvedMode === 'stack';
|
|
126
|
-
const
|
|
127
|
-
const
|
|
128
|
-
const
|
|
182
|
+
const stacked = showList && isStack;
|
|
183
|
+
const listHidden = !showList || (stacked && activePane !== 'list');
|
|
184
|
+
const mainHidden = stacked && activePane !== 'main';
|
|
185
|
+
const contextHidden = stacked
|
|
129
186
|
? activePane !== 'context'
|
|
130
187
|
: Boolean(contextConfig?.collapsible && contextCollapsed);
|
|
131
|
-
return (_jsx(WorkspaceLayoutContext.Provider, { value: navigation, children: _jsxs("section", { className: cn('flex min-h-0 flex-1 flex-col bg-background', className), "data-workspace-layout": "three-pane", "data-workspace-mode": resolvedMode, children: [header ? (_jsx("header", { className: "h-16 shrink-0 border-b border-border bg-layout-content", children: header })) : null, contextConfig?.collapsible && !
|
|
188
|
+
return (_jsx(WorkspaceLayoutContext.Provider, { value: navigation, children: _jsxs("section", { className: cn('flex min-h-0 flex-1 flex-col bg-background', className), "data-workspace-layout": "three-pane", "data-workspace-mode": resolvedMode, children: [header ? (_jsx("header", { className: "h-16 shrink-0 border-b border-border bg-layout-content", children: header })) : null, contextConfig?.collapsible && !stacked ? (_jsx("div", { className: "shrink-0 border-b border-border bg-layout-content px-3 py-2", children: _jsx("button", { type: "button", "aria-expanded": !contextCollapsed, className: "inline-flex items-center rounded-md px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground", onClick: toggleContextCollapsed, children: contextCollapsed ? '展开上下文面板' : '折叠上下文面板' }) })) : null, _jsxs("div", { className: cn('grid min-h-0 flex-1', stacked ? 'grid-cols-1' : null), style: stacked || !showList ? undefined : threePaneGridStyle, "data-workspace-layout-mode": mode, "data-workspace-active-pane": activePane, children: [_jsx("aside", { ref: paneRefs.list, className: cn('min-h-0 overflow-y-auto bg-layout-list-item @container', listHidden ? 'hidden' : null, stacked ? 'border-r-0' : 'border-r border-border'), "data-testid": "workspace-list-pane", "data-workspace-pane": "list", hidden: listHidden, tabIndex: stacked ? -1 : undefined, children: list }), _jsxs("main", { ref: paneRefs.main, className: cn('min-h-0 overflow-y-auto bg-layout-content @container', mainHidden ? 'hidden' : null), "data-testid": "workspace-main-pane", "data-workspace-pane": "main", hidden: mainHidden, tabIndex: stacked ? -1 : undefined, children: [stacked ? (_jsx("button", { type: "button", className: "inline-flex items-center px-4 py-3 text-sm text-muted-foreground hover:text-foreground", onClick: openList, children: "\u8FD4\u56DE\u5217\u8868" })) : null, main] }), _jsxs("aside", { ref: paneRefs.context, className: cn('min-h-0 overflow-y-auto bg-layout-content @container', contextHidden ? 'hidden' : null, stacked ? 'border-l-0' : 'border-l border-border'), "data-testid": "workspace-context-pane", "data-workspace-pane": "context", hidden: contextHidden, tabIndex: stacked ? -1 : undefined, children: [stacked ? (_jsx("button", { type: "button", className: "inline-flex items-center px-4 py-3 text-sm text-muted-foreground hover:text-foreground", onClick: openMain, children: "\u8FD4\u56DE\u4E3B\u533A\u57DF" })) : null, context] })] })] }) }));
|
|
132
189
|
}
|
|
@@ -86,16 +86,16 @@ export function AuthSurface({ mode, title, children, presentation = 'standard',
|
|
|
86
86
|
const bodyClassName = isCompact
|
|
87
87
|
? 'flex min-h-0 flex-1 flex-col overflow-y-auto'
|
|
88
88
|
: 'max-h-[min(80vh,48rem)] overflow-y-auto';
|
|
89
|
-
const surfaceContent = (_jsxs(_Fragment, { children: [isCompact ? (_jsxs(_Fragment, { children: [_jsx("h1", { id: titleId, className: "sr-only", children: title }), mode === 'modal' && onClose && closeLabel ? (_jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: onClose, "aria-label": closeLabel, className: "absolute right-2 top-2 z-
|
|
89
|
+
const surfaceContent = (_jsxs(_Fragment, { children: [isCompact ? (_jsxs(_Fragment, { children: [_jsx("h1", { id: titleId, className: "sr-only", children: title }), mode === 'modal' && onClose && closeLabel ? (_jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: onClose, "aria-label": closeLabel, className: "absolute right-2 top-2 z-[var(--layer-sticky)]", children: _jsx("span", { "aria-hidden": "true", children: "\u00D7" }) })) : null] })) : (_jsxs("div", { className: "flex items-start justify-between gap-4 border-b border-border/60 p-4", children: [_jsx("h1", { id: titleId, className: "text-lg font-semibold text-foreground", children: title }), mode === 'modal' && onClose && closeLabel ? (_jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: onClose, "aria-label": closeLabel, children: _jsx("span", { "aria-hidden": "true", children: "\u00D7" }) })) : null] })), lead ? (_jsx("div", { "data-testid": "auth-surface-lead", className: cn(isCompact
|
|
90
90
|
? 'shrink-0 px-5 pt-7 has-[[data-presentation=compact]]:pt-5'
|
|
91
91
|
: 'border-b border-border/60 p-4'), children: lead })) : null, _jsx(AuthSurfaceBody, { className: cn(bodyClassName, contentClassName), children: children })] }));
|
|
92
92
|
return (_jsx("div", { "data-testid": `auth-surface-${mode}`, "data-auth-surface-mode": mode, "data-auth-surface-presentation": isCompact ? 'compact' : undefined, "data-auth-surface-host": isWindowHost ? 'window' : undefined, className: cn(isWindowHost
|
|
93
|
-
? 'fixed inset-0 z-
|
|
93
|
+
? 'fixed inset-0 z-[var(--layer-modal)] flex items-stretch justify-stretch overflow-hidden bg-card p-0'
|
|
94
94
|
: mode === 'modal'
|
|
95
|
-
? cn('fixed inset-0 z-
|
|
95
|
+
? cn('fixed inset-0 z-[var(--layer-modal)] flex items-center justify-center p-4',
|
|
96
|
+
// §5.1:compact 用主题画布铺满,不铺遮罩
|
|
97
|
+
'bg-background')
|
|
96
98
|
: mode === 'page'
|
|
97
99
|
? 'flex min-h-[100dvh] w-full items-center justify-center bg-background p-4'
|
|
98
|
-
: 'flex min-h-0 w-full items-center justify-center p-4', className), children: isWindowHost ? (_jsx("div", { ref: surfaceRef, ...dialogProps, "data-auth-surface-frame": "window", tabIndex: -1, className: "relative flex h-full min-h-0 w-full flex-col overflow-hidden bg-card text-card-foreground focus:outline-none", children: surfaceContent })) : (_jsx(Card, { ref: surfaceRef, ...dialogProps, tabIndex: -1, style: { outline: 'none' }, className: cn('relative flex min-h-0 w-full flex-col border-border bg-card text-card-foreground focus:outline-none',
|
|
99
|
-
? 'h-[400px] w-[280px] max-h-[calc(100dvh-2rem)] max-w-[calc(100vw-2rem)] overflow-hidden rounded-xl border-border/50 shadow-lg shadow-black/5'
|
|
100
|
-
: mode === 'embedded' ? 'max-w-none shadow-none' : 'max-w-lg'), children: surfaceContent })) }));
|
|
100
|
+
: 'flex min-h-0 w-full items-center justify-center p-4', className), children: isWindowHost ? (_jsx("div", { ref: surfaceRef, ...dialogProps, "data-auth-surface-frame": "window", tabIndex: -1, className: "relative flex h-full min-h-0 w-full flex-col overflow-hidden bg-card text-card-foreground focus:outline-none", children: surfaceContent })) : isCompact ? (_jsx("div", { ref: surfaceRef, ...dialogProps, "data-auth-surface-frame": "compact", tabIndex: -1, style: { outline: 'none' }, className: "flex h-[400px] w-[280px] max-h-[calc(100dvh-2rem)] max-w-[calc(100vw-2rem)] min-w-0 flex-col overflow-y-auto overscroll-contain focus:outline-none", children: surfaceContent })) : (_jsx(Card, { ref: surfaceRef, ...dialogProps, tabIndex: -1, style: { outline: 'none' }, className: cn('relative flex min-h-0 w-full flex-col border-border bg-card text-card-foreground focus:outline-none', mode === 'embedded' ? 'max-w-none shadow-none' : 'max-w-lg'), children: surfaceContent })) }));
|
|
101
101
|
}
|
|
@@ -8,13 +8,13 @@ const Dialog = DialogPrimitive.Root;
|
|
|
8
8
|
const DialogTrigger = DialogPrimitive.Trigger;
|
|
9
9
|
const DialogPortal = DialogPrimitive.Portal;
|
|
10
10
|
const DialogClose = DialogPrimitive.Close;
|
|
11
|
-
const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Overlay, { ref: ref, className: cn("fixed inset-0 z-
|
|
11
|
+
const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Overlay, { ref: ref, className: cn("fixed inset-0 z-[var(--layer-backdrop)] xpod-overlay-scrim", "data-[state=open]:animate-in data-[state=closed]:animate-out", "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", className), ...props })));
|
|
12
12
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
13
13
|
const DialogContent = React.forwardRef(({ className, children, variant = "center", ...props }, ref) => (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Content, { ref: ref, className: cn(variant === "sheet-left"
|
|
14
|
-
? "fixed inset-y-0 left-0 z-
|
|
14
|
+
? "fixed inset-y-0 left-0 z-[var(--layer-modal)] flex h-dvh w-[min(88vw,320px)] flex-col border-r bg-background p-0 shadow-[16px_0_30px_rgba(15,23,42,0.08)] duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:slide-out-to-left-full data-[state=open]:slide-in-from-left-full rounded-none"
|
|
15
15
|
: variant === "sheet-right"
|
|
16
|
-
? "fixed inset-y-0 right-0 z-
|
|
17
|
-
: "fixed left-[50%] top-[50%] z-
|
|
16
|
+
? "fixed inset-y-0 right-0 z-[var(--layer-modal)] flex h-dvh w-full max-w-4xl flex-col border-l bg-background p-0 shadow-[-16px_0_30px_rgba(15,23,42,0.08)] duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-right-full rounded-none"
|
|
17
|
+
: "fixed left-[50%] top-[50%] z-[var(--layer-modal)] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] rounded-lg", className), ...props, children: [children, _jsxs(DialogPrimitive.Close, { className: cn("absolute right-4 top-4 rounded-xl opacity-70 transition-all hover:opacity-100 hover:bg-muted/50 p-1 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", interactiveFocusClass), children: [_jsx(X, { className: "h-4 w-4" }), _jsx("span", { className: "sr-only", children: "Close" })] })] })] })));
|
|
18
18
|
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
19
19
|
const DialogHeader = ({ className, ...props }) => (_jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props }));
|
|
20
20
|
DialogHeader.displayName = "DialogHeader";
|
|
@@ -32,7 +32,7 @@ export function LoginCardShell({ children, ariaLabel, overlayClassName, cardClas
|
|
|
32
32
|
const baseCardClassName = cardSize === 'auto'
|
|
33
33
|
? 'w-compact-modal warm-card overflow-hidden rounded-xl flex flex-col'
|
|
34
34
|
: 'w-compact-modal h-compact-modal warm-card overflow-hidden rounded-xl flex flex-col';
|
|
35
|
-
return (_jsx("div", { "data-testid": surfaceTestId, "data-auth-surface-host": surfaceHost, className: cn('fixed inset-0 z-[
|
|
35
|
+
return (_jsx("div", { "data-testid": surfaceTestId, "data-auth-surface-host": surfaceHost, className: cn('fixed inset-0 z-[var(--layer-backdrop)] flex items-center justify-center xpod-overlay-scrim', overlayClassName), children: _jsx("div", { role: "dialog", "aria-modal": "true", "aria-label": ariaLabel, "data-login-card-size": cardSize, className: cn(baseCardClassName, cardClassName), children: children }) }));
|
|
36
36
|
}
|
|
37
37
|
export function LoginErrorBanner({ error, onDismiss, dismissLabel, }) {
|
|
38
38
|
if (!error)
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
@layer base {
|
|
2
2
|
:root {
|
|
3
3
|
color-scheme: light;
|
|
4
|
-
--background:
|
|
5
|
-
--foreground:
|
|
6
|
-
--card:
|
|
7
|
-
--card-foreground:
|
|
8
|
-
--popover:
|
|
9
|
-
--popover-foreground:
|
|
10
|
-
--primary:
|
|
11
|
-
--primary-foreground:
|
|
12
|
-
--secondary: 0
|
|
13
|
-
--secondary-foreground:
|
|
14
|
-
--muted:
|
|
15
|
-
--muted-foreground:
|
|
16
|
-
--accent:
|
|
17
|
-
--accent-foreground:
|
|
4
|
+
--background: 42 38.5% 94.9%;
|
|
5
|
+
--foreground: 30 13.2% 14.9%;
|
|
6
|
+
--card: 45 33.3% 97.6%;
|
|
7
|
+
--card-foreground: 30 13.2% 14.9%;
|
|
8
|
+
--popover: 45 33.3% 97.6%;
|
|
9
|
+
--popover-foreground: 30 13.2% 14.9%;
|
|
10
|
+
--primary: 260.6 36.1% 38%;
|
|
11
|
+
--primary-foreground: 42 38.5% 94.9%;
|
|
12
|
+
--secondary: 0 10.2% 90.4%;
|
|
13
|
+
--secondary-foreground: 30 13.2% 14.9%;
|
|
14
|
+
--muted: 18 15.6% 87.5%;
|
|
15
|
+
--muted-foreground: 33.3 9.8% 36.1%;
|
|
16
|
+
--accent: 324 7.5% 86.9%;
|
|
17
|
+
--accent-foreground: 30 13.2% 14.9%;
|
|
18
18
|
--destructive: 352 43% 49%;
|
|
19
19
|
--destructive-foreground: 0 0% 100%;
|
|
20
|
-
--border:
|
|
21
|
-
--input:
|
|
22
|
-
--ring:
|
|
23
|
-
--lineage:
|
|
24
|
-
--lineage-foreground:
|
|
20
|
+
--border: 36 13.5% 85.5%;
|
|
21
|
+
--input: 36 4% 51%;
|
|
22
|
+
--ring: 260.6 36.1% 38%;
|
|
23
|
+
--lineage: 260.6 36.1% 38%;
|
|
24
|
+
--lineage-foreground: 42 38.5% 94.9%;
|
|
25
25
|
--boundary: 202 34% 37%;
|
|
26
26
|
--boundary-foreground: 0 0% 100%;
|
|
27
27
|
--success: 160 48% 30%;
|
|
@@ -36,92 +36,136 @@
|
|
|
36
36
|
--radius-2xl: 16px;
|
|
37
37
|
--radius-3xl: 16px;
|
|
38
38
|
--radius: 0.5rem;
|
|
39
|
-
--layout-sidebar:
|
|
40
|
-
--layout-list-header:
|
|
41
|
-
--layout-list-hover: 0
|
|
42
|
-
--layout-list-item:
|
|
43
|
-
--layout-list-selected:
|
|
44
|
-
--layout-content:
|
|
45
|
-
--purple-medium:
|
|
46
|
-
--purple-deep:
|
|
39
|
+
--layout-sidebar: 41.3 38.1% 91.8%;
|
|
40
|
+
--layout-list-header: 42 38.5% 94.9%;
|
|
41
|
+
--layout-list-hover: 0 10.2% 90.4%;
|
|
42
|
+
--layout-list-item: 45 33.3% 97.6%;
|
|
43
|
+
--layout-list-selected: 324 7.5% 86.9%;
|
|
44
|
+
--layout-content: 42 38.5% 94.9%;
|
|
45
|
+
--purple-medium: 260.6 36.1% 38%;
|
|
46
|
+
--purple-deep: 261.2 35.7% 28%;
|
|
47
47
|
--purple-light: 258 48% 84%;
|
|
48
|
+
--control-strong: 33.3 9.8% 36.1%;
|
|
49
|
+
--action-hover: 261 35.7% 32.9%;
|
|
50
|
+
--action-pressed: 261.2 35.7% 28%;
|
|
51
|
+
--tint-canvas: 0 10.2% 90.4%;
|
|
52
|
+
--tint-sunken: 18 15.6% 87.5%;
|
|
53
|
+
--tint-badge: 324 7.5% 86.9%;
|
|
54
|
+
/* 公共叠层:§8.2 层级表的唯一来源,页面不得自带数值 */
|
|
55
|
+
--layer-base: 0;
|
|
56
|
+
--layer-sticky: 10;
|
|
57
|
+
--layer-popover: 20;
|
|
58
|
+
--layer-backdrop: 30;
|
|
59
|
+
--layer-modal: 40;
|
|
60
|
+
--layer-toast: 50;
|
|
61
|
+
--scrim: 30 13.8% 11.4%;
|
|
48
62
|
}
|
|
49
63
|
|
|
50
64
|
.dark {
|
|
51
65
|
color-scheme: dark;
|
|
52
|
-
--background:
|
|
53
|
-
--foreground:
|
|
54
|
-
--card:
|
|
55
|
-
--card-foreground:
|
|
56
|
-
--popover:
|
|
57
|
-
--popover-foreground:
|
|
58
|
-
--primary:
|
|
59
|
-
--primary-foreground:
|
|
60
|
-
--secondary:
|
|
61
|
-
--secondary-foreground:
|
|
62
|
-
--muted:
|
|
63
|
-
--muted-foreground:
|
|
64
|
-
--accent:
|
|
65
|
-
--accent-foreground:
|
|
66
|
+
--background: 30 13.8% 11.4%;
|
|
67
|
+
--foreground: 42 38.5% 94.9%;
|
|
68
|
+
--card: 30 13.2% 14.9%;
|
|
69
|
+
--card-foreground: 42 38.5% 94.9%;
|
|
70
|
+
--popover: 30 13.2% 14.9%;
|
|
71
|
+
--popover-foreground: 42 38.5% 94.9%;
|
|
72
|
+
--primary: 270 16.7% 71.8%;
|
|
73
|
+
--primary-foreground: 30 13.8% 11.4%;
|
|
74
|
+
--secondary: 276.9 11.7% 21.8%;
|
|
75
|
+
--secondary-foreground: 42 38.5% 94.9%;
|
|
76
|
+
--muted: 276.9 11.7% 21.8%;
|
|
77
|
+
--muted-foreground: 34.3 15.8% 73.9%;
|
|
78
|
+
--accent: 276.9 11.7% 21.8%;
|
|
79
|
+
--accent-foreground: 42 38.5% 94.9%;
|
|
66
80
|
--destructive: 352 43% 49%;
|
|
67
81
|
--destructive-foreground: 0 0% 100%;
|
|
68
|
-
--border:
|
|
69
|
-
--input:
|
|
70
|
-
--ring:
|
|
71
|
-
--lineage:
|
|
72
|
-
--lineage-foreground:
|
|
82
|
+
--border: 30 12.3% 25.5%;
|
|
83
|
+
--input: 32.7 9.2% 53.3%;
|
|
84
|
+
--ring: 270 16.7% 71.8%;
|
|
85
|
+
--lineage: 270 16.7% 71.8%;
|
|
86
|
+
--lineage-foreground: 30 13.8% 11.4%;
|
|
73
87
|
--boundary: 202 34% 48%;
|
|
74
88
|
--boundary-foreground: 0 0% 100%;
|
|
75
89
|
--success: 160 48% 42%;
|
|
76
90
|
--success-foreground: 0 0% 100%;
|
|
77
91
|
--warning: 44 72% 48%;
|
|
78
92
|
--warning-foreground: 0 0% 100%;
|
|
79
|
-
--layout-sidebar:
|
|
80
|
-
--layout-list-header:
|
|
81
|
-
--layout-list-hover:
|
|
82
|
-
--layout-list-item:
|
|
83
|
-
--layout-list-selected:
|
|
84
|
-
--layout-content:
|
|
93
|
+
--layout-sidebar: 30 13.6% 8.6%;
|
|
94
|
+
--layout-list-header: 30 13.8% 11.4%;
|
|
95
|
+
--layout-list-hover: 276.9 11.7% 21.8%;
|
|
96
|
+
--layout-list-item: 30 13.2% 14.9%;
|
|
97
|
+
--layout-list-selected: 276.9 11.7% 21.8%;
|
|
98
|
+
--layout-content: 30 13.8% 11.4%;
|
|
99
|
+
--control-strong: 33.9 13.6% 66.9%;
|
|
100
|
+
--action-hover: 271.6 16.8% 77.8%;
|
|
101
|
+
--action-pressed: 264.4 18.8% 66.7%;
|
|
102
|
+
--tint-canvas: 276.9 11.7% 21.8%;
|
|
103
|
+
--tint-sunken: 276.9 11.7% 21.8%;
|
|
104
|
+
--tint-badge: 276.9 11.7% 21.8%;
|
|
105
|
+
--purple-medium: 270 16.7% 71.8%;
|
|
106
|
+
--purple-deep: 264.4 18.8% 66.7%;
|
|
107
|
+
/* 公共叠层:§8.2 层级表的唯一来源,页面不得自带数值 */
|
|
108
|
+
--layer-base: 0;
|
|
109
|
+
--layer-sticky: 10;
|
|
110
|
+
--layer-popover: 20;
|
|
111
|
+
--layer-backdrop: 30;
|
|
112
|
+
--layer-modal: 40;
|
|
113
|
+
--layer-toast: 50;
|
|
114
|
+
--scrim: 30 13.8% 11.4%;
|
|
85
115
|
}
|
|
86
116
|
|
|
87
117
|
.light {
|
|
88
118
|
color-scheme: light;
|
|
89
|
-
--background:
|
|
90
|
-
--foreground:
|
|
91
|
-
--card:
|
|
92
|
-
--card-foreground:
|
|
93
|
-
--popover:
|
|
94
|
-
--popover-foreground:
|
|
95
|
-
--primary:
|
|
96
|
-
--primary-foreground:
|
|
97
|
-
--secondary: 0
|
|
98
|
-
--secondary-foreground:
|
|
99
|
-
--muted:
|
|
100
|
-
--muted-foreground:
|
|
101
|
-
--accent:
|
|
102
|
-
--accent-foreground:
|
|
119
|
+
--background: 42 38.5% 94.9%;
|
|
120
|
+
--foreground: 30 13.2% 14.9%;
|
|
121
|
+
--card: 45 33.3% 97.6%;
|
|
122
|
+
--card-foreground: 30 13.2% 14.9%;
|
|
123
|
+
--popover: 45 33.3% 97.6%;
|
|
124
|
+
--popover-foreground: 30 13.2% 14.9%;
|
|
125
|
+
--primary: 260.6 36.1% 38%;
|
|
126
|
+
--primary-foreground: 42 38.5% 94.9%;
|
|
127
|
+
--secondary: 0 10.2% 90.4%;
|
|
128
|
+
--secondary-foreground: 30 13.2% 14.9%;
|
|
129
|
+
--muted: 18 15.6% 87.5%;
|
|
130
|
+
--muted-foreground: 33.3 9.8% 36.1%;
|
|
131
|
+
--accent: 324 7.5% 86.9%;
|
|
132
|
+
--accent-foreground: 30 13.2% 14.9%;
|
|
103
133
|
--destructive: 352 43% 49%;
|
|
104
134
|
--destructive-foreground: 0 0% 100%;
|
|
105
|
-
--border:
|
|
106
|
-
--input:
|
|
107
|
-
--ring:
|
|
108
|
-
--lineage:
|
|
109
|
-
--lineage-foreground:
|
|
135
|
+
--border: 36 13.5% 85.5%;
|
|
136
|
+
--input: 36 4% 51%;
|
|
137
|
+
--ring: 260.6 36.1% 38%;
|
|
138
|
+
--lineage: 260.6 36.1% 38%;
|
|
139
|
+
--lineage-foreground: 42 38.5% 94.9%;
|
|
110
140
|
--boundary: 202 34% 37%;
|
|
111
141
|
--boundary-foreground: 0 0% 100%;
|
|
112
142
|
--success: 160 48% 30%;
|
|
113
143
|
--success-foreground: 0 0% 100%;
|
|
114
144
|
--warning: 44 72% 36%;
|
|
115
145
|
--warning-foreground: 0 0% 100%;
|
|
116
|
-
--layout-sidebar:
|
|
117
|
-
--layout-list-header:
|
|
118
|
-
--layout-list-hover: 0
|
|
119
|
-
--layout-list-item:
|
|
120
|
-
--layout-list-selected:
|
|
121
|
-
--layout-content:
|
|
122
|
-
--purple-medium:
|
|
123
|
-
--purple-deep:
|
|
146
|
+
--layout-sidebar: 41.3 38.1% 91.8%;
|
|
147
|
+
--layout-list-header: 42 38.5% 94.9%;
|
|
148
|
+
--layout-list-hover: 0 10.2% 90.4%;
|
|
149
|
+
--layout-list-item: 45 33.3% 97.6%;
|
|
150
|
+
--layout-list-selected: 324 7.5% 86.9%;
|
|
151
|
+
--layout-content: 42 38.5% 94.9%;
|
|
152
|
+
--purple-medium: 260.6 36.1% 38%;
|
|
153
|
+
--purple-deep: 261.2 35.7% 28%;
|
|
124
154
|
--purple-light: 258 48% 84%;
|
|
155
|
+
--control-strong: 33.3 9.8% 36.1%;
|
|
156
|
+
--action-hover: 261 35.7% 32.9%;
|
|
157
|
+
--action-pressed: 261.2 35.7% 28%;
|
|
158
|
+
--tint-canvas: 0 10.2% 90.4%;
|
|
159
|
+
--tint-sunken: 18 15.6% 87.5%;
|
|
160
|
+
--tint-badge: 324 7.5% 86.9%;
|
|
161
|
+
/* 公共叠层:§8.2 层级表的唯一来源,页面不得自带数值 */
|
|
162
|
+
--layer-base: 0;
|
|
163
|
+
--layer-sticky: 10;
|
|
164
|
+
--layer-popover: 20;
|
|
165
|
+
--layer-backdrop: 30;
|
|
166
|
+
--layer-modal: 40;
|
|
167
|
+
--layer-toast: 50;
|
|
168
|
+
--scrim: 30 13.8% 11.4%;
|
|
125
169
|
}
|
|
126
170
|
|
|
127
171
|
html,
|
|
@@ -216,6 +260,11 @@
|
|
|
216
260
|
}
|
|
217
261
|
|
|
218
262
|
@layer components {
|
|
263
|
+
/* 弹层遮罩的唯一实现:颜色来自 --scrim,透明度不散落在页面 */
|
|
264
|
+
.xpod-overlay-scrim {
|
|
265
|
+
background-color: hsl(var(--scrim) / 0.45);
|
|
266
|
+
}
|
|
267
|
+
|
|
219
268
|
.warm-card {
|
|
220
269
|
border: 1px solid hsl(var(--border) / 0.5);
|
|
221
270
|
border-radius: var(--radius-xl);
|