@tinycloud/web-sdk 3.8.0-beta.9 → 3.8.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/adapters/BrowserSessionStorage.d.ts +17 -0
- package/dist/credentials.cjs +1 -1
- package/dist/credentials.mjs +1 -1
- package/dist/delegations-issued-entry.d.ts +3 -0
- package/dist/delegations-issued.cjs +1 -0
- package/dist/delegations-issued.mjs +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +1 -1
- package/dist/modals.cjs +1 -1
- package/dist/modals.mjs +1 -1
- package/dist/modules/Storage/tinycloud/types.schema.d.ts +2 -2
- package/dist/modules/requestPermissionsCore.d.ts +8 -1
- package/dist/modules/runtimeGrantPersistence.d.ts +41 -0
- package/dist/modules/tcw.d.ts +52 -1
- package/dist/panel.cjs +1 -1
- package/dist/panel.mjs +1 -1
- package/dist/ui/api.d.ts +8 -0
- package/dist/ui/client.d.ts +14 -2
- package/dist/ui/config.d.ts +9 -0
- package/dist/ui/data/authority.d.ts +9 -1
- package/dist/ui/host.d.ts +2 -0
- package/dist/ui/panel-styles.d.ts +1 -1
- package/dist/ui/pending.d.ts +1 -1
- package/dist/ui/sections/delegations.strings.d.ts +5 -0
- package/dist/ui/slots.d.ts +13 -1
- package/dist/ui/styles.d.ts +1 -1
- package/package.json +6 -6
package/dist/ui/api.d.ts
CHANGED
|
@@ -12,6 +12,13 @@ export interface TinyCloudUI {
|
|
|
12
12
|
/** Closes the panel only. Never changes the hidden flag. */
|
|
13
13
|
close(): void;
|
|
14
14
|
toggle(): void;
|
|
15
|
+
/**
|
|
16
|
+
* Shows or hides the floating button now. `true` shows it even under `ui.button: false` for this page
|
|
17
|
+
* session and clears the persisted hidden flag. `false` hides it without writing that flag. The SDK
|
|
18
|
+
* does not persist the choice: the host app calls this on load from its own setting. `open()`,
|
|
19
|
+
* `openPage()` and `toggle()` work whether the button is shown or not.
|
|
20
|
+
*/
|
|
21
|
+
setButtonVisible(visible: boolean): void;
|
|
15
22
|
readonly isOpen: boolean;
|
|
16
23
|
/** False in iframes, opaque origins, SSR, no document, or when `ui: false`. */
|
|
17
24
|
readonly available: boolean;
|
|
@@ -21,6 +28,7 @@ export interface UiTarget {
|
|
|
21
28
|
openPage(section?: SectionId): void;
|
|
22
29
|
close(): void;
|
|
23
30
|
isOpen(): boolean;
|
|
31
|
+
setButtonVisible(visible: boolean): void;
|
|
24
32
|
}
|
|
25
33
|
/**
|
|
26
34
|
* `getTarget` returns undefined when this client is not registered (ui:false,
|
package/dist/ui/client.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { IStorageService } from "@tinycloud/sdk-core";
|
|
1
|
+
import type { IStorageService, PermissionEntry } from "@tinycloud/sdk-core";
|
|
2
2
|
import type { PanelDataFactory } from "./data";
|
|
3
|
+
import type { UiPlatform } from "./config";
|
|
3
4
|
import type { PanelClient, PurgeLocalCopyResult, RequestLogReader, SyncFacade } from "./slots";
|
|
4
5
|
/**
|
|
5
6
|
* What the UI reads from a TinyCloudWeb instance. The panel never sees
|
|
@@ -17,11 +18,22 @@ export interface ClientSource {
|
|
|
17
18
|
signOut?: (() => Promise<void>) | undefined;
|
|
18
19
|
/** Removes the local copy from this browser; the panel calls it after sign-out settles. Undefined: nothing to purge. */
|
|
19
20
|
purgeLocalCopy?: (() => Promise<PurgeLocalCopyResult>) | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* True when this page can show the SDK's permission prompt: a page signer and a manifest exist. Absent: no.
|
|
23
|
+
* Read on each use, so it turns false after sign-out.
|
|
24
|
+
*/
|
|
25
|
+
canRequestPermissions?(): boolean;
|
|
26
|
+
/** Asks the SDK for `entries` as a runtime grant. Resolves `{ approved: false }` on a decline; rejects on an error. */
|
|
27
|
+
requestPermissions?(entries: PermissionEntry[], options: {
|
|
28
|
+
expiryMs: number;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
approved: boolean;
|
|
31
|
+
}>;
|
|
20
32
|
}
|
|
21
33
|
export interface PanelClientHandle {
|
|
22
34
|
readonly client: PanelClient;
|
|
23
35
|
/** Clears this client's per-account view state and fires onReset listeners. */
|
|
24
36
|
reset(): void;
|
|
25
37
|
}
|
|
26
|
-
export declare function createPanelClient(id: number, source: ClientSource, dataFactory?: PanelDataFactory): PanelClientHandle;
|
|
38
|
+
export declare function createPanelClient(id: number, source: ClientSource, dataFactory?: PanelDataFactory, platform?: UiPlatform): PanelClientHandle;
|
|
27
39
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/ui/config.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ type BottomPosition = "bottom-right" | "bottom-left" | "bottom-center";
|
|
|
7
7
|
* opens the full page directly.
|
|
8
8
|
*/
|
|
9
9
|
export type UiMode = "sidebar" | "page" | "both";
|
|
10
|
+
/**
|
|
11
|
+
* Where the app runs. `"web"` (default) is a browser page with its own wallet signer. `"native"` is a
|
|
12
|
+
* desktop or mobile shell that cannot show the permission prompt in the page: the panel then explains
|
|
13
|
+
* that and offers no working "allow" button.
|
|
14
|
+
*/
|
|
15
|
+
export type UiPlatform = "web" | "native";
|
|
10
16
|
/** Config passed as `ui` on TinyCloudWeb. `ui: false` disables the UI entirely (see index.ts). */
|
|
11
17
|
export interface UiConfig {
|
|
12
18
|
/** Default true. false hides the button only; the panel, prompts, and open() still work. */
|
|
@@ -21,6 +27,8 @@ export interface UiConfig {
|
|
|
21
27
|
appId?: string;
|
|
22
28
|
/** Default "both". Which layouts the panel offers. */
|
|
23
29
|
mode?: UiMode;
|
|
30
|
+
/** Default "web". Set "native" in a desktop or mobile shell, where the panel cannot ask for a permission itself. */
|
|
31
|
+
platform?: UiPlatform;
|
|
24
32
|
}
|
|
25
33
|
export interface ResolvedUiConfig {
|
|
26
34
|
readonly button: boolean;
|
|
@@ -29,6 +37,7 @@ export interface ResolvedUiConfig {
|
|
|
29
37
|
readonly position: BottomPosition;
|
|
30
38
|
readonly appId: string | undefined;
|
|
31
39
|
readonly mode: UiMode;
|
|
40
|
+
readonly platform: UiPlatform;
|
|
32
41
|
}
|
|
33
42
|
export declare function resolveUiConfig(ui: UiConfig | undefined): ResolvedUiConfig;
|
|
34
43
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PermissionEntry } from "@tinycloud/sdk-core";
|
|
2
|
-
import type { PanelDataHost } from "../data";
|
|
2
|
+
import type { PanelDataHost, PermissionAbility } from "../data";
|
|
3
3
|
/** The account index read: `tinycloud.sql/read` on the `account` database of the account space. */
|
|
4
4
|
export declare const ACCOUNT_INDEX_READ: PermissionEntry;
|
|
5
5
|
/** `tinycloud.space/info` on one space, given by its full space id: the storage status read. */
|
|
@@ -9,6 +9,14 @@ export declare function spaceInfoOn(spaceId: string): PermissionEntry;
|
|
|
9
9
|
* so its reads are sent as before.
|
|
10
10
|
*/
|
|
11
11
|
export declare function sessionHolds(host: Pick<PanelDataHost, "hasPermissions">, entry: PermissionEntry): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* The one read-only entry a tab asks for when its no-access state shows a button, keyed by the ability that state
|
|
14
|
+
* names. Delegations: `delegation/list` on this app's own space (`applications`), never the account space.
|
|
15
|
+
* A tab with no entry here has no button.
|
|
16
|
+
*/
|
|
17
|
+
export declare const TAB_PERMISSION: Readonly<Partial<Record<PermissionAbility, PermissionEntry>>>;
|
|
18
|
+
/** Requested lifetime of a panel-requested grant: 7 days. The SDK shortens it to the session's own expiry. */
|
|
19
|
+
export declare const TAB_PERMISSION_EXPIRY_MS: number;
|
|
12
20
|
/**
|
|
13
21
|
* The spaces to sign the delegation query for, in the order the SDK tries them (account space, then the
|
|
14
22
|
* session's own space), limited to those the session holds `delegation/list` on. Empty: nothing to send.
|
package/dist/ui/host.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export interface HostRuntime {
|
|
|
20
20
|
unregister(id: number): void;
|
|
21
21
|
reset(id: number): void;
|
|
22
22
|
open(section?: SectionId): void;
|
|
23
|
+
/** Absent on a runtime created by an older web-sdk bundle that shares the page. */
|
|
24
|
+
setButtonVisible?(visible: boolean): void;
|
|
23
25
|
openPage(section?: SectionId): void;
|
|
24
26
|
close(): void;
|
|
25
27
|
isOpen(): boolean;
|
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
* (aria-current, .ring) keep winning box-shadow where they did before the split.
|
|
7
7
|
* The drawer edge (#e4e4e7 / #69696b) is decorative, not a 3:1 target.
|
|
8
8
|
*/
|
|
9
|
-
export declare const PANEL_CSS = "\n.glance-row:focus-visible,.nav-i:focus-visible,.action:focus-visible,.switch:focus-visible,.icon-btn:focus-visible,.menu-i:focus-visible{outline:2px solid #111827;outline-offset:2px;box-shadow:0 0 0 6px #fafafa}\n.panel{position:fixed;top:0;bottom:0;right:0;box-sizing:border-box;width:min(420px,100%);display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto minmax(0,1fr);grid-template-areas:\"head\" \"nav\" \"main\";overflow:hidden;border-left:1px solid #e4e4e7;background:#fff;color:#111827;box-shadow:-18px 0 48px -18px rgba(0,0,0,.35);pointer-events:auto;animation:tc-in .42s cubic-bezier(.22,1,.36,1)}\n.layer[data-position=\"bottom-left\"] .panel{left:0;right:auto;border-left:0;border-right:1px solid #e4e4e7;box-shadow:18px 0 48px -18px rgba(0,0,0,.35);animation-name:tc-in-l}\n.layer .panel[data-layout=\"page\"]{top:0;bottom:0;left:0;right:0;width:auto;border:0;box-shadow:none;grid-template-rows:auto minmax(0,1fr);grid-template-columns:288px minmax(0,1fr);grid-template-areas:\"head head\" \"nav main\"}\n.head{grid-area:head;display:flex;flex-wrap:nowrap;align-items:center;justify-content:space-between;gap:8px;box-sizing:border-box;min-height:68px;padding:14px 12px 10px 20px}\n.brand{display:flex;flex-direction:column;min-width:0;flex:1 0 92px}\n.title{margin:0;font-size:15px;font-weight:600}\n.ctx{overflow:hidden;font-size:12.5px;color:#71717a;text-overflow:ellipsis;white-space:nowrap}\n.head-actions{display:flex;flex-wrap:nowrap;align-items:center;min-width:0;flex-shrink:1;gap:6px}\n.head-actions .layout-switch{flex-shrink:0}\n.head-actions > .action{min-width:44px;overflow:hidden}\n.head-actions > .action span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.icon-btn{display:inline-flex;flex:none;align-items:center;justify-content:center;box-sizing:border-box;width:44px;height:44px;min-width:44px;min-height:44px;padding:0;border:0;border-radius:50%;background:transparent;color:inherit;cursor:pointer}\n.icon-btn.ring{box-shadow:inset 0 0 0 1px #71717a}\n.icon-btn svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}\n.status{font-size:12px;color:#4b5563}\n.nav{grid-area:nav;display:flex;flex-wrap:wrap;gap:6px;padding:6px 20px 14px}\n.nav-i{display:inline-flex;align-items:center;min-height:44px;padding:0 13px;border:0;border-radius:999px;background:#f4f4f5;color:#09090b;font:inherit;font-size:13.5px;font-weight:500;white-space:nowrap;cursor:pointer}\n.nav-i[aria-current=\"page\"]{background:#fff;font-weight:700;box-shadow:inset 0 0 0 2px #09090b}\n.nav-n,.nav-ic,.nav-m{display:none}\n.main{grid-area:main;min-width:0;min-height:0;overflow:auto;overflow-wrap:anywhere;box-sizing:border-box;padding:24px 20px 56px;border-top:2px solid #09090b}\n.sec-title{margin:0 0 28px;font-family:\"Literata Variable\",\"Iowan Old Style\",\"Palatino Linotype\",Palatino,Georgia,serif;font-size:1.5rem;font-weight:400;line-height:1.2;letter-spacing:-.005em}\n.section+.section{margin-top:12px;padding-top:12px;border-top:1px solid #e4e4e7}\n.action{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-width:44px;min-height:44px;padding:0 20px;border:1px solid;border-color:#71717a;border-radius:999px;background:#fff;color:#09090b;font:inherit;font-size:13.5px;font-weight:700;white-space:nowrap;cursor:pointer}\n.action:hover{background:#f4f4f5}\n.layout-switch{display:inline-flex;align-items:center;gap:8px;white-space:nowrap}\n.layout-switch[hidden]{display:none}\n.layout-switch svg{width:16px;height:16px;flex:none;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}\n.row{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:44px}\n.label{font-weight:500}\n.switch{display:inline-flex;align-items:center;width:56px;min-width:44px;height:44px;padding:0;border:0;background:none;cursor:pointer}\n.switch:disabled{cursor:default;opacity:.6}\n/* The mockup switch: a 56x30 track with a 1px #71717a edge (the .knob background, so it clears 3:1 on the panel) around a muted fill (::before), and a 22px thumb that is black when off and white on a black track when on. */\n.knob{position:relative;display:block;width:56px;height:30px;border-radius:999px;background:#71717a}\n.knob::before{content:\"\";position:absolute;inset:1px;border-radius:999px;background:#f4f4f5}\n.knob::after{content:\"\";position:absolute;top:4px;left:4px;width:22px;height:22px;border-radius:50%;background:#09090b;transition:transform .3s cubic-bezier(.22,1,.36,1)}\n.switch[aria-checked=\"true\"] .knob{background:#09090b}\n.switch[aria-checked=\"true\"] .knob::before{background:#09090b}\n.switch[aria-checked=\"true\"] .knob::after{transform:translateX(26px);background:#fff}\n.busy,.note,.error{margin:6px 0 0;font-size:12px;color:#4b5563}\n.note{text-wrap:pretty}\n.action+.note,.note:not([hidden])+.action,.row~.action{margin-top:8px}\n.error{color:#111827}\n.confirm{margin-top:8px}\n.confirm .actions{display:flex;flex-wrap:wrap;gap:8px;margin:8px 0}\n.layer .panel[data-layout=\"page\"] .head{padding:12px 24px;border-bottom:1px solid #e4e4e7;background:#fff}\n.layer .panel[data-layout=\"page\"] .nav{flex-direction:column;flex-wrap:nowrap;width:288px;box-sizing:border-box;padding:24px 16px;border-right:1px solid #e4e4e7;background:#fafafa}\n.layer .panel[data-layout=\"page\"] .nav-i{width:100%;min-height:48px;padding:0 12px;border-radius:14px;background:transparent;font-size:14.5px}\n.layer .panel[data-layout=\"page\"] .nav-i[aria-current=\"page\"]{background:#fff}\n.layer .panel[data-layout=\"page\"] .nav-i{gap:8px}\n.layer .panel[data-layout=\"page\"] .nav-ic{display:inline-block;width:16px;height:16px}\n.layer .panel[data-layout=\"page\"] .nav-m{display:inline;max-width:90px;margin-left:auto;overflow:hidden;color:#71717a;font-size:12.5px;font-weight:400;text-overflow:ellipsis;white-space:nowrap}\n.layer .panel[data-layout=\"page\"] .nav-i[aria-current=\"page\"] .nav-m{color:#09090b}\n.layer .panel[data-layout=\"page\"] .nav-n{display:inline-block;width:18px;font:500 11px/1 ui-monospace,SFMono-Regular,Menlo,Consolas,\"Liberation Mono\",monospace;color:#71717a}\n.layer .panel[data-layout=\"page\"] .main{padding:40px 40px 80px;border-top:0;max-width:960px;width:100%;margin:0 auto}\n.layer .panel[data-layout=\"page\"] .sec-title{font-size:1.75rem;line-height:2.125rem;font-weight:600}\n@keyframes tc-in{from{transform:translateX(104%)}to{transform:none}}\n@keyframes tc-in-l{from{transform:translateX(-104%)}to{transform:none}}\n.menu-wrap{display:none;position:relative}\n.menu{position:absolute;top:calc(100% + 6px);right:0;z-index:2;box-sizing:border-box;width:min(280px,calc(100vw - 24px));padding:6px;border-radius:16px;background:#fff;box-shadow:inset 0 0 0 1px #e4e4e7,0 12px 32px -8px rgba(0,0,0,.3)}\n.menu[hidden]{display:none}\n.menu-i{display:flex;align-items:center;width:100%;min-height:44px;padding:0 12px;border:0;border-radius:12px;background:transparent;color:inherit;font:inherit;text-align:left;white-space:nowrap;cursor:pointer}\n.menu-i[aria-current=\"page\"]{font-weight:700;background:#f4f4f5}\n.layer[data-phone] .menu-wrap{display:block}\n.layer[data-phone] .nav{display:none}\n.layer[data-phone] .panel[data-layout=\"page\"]{grid-template-columns:minmax(0,1fr);grid-template-areas:\"head\" \"main\"}\n.layer[data-phone] .panel[data-layout=\"page\"] .head{padding:12px 12px 12px 16px}\n.layer[data-phone] .panel[data-layout=\"page\"] .main{padding:24px 16px 56px}\n.layer{--tc-color-overlay:rgb(9 9 11 / .4)}\n.scrim{position:fixed;inset:0;background:var(--tc-color-overlay);opacity:0;visibility:hidden;pointer-events:none;transition:opacity .35s cubic-bezier(.22,1,.36,1),visibility 0s .35s}\n.layer[data-panel-open][data-layout=\"drawer\"] .scrim{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .35s cubic-bezier(.22,1,.36,1)}\n@media (prefers-reduced-motion:reduce){\n.panel,.knob::after,.scrim,.layer[data-panel-open][data-layout=\"drawer\"] .scrim{animation:none;transition:none}\n}\n@media (prefers-color-scheme: dark){\n.layer{--tc-color-overlay:rgb(0 0 0 / .6)}\n.glance-row:focus-visible,.nav-i:focus-visible,.action:focus-visible,.switch:focus-visible,.icon-btn:focus-visible,.menu-i:focus-visible{outline-color:#fafafa;box-shadow:0 0 0 6px #111827}\n.panel{border-left-color:#69696b;background:#151517;color:#fafafa}\n.main{border-top-color:#fafafa}\n.ctx,.status,.busy,.note{color:#a1a1aa}\n.nav-i{background:#27272a;color:#fafafa}\n.nav-i[aria-current=\"page\"]{background:#151517;box-shadow:inset 0 0 0 2px #fafafa}\n.icon-btn.ring{box-shadow:inset 0 0 0 1px #71717a}\n.section+.section{border-top-color:#69696b}\n.action{border-color:#71717a;background:#151517;color:#fafafa}\n.action:hover{background:#27272a}\n.error{color:#fafafa}\n.knob::before{background:#27272a}\n.knob::after{background:#fafafa}\n.switch[aria-checked=\"true\"] .knob{background:#fafafa}\n.switch[aria-checked=\"true\"] .knob::before{background:#fafafa}\n.switch[aria-checked=\"true\"] .knob::after{background:#09090b}\n.layer .panel[data-layout=\"page\"] .head{background:#151517;border-bottom-color:#69696b}\n.layer .panel[data-layout=\"page\"] .nav{background:#151517;border-right-color:#69696b}\n.layer .panel[data-layout=\"page\"] .nav-i{background:transparent}\n.layer .panel[data-layout=\"page\"] .nav-i[aria-current=\"page\"]{background:#27272a}\n.layer .panel[data-layout=\"page\"] .nav-n,.layer .panel[data-layout=\"page\"] .nav-m{color:#a1a1aa}\n.layer .panel[data-layout=\"page\"] .nav-i[aria-current=\"page\"] .nav-m{color:#fafafa}\n.menu{background:#151517;box-shadow:inset 0 0 0 1px #69696b,0 12px 32px -8px rgba(0,0,0,.6)}\n.menu-i[aria-current=\"page\"]{background:#27272a}\n}\n";
|
|
9
|
+
export declare const PANEL_CSS = "\n.glance-row:focus-visible,.nav-i:focus-visible,.action:focus-visible,.switch:focus-visible,.icon-btn:focus-visible,.menu-i:focus-visible{outline:2px solid #111827;outline-offset:2px;box-shadow:0 0 0 6px #fafafa}\n.panel{position:fixed;top:0;bottom:0;right:0;box-sizing:border-box;width:min(420px,100%);padding:env(safe-area-inset-top,0px) env(safe-area-inset-right,0px) env(safe-area-inset-bottom,0px) env(safe-area-inset-left,0px);display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto minmax(0,1fr);grid-template-areas:\"head\" \"nav\" \"main\";overflow:hidden;border-left:1px solid #e4e4e7;background:#fff;color:#111827;box-shadow:-18px 0 48px -18px rgba(0,0,0,.35);pointer-events:auto;animation:tc-in .42s cubic-bezier(.22,1,.36,1)}\n.layer[data-position=\"bottom-left\"] .panel{left:0;right:auto;border-left:0;border-right:1px solid #e4e4e7;box-shadow:18px 0 48px -18px rgba(0,0,0,.35);animation-name:tc-in-l}\n.layer .panel[data-layout=\"page\"]{top:0;bottom:0;left:0;right:0;width:auto;border:0;box-shadow:none;grid-template-rows:auto minmax(0,1fr);grid-template-columns:288px minmax(0,1fr);grid-template-areas:\"head head\" \"nav main\"}\n.head{grid-area:head;position:sticky;top:0;z-index:1;touch-action:none;background:#fff;display:flex;flex-wrap:nowrap;align-items:center;justify-content:space-between;gap:8px;box-sizing:border-box;min-height:68px;padding:14px 12px 10px 20px}\n.brand{display:flex;flex-direction:column;min-width:0;flex:1 0 92px}\n.title{margin:0;font-size:15px;font-weight:600}\n.ctx{overflow:hidden;font-size:12.5px;color:#71717a;text-overflow:ellipsis;white-space:nowrap}\n.head-actions{display:flex;flex-wrap:nowrap;align-items:center;min-width:0;flex-shrink:1;gap:6px}\n.head-actions .layout-switch{flex-shrink:0}\n.head-actions > .action{min-width:44px;overflow:hidden}\n.head-actions > .action span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.icon-btn{display:inline-flex;flex:none;align-items:center;justify-content:center;box-sizing:border-box;width:44px;height:44px;min-width:44px;min-height:44px;padding:0;border:0;border-radius:50%;background:transparent;color:inherit;cursor:pointer}\n.icon-btn.ring{box-shadow:inset 0 0 0 1px #71717a}\n.icon-btn svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}\n.status{font-size:12px;color:#4b5563}\n.nav{grid-area:nav;display:flex;flex-wrap:wrap;gap:6px;padding:6px 20px 14px}\n.nav-i{display:inline-flex;align-items:center;min-height:44px;padding:0 13px;border:0;border-radius:999px;background:#f4f4f5;color:#09090b;font:inherit;font-size:13.5px;font-weight:500;white-space:nowrap;cursor:pointer}\n.nav-i[aria-current=\"page\"]{background:#fff;font-weight:700;box-shadow:inset 0 0 0 2px #09090b}\n.nav-n,.nav-ic,.nav-m{display:none}\n.main{grid-area:main;min-width:0;min-height:0;overflow:auto;overflow-wrap:anywhere;box-sizing:border-box;padding:24px 20px 56px;border-top:2px solid #09090b}\n.sec-title{margin:0 0 28px;font-family:\"Literata Variable\",\"Iowan Old Style\",\"Palatino Linotype\",Palatino,Georgia,serif;font-size:1.5rem;font-weight:400;line-height:1.2;letter-spacing:-.005em}\n.section+.section{margin-top:12px;padding-top:12px;border-top:1px solid #e4e4e7}\n.action{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-width:44px;min-height:44px;padding:0 20px;border:1px solid;border-color:#71717a;border-radius:999px;background:#fff;color:#09090b;font:inherit;font-size:13.5px;font-weight:700;white-space:nowrap;cursor:pointer}\n.action:hover{background:#f4f4f5}\n.layout-switch{display:inline-flex;align-items:center;gap:8px;white-space:nowrap}\n.layout-switch[hidden]{display:none}\n.layout-switch svg{width:16px;height:16px;flex:none;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}\n.row{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:44px}\n.label{font-weight:500}\n.switch{display:inline-flex;align-items:center;width:56px;min-width:44px;height:44px;padding:0;border:0;background:none;cursor:pointer}\n.switch:disabled{cursor:default;opacity:.6}\n/* The mockup switch: a 56x30 track with a 1px #71717a edge (the .knob background, so it clears 3:1 on the panel) around a muted fill (::before), and a 22px thumb that is black when off and white on a black track when on. */\n.knob{position:relative;display:block;width:56px;height:30px;border-radius:999px;background:#71717a}\n.knob::before{content:\"\";position:absolute;inset:1px;border-radius:999px;background:#f4f4f5}\n.knob::after{content:\"\";position:absolute;top:4px;left:4px;width:22px;height:22px;border-radius:50%;background:#09090b;transition:transform .3s cubic-bezier(.22,1,.36,1)}\n.switch[aria-checked=\"true\"] .knob{background:#09090b}\n.switch[aria-checked=\"true\"] .knob::before{background:#09090b}\n.switch[aria-checked=\"true\"] .knob::after{transform:translateX(26px);background:#fff}\n.busy,.note,.error{margin:6px 0 0;font-size:12px;color:#4b5563}\n.note{text-wrap:pretty}\n.action+.note,.note:not([hidden])+.action,.row~.action{margin-top:8px}\n.error{color:#111827}\n.confirm{margin-top:8px}\n.confirm .actions{display:flex;flex-wrap:wrap;gap:8px;margin:8px 0}\n.layer .panel[data-layout=\"page\"] .head{padding:12px 24px;border-bottom:1px solid #e4e4e7;background:#fff}\n.layer .panel[data-layout=\"page\"] .nav{flex-direction:column;flex-wrap:nowrap;width:288px;box-sizing:border-box;padding:24px 16px;border-right:1px solid #e4e4e7;background:#fafafa}\n.layer .panel[data-layout=\"page\"] .nav-i{width:100%;min-height:48px;padding:0 12px;border-radius:14px;background:transparent;font-size:14.5px}\n.layer .panel[data-layout=\"page\"] .nav-i[aria-current=\"page\"]{background:#fff}\n.layer .panel[data-layout=\"page\"] .nav-i{gap:8px}\n.layer .panel[data-layout=\"page\"] .nav-ic{display:inline-block;width:16px;height:16px}\n.layer .panel[data-layout=\"page\"] .nav-m{display:inline;max-width:90px;margin-left:auto;overflow:hidden;color:#71717a;font-size:12.5px;font-weight:400;text-overflow:ellipsis;white-space:nowrap}\n.layer .panel[data-layout=\"page\"] .nav-i[aria-current=\"page\"] .nav-m{color:#09090b}\n.layer .panel[data-layout=\"page\"] .nav-n{display:inline-block;width:18px;font:500 11px/1 ui-monospace,SFMono-Regular,Menlo,Consolas,\"Liberation Mono\",monospace;color:#71717a}\n.layer .panel[data-layout=\"page\"] .main{padding:40px 40px 80px;border-top:0;max-width:960px;width:100%;margin:0 auto}\n.layer .panel[data-layout=\"page\"] .sec-title{font-size:1.75rem;line-height:2.125rem;font-weight:600}\n@keyframes tc-in{from{transform:translateX(104%)}to{transform:none}}\n@keyframes tc-in-l{from{transform:translateX(-104%)}to{transform:none}}\n.menu-wrap{display:none;position:relative}\n.menu{position:absolute;top:calc(100% + 6px);right:0;z-index:2;box-sizing:border-box;width:min(280px,calc(100vw - 24px));padding:6px;border-radius:16px;background:#fff;box-shadow:inset 0 0 0 1px #e4e4e7,0 12px 32px -8px rgba(0,0,0,.3)}\n.menu[hidden]{display:none}\n.menu-i{display:flex;align-items:center;width:100%;min-height:44px;padding:0 12px;border:0;border-radius:12px;background:transparent;color:inherit;font:inherit;text-align:left;white-space:nowrap;cursor:pointer}\n.menu-i[aria-current=\"page\"]{font-weight:700;background:#f4f4f5}\n.layer[data-phone] .menu-wrap{display:block}\n.layer[data-phone] .nav{display:none}\n.layer[data-phone] .panel[data-layout=\"page\"]{grid-template-columns:minmax(0,1fr);grid-template-areas:\"head\" \"main\"}\n.layer[data-phone] .panel[data-layout=\"page\"] .head{padding:12px 12px 12px 16px}\n.layer[data-phone] .panel[data-layout=\"page\"] .main{padding:24px 16px 56px}\n.layer{--tc-color-overlay:rgb(9 9 11 / .4)}\n.scrim{position:fixed;inset:0;background:var(--tc-color-overlay);opacity:0;visibility:hidden;pointer-events:none;transition:opacity .35s cubic-bezier(.22,1,.36,1),visibility 0s .35s}\n.layer[data-panel-open][data-layout=\"drawer\"] .scrim{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .35s cubic-bezier(.22,1,.36,1)}\n@media (prefers-reduced-motion:reduce){\n.panel,.knob::after,.scrim,.layer[data-panel-open][data-layout=\"drawer\"] .scrim{animation:none;transition:none}\n}\n@media (prefers-color-scheme: dark){\n.layer{--tc-color-overlay:rgb(0 0 0 / .6)}\n.glance-row:focus-visible,.nav-i:focus-visible,.action:focus-visible,.switch:focus-visible,.icon-btn:focus-visible,.menu-i:focus-visible{outline-color:#fafafa;box-shadow:0 0 0 6px #111827}\n.panel{border-left-color:#69696b;background:#151517;color:#fafafa}\n.head{background:#151517}\n.main{border-top-color:#fafafa}\n.ctx,.status,.busy,.note{color:#a1a1aa}\n.nav-i{background:#27272a;color:#fafafa}\n.nav-i[aria-current=\"page\"]{background:#151517;box-shadow:inset 0 0 0 2px #fafafa}\n.icon-btn.ring{box-shadow:inset 0 0 0 1px #71717a}\n.section+.section{border-top-color:#69696b}\n.action{border-color:#71717a;background:#151517;color:#fafafa}\n.action:hover{background:#27272a}\n.error{color:#fafafa}\n.knob::before{background:#27272a}\n.knob::after{background:#fafafa}\n.switch[aria-checked=\"true\"] .knob{background:#fafafa}\n.switch[aria-checked=\"true\"] .knob::before{background:#fafafa}\n.switch[aria-checked=\"true\"] .knob::after{background:#09090b}\n.layer .panel[data-layout=\"page\"] .head{background:#151517;border-bottom-color:#69696b}\n.layer .panel[data-layout=\"page\"] .nav{background:#151517;border-right-color:#69696b}\n.layer .panel[data-layout=\"page\"] .nav-i{background:transparent}\n.layer .panel[data-layout=\"page\"] .nav-i[aria-current=\"page\"]{background:#27272a}\n.layer .panel[data-layout=\"page\"] .nav-n,.layer .panel[data-layout=\"page\"] .nav-m{color:#a1a1aa}\n.layer .panel[data-layout=\"page\"] .nav-i[aria-current=\"page\"] .nav-m{color:#fafafa}\n.menu{background:#151517;box-shadow:inset 0 0 0 1px #69696b,0 12px 32px -8px rgba(0,0,0,.6)}\n.menu-i[aria-current=\"page\"]{background:#27272a}\n}\n";
|
|
10
10
|
//# sourceMappingURL=panel-styles.d.ts.map
|
package/dist/ui/pending.d.ts
CHANGED
|
@@ -9,5 +9,5 @@ export interface PendingPanel {
|
|
|
9
9
|
showLoading(): void;
|
|
10
10
|
showError(retry: () => void): void;
|
|
11
11
|
}
|
|
12
|
-
export declare function createPendingPanel(
|
|
12
|
+
export declare function createPendingPanel(onClose: () => void): PendingPanel;
|
|
13
13
|
//# sourceMappingURL=pending.d.ts.map
|
|
@@ -35,6 +35,11 @@ export declare const DELEGATIONS_STRINGS: {
|
|
|
35
35
|
readonly "delegations.ask.openkey": " You'll approve it in OpenKey.";
|
|
36
36
|
readonly "delegations.ask.button": "Allow delegation list";
|
|
37
37
|
readonly "delegations.ask.declined": "That wasn't allowed, so nothing changed.";
|
|
38
|
+
readonly "delegations.ask.scope": "This shows every app and link that can reach your data across your whole account, and the names of what each can reach. It doesn't show keys or contents.";
|
|
39
|
+
readonly "delegations.ask.busy": "Waiting for your answer…";
|
|
40
|
+
readonly "delegations.ask.error": "The request didn't go through. Try again.";
|
|
41
|
+
readonly "delegations.ask.signin": "Sign in again to allow it.";
|
|
42
|
+
readonly "delegations.ask.native": "This app can't ask for this permission from here.";
|
|
38
43
|
readonly "delegations.kind.app": "This app";
|
|
39
44
|
readonly "delegations.kind.others": "Granted by you";
|
|
40
45
|
readonly "delegations.kind.received": "Shared with you by {who}";
|
package/dist/ui/slots.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { ShellLayout } from "./panel";
|
|
|
8
8
|
import type { ReceiptRequest } from "./panel-toasts";
|
|
9
9
|
import type { IconName } from "./sections/ui";
|
|
10
10
|
import type { StringKey } from "./strings";
|
|
11
|
+
import type { UiPlatform } from "./config";
|
|
11
12
|
import type { ToastRequest } from "./toast-store";
|
|
12
13
|
/** Panel sections, in nav order. Ids match the full-page and sidebar mockup. */
|
|
13
14
|
export type SectionId = "account" | "local-tinycloud" | "local-copy" | "delegations" | "nodes" | "storage" | "activity";
|
|
@@ -55,6 +56,8 @@ export interface HostContext {
|
|
|
55
56
|
canHideButton(): boolean;
|
|
56
57
|
/** Hides the launcher button, persists it, and closes the panel. */
|
|
57
58
|
hideButton(): void;
|
|
59
|
+
/** Fires when the button's presence changes (`setButtonVisible`), so an open section can follow `canHideButton()`. Optional: a context without it never changes. */
|
|
60
|
+
onButtonChange?(cb: () => void): () => void;
|
|
58
61
|
}
|
|
59
62
|
/** Views the shell reads for statuses. `account` is read by Overview itself. */
|
|
60
63
|
export interface DataViews {
|
|
@@ -198,11 +201,20 @@ export interface PanelClient {
|
|
|
198
201
|
subscribe(cb: () => void): () => void;
|
|
199
202
|
subscribeDelegated(cb: () => void): () => void;
|
|
200
203
|
} | undefined;
|
|
201
|
-
/**
|
|
204
|
+
/**
|
|
205
|
+
* Asks for the read-only permission a tab is missing. Defined only when the page can show the SDK's permission prompt
|
|
206
|
+
* (a page signer and a manifest exist); undefined otherwise. Resolves `{ approved: false, code: "declined" }` when
|
|
207
|
+
* the user declines or closes the prompt and `code: "failed"` when the request errors. One request at a time:
|
|
208
|
+
* a second call while one is open returns the open one.
|
|
209
|
+
*/
|
|
202
210
|
readonly requestAuthority?: ((kind: AuthorityKind) => Promise<{
|
|
203
211
|
approved: boolean;
|
|
204
212
|
code?: FacadeErrorCode;
|
|
205
213
|
}>) | undefined;
|
|
214
|
+
/** False when `requestAuthority` has no entry for `kind`, so a tab has no button for it. Absent: unknown. */
|
|
215
|
+
readonly canRequest?: ((kind: AuthorityKind) => boolean) | undefined;
|
|
216
|
+
/** Where the app runs (`ui.platform`). Absent: web. */
|
|
217
|
+
readonly platform?: UiPlatform | undefined;
|
|
206
218
|
/** E: request log, present only in developer mode. */
|
|
207
219
|
readonly requests?: RequestLogReader | undefined;
|
|
208
220
|
/** Panel data for the views. Undefined unless the host supplied a data factory (harness or preview); production panels show placeholders. */
|
package/dist/ui/styles.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* adoptedStyleSheets. Neutral palette only. Offsets are CSS custom properties
|
|
6
6
|
* so an app can reserve space without an API.
|
|
7
7
|
*/
|
|
8
|
-
export declare const HOST_CSS = "\n[hidden]{display:none!important}\n.layer{--b:calc(env(safe-area-inset-bottom,0px) + var(--tinycloud-ui-offset-bottom,12px));position:fixed;inset:0;pointer-events:none;font:14px/1.4 system-ui,-apple-system,\"Segoe UI\",sans-serif;color:#111827}\n.button{position:fixed;bottom:var(--b);width:44px;height:44px;padding:0;display:inline-flex;align-items:center;justify-content:center;border:1px solid #71717a;border-radius:50%;background:#fff;color:#111827;box-shadow:0 1px 3px rgba(0,0,0,.16);cursor:pointer;pointer-events:auto}\n.button svg{width:20px;height:20px}\n.button:focus-visible{outline:2px solid #111827;outline-offset:2px;box-shadow:0 0 0 6px #fafafa}\n.dot{position:absolute;top:6px;right:6px;width:8px;height:8px;border-radius:50%;background:#4b5563;border:2px solid #fff}\n.layer[data-position=\"bottom-right\"] .button{right:var(--tinycloud-ui-offset-inline,12px)}\n.layer[data-position=\"bottom-left\"] .button{left:var(--tinycloud-ui-offset-inline,12px)}\n.layer[data-position=\"bottom-center\"] .button{left:50%;transform:translateX(-50%)}\n.pending{position:fixed;top:0;bottom:0;right:0;box-sizing:border-box;width:min(420px,100%);padding:20px;overflow:auto;border-left:1px solid #e4e4e7;background:#fff;color:#111827;box-shadow:-18px 0 48px -18px rgba(0,0,0,.35);pointer-events:auto}\n.layer[data-position=\"bottom-left\"] .pending{right:auto;left:0;border-left:0;border-right:1px solid #e4e4e7}\n.pending p{margin:0 0 12px;color:#71717a}\n.pending button{min-height:44px;padding:0 16px;border:1px solid #71717a;border-radius:12px;background:transparent;color:inherit;font:inherit;cursor:pointer}\n.pending button:focus-visible{outline:2px solid #111827;outline-offset:2px;box-shadow:0 0 0 6px #fafafa}\n@media (prefers-color-scheme: dark){\n.layer{color:#fafafa}\n.button{border-color:#71717a;background:#151517;color:#fafafa}\n.button:focus-visible{outline-color:#fafafa;box-shadow:0 0 0 6px #111827}\n.dot{background:#a1a1aa;border-color:#151517}\n.pending{border-left-color:#69696b;background:#151517;color:#fafafa;box-shadow:-18px 0 48px -18px rgba(0,0,0,.6)}\n.layer[data-position=\"bottom-left\"] .pending{border-right-color:#69696b}\n.pending p{color:#a1a1aa}\n.pending button:focus-visible{outline-color:#fafafa;box-shadow:0 0 0 6px #111827}\n}\n";
|
|
8
|
+
export declare const HOST_CSS = "\n[hidden]{display:none!important}\n.layer{--b:calc(env(safe-area-inset-bottom,0px) + var(--tinycloud-ui-offset-bottom,12px));position:fixed;inset:0;pointer-events:none;font:14px/1.4 system-ui,-apple-system,\"Segoe UI\",sans-serif;color:#111827}\n.button{position:fixed;bottom:var(--b);width:44px;height:44px;padding:0;display:inline-flex;align-items:center;justify-content:center;border:1px solid #71717a;border-radius:50%;background:#fff;color:#111827;box-shadow:0 1px 3px rgba(0,0,0,.16);cursor:pointer;pointer-events:auto}\n.button svg{width:20px;height:20px}\n.button:focus-visible{outline:2px solid #111827;outline-offset:2px;box-shadow:0 0 0 6px #fafafa}\n.dot{position:absolute;top:6px;right:6px;width:8px;height:8px;border-radius:50%;background:#4b5563;border:2px solid #fff}\n.layer[data-position=\"bottom-right\"] .button{right:var(--tinycloud-ui-offset-inline,12px)}\n.layer[data-position=\"bottom-left\"] .button{left:var(--tinycloud-ui-offset-inline,12px)}\n.layer[data-position=\"bottom-center\"] .button{left:50%;transform:translateX(-50%)}\n.pending{position:fixed;top:0;bottom:0;right:0;box-sizing:border-box;width:min(420px,100%);padding:max(20px,env(safe-area-inset-top,0px)) max(20px,env(safe-area-inset-right,0px)) max(20px,env(safe-area-inset-bottom,0px)) max(20px,env(safe-area-inset-left,0px));overflow:auto;border-left:1px solid #e4e4e7;background:#fff;color:#111827;box-shadow:-18px 0 48px -18px rgba(0,0,0,.35);pointer-events:auto}\n.layer[data-position=\"bottom-left\"] .pending{right:auto;left:0;border-left:0;border-right:1px solid #e4e4e7}\n.pending p{margin:0 0 12px;color:#71717a}\n.pending button{min-height:44px;padding:0 16px;border:1px solid #71717a;border-radius:12px;background:transparent;color:inherit;font:inherit;cursor:pointer}\n.pending .pclose{display:flex;align-items:center;justify-content:center;width:44px;padding:0;margin:0 0 8px auto;border-radius:50%}\n.pending .pclose svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}\n.pending button:focus-visible{outline:2px solid #111827;outline-offset:2px;box-shadow:0 0 0 6px #fafafa}\n@media (prefers-color-scheme: dark){\n.layer{color:#fafafa}\n.button{border-color:#71717a;background:#151517;color:#fafafa}\n.button:focus-visible{outline-color:#fafafa;box-shadow:0 0 0 6px #111827}\n.dot{background:#a1a1aa;border-color:#151517}\n.pending{border-left-color:#69696b;background:#151517;color:#fafafa;box-shadow:-18px 0 48px -18px rgba(0,0,0,.6)}\n.layer[data-position=\"bottom-left\"] .pending{border-right-color:#69696b}\n.pending p{color:#a1a1aa}\n.pending button:focus-visible{outline-color:#fafafa;box-shadow:0 0 0 6px #111827}\n}\n";
|
|
9
9
|
//# sourceMappingURL=styles.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tinycloud/web-sdk",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.1-beta.0",
|
|
4
4
|
"description": "A set of tools and utilities to help you build your app with TinyCloud.",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -66,11 +66,11 @@
|
|
|
66
66
|
"@multiformats/multiaddr": "^13.0.1",
|
|
67
67
|
"@multiformats/multiaddr-to-uri": "^12.0.0",
|
|
68
68
|
"@noble/curves": "^1.9.7",
|
|
69
|
-
"@tinycloud/node-sdk": "3.8.
|
|
70
|
-
"@tinycloud/replica": "0.4.0
|
|
71
|
-
"@tinycloud/sdk-core": "3.8.0
|
|
72
|
-
"@tinycloud/share-envelope": "1.
|
|
73
|
-
"@tinycloud/share-sdk": "1.4.1
|
|
69
|
+
"@tinycloud/node-sdk": "3.8.1-beta.0",
|
|
70
|
+
"@tinycloud/replica": "0.4.0",
|
|
71
|
+
"@tinycloud/sdk-core": "3.8.0",
|
|
72
|
+
"@tinycloud/share-envelope": "1.4.0",
|
|
73
|
+
"@tinycloud/share-sdk": "1.4.1",
|
|
74
74
|
"@tinycloud/web-sdk-wasm": "1.7.7",
|
|
75
75
|
"axios": "^1.7.9",
|
|
76
76
|
"viem": "^2.45.0",
|