@undefineds.co/xpod 0.4.19 → 0.4.20

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.
Files changed (136) hide show
  1. package/dist/api/container/common.js +2 -1
  2. package/dist/api/handlers/AiConfigHandler.js +10 -2
  3. package/dist/runtime/host/node/NodeRuntimeHost.js +7 -3
  4. package/dist/runtime/port-finder.d.ts +0 -5
  5. package/dist/runtime/port-finder.js +24 -12
  6. package/node_modules/@undefineds.co/extension-sdk/dist/react/solid-auth-boundary.d.ts +20 -2
  7. package/node_modules/@undefineds.co/extension-sdk/dist/react/solid-auth-boundary.js +142 -125
  8. package/node_modules/@undefineds.co/shared-ui/dist/focus.d.ts +1 -1
  9. package/node_modules/@undefineds.co/shared-ui/dist/focus.js +1 -1
  10. package/node_modules/@undefineds.co/shared-ui/dist/index.d.ts +1 -0
  11. package/node_modules/@undefineds.co/shared-ui/dist/index.js +1 -0
  12. package/node_modules/@undefineds.co/shared-ui/dist/login/LoginModal.d.ts +2 -0
  13. package/node_modules/@undefineds.co/shared-ui/dist/login/LoginModal.js +2 -0
  14. package/node_modules/@undefineds.co/shared-ui/dist/login/LoginView.d.ts +3 -0
  15. package/node_modules/@undefineds.co/shared-ui/dist/login/LoginView.js +3 -0
  16. package/node_modules/@undefineds.co/shared-ui/dist/login.d.ts +15 -0
  17. package/node_modules/@undefineds.co/shared-ui/dist/login.js +15 -0
  18. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/AccountSections.d.ts +141 -0
  19. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/AccountSections.js +67 -0
  20. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/ConsentView.d.ts +53 -0
  21. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/ConsentView.js +27 -0
  22. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/DeviceDialogs.d.ts +40 -0
  23. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/DeviceDialogs.js +33 -0
  24. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/IdpChrome.d.ts +15 -0
  25. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/IdpChrome.js +8 -0
  26. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/IdpViews.d.ts +93 -0
  27. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/IdpViews.js +88 -0
  28. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/NetworkPanel.d.ts +46 -0
  29. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/NetworkPanel.js +42 -0
  30. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/PodSignIn.d.ts +63 -0
  31. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/PodSignIn.js +65 -0
  32. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/PodSignInFrame.d.ts +31 -0
  33. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/PodSignInFrame.js +111 -0
  34. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/StorageBadge.d.ts +8 -0
  35. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/StorageBadge.js +7 -0
  36. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/XpodMark.d.ts +8 -0
  37. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/XpodMark.js +8 -0
  38. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/account-parts.d.ts +37 -0
  39. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/account-parts.js +33 -0
  40. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/copy.d.ts +156 -0
  41. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/copy.js +304 -0
  42. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/index.d.ts +20 -0
  43. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/index.js +18 -0
  44. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/parts.d.ts +69 -0
  45. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/parts.js +65 -0
  46. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/types.d.ts +14 -0
  47. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/types.js +1 -0
  48. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/webid-name.d.ts +5 -0
  49. package/node_modules/@undefineds.co/shared-ui/dist/pod-sign-in/webid-name.js +14 -0
  50. package/node_modules/@undefineds.co/shared-ui/dist/storage-bootstrap.d.ts +3 -0
  51. package/node_modules/@undefineds.co/shared-ui/dist/storage-bootstrap.js +3 -0
  52. package/node_modules/@undefineds.co/shared-ui/dist/theme.css +168 -83
  53. package/node_modules/@undefineds.co/shared-ui/dist/webid-auth.d.ts +5 -0
  54. package/node_modules/@undefineds.co/shared-ui/dist/webid-auth.js +5 -0
  55. package/package.json +2 -2
  56. package/static/app/assets/main.css +1 -1
  57. package/static/app/assets/main.js +55 -15
  58. package/static/dashboard/assets/{AiConfigContext-B5QP7ow2.js → AiConfigContext-CZEW16so.js} +1 -1
  59. package/static/dashboard/assets/{AiConfigPage-C_TdlUjq.js → AiConfigPage-Cfp0fRX1.js} +1 -1
  60. package/static/dashboard/assets/{DocumentProcessingPanel-CormNOdI.js → DocumentProcessingPanel-DaaRCLp6.js} +1 -1
  61. package/static/dashboard/assets/{IndexLifecyclePanel-S9wNNyHO.js → IndexLifecyclePanel-BCz3jNM8.js} +1 -1
  62. package/static/dashboard/assets/{IndexSubjectPanel-CofZT1oE.js → IndexSubjectPanel-DVCVIt7V.js} +1 -1
  63. package/static/dashboard/assets/ModelAssignmentsPanel-DxauxtEY.js +1 -0
  64. package/static/dashboard/assets/{ModelsPage-DZ46VnUh.js → ModelsPage-B8F3AtZL.js} +3 -3
  65. package/static/dashboard/assets/{NetworkPage-TwbIWASf.js → NetworkPage-Cu7ty71x.js} +2 -2
  66. package/static/dashboard/assets/{PaneListHeader-BtVnyutC.js → PaneListHeader-BEAXSlD9.js} +1 -1
  67. package/static/dashboard/assets/{SearchIndexingPanel-BCq_YMOP.js → SearchIndexingPanel-DEr1EDDC.js} +1 -1
  68. package/static/dashboard/assets/{StatusSubjectPanel-DsUKTysU.js → StatusSubjectPanel-Cg92MGhO.js} +1 -1
  69. package/static/dashboard/assets/{StatusWorkspace-CaVJBRqI.js → StatusWorkspace-BmJSOF3z.js} +1 -1
  70. package/static/dashboard/assets/{SystemSettingsPage-DRWfPjtu.js → SystemSettingsPage-rziu4Q3U.js} +1 -1
  71. package/static/dashboard/assets/SystemSettingsSubjectPanel-D16DGDNW.js +33 -0
  72. package/static/dashboard/assets/{XpodAiConnectionsPodStore-C9tHqutw.js → XpodAiConnectionsPodStore-FlZ0LEn0.js} +1 -1
  73. package/static/dashboard/assets/{activity-tgjewO88.js → activity-D55X-5L5.js} +1 -1
  74. package/static/dashboard/assets/{badge-Czun47II.js → badge-CRf1ISRJ.js} +1 -1
  75. package/static/dashboard/assets/{collection-runtime-DnYlU23-.js → collection-runtime-CfXMuwNc.js} +1 -1
  76. package/static/dashboard/assets/dashboard-B3kGI946.css +1 -0
  77. package/static/dashboard/assets/{dashboard-CF8SbVSR.js → dashboard-D4DWPaAy.js} +122 -122
  78. package/static/dashboard/assets/{dialog-D-Yc_lg-.js → dialog-EVyIyybL.js} +1 -1
  79. package/static/dashboard/assets/{download-vFuOkjCi.js → download-Et4aRDT2.js} +1 -1
  80. package/static/dashboard/assets/{external-link-Cg_VIecD.js → external-link-DT746o7t.js} +1 -1
  81. package/static/dashboard/assets/{index-IXCNeEwi.js → index-D2agcVRx.js} +3 -3
  82. package/static/dashboard/assets/{index-0au0WwkE.js → index-_wC13YGI.js} +1 -1
  83. package/static/dashboard/assets/{index-YDcVky3o.js → index-z6TnJzW6.js} +1 -1
  84. package/static/dashboard/assets/{key-round-9n1xgLbG.js → key-round-CHnogQ1D.js} +1 -1
  85. package/static/dashboard/assets/{rotate-ccw-DJ6s86DW.js → rotate-ccw-BNVDC4Zr.js} +1 -1
  86. package/static/dashboard/assets/{skeleton-Dg9HePtI.js → skeleton-BzsZekVf.js} +1 -1
  87. package/static/dashboard/assets/{waypoints-uxc_qOzk.js → waypoints-CLZA22UN.js} +1 -1
  88. package/static/dashboard/assets/{workspace-layout-BNtAXhPW.js → workspace-layout-urYcwAhS.js} +1 -1
  89. package/static/dashboard/dashboard.html +2 -2
  90. package/static/settings/assets/{AiConfigContext-y6ha7pGs.js → AiConfigContext-B2cVJFNu.js} +1 -1
  91. package/static/settings/assets/AiConfigPage-D_5jSPPF.js +1 -0
  92. package/static/settings/assets/{DocumentProcessingPanel-Oa_cxMcn.js → DocumentProcessingPanel-DodGlYIk.js} +1 -1
  93. package/static/settings/assets/{IndexLifecyclePanel-DlrnI0Kh.js → IndexLifecyclePanel-BtH-0GKv.js} +1 -1
  94. package/static/settings/assets/{IndexSubjectPanel-Dhsl0W32.js → IndexSubjectPanel-CqKhUcw2.js} +1 -1
  95. package/static/settings/assets/ModelAssignmentsPanel-Cam9V9BN.js +1 -0
  96. package/static/settings/assets/{ModelsPage-CuNW1hGX.js → ModelsPage-DWFic09l.js} +3 -3
  97. package/static/settings/assets/{NetworkPage-BBD2Lc_P.js → NetworkPage-CSwHoAWm.js} +2 -2
  98. package/static/settings/assets/{PaneListHeader-C81adSBX.js → PaneListHeader-270Z179Z.js} +1 -1
  99. package/static/settings/assets/{SearchIndexingPanel-Dc4QKWd0.js → SearchIndexingPanel-ATHKMDBQ.js} +1 -1
  100. package/static/settings/assets/{StatusSubjectPanel-DuxOvqzS.js → StatusSubjectPanel-DDWo3v3d.js} +1 -1
  101. package/static/settings/assets/StatusWorkspace-BYgqeCBM.js +1 -0
  102. package/static/settings/assets/SystemSettingsPage-BRaQAFWC.js +1 -0
  103. package/static/settings/assets/SystemSettingsSubjectPanel-Dc0roh9d.js +33 -0
  104. package/static/settings/assets/{XpodAiConnectionsPodStore-G0ClZksP.js → XpodAiConnectionsPodStore-OndzbigX.js} +2 -2
  105. package/static/settings/assets/{activity-DT8pzOea.js → activity-BAZEToJ3.js} +1 -1
  106. package/static/settings/assets/auth-callback-Bd3tvCOa.js +1 -0
  107. package/static/settings/assets/{badge-CvKRjSY2.js → badge-Cpol0LWF.js} +1 -1
  108. package/static/settings/assets/{collection-runtime-C6ZAp2cM.js → collection-runtime-B5vGx3gk.js} +1 -1
  109. package/static/settings/assets/{dialog-LFluK7Nx.js → dialog-_7AVvv5q.js} +1 -1
  110. package/static/settings/assets/{download-CZJeqUm1.js → download-DRAi-dnn.js} +1 -1
  111. package/static/settings/assets/{external-link-BsDft3Oe.js → external-link--Yq8inDb.js} +1 -1
  112. package/static/settings/assets/global-B3kGI946.css +1 -0
  113. package/static/settings/assets/{global-cmKEraT4.js → global-DMtP8ZF4.js} +111 -111
  114. package/static/settings/assets/{index-BiqSFOS1.js → index-C36H49PZ.js} +1 -1
  115. package/static/settings/assets/{index-XRgmPBKw.js → index-CQR3iePj.js} +1 -1
  116. package/static/settings/assets/{index-BMPlaRWG.js → index-DURnCfoQ.js} +1 -1
  117. package/static/settings/assets/{index-browser-B0slhJKc.js → index-browser-kAl2JmYB.js} +1 -1
  118. package/static/settings/assets/{key-round-D1XsWbN_.js → key-round-DzpWBVN9.js} +1 -1
  119. package/static/settings/assets/{rotate-ccw-CEe0P0fY.js → rotate-ccw-CtVsCcAx.js} +1 -1
  120. package/static/settings/assets/settings-DQtt6lql.js +1 -0
  121. package/static/settings/assets/{skeleton-DA404w6m.js → skeleton-R_ACks7d.js} +1 -1
  122. package/static/settings/assets/{waypoints-DJDWc4S9.js → waypoints-D-Qv_sME.js} +1 -1
  123. package/static/settings/assets/{workspace-layout-K38jT4OV.js → workspace-layout-BSMCQq35.js} +1 -1
  124. package/static/settings/auth-callback.html +3 -3
  125. package/static/settings/settings.html +3 -3
  126. package/static/dashboard/assets/ModelAssignmentsPanel-9tgOjj-y.js +0 -1
  127. package/static/dashboard/assets/SystemSettingsSubjectPanel-CgDP7Ii2.js +0 -33
  128. package/static/dashboard/assets/dashboard-DvuM3VTP.css +0 -1
  129. package/static/settings/assets/AiConfigPage-CIcIWdXA.js +0 -1
  130. package/static/settings/assets/ModelAssignmentsPanel-CHoiRZeL.js +0 -1
  131. package/static/settings/assets/StatusWorkspace-DeD3zi3G.js +0 -1
  132. package/static/settings/assets/SystemSettingsPage-8sHOaPb8.js +0 -1
  133. package/static/settings/assets/SystemSettingsSubjectPanel-B1JXut7S.js +0 -33
  134. package/static/settings/assets/auth-callback-1BlsOtMG.js +0 -1
  135. package/static/settings/assets/global-DvuM3VTP.css +0 -1
  136. package/static/settings/assets/settings-DfjkqEJ8.js +0 -1
@@ -0,0 +1,156 @@
1
+ /**
2
+ * User-facing wording of the Pod sign-in front door (spec §3).
3
+ *
4
+ * One vocabulary: WebID (the identity), sign-in service (the OIDC issuer),
5
+ * Pod (where data lives), Xpod Cloud / Xpod Edge (where a Pod lives). Hosts may
6
+ * override any string through the `copy` prop; they must not keep a second copy.
7
+ *
8
+ * Placeholders use `{name}` and are filled by `formatCopy`.
9
+ */
10
+ export type PodSignInLocale = 'zh-CN' | 'en';
11
+ export interface PodSignInCopy {
12
+ restoring: string;
13
+ enterApp: string;
14
+ reauthenticate: string;
15
+ useAnother: string;
16
+ expiredLine: string;
17
+ chooseTitle: string;
18
+ chooseLead: string;
19
+ useXpod: string;
20
+ useOtherSolid: string;
21
+ customLabel: string;
22
+ customPlaceholder: string;
23
+ customSubmit: string;
24
+ noAccount: string;
25
+ register: string;
26
+ noticeDetailsToggle: string;
27
+ noticeCopy: string;
28
+ noticeCopied: string;
29
+ whatIsPod: string;
30
+ whatIsPodBody: string;
31
+ whatIsWebId: string;
32
+ whatIsWebIdBody: string;
33
+ signInWith: string;
34
+ select: string;
35
+ selected: string;
36
+ choosePodTitle: string;
37
+ choosePodLead: string;
38
+ retry: string;
39
+ goCreate: string;
40
+ refreshPage: string;
41
+ startAndEnter: string;
42
+ openXpod: string;
43
+ noticeUnreachable: string;
44
+ noticeIncomplete: string;
45
+ noticeNoWebId: string;
46
+ noticeCancelled: string;
47
+ noticeLocalStopped: string;
48
+ noticePending: string;
49
+ serviceLabel: string;
50
+ signInTitle: string;
51
+ returnToApp: string;
52
+ email: string;
53
+ password: string;
54
+ forgotPassword: string;
55
+ rememberDevice: string;
56
+ signIn: string;
57
+ registerLink: string;
58
+ registerTitle: string;
59
+ username: string;
60
+ registerSubmit: string;
61
+ haveAccount: string;
62
+ podElsewhereSummary: string;
63
+ podElsewhereBody: string;
64
+ noWebIdTitle: string;
65
+ noWebIdLead: string;
66
+ webIdName: string;
67
+ noWebIdLocation: string;
68
+ createAndContinue: string;
69
+ chooseOtherLocation: string;
70
+ consentTitle: string;
71
+ unverifiedWarning: string;
72
+ chooseWebId: string;
73
+ consentConsequence: string;
74
+ requestDetails: string;
75
+ scopes: string;
76
+ clientId: string;
77
+ webIdFull: string;
78
+ rememberChoice: string;
79
+ manageAccount: string;
80
+ switchAccount: string;
81
+ deny: string;
82
+ allow: string;
83
+ storageCloud: string;
84
+ storageEdge: string;
85
+ webIdSectionTitle: string;
86
+ webIdEmpty: string;
87
+ createWebId: string;
88
+ linkExistingWebId: string;
89
+ podOnDevice: string;
90
+ authorizedApps: string;
91
+ createStepName: string;
92
+ createStepLocation: string;
93
+ createNameHint: string;
94
+ changeDevice: string;
95
+ cannotChangeLater: string;
96
+ createPod: string;
97
+ startDeviceXpod: string;
98
+ creatingNote: string;
99
+ cancel: string;
100
+ devicePickerTitle: string;
101
+ addDevice: string;
102
+ deviceSectionTitle: string;
103
+ deviceStatusOk: string;
104
+ deviceStatusUnreachable: string;
105
+ deviceStatusStopped: string;
106
+ deviceStatusOffline: string;
107
+ deviceCloud: string;
108
+ deviceEdge: string;
109
+ podCount: string;
110
+ networkAction: string;
111
+ fixAction: string;
112
+ collapseAction: string;
113
+ webIdSectionHint: string;
114
+ deviceSectionHint: string;
115
+ credentialSectionHint: string;
116
+ startAction: string;
117
+ networkTitle: string;
118
+ probeLocal: string;
119
+ probeLan: string;
120
+ probeWan: string;
121
+ probeIdle: string;
122
+ probeChecking: string;
123
+ probeOk: string;
124
+ probeFailed: string;
125
+ tunnelTitle: string;
126
+ enableAndRecheck: string;
127
+ enableAndCheck: string;
128
+ recheck: string;
129
+ skipForNow: string;
130
+ reachableVia: string;
131
+ networkFootnote: string;
132
+ addDeviceTitle: string;
133
+ stepInstall: string;
134
+ stepNetwork: string;
135
+ stepDone: string;
136
+ joinThisComputer: string;
137
+ installOnOther: string;
138
+ waitingForDevice: string;
139
+ deviceOnline: string;
140
+ finish: string;
141
+ useThisDevice: string;
142
+ credentialSectionTitle: string;
143
+ credentialEmpty: string;
144
+ createCredential: string;
145
+ revokeCredential: string;
146
+ resumeTitle: string;
147
+ resumeWaiting: string;
148
+ resumeReady: string;
149
+ resumeCancel: string;
150
+ resumeContinue: string;
151
+ close: string;
152
+ }
153
+ export declare const podSignInCopy: Record<PodSignInLocale, PodSignInCopy>;
154
+ export declare function resolvePodSignInCopy(locale?: PodSignInLocale, overrides?: Partial<PodSignInCopy>): PodSignInCopy;
155
+ /** Fills `{name}` placeholders; unknown placeholders are left untouched. */
156
+ export declare function formatCopy(template: string, values: Record<string, string | number | undefined>): string;
@@ -0,0 +1,304 @@
1
+ /**
2
+ * User-facing wording of the Pod sign-in front door (spec §3).
3
+ *
4
+ * One vocabulary: WebID (the identity), sign-in service (the OIDC issuer),
5
+ * Pod (where data lives), Xpod Cloud / Xpod Edge (where a Pod lives). Hosts may
6
+ * override any string through the `copy` prop; they must not keep a second copy.
7
+ *
8
+ * Placeholders use `{name}` and are filled by `formatCopy`.
9
+ */
10
+ const zhCN = {
11
+ restoring: '正在恢复登录…',
12
+ enterApp: '进入 {app}',
13
+ reauthenticate: '重新登录',
14
+ useAnother: '使用其他账号',
15
+ expiredLine: '登录已过期,需要重新确认',
16
+ chooseTitle: '登录',
17
+ chooseLead: '用你的 WebID 账号登录,数据保存在你自己的 Pod 里',
18
+ useXpod: '使用 Xpod 账号登录',
19
+ useOtherSolid: '使用其他 Solid 账号',
20
+ customLabel: '账号服务地址或 WebID',
21
+ customPlaceholder: 'https://example.com/',
22
+ customSubmit: '继续',
23
+ noAccount: '没有账号?',
24
+ register: '注册 Xpod',
25
+ noticeDetailsToggle: '详情',
26
+ noticeCopy: '复制',
27
+ noticeCopied: '已复制',
28
+ whatIsPod: '什么是 Pod?',
29
+ whatIsPodBody: 'Pod 是保存你数据的个人空间。',
30
+ whatIsWebId: '什么是 WebID?',
31
+ whatIsWebIdBody: 'WebID 是登录用的身份,它指向你的个人资料和 Pod。',
32
+ signInWith: '使用 {service} 登录',
33
+ select: '选择',
34
+ selected: '已选择',
35
+ choosePodTitle: '选择 Pod',
36
+ choosePodLead: '选择要继续使用的 Pod',
37
+ retry: '重试',
38
+ goCreate: '去创建',
39
+ refreshPage: '刷新页面',
40
+ startAndEnter: '启动 Xpod 并进入',
41
+ openXpod: '打开 Xpod',
42
+ noticeUnreachable: '暂时连不上 Xpod,请稍后再试',
43
+ noticeIncomplete: '登录没有完成,请再试一次',
44
+ noticeNoWebId: '还没有 WebID',
45
+ noticeCancelled: '登录已取消',
46
+ noticeLocalStopped: '这台电脑上的 Xpod 没有运行',
47
+ noticePending: '上次登录尚未结束',
48
+ serviceLabel: '账号服务',
49
+ signInTitle: '登录 {service}',
50
+ returnToApp: '完成后回到 {app}',
51
+ email: '邮箱',
52
+ password: '密码',
53
+ forgotPassword: '忘记密码?',
54
+ rememberDevice: '在这台设备上保持登录',
55
+ signIn: '登录',
56
+ registerLink: '注册账号',
57
+ registerTitle: '注册 {service}',
58
+ username: '用户名',
59
+ registerSubmit: '注册',
60
+ haveAccount: '已有账号?登录',
61
+ podElsewhereSummary: '想用你自己的独立部署存放 Pod?',
62
+ podElsewhereBody: '注册后,可以在账号页的“存储”里把 Pod 建到你自己的独立部署上;它和当前账号服务是分开的,普通浏览器不会自动把 Pod 转到本机。',
63
+ noWebIdTitle: '还没有 WebID',
64
+ noWebIdLead: '新建一个 WebID 来登录 {app},数据存在它的 Pod 里',
65
+ webIdName: 'WebID 名称',
66
+ noWebIdLocation: '存放在当前服务',
67
+ createAndContinue: '创建并继续',
68
+ chooseOtherLocation: '存到边缘设备(打开账号页)',
69
+ consentTitle: '授权 {app}',
70
+ unverifiedWarning: '未能验证这个应用的来源,请确认是你要使用的应用',
71
+ chooseWebId: '用哪个 WebID 登录?',
72
+ consentConsequence: '{app} 将以这个身份读写你的数据,之后可以在 Xpod 中收回。',
73
+ requestDetails: '请求详情',
74
+ scopes: '权限范围',
75
+ clientId: '应用标识',
76
+ webIdFull: 'WebID',
77
+ rememberChoice: '以后不再询问',
78
+ manageAccount: '管理账号',
79
+ switchAccount: '换一个账号',
80
+ deny: '拒绝',
81
+ allow: '允许',
82
+ storageCloud: '数据存在 Xpod 云端',
83
+ storageEdge: '数据存在边缘设备上',
84
+ webIdSectionTitle: 'WebID',
85
+ webIdEmpty: '还没有 WebID。新建一个,用它登录应用。',
86
+ createWebId: '新建 WebID',
87
+ linkExistingWebId: '关联已有 WebID',
88
+ podOnDevice: 'Pod 在 {device}',
89
+ authorizedApps: '已授权 {count} 个应用',
90
+ createStepName: '名称',
91
+ createStepLocation: '存放在',
92
+ createNameHint: 'WebID 地址',
93
+ changeDevice: '更换 ›',
94
+ cannotChangeLater: '创建后不能直接更换,以后要换请使用迁移',
95
+ createPod: '创建 WebID 和 Pod',
96
+ startDeviceXpod: '启动这台设备上的 Xpod',
97
+ creatingNote: '关闭页面不会中断创建',
98
+ cancel: '取消',
99
+ devicePickerTitle: '选择存放设备',
100
+ addDevice: '+ 添加设备',
101
+ deviceSectionTitle: '设备',
102
+ deviceStatusOk: '正常',
103
+ deviceStatusUnreachable: '⚠ 其他设备访问不到',
104
+ deviceStatusStopped: 'Xpod 已停止',
105
+ deviceStatusOffline: '离线',
106
+ deviceCloud: 'Xpod 云端',
107
+ deviceEdge: '边缘',
108
+ podCount: '{count} 个 Pod',
109
+ networkAction: '网络',
110
+ fixAction: '处理',
111
+ collapseAction: '收起',
112
+ webIdSectionHint: '登录应用时使用的身份,数据存在它的 Pod 里',
113
+ deviceSectionHint: 'Pod 可以存放的地方,网络设置跟着设备走',
114
+ credentialSectionHint: '让脚本或服务以某个 WebID 直接访问 Pod',
115
+ startAction: '启动',
116
+ networkTitle: '网络访问',
117
+ probeLocal: '这台电脑',
118
+ probeLan: '局域网',
119
+ probeWan: '其他网络',
120
+ probeIdle: '未检测',
121
+ probeChecking: '检测中',
122
+ probeOk: '可以访问',
123
+ probeFailed: '不通',
124
+ tunnelTitle: '选择隧道',
125
+ enableAndRecheck: '开启并重新检测',
126
+ enableAndCheck: '开启并检测',
127
+ recheck: '重新检测',
128
+ skipForNow: '跳过,稍后设置',
129
+ reachableVia: '通过 {tunnel} 可以访问',
130
+ networkFootnote: '只影响其他设备;这台电脑上照常可用',
131
+ addDeviceTitle: '添加设备',
132
+ stepInstall: '安装并登录',
133
+ stepNetwork: '检查网络',
134
+ stepDone: '完成',
135
+ joinThisComputer: '把这台电脑加入',
136
+ installOnOther: '在那台设备上安装 Xpod 边缘并登录本账号',
137
+ waitingForDevice: '正在等待新设备上线,登录后这里会自动继续',
138
+ deviceOnline: '已上线',
139
+ finish: '完成',
140
+ useThisDevice: '用这台设备',
141
+ credentialSectionTitle: '密钥',
142
+ credentialEmpty: '还没有密钥。',
143
+ createCredential: '新建密钥',
144
+ revokeCredential: '删除',
145
+ resumeTitle: '{app} 正在等你完成授权',
146
+ resumeWaiting: '在下面新建一个 WebID,完成后就能回去授权',
147
+ resumeReady: 'WebID 已就绪,可以回去授权了',
148
+ resumeCancel: '取消授权',
149
+ resumeContinue: '继续授权 {app}',
150
+ close: '关闭',
151
+ };
152
+ const en = {
153
+ restoring: 'Restoring your sign-in…',
154
+ enterApp: 'Open {app}',
155
+ reauthenticate: 'Sign in again',
156
+ useAnother: 'Use another account',
157
+ expiredLine: 'Your sign-in expired. Please confirm again.',
158
+ chooseTitle: 'Sign in',
159
+ chooseLead: 'Sign in with your WebID account. Your data stays in your own Pod.',
160
+ useXpod: 'Sign in with Xpod',
161
+ useOtherSolid: 'Use another Solid account',
162
+ customLabel: 'Sign-in service address or WebID',
163
+ customPlaceholder: 'https://example.com/',
164
+ customSubmit: 'Continue',
165
+ noAccount: 'No account?',
166
+ register: 'Register for Xpod',
167
+ noticeDetailsToggle: 'Details',
168
+ noticeCopy: 'Copy',
169
+ noticeCopied: 'Copied',
170
+ whatIsPod: 'What is a Pod?',
171
+ whatIsPodBody: 'A Pod is a personal space that holds your data.',
172
+ whatIsWebId: 'What is a WebID?',
173
+ whatIsWebIdBody: 'A WebID is the identity you sign in with. It points to your profile and your Pod.',
174
+ signInWith: 'Sign in with {service}',
175
+ select: 'Select',
176
+ selected: 'Selected',
177
+ choosePodTitle: 'Choose a Pod',
178
+ choosePodLead: 'Choose the Pod to continue with',
179
+ retry: 'Retry',
180
+ goCreate: 'Create one',
181
+ refreshPage: 'Refresh page',
182
+ startAndEnter: 'Start Xpod and open',
183
+ openXpod: 'Open Xpod',
184
+ noticeUnreachable: 'Cannot reach Xpod right now. Please try again later.',
185
+ noticeIncomplete: 'Sign-in did not finish. Please try again.',
186
+ noticeNoWebId: 'No WebID yet',
187
+ noticeCancelled: 'Sign-in cancelled',
188
+ noticeLocalStopped: 'Xpod is not running on this computer',
189
+ noticePending: 'The previous sign-in has not finished',
190
+ serviceLabel: 'Sign-in service',
191
+ signInTitle: 'Sign in to {service}',
192
+ returnToApp: 'You will return to {app}',
193
+ email: 'Email',
194
+ password: 'Password',
195
+ forgotPassword: 'Forgot password?',
196
+ rememberDevice: 'Keep me signed in on this device',
197
+ signIn: 'Sign in',
198
+ registerLink: 'Register',
199
+ registerTitle: 'Register for {service}',
200
+ username: 'Username',
201
+ registerSubmit: 'Register',
202
+ haveAccount: 'Already have an account? Sign in',
203
+ podElsewhereSummary: 'Want it on your own standalone deployment?',
204
+ podElsewhereBody: 'After registering, create the Pod on your own standalone deployment under Storage on the account page; it is separate from this account service.',
205
+ noWebIdTitle: 'No WebID yet',
206
+ noWebIdLead: 'Create a WebID to sign in to {app}. Your data lives in its Pod.',
207
+ webIdName: 'WebID name',
208
+ noWebIdLocation: 'Stored on the current service',
209
+ createAndContinue: 'Create and continue',
210
+ chooseOtherLocation: 'Store on an edge device (open account page)',
211
+ consentTitle: 'Authorize {app}',
212
+ unverifiedWarning: 'We could not verify this application. Make sure it is the one you meant to use.',
213
+ chooseWebId: 'Which WebID do you sign in with?',
214
+ consentConsequence: '{app} will read and write your data as this identity. You can revoke it later in Xpod.',
215
+ requestDetails: 'Request details',
216
+ scopes: 'Permissions',
217
+ clientId: 'Application ID',
218
+ webIdFull: 'WebID',
219
+ rememberChoice: 'Do not ask again',
220
+ manageAccount: 'Manage account',
221
+ switchAccount: 'Switch account',
222
+ deny: 'Deny',
223
+ allow: 'Allow',
224
+ storageCloud: 'Data is stored on Xpod Cloud',
225
+ storageEdge: 'Data is stored on an edge device',
226
+ webIdSectionTitle: 'WebID',
227
+ webIdEmpty: 'No WebID yet. Create one to sign in to applications.',
228
+ createWebId: 'New WebID',
229
+ linkExistingWebId: 'Link an existing WebID',
230
+ podOnDevice: 'Pod on {device}',
231
+ authorizedApps: '{count} authorized apps',
232
+ createStepName: 'Name',
233
+ createStepLocation: 'Store on',
234
+ createNameHint: 'WebID address',
235
+ changeDevice: 'Change ›',
236
+ cannotChangeLater: 'It cannot be changed directly after creation. Use migration later.',
237
+ createPod: 'Create WebID and Pod',
238
+ startDeviceXpod: 'Start Xpod on this device',
239
+ creatingNote: 'Closing this page will not interrupt creation',
240
+ cancel: 'Cancel',
241
+ devicePickerTitle: 'Choose where to store',
242
+ addDevice: '+ Add device',
243
+ deviceSectionTitle: 'Devices',
244
+ deviceStatusOk: 'Healthy',
245
+ deviceStatusUnreachable: '⚠ Not reachable from other devices',
246
+ deviceStatusStopped: 'Xpod stopped',
247
+ deviceStatusOffline: 'Offline',
248
+ deviceCloud: 'Xpod Cloud',
249
+ deviceEdge: 'Edge',
250
+ podCount: '{count} Pods',
251
+ networkAction: 'Network',
252
+ fixAction: 'Fix',
253
+ collapseAction: 'Collapse',
254
+ webIdSectionHint: 'The identity you sign in to apps with. Your data lives in its Pod.',
255
+ deviceSectionHint: 'Places a Pod can live. Network settings follow the device.',
256
+ credentialSectionHint: 'Let a script or service reach a Pod directly as one WebID.',
257
+ startAction: 'Start',
258
+ networkTitle: 'Network access',
259
+ probeLocal: 'This computer',
260
+ probeLan: 'Local network',
261
+ probeWan: 'Other networks',
262
+ probeIdle: 'Not checked',
263
+ probeChecking: 'Checking',
264
+ probeOk: 'Reachable',
265
+ probeFailed: 'Unreachable',
266
+ tunnelTitle: 'Choose a tunnel',
267
+ enableAndRecheck: 'Enable and recheck',
268
+ enableAndCheck: 'Enable and check',
269
+ recheck: 'Recheck',
270
+ skipForNow: 'Skip, set up later',
271
+ reachableVia: 'Reachable through {tunnel}',
272
+ networkFootnote: 'Only affects other devices. This computer keeps working as usual.',
273
+ addDeviceTitle: 'Add a device',
274
+ stepInstall: 'Install and sign in',
275
+ stepNetwork: 'Check network',
276
+ stepDone: 'Done',
277
+ joinThisComputer: 'Add this computer',
278
+ installOnOther: 'Install Xpod Edge on that device and sign in to this account',
279
+ waitingForDevice: 'Waiting for the new device to come online. This continues automatically after sign-in.',
280
+ deviceOnline: 'Online',
281
+ finish: 'Done',
282
+ useThisDevice: 'Use this device',
283
+ credentialSectionTitle: 'Credentials',
284
+ credentialEmpty: 'No credentials yet.',
285
+ createCredential: 'New credential',
286
+ revokeCredential: 'Delete',
287
+ resumeTitle: '{app} is waiting for you to finish authorizing',
288
+ resumeWaiting: 'Create a WebID below, then you can go back and authorize',
289
+ resumeReady: 'Your WebID is ready. You can go back and authorize.',
290
+ resumeCancel: 'Cancel authorization',
291
+ resumeContinue: 'Continue authorizing {app}',
292
+ close: 'Close',
293
+ };
294
+ export const podSignInCopy = { 'zh-CN': zhCN, en };
295
+ export function resolvePodSignInCopy(locale = 'zh-CN', overrides) {
296
+ return { ...podSignInCopy[locale], ...overrides };
297
+ }
298
+ /** Fills `{name}` placeholders; unknown placeholders are left untouched. */
299
+ export function formatCopy(template, values) {
300
+ return template.replace(/\{(\w+)\}/g, (match, key) => {
301
+ const value = values[key];
302
+ return value === undefined ? match : String(value);
303
+ });
304
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Pod sign-in front door: one presentation for every host (spec
3
+ * docs/superpowers/specs/2026-09-29-shared-ui-pod-sign-in-design.md).
4
+ * These components only render; hosts own requests, redirects and storage.
5
+ */
6
+ export { PodSignInFrame, type PodSignInFrameProps } from './PodSignInFrame';
7
+ export { StorageBadge, type StorageBadgeProps } from './StorageBadge';
8
+ export { IdpChrome, type IdpChromeProps } from './IdpChrome';
9
+ export { XpodMark } from './XpodMark';
10
+ export { ScreenLayout, SourceMark } from './parts';
11
+ export { PodSignIn, type PodSignInNotice, type PodSignInProps, type PodSignInState, type RememberedIdentity, } from './PodSignIn';
12
+ export { IdpNoWebIdView, IdpRegisterView, IdpSignInView, type IdpNoWebIdViewProps, type IdpRegisterViewProps, type IdpSignInViewProps, type IdpViewCommonProps, } from './IdpViews';
13
+ export { ConsentView, type ConsentViewProps, type ConsentWebId } from './ConsentView';
14
+ export { ConsentResumeBanner, CreateWebIdForm, CredentialSection, DeviceSection, WebIdSection, type ConsentResumeBannerProps, type CreateWebIdFormProps, type CredentialEntry, type CredentialSectionProps, type DeviceSectionProps, type UnlinkedPodEntry, type WebIdEntry, type WebIdSectionProps, } from './AccountSections';
15
+ export { AddDeviceDialog, DevicePickerDialog, type AddDeviceDialogProps, type AddDeviceStep, type DevicePickerDialogProps, } from './DeviceDialogs';
16
+ export { NetworkPanel, type NetworkChecks, type NetworkPanelProps, type ProbeState, type TunnelFieldDescriptor, type TunnelOption, } from './NetworkPanel';
17
+ export type { DeviceStatus, DeviceSummary } from './account-parts';
18
+ export { formatCopy, podSignInCopy, resolvePodSignInCopy, type PodSignInCopy, type PodSignInLocale, } from './copy';
19
+ export type { AppIdentity, SignInPresentation, StorageLocation, StorageLocationKind, } from './types';
20
+ export { webIdShortName } from './webid-name';
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Pod sign-in front door: one presentation for every host (spec
3
+ * docs/superpowers/specs/2026-09-29-shared-ui-pod-sign-in-design.md).
4
+ * These components only render; hosts own requests, redirects and storage.
5
+ */
6
+ export { PodSignInFrame } from './PodSignInFrame.js';
7
+ export { StorageBadge } from './StorageBadge.js';
8
+ export { IdpChrome } from './IdpChrome.js';
9
+ export { XpodMark } from './XpodMark.js';
10
+ export { ScreenLayout, SourceMark } from './parts.js';
11
+ export { PodSignIn, } from './PodSignIn.js';
12
+ export { IdpNoWebIdView, IdpRegisterView, IdpSignInView, } from './IdpViews.js';
13
+ export { ConsentView } from './ConsentView.js';
14
+ export { ConsentResumeBanner, CreateWebIdForm, CredentialSection, DeviceSection, WebIdSection, } from './AccountSections.js';
15
+ export { AddDeviceDialog, DevicePickerDialog, } from './DeviceDialogs.js';
16
+ export { NetworkPanel, } from './NetworkPanel.js';
17
+ export { formatCopy, podSignInCopy, resolvePodSignInCopy, } from './copy.js';
18
+ export { webIdShortName } from './webid-name.js';
@@ -0,0 +1,69 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type ButtonProps } from '../button';
3
+ import type { StorageLocation } from './types';
4
+ /** Every screen-level control shares these sizes (spec §5): 44px primary/outline, 36px text. */
5
+ export declare const primaryButtonClass = "h-11 w-full rounded-lg text-sm font-medium";
6
+ export declare const outlineButtonClass = "h-11 w-full rounded-lg text-sm font-medium";
7
+ export declare const textButtonClass = "h-9 rounded-lg px-2 text-sm font-medium";
8
+ export declare const fieldClass = "h-11 w-full rounded-lg border border-input bg-card px-3 text-sm text-foreground placeholder:text-muted-foreground disabled:opacity-60";
9
+ export declare function Spinner({ className }: {
10
+ className?: string;
11
+ }): import("react").JSX.Element;
12
+ /** Button that shows a spinner and disables itself while `busy` (no separate "verifying" screen). */
13
+ export declare function ActionButton({ busy, children, disabled, ...props }: ButtonProps & {
14
+ busy?: boolean;
15
+ }): import("react").JSX.Element;
16
+ /** One-line source mark: 24px icon and 13px name. It is not a heading. */
17
+ export declare function SourceMark({ icon, name }: {
18
+ icon?: ReactNode;
19
+ name: string;
20
+ }): import("react").JSX.Element;
21
+ export declare function Hostname({ children, className }: {
22
+ children: ReactNode;
23
+ className?: string;
24
+ }): import("react").JSX.Element;
25
+ export declare function PodAvatar({ name, avatarUrl, storage, size, }: {
26
+ name: string;
27
+ avatarUrl?: string;
28
+ storage?: StorageLocation;
29
+ size?: number;
30
+ }): import("react").JSX.Element;
31
+ /** Label + control + inline error, wired with aria-describedby. */
32
+ export declare function Field({ label, error, hint, labelAside, children, }: {
33
+ label: string;
34
+ error?: string;
35
+ hint?: ReactNode;
36
+ labelAside?: ReactNode;
37
+ children: (props: {
38
+ id: string;
39
+ 'aria-invalid'?: true;
40
+ 'aria-describedby'?: string;
41
+ }) => ReactNode;
42
+ }): import("react").JSX.Element;
43
+ /** Secondary information stays folded until asked for (spec §4). */
44
+ export declare function Disclosure({ summary, children, className }: {
45
+ summary: string;
46
+ children: ReactNode;
47
+ className?: string;
48
+ }): import("react").JSX.Element;
49
+ export declare function CheckboxRow({ checked, onChange, label, disabled, }: {
50
+ checked: boolean;
51
+ onChange(value: boolean): void;
52
+ label: string;
53
+ disabled?: boolean;
54
+ }): import("react").JSX.Element;
55
+ /** Fires `open` after `delayMs`; used so fast restores show no intermediate UI. */
56
+ export declare function usePastDelay(delayMs: number): boolean;
57
+ /**
58
+ * One screen: an optional top bar, a scrolling main area, and an action area
59
+ * pinned to the bottom so the primary action and errors are always visible.
60
+ * Pass `onSubmit` to make the whole screen one form (actions submit it).
61
+ */
62
+ export declare function ScreenLayout({ chrome, children, actions, onSubmit, mainClassName, ...state }: {
63
+ chrome?: ReactNode;
64
+ children: ReactNode;
65
+ actions?: ReactNode;
66
+ onSubmit?: (event: React.FormEvent<HTMLFormElement>) => void;
67
+ mainClassName?: string;
68
+ 'data-pod-sign-in-state'?: string;
69
+ }): import("react").JSX.Element;
@@ -0,0 +1,65 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Loader2 } from 'lucide-react';
3
+ import { useEffect, useId, useState } from 'react';
4
+ import { Avatar, AvatarFallback, AvatarImage } from '../avatar.js';
5
+ import { Button } from '../button.js';
6
+ import { cn } from '../utils.js';
7
+ import { StorageBadge } from './StorageBadge.js';
8
+ /** Every screen-level control shares these sizes (spec §5): 44px primary/outline, 36px text. */
9
+ export const primaryButtonClass = 'h-11 w-full rounded-lg text-sm font-medium';
10
+ export const outlineButtonClass = 'h-11 w-full rounded-lg text-sm font-medium';
11
+ export const textButtonClass = 'h-9 rounded-lg px-2 text-sm font-medium';
12
+ export const fieldClass = 'h-11 w-full rounded-lg border border-input bg-card px-3 text-sm text-foreground placeholder:text-muted-foreground disabled:opacity-60';
13
+ export function Spinner({ className }) {
14
+ return _jsx(Loader2, { "aria-hidden": "true", className: cn('h-4 w-4 shrink-0 animate-spin motion-reduce:animate-none', className) });
15
+ }
16
+ /** Button that shows a spinner and disables itself while `busy` (no separate "verifying" screen). */
17
+ export function ActionButton({ busy = false, children, disabled, ...props }) {
18
+ return (_jsxs(Button, { type: "button", ...props, disabled: disabled || busy, "aria-busy": busy || undefined, children: [busy ? _jsx(Spinner, { className: "mr-2" }) : null, children] }));
19
+ }
20
+ /** One-line source mark: 24px icon and 13px name. It is not a heading. */
21
+ export function SourceMark({ icon, name }) {
22
+ return (_jsxs("div", { "data-pod-sign-in": "source", className: "flex h-6 items-center gap-2 text-[13px] text-muted-foreground", children: [icon ? _jsx("span", { "aria-hidden": "true", className: "flex h-6 w-6 shrink-0 items-center justify-center overflow-hidden rounded-md", children: icon }) : null, _jsx("span", { className: "truncate", children: name })] }));
23
+ }
24
+ export function Hostname({ children, className }) {
25
+ return _jsx("span", { className: cn('font-mono text-xs text-muted-foreground', className), children: children });
26
+ }
27
+ export function PodAvatar({ name, avatarUrl, storage, size = 56, }) {
28
+ return (_jsxs("span", { className: "relative inline-flex shrink-0", style: { width: size, height: size }, "data-pod-sign-in": "avatar", children: [_jsxs(Avatar, { className: "h-full w-full rounded-full", "aria-hidden": "true", children: [avatarUrl ? _jsx(AvatarImage, { src: avatarUrl, alt: "" }) : null, _jsx(AvatarFallback, { className: "text-base", children: Array.from(name.trim())[0]?.toUpperCase() ?? '?' })] }), storage ? (_jsx("span", { className: "absolute -bottom-0.5 -right-0.5", children: _jsx(StorageBadge, { kind: storage.kind, label: storage.label }) })) : null] }));
29
+ }
30
+ /** Label + control + inline error, wired with aria-describedby. */
31
+ export function Field({ label, error, hint, labelAside, children, }) {
32
+ const id = useId();
33
+ const errorId = `${id}-error`;
34
+ const hintId = `${id}-hint`;
35
+ const describedBy = [error ? errorId : undefined, hint ? hintId : undefined].filter(Boolean).join(' ') || undefined;
36
+ return (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("label", { htmlFor: id, className: "text-[13px] font-medium text-foreground", children: label }), labelAside] }), children({ id, ...(error ? { 'aria-invalid': true } : {}), 'aria-describedby': describedBy }), error ? _jsx("p", { id: errorId, role: "alert", className: "text-[13px] text-destructive", children: error }) : null, hint ? _jsx("div", { id: hintId, className: "text-[13px] text-muted-foreground", children: hint }) : null] }));
37
+ }
38
+ /** Secondary information stays folded until asked for (spec §4). */
39
+ export function Disclosure({ summary, children, className }) {
40
+ return (_jsxs("details", { className: cn('text-[13px] text-muted-foreground', className), children: [_jsx("summary", { className: "cursor-pointer select-none rounded py-1 text-[13px] font-medium text-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring", children: summary }), _jsx("div", { className: "pt-1 leading-5", children: children })] }));
41
+ }
42
+ export function CheckboxRow({ checked, onChange, label, disabled, }) {
43
+ return (_jsxs("label", { className: "flex min-h-9 cursor-pointer items-center gap-2 text-sm text-foreground", children: [_jsx("input", { type: "checkbox", className: "h-4 w-4 rounded", checked: checked, disabled: disabled, onChange: (event) => onChange(event.target.checked) }), label] }));
44
+ }
45
+ /** Fires `open` after `delayMs`; used so fast restores show no intermediate UI. */
46
+ export function usePastDelay(delayMs) {
47
+ const [elapsed, setElapsed] = useState(false);
48
+ useEffect(() => {
49
+ const timer = setTimeout(() => setElapsed(true), delayMs);
50
+ return () => clearTimeout(timer);
51
+ }, [delayMs]);
52
+ return elapsed;
53
+ }
54
+ /**
55
+ * One screen: an optional top bar, a scrolling main area, and an action area
56
+ * pinned to the bottom so the primary action and errors are always visible.
57
+ * Pass `onSubmit` to make the whole screen one form (actions submit it).
58
+ */
59
+ export function ScreenLayout({ chrome, children, actions, onSubmit, mainClassName, ...state }) {
60
+ const inner = (_jsxs(_Fragment, { children: [chrome, _jsx("div", { "data-pod-sign-in": "main", className: cn('flex min-h-0 flex-1 flex-col gap-5 overflow-y-auto px-6 pb-2 pt-5', mainClassName), children: children }), actions ? _jsx("div", { "data-pod-sign-in": "actions", className: "flex shrink-0 flex-col gap-3 px-6 pb-6 pt-3", children: actions }) : null] }));
61
+ const className = 'flex min-h-0 flex-1 flex-col';
62
+ return onSubmit
63
+ ? _jsx("form", { ...state, onSubmit: onSubmit, className: className, noValidate: true, children: inner })
64
+ : _jsx("div", { ...state, className: className, children: inner });
65
+ }
@@ -0,0 +1,14 @@
1
+ import type { ReactNode } from 'react';
2
+ export type SignInPresentation = 'window' | 'dialog' | 'page';
3
+ /** Application-side source mark. The component never hard-codes an application. */
4
+ export interface AppIdentity {
5
+ name: string;
6
+ icon?: ReactNode;
7
+ }
8
+ /** Where a Pod lives: Xpod Cloud, or an edge device (this computer, a NAS...). */
9
+ export type StorageLocationKind = 'cloud' | 'edge';
10
+ export interface StorageLocation {
11
+ kind: StorageLocationKind;
12
+ /** Announced by screen readers and shown on hover. */
13
+ label: string;
14
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Short display name for a WebID that has no remembered profile: the last
3
+ * meaningful path segment (`/alice/profile/card#me` -> `alice`), else the host.
4
+ */
5
+ export declare function webIdShortName(webId: string): string;