sveltekit-ui 1.1.17 → 1.1.18
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/dist/Components/Alert/index.svelte +88 -0
- package/dist/Components/Alert/index.svelte.js +101 -0
- package/dist/Components/ArrowToggle/index.svelte +62 -0
- package/dist/Components/Attachment/index.svelte +77 -0
- package/dist/Components/Attachment/index.svelte.js +119 -0
- package/dist/Components/Audio/index.svelte +193 -0
- package/dist/Components/Audio/index.svelte.js +463 -0
- package/dist/Components/AudioEditor/index.svelte +252 -0
- package/dist/Components/AudioEditor/index.svelte.js +977 -0
- package/dist/Components/AudioEditor/samples/alloy-voice-sample.mp3 +0 -0
- package/dist/Components/AudioEditor/samples/echo-voice-sample.mp3 +0 -0
- package/dist/Components/AudioEditor/samples/fable-voice-sample.mp3 +0 -0
- package/dist/Components/AudioEditor/samples/nova-voice-sample.mp3 +0 -0
- package/dist/Components/AudioEditor/samples/onyx-voice-sample.mp3 +0 -0
- package/dist/Components/AudioEditor/samples/shimmer-voice-sample.mp3 +0 -0
- package/dist/Components/AuthCodeInput/index.svelte +85 -0
- package/dist/Components/AuthCodeInput/index.svelte.js +95 -0
- package/dist/Components/Breadcrumbs/index.svelte +27 -0
- package/dist/Components/Breadcrumbs/index.svelte.js +88 -0
- package/dist/Components/Button/index.svelte +721 -0
- package/dist/Components/Button/index.svelte.js +375 -0
- package/dist/Components/Chart/Klines/index.svelte +87 -0
- package/dist/Components/Chart/index.svelte +226 -0
- package/dist/Components/Chart/index.svelte.js +1090 -0
- package/dist/Components/ChartInput/DisplayNav/Klines/index.svelte +150 -0
- package/dist/Components/ChartInput/DisplayNav/Lines/index.svelte +45 -0
- package/dist/Components/ChartInput/DisplayNav/index.svelte +297 -0
- package/dist/Components/ChartInput/EditPanel/index.svelte +155 -0
- package/dist/Components/ChartInput/index.svelte +21 -0
- package/dist/Components/ChartInput/index.svelte.js +671 -0
- package/dist/Components/Checkbox/index.svelte +411 -0
- package/dist/Components/Checkbox/index.svelte.js +178 -0
- package/dist/Components/Code/index.svelte +23 -0
- package/dist/Components/Code/index.svelte.js +33 -0
- package/dist/Components/Color/index.svelte +51 -0
- package/dist/Components/Color/index.svelte.js +31 -0
- package/dist/Components/ColorInput/ChromaPicker/index.svelte +50 -0
- package/dist/Components/ColorInput/ColorPalette/index.svelte +62 -0
- package/dist/Components/ColorInput/OpacityPicker/index.svelte +68 -0
- package/dist/Components/ColorInput/ShowcasePicker/index.svelte +136 -0
- package/dist/Components/ColorInput/index.svelte +70 -0
- package/dist/Components/ColorInput/index.svelte.js +386 -0
- package/dist/Components/ConditionsInput/index.svelte +46 -0
- package/dist/Components/ConditionsInput/index.svelte.js +201 -0
- package/dist/Components/Confetti/index.svelte +98 -0
- package/dist/Components/Confetti/index.svelte.js +94 -0
- package/dist/Components/Content/index.svelte +500 -0
- package/dist/Components/Content/index.svelte.js +910 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Audio/index.svelte +31 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Audio/index.svelte.js +258 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/AudioAdvanced/index.svelte +31 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/AudioAdvanced/index.svelte.js +258 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Dropdown/index.svelte +58 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Dropdown/index.svelte.js +206 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Image/index.svelte +28 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Image/index.svelte.js +224 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Number/index.svelte +44 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Number/index.svelte.js +272 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Qr/index.svelte +41 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Qr/index.svelte.js +202 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Slider/index.svelte +19 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Slider/index.svelte.js +117 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/TableAdvanced/index.svelte +60 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/TableAdvanced/index.svelte.js +542 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Tag/index.svelte +47 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/Tag/index.svelte.js +185 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/TextInput/index.svelte +35 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/TextInput/index.svelte.js +222 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/TimeInput/index.svelte +20 -0
- package/dist/Components/ContentInput/AttributesInput/CustomConfig/TimeInput/index.svelte.js +84 -0
- package/dist/Components/ContentInput/AttributesInput/DefinedTypeInput/index.svelte +25 -0
- package/dist/Components/ContentInput/AttributesInput/DefinedTypeInput/index.svelte.js +91 -0
- package/dist/Components/ContentInput/AttributesInput/index.svelte +352 -0
- package/dist/Components/ContentInput/AttributesInput/index.svelte.js +1436 -0
- package/dist/Components/ContentInput/ContentPanelBuilder/AddElement/index.svelte +64 -0
- package/dist/Components/ContentInput/ContentPanelBuilder/AddElement/index.svelte.js +97 -0
- package/dist/Components/ContentInput/ContentPanelBuilder/ElementList/index.svelte +184 -0
- package/dist/Components/ContentInput/ContentPanelBuilder/index.svelte +41 -0
- package/dist/Components/ContentInput/index.svelte +78 -0
- package/dist/Components/ContentInput/index.svelte.js +1197 -0
- package/dist/Components/CronInput/index.svelte +78 -0
- package/dist/Components/CronInput/index.svelte.js +198 -0
- package/dist/Components/DataTypeInput/index.svelte +174 -0
- package/dist/Components/DataTypeInput/index.svelte.js +565 -0
- package/dist/Components/Dropdown/index.svelte +116 -0
- package/dist/Components/Dropdown/index.svelte.js +403 -0
- package/dist/Components/EmailAddress/index.svelte +22 -0
- package/dist/Components/EmailAddress/index.svelte.js +45 -0
- package/dist/Components/ErrorX/index.svelte +58 -0
- package/dist/Components/Eye/index.svelte +57 -0
- package/dist/Components/FileInput/index.svelte +146 -0
- package/dist/Components/FileInput/index.svelte.js +225 -0
- package/dist/Components/Hamburger/index.svelte +99 -0
- package/dist/Components/HorizScrollBox/index.svelte +145 -0
- package/dist/Components/Icon/index.svelte +412 -0
- package/dist/Components/Icon/index.svelte.js +116 -0
- package/dist/Components/IconInput/index.svelte +77 -0
- package/dist/Components/IconInput/index.svelte.js +259 -0
- package/dist/Components/Image/index.svelte +126 -0
- package/dist/Components/Image/index.svelte.js +116 -0
- package/dist/Components/ImageEditor/Image/CropBox/index.svelte +165 -0
- package/dist/Components/ImageEditor/Image/index.svelte +104 -0
- package/dist/Components/ImageEditor/Panels/AI/index.svelte +44 -0
- package/dist/Components/ImageEditor/Panels/Crop/index.svelte +96 -0
- package/dist/Components/ImageEditor/Panels/File/QualityPicker/index.svelte +124 -0
- package/dist/Components/ImageEditor/Panels/File/index.svelte +74 -0
- package/dist/Components/ImageEditor/Panels/Filters/index.svelte +46 -0
- package/dist/Components/ImageEditor/Panels/Resize/index.svelte +58 -0
- package/dist/Components/ImageEditor/index.svelte +93 -0
- package/dist/Components/ImageEditor/index.svelte.js +1961 -0
- package/dist/Components/ImageSlider/index.svelte +124 -0
- package/dist/Components/ImageSlider/index.svelte.js +99 -0
- package/dist/Components/InfoBox/index.svelte +89 -0
- package/dist/Components/Json/Nested/index.svelte +157 -0
- package/dist/Components/Json/index.svelte +60 -0
- package/dist/Components/Json/index.svelte.js +594 -0
- package/dist/Components/LabeledItem/index.svelte +102 -0
- package/dist/Components/Layout/NavBar/FullNav/index.svelte +52 -0
- package/dist/Components/Layout/NavBar/NavGuts/index.svelte +87 -0
- package/dist/Components/Layout/NavBar/index.svelte +72 -0
- package/dist/Components/Layout/index.svelte +149 -0
- package/dist/Components/Layout/index.svelte.js +360 -0
- package/dist/Components/Link/index.svelte +47 -0
- package/dist/Components/Link/index.svelte.js +136 -0
- package/dist/Components/LoadingSuccessDiv/index.svelte +51 -0
- package/dist/Components/LoadingWheel/index.svelte +38 -0
- package/dist/Components/Location/index.svelte +79 -0
- package/dist/Components/Location/index.svelte.js +288 -0
- package/dist/Components/LocationInput/index.svelte +197 -0
- package/dist/Components/LocationInput/index.svelte.js +965 -0
- package/dist/Components/Number/index.svelte +47 -0
- package/dist/Components/Number/index.svelte.js +151 -0
- package/dist/Components/PhoneCountryCode/index.svelte +7 -0
- package/dist/Components/PhoneCountryCode/index.svelte.js +260 -0
- package/dist/Components/PhoneNumber/index.svelte +22 -0
- package/dist/Components/PhoneNumber/index.svelte.js +41 -0
- package/dist/Components/Popover/index.svelte +396 -0
- package/dist/Components/Popover/index.svelte.js +319 -0
- package/dist/Components/Qr/index.svelte +85 -0
- package/dist/Components/Qr/index.svelte.js +301 -0
- package/dist/Components/QrInput/index.svelte +47 -0
- package/dist/Components/QrInput/index.svelte.js +218 -0
- package/dist/Components/Slider/index.svelte +239 -0
- package/dist/Components/Slider/index.svelte.js +469 -0
- package/dist/Components/Spacer/index.svelte +41 -0
- package/dist/Components/StoragePicker/DisplayFile/index.svelte +15 -0
- package/dist/Components/StoragePicker/index.svelte +187 -0
- package/dist/Components/StoragePicker/index.svelte.js +592 -0
- package/dist/Components/SuccessCheck/index.svelte +56 -0
- package/dist/Components/TableAdvanced/ColumnInput/index.svelte +117 -0
- package/dist/Components/TableAdvanced/ColumnInput/index.svelte.js +456 -0
- package/dist/Components/TableAdvanced/FilterInput/index.svelte +54 -0
- package/dist/Components/TableAdvanced/FilterInput/index.svelte.js +247 -0
- package/dist/Components/TableAdvanced/Pagination/index.svelte +43 -0
- package/dist/Components/TableAdvanced/Pagination/index.svelte.js +97 -0
- package/dist/Components/TableAdvanced/SortByInput/index.svelte +72 -0
- package/dist/Components/TableAdvanced/SortByInput/index.svelte.js +176 -0
- package/dist/Components/TableAdvanced/index.svelte +275 -0
- package/dist/Components/TableAdvanced/index.svelte.js +1565 -0
- package/dist/Components/Tag/index.svelte +45 -0
- package/dist/Components/Tag/index.svelte.js +76 -0
- package/dist/Components/TextArrayInput/index.svelte +108 -0
- package/dist/Components/TextArrayInput/index.svelte.js +239 -0
- package/dist/Components/TextInput/PasswordTooltip/index.svelte +89 -0
- package/dist/Components/TextInput/index.svelte +223 -0
- package/dist/Components/TextInput/index.svelte.js +447 -0
- package/dist/Components/Time/index.svelte +7 -0
- package/dist/Components/Time/index.svelte.js +38 -0
- package/dist/Components/TimeInput/NumberToggler/index.svelte +34 -0
- package/dist/Components/TimeInput/NumberToggler/index.svelte.js +79 -0
- package/dist/Components/TimeInput/index.js +702 -0
- package/dist/Components/TimeInput/index.svelte +211 -0
- package/dist/Components/TimeInput/index.svelte.js +638 -0
- package/dist/Components/Tooltip/index.svelte +143 -0
- package/dist/Components/TransparentBackground/index.svelte +153 -0
- package/dist/Components/TypingDots/index.svelte +84 -0
- package/dist/Components/VariablePathInput/index.svelte +63 -0
- package/dist/Components/VariablePathInput/index.svelte.js +273 -0
- package/dist/Components/VideoTBD/index.svelte +100 -0
- package/dist/Components/XFollow/index.svelte +42 -0
- package/dist/Components/XPost/index.svelte +52 -0
- package/dist/Components/XPost/index.svelte.js +64 -0
- package/dist/Components/YoutubeChannelButton/index.svelte +82 -0
- package/dist/Components/YoutubeVideo/index.svelte +73 -0
- package/dist/Components/YoutubeVideo/index.svelte.js +54 -0
- package/dist/actions/draggable.js +49 -0
- package/dist/actions/index.js +24 -0
- package/dist/actions/no_spaces.js +33 -0
- package/dist/actions/numbers_only.js +26 -0
- package/dist/actions/scroll_y.js +28 -0
- package/dist/actions/stop_scroll_propagation_y.js +42 -0
- package/dist/actions/swipe_handler.js +295 -0
- package/dist/client/astc_formatting/index.js +1128 -0
- package/dist/client/docs/index.js +7622 -0
- package/dist/client/index.js +735 -0
- package/dist/client/types/index.js +2812 -0
- package/dist/index.js +180 -0
- package/dist/style.css +682 -0
- package/package.json +1 -1
|
@@ -0,0 +1,592 @@
|
|
|
1
|
+
import {
|
|
2
|
+
set_closurable,
|
|
3
|
+
create_unique_id,
|
|
4
|
+
deep_copy,
|
|
5
|
+
clean_custom_identifier,
|
|
6
|
+
mime_type_extensions,
|
|
7
|
+
} from "../../client/index.js"
|
|
8
|
+
import { create_button_manager } from "../Button/index.svelte.js"
|
|
9
|
+
import { create_popover_manager } from "../Popover/index.svelte.js"
|
|
10
|
+
import { create_audio_manager } from "../Audio/index.svelte.js"
|
|
11
|
+
import { create_image_manager } from "../Image/index.svelte.js"
|
|
12
|
+
import { create_breadcrumbs_manager } from "../Breadcrumbs/index.svelte.js"
|
|
13
|
+
import { create_file_input_manager } from "../FileInput/index.svelte.js"
|
|
14
|
+
import { create_icon_manager } from "../Icon/index.svelte.js"
|
|
15
|
+
|
|
16
|
+
export function create_storage_picker_manager(config) {
|
|
17
|
+
const id = create_unique_id(null, 20)
|
|
18
|
+
|
|
19
|
+
let val = $state(null)
|
|
20
|
+
let storage = $state(null)
|
|
21
|
+
let storage_path = $state([])
|
|
22
|
+
let default_folder_path = $state(null)
|
|
23
|
+
let display_height = $state(20)
|
|
24
|
+
let locally_uploaded_files = $state(null)
|
|
25
|
+
let storage_origins = $state(null)
|
|
26
|
+
let mt = $state(0)
|
|
27
|
+
let mb = $state(0)
|
|
28
|
+
let breadcrumbs_manager = $state(null)
|
|
29
|
+
let locally_uploaded_files_prepped = $state([])
|
|
30
|
+
let storage_files_prepped = $state([])
|
|
31
|
+
|
|
32
|
+
let popover_manager = $state(null)
|
|
33
|
+
let file_input_manager = $state(null)
|
|
34
|
+
let folders_prepped = $state(null)
|
|
35
|
+
let select_file_from_storage_button_manager = $state(null)
|
|
36
|
+
let clear_button_manager = $state(null)
|
|
37
|
+
let finish_multiselect_button_manager = $state(null)
|
|
38
|
+
let display_file = $state(null)
|
|
39
|
+
let file_icon_manager = $state(null)
|
|
40
|
+
|
|
41
|
+
let is_show_content = $derived(set_closurable(config?.is_show_content, true))
|
|
42
|
+
let is_multiselect = $derived(set_closurable(config?.is_multiselect, false))
|
|
43
|
+
let is_disabled = $derived(set_closurable(config?.is_disabled, false))
|
|
44
|
+
let storage_src = $derived(
|
|
45
|
+
set_closurable(config?.storage_src, "https://www.contibase.com/api/v1/storage/{storage_id}")
|
|
46
|
+
)
|
|
47
|
+
let select_file_loading_id = $state(null)
|
|
48
|
+
|
|
49
|
+
function get_src(src, storage_id) {
|
|
50
|
+
if (src) {
|
|
51
|
+
return src
|
|
52
|
+
} else if (storage_id && storage_src) {
|
|
53
|
+
return storage_src.replace("{storage_id}", storage_id)
|
|
54
|
+
} else {
|
|
55
|
+
return null
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function set_display_file() {
|
|
60
|
+
if (Array.isArray(val)) {
|
|
61
|
+
let display_files = []
|
|
62
|
+
for (let item of val) {
|
|
63
|
+
const display_file_res = await set_display_single_file(item)
|
|
64
|
+
display_files.push(display_file_res)
|
|
65
|
+
}
|
|
66
|
+
display_file = display_files
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
const display_file_res = await set_display_single_file(val)
|
|
70
|
+
display_file = display_file_res
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function set_display_single_file(input) {
|
|
74
|
+
let display_file_loc = null
|
|
75
|
+
if (input?.file) {
|
|
76
|
+
display_file_loc = {
|
|
77
|
+
mime_type: input?.file?.type,
|
|
78
|
+
src: URL.createObjectURL(input?.file),
|
|
79
|
+
}
|
|
80
|
+
} else if (input?.id) {
|
|
81
|
+
display_file_loc = {
|
|
82
|
+
...input,
|
|
83
|
+
src: get_src(input?.src, input?.id),
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (display_file_loc?.mime_type == "audio/mpeg") {
|
|
87
|
+
display_file_loc.manager = create_audio_manager({
|
|
88
|
+
src: display_file_loc?.src,
|
|
89
|
+
type: display_file_loc?.mime_type,
|
|
90
|
+
image_src: display_file_loc?.image_src,
|
|
91
|
+
image_type: display_file_loc?.image_type,
|
|
92
|
+
})
|
|
93
|
+
} else if (["image/webp", "image/jpeg", "image/png", "image/gif"].includes(display_file_loc?.mime_type)) {
|
|
94
|
+
display_file_loc.manager = create_image_manager({
|
|
95
|
+
src: display_file_loc?.src,
|
|
96
|
+
display_max_height: 200,
|
|
97
|
+
display_max_width: 200,
|
|
98
|
+
bg_img_blur: 20,
|
|
99
|
+
bg_img_opacity: 0.01,
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
return display_file_loc
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let acceptable_mime_types = $derived(Array.isArray(config?.accept) ? config?.accept : null)
|
|
106
|
+
let ordered_items = $derived(get_ordered_items(storage, locally_uploaded_files, storage_path, acceptable_mime_types))
|
|
107
|
+
let is_file_chosen = $derived((Array.isArray(val) && val.length > 0) || !!val?.file || !!val?.file_name)
|
|
108
|
+
|
|
109
|
+
function get_ordered_items(storage, locally_uploaded_files, storage_path, acceptable_mime_types) {
|
|
110
|
+
let folder_ids = []
|
|
111
|
+
let storage_ids = []
|
|
112
|
+
let locally_uploaded_files_ids = []
|
|
113
|
+
const is_acceptable_mime_type = (item) => {
|
|
114
|
+
return (
|
|
115
|
+
!(Array.isArray(acceptable_mime_types) && acceptable_mime_types.length > 0) ||
|
|
116
|
+
acceptable_mime_types.includes(item?.mime_type)
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
if (
|
|
120
|
+
Array.isArray(storage_origins) &&
|
|
121
|
+
storage_origins.includes("storage") &&
|
|
122
|
+
typeof storage === "object" &&
|
|
123
|
+
!Array.isArray(storage) &&
|
|
124
|
+
Object.keys(storage || {}).length > 0
|
|
125
|
+
) {
|
|
126
|
+
let folders_with_acceptable_files = new Set()
|
|
127
|
+
Object.entries(storage).forEach(([id, item]) => {
|
|
128
|
+
const item_path = item?.folder_path || []
|
|
129
|
+
const is_at_current_path = storage_path.every((part, index) => part === (item_path[index] || ""))
|
|
130
|
+
const is_next_folder = storage_path.length < item_path.length && is_at_current_path
|
|
131
|
+
if (is_at_current_path && item_path.length === storage_path.length && is_acceptable_mime_type(item)) {
|
|
132
|
+
storage_ids.push(id)
|
|
133
|
+
}
|
|
134
|
+
if (is_next_folder && is_acceptable_mime_type(item)) {
|
|
135
|
+
folders_with_acceptable_files.add(item_path[storage_path.length])
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
folder_ids = Array.from(folders_with_acceptable_files).sort()
|
|
139
|
+
storage_ids = storage_ids.sort()
|
|
140
|
+
}
|
|
141
|
+
if (
|
|
142
|
+
Array.isArray(storage_origins) &&
|
|
143
|
+
storage_origins.includes("locally_uploaded_files") &&
|
|
144
|
+
typeof locally_uploaded_files === "object" &&
|
|
145
|
+
!Array.isArray(locally_uploaded_files) &&
|
|
146
|
+
Object.keys(locally_uploaded_files || {}).length > 0
|
|
147
|
+
) {
|
|
148
|
+
locally_uploaded_files_ids = Object.values(locally_uploaded_files)
|
|
149
|
+
.filter((locally_uploaded_file) => is_acceptable_mime_type(locally_uploaded_file))
|
|
150
|
+
.sort((a, b) => {
|
|
151
|
+
if (a?.db_epoch_updated == null && b?.db_epoch_updated == null) return 0
|
|
152
|
+
if (a?.db_epoch_updated == null) return 1
|
|
153
|
+
if (b?.db_epoch_updated == null) return -1
|
|
154
|
+
return b.db_epoch_updated - a.db_epoch_updated
|
|
155
|
+
})
|
|
156
|
+
.map((locally_uploaded_file) => locally_uploaded_file?.id)
|
|
157
|
+
}
|
|
158
|
+
return { folder_ids, storage_ids, locally_uploaded_files_ids }
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function convert_file_to_base64(file) {
|
|
162
|
+
return new Promise((resolve, reject) => {
|
|
163
|
+
const reader = new FileReader()
|
|
164
|
+
reader.onload = () => resolve(reader.result.split(",")[1])
|
|
165
|
+
reader.onerror = (error) => reject(error)
|
|
166
|
+
reader.readAsDataURL(file)
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async function fetch_and_convert_to_base64(storage_id, file_name, mime_type) {
|
|
171
|
+
try {
|
|
172
|
+
let storage_src_loc = storage_src.replace("{storage_id}", storage_id)
|
|
173
|
+
console.log("storage_src_loc", storage_src_loc)
|
|
174
|
+
const response = await fetch(storage_src_loc)
|
|
175
|
+
if (!response.ok) {
|
|
176
|
+
throw new Error(`Failed to fetch file from storage. Status: ${response.status}`)
|
|
177
|
+
}
|
|
178
|
+
const blob = await response.blob()
|
|
179
|
+
const file = new File([blob], file_name, { type: mime_type })
|
|
180
|
+
const base64_content = await convert_file_to_base64(file)
|
|
181
|
+
return base64_content
|
|
182
|
+
} catch (error) {
|
|
183
|
+
console.error("Error fetching or converting file to Base64:", error)
|
|
184
|
+
return null
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async function select_file(storage_item, loading_id) {
|
|
189
|
+
if (!loading_id) {
|
|
190
|
+
loading_id = create_unique_id(null, 20)
|
|
191
|
+
}
|
|
192
|
+
select_file_loading_id = loading_id
|
|
193
|
+
if (is_multiselect) {
|
|
194
|
+
const existing_index = Array.isArray(val) ? val.findIndex((h) => h?.id == storage_item?.id) : -1
|
|
195
|
+
if (existing_index > -1) {
|
|
196
|
+
val = val.filter((h) => h?.id != storage_item?.id)
|
|
197
|
+
} else {
|
|
198
|
+
if (storage_item?.file) {
|
|
199
|
+
storage_item.base64_content = await convert_file_to_base64(storage_item?.file)
|
|
200
|
+
} else {
|
|
201
|
+
storage_item.base64_content = await fetch_and_convert_to_base64(
|
|
202
|
+
storage_item?.id,
|
|
203
|
+
storage_item?.file_name,
|
|
204
|
+
storage_item?.mime_type
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
val = [...(Array.isArray(val) ? val : []), storage_item]
|
|
208
|
+
}
|
|
209
|
+
} else {
|
|
210
|
+
if (storage_item?.file) {
|
|
211
|
+
storage_item.base64_content = await convert_file_to_base64(storage_item?.file)
|
|
212
|
+
} else {
|
|
213
|
+
storage_item.base64_content = await fetch_and_convert_to_base64(
|
|
214
|
+
storage_item?.id,
|
|
215
|
+
storage_item?.file_name,
|
|
216
|
+
storage_item?.mime_type
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
val = storage_item
|
|
220
|
+
if (typeof config?.on_finish == "function") {
|
|
221
|
+
config?.on_finish(val)
|
|
222
|
+
}
|
|
223
|
+
popover_manager?.close()
|
|
224
|
+
}
|
|
225
|
+
set_display_file()
|
|
226
|
+
select_file_loading_id = null
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async function set_val(input) {
|
|
230
|
+
if (input && typeof input == "object" && !Array.isArray(input)) {
|
|
231
|
+
if (input?.file) {
|
|
232
|
+
input.base64_content = await convert_file_to_base64(input?.file)
|
|
233
|
+
} else {
|
|
234
|
+
input.base64_content = await fetch_and_convert_to_base64(input?.id, input?.file_name, input?.mime_type)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
val = input
|
|
238
|
+
set_display_file()
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function clear(is_call_finish = true) {
|
|
242
|
+
val = null
|
|
243
|
+
if (is_call_finish && typeof config?.on_finish == "function") {
|
|
244
|
+
config?.on_finish(val)
|
|
245
|
+
}
|
|
246
|
+
set_display_file()
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function set_locally_uploaded_files_prepped() {
|
|
250
|
+
let locally_uploaded_files_prepped_loc = []
|
|
251
|
+
if (
|
|
252
|
+
storage_origins.includes("locally_uploaded_files") &&
|
|
253
|
+
Array.isArray(ordered_items?.locally_uploaded_files_ids) &&
|
|
254
|
+
ordered_items?.locally_uploaded_files_ids.length > 0
|
|
255
|
+
) {
|
|
256
|
+
for (let locally_uploaded_file_id of ordered_items?.locally_uploaded_files_ids) {
|
|
257
|
+
const locally_uploaded_file = locally_uploaded_files?.[locally_uploaded_file_id]
|
|
258
|
+
const loading_id = create_unique_id(null, 20)
|
|
259
|
+
let locally_uploaded_file_prepped = {
|
|
260
|
+
...locally_uploaded_file,
|
|
261
|
+
select_button_manager: create_button_manager({
|
|
262
|
+
text: () =>
|
|
263
|
+
Array.isArray(val) && val.some((h) => h?.id == locally_uploaded_file?.id)
|
|
264
|
+
? "Deselect File"
|
|
265
|
+
: "Select File",
|
|
266
|
+
selected_type: () =>
|
|
267
|
+
Array.isArray(val) && val.some((h) => h?.id == locally_uploaded_file?.id) ? "selected" : null,
|
|
268
|
+
is_loading: () => select_file_loading_id == loading_id,
|
|
269
|
+
is_disabled: () => select_file_loading_id && select_file_loading_id != loading_id,
|
|
270
|
+
mt: 1,
|
|
271
|
+
on_click: () => select_file(locally_uploaded_file, loading_id),
|
|
272
|
+
}),
|
|
273
|
+
}
|
|
274
|
+
if (["audio/mpeg"].includes(locally_uploaded_file_prepped?.mime_type)) {
|
|
275
|
+
locally_uploaded_file_prepped.manager = create_audio_manager({
|
|
276
|
+
ui_type: "short",
|
|
277
|
+
src: get_src(locally_uploaded_file?.src, locally_uploaded_file?.id),
|
|
278
|
+
type: "audio/mpeg",
|
|
279
|
+
})
|
|
280
|
+
} else if (
|
|
281
|
+
["image/webp", "image/jpeg", "image/png", "image/gif"].includes(locally_uploaded_file_prepped?.mime_type)
|
|
282
|
+
) {
|
|
283
|
+
locally_uploaded_file_prepped.manager = create_image_manager({
|
|
284
|
+
src: get_src(locally_uploaded_file?.src, locally_uploaded_file?.id),
|
|
285
|
+
display_max_height: 200,
|
|
286
|
+
display_max_width: 200,
|
|
287
|
+
bg_img_blur: 20,
|
|
288
|
+
bg_img_opacity: 0.01,
|
|
289
|
+
})
|
|
290
|
+
}
|
|
291
|
+
locally_uploaded_files_prepped_loc.push(locally_uploaded_file_prepped)
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
locally_uploaded_files_prepped = locally_uploaded_files_prepped_loc
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function set_files_prepped() {
|
|
298
|
+
set_locally_uploaded_files_prepped()
|
|
299
|
+
let storage_files_prepped_loc = []
|
|
300
|
+
if (storage_origins.includes("storage")) {
|
|
301
|
+
breadcrumbs_manager = create_breadcrumbs_manager({
|
|
302
|
+
val: deep_copy(storage_path),
|
|
303
|
+
on_change: (input) => {
|
|
304
|
+
storage_path = input
|
|
305
|
+
set_files_prepped()
|
|
306
|
+
},
|
|
307
|
+
})
|
|
308
|
+
let folder_buttons_prepped = []
|
|
309
|
+
if (Array.isArray(ordered_items?.folder_ids) && ordered_items?.folder_ids.length > 0) {
|
|
310
|
+
for (let folder_id of ordered_items?.folder_ids) {
|
|
311
|
+
folder_buttons_prepped.push(
|
|
312
|
+
create_button_manager({
|
|
313
|
+
type: "soft",
|
|
314
|
+
support_icon: "folder",
|
|
315
|
+
icon_pos: "left",
|
|
316
|
+
text_align: "left",
|
|
317
|
+
text: folder_id,
|
|
318
|
+
on_click: () => {
|
|
319
|
+
storage_path = deep_copy([...storage_path, folder_id])
|
|
320
|
+
set_files_prepped()
|
|
321
|
+
},
|
|
322
|
+
})
|
|
323
|
+
)
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
folders_prepped = folder_buttons_prepped
|
|
327
|
+
if (Array.isArray(ordered_items?.storage_ids) && ordered_items?.storage_ids.length > 0) {
|
|
328
|
+
for (let storage_id of ordered_items?.storage_ids) {
|
|
329
|
+
const storage_item = storage?.[storage_id]
|
|
330
|
+
const loading_id = create_unique_id(null, 20)
|
|
331
|
+
const src = get_src(storage_item?.src, storage_item?.id)
|
|
332
|
+
let storage_file_prepped_loc = {
|
|
333
|
+
...storage_item,
|
|
334
|
+
src: src,
|
|
335
|
+
select_button_manager: create_button_manager({
|
|
336
|
+
text: () =>
|
|
337
|
+
Array.isArray(val) && val.some((h) => h?.id == storage_id) ? "Deselect File" : "Select File",
|
|
338
|
+
selected_type: () => (Array.isArray(val) && val.some((h) => h?.id == storage_id) ? "selected" : null),
|
|
339
|
+
is_loading: () => select_file_loading_id == loading_id,
|
|
340
|
+
is_disabled: () => select_file_loading_id && select_file_loading_id != loading_id,
|
|
341
|
+
mt: 1,
|
|
342
|
+
on_click: () => select_file(storage?.[storage_id], loading_id),
|
|
343
|
+
}),
|
|
344
|
+
}
|
|
345
|
+
if (["audio/mpeg"].includes(storage_item?.mime_type)) {
|
|
346
|
+
storage_file_prepped_loc.manager = create_audio_manager({
|
|
347
|
+
ui_type: "short",
|
|
348
|
+
src: src,
|
|
349
|
+
type: "audio/mpeg",
|
|
350
|
+
})
|
|
351
|
+
} else if (["image/webp", "image/jpeg", "image/png", "image/gif"].includes(storage_item?.mime_type)) {
|
|
352
|
+
storage_file_prepped_loc.manager = create_image_manager({
|
|
353
|
+
src: src,
|
|
354
|
+
display_max_height: 200,
|
|
355
|
+
display_max_width: 200,
|
|
356
|
+
bg_img_blur: 20,
|
|
357
|
+
bg_img_opacity: 0.01,
|
|
358
|
+
})
|
|
359
|
+
}
|
|
360
|
+
storage_files_prepped_loc.push(storage_file_prepped_loc)
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
storage_files_prepped = storage_files_prepped_loc
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function open_popover() {
|
|
368
|
+
popover_manager.open()
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function init(config) {
|
|
372
|
+
storage =
|
|
373
|
+
config?.storage && Array.isArray(config?.storage)
|
|
374
|
+
? config?.storage.reduce((acc, item) => {
|
|
375
|
+
acc[item.id] = item
|
|
376
|
+
return acc
|
|
377
|
+
}, {})
|
|
378
|
+
: config?.storage
|
|
379
|
+
locally_uploaded_files =
|
|
380
|
+
config?.locally_uploaded_files && Array.isArray(config?.locally_uploaded_files)
|
|
381
|
+
? config?.locally_uploaded_files.reduce((acc, item) => {
|
|
382
|
+
acc[item?.id] = item
|
|
383
|
+
return acc
|
|
384
|
+
}, {})
|
|
385
|
+
: config?.locally_uploaded_files
|
|
386
|
+
storage_path = Array.isArray(config?.default_folder_path) ? config?.default_folder_path : []
|
|
387
|
+
storage_origins = config?.storage_origins ?? ["locally_uploaded_files", "storage"]
|
|
388
|
+
popover_manager = create_popover_manager({
|
|
389
|
+
min_width: 320,
|
|
390
|
+
target_width: 900,
|
|
391
|
+
min_height: 320,
|
|
392
|
+
target_height: 700,
|
|
393
|
+
type: "center",
|
|
394
|
+
header: "Storage Picker",
|
|
395
|
+
anchor_id: () => `button_${select_file_from_storage_button_manager?.id}`,
|
|
396
|
+
})
|
|
397
|
+
select_file_from_storage_button_manager = create_button_manager({
|
|
398
|
+
type: "outlined",
|
|
399
|
+
is_compressed: true,
|
|
400
|
+
text: () => `Select File${is_multiselect ? "s" : ""}`,
|
|
401
|
+
is_loading: () => select_file_loading_id,
|
|
402
|
+
mb: 1,
|
|
403
|
+
is_disabled: () => is_disabled,
|
|
404
|
+
popover_target: () => `popover_${popover_manager?.id}`,
|
|
405
|
+
})
|
|
406
|
+
file_input_manager = create_file_input_manager({
|
|
407
|
+
accept: acceptable_mime_types,
|
|
408
|
+
is_multiselect: true,
|
|
409
|
+
is_drop_zone: true,
|
|
410
|
+
is_disabled: () => is_disabled,
|
|
411
|
+
on_get_file: async (input) => {
|
|
412
|
+
console.log("on_get_file", input)
|
|
413
|
+
let locally_uploaded_files_to_add = {}
|
|
414
|
+
if (Array.isArray(input)) {
|
|
415
|
+
for (let file of input) {
|
|
416
|
+
console.log("item", file)
|
|
417
|
+
const id = create_unique_id(null, 20)
|
|
418
|
+
let file_obj = {
|
|
419
|
+
id: id,
|
|
420
|
+
file: file,
|
|
421
|
+
src: file ? URL.createObjectURL(file) : null,
|
|
422
|
+
file_name: clean_custom_identifier(file?.name.replace(/\..+$/, "")),
|
|
423
|
+
mime_type: file?.type,
|
|
424
|
+
file_extension: mime_type_extensions?.[file?.type],
|
|
425
|
+
size_kb: file?.size ? Math.round(file?.size * 0.001) : null,
|
|
426
|
+
}
|
|
427
|
+
const base64_content = await convert_file_to_base64(file)
|
|
428
|
+
file_obj.base64_content = base64_content
|
|
429
|
+
locally_uploaded_files_to_add[id] = file_obj
|
|
430
|
+
}
|
|
431
|
+
} else {
|
|
432
|
+
const id = create_unique_id(null, 20)
|
|
433
|
+
let file_obj = {
|
|
434
|
+
id: id,
|
|
435
|
+
file: input,
|
|
436
|
+
src: input ? URL.createObjectURL(input) : null,
|
|
437
|
+
file_name: clean_custom_identifier(input?.name.replace(/\..+$/, "")),
|
|
438
|
+
mime_type: input?.type,
|
|
439
|
+
file_extension: mime_type_extensions?.[input?.type],
|
|
440
|
+
size_kb: input?.size ? Math.round(input?.size * 0.001) : null,
|
|
441
|
+
}
|
|
442
|
+
const base64_content = await convert_file_to_base64(input)
|
|
443
|
+
file_obj.base64_content = base64_content
|
|
444
|
+
locally_uploaded_files_to_add[id] = file_obj
|
|
445
|
+
}
|
|
446
|
+
locally_uploaded_files = {
|
|
447
|
+
...(locally_uploaded_files &&
|
|
448
|
+
typeof locally_uploaded_files == "object" &&
|
|
449
|
+
!Array.isArray(locally_uploaded_files)
|
|
450
|
+
? locally_uploaded_files
|
|
451
|
+
: {}),
|
|
452
|
+
...locally_uploaded_files_to_add,
|
|
453
|
+
}
|
|
454
|
+
set_locally_uploaded_files_prepped()
|
|
455
|
+
set_display_file()
|
|
456
|
+
file_input_manager.clear_files()
|
|
457
|
+
},
|
|
458
|
+
})
|
|
459
|
+
clear_button_manager = create_button_manager({
|
|
460
|
+
type: "outlined",
|
|
461
|
+
support_icon: "x",
|
|
462
|
+
is_disabled: () => is_disabled,
|
|
463
|
+
text: () =>
|
|
464
|
+
val?.file_name ??
|
|
465
|
+
val?.file?.name ??
|
|
466
|
+
(Array.isArray(val) ? `${val.length} file${val.length > 1 ? "s" : ""} selected` : "Untitled"),
|
|
467
|
+
on_click: () => clear(),
|
|
468
|
+
})
|
|
469
|
+
finish_multiselect_button_manager = create_button_manager({
|
|
470
|
+
text: () =>
|
|
471
|
+
`Finish ${
|
|
472
|
+
Array.isArray(val)
|
|
473
|
+
? val.length === 1
|
|
474
|
+
? "(1 File Selected)"
|
|
475
|
+
: val.length > 1
|
|
476
|
+
? "(" + val.length + " files selected)"
|
|
477
|
+
: ""
|
|
478
|
+
: ""
|
|
479
|
+
}`,
|
|
480
|
+
is_disabled: () => is_disabled || (Array.isArray(val) && val.length < 1),
|
|
481
|
+
on_click: () => {
|
|
482
|
+
console.log("val_fin", deep_copy(val))
|
|
483
|
+
set_display_file()
|
|
484
|
+
if (typeof config?.on_finish == "function") {
|
|
485
|
+
config?.on_finish(val)
|
|
486
|
+
}
|
|
487
|
+
popover_manager?.close()
|
|
488
|
+
},
|
|
489
|
+
})
|
|
490
|
+
file_icon_manager = create_icon_manager({
|
|
491
|
+
icon_id: "file",
|
|
492
|
+
size: 10,
|
|
493
|
+
sw: 10,
|
|
494
|
+
color: "var(--g6-t)",
|
|
495
|
+
})
|
|
496
|
+
set_files_prepped()
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
init(config)
|
|
500
|
+
|
|
501
|
+
return {
|
|
502
|
+
id,
|
|
503
|
+
get val() {
|
|
504
|
+
return val
|
|
505
|
+
},
|
|
506
|
+
get storage() {
|
|
507
|
+
return storage
|
|
508
|
+
},
|
|
509
|
+
get storage_path() {
|
|
510
|
+
return storage_path
|
|
511
|
+
},
|
|
512
|
+
get default_folder_path() {
|
|
513
|
+
return default_folder_path
|
|
514
|
+
},
|
|
515
|
+
get display_height() {
|
|
516
|
+
return display_height
|
|
517
|
+
},
|
|
518
|
+
get locally_uploaded_files() {
|
|
519
|
+
return locally_uploaded_files
|
|
520
|
+
},
|
|
521
|
+
get is_show_content() {
|
|
522
|
+
return is_show_content
|
|
523
|
+
},
|
|
524
|
+
get is_multiselect() {
|
|
525
|
+
return is_multiselect
|
|
526
|
+
},
|
|
527
|
+
get is_disabled() {
|
|
528
|
+
return is_disabled
|
|
529
|
+
},
|
|
530
|
+
get storage_origins() {
|
|
531
|
+
return storage_origins
|
|
532
|
+
},
|
|
533
|
+
get mt() {
|
|
534
|
+
return mt
|
|
535
|
+
},
|
|
536
|
+
get mb() {
|
|
537
|
+
return mb
|
|
538
|
+
},
|
|
539
|
+
get breadcrumbs_manager() {
|
|
540
|
+
return breadcrumbs_manager
|
|
541
|
+
},
|
|
542
|
+
get popover_manager() {
|
|
543
|
+
return popover_manager
|
|
544
|
+
},
|
|
545
|
+
get file_input_manager() {
|
|
546
|
+
return file_input_manager
|
|
547
|
+
},
|
|
548
|
+
get select_file_from_storage_button_manager() {
|
|
549
|
+
return select_file_from_storage_button_manager
|
|
550
|
+
},
|
|
551
|
+
get folders_prepped() {
|
|
552
|
+
return folders_prepped
|
|
553
|
+
},
|
|
554
|
+
get clear_button_manager() {
|
|
555
|
+
return clear_button_manager
|
|
556
|
+
},
|
|
557
|
+
get finish_multiselect_button_manager() {
|
|
558
|
+
return finish_multiselect_button_manager
|
|
559
|
+
},
|
|
560
|
+
get acceptable_mime_types() {
|
|
561
|
+
return acceptable_mime_types
|
|
562
|
+
},
|
|
563
|
+
get ordered_items() {
|
|
564
|
+
return ordered_items
|
|
565
|
+
},
|
|
566
|
+
get is_file_chosen() {
|
|
567
|
+
return is_file_chosen
|
|
568
|
+
},
|
|
569
|
+
get locally_uploaded_files_prepped() {
|
|
570
|
+
return locally_uploaded_files_prepped
|
|
571
|
+
},
|
|
572
|
+
get storage_files_prepped() {
|
|
573
|
+
return storage_files_prepped
|
|
574
|
+
},
|
|
575
|
+
get is_show_button() {
|
|
576
|
+
return config?.is_show_button ?? true
|
|
577
|
+
},
|
|
578
|
+
get display_file() {
|
|
579
|
+
return display_file
|
|
580
|
+
},
|
|
581
|
+
get file_icon_manager() {
|
|
582
|
+
return file_icon_manager
|
|
583
|
+
},
|
|
584
|
+
init,
|
|
585
|
+
get_ordered_items,
|
|
586
|
+
select_file,
|
|
587
|
+
clear,
|
|
588
|
+
set_files_prepped,
|
|
589
|
+
open_popover,
|
|
590
|
+
set_val,
|
|
591
|
+
}
|
|
592
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
let { is_show = true, color = "var(--primary-t)", sw = 30 } = $props()
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
{#if is_show}
|
|
6
|
+
<svg
|
|
7
|
+
class="checkmark"
|
|
8
|
+
style="--color: {color}; --sw: {sw};"
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
viewBox="0 0 512 512"
|
|
11
|
+
fill="none"
|
|
12
|
+
stroke-linecap="round"
|
|
13
|
+
stroke-linejoin="round"
|
|
14
|
+
>
|
|
15
|
+
<circle class="checkmark_circle" cx="256" cy="256" r="196.16" />
|
|
16
|
+
<path class="checkmark_check" d="m162.63 265.42 55.71 56.49 131-131.82" />
|
|
17
|
+
</svg>
|
|
18
|
+
{/if}
|
|
19
|
+
|
|
20
|
+
<style>
|
|
21
|
+
.checkmark {
|
|
22
|
+
width: 100%;
|
|
23
|
+
height: 100%;
|
|
24
|
+
border-radius: 50%;
|
|
25
|
+
stroke-width: var(--sw);
|
|
26
|
+
stroke: var(--color);
|
|
27
|
+
stroke-miterlimit: 10;
|
|
28
|
+
animation:
|
|
29
|
+
ease-in-out 0.4s forwards,
|
|
30
|
+
scale 0.3s ease-in-out 0.9s both;
|
|
31
|
+
}
|
|
32
|
+
.checkmark_circle {
|
|
33
|
+
stroke-dasharray: 1250;
|
|
34
|
+
stroke-dashoffset: 1250;
|
|
35
|
+
animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;
|
|
36
|
+
}
|
|
37
|
+
.checkmark_check {
|
|
38
|
+
stroke-dasharray: 270;
|
|
39
|
+
stroke-dashoffset: 270;
|
|
40
|
+
animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards;
|
|
41
|
+
}
|
|
42
|
+
@keyframes stroke {
|
|
43
|
+
100% {
|
|
44
|
+
stroke-dashoffset: 0;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
@keyframes scale {
|
|
48
|
+
0%,
|
|
49
|
+
100% {
|
|
50
|
+
transform: none;
|
|
51
|
+
}
|
|
52
|
+
50% {
|
|
53
|
+
transform: scale3d(1.1, 1.1, 1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
</style>
|