@gradio/imageeditor 0.12.14 → 0.13.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.
Files changed (130) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/Example.svelte +1 -1
  3. package/IMAGE_EDITOR_OVERVIEW.md +224 -0
  4. package/ImageEditor.stories.svelte +4 -4
  5. package/Index.svelte +35 -46
  6. package/{shared/InteractiveImageEditor.svelte → InteractiveImageEditor.svelte} +56 -103
  7. package/dist/Example.svelte.d.ts +1 -1
  8. package/dist/Index.svelte +29 -33
  9. package/dist/Index.svelte.d.ts +17 -16
  10. package/dist/{shared/InteractiveImageEditor.svelte → InteractiveImageEditor.svelte} +47 -88
  11. package/dist/{shared/InteractiveImageEditor.svelte.d.ts → InteractiveImageEditor.svelte.d.ts} +13 -15
  12. package/dist/shared/Anchor.svelte +311 -0
  13. package/dist/shared/Anchor.svelte.d.ts +18 -0
  14. package/dist/shared/Controls.svelte +162 -23
  15. package/dist/shared/Controls.svelte.d.ts +7 -2
  16. package/dist/shared/{tools/IconButton.svelte → IconButton.svelte} +19 -3
  17. package/dist/shared/{tools/IconButton.svelte.d.ts → IconButton.svelte.d.ts} +4 -1
  18. package/dist/shared/ImageEditor.svelte +546 -289
  19. package/dist/shared/ImageEditor.svelte.d.ts +51 -56
  20. package/dist/shared/Layers.svelte +233 -0
  21. package/dist/shared/Layers.svelte.d.ts +35 -0
  22. package/dist/shared/Resize.svelte +218 -0
  23. package/dist/shared/Resize.svelte.d.ts +29 -0
  24. package/dist/shared/SecondaryToolbar.svelte +54 -0
  25. package/dist/shared/SecondaryToolbar.svelte.d.ts +35 -0
  26. package/dist/shared/Toolbar.svelte +337 -0
  27. package/dist/shared/Toolbar.svelte.d.ts +42 -0
  28. package/dist/shared/{tools → brush}/BrushOptions.svelte +68 -64
  29. package/dist/shared/{tools → brush}/BrushOptions.svelte.d.ts +9 -9
  30. package/dist/shared/{tools → brush}/BrushSize.svelte +2 -27
  31. package/dist/shared/{tools → brush}/ColorField.svelte +2 -1
  32. package/dist/shared/{tools → brush}/ColorField.svelte.d.ts +1 -0
  33. package/dist/shared/{tools → brush}/ColorPicker.svelte +81 -9
  34. package/dist/shared/{tools → brush}/ColorPicker.svelte.d.ts +1 -0
  35. package/dist/shared/{tools → brush}/ColorSwatch.svelte +78 -38
  36. package/dist/shared/{tools → brush}/ColorSwatch.svelte.d.ts +6 -2
  37. package/dist/shared/brush/brush-cursor.d.ts +101 -0
  38. package/dist/shared/brush/brush-cursor.js +327 -0
  39. package/dist/shared/brush/brush-textures.d.ts +71 -0
  40. package/dist/shared/brush/brush-textures.js +404 -0
  41. package/dist/shared/brush/brush-utils.d.ts +32 -0
  42. package/dist/shared/brush/brush-utils.js +59 -0
  43. package/dist/shared/brush/brush.d.ts +152 -0
  44. package/dist/shared/brush/brush.js +396 -0
  45. package/dist/shared/brush/types.d.ts +37 -0
  46. package/dist/shared/brush/types.js +1 -0
  47. package/dist/shared/core/editor.d.ts +252 -0
  48. package/dist/shared/core/editor.js +1221 -0
  49. package/dist/shared/crop/crop.d.ts +201 -0
  50. package/dist/shared/crop/crop.js +727 -0
  51. package/dist/shared/image/image.d.ts +89 -0
  52. package/dist/shared/image/image.js +185 -0
  53. package/dist/shared/resize/resize.d.ts +270 -0
  54. package/dist/shared/resize/resize.js +1413 -0
  55. package/dist/shared/types.d.ts +12 -0
  56. package/dist/shared/utils/pixi.d.ts +16 -57
  57. package/dist/shared/utils/pixi.js +15 -113
  58. package/dist/shared/zoom/zoom.d.ts +136 -0
  59. package/dist/shared/zoom/zoom.js +548 -0
  60. package/package.json +10 -9
  61. package/shared/Anchor.svelte +384 -0
  62. package/shared/Controls.svelte +194 -27
  63. package/shared/{tools/IconButton.svelte → IconButton.svelte} +21 -4
  64. package/shared/ImageEditor.svelte +682 -349
  65. package/shared/Layers.svelte +249 -0
  66. package/shared/Resize.svelte +239 -0
  67. package/shared/SecondaryToolbar.svelte +61 -0
  68. package/shared/Toolbar.svelte +386 -0
  69. package/shared/brush/BRUSH_TOOL.md +134 -0
  70. package/shared/brush/BrushOptions.svelte +200 -0
  71. package/shared/{tools → brush}/BrushSize.svelte +2 -30
  72. package/shared/{tools → brush}/ColorField.svelte +3 -1
  73. package/shared/{tools → brush}/ColorPicker.svelte +86 -9
  74. package/shared/{tools → brush}/ColorSwatch.svelte +95 -42
  75. package/shared/brush/brush-cursor.ts +408 -0
  76. package/shared/brush/brush-textures.ts +508 -0
  77. package/shared/brush/brush-utils.ts +76 -0
  78. package/shared/brush/brush.ts +506 -0
  79. package/shared/brush/types.ts +41 -0
  80. package/shared/core/EDITOR.md +182 -0
  81. package/shared/core/editor.ts +1730 -0
  82. package/shared/crop/CROP.md +139 -0
  83. package/shared/crop/crop.ts +1027 -0
  84. package/shared/image/IMAGE.md +135 -0
  85. package/shared/image/image.ts +300 -0
  86. package/shared/resize/resize.ts +1894 -0
  87. package/shared/types.ts +14 -0
  88. package/shared/utils/pixi.ts +19 -246
  89. package/shared/zoom/zoom.ts +729 -0
  90. package/dist/shared/layers/Layers.svelte +0 -231
  91. package/dist/shared/layers/Layers.svelte.d.ts +0 -18
  92. package/dist/shared/layers/utils.d.ts +0 -73
  93. package/dist/shared/layers/utils.js +0 -156
  94. package/dist/shared/tools/Brush.svelte +0 -215
  95. package/dist/shared/tools/Brush.svelte.d.ts +0 -29
  96. package/dist/shared/tools/Crop.svelte +0 -155
  97. package/dist/shared/tools/Crop.svelte.d.ts +0 -16
  98. package/dist/shared/tools/Cropper.svelte +0 -271
  99. package/dist/shared/tools/Cropper.svelte.d.ts +0 -41
  100. package/dist/shared/tools/Handle.svelte +0 -260
  101. package/dist/shared/tools/Handle.svelte.d.ts +0 -29
  102. package/dist/shared/tools/Sources.svelte +0 -257
  103. package/dist/shared/tools/Sources.svelte.d.ts +0 -34
  104. package/dist/shared/tools/Tools.svelte +0 -102
  105. package/dist/shared/tools/Tools.svelte.d.ts +0 -48
  106. package/dist/shared/tools/brush.d.ts +0 -62
  107. package/dist/shared/tools/brush.js +0 -133
  108. package/dist/shared/tools/crop.d.ts +0 -15
  109. package/dist/shared/tools/crop.js +0 -154
  110. package/dist/shared/tools/index.d.ts +0 -5
  111. package/dist/shared/tools/index.js +0 -5
  112. package/dist/shared/tools/sources.d.ts +0 -46
  113. package/dist/shared/tools/sources.js +0 -121
  114. package/dist/shared/tools/types.d.ts +0 -1
  115. package/shared/layers/Layers.svelte +0 -250
  116. package/shared/layers/utils.ts +0 -294
  117. package/shared/tools/Brush.svelte +0 -280
  118. package/shared/tools/BrushOptions.svelte +0 -180
  119. package/shared/tools/Crop.svelte +0 -189
  120. package/shared/tools/Cropper.svelte +0 -346
  121. package/shared/tools/Handle.svelte +0 -289
  122. package/shared/tools/Sources.svelte +0 -283
  123. package/shared/tools/Tools.svelte +0 -162
  124. package/shared/tools/brush.ts +0 -247
  125. package/shared/tools/crop.ts +0 -213
  126. package/shared/tools/index.ts +0 -5
  127. package/shared/tools/sources.ts +0 -195
  128. package/shared/tools/types.ts +0 -1
  129. /package/dist/shared/{tools → brush}/BrushSize.svelte.d.ts +0 -0
  130. /package/dist/shared/{tools/types.js → types.js} +0 -0
@@ -0,0 +1,249 @@
1
+ <script lang="ts">
2
+ import { click_outside } from "./utils/events";
3
+ import { Layers, Clear, ArrowUp, ArrowDown, Plus } from "@gradio/icons";
4
+ import { IconButton } from "@gradio/atoms";
5
+ import { createEventDispatcher } from "svelte";
6
+ import type { Writable } from "svelte/store";
7
+
8
+ const dispatch = createEventDispatcher<{
9
+ new_layer: void;
10
+ change_layer: string;
11
+ move_layer: { id: string; direction: "up" | "down" };
12
+ delete_layer: string;
13
+ }>();
14
+
15
+ export let layers: Writable<{
16
+ active_layer: string;
17
+ layers: { name: string; id: string; user_created: boolean }[];
18
+ }>;
19
+ export let enable_additional_layers = true;
20
+ export let enable_layers = true;
21
+ export let show_layers = false;
22
+
23
+ function new_layer(): void {
24
+ dispatch("new_layer");
25
+ }
26
+
27
+ function change_layer(id: string): void {
28
+ dispatch("change_layer", id);
29
+ show_layers = false;
30
+ }
31
+
32
+ function move_layer(id: string, direction: "up" | "down"): void {
33
+ dispatch("move_layer", { id, direction });
34
+ }
35
+
36
+ function delete_layer(id: string): void {
37
+ dispatch("delete_layer", id);
38
+ }
39
+ </script>
40
+
41
+ {#if enable_layers}
42
+ <div
43
+ class="layer-wrap"
44
+ class:closed={!show_layers}
45
+ use:click_outside={() => (show_layers = false)}
46
+ >
47
+ <button
48
+ class="layer-title-button"
49
+ aria-label="Show Layers"
50
+ on:click|stopPropagation={() => (show_layers = !show_layers)}
51
+ >
52
+ {show_layers
53
+ ? "Layers"
54
+ : $layers.layers.find((l) => l.id === $layers.active_layer)?.name}
55
+ <span class="icon"><Layers /></span>
56
+ </button>
57
+ {#if show_layers}
58
+ <ul>
59
+ {#each $layers.layers as { id, name, user_created }, i (i)}
60
+ <li>
61
+ <button
62
+ class:selected_layer={$layers.active_layer === id}
63
+ aria-label={`layer-${i + 1}`}
64
+ on:click|stopPropagation={() => change_layer(id)}>{name}</button
65
+ >
66
+ {#if $layers.layers.length > 1}
67
+ <div>
68
+ {#if i > 0}
69
+ <IconButton
70
+ on:click={(e) => {
71
+ e.stopPropagation();
72
+ move_layer(id, "up");
73
+ }}
74
+ Icon={ArrowUp}
75
+ size="x-small"
76
+ />
77
+ {/if}
78
+ {#if i < $layers.layers.length - 1}
79
+ <IconButton
80
+ on:click={(e) => {
81
+ e.stopPropagation();
82
+ move_layer(id, "down");
83
+ }}
84
+ Icon={ArrowDown}
85
+ size="x-small"
86
+ />
87
+ {/if}
88
+ {#if $layers.layers.length > 1 && user_created}
89
+ <IconButton
90
+ on:click={(e) => {
91
+ e.stopPropagation();
92
+ delete_layer(id);
93
+ }}
94
+ Icon={Clear}
95
+ size="x-small"
96
+ />
97
+ {/if}
98
+ </div>
99
+ {/if}
100
+ </li>
101
+ {/each}
102
+ {#if enable_additional_layers}
103
+ <li class="add-layer">
104
+ <IconButton
105
+ Icon={Plus}
106
+ label="Add Layer"
107
+ on:click={(e) => {
108
+ e.stopPropagation();
109
+ new_layer();
110
+ }}
111
+ size="x-small"
112
+ />
113
+ </li>
114
+ {/if}
115
+ </ul>
116
+ {/if}
117
+ </div>
118
+ {/if}
119
+
120
+ <style>
121
+ .add-layer {
122
+ display: flex;
123
+ justify-content: center;
124
+ align-items: center;
125
+ margin: var(--spacing-sm) 0 0 0;
126
+ }
127
+
128
+ .add-layer :global(button) {
129
+ width: 100%;
130
+ }
131
+ .icon {
132
+ width: 14px;
133
+ color: var(--body-text-color);
134
+ transition: color 0.15s ease;
135
+ }
136
+
137
+ .layer-wrap {
138
+ /* position: absolute; */
139
+ display: flex;
140
+ justify-content: center;
141
+ align-items: center;
142
+ /* border: 1px solid var(--border-color-primary); */
143
+ /* z-index: var(--layer-1); */
144
+ /* border-radius: var(--radius-sm); */
145
+ /* background-color: var(--block-background-fill); */
146
+ width: 100%;
147
+ flex-direction: column;
148
+ /* bottom: 5px; */
149
+ /* right: 5px; */
150
+ /* border-bottom: 0;
151
+ border-right: 0; */
152
+ /* box-shadow: var(--shadow-drop); */
153
+ }
154
+
155
+ .layer-wrap button {
156
+ justify-content: space-between;
157
+ align-items: center;
158
+ width: 100%;
159
+ display: flex;
160
+ font-size: var(--text-sm);
161
+ line-height: var(--line-sm);
162
+ transition: all 0.15s ease;
163
+ padding: var(--spacing-md) var(--spacing-lg);
164
+ /* padding-right: var(--spacing-lg); */
165
+ border-radius: var(--radius-sm);
166
+ /* padding-left: 30px; */
167
+ }
168
+
169
+ button.layer-title-button {
170
+ width: 100%;
171
+ /* padding-left: 30px; */
172
+ }
173
+
174
+ .layer-wrap button:hover .icon {
175
+ color: var(--color-accent);
176
+ }
177
+
178
+ .selected_layer {
179
+ color: var(--color-accent);
180
+ font-weight: var(--weight-semibold);
181
+ }
182
+
183
+ ul {
184
+ /* position: absolute; */
185
+ bottom: 0;
186
+ right: 0;
187
+ /* background: var(--block-background-fill); */
188
+ width: 100%;
189
+ /* min-width: 100%; */
190
+ list-style: none;
191
+ z-index: var(--layer-top);
192
+ /* border: 1px solid var(--border-color-primary); */
193
+ /* border-radius: var(--radius-sm); */
194
+ /* box-shadow: var(--shadow-drop-lg); */
195
+ padding: var(--spacing-sm);
196
+ /* transform: translate(-1px, 1px); */
197
+ border-top: 1px solid var(--border-color-primary);
198
+ }
199
+
200
+ /* .sep {
201
+ height: 12px;
202
+ background-color: var(--block-border-color);
203
+ width: 1px;
204
+ display: block;
205
+ margin-left: var(--spacing-xl);
206
+ } */
207
+
208
+ li {
209
+ display: flex;
210
+ justify-content: space-between;
211
+ align-items: center;
212
+ /* border-radius: var(--radius-sm); */
213
+ transition: background-color 0.15s ease;
214
+ border-bottom: 1px solid var(--border-color-primary);
215
+ }
216
+
217
+ .layer-wrap ul > li > button {
218
+ padding-left: calc(var(--spacing-md));
219
+ }
220
+
221
+ li:hover {
222
+ background-color: var(--background-fill-secondary);
223
+ }
224
+
225
+ li:last-child {
226
+ border-bottom: none;
227
+ }
228
+ li:last-child:hover {
229
+ background-color: unset;
230
+ }
231
+
232
+ li div {
233
+ display: flex;
234
+ gap: var(--spacing-sm);
235
+ padding: var(--spacing-sm);
236
+ }
237
+ li > button {
238
+ padding: var(--spacing-sm) var(--spacing-md);
239
+ }
240
+
241
+ /* li > div > button {
242
+ opacity: 0.7;
243
+ transition: opacity 0.15s ease;
244
+ }
245
+
246
+ li > div > button:hover {
247
+ opacity: 1;
248
+ } */
249
+ </style>
@@ -0,0 +1,239 @@
1
+ <script lang="ts" context="module">
2
+ export type Position =
3
+ | "top-left"
4
+ | "top"
5
+ | "top-right"
6
+ | "left"
7
+ | "center"
8
+ | "right"
9
+ | "bottom-left"
10
+ | "bottom"
11
+ | "bottom-right";
12
+ </script>
13
+
14
+ <script lang="ts">
15
+ import { createEventDispatcher } from "svelte";
16
+ import type { Spring } from "svelte/motion";
17
+ import Anchor from "./Anchor.svelte";
18
+
19
+ export let dimensions: Spring<{ width: number; height: number }>;
20
+
21
+ const dispatch = createEventDispatcher<{
22
+ change: { anchor: Position; scale: boolean; width: number; height: number };
23
+ }>();
24
+
25
+ let selected_anchor: Position = "center";
26
+ let scale = false;
27
+
28
+ let new_width = $dimensions?.width;
29
+ let new_height = $dimensions?.height;
30
+
31
+ function handle_click(): void {
32
+ dispatch("change", {
33
+ anchor: selected_anchor,
34
+ scale,
35
+ width: new_width,
36
+ height: new_height
37
+ });
38
+ }
39
+
40
+ function set_anchor(position: Position): void {
41
+ selected_anchor = position;
42
+ }
43
+ </script>
44
+
45
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
46
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
47
+ <div class="wrap" on:click|stopPropagation>
48
+ <div class="size-wrap">
49
+ <div class="size-input">
50
+ <label for="width">Width</label><input
51
+ type="number"
52
+ id="width"
53
+ bind:value={new_width}
54
+ />
55
+ </div>
56
+ <div class="size-input">
57
+ <label for="height">Height </label><input
58
+ type="number"
59
+ id="height"
60
+ bind:value={new_height}
61
+ />
62
+ </div>
63
+ </div>
64
+
65
+ <div class="scale-wrap">
66
+ <h2 class="image-will-label">Image will:</h2>
67
+ <div class="toggle-container">
68
+ <label class="radio-label">
69
+ <input
70
+ type="radio"
71
+ name="resize_mode"
72
+ value={true}
73
+ bind:group={scale}
74
+ />
75
+ <span class="radio-button">rescale</span>
76
+ </label>
77
+ <label class="radio-label">
78
+ <input
79
+ type="radio"
80
+ name="resize_mode"
81
+ value={false}
82
+ bind:group={scale}
83
+ />
84
+ <span class="radio-button">anchor</span>
85
+ </label>
86
+ </div>
87
+ </div>
88
+ <div class="anchor-wrap">
89
+ <Anchor on:position={(e) => set_anchor(e.detail)} />
90
+ </div>
91
+ <button class="apply-button" on:click={() => handle_click()}
92
+ >Resize Canvas</button
93
+ >
94
+ </div>
95
+
96
+ <!-- </div> -->
97
+
98
+ <style>
99
+ .wrap {
100
+ padding: var(--spacing-xl) var(--spacing-lg);
101
+ color: var(--block-label-text-color);
102
+ }
103
+
104
+ .size-wrap {
105
+ display: flex;
106
+ flex-direction: row;
107
+ gap: 10px;
108
+ }
109
+
110
+ .size-input {
111
+ display: flex;
112
+ flex-direction: column;
113
+ gap: var(--spacing-xxs);
114
+ }
115
+
116
+ label,
117
+ h2 {
118
+ display: flex;
119
+ align-items: center;
120
+ gap: 15px;
121
+
122
+ cursor: pointer;
123
+ color: var(--checkbox-label-text-color);
124
+ font-weight: var(--checkbox-label-text-weight);
125
+ font-size: var(--text-sm);
126
+ line-height: var(--line-md);
127
+ }
128
+
129
+ .scale-wrap {
130
+ display: flex;
131
+ flex-direction: column;
132
+ gap: var(--spacing-sm);
133
+ margin-top: var(--spacing-md);
134
+ }
135
+
136
+ input[type="number"] {
137
+ border: 1px solid var(--border-color-primary);
138
+ width: 60px;
139
+ border-radius: var(--radius-sm);
140
+ background-color: var(--checkbox-background-color-focus);
141
+ color: var(--body-text-color);
142
+ font-size: var(--text-sm);
143
+ transition: border-color 0.15s ease;
144
+ padding: var(--spacing-xs);
145
+ line-height: 1rem;
146
+ }
147
+
148
+ input[type="number"]:hover {
149
+ border-color: var(--color-accent-soft);
150
+ }
151
+
152
+ input[type="number"]:focus {
153
+ border-color: var(--color-accent);
154
+ outline: none;
155
+ box-shadow: 0 0 0 1px var(--color-accent-soft);
156
+ }
157
+
158
+ .image-will-label {
159
+ grid-column: 1;
160
+ }
161
+
162
+ .toggle-container {
163
+ display: flex;
164
+ grid-column: 2;
165
+ border-radius: var(--radius-sm);
166
+ border: 1px solid var(--border-color-primary);
167
+ overflow: hidden;
168
+ }
169
+
170
+ .toggle-container {
171
+ display: flex;
172
+ grid-column: 2;
173
+ border-radius: var(--radius-sm);
174
+ border: 1px solid var(--border-color-primary);
175
+ overflow: hidden;
176
+ }
177
+
178
+ .radio-label {
179
+ flex: 1;
180
+ margin: 0;
181
+ padding: 0;
182
+ position: relative;
183
+ cursor: pointer;
184
+ }
185
+
186
+ .radio-button {
187
+ display: flex;
188
+ justify-content: center;
189
+ align-items: center;
190
+ padding: var(--spacing-sm);
191
+ background: var(--checkbox-background-color);
192
+ color: var(--body-text-color);
193
+ font-size: var(--text-sm);
194
+ transition: background-color 0.15s ease;
195
+ width: 100%;
196
+ height: 100%;
197
+ }
198
+
199
+ input[type="radio"] {
200
+ position: absolute;
201
+ opacity: 0;
202
+ width: 0;
203
+ height: 0;
204
+ }
205
+
206
+ input[type="radio"]:not(:checked) + .radio-button:hover {
207
+ background: var(--checkbox-background-color-hover);
208
+ }
209
+
210
+ input[type="radio"]:checked + .radio-button {
211
+ background: var(--color-accent);
212
+ color: white;
213
+ }
214
+
215
+ .apply-button {
216
+ width: 100%;
217
+ margin-top: var(--spacing-md);
218
+ padding: var(--spacing-sm) var(--spacing-md);
219
+ background: var(--color-accent);
220
+ color: white;
221
+ border: none;
222
+ border-radius: var(--radius-sm);
223
+ font-size: var(--text-sm);
224
+ font-weight: var(--weight-semibold);
225
+ transition: all 0.15s ease;
226
+ }
227
+
228
+ .apply-button:hover {
229
+ background: var(--button-primary-background-fill-hover);
230
+ }
231
+
232
+ .anchor-wrap {
233
+ display: flex;
234
+ justify-content: center;
235
+ align-items: center;
236
+ flex-direction: column;
237
+ gap: 10px;
238
+ }
239
+ </style>
@@ -0,0 +1,61 @@
1
+ <script lang="ts">
2
+ import Layers from "./Layers.svelte";
3
+ import type { Writable } from "svelte/store";
4
+
5
+ export let layers: Writable<{
6
+ active_layer: string;
7
+ layers: { name: string; id: string; user_created: boolean }[];
8
+ }>;
9
+
10
+ export let enable_additional_layers = true;
11
+ export let enable_layers = true;
12
+ export let show_layers = false;
13
+ </script>
14
+
15
+ <div class="toolbar-wrap-wrap">
16
+ <div class="toolbar-wrap">
17
+ {#if enable_layers}
18
+ <Layers
19
+ {layers}
20
+ {enable_additional_layers}
21
+ {enable_layers}
22
+ {show_layers}
23
+ on:new_layer
24
+ on:change_layer
25
+ on:move_layer
26
+ on:delete_layer
27
+ />
28
+ {/if}
29
+ </div>
30
+ </div>
31
+
32
+ <style>
33
+ .toolbar-wrap-wrap {
34
+ position: absolute;
35
+ right: 0;
36
+ bottom: 0;
37
+ width: fit-content;
38
+ max-height: 100%;
39
+ overflow-y: auto;
40
+ display: flex;
41
+ flex-direction: column-reverse;
42
+ }
43
+
44
+ .toolbar-wrap {
45
+ min-width: 110px;
46
+ display: flex;
47
+ flex-direction: column;
48
+ justify-content: center;
49
+ align-items: center;
50
+ position: relative;
51
+ right: 0;
52
+ bottom: 0;
53
+ border: 1px solid var(--block-border-color);
54
+ border-radius: 0;
55
+ border-top-left-radius: var(--radius-md);
56
+ border-right: none;
57
+ border-bottom: none;
58
+ z-index: 1000;
59
+ background-color: var(--block-background-fill);
60
+ }
61
+ </style>