@synopackageland/sdk 0.10.2 → 0.10.4

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 (58) hide show
  1. package/README.md +77 -5
  2. package/dist/i18n/background/zh-CN.json +7 -7
  3. package/dist/i18n/bridge/de.json +3 -1
  4. package/dist/i18n/bridge/en.json +3 -1
  5. package/dist/i18n/bridge/es.json +3 -1
  6. package/dist/i18n/bridge/fr.json +3 -1
  7. package/dist/i18n/bridge/it.json +3 -1
  8. package/dist/i18n/bridge/ja.json +3 -1
  9. package/dist/i18n/bridge/ko.json +3 -1
  10. package/dist/i18n/bridge/zh-CN.json +3 -1
  11. package/dist/i18n/bridge/zh-TW.json +3 -1
  12. package/dist/i18n/delegate/de.json +5 -3
  13. package/dist/i18n/delegate/en.json +5 -3
  14. package/dist/i18n/delegate/es.json +5 -3
  15. package/dist/i18n/delegate/fr.json +5 -3
  16. package/dist/i18n/delegate/it.json +5 -3
  17. package/dist/i18n/delegate/ja.json +5 -3
  18. package/dist/i18n/delegate/ko.json +5 -3
  19. package/dist/i18n/delegate/zh-CN.json +5 -3
  20. package/dist/i18n/delegate/zh-TW.json +5 -3
  21. package/dist/i18n/identity/zh-CN.json +5 -5
  22. package/dist/i18n/save/de.json +16 -17
  23. package/dist/i18n/save/en.json +16 -17
  24. package/dist/i18n/save/es.json +16 -17
  25. package/dist/i18n/save/fr.json +16 -17
  26. package/dist/i18n/save/it.json +16 -17
  27. package/dist/i18n/save/ja.json +16 -17
  28. package/dist/i18n/save/ko.json +16 -17
  29. package/dist/i18n/save/zh-CN.json +16 -17
  30. package/dist/i18n/save/zh-TW.json +16 -17
  31. package/dist/index.js +2334 -2296
  32. package/dist/native.js +350 -0
  33. package/dist/src/delegate/BackgroundSavePanel.vue.d.ts +3 -0
  34. package/dist/src/delegate/BackgroundSaveSettings.vue.d.ts +42 -0
  35. package/dist/src/delegate/ExecutorSettings.vue.d.ts +1 -2
  36. package/dist/src/delegate/SaveOperations.vue.d.ts +23 -0
  37. package/dist/src/delegate/copy.d.ts +10 -6
  38. package/dist/src/delegate/executor-setup.d.ts +2 -0
  39. package/dist/src/delegate/save-copy.d.ts +33 -36
  40. package/dist/src/delegate/use-executor-setup.d.ts +5 -1
  41. package/dist/src/delegate/use-scope-approval.d.ts +50 -0
  42. package/dist/src/dsm/file-station.d.ts +1 -1
  43. package/dist/src/native/authorization-runtime.d.ts +2 -0
  44. package/dist/src/native/dsm-version.d.ts +6 -0
  45. package/dist/src/native/root-runtime.d.ts +34 -0
  46. package/dist/src/native.d.ts +2 -0
  47. package/dist/src/protocol/v1.d.ts +20 -2
  48. package/dist/src/shell/AppShell.vue.d.ts +3 -0
  49. package/dist/src/shell/PageActions.vue.d.ts +13 -0
  50. package/dist/src/shell/app-pages.d.ts +2 -0
  51. package/dist/src/shell/page-actions.d.ts +3 -0
  52. package/dist/src/vue.d.ts +3 -0
  53. package/dist/style.css +1 -1
  54. package/dist/vue.js +2128 -1809
  55. package/package.json +7 -3
  56. package/spec/protocol/v1/README.md +99 -5
  57. package/spec/protocol/v1/errors.json +24 -0
  58. package/spec/protocol/v1/timeouts.json +21 -0
@@ -2,9 +2,7 @@ export declare const saveCatalogs: Record<import("..").UiLocale, {
2
2
  title: string;
3
3
  help: string;
4
4
  selection: string;
5
- delegations: string;
6
5
  operations: string;
7
- empty: string;
8
6
  noOperations: string;
9
7
  revoke: string;
10
8
  choose: string;
@@ -13,10 +11,8 @@ export declare const saveCatalogs: Record<import("..").UiLocale, {
13
11
  disable: string;
14
12
  enable: string;
15
13
  disableHelp: string;
14
+ disableConfirm: string;
16
15
  disabled: string;
17
- enabled: string;
18
- revoked: string;
19
- untilRevoked: string;
20
16
  queued: string;
21
17
  copying: string;
22
18
  committed: string;
@@ -26,7 +22,6 @@ export declare const saveCatalogs: Record<import("..").UiLocale, {
26
22
  uncertain: string;
27
23
  uncertainHelp: string;
28
24
  interruptedHelp: string;
29
- loading: string;
30
25
  denied: string;
31
26
  permission: string;
32
27
  permissionSelect: string;
@@ -37,29 +32,31 @@ export declare const saveCatalogs: Record<import("..").UiLocale, {
37
32
  conflict: string;
38
33
  space: string;
39
34
  error: string;
40
- scope: string;
41
- scopeNeeds: string;
42
- scopeMismatch: string;
43
35
  reselect: string;
44
36
  example: string;
45
37
  exampleHelp: string;
46
- statusEnabled: string;
47
- statusDisabled: string;
48
- statusNeedsScope: string;
49
38
  status: string;
50
39
  file: string;
51
40
  size: string;
52
41
  location: string;
53
42
  openFolder: string;
54
43
  retry: string;
44
+ folder: string;
45
+ folderNone: string;
46
+ scopeRow: string;
47
+ change: string;
48
+ cancelChange: string;
49
+ changeHelp: string;
50
+ approveHelp: string;
51
+ approve: string;
52
+ confirmChange: string;
53
+ password: string;
55
54
  }>;
56
55
  export declare function saveCopy(locale?: string): {
57
56
  title: string;
58
57
  help: string;
59
58
  selection: string;
60
- delegations: string;
61
59
  operations: string;
62
- empty: string;
63
60
  noOperations: string;
64
61
  revoke: string;
65
62
  choose: string;
@@ -68,10 +65,8 @@ export declare function saveCopy(locale?: string): {
68
65
  disable: string;
69
66
  enable: string;
70
67
  disableHelp: string;
68
+ disableConfirm: string;
71
69
  disabled: string;
72
- enabled: string;
73
- revoked: string;
74
- untilRevoked: string;
75
70
  queued: string;
76
71
  copying: string;
77
72
  committed: string;
@@ -81,7 +76,6 @@ export declare function saveCopy(locale?: string): {
81
76
  uncertain: string;
82
77
  uncertainHelp: string;
83
78
  interruptedHelp: string;
84
- loading: string;
85
79
  denied: string;
86
80
  permission: string;
87
81
  permissionSelect: string;
@@ -92,29 +86,31 @@ export declare function saveCopy(locale?: string): {
92
86
  conflict: string;
93
87
  space: string;
94
88
  error: string;
95
- scope: string;
96
- scopeNeeds: string;
97
- scopeMismatch: string;
98
89
  reselect: string;
99
90
  example: string;
100
91
  exampleHelp: string;
101
- statusEnabled: string;
102
- statusDisabled: string;
103
- statusNeedsScope: string;
104
92
  status: string;
105
93
  file: string;
106
94
  size: string;
107
95
  location: string;
108
96
  openFolder: string;
109
97
  retry: string;
98
+ folder: string;
99
+ folderNone: string;
100
+ scopeRow: string;
101
+ change: string;
102
+ cancelChange: string;
103
+ changeHelp: string;
104
+ approveHelp: string;
105
+ approve: string;
106
+ confirmChange: string;
107
+ password: string;
110
108
  };
111
109
  export declare function saveError(error: unknown, copy?: {
112
110
  title: string;
113
111
  help: string;
114
112
  selection: string;
115
- delegations: string;
116
113
  operations: string;
117
- empty: string;
118
114
  noOperations: string;
119
115
  revoke: string;
120
116
  choose: string;
@@ -123,10 +119,8 @@ export declare function saveError(error: unknown, copy?: {
123
119
  disable: string;
124
120
  enable: string;
125
121
  disableHelp: string;
122
+ disableConfirm: string;
126
123
  disabled: string;
127
- enabled: string;
128
- revoked: string;
129
- untilRevoked: string;
130
124
  queued: string;
131
125
  copying: string;
132
126
  committed: string;
@@ -136,7 +130,6 @@ export declare function saveError(error: unknown, copy?: {
136
130
  uncertain: string;
137
131
  uncertainHelp: string;
138
132
  interruptedHelp: string;
139
- loading: string;
140
133
  denied: string;
141
134
  permission: string;
142
135
  permissionSelect: string;
@@ -147,19 +140,23 @@ export declare function saveError(error: unknown, copy?: {
147
140
  conflict: string;
148
141
  space: string;
149
142
  error: string;
150
- scope: string;
151
- scopeNeeds: string;
152
- scopeMismatch: string;
153
143
  reselect: string;
154
144
  example: string;
155
145
  exampleHelp: string;
156
- statusEnabled: string;
157
- statusDisabled: string;
158
- statusNeedsScope: string;
159
146
  status: string;
160
147
  file: string;
161
148
  size: string;
162
149
  location: string;
163
150
  openFolder: string;
164
151
  retry: string;
152
+ folder: string;
153
+ folderNone: string;
154
+ scopeRow: string;
155
+ change: string;
156
+ cancelChange: string;
157
+ changeHelp: string;
158
+ approveHelp: string;
159
+ approve: string;
160
+ confirmChange: string;
161
+ password: string;
165
162
  }, situation?: 'save' | 'select'): string;
@@ -1,4 +1,8 @@
1
1
  import { type InjectionKey } from 'vue';
2
- import type { ExecutorSetup } from './executor-setup';
2
+ import type { CapabilityStatus, ExecutorSetup } from './executor-setup';
3
3
  export declare const ExecutorSetupKey: InjectionKey<ExecutorSetup>;
4
4
  export declare function useExecutorSetup(): ExecutorSetup;
5
+ export type ConfirmFailure = 'password_rejected' | 'password_required' | 'password_confirm_failed';
6
+ export declare function confirmFailure(status: CapabilityStatus): ConfirmFailure | undefined;
7
+ export declare function passwordRejected(status: CapabilityStatus): boolean;
8
+ export declare function statusUnreachable(reason?: string): boolean;
@@ -0,0 +1,50 @@
1
+ import type { Context } from '../context';
2
+ import type { ScopeSelection } from './long-running';
3
+ import type { CapabilityStatus } from './executor-setup';
4
+ import { type ConfirmFailure } from './use-executor-setup';
5
+ export interface ScopeDetail {
6
+ scope_mode?: string;
7
+ preselection?: string;
8
+ selection?: ScopeSelection | null;
9
+ mismatch?: boolean;
10
+ }
11
+ export declare const SCOPE_READBACK_MS = 60000, SCOPE_READBACK_POLL_MS = 1000;
12
+ export declare function useScopeApproval(props: {
13
+ readonly admin: boolean;
14
+ readonly locale?: string;
15
+ readonly ctx?: Pick<Context, 'call'>;
16
+ }, confirmed: () => void): {
17
+ status: import("vue").Ref<CapabilityStatus | undefined, CapabilityStatus | undefined>;
18
+ password: import("vue").Ref<string, string>;
19
+ busy: import("vue").Ref<boolean, boolean>;
20
+ confirming: import("vue").Ref<boolean, boolean>;
21
+ error: import("vue").Ref<boolean, boolean>;
22
+ failure: import("vue").Ref<{
23
+ confirm: ConfirmFailure;
24
+ } | {
25
+ reason: string;
26
+ code?: string;
27
+ } | undefined, {
28
+ confirm: ConfirmFailure;
29
+ } | {
30
+ reason: string;
31
+ code?: string;
32
+ } | undefined>;
33
+ scope: import("vue").Ref<ScopeDetail | undefined, ScopeDetail | undefined>;
34
+ chosen: import("vue").Ref<string, string>;
35
+ options: import("vue").ComputedRef<{
36
+ label: string;
37
+ value: string;
38
+ }[]>;
39
+ dynamic: import("vue").ComputedRef<boolean>;
40
+ files: import("vue").ComputedRef<boolean>;
41
+ canConfirm: import("vue").ComputedRef<boolean>;
42
+ needsScope: import("vue").ComputedRef<boolean>;
43
+ changed: import("vue").ComputedRef<boolean>;
44
+ refresh: () => Promise<void>;
45
+ authorize: () => Promise<void>;
46
+ explain: (r?: {
47
+ reason?: string;
48
+ code?: string;
49
+ }) => string | undefined;
50
+ };
@@ -21,7 +21,7 @@ export interface FileStationOptions {
21
21
  * stay literal: this is a JS value, not a URL. */
22
22
  export declare function fileStationPath(path: string, mount?: string): string;
23
23
  /** Opens File Station showing the folder. False when nothing was launched:
24
- * outside DSM, an empty path, or File Station disabled or not launchable. */
24
+ * outside DSM, a path that is not one shared-folder path, or File Station disabled or not launchable. */
25
25
  export declare function openFolderInFileStation(path: string, options?: FileStationOptions): boolean;
26
26
  /** Opens File Station at the file's folder with the file selected. False as for openFolderInFileStation. */
27
27
  export declare function openFileInFileStation(path: string, options?: FileStationOptions): boolean;
@@ -0,0 +1,2 @@
1
+ /** Shared host flow. CGI plans are never accepted as completed authorization. */
2
+ export declare const AUTHORIZATION_RUNTIME = "function createAuthorizationAccess(options) {\n var busy = null;\n function fail(code) { var error = new Error(code); error.code = code; return error; }\n function status() { return options.call(\"authorization.status\").then(function (d) {\n if (!d || d.command !== \"authorization\" || d.schema_version !== 1 || [\"ready\",\"authorization_required\",\"not_admin\",\"session_expired\",\"unavailable\"].indexOf(d.state) < 0) throw fail(\"authorization_bad_response\");\n // upgrade_reapproval is a reason-only tombstone: it can only explain a pending request.\n if (d.reason === \"upgrade_reapproval\" && d.state !== \"authorization_required\") throw fail(\"authorization_bad_response\");\n return d;\n }); }\n function plan(method) { return options.call(method).then(function (p) {\n if (!p || p.command !== \"authorization\" || p.schema_version !== 1 || p.phase !== \"plan\" || !Array.isArray(p.operations) || p.operations.length === 0 || p.operations.length > options.tasks.length) throw fail(\"authorization_bad_response\");\n var seen = {};\n p.operations.forEach(function (op) { if (seen[op] || !options.tasks.some(function (t) { return t.op === op; })) throw fail(\"authorization_bad_response\"); seen[op] = true; });\n return p;\n }); }\n // The backend's grant decides: a task still waiting at the window's limit, or\n // one signalled after it wrote the grant, has still authorized the package.\n function settled(e) {\n if (!e || (e.code !== \"root_timeout\" && e.code !== \"root_task_failed\")) throw e;\n return status().then(function (d) { if (d.state !== \"ready\") throw e; });\n }\n function exclusive(fn) { if (busy) return busy; busy = Promise.resolve().then(fn).then(function (s) { busy = null; return s; },function (e) { busy = null; throw e; });return busy; }\n function authorize(ops,run) { return ops.reduce(function (previous,op) { return previous.then(function () {\n return options.root.authorize(op).then(function (state) { if (state !== \"ready\") throw fail(\"root_cancelled\"); return run ? options.root.run(op).catch(settled) : null; });\n }); },Promise.resolve()); }\n return {canManage:function () {return !!options.user && options.user().admin === true;},status:status,request:function () { return exclusive(function () {\n return plan(\"authorization.request\").then(function (p) { return authorize(p.operations,p.run === true); }).then(status,function (e) { if (e.code === \"root_cancelled\") return status();throw e; });\n }); },revoke:function () { return exclusive(function () {\n return plan(\"authorization.revoke\").then(function (p) {\n if (p.withdraw === true && typeof options.withdraw !== \"function\") throw fail(\"authorization_bad_response\");\n var disabled = p.withdraw === true ? options.withdraw() : p.disable === true ? authorize([\"helper_disable\"],true) : Promise.resolve();\n return disabled.then(function () { return p.purge === true ? authorize([\"helper_purge\"],true) : null; }).then(function () { return p.operations.reduce(function (previous,op) {return previous.then(function () {return options.root.remove(op);});},Promise.resolve()); });\n }).then(status,function (e) { if (e.code === \"root_cancelled\") return status();throw e; });\n }); }};\n}";
@@ -0,0 +1,6 @@
1
+ /** Self-contained: the same function is embedded in the DSM window. True only
2
+ * when DSM refused a request because this method version is unavailable, the
3
+ * one refusal that may be retried with an older version. DSM 7.1.1 (t-0234)
4
+ * returns 104 for a version above maxVersion and 103 for a method absent at an
5
+ * existing version. Accepts the numeric code and the window's dsm_ form. */
6
+ export declare function versionUnsupported(code: unknown): boolean;
@@ -0,0 +1,34 @@
1
+ /** Build-time adapter for explicitly approved native product tasks. */
2
+ /** What the window embeds per root operation: the task it may create, and how to recognize it. */
3
+ export interface RootTask {
4
+ op: string;
5
+ name: string;
6
+ header: string;
7
+ script: string;
8
+ /** Whether the package backend serves `root.output` for this op; helper ops report through the helper instead. */
9
+ output: boolean;
10
+ }
11
+ /**
12
+ * `createRootAccess(options)` → `{ state, authorize, run, remove }`, plain
13
+ * ES5 for DSM's desktop. Every DSM call goes through `options.send` (the
14
+ * AppWindow's sendWebAPI) as the signed-in administrator:
15
+ *
16
+ * - authorize: DSM's own password confirmation, then one disabled root task
17
+ * with exactly the embedded script. The one-use token goes into that single
18
+ * create call and is never kept.
19
+ * - run: re-reads the task and runs it only if it is still exactly ours (the
20
+ * first run after an authorize uses the task that authorize just read back), then
21
+ * waits for its history entry and asks the backend for the output. A queued
22
+ * or running task keeps the wait going, up to RUN_LIMIT_MS (loaded NAS took
23
+ * 4.5 minutes), and `options.progress({op, state, elapsedMs})` hears each poll. Repair
24
+ * additionally requires fresh PasswordConfirm and another exact task check.
25
+ * - reads follow spec/scheduler/v1: a step lists Task Scheduler once and gets
26
+ * the task by that id; a step that deletes nothing gets the id an earlier
27
+ * list showed and lists again when DSM answers 4801 or another task. A
28
+ * duplicate name and any difference from the exact definition and script
29
+ * are never ready.
30
+ * - an older version of our task is "outdated" and never runs; authorizing
31
+ * again replaces it. A same-named task that is not ours is a "conflict" and
32
+ * is never run, replaced or deleted.
33
+ */
34
+ export declare const ROOT_RUNTIME: string;
@@ -0,0 +1,2 @@
1
+ export { ROOT_RUNTIME, type RootTask } from './native/root-runtime';
2
+ export { AUTHORIZATION_RUNTIME } from './native/authorization-runtime';
@@ -78,6 +78,12 @@ export declare const protocolCodes: {
78
78
  readonly retryable: true;
79
79
  readonly httpStatus: 503;
80
80
  };
81
+ /** The executor is running the App's start step after an install or upgrade; status answers state starting until it ends. */
82
+ readonly EXECUTOR_STARTING: {
83
+ readonly kind: "refusal";
84
+ readonly retryable: true;
85
+ readonly httpStatus: 503;
86
+ };
81
87
  /** The executor could not read or write its protected state. */
82
88
  readonly STORAGE_ERROR: {
83
89
  readonly kind: "refusal";
@@ -348,6 +354,18 @@ export declare const protocolCodes: {
348
354
  readonly retryable: true;
349
355
  readonly httpStatus: 503;
350
356
  };
357
+ /** The package is stopped: its lifecycle mailbox asks the executor to stop. The client sent nothing. */
358
+ readonly APP_STOPPED: {
359
+ readonly kind: "client";
360
+ readonly retryable: true;
361
+ readonly httpStatus: 503;
362
+ };
363
+ /** The package was just started and its executor is not listening yet. The client sent nothing. */
364
+ readonly APP_STARTING: {
365
+ readonly kind: "client";
366
+ readonly retryable: true;
367
+ readonly httpStatus: 503;
368
+ };
351
369
  /** The executor did not answer in time. */
352
370
  readonly EXECUTOR_TIMEOUT: {
353
371
  readonly kind: "client";
@@ -368,10 +386,10 @@ export declare const protocolCodes: {
368
386
  };
369
387
  };
370
388
  export type ProtocolCode = keyof typeof protocolCodes;
371
- export type RefusalCode = "AUTH_DENIED" | "INELIGIBLE" | "APP_DENIED" | "ADMIN_REQUIRED" | "DELEGATION_DENIED" | "SCOPE_DENIED" | "POLICY_DENIED" | "PEER_DENIED" | "PERMISSION_DENIED" | "UNKNOWN_OP" | "INVALID_REQUEST" | "REQUEST_TOO_LARGE" | "EXECUTOR_PAUSED" | "STORAGE_ERROR" | "INTERNAL" | "WRITE_FAILED" | "READ_FAILED" | "DSM_FAILED" | "ROOT_FAILED" | "ROOT_TIMEOUT" | "ROOT_BUSY" | "ROOT_STAGING_FULL" | "ROOT_JOB_NOT_FOUND" | "PORTAL_FAILED" | "NO_SPACE" | "SCOPE_APPROVAL_STALE" | "IDENTITY_CHANGED" | "needs-scope-confirmation" | "disabled" | "invalid-destination" | "invalid-size" | "operation-conflict" | "operation-not-found" | "destination-exists" | "invalid-path" | "path-too-deep" | "destination-not-directory" | "name-too-long" | "not-found" | "not-a-file" | "recursive-required" | "recycle-bin-disabled" | "task-not-found" | "too-many-tasks" | "queue-full" | "limit-exceeded";
389
+ export type RefusalCode = "AUTH_DENIED" | "INELIGIBLE" | "APP_DENIED" | "ADMIN_REQUIRED" | "DELEGATION_DENIED" | "SCOPE_DENIED" | "POLICY_DENIED" | "PEER_DENIED" | "PERMISSION_DENIED" | "UNKNOWN_OP" | "INVALID_REQUEST" | "REQUEST_TOO_LARGE" | "EXECUTOR_PAUSED" | "EXECUTOR_STARTING" | "STORAGE_ERROR" | "INTERNAL" | "WRITE_FAILED" | "READ_FAILED" | "DSM_FAILED" | "ROOT_FAILED" | "ROOT_TIMEOUT" | "ROOT_BUSY" | "ROOT_STAGING_FULL" | "ROOT_JOB_NOT_FOUND" | "PORTAL_FAILED" | "NO_SPACE" | "SCOPE_APPROVAL_STALE" | "IDENTITY_CHANGED" | "needs-scope-confirmation" | "disabled" | "invalid-destination" | "invalid-size" | "operation-conflict" | "operation-not-found" | "destination-exists" | "invalid-path" | "path-too-deep" | "destination-not-directory" | "name-too-long" | "not-found" | "not-a-file" | "recursive-required" | "recycle-bin-disabled" | "task-not-found" | "too-many-tasks" | "queue-full" | "limit-exceeded";
372
390
  export type OutcomeCode = "OPERATION_CANCELED" | "CANCEL_REQUESTED" | "CLEANUP_PENDING";
373
391
  export type ReasonCode = "grant-revoked" | "destination-replaced" | "integration-disabled" | "validation-denied" | "scope-changed" | "storage-error" | "operation-canceled-by-user" | "operation-deadline-exceeded";
374
- export type ClientCode = "EXECUTOR_UNAVAILABLE" | "EXECUTOR_TIMEOUT" | "EXECUTOR_TOO_LARGE" | "EXECUTOR_PROTOCOL";
392
+ export type ClientCode = "EXECUTOR_UNAVAILABLE" | "APP_STOPPED" | "APP_STARTING" | "EXECUTOR_TIMEOUT" | "EXECUTOR_TOO_LARGE" | "EXECUTOR_PROTOCOL";
375
393
  /** delegate.audit: Administrator: read the audit log. Since 0.9.0. */
376
394
  export interface DelegateAuditParams {
377
395
  }
@@ -23,6 +23,9 @@ type __VLS_Slots = {
23
23
  actions?: (scope: {
24
24
  page: string;
25
25
  }) => unknown;
26
+ meta?: (scope: {
27
+ page: string;
28
+ }) => unknown;
26
29
  toolbar?: (scope: {
27
30
  page: string;
28
31
  }) => unknown;
@@ -0,0 +1,13 @@
1
+ declare var __VLS_7: {};
2
+ type __VLS_Slots = {} & {
3
+ default?: (props: typeof __VLS_7) => any;
4
+ };
5
+ declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
6
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
7
+ declare const _default: typeof __VLS_export;
8
+ export default _default;
9
+ type __VLS_WithSlots<T, S> = T & {
10
+ new (): {
11
+ $slots: S;
12
+ };
13
+ };
@@ -14,6 +14,8 @@ export interface AppShellPage {
14
14
  component?: Component;
15
15
  /** Reachable through v-model but not listed in the sidebar. */
16
16
  hidden?: boolean;
17
+ /** 'bottom': listed after every other page, in a group of its own (an App's settings). */
18
+ placement?: 'bottom';
17
19
  /** Replaces the shell's description for this page. */
18
20
  description?: string;
19
21
  /** false: the page draws its own header. */
@@ -0,0 +1,3 @@
1
+ import type { InjectionKey, ShallowRef } from 'vue';
2
+ /** Where AppShell's page header takes a page's own actions. */
3
+ export declare const PageActionsTarget: InjectionKey<Readonly<ShallowRef<HTMLElement | null>>>;
package/dist/src/vue.d.ts CHANGED
@@ -3,6 +3,8 @@ export { ExecutorSetupKey, useExecutorSetup } from './delegate/use-executor-setu
3
3
  export { createSession, type IdentitySession, type SessionSubject } from './identity/session';
4
4
  export { useNasRequest } from './nas/use-request';
5
5
  export { default as AppShell } from './shell/AppShell.vue';
6
+ export { default as PageActions } from './shell/PageActions.vue';
7
+ export { PageActionsTarget } from './shell/page-actions';
6
8
  export type { AppShellDenied, AppShellPage, AppShellPageEntry } from './shell/app-pages';
7
9
  export { default as FilesPage } from './files/FilesPage.vue';
8
10
  export { default as FileBrowser } from './files/FileBrowser.vue';
@@ -15,6 +17,7 @@ export { default as ExecutorApproval } from './delegate/ExecutorApproval.vue';
15
17
  export { default as ExecutorNotice } from './delegate/ExecutorNotice.vue';
16
18
  export { default as DelegatePanel } from './delegate/DelegatePanel.vue';
17
19
  export { default as BackgroundSavePanel } from './delegate/BackgroundSavePanel.vue';
20
+ export { default as BackgroundSaveSettings } from './delegate/BackgroundSaveSettings.vue';
18
21
  export { default as AuthorizationGate } from './authorization/AuthorizationGate.vue';
19
22
  export { useAuthorization, type AuthorizationControl, type AuthorizationGateState } from './authorization/use-authorization';
20
23
  export { default as AuthorizationSettings } from './authorization/AuthorizationSettings.vue';
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .executor-help[data-v-928609ab]{margin:0 0 var(--ui-space-3,12px);max-width:72ch;color:var(--ui-text-secondary)}.executor-summary[data-v-928609ab]{margin-bottom:var(--ui-space-3,12px)}.executor-form[data-v-928609ab]{margin-top:var(--ui-space-4,16px);max-width:28rem}.executor-hint[data-v-928609ab]{font-size:12px;color:var(--ui-text-secondary)}.executor-reason[data-v-928609ab]{display:block;margin-top:var(--ui-space-1,4px);font-size:12px}.executor-alert[data-v-928609ab]{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--ui-space-2,8px)}.executor-notice[data-v-771da19a]{margin-bottom:var(--ui-space-4, 16px)}.executor-notice-body[data-v-771da19a]{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--ui-space-2, 8px)}.app-shell[data-v-098c9e72]{height:100%;min-width:0;grid-template-rows:minmax(0,1fr)}.app-shell[data-v-098c9e72]>div{min-height:0}.app-shell[data-v-098c9e72] main{display:flex;flex-direction:column;overflow:hidden}.app-page[data-v-098c9e72]{flex:1 1 auto;min-height:0;overflow-y:auto}.app-denied[data-v-098c9e72]{height:100%;overflow-y:auto}.app-shell-fill[data-v-098c9e72]{max-height:100dvh}.app-page-fill[data-v-098c9e72]{display:flex;flex-direction:column;overflow:hidden}.app-page-fill[data-v-098c9e72]>[data-page-content-body]{display:flex;flex:1 1 auto;flex-direction:column;width:100%;min-height:0}.app-page-fill .app-notices[data-v-098c9e72]{flex:0 0 auto}.app-page-fill .app-page-content[data-v-098c9e72]{display:grid;flex:1 1 auto;grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr);min-height:0}.app-notices[data-v-098c9e72]{display:flex;flex-direction:column;gap:var(--ui-space-2, 8px);margin-bottom:var(--ui-space-4, 16px)}.app-page-content[data-v-098c9e72]{padding-bottom:var(--ui-space-6, 24px)}.file-browser[data-v-c689761c]{min-width:0;color:var(--ui-text)}.file-toolbar[data-v-c689761c]{display:flex;flex-wrap:wrap;gap:var(--ui-space-2, 8px);margin-block:var(--ui-space-3, 12px)}.file-location[data-v-c689761c]{flex-wrap:nowrap;align-items:center;gap:var(--ui-space-1, 4px)}.file-path[data-v-c689761c]{flex:1;min-width:0;margin-inline-start:var(--ui-space-2, 8px)}.file-columns[data-v-c689761c]{display:grid;grid-template-columns:minmax(140px,1fr) minmax(0,3fr);gap:var(--ui-space-3, 12px);height:clamp(240px,60vh,400px)}.file-tree[data-v-c689761c]{min-width:0;overflow:auto;border-inline-end:1px solid var(--ui-border)}.file-content[data-v-c689761c]{display:flex;flex-direction:column;min-width:0;min-height:0;overflow:auto}.file-empty[data-v-c689761c]{display:flex;flex-direction:column;align-items:center;gap:var(--ui-space-2, 8px);padding-block:var(--ui-space-6, 24px);color:var(--ui-text-muted)}.file-name[data-v-c689761c]{display:inline-flex;align-items:center;gap:var(--ui-space-2, 8px);overflow-wrap:anywhere}.file-bytes[data-v-c689761c]{font-variant-numeric:tabular-nums}.file-selection[data-v-c689761c]{overflow-wrap:anywhere}@media(max-width:600px){.file-columns[data-v-c689761c]{grid-template-columns:minmax(0,1fr);height:auto}.file-content[data-v-c689761c] th:nth-child(2),.file-content[data-v-c689761c] td:nth-child(2),.file-content[data-v-c689761c] th:nth-child(3),.file-content[data-v-c689761c] td:nth-child(3){display:none}.file-tree[data-v-c689761c]{height:clamp(96px,25vh,180px);border-inline-end:0;border-bottom:1px solid var(--ui-border)}.file-content[data-v-c689761c]{height:clamp(200px,45vh,360px)}}.nas-picker-content[data-v-6ed8b8f6]{max-height:65vh;overflow:auto}.save-message[data-v-6ed8b8f6]{--ui-text-secondary:var(--ui-text)}.save-consent[data-v-6ed8b8f6]{color:var(--ui-text);margin-block:0 var(--ui-space-4,16px)}.files-actions[data-v-15f9eb8e]{display:flex;flex-wrap:wrap;gap:var(--ui-space-2, 8px)}.files-path[data-v-15f9eb8e]{display:flex;min-width:0}.identity-login[data-v-1c0358cd]{max-width:36rem;margin-inline:auto;padding:var(--ui-space-4, 16px);overflow:auto;max-height:100%;color:var(--ui-text);font-family:var(--ui-font-sans);font-size:13px;line-height:1.5}.identity-login p[data-v-1c0358cd]{margin-block:var(--ui-space-4, 16px);overflow-wrap:anywhere}.bg-cards[data-v-fa2b6101]{display:grid;gap:var(--ui-space-3,12px);min-width:0;overflow-wrap:anywhere}.bg-card-body[data-v-fa2b6101]{display:flex;flex-direction:column;align-items:flex-start;gap:var(--ui-space-2,8px);min-width:0}.bg-card-body>span[data-v-fa2b6101]{min-width:0;max-width:100%}.integration-actions[data-v-fa2b6101]{display:flex;flex-wrap:wrap;gap:var(--ui-space-2,8px)}.bg-schedules[data-v-fa2b6101]{margin-block-start:var(--ui-space-6,24px);min-width:0;overflow-wrap:anywhere}.bg-schedules p[data-v-fa2b6101]{min-width:0;max-width:100%}.bg-schedules h3[data-v-fa2b6101]{font-size:15px;font-weight:600}.bg-schedule-form[data-v-fa2b6101]{margin-block:var(--ui-space-4,16px)}.bg-path[data-v-fa2b6101]{display:flex;align-items:center;gap:var(--ui-space-2,8px);min-width:0;max-width:100%}.executor-approval[data-v-632b6fba]{padding:var(--ui-space-6, 24px)}.executor-brand[data-v-632b6fba]{display:flex;align-items:center;gap:var(--ui-space-2, 8px);margin-bottom:var(--ui-space-4, 16px);font-size:16px;font-weight:600;color:var(--ui-text-primary)}.executor-brand img[data-v-632b6fba]{width:24px;height:24px}.delegate-panel[data-v-c590f505]{min-width:0;overflow-wrap:anywhere}h3[data-v-c590f505]{font-size:var(--ui-font-size-base,14px);font-weight:600;margin:var(--ui-space-6,24px) 0 var(--ui-space-3,12px)}.records[data-v-c590f505]{list-style:none;padding:0;margin:0}.records li[data-v-c590f505]{display:flex;align-items:flex-start;justify-content:space-between;flex-wrap:wrap;gap:var(--ui-space-3,12px);padding-block:var(--ui-space-4,16px);border-bottom:1px solid var(--ui-border)}.records li>div[data-v-c590f505],.records li>span[data-v-c590f505],.destination[data-v-c590f505]{min-width:0;max-width:100%;overflow-wrap:anywhere}.records p[data-v-c590f505]{margin:var(--ui-space-2,8px) 0 0}.destination[data-v-c590f505]{display:flex;align-items:center;gap:var(--ui-space-2,8px)}.background-save-panel[data-v-5ef5e256]{min-width:0;overflow-wrap:anywhere}.save-message[data-v-5ef5e256]{--ui-text-secondary:var(--ui-text)}.save-help[data-v-5ef5e256]{margin:0 0 var(--ui-space-3,12px);max-width:72ch;color:var(--ui-text-secondary)}.save-summary[data-v-5ef5e256]{margin-bottom:var(--ui-space-3,12px)}h3[data-v-5ef5e256]{font-size:var(--ui-font-size-base,14px);font-weight:600;margin:var(--ui-space-6,24px) 0 var(--ui-space-3,12px)}.save-actions[data-v-5ef5e256],.save-records li[data-v-5ef5e256],.save-danger[data-v-5ef5e256]{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--ui-space-2,8px)}.save-actions[data-v-5ef5e256]{justify-content:flex-start;margin-top:var(--ui-space-3,12px)}.save-records[data-v-5ef5e256]{list-style:none;margin:0;padding:0}.save-records li[data-v-5ef5e256]{padding-block:var(--ui-space-2,8px);border-bottom:1px solid var(--ui-border)}.save-record[data-v-5ef5e256]{display:flex;flex-direction:column;align-items:flex-start;min-width:0;flex:1}.save-name[data-v-5ef5e256]{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.save-note[data-v-5ef5e256]{margin:var(--ui-space-1,4px) 0 0;font-size:12px;color:var(--ui-text-secondary);white-space:normal}.save-alert[data-v-5ef5e256]{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--ui-space-2,8px)}.save-icon[data-v-5ef5e256]{width:16px;height:16px}[data-save-operations][data-v-5ef5e256] table{table-layout:fixed}[data-save-operations][data-v-5ef5e256] th,[data-save-operations][data-v-5ef5e256] td{overflow-wrap:normal;white-space:nowrap}[data-save-operations][data-v-5ef5e256] td{padding-block:var(--ui-space-2,8px)}.save-example[data-v-5ef5e256]{margin-top:var(--ui-space-5,20px)}.save-pages[data-v-5ef5e256]{margin-top:var(--ui-space-3,12px)}.save-danger[data-v-5ef5e256]{flex:1;margin-top:var(--ui-space-2,8px);padding-top:var(--ui-space-4,16px);border-top:1px solid var(--ui-border)}.save-danger p[data-v-5ef5e256]{margin:0;flex:1 1 20rem;max-width:72ch;color:var(--ui-text-secondary)}.authorization-view[data-v-e16b5f7d]{display:flex;flex-direction:column;gap:12px}.authorization-body[data-v-e16b5f7d]{margin:0;font-size:13px;line-height:1.6;color:var(--ui-text);text-wrap:pretty}.authorization-status[data-v-e16b5f7d],.authorization-failed[data-v-e16b5f7d]{color:var(--ui-text)}.authorization-content[data-v-e16b5f7d]{display:flex;flex-direction:column;height:100%;min-height:0}.authorization-content[data-v-e16b5f7d] .app-shell{flex:1;min-height:0;height:auto}.authorization-setting[data-v-f031e7c7]{display:flex;align-items:center;flex-wrap:wrap;gap:12px}.authorization-revoke-body[data-v-f031e7c7]{margin:0;font-size:13px;line-height:1.6;color:var(--ui-text)}.authorization-state[data-v-f031e7c7]{display:inline-flex;align-items:center;gap:6px;color:var(--ui-text)}
1
+ .executor-help[data-v-8e5504f7]{margin:0 0 var(--ui-space-3,12px);max-width:72ch;color:var(--ui-text-secondary)}.executor-summary[data-v-8e5504f7]:not(:last-child){margin-bottom:var(--ui-space-3,12px)}.executor-form[data-v-8e5504f7]{margin-top:var(--ui-space-4,16px);max-width:28rem}.executor-hint[data-v-8e5504f7]{font-size:var(--ui-font-size-sm,12px);color:var(--ui-text-secondary)}.executor-reason[data-v-8e5504f7]{display:block;margin-top:var(--ui-space-1,4px);font-size:var(--ui-font-size-sm,12px)}.executor-alert[data-v-8e5504f7]{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--ui-space-2,8px)}.executor-notice[data-v-8ec9f312]{margin-bottom:var(--ui-space-4, 16px)}.executor-notice-body[data-v-8ec9f312]{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--ui-space-2, 8px)}.app-shell[data-v-c9bc6bd5]{height:100%;min-width:0;grid-template-rows:minmax(0,1fr)}.app-shell[data-v-c9bc6bd5]>div{min-height:0}.app-shell[data-v-c9bc6bd5] main{display:flex;flex-direction:column;overflow:hidden}.app-page[data-v-c9bc6bd5]{flex:1 1 auto;min-height:0;overflow-y:auto}.app-denied[data-v-c9bc6bd5]{height:100%;overflow-y:auto}.app-page-actions[data-v-c9bc6bd5]{display:contents}.app-shell-fill[data-v-c9bc6bd5]{max-height:100dvh}.app-page-fill[data-v-c9bc6bd5]{display:flex;flex-direction:column;overflow:hidden}.app-page-fill[data-v-c9bc6bd5]>[data-page-content-body]{display:flex;flex:1 1 auto;flex-direction:column;width:100%;min-height:0}.app-page-fill .app-notices[data-v-c9bc6bd5]{flex:0 0 auto}.app-page-fill .app-page-content[data-v-c9bc6bd5]{display:grid;flex:1 1 auto;grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr);min-height:0}.app-notices[data-v-c9bc6bd5]{display:flex;flex-direction:column;gap:var(--ui-space-2, 8px);margin-bottom:var(--ui-space-4, 16px)}.app-page-content[data-v-c9bc6bd5]{padding-bottom:var(--ui-space-6, 24px)}.file-browser[data-v-c689761c]{min-width:0;color:var(--ui-text)}.file-toolbar[data-v-c689761c]{display:flex;flex-wrap:wrap;gap:var(--ui-space-2, 8px);margin-block:var(--ui-space-3, 12px)}.file-location[data-v-c689761c]{flex-wrap:nowrap;align-items:center;gap:var(--ui-space-1, 4px)}.file-path[data-v-c689761c]{flex:1;min-width:0;margin-inline-start:var(--ui-space-2, 8px)}.file-columns[data-v-c689761c]{display:grid;grid-template-columns:minmax(140px,1fr) minmax(0,3fr);gap:var(--ui-space-3, 12px);height:clamp(240px,60vh,400px)}.file-tree[data-v-c689761c]{min-width:0;overflow:auto;border-inline-end:1px solid var(--ui-border)}.file-content[data-v-c689761c]{display:flex;flex-direction:column;min-width:0;min-height:0;overflow:auto}.file-empty[data-v-c689761c]{display:flex;flex-direction:column;align-items:center;gap:var(--ui-space-2, 8px);padding-block:var(--ui-space-6, 24px);color:var(--ui-text-muted)}.file-name[data-v-c689761c]{display:inline-flex;align-items:center;gap:var(--ui-space-2, 8px);overflow-wrap:anywhere}.file-bytes[data-v-c689761c]{font-variant-numeric:tabular-nums}.file-selection[data-v-c689761c]{overflow-wrap:anywhere}@media(max-width:600px){.file-columns[data-v-c689761c]{grid-template-columns:minmax(0,1fr);height:auto}.file-content[data-v-c689761c] th:nth-child(2),.file-content[data-v-c689761c] td:nth-child(2),.file-content[data-v-c689761c] th:nth-child(3),.file-content[data-v-c689761c] td:nth-child(3){display:none}.file-tree[data-v-c689761c]{height:clamp(96px,25vh,180px);border-inline-end:0;border-bottom:1px solid var(--ui-border)}.file-content[data-v-c689761c]{height:clamp(200px,45vh,360px)}}.nas-picker-content[data-v-6ed8b8f6]{max-height:65vh;overflow:auto}.save-message[data-v-6ed8b8f6]{--ui-text-secondary:var(--ui-text)}.save-consent[data-v-6ed8b8f6]{color:var(--ui-text);margin-block:0 var(--ui-space-4,16px)}.files-actions[data-v-15f9eb8e]{display:flex;flex-wrap:wrap;gap:var(--ui-space-2, 8px)}.files-path[data-v-15f9eb8e]{display:flex;min-width:0}.identity-login[data-v-1c0358cd]{max-width:36rem;margin-inline:auto;padding:var(--ui-space-4, 16px);overflow:auto;max-height:100%;color:var(--ui-text);font-family:var(--ui-font-sans);font-size:13px;line-height:1.5}.identity-login p[data-v-1c0358cd]{margin-block:var(--ui-space-4, 16px);overflow-wrap:anywhere}.bg-cards[data-v-3e23f18f]{display:grid;gap:var(--ui-space-3,12px);min-width:0;overflow-wrap:anywhere}.bg-card-body[data-v-3e23f18f]{display:flex;flex-direction:column;align-items:flex-start;gap:var(--ui-space-2,8px);min-width:0}.bg-card-body>span[data-v-3e23f18f]{min-width:0;max-width:100%}.integration-actions[data-v-3e23f18f]{display:flex;flex-wrap:wrap;gap:var(--ui-space-2,8px)}.bg-schedules[data-v-3e23f18f]{margin-block-start:var(--ui-space-6,24px);min-width:0;overflow-wrap:anywhere}.bg-schedules p[data-v-3e23f18f]{min-width:0;max-width:100%}.bg-schedule-form[data-v-3e23f18f]{margin-block:var(--ui-space-4,16px)}.bg-path[data-v-3e23f18f]{display:flex;align-items:center;gap:var(--ui-space-2,8px);min-width:0;max-width:100%}.executor-approval[data-v-88a4ee77]{padding:var(--ui-space-6, 24px)}.executor-brand[data-v-88a4ee77]{display:flex;align-items:center;gap:var(--ui-space-2, 8px);margin-bottom:var(--ui-space-4, 16px);font-size:16px;font-weight:600;color:var(--ui-text-primary)}.executor-brand img[data-v-88a4ee77]{width:24px;height:24px}.delegate-panel[data-v-e6f168a0]{min-width:0;overflow-wrap:anywhere}.delegate-group[data-v-e6f168a0]{margin-top:var(--ui-space-6,24px)}.records[data-v-e6f168a0]{list-style:none;padding:0;margin:0}.records li[data-v-e6f168a0]{display:flex;align-items:flex-start;justify-content:space-between;flex-wrap:wrap;gap:var(--ui-space-3,12px);padding-block:var(--ui-space-4,16px);border-bottom:1px solid var(--ui-border)}.records li>div[data-v-e6f168a0],.records li>span[data-v-e6f168a0],.destination[data-v-e6f168a0]{min-width:0;max-width:100%;overflow-wrap:anywhere}.records p[data-v-e6f168a0]{margin:var(--ui-space-2,8px) 0 0}.destination[data-v-e6f168a0]{display:flex;align-items:center;gap:var(--ui-space-2,8px)}.save-help[data-v-8c9a2ec0]{margin:0 0 var(--ui-space-3,12px);max-width:72ch;color:var(--ui-text-secondary)}.save-alert[data-v-8c9a2ec0]{display:flex;align-items:center;flex-wrap:wrap;gap:var(--ui-space-2,8px);justify-content:space-between}.save-name[data-v-8c9a2ec0]{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.save-note[data-v-8c9a2ec0]{margin:var(--ui-space-1,4px) 0 0;font-size:var(--ui-font-size-sm,12px);color:var(--ui-text-secondary);white-space:normal}.save-icon[data-v-8c9a2ec0]{width:16px;height:16px}[data-save-operations][data-v-8c9a2ec0] table{table-layout:fixed}[data-save-operations][data-v-8c9a2ec0] th,[data-save-operations][data-v-8c9a2ec0] td{overflow-wrap:normal;white-space:nowrap}[data-save-operations][data-v-8c9a2ec0] td{padding-block:var(--ui-space-2,8px)}.save-pages[data-v-8c9a2ec0]{margin-top:var(--ui-space-3,12px)}.background-save-settings[data-v-abaa1bee]{min-width:0;overflow-wrap:anywhere}.save-help[data-v-abaa1bee]{margin:0 0 var(--ui-space-2,8px);max-width:72ch;color:var(--ui-text-secondary)}.save-form[data-v-abaa1bee]{max-width:44rem}.save-actions[data-v-abaa1bee],.save-alert[data-v-abaa1bee],.save-danger[data-v-abaa1bee]{display:flex;align-items:center;flex-wrap:wrap;gap:var(--ui-space-2,8px)}.save-alert[data-v-abaa1bee],.save-danger[data-v-abaa1bee]{justify-content:space-between}.save-none[data-v-abaa1bee]{color:var(--ui-text-secondary)}.save-reason[data-v-abaa1bee]{display:block;margin-top:var(--ui-space-1,4px);font-size:var(--ui-font-size-sm,12px)}.save-danger[data-v-abaa1bee]{flex:1;padding-top:var(--ui-space-3,12px);border-top:1px solid var(--ui-border)}.save-danger p[data-v-abaa1bee]{margin:0;flex:1 1 20rem;max-width:72ch;font-size:var(--ui-font-size-sm,12px);color:var(--ui-text-secondary)}.background-save-panel[data-v-55770b8c]{min-width:0;overflow-wrap:anywhere}.save-help[data-v-55770b8c]{margin:0 0 var(--ui-space-3,12px);max-width:72ch;color:var(--ui-text-secondary)}.save-actions[data-v-55770b8c]{display:flex;align-items:center;flex-wrap:wrap;gap:var(--ui-space-2,8px);margin-bottom:var(--ui-space-3,12px)}.authorization-view[data-v-e16b5f7d]{display:flex;flex-direction:column;gap:12px}.authorization-body[data-v-e16b5f7d]{margin:0;font-size:13px;line-height:1.6;color:var(--ui-text);text-wrap:pretty}.authorization-status[data-v-e16b5f7d],.authorization-failed[data-v-e16b5f7d]{color:var(--ui-text)}.authorization-content[data-v-e16b5f7d]{display:flex;flex-direction:column;height:100%;min-height:0}.authorization-content[data-v-e16b5f7d] .app-shell{flex:1;min-height:0;height:auto}.authorization-setting[data-v-f031e7c7]{display:flex;align-items:center;flex-wrap:wrap;gap:12px}.authorization-revoke-body[data-v-f031e7c7]{margin:0;font-size:13px;line-height:1.6;color:var(--ui-text)}.authorization-state[data-v-f031e7c7]{display:inline-flex;align-items:center;gap:6px;color:var(--ui-text)}