@duplicati/ngclient 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/.dockerignore +13 -0
  2. package/.github/workflows/npm-publish.yml +59 -0
  3. package/.prettierignore +13 -0
  4. package/.prettierrc +12 -0
  5. package/.vscode/extensions.json +4 -0
  6. package/.vscode/launch.json +13 -0
  7. package/.vscode/settings.json +8 -0
  8. package/.vscode/tasks.json +24 -0
  9. package/Dockerfile +38 -0
  10. package/LICENSE +21 -0
  11. package/README.md +27 -0
  12. package/angular.json +98 -0
  13. package/bun.lockb +0 -0
  14. package/openapi-ts.config.ts +13 -0
  15. package/package.json +46 -0
  16. package/scripts/generate-package-json.ts +15 -0
  17. package/src/app/about/about.component.html +15 -0
  18. package/src/app/about/about.component.scss +19 -0
  19. package/src/app/about/about.component.ts +13 -0
  20. package/src/app/about/changelog/changelog.component.html +3 -0
  21. package/src/app/about/changelog/changelog.component.scss +7 -0
  22. package/src/app/about/changelog/changelog.component.ts +18 -0
  23. package/src/app/about/general/general.component.html +9 -0
  24. package/src/app/about/general/general.component.scss +23 -0
  25. package/src/app/about/general/general.component.ts +30 -0
  26. package/src/app/about/libraries/libraries.component.html +3 -0
  27. package/src/app/about/libraries/libraries.component.scss +7 -0
  28. package/src/app/about/libraries/libraries.component.ts +18 -0
  29. package/src/app/about/logs/logs.component.html +5 -0
  30. package/src/app/about/logs/logs.component.scss +7 -0
  31. package/src/app/about/logs/logs.component.ts +18 -0
  32. package/src/app/about/system-info/system-info.component.html +3 -0
  33. package/src/app/about/system-info/system-info.component.scss +7 -0
  34. package/src/app/about/system-info/system-info.component.ts +17 -0
  35. package/src/app/add-backup/add-backup.component.html +29 -0
  36. package/src/app/add-backup/add-backup.component.scss +38 -0
  37. package/src/app/add-backup/add-backup.component.ts +14 -0
  38. package/src/app/app.component.ts +35 -0
  39. package/src/app/app.config.ts +23 -0
  40. package/src/app/app.routes.ts +121 -0
  41. package/src/app/core/components/file-tree/file-tree.component.html +87 -0
  42. package/src/app/core/components/file-tree/file-tree.component.scss +80 -0
  43. package/src/app/core/components/file-tree/file-tree.component.ts +485 -0
  44. package/src/app/core/components/logo/logo.component.html +22 -0
  45. package/src/app/core/components/logo/logo.component.scss +12 -0
  46. package/src/app/core/components/logo/logo.component.ts +11 -0
  47. package/src/app/core/components/status-bar/status-bar.component.html +38 -0
  48. package/src/app/core/components/status-bar/status-bar.component.scss +27 -0
  49. package/src/app/core/components/status-bar/status-bar.component.ts +33 -0
  50. package/src/app/core/components/status-bar/status-bar.state.ts +182 -0
  51. package/src/app/core/components/toggle-card/toggle-card.component.html +11 -0
  52. package/src/app/core/components/toggle-card/toggle-card.component.scss +49 -0
  53. package/src/app/core/components/toggle-card/toggle-card.component.ts +28 -0
  54. package/src/app/core/interceptors/http.interceptor.ts +69 -0
  55. package/src/app/core/interceptors/websocket.interceptor.ts +66 -0
  56. package/src/app/core/openapi/core/ApiError.ts +21 -0
  57. package/src/app/core/openapi/core/ApiRequestOptions.ts +21 -0
  58. package/src/app/core/openapi/core/ApiResult.ts +7 -0
  59. package/src/app/core/openapi/core/OpenAPI.ts +55 -0
  60. package/src/app/core/openapi/core/request.ts +337 -0
  61. package/src/app/core/openapi/index.ts +6 -0
  62. package/src/app/core/openapi/schemas.gen.ts +3611 -0
  63. package/src/app/core/openapi/services.gen.ts +1460 -0
  64. package/src/app/core/openapi/types.gen.ts +1510 -0
  65. package/src/app/core/pipes/duration.pipe.ts +27 -0
  66. package/src/app/core/pipes/relative-time.pipe.ts +14 -0
  67. package/src/app/core/providers/dayjs.ts +16 -0
  68. package/src/app/core/services/dict.en.ts +0 -0
  69. package/src/app/core/services/dictionary.service.ts +12 -0
  70. package/src/app/core/services/localstorage.token.ts +82 -0
  71. package/src/app/core/services/password-generator.service.ts +39 -0
  72. package/src/app/core/services/relay-websocket.service.ts +268 -0
  73. package/src/app/core/services/timespan-literals.service.ts +25 -0
  74. package/src/app/core/states/app-auth.state.ts +87 -0
  75. package/src/app/core/states/backups.state.ts +71 -0
  76. package/src/app/core/states/relayconfig.state.ts +23 -0
  77. package/src/app/core/states/sysinfo.state.ts +31 -0
  78. package/src/app/core/states/tasks.state.ts +34 -0
  79. package/src/app/core/types/subscribed.ts +7 -0
  80. package/src/app/core/validators/custom.validators.ts +120 -0
  81. package/src/app/create-edit-backup/create-edit-backup.component.html +28 -0
  82. package/src/app/create-edit-backup/create-edit-backup.component.scss +15 -0
  83. package/src/app/create-edit-backup/create-edit-backup.component.ts +33 -0
  84. package/src/app/create-edit-backup/create-edit-backup.state.ts +582 -0
  85. package/src/app/create-edit-backup/destination/destination.component.html +367 -0
  86. package/src/app/create-edit-backup/destination/destination.component.scss +85 -0
  87. package/src/app/create-edit-backup/destination/destination.component.ts +249 -0
  88. package/src/app/create-edit-backup/destination/destination.config.ts +103 -0
  89. package/src/app/create-edit-backup/destination/destination.mapper.ts +177 -0
  90. package/src/app/create-edit-backup/general/general.component.html +108 -0
  91. package/src/app/create-edit-backup/general/general.component.scss +34 -0
  92. package/src/app/create-edit-backup/general/general.component.ts +136 -0
  93. package/src/app/create-edit-backup/options/options.component.html +95 -0
  94. package/src/app/create-edit-backup/options/options.component.scss +42 -0
  95. package/src/app/create-edit-backup/options/options.component.ts +113 -0
  96. package/src/app/create-edit-backup/schedule/schedule.component.html +102 -0
  97. package/src/app/create-edit-backup/schedule/schedule.component.scss +38 -0
  98. package/src/app/create-edit-backup/schedule/schedule.component.ts +137 -0
  99. package/src/app/create-edit-backup/source-data/source-data.component.html +93 -0
  100. package/src/app/create-edit-backup/source-data/source-data.component.scss +41 -0
  101. package/src/app/create-edit-backup/source-data/source-data.component.ts +114 -0
  102. package/src/app/home/backup.const.ts +167 -0
  103. package/src/app/home/home.component.html +98 -0
  104. package/src/app/home/home.component.scss +88 -0
  105. package/src/app/home/home.component.ts +54 -0
  106. package/src/app/layout/layout.component.html +64 -0
  107. package/src/app/layout/layout.component.scss +24 -0
  108. package/src/app/layout/layout.component.ts +51 -0
  109. package/src/app/layout/layout.state.ts +70 -0
  110. package/src/app/login/login.component.html +12 -0
  111. package/src/app/login/login.component.scss +25 -0
  112. package/src/app/login/login.component.ts +34 -0
  113. package/src/app/logout/logout.component.html +1 -0
  114. package/src/app/logout/logout.component.scss +3 -0
  115. package/src/app/logout/logout.component.ts +18 -0
  116. package/src/app/restore/restore.component.html +56 -0
  117. package/src/app/restore/restore.component.scss +37 -0
  118. package/src/app/restore/restore.component.ts +55 -0
  119. package/src/app/restore-flow/options/options.component.html +57 -0
  120. package/src/app/restore-flow/options/options.component.scss +16 -0
  121. package/src/app/restore-flow/options/options.component.ts +58 -0
  122. package/src/app/restore-flow/restore-flow.component.html +14 -0
  123. package/src/app/restore-flow/restore-flow.component.scss +15 -0
  124. package/src/app/restore-flow/restore-flow.component.ts +23 -0
  125. package/src/app/restore-flow/restore-flow.state.ts +120 -0
  126. package/src/app/restore-flow/select-files/select-files.component.html +42 -0
  127. package/src/app/restore-flow/select-files/select-files.component.scss +16 -0
  128. package/src/app/restore-flow/select-files/select-files.component.ts +129 -0
  129. package/src/app/settings/settings.component.html +256 -0
  130. package/src/app/settings/settings.component.scss +106 -0
  131. package/src/app/settings/settings.component.ts +475 -0
  132. package/src/assets/duplicati-logo.png +0 -0
  133. package/src/assets/duplicati-logo.svg +10 -0
  134. package/src/assets/favicon.ico +0 -0
  135. package/src/assets/images/backup.png +0 -0
  136. package/src/assets/images/dark-theme.png +0 -0
  137. package/src/assets/images/folder.png +0 -0
  138. package/src/assets/images/light-theme.png +0 -0
  139. package/src/assets/images/new-backup.png +0 -0
  140. package/src/assets/images/restore.png +0 -0
  141. package/src/assets/images/system-theme.png +0 -0
  142. package/src/assets/spk.css +33 -0
  143. package/src/assets/spk.woff2 +0 -0
  144. package/src/environments/environment-token.ts +4 -0
  145. package/src/environments/environment.prod.ts +6 -0
  146. package/src/environments/environment.ts +6 -0
  147. package/src/index.html +15 -0
  148. package/src/main.ts +6 -0
  149. package/src/proxy.conf.mjs +6 -0
  150. package/src/styles.scss +41 -0
  151. package/tsconfig.app.json +15 -0
  152. package/tsconfig.json +30 -0
@@ -0,0 +1,17 @@
1
+ import { JsonPipe } from '@angular/common';
2
+ import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
3
+ import { SysinfoState } from '../../core/states/sysinfo.state';
4
+
5
+ @Component({
6
+ selector: 'app-system-info',
7
+ standalone: true,
8
+ imports: [JsonPipe],
9
+ templateUrl: './system-info.component.html',
10
+ styleUrl: './system-info.component.scss',
11
+ changeDetection: ChangeDetectionStrategy.OnPush,
12
+ })
13
+ export default class SystemInfoComponent {
14
+ #sysInfo = inject(SysinfoState);
15
+
16
+ systemInfo = this.#sysInfo.systemInfo;
17
+ }
@@ -0,0 +1,29 @@
1
+ <app-status-bar />
2
+
3
+ <section>
4
+ <h2>Add a new backup</h2>
5
+
6
+ <div class="backup-types">
7
+ <spk-card class="type-a">
8
+ <img src="/assets/images/new-backup.png" />
9
+ <h3>New backup</h3>
10
+
11
+ <p>Configure a new backup. Choose your destination, source data and schedule.</p>
12
+
13
+ <button spk-button class="raised primary" [routerLink]="['/backup/new']">
14
+ Add a new backup
15
+ <spk-icon>plus</spk-icon>
16
+ </button>
17
+ </spk-card>
18
+
19
+ <!-- <spk-card class="type-a">
20
+ <img src="/assets/images/new-backup.png" />
21
+ <h3>Import from file</h3>
22
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod.</p>
23
+ <button spk-button class="raised primary">
24
+ Import from file
25
+ <spk-icon>upload-simple</spk-icon>
26
+ </button>
27
+ </spk-card> -->
28
+ </div>
29
+ </section>
@@ -0,0 +1,38 @@
1
+ @use '@sparkle-ui/core/styles/helpers' as *;
2
+
3
+ :host {
4
+ display: block;
5
+ }
6
+
7
+ section {
8
+ display: flex;
9
+ align-items: center;
10
+ flex-direction: column;
11
+ gap: p2r(32);
12
+ padding: p2r(32 0);
13
+ }
14
+
15
+ div.backup-types {
16
+ display: grid;
17
+ grid-template-columns: 1fr;
18
+ gap: p2r(16);
19
+ max-width: 700px;
20
+ }
21
+
22
+ spk-card {
23
+ display: flex;
24
+ flex-direction: column;
25
+ align-items: center;
26
+ gap: p2r(16);
27
+ padding-bottom: p2r(48);
28
+
29
+ img {
30
+ max-width: 300px;
31
+ }
32
+
33
+ p {
34
+ text-wrap: balance;
35
+ text-align: center;
36
+ width: 75%;
37
+ }
38
+ }
@@ -0,0 +1,14 @@
1
+ import { ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { RouterLink } from '@angular/router';
3
+ import { SparkleButtonComponent, SparkleCardComponent, SparkleIconComponent } from '@sparkle-ui/core';
4
+ import StatusBarComponent from '../core/components/status-bar/status-bar.component';
5
+
6
+ @Component({
7
+ selector: 'app-add-backup',
8
+ standalone: true,
9
+ imports: [StatusBarComponent, SparkleButtonComponent, SparkleCardComponent, SparkleIconComponent, RouterLink],
10
+ templateUrl: './add-backup.component.html',
11
+ styleUrl: './add-backup.component.scss',
12
+ changeDetection: ChangeDetectionStrategy.OnPush,
13
+ })
14
+ export default class AddBackupComponent {}
@@ -0,0 +1,35 @@
1
+ import { Component, inject } from '@angular/core';
2
+ import { ActivatedRoute, RouterOutlet } from '@angular/router';
3
+ import { Subscription } from 'rxjs';
4
+ import { LOCALSTORAGE } from './core/services/localstorage.token';
5
+ import { RelayconfigState } from './core/states/relayconfig.state';
6
+
7
+ @Component({
8
+ selector: 'app-root',
9
+ standalone: true,
10
+ imports: [RouterOutlet],
11
+ template: `
12
+ <router-outlet />
13
+ `,
14
+ styles: [],
15
+ })
16
+ export class AppComponent {
17
+ #ls = inject(LOCALSTORAGE);
18
+ #route = inject(ActivatedRoute);
19
+ #relayConfigState = inject(RelayconfigState);
20
+
21
+ sub: Subscription | null = null;
22
+
23
+ ngOnInit() {
24
+ this.sub = this.#route.queryParams.subscribe(({ accessToken, clientId }: { [key: string]: string }) => {
25
+ if (accessToken?.length && clientId?.length) {
26
+ this.#relayConfigState.setConfig({ accessToken, clientId });
27
+ }
28
+ });
29
+ this.#ls.clearAllNotCurrentVersion();
30
+ }
31
+
32
+ ngOnDestroy() {
33
+ this.sub?.unsubscribe();
34
+ }
35
+ }
@@ -0,0 +1,23 @@
1
+ import { ApplicationConfig, provideExperimentalZonelessChangeDetection } from '@angular/core';
2
+ import { provideRouter, withComponentInputBinding } from '@angular/router';
3
+
4
+ import { provideHttpClient, withFetch, withInterceptors } from '@angular/common/http';
5
+ import { environment } from '../environments/environment';
6
+ import { ENVIRONMENT_TOKEN } from '../environments/environment-token';
7
+ import { routes } from './app.routes';
8
+ import { httpInterceptor } from './core/interceptors/http.interceptor';
9
+ import { httpInterceptorWebsocketRelay } from './core/interceptors/websocket.interceptor';
10
+ import { DayJsProvider } from './core/providers/dayjs';
11
+ import { LOCALSTORAGE } from './core/services/localstorage.token';
12
+
13
+ export const appConfig: ApplicationConfig = {
14
+ providers: [
15
+ provideExperimentalZonelessChangeDetection(),
16
+ provideRouter(routes, withComponentInputBinding()),
17
+ provideHttpClient(withFetch(), withInterceptors([httpInterceptorWebsocketRelay, httpInterceptor])),
18
+ LOCALSTORAGE,
19
+
20
+ { provide: ENVIRONMENT_TOKEN, useValue: environment },
21
+ DayJsProvider,
22
+ ],
23
+ };
@@ -0,0 +1,121 @@
1
+ import { Routes } from '@angular/router';
2
+
3
+ export const routes: Routes = [
4
+ {
5
+ path: '',
6
+ // canActivate: [() => socketConnection],
7
+ children: [
8
+ {
9
+ path: 'login',
10
+ loadComponent: () => import('./login/login.component'),
11
+ },
12
+ {
13
+ path: 'logout',
14
+ loadComponent: () => import('./logout/logout.component'),
15
+ },
16
+ {
17
+ path: '',
18
+ loadComponent: () => import('./layout/layout.component'),
19
+ children: [
20
+ {
21
+ path: '',
22
+ loadComponent: () => import('./home/home.component'),
23
+ },
24
+ {
25
+ path: 'add-backup',
26
+ loadComponent: () => import('./add-backup/add-backup.component'),
27
+ },
28
+ {
29
+ path: 'backup/:id',
30
+ loadComponent: () => import('./create-edit-backup/create-edit-backup.component'),
31
+ children: [
32
+ {
33
+ path: '',
34
+ redirectTo: 'general',
35
+ pathMatch: 'full',
36
+ },
37
+ {
38
+ path: 'general',
39
+ loadComponent: () => import('./create-edit-backup/general/general.component'),
40
+ },
41
+ {
42
+ path: 'destination',
43
+ loadComponent: () => import('./create-edit-backup/destination/destination.component'),
44
+ },
45
+ {
46
+ path: 'source-data',
47
+ loadComponent: () => import('./create-edit-backup/source-data/source-data.component'),
48
+ },
49
+ {
50
+ path: 'schedule',
51
+ loadComponent: () => import('./create-edit-backup/schedule/schedule.component'),
52
+ },
53
+ {
54
+ path: 'options',
55
+ loadComponent: () => import('./create-edit-backup/options/options.component'),
56
+ },
57
+ ],
58
+ },
59
+ {
60
+ path: 'restore',
61
+ loadComponent: () => import('./restore/restore.component'),
62
+ },
63
+ {
64
+ path: 'restore-flow/:id',
65
+ loadComponent: () => import('./restore-flow/restore-flow.component'),
66
+ children: [
67
+ {
68
+ path: '',
69
+ redirectTo: 'select-files',
70
+ pathMatch: 'full',
71
+ },
72
+ {
73
+ path: 'select-files',
74
+ loadComponent: () => import('./restore-flow/select-files/select-files.component'),
75
+ },
76
+ {
77
+ path: 'options',
78
+ loadComponent: () => import('./restore-flow/options/options.component'),
79
+ },
80
+ ],
81
+ },
82
+ {
83
+ path: 'settings',
84
+ loadComponent: () => import('./settings/settings.component'),
85
+ },
86
+ {
87
+ path: 'about',
88
+ loadComponent: () => import('./about/about.component'),
89
+ children: [
90
+ {
91
+ path: '',
92
+ redirectTo: 'general',
93
+ pathMatch: 'full',
94
+ },
95
+ {
96
+ path: 'general',
97
+ loadComponent: () => import('./about/general/general.component'),
98
+ },
99
+ {
100
+ path: 'changelog',
101
+ loadComponent: () => import('./about/changelog/changelog.component'),
102
+ },
103
+ {
104
+ path: 'libraries',
105
+ loadComponent: () => import('./about/libraries/libraries.component'),
106
+ },
107
+ {
108
+ path: 'system-info',
109
+ loadComponent: () => import('./about/system-info/system-info.component'),
110
+ },
111
+ {
112
+ path: 'logs',
113
+ loadComponent: () => import('./about/logs/logs.component'),
114
+ },
115
+ ],
116
+ },
117
+ ],
118
+ },
119
+ ],
120
+ },
121
+ ];
@@ -0,0 +1,87 @@
1
+ @if (!multiSelect()) {
2
+ <spk-button-group>
3
+ <button
4
+ type="button"
5
+ [class.active]="pathDiscoveryMethod() === 'browse'"
6
+ (click)="pathDiscoveryMethod.set('browse')">
7
+ Browser path
8
+ </button>
9
+
10
+ <button type="button" [class.active]="pathDiscoveryMethod() === 'path'" (click)="pathDiscoveryMethod.set('path')">
11
+ Manually type path
12
+ </button>
13
+ </spk-button-group>
14
+ }
15
+
16
+ <!-- <spk-form-field>
17
+ <label for="search">Search</label>
18
+ <input type="text" id="search" [(ngModel)]="treeSearchQuery" />
19
+ </spk-form-field> -->
20
+
21
+ <div class="section" [class.hidden]="pathDiscoveryMethod() !== 'browse'">
22
+ <ng-content select="label" ngProjectAs="label"></ng-content>
23
+
24
+ <div class="browse-files" #treeContainer>
25
+ <ng-template #recursiveTree let-data>
26
+ <spk-list [style.padding-left.rem]="data.level * 0.5">
27
+ @for (node of data.children; track node.id) {
28
+ @if ((node.hidden && showHiddenFiles()) || !node.hidden) {
29
+ <div
30
+ spk-action-item
31
+ #treeNode
32
+ [class.active]="node.isSelected"
33
+ [class.open]="node.children.length"
34
+ [class.usually-hidden]="node.hidden"
35
+ (click)="node.id !== '/' && toggleNode($event, node.id, node)">
36
+ <div class="icon">
37
+ @if (node.id !== '/') {
38
+ @if (node.children.length) {
39
+ <spk-icon class="spk-primary">folder-open</spk-icon>
40
+ } @else if (node.cls === 'file') {
41
+ <spk-icon>file</spk-icon>
42
+ } @else {
43
+ <spk-icon class="spk-primary">folder</spk-icon>
44
+ }
45
+ } @else {
46
+ <spk-icon class="spk-primary">desktop-tower</spk-icon>
47
+ }
48
+ </div>
49
+
50
+ <div class="text" (click)="node.id !== '/' && toggleSelectedNode($event, node)">
51
+ {{ node.text }}
52
+ </div>
53
+ </div>
54
+
55
+ @if (node.children.length > 0) {
56
+ <ng-container
57
+ *ngTemplateOutlet="
58
+ recursiveTree;
59
+ context: { $implicit: { children: node.children, level: data.level + 1 } }
60
+ "></ng-container>
61
+ }
62
+ }
63
+ }
64
+ </spk-list>
65
+ </ng-template>
66
+
67
+ <ng-container
68
+ *ngTemplateOutlet="recursiveTree; context: { $implicit: { children: treeStructure(), level: 0 } }"></ng-container>
69
+ </div>
70
+
71
+ <spk-toggle
72
+ [class.active]="showHiddenFiles()"
73
+ class="primary raised browse-files-toggle"
74
+ (click)="showHiddenFiles.set(!showHiddenFiles())">
75
+ Show hidden {{ showFiles() ? 'files' : 'folders' }}
76
+ </spk-toggle>
77
+ </div>
78
+
79
+ <div #formRef>
80
+ <spk-form-field [class.hidden]="pathDiscoveryMethod() !== 'path'">
81
+ <ng-content select="label" ngProjectAs="label"></ng-content>
82
+ <ng-content select="input" ngProjectAs="input"></ng-content>
83
+ </spk-form-field>
84
+
85
+ <!-- <pre>{{ selectedPaths() | json }}</pre> -->
86
+ <!-- <pre>{{ currentPath() }}</pre> -->
87
+ </div>
@@ -0,0 +1,80 @@
1
+ @use '@sparkle-ui/core/styles/helpers' as *;
2
+
3
+ :host {
4
+ display: flex;
5
+ flex-direction: column;
6
+ gap: p2r(16);
7
+
8
+ &.disabled {
9
+ opacity: 0.5;
10
+ user-select: none;
11
+ pointer-events: none;
12
+ position: relative;
13
+
14
+ &:before {
15
+ content: '';
16
+ position: absolute;
17
+ inset: 0;
18
+ background: transparent;
19
+ }
20
+ }
21
+ }
22
+
23
+ .section {
24
+ display: flex;
25
+ flex-direction: column;
26
+ gap: p2r(8);
27
+ }
28
+
29
+ .browse-files {
30
+ display: flex;
31
+ gap: p2r(8);
32
+ padding: p2r(8 16);
33
+ height: p2r(200);
34
+ border: 1px solid var(--base-level-40);
35
+ border-radius: var(--shape-3);
36
+ overflow: auto;
37
+ resize: vertical;
38
+
39
+ spk-list {
40
+ --list-active-bg: var(--base-level-30);
41
+ gap: 0;
42
+ padding: 0;
43
+ height: min-content;
44
+ min-width: min-content;
45
+
46
+ [spk-action-item] {
47
+ padding: 0;
48
+ gap: p2r(4);
49
+
50
+ &.usually-hidden {
51
+ opacity: 0.6;
52
+ }
53
+
54
+ .text {
55
+ flex: 1 0;
56
+ height: 100%;
57
+ width: max-content;
58
+ display: flex;
59
+ align-items: center;
60
+ }
61
+
62
+ .icon {
63
+ width: p2r(24);
64
+ height: p2r(24);
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: center;
68
+ cursor: pointer;
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ .browse-files-toggle {
75
+ color: var(--base-level-60R);
76
+ }
77
+
78
+ .hidden {
79
+ display: none;
80
+ }