@widgetic/editor 3.11.4 → 4.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 (497) hide show
  1. package/README.md +245 -0
  2. package/dist/assets/fonts.json +331 -0
  3. package/dist/assets/icons/ic-browser/audio.svg +7 -0
  4. package/dist/assets/icons/ic-browser/document.svg +11 -0
  5. package/dist/assets/icons/ic-browser/error.svg +5 -0
  6. package/dist/assets/icons/ic-browser/folder.svg +28 -0
  7. package/dist/assets/icons/ic-browser/player-pause.svg +1 -0
  8. package/dist/assets/icons/ic-browser/player-play.svg +1 -0
  9. package/dist/assets/icons/ic-browser/trash.svg +1 -0
  10. package/dist/assets/icons/ic-fixed-position/background-deselected.svg +3 -0
  11. package/dist/assets/icons/ic-fixed-position/background-selected.svg +3 -0
  12. package/dist/assets/icons/ic-fixed-position/bottom-left-background-deselected.svg +3 -0
  13. package/dist/assets/icons/ic-fixed-position/bottom-left-background-selected.svg +3 -0
  14. package/dist/assets/icons/ic-fixed-position/bottom-left-icon.svg +4 -0
  15. package/dist/assets/icons/ic-fixed-position/bottom-right-background-deselected.svg +3 -0
  16. package/dist/assets/icons/ic-fixed-position/bottom-right-background-selected.svg +3 -0
  17. package/dist/assets/icons/ic-fixed-position/bottom-right-icon.svg +4 -0
  18. package/dist/assets/icons/ic-fixed-position/center-bottom-icon.svg +5 -0
  19. package/dist/assets/icons/ic-fixed-position/center-center-icon.svg +3 -0
  20. package/dist/assets/icons/ic-fixed-position/center-left-icon.svg +5 -0
  21. package/dist/assets/icons/ic-fixed-position/center-right-icon.svg +5 -0
  22. package/dist/assets/icons/ic-fixed-position/center-top-icon.svg +5 -0
  23. package/dist/assets/icons/ic-fixed-position/top-left-background-deselected.svg +3 -0
  24. package/dist/assets/icons/ic-fixed-position/top-left-background-selected.svg +3 -0
  25. package/dist/assets/icons/ic-fixed-position/top-left-icon.svg +4 -0
  26. package/dist/assets/icons/ic-fixed-position/top-right-background-deselected.svg +3 -0
  27. package/dist/assets/icons/ic-fixed-position/top-right-background-selected.svg +3 -0
  28. package/dist/assets/icons/ic-fixed-position/top-right-icon.svg +4 -0
  29. package/dist/assets/icons/trash.svg +1 -0
  30. package/dist/components/MockWidget.svelte +108 -0
  31. package/dist/components/MockWidget.svelte.d.ts +22 -0
  32. package/dist/components/WidgetPreview.svelte +852 -0
  33. package/dist/components/WidgetPreview.svelte.d.ts +100 -0
  34. package/dist/components/color-select/ColorSelect.svelte +258 -0
  35. package/dist/components/color-select/ColorSelect.svelte.d.ts +42 -0
  36. package/dist/components/color-select/color.d.ts +25 -0
  37. package/dist/components/color-select/color.js +21 -0
  38. package/dist/components/color-select/constants.d.ts +5 -0
  39. package/dist/components/color-select/constants.js +5 -0
  40. package/dist/components/color-select/render.d.ts +5 -0
  41. package/dist/components/color-select/render.js +77 -0
  42. package/dist/components/color-select/shaders.d.ts +3 -0
  43. package/dist/components/color-select/shaders.js +8 -0
  44. package/dist/components/editors/EmbedEditor.svelte +700 -0
  45. package/dist/components/editors/EmbedEditor.svelte.d.ts +50 -0
  46. package/dist/components/editors/PropsEditor.svelte +3952 -0
  47. package/dist/components/editors/PropsEditor.svelte.d.ts +62 -0
  48. package/dist/components/editors/props-editor.css +73 -0
  49. package/dist/components/ic/AngleInputController.svelte +276 -0
  50. package/dist/components/ic/AngleInputController.svelte.d.ts +26 -0
  51. package/dist/components/ic/BrowserInputController.svelte +724 -0
  52. package/dist/components/ic/BrowserInputController.svelte.d.ts +39 -0
  53. package/dist/components/ic/CheckboxInputController.svelte +203 -0
  54. package/dist/components/ic/CheckboxInputController.svelte.d.ts +41 -0
  55. package/dist/components/ic/ColorPickerInputController.svelte +1584 -0
  56. package/dist/components/ic/ColorPickerInputController.svelte.d.ts +50 -0
  57. package/dist/components/ic/DateFieldInputController.svelte +453 -0
  58. package/dist/components/ic/DateFieldInputController.svelte.d.ts +35 -0
  59. package/dist/components/ic/DatePickerInputController.svelte +364 -0
  60. package/dist/components/ic/DatePickerInputController.svelte.d.ts +28 -0
  61. package/dist/components/ic/DropdownInputController.svelte +226 -0
  62. package/dist/components/ic/DropdownInputController.svelte.d.ts +43 -0
  63. package/dist/components/ic/FixedPositionInputController.svelte +353 -0
  64. package/dist/components/ic/FixedPositionInputController.svelte.d.ts +23 -0
  65. package/dist/components/ic/FontInputController.svelte +2062 -0
  66. package/dist/components/ic/FontInputController.svelte.d.ts +47 -0
  67. package/dist/components/ic/InputControllerHeader.svelte +147 -0
  68. package/dist/components/ic/InputControllerHeader.svelte.d.ts +23 -0
  69. package/dist/components/ic/NumberControls.svelte +299 -0
  70. package/dist/components/ic/NumberControls.svelte.d.ts +30 -0
  71. package/dist/components/ic/NumberInputController.svelte +397 -0
  72. package/dist/components/ic/NumberInputController.svelte.d.ts +30 -0
  73. package/dist/components/ic/PositionInputController.svelte +252 -0
  74. package/dist/components/ic/PositionInputController.svelte.d.ts +37 -0
  75. package/dist/components/ic/RadioGroupInputController.svelte +162 -0
  76. package/dist/components/ic/RadioGroupInputController.svelte.d.ts +38 -0
  77. package/dist/components/ic/RangeCalendarInputController.svelte +262 -0
  78. package/dist/components/ic/RangeCalendarInputController.svelte.d.ts +32 -0
  79. package/dist/components/ic/RoundedCornersInputController.svelte +469 -0
  80. package/dist/components/ic/RoundedCornersInputController.svelte.d.ts +37 -0
  81. package/dist/components/ic/SliderInputController.svelte +411 -0
  82. package/dist/components/ic/SliderInputController.svelte.d.ts +46 -0
  83. package/dist/components/ic/SliderRangeInputController.svelte +155 -0
  84. package/dist/components/ic/SliderRangeInputController.svelte.d.ts +33 -0
  85. package/dist/components/ic/SwitchInputController.svelte +107 -0
  86. package/dist/components/ic/SwitchInputController.svelte.d.ts +24 -0
  87. package/dist/components/ic/TagsInputController.svelte +125 -0
  88. package/dist/components/ic/TagsInputController.svelte.d.ts +27 -0
  89. package/dist/components/ic/TextAreaInputController.svelte +1804 -0
  90. package/dist/components/ic/TextAreaInputController.svelte.d.ts +13 -0
  91. package/dist/components/ic/TextAreaPreviewInputController.svelte +476 -0
  92. package/dist/components/ic/TextAreaPreviewInputController.svelte.d.ts +28 -0
  93. package/dist/components/ic/TextInputController.svelte +70 -0
  94. package/dist/components/ic/TextInputController.svelte.d.ts +30 -0
  95. package/dist/components/ic/TimeInputController.svelte +434 -0
  96. package/dist/components/ic/TimeInputController.svelte.d.ts +25 -0
  97. package/dist/components/ic/VectorInputController.svelte +1826 -0
  98. package/dist/components/ic/VectorInputController.svelte.d.ts +47 -0
  99. package/dist/components/ic/index.d.ts +39 -0
  100. package/dist/components/ic/index.js +24 -0
  101. package/dist/components/ic/shared/CategoryTabs.svelte +40 -0
  102. package/dist/components/ic/shared/CategoryTabs.svelte.d.ts +25 -0
  103. package/dist/components/ic/shared/ItemGrid.svelte +181 -0
  104. package/dist/components/ic/shared/ItemGrid.svelte.d.ts +35 -0
  105. package/dist/components/ic/shared/RecentItemsSection.svelte +260 -0
  106. package/dist/components/ic/shared/RecentItemsSection.svelte.d.ts +35 -0
  107. package/dist/components/ic/shared/index.d.ts +8 -0
  108. package/dist/components/ic/shared/index.js +9 -0
  109. package/dist/components/icons/addnew.svelte +21 -0
  110. package/dist/components/icons/addnew.svelte.d.ts +20 -0
  111. package/dist/components/icons/drag.svelte +29 -0
  112. package/dist/components/icons/drag.svelte.d.ts +20 -0
  113. package/dist/components/icons/drag.svg +1 -0
  114. package/dist/components/icons/locked.svelte +4 -0
  115. package/dist/components/icons/locked.svelte.d.ts +26 -0
  116. package/dist/components/icons/locked.svg +4 -0
  117. package/dist/components/icons/ok.svelte +20 -0
  118. package/dist/components/icons/ok.svelte.d.ts +20 -0
  119. package/dist/components/icons/ok.svg +11 -0
  120. package/dist/components/icons/unlocked.svelte +4 -0
  121. package/dist/components/icons/unlocked.svelte.d.ts +26 -0
  122. package/dist/components/icons/unlocked.svg +4 -0
  123. package/dist/components/icons/x.svelte +14 -0
  124. package/dist/components/icons/x.svelte.d.ts +20 -0
  125. package/dist/components/icons/x.svg +5 -0
  126. package/dist/components/ui/arrows/OpacitySliderArrows.svelte +43 -0
  127. package/dist/components/ui/arrows/OpacitySliderArrows.svelte.d.ts +23 -0
  128. package/dist/components/ui/checkerboard-background/CheckerboardBackground.svelte +15 -0
  129. package/dist/components/ui/checkerboard-background/CheckerboardBackground.svelte.d.ts +20 -0
  130. package/dist/config.d.ts +5 -0
  131. package/dist/config.js +19 -0
  132. package/dist/index.d.ts +4 -0
  133. package/dist/index.js +8 -0
  134. package/dist/stores/userSession.d.ts +7 -0
  135. package/dist/stores/userSession.js +28 -0
  136. package/dist/utils/FontManager.d.ts +276 -0
  137. package/dist/utils/FontManager.js +1283 -0
  138. package/dist/utils/MediaManager.d.ts +35 -0
  139. package/dist/utils/MediaManager.js +59 -0
  140. package/dist/utils/VectorManager.d.ts +190 -0
  141. package/dist/utils/VectorManager.js +754 -0
  142. package/dist/utils/colorAutocomplete.d.ts +10 -0
  143. package/dist/utils/colorAutocomplete.js +28 -0
  144. package/dist/utils/colorNames.d.ts +3 -0
  145. package/dist/utils/colorNames.js +152 -0
  146. package/dist/utils/colorTransparency.d.ts +52 -0
  147. package/dist/utils/colorTransparency.js +114 -0
  148. package/dist/utils/fontUtils.d.ts +34 -0
  149. package/dist/utils/fontUtils.js +132 -0
  150. package/dist/utils/passiveEvents.js +20 -0
  151. package/dist/utils/recentColors.d.ts +10 -0
  152. package/dist/utils/recentColors.js +63 -0
  153. package/dist/utils/skipFonts.d.ts +3 -0
  154. package/dist/utils/skipFonts.js +49 -0
  155. package/dist/utils/vectorUtils.d.ts +34 -0
  156. package/dist/utils/vectorUtils.js +71 -0
  157. package/dist/utils.d.ts +11 -0
  158. package/dist/utils.js +38 -0
  159. package/package.json +134 -74
  160. package/.babelrc +0 -10
  161. package/.bowerrc +0 -4
  162. package/.nvmrc +0 -1
  163. package/Gruntfile.coffee +0 -69
  164. package/bower.json +0 -28
  165. package/css/browser/entries/activateable.styl +0 -29
  166. package/css/browser/entries/audio.styl +0 -39
  167. package/css/browser/entries/folder.styl +0 -79
  168. package/css/browser/entries/image.styl +0 -26
  169. package/css/browser/entries/index.styl +0 -66
  170. package/css/browser/entries/rss.styl +0 -11
  171. package/css/browser/entries/video.styl +0 -11
  172. package/css/browser/index.styl +0 -86
  173. package/css/browser/intent/index.styl +0 -61
  174. package/css/browser/nav/index.styl +0 -73
  175. package/css/browser/social-browser.styl +0 -23
  176. package/css/controls/clock.styl +0 -110
  177. package/css/controls/config.styl +0 -6
  178. package/css/controls/control-audio-details.styl +0 -63
  179. package/css/controls/control-audio.styl +0 -28
  180. package/css/controls/control-browser.styl +0 -48
  181. package/css/controls/control-color.styl +0 -423
  182. package/css/controls/control-date_time.styl +0 -191
  183. package/css/controls/control-dropdown.styl +0 -79
  184. package/css/controls/control-font.styl +0 -147
  185. package/css/controls/control-image-details.styl +0 -35
  186. package/css/controls/control-image.styl +0 -43
  187. package/css/controls/control-order-picker.styl +0 -29
  188. package/css/controls/control-position.styl +0 -390
  189. package/css/controls/control-range.styl +0 -68
  190. package/css/controls/control-scale.styl +0 -30
  191. package/css/controls/control-slider.styl +0 -38
  192. package/css/controls/control-spinner.styl +0 -39
  193. package/css/controls/control-textarea.styl +0 -52
  194. package/css/controls/control-toggle.styl +0 -34
  195. package/css/controls/control-url.styl +0 -32
  196. package/css/controls/control-video-details.styl +0 -85
  197. package/css/controls/control-video.styl +0 -43
  198. package/css/controls/general.styl +0 -98
  199. package/css/controls/index.styl +0 -25
  200. package/css/editor/colors.styl +0 -7
  201. package/css/editor/content/directinput.styl +0 -47
  202. package/css/editor/content/index.styl +0 -111
  203. package/css/editor/content/message.styl +0 -53
  204. package/css/editor/content/tabs.styl +0 -75
  205. package/css/editor/copied-from-old-style.styl +0 -197
  206. package/css/editor/details/bulk-editor.styl +0 -104
  207. package/css/editor/details/index.styl +0 -21
  208. package/css/editor/details/item.styl +0 -153
  209. package/css/editor/embed.styl +0 -106
  210. package/css/editor/footer.styl +0 -180
  211. package/css/editor/full-editor.styl +0 -16
  212. package/css/editor/index.styl +0 -124
  213. package/css/editor/login-popup.styl +0 -13
  214. package/css/editor/preview.styl +0 -257
  215. package/css/editor/skin/editor/index.styl +0 -54
  216. package/css/editor/skin/editor/tabs.styl +0 -111
  217. package/css/editor/skin/index.styl +0 -138
  218. package/css/editor/skin/popup.styl +0 -152
  219. package/css/editor/skin/presets/dropdown.styl +0 -61
  220. package/css/editor/skin/presets/index.styl +0 -86
  221. package/css/editor/skin/presets/list.styl +0 -244
  222. package/css/editor/tooltips.styl +0 -85
  223. package/css/fonts.styl +0 -47
  224. package/css/icons/BlogvioEditor.dev.svg +0 -112
  225. package/css/icons.styl +0 -16
  226. package/css/img/arrow-right-rounded-v-small.png +0 -0
  227. package/css/img/browser-folder-separator.png +0 -0
  228. package/css/img/calendar-input-icons.png +0 -0
  229. package/css/img/check.png +0 -0
  230. package/css/img/close.png +0 -0
  231. package/css/img/composition/edit-icon.png +0 -0
  232. package/css/img/content/audio-icon.png +0 -0
  233. package/css/img/content/folder-icon.png +0 -0
  234. package/css/img/content/messages/error-background.png +0 -0
  235. package/css/img/content/messages/error-icon.png +0 -0
  236. package/css/img/content/messages/notification-background.png +0 -0
  237. package/css/img/content/messages/notification-icon.png +0 -0
  238. package/css/img/content/no-files-audio.png +0 -0
  239. package/css/img/content/no-files-image.png +0 -0
  240. package/css/img/content/no-files-video.png +0 -0
  241. package/css/img/content/no-files.png +0 -0
  242. package/css/img/content/rss-icon.png +0 -0
  243. package/css/img/content/selected.png +0 -0
  244. package/css/img/content/video-icon.png +0 -0
  245. package/css/img/content/with-control-text.png +0 -0
  246. package/css/img/control-dropdown-arrow.png +0 -0
  247. package/css/img/control-image-valid.png +0 -0
  248. package/css/img/control-position-icon.png +0 -0
  249. package/css/img/control-scale-lock-icon.png +0 -0
  250. package/css/img/control-slider-arrows-hover.png +0 -0
  251. package/css/img/control-slider-arrows.png +0 -0
  252. package/css/img/control-spinner-buttons-hover.png +0 -0
  253. package/css/img/control-spinner-buttons.png +0 -0
  254. package/css/img/control-textarea-bold-active.png +0 -0
  255. package/css/img/control-textarea-bold.png +0 -0
  256. package/css/img/control-textarea-italic-active.png +0 -0
  257. package/css/img/control-textarea-italic.png +0 -0
  258. package/css/img/control-textarea-underline-active.png +0 -0
  259. package/css/img/control-textarea-underline.png +0 -0
  260. package/css/img/custom-checkbox-sprite.png +0 -0
  261. package/css/img/details/item-collapse-icon.png +0 -0
  262. package/css/img/details/item-expand-icon.png +0 -0
  263. package/css/img/details/item-sort-icon.png +0 -0
  264. package/css/img/done-arrow.png +0 -0
  265. package/css/img/fb-logo-icon-w.png +0 -0
  266. package/css/img/grid-icons.png +0 -0
  267. package/css/img/icon-reference.png +0 -0
  268. package/css/img/indicator.png +0 -0
  269. package/css/img/loader.gif +0 -0
  270. package/css/img/loaders/audio-white.png +0 -0
  271. package/css/img/loaders/audio.png +0 -0
  272. package/css/img/loaders/photo-white.png +0 -0
  273. package/css/img/loaders/photo.png +0 -0
  274. package/css/img/loaders/util-white.png +0 -0
  275. package/css/img/loaders/util.png +0 -0
  276. package/css/img/loaders/video-white.png +0 -0
  277. package/css/img/loaders/video.png +0 -0
  278. package/css/img/maximize.png +0 -0
  279. package/css/img/minimize.png +0 -0
  280. package/css/img/next-btn.png +0 -0
  281. package/css/img/search-icon-sprite.png +0 -0
  282. package/css/img/services/blogvio.png +0 -0
  283. package/css/img/services/drive.png +0 -0
  284. package/css/img/services/dropbox-login.png +0 -0
  285. package/css/img/services/dropbox.png +0 -0
  286. package/css/img/services/facebook-login.png +0 -0
  287. package/css/img/services/facebook.png +0 -0
  288. package/css/img/services/flickr-login.png +0 -0
  289. package/css/img/services/flickr.png +0 -0
  290. package/css/img/services/instagram-login.png +0 -0
  291. package/css/img/services/instagram.png +0 -0
  292. package/css/img/services/text.png +0 -0
  293. package/css/img/services/uploads.png +0 -0
  294. package/css/img/services/uploads.svg +0 -689
  295. package/css/img/services/webaddress-bw.png +0 -0
  296. package/css/img/services/webaddress.png +0 -0
  297. package/css/img/services/webadress.png +0 -0
  298. package/css/img/services/websearch.png +0 -0
  299. package/css/img/services/wix.png +0 -0
  300. package/css/img/skin/item-active-indicator.png +0 -0
  301. package/css/img/skin/item-hover-icon.png +0 -0
  302. package/css/img/skin/overwrite.png +0 -0
  303. package/css/img/skin/popup-name-icon.png +0 -0
  304. package/css/img/skin/popup-save.png +0 -0
  305. package/css/img/skin/preset.png +0 -0
  306. package/css/img/skin/presets-arrow-purple.png +0 -0
  307. package/css/img/tw-icon-w.png +0 -0
  308. package/css/img/warning.png +0 -0
  309. package/css/img/white-rounded-check.png +0 -0
  310. package/css/index.styl +0 -9
  311. package/css/mixins.styl +0 -62
  312. package/css/scrollable.styl +0 -101
  313. package/karma.conf.js +0 -73
  314. package/lib/control.js +0 -1
  315. package/lib/controls.js +0 -1
  316. package/lib/core.editor.js +0 -4
  317. package/lib/core.js +0 -1
  318. package/lib/core.vendor.js +0 -3
  319. package/lib/dev/control.js +0 -845
  320. package/lib/dev/controls.js +0 -7774
  321. package/lib/dev/core.editor.js +0 -6439
  322. package/lib/dev/core.js +0 -1486
  323. package/lib/dev/core.vendor.js +0 -10708
  324. package/lib/dev/editor.css +0 -166
  325. package/lib/dev/editor.js +0 -29710
  326. package/lib/dev/editor.vendor.js +0 -15119
  327. package/lib/dev/jquery.nanoscroller.js.map +0 -10
  328. package/lib/editor.css +0 -167
  329. package/lib/editor.js +0 -49
  330. package/lib/editor.vendor.js +0 -11
  331. package/src/api/index.coffee +0 -23
  332. package/src/api/mixin.coffee +0 -89
  333. package/src/browser/controller/entry/audio.coffee +0 -38
  334. package/src/browser/controller/entry/button.coffee +0 -16
  335. package/src/browser/controller/entry/file.coffee +0 -35
  336. package/src/browser/controller/entry/folder.coffee +0 -14
  337. package/src/browser/controller/entry/image.coffee +0 -24
  338. package/src/browser/controller/entry/index.coffee +0 -18
  339. package/src/browser/controller/entry/rss.coffee +0 -5
  340. package/src/browser/controller/entry/video.coffee +0 -4
  341. package/src/browser/controller/index.coffee +0 -289
  342. package/src/browser/controller/instagram.coffee +0 -129
  343. package/src/browser/controller/navbar.coffee +0 -48
  344. package/src/browser/controller/social.coffee +0 -213
  345. package/src/browser/model/entry.coffee +0 -18
  346. package/src/browser/model/index.coffee +0 -34
  347. package/src/core/controller/font-loader.coffee +0 -65
  348. package/src/core/controller/lazyload.coffee +0 -14
  349. package/src/core/controller/overlay.coffee +0 -146
  350. package/src/core/controller/popup.coffee +0 -36
  351. package/src/core/controller/scrollable.coffee +0 -68
  352. package/src/core/controls/audio.coffee +0 -56
  353. package/src/core/controls/browser.coffee +0 -271
  354. package/src/core/controls/color.coffee +0 -121
  355. package/src/core/controls/date-time/calendar/index.coffee +0 -99
  356. package/src/core/controls/date-time/calendar/months.coffee +0 -52
  357. package/src/core/controls/date-time/calendar/years.coffee +0 -58
  358. package/src/core/controls/date-time/clock.coffee +0 -62
  359. package/src/core/controls/date-time/helper.coffee +0 -31
  360. package/src/core/controls/date-time/index.coffee +0 -62
  361. package/src/core/controls/date-time/popup.coffee +0 -56
  362. package/src/core/controls/details/audio.coffee +0 -33
  363. package/src/core/controls/details/image.coffee +0 -19
  364. package/src/core/controls/details/video.coffee +0 -14
  365. package/src/core/controls/dropdown.coffee +0 -100
  366. package/src/core/controls/font/font-item.coffee +0 -22
  367. package/src/core/controls/font/font-list.coffee +0 -108
  368. package/src/core/controls/font/fonts-popup.coffee +0 -91
  369. package/src/core/controls/font/index.coffee +0 -66
  370. package/src/core/controls/image.coffee +0 -37
  371. package/src/core/controls/index.coffee +0 -88
  372. package/src/core/controls/orderPicker.coffee +0 -93
  373. package/src/core/controls/position/grid-panel.coffee +0 -75
  374. package/src/core/controls/position/index.coffee +0 -98
  375. package/src/core/controls/position/panel.coffee +0 -68
  376. package/src/core/controls/position/pixel-panel.coffee +0 -54
  377. package/src/core/controls/position/popup.coffee +0 -63
  378. package/src/core/controls/position/reference-panel.coffee +0 -26
  379. package/src/core/controls/range.coffee +0 -191
  380. package/src/core/controls/rss.coffee +0 -16
  381. package/src/core/controls/scale.coffee +0 -78
  382. package/src/core/controls/slider.coffee +0 -122
  383. package/src/core/controls/stepper.coffee +0 -97
  384. package/src/core/controls/text.coffee +0 -54
  385. package/src/core/controls/textarea.coffee +0 -78
  386. package/src/core/controls/toggle.coffee +0 -29
  387. package/src/core/controls/url.coffee +0 -88
  388. package/src/core/controls/video.coffee +0 -9
  389. package/src/core/embed/api.js +0 -178
  390. package/src/core/embed/controller.js +0 -331
  391. package/src/core/models/composition.coffee +0 -178
  392. package/src/core/models/content.coffee +0 -79
  393. package/src/core/models/skin.coffee +0 -91
  394. package/src/core/models/user.coffee +0 -6
  395. package/src/core/models/widget.coffee +0 -88
  396. package/src/core/router/index.coffee +0 -44
  397. package/src/core/services/container/index.js +0 -18
  398. package/src/core/services/container/instance.js +0 -3
  399. package/src/core/services/content.js +0 -80
  400. package/src/core/services/instagram.coffee +0 -47
  401. package/src/core/services/mixin/events.js +0 -17
  402. package/src/core/services/service.js +0 -1
  403. package/src/core/services/sounds.js +0 -81
  404. package/src/core/services/uploads.js +0 -299
  405. package/src/core/utils/popup.coffee +0 -67
  406. package/src/core/utils/should-show.coffee +0 -12
  407. package/src/core/views/audio-details.pug +0 -9
  408. package/src/core/views/audio.pug +0 -7
  409. package/src/core/views/browser.pug +0 -4
  410. package/src/core/views/color.pug +0 -8
  411. package/src/core/views/date-time/calendar.pug +0 -3
  412. package/src/core/views/date-time/clock.pug +0 -12
  413. package/src/core/views/date-time/grid.pug +0 -6
  414. package/src/core/views/date-time/input.pug +0 -4
  415. package/src/core/views/date-time/table.pug +0 -6
  416. package/src/core/views/dropdown.pug +0 -9
  417. package/src/core/views/font/font-item.pug +0 -3
  418. package/src/core/views/font/fonts-list.pug +0 -7
  419. package/src/core/views/font/fonts-popup.pug +0 -5
  420. package/src/core/views/font/index.pug +0 -7
  421. package/src/core/views/image-details.pug +0 -6
  422. package/src/core/views/image.pug +0 -5
  423. package/src/core/views/input-layout.pug +0 -15
  424. package/src/core/views/order-items.pug +0 -7
  425. package/src/core/views/order-picker.pug +0 -7
  426. package/src/core/views/pixelpanel.pug +0 -69
  427. package/src/core/views/position.pug +0 -10
  428. package/src/core/views/range.pug +0 -9
  429. package/src/core/views/scale.pug +0 -7
  430. package/src/core/views/slider.pug +0 -6
  431. package/src/core/views/stepper.pug +0 -6
  432. package/src/core/views/text.pug +0 -4
  433. package/src/core/views/textarea.pug +0 -8
  434. package/src/core/views/toggle.pug +0 -5
  435. package/src/core/views/video-details.pug +0 -7
  436. package/src/core/views/video.pug +0 -4
  437. package/src/core/widget/index.coffee +0 -66
  438. package/src/editor/content/browser/dropzone.html +0 -268
  439. package/src/editor/content/browser/file.html +0 -124
  440. package/src/editor/content/browser/scroll-pane.html +0 -32
  441. package/src/editor/content/browser/service.html +0 -53
  442. package/src/editor/content/browser/upload.coffee +0 -44
  443. package/src/editor/content/browser/upload.html +0 -439
  444. package/src/editor/content/index.coffee +0 -294
  445. package/src/editor/content/input/field.coffee +0 -45
  446. package/src/editor/content/input/index.coffee +0 -115
  447. package/src/editor/content/service/base/photoitem.coffee +0 -49
  448. package/src/editor/content/service/cache.coffee +0 -20
  449. package/src/editor/content/service/default.coffee +0 -59
  450. package/src/editor/content/service/dropbox.coffee +0 -71
  451. package/src/editor/content/service/facebook.coffee +0 -143
  452. package/src/editor/content/service/flickr.coffee +0 -85
  453. package/src/editor/content/service/google-drive-sdk.coffee +0 -18
  454. package/src/editor/content/service/google-drive.coffee +0 -144
  455. package/src/editor/content/service/instagram-social.coffee +0 -84
  456. package/src/editor/content/service/instagram.coffee +0 -168
  457. package/src/editor/content/service/share-popup.coffee +0 -15
  458. package/src/editor/content/service/soundcloud.coffee +0 -163
  459. package/src/editor/content/tab.coffee +0 -27
  460. package/src/editor/details/bulk-editor/attributes-panel.coffee +0 -11
  461. package/src/editor/details/bulk-editor/index.coffee +0 -86
  462. package/src/editor/details/index.coffee +0 -156
  463. package/src/editor/details/item/attributes.coffee +0 -45
  464. package/src/editor/details/item/index.coffee +0 -82
  465. package/src/editor/editor.coffee +0 -274
  466. package/src/editor/footer/breadcrumb.coffee +0 -17
  467. package/src/editor/footer/index.coffee +0 -36
  468. package/src/editor/index.coffee +0 -79
  469. package/src/editor/listeners/embed-listener.coffee +0 -143
  470. package/src/editor/login-popup.coffee +0 -29
  471. package/src/editor/notification-controller.coffee +0 -35
  472. package/src/editor/popup.coffee +0 -68
  473. package/src/editor/remote-preview.coffee +0 -68
  474. package/src/editor/save/index.coffee +0 -62
  475. package/src/editor/skin/delete.coffee +0 -33
  476. package/src/editor/skin/editor/index.coffee +0 -188
  477. package/src/editor/skin/editor/panel.coffee +0 -37
  478. package/src/editor/skin/index.coffee +0 -126
  479. package/src/editor/skin/save.coffee +0 -58
  480. package/src/editor/skin/selector/index.coffee +0 -59
  481. package/src/editor/skin/selector/item.coffee +0 -123
  482. package/src/editor/skin/selector/list.coffee +0 -97
  483. package/src/editor/views/embed.pug +0 -10
  484. package/src/editor/views/loginbutton.pug +0 -8
  485. package/src/editor/views/popup.pug +0 -17
  486. package/src/editor/views/presets.pug +0 -8
  487. package/src/editor/views/presetslist-header.pug +0 -8
  488. package/src/editor/views/skinitem.pug +0 -13
  489. package/src/modules/control.js +0 -3
  490. package/src/modules/controls.js +0 -29
  491. package/src/modules/core.js +0 -19
  492. package/src/modules/editor.js +0 -80
  493. package/test/config.js +0 -3
  494. package/test/core/models/skin-spec.js +0 -209
  495. package/webpack.config.js +0 -46
  496. package/webpack.config.prod.js +0 -9
  497. /package/{src/core/views/date-time/popup.pug → dist/utils/passiveEvents.d.ts} +0 -0
@@ -0,0 +1,724 @@
1
+ <script lang="ts">
2
+ /**
3
+ * BrowserInputController Component
4
+ * A specialized input controller for file browsing and media preview functionality.
5
+ * Handles various file types (image, video, audio, document) with appropriate previews
6
+ * and playback controls.
7
+ */
8
+
9
+ // Svelte imports
10
+ import { onDestroy, tick } from 'svelte';
11
+
12
+ // Shadcn UI Components
13
+ import { Portal, Tooltip } from '@widgetic/design-system/components';
14
+ import { ThumbHashImage } from "@widgetic/design-system/components";
15
+ import { FileBrowser, setFileBrowserUploadConfig, persistentSelectStore } from '@widgetic/file-browser';
16
+ import X from '../icons/x.svelte';
17
+ // console.log("BrowserInputController - Tooltip:", Tooltip);
18
+
19
+ // config imports
20
+ import type { InputControllerConfig } from './index';
21
+
22
+ // utils imports
23
+ import MediaManager from '../../utils/MediaManager';
24
+
25
+ // Static asset imports (bundled via Vite, works when imported as library)
26
+ import icAudio from '../../assets/icons/ic-browser/audio.svg?url';
27
+ import icDocument from '../../assets/icons/ic-browser/document.svg?url';
28
+ import icError from '../../assets/icons/ic-browser/error.svg?url';
29
+ import icFolder from '../../assets/icons/ic-browser/folder.svg?url';
30
+ import icPlayerPause from '../../assets/icons/ic-browser/player-pause.svg?url';
31
+ import icPlayerPlay from '../../assets/icons/ic-browser/player-play.svg?url';
32
+
33
+ import { InputControllerHeader } from './index';
34
+
35
+ interface FileValue {
36
+ id: string;
37
+ file: string;
38
+ url: string;
39
+ hash?: string; // Add hash property for ThumbHash
40
+ }
41
+
42
+ // Component props with default values
43
+ export let header: { label: string; helpText?: string } | undefined = undefined;
44
+ export let label: string = '';
45
+ export let value: string | FileValue = '';
46
+ export let onChange: (newValue: string | FileValue) => void = () => {};
47
+ export let portalTarget: string | HTMLElement = 'portal-element';
48
+
49
+ /** Full-panel overlay when portaled to props-editor panel (not document body). */
50
+ $: fillEditorPanel =
51
+ portalTarget === 'props-editor-file-browser-portal' ||
52
+ (portalTarget instanceof HTMLElement &&
53
+ portalTarget.id === 'props-editor-file-browser-portal');
54
+ export let config: InputControllerConfig = {};
55
+
56
+ // Extract allowed file types from config or default to all files
57
+ const fileTypes = config.fileTypes || ['*'];
58
+
59
+ // Media element references for audio/video playback
60
+ let audioElement: HTMLAudioElement | null = null;
61
+ let videoElement: HTMLVideoElement | null = null;
62
+ let isPlaying = false;
63
+
64
+ // Add loading state
65
+ let isChecking = true;
66
+ let hasError = false;
67
+ let isFileBrowserOpen = false;
68
+
69
+ let mouseX = 0;
70
+ let mouseY = 0;
71
+ let showHelp = false;
72
+ let showHelpTimeout: ReturnType<typeof setTimeout>;
73
+
74
+ function handleMouseEnter(event: MouseEvent) {
75
+ mouseX = event.clientX;
76
+ mouseY = event.clientY;
77
+ showHelpTimeout = setTimeout(() => {
78
+ showHelp = true;
79
+ }, 250);
80
+ }
81
+
82
+ function handleMouseMove(event: MouseEvent) {
83
+ mouseX = event.clientX;
84
+ mouseY = event.clientY;
85
+ }
86
+
87
+ function handleMouseLeave() {
88
+ clearTimeout(showHelpTimeout);
89
+ showHelp = false;
90
+ }
91
+
92
+
93
+ /**
94
+ * Extracts filename from file value
95
+ * @param value - String path or FileValue object
96
+ * @returns Filename or empty string if invalid
97
+ */
98
+ function getFileName(value: string | FileValue | null | undefined): string {
99
+ if (!value) return '';
100
+ if (typeof value === 'object' && value.file) {
101
+ return value.file;
102
+ }
103
+ if (typeof value === 'string') {
104
+ try {
105
+ const parts = value.split('/');
106
+ return parts[parts.length - 1] || '';
107
+ } catch (error) {
108
+ console.error('Error extracting filename:', error);
109
+ return '';
110
+ }
111
+ }
112
+ return '';
113
+ }
114
+
115
+ /**
116
+ * Gets the URL for preview from the value
117
+ * @param value - String path or FileValue object
118
+ * @returns URL for preview
119
+ */
120
+ function getPreviewUrl(value: string | FileValue | null | undefined): string {
121
+ if (!value) return '';
122
+ if (typeof value === 'object' && value.url) {
123
+ return value.url;
124
+ }
125
+ return typeof value === 'string' ? value : '';
126
+ }
127
+
128
+ /**
129
+ * Gets the thumbnail URL for a video
130
+ * @param videoUrl - URL of the video file
131
+ * @returns URL of the thumbnail
132
+ */
133
+ function getVideoThumbnailUrl(videoUrl: string): string {
134
+ return videoUrl.replace(/\.[^/.]+$/, '.png');
135
+ }
136
+
137
+ /**
138
+ * Determines the type of file based on its extension
139
+ * @param path - File path to analyze
140
+ * @returns File type category or 'unknown'
141
+ */
142
+ function getFileType(path: string | null | undefined): 'image' | 'video' | 'audio' | 'document' | 'unknown' {
143
+ if (!path || typeof path !== 'string') return 'unknown';
144
+
145
+ const ext = path.split('.').pop()?.toLowerCase() || '';
146
+ if (['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(ext)) return 'image';
147
+ if (['mp4', 'webm', 'ogg'].includes(ext)) return 'video';
148
+ if (['mp3', 'wav', 'ogg'].includes(ext)) return 'audio';
149
+ if (['pdf', 'doc', 'docx', 'txt'].includes(ext)) return 'document';
150
+ return 'unknown';
151
+ }
152
+
153
+ /** Only embedded iframe mode (URL params) sets upload config here; standalone uses parent +page sync. */
154
+ function syncFileBrowserUploadConfigIfEmbedded() {
155
+ if (typeof window === 'undefined') return;
156
+ const params = new URLSearchParams(window.location.search);
157
+ const apiUrl = params.get('apiUrl');
158
+ const token = params.get('token');
159
+ if (!apiUrl || !token) return;
160
+ const widgetId = params.get('widgetId');
161
+ const apiBase = apiUrl.replace(/\/+$/, '');
162
+ setFileBrowserUploadConfig({
163
+ apiBasePath: `${apiBase}/v1`,
164
+ accessToken: token.replace(/^Bearer\s+/i, ''),
165
+ contextType: 'content-property',
166
+ source: 'file-browser-upload',
167
+ widgetId: widgetId || undefined,
168
+ });
169
+ }
170
+
171
+ /**
172
+ * Opens the shared FileBrowser package and lets the user select one file.
173
+ */
174
+ function getPortalHost(): HTMLElement | null {
175
+ if (portalTarget instanceof HTMLElement) return portalTarget;
176
+ if (typeof document === 'undefined') return null;
177
+ return document.getElementById('props-editor-file-browser-portal');
178
+ }
179
+
180
+ function setPortalHostInteractive(active: boolean) {
181
+ const host = getPortalHost();
182
+ if (host) {
183
+ host.classList.toggle('pointer-events-none', !active);
184
+ host.classList.toggle('pointer-events-auto', active);
185
+ }
186
+ }
187
+
188
+ async function openFileBrowser() {
189
+ try {
190
+ syncFileBrowserUploadConfigIfEmbedded();
191
+ console.log('BrowserInputController: opening file browser', {
192
+ fileTypes,
193
+ id: typeof value === 'object' ? value.id : undefined,
194
+ batch: 1
195
+ });
196
+ isFileBrowserOpen = true;
197
+ await tick();
198
+ syncFileBrowserInitialSelection();
199
+ setPortalHostInteractive(true);
200
+ } catch (error) {
201
+ console.error('Error opening file browser:', error);
202
+ }
203
+ }
204
+
205
+ function closeFileBrowser() {
206
+ isFileBrowserOpen = false;
207
+ setPortalHostInteractive(false);
208
+ }
209
+
210
+ function handleFileBrowserSelect(event: CustomEvent<{ files?: Array<FileValue & { name?: string; thumbnail?: string }> }>) {
211
+ try {
212
+ const selectedFile = event.detail?.files?.[0];
213
+ if (!selectedFile) {
214
+ console.log('BrowserInputController: file browser selection skipped, no file selected');
215
+ return;
216
+ }
217
+
218
+ const nextValue: FileValue = {
219
+ id: selectedFile.id,
220
+ file: selectedFile.file || selectedFile.name || '',
221
+ url: selectedFile.url,
222
+ hash: selectedFile.hash
223
+ };
224
+
225
+ console.log('BrowserInputController: selected file', {
226
+ id: nextValue.id,
227
+ file: nextValue.file,
228
+ url: nextValue.url
229
+ });
230
+
231
+ value = nextValue;
232
+ onChange(nextValue);
233
+ closeFileBrowser();
234
+ } catch (error) {
235
+ console.error('BrowserInputController: failed to select file', error);
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Toggles playback for audio/video elements
241
+ * Uses MediaManager to ensure only one plays at a time
242
+ */
243
+ function togglePlayback() {
244
+ if (audioElement) {
245
+ if (isPlaying) {
246
+ MediaManager.pause(audioElement);
247
+ } else {
248
+ MediaManager.play(audioElement);
249
+ }
250
+ isPlaying = !isPlaying;
251
+ } else if (videoElement) {
252
+ if (isPlaying) {
253
+ MediaManager.pause(videoElement);
254
+ } else {
255
+ MediaManager.play(videoElement);
256
+ }
257
+ isPlaying = !isPlaying;
258
+ }
259
+ }
260
+
261
+ onDestroy(() => {
262
+ clearTimeout(showHelpTimeout);
263
+ setPortalHostInteractive(false);
264
+ if (audioElement) {
265
+ MediaManager.cleanup(audioElement);
266
+ audioElement = null;
267
+ }
268
+ if (videoElement) {
269
+ MediaManager.cleanup(videoElement);
270
+ videoElement = null;
271
+ }
272
+ });
273
+
274
+ /**
275
+ * Checks if an image URL is accessible using Image() constructor
276
+ * to avoid CORS issues with external services (picsum.photos, etc.)
277
+ */
278
+ async function checkFileExists(url: string): Promise<boolean> {
279
+ return new Promise((resolve) => {
280
+ const img = new Image();
281
+ img.onload = () => resolve(true);
282
+ img.onerror = () => resolve(false);
283
+ img.src = url;
284
+ setTimeout(() => resolve(false), 5000);
285
+ });
286
+ }
287
+
288
+ // Update error state handling
289
+ async function updateErrorState(url: string) {
290
+ isChecking = true;
291
+ if (!url) {
292
+ hasError = true;
293
+ isChecking = false;
294
+ return;
295
+ }
296
+ hasError = !(await checkFileExists(url));
297
+ isChecking = false;
298
+ }
299
+
300
+ // Watch previewUrl changes
301
+ $: if (previewUrl) {
302
+ updateErrorState(previewUrl);
303
+ } else {
304
+ hasError = false;
305
+ isChecking = false;
306
+ }
307
+
308
+ /**
309
+ * Trims a string to a maximum length and adds ellipsis if needed
310
+ * @param str - String to trim
311
+ * @param maxLength - Maximum length before trimming
312
+ * @returns Trimmed string with ellipsis if needed
313
+ */
314
+ function trimString(str: string, maxLength: number = 30): string {
315
+ if (str.length <= maxLength) return str;
316
+ return str.substring(0, maxLength - 3) + '...';
317
+ }
318
+
319
+ // Update the reactive statement to use trimString
320
+ $: displayLabel = value ? trimString(getFileName(value)) : (header?.label || label);
321
+ $: previewUrl = getPreviewUrl(value);
322
+
323
+ // Add hash extraction helper
324
+ function getThumbHash(value: string | FileValue | null | undefined): string | undefined {
325
+ if (!value) return undefined;
326
+ if (typeof value === 'object' && 'hash' in value) {
327
+ return value.hash;
328
+ }
329
+ return undefined;
330
+ }
331
+
332
+ // Update the reactive statement to use getThumbHash
333
+ $: thumbHash = getThumbHash(value);
334
+
335
+ // Add event listeners for media elements
336
+ function setupMediaElement(element: HTMLMediaElement) {
337
+ if (!element) return;
338
+
339
+ element.addEventListener('play', () => {
340
+ console.log('Media started playing');
341
+ isPlaying = true;
342
+ });
343
+
344
+ element.addEventListener('pause', () => {
345
+ console.log('Media paused');
346
+ isPlaying = false;
347
+ });
348
+
349
+ element.addEventListener('ended', () => {
350
+ console.log('Media ended');
351
+ isPlaying = false;
352
+ });
353
+
354
+ // Add listener for when the media is stopped externally
355
+ element.addEventListener('timeupdate', () => {
356
+ if (element.paused && isPlaying) {
357
+ isPlaying = false;
358
+ }
359
+ });
360
+ }
361
+
362
+ // Update bindings to setup media elements
363
+ $: if (audioElement) setupMediaElement(audioElement);
364
+ $: if (videoElement) setupMediaElement(videoElement);
365
+
366
+ // Add placeholder text logic
367
+ function getAddToEditorLabelSingular(fileTypes: string[]): string {
368
+ if (!fileTypes || fileTypes.includes('*')) return 'Use file';
369
+ const type = fileTypes[0].split('/')[0];
370
+ switch (type) {
371
+ case 'image': return 'Use image';
372
+ case 'video': return 'Use video';
373
+ case 'audio': return 'Use audio';
374
+ case 'document': return 'Use document';
375
+ default: return 'Use file';
376
+ }
377
+ }
378
+
379
+ function getCurrentFileId(): string | null {
380
+ if (value && typeof value === 'object' && value.id) return value.id;
381
+ return null;
382
+ }
383
+
384
+ function syncFileBrowserInitialSelection() {
385
+ const fileId = getCurrentFileId();
386
+ persistentSelectStore.clearSelections(fileBrowserFilter);
387
+ if (fileId) {
388
+ persistentSelectStore.setSelections(fileBrowserFilter, [fileId]);
389
+ if (fileBrowserFilter !== 'all') {
390
+ persistentSelectStore.setSelections('all', [fileId]);
391
+ }
392
+ }
393
+ }
394
+
395
+ function getPlaceholderText(fileTypes: string[]): string {
396
+ if (!fileTypes || fileTypes.includes('*')) return 'Add file...';
397
+ const type = fileTypes[0].split('/')[0];
398
+ switch (type) {
399
+ case 'image': return 'Add image...';
400
+ case 'video': return 'Add video...';
401
+ case 'audio': return 'Add audio...';
402
+ case 'document': return 'Add docs...';
403
+ default: return 'Add file...';
404
+ }
405
+ }
406
+
407
+ function getInitialFileBrowserFilter(fileTypes: string[]): 'all' | 'image' | 'video' | 'audio' | 'document' | 'font' | 'svg' {
408
+ if (!fileTypes || fileTypes.includes('*')) return 'all';
409
+ const type = fileTypes[0].split('/')[0];
410
+ if (fileTypes[0] === 'image/svg+xml') return 'svg';
411
+ if (type === 'font') return 'font';
412
+ if (['image', 'video', 'audio'].includes(type)) return type as 'image' | 'video' | 'audio';
413
+ if (type === 'application' || type === 'text') return 'document';
414
+ return 'all';
415
+ }
416
+
417
+ $: fileBrowserFilter = getInitialFileBrowserFilter(fileTypes);
418
+ $: fileBrowserRestrictUpload = fileBrowserFilter !== 'all';
419
+ $: fileBrowserAddToEditorLabelSingular = getAddToEditorLabelSingular(fileTypes);
420
+
421
+ function handleContentRemoval(e: MouseEvent) {
422
+ e.stopPropagation();
423
+ e.preventDefault();
424
+ value = '';
425
+ onChange('');
426
+ isPlaying = false;
427
+ hasError = false;
428
+
429
+ if (audioElement) {
430
+ MediaManager.pause(audioElement);
431
+ MediaManager.cleanup(audioElement);
432
+ audioElement = null;
433
+ }
434
+ if (videoElement) {
435
+ MediaManager.pause(videoElement);
436
+ MediaManager.cleanup(videoElement);
437
+ videoElement = null;
438
+ }
439
+
440
+ onChange('');
441
+ }
442
+
443
+ function handleControllerClick(e: MouseEvent) {
444
+ const target = e.target as HTMLElement;
445
+ if (target.closest('.browser-ic-clear-btn')) return;
446
+ openFileBrowser();
447
+ }
448
+ </script>
449
+
450
+ <!-- Main container with updated styling -->
451
+ <div class="flex flex-col gap-2 widgetic-colors">
452
+ <div class="flex items-center w-full relative">
453
+ <div class="flex-1 min-w-0">
454
+ <InputControllerHeader label={header?.label || label} helpText={header?.helpText} />
455
+ </div>
456
+
457
+ <div class="absolute right-0">
458
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
459
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
460
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
461
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
462
+ <div
463
+ class="browser-input-controller-field cursor-pointer h-[48px] w-[185px] rounded-large border border-grey2 flex items-center bg-grey1 transition-colors duration-200 hover:border-forest-green relative"
464
+ on:click={handleControllerClick}
465
+ on:keydown={(e) => e.key === 'Enter' && openFileBrowser()}
466
+ role="button"
467
+ tabindex={0}
468
+ >
469
+ <!-- File name or placeholder -->
470
+ <div class="browser-input-controller-label flex-1 min-w-0 px-4 flex items-center h-full">
471
+ <span class="subtext {value ? 'text-grey7' : 'text-grey3'} truncate inline-block">
472
+ {value ? getFileName(value) : getPlaceholderText(fileTypes)}
473
+ </span>
474
+ </div>
475
+
476
+ <!-- Preview area -->
477
+ <div class="flex-none h-full flex items-center pr-[16px]">
478
+ {#if isChecking}
479
+ <!-- Loading state -->
480
+ <div class="w-8 h-7 bg-gray-100 rounded-lg"></div>
481
+ {:else if previewUrl && !hasError}
482
+ <!-- File preview content -->
483
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
484
+ {#if getFileType(previewUrl) === 'image'}
485
+ <div
486
+ class="w-8 h-7 overflow-hidden rounded-lg bg-gray-100 cursor-pointer hover:opacity-80 transition-opacity"
487
+ on:click|stopPropagation={() => window.open(previewUrl, '_blank')}
488
+ role="button"
489
+ tabindex={0}
490
+ >
491
+ {#if thumbHash}
492
+ <div on:error={() => hasError = true}>
493
+ <ThumbHashImage
494
+ src={previewUrl || ''}
495
+ alt={displayLabel || ''}
496
+ thumbhash={thumbHash}
497
+ class_="w-full h-full object-cover"
498
+ />
499
+ </div>
500
+ {:else}
501
+ <img
502
+ src={previewUrl}
503
+ alt={displayLabel || ''}
504
+ class="w-full h-full object-cover"
505
+ on:error={() => hasError = true}
506
+ />
507
+ {/if}
508
+ </div>
509
+ {:else if getFileType(previewUrl) === 'video'}
510
+ <div
511
+ class="relative w-8 h-7 overflow-hidden rounded-lg cursor-pointer"
512
+ on:click|stopPropagation={togglePlayback}
513
+ role="button"
514
+ tabindex={0}
515
+ >
516
+ <!-- Video element always present -->
517
+ <!-- svelte-ignore a11y-media-has-caption -->
518
+ <video
519
+ bind:this={videoElement}
520
+ src={previewUrl}
521
+ class="absolute inset-0 w-full h-full object-cover {!isPlaying ? 'opacity-0' : 'opacity-100'}"
522
+ on:error={() => hasError = true}
523
+ >
524
+ <track kind="captions" />
525
+ </video>
526
+
527
+ <!-- Thumbnail image shown when not playing -->
528
+ {#if !isPlaying}
529
+ {#if thumbHash}
530
+ <div on:error={() => hasError = true}>
531
+ <ThumbHashImage
532
+ src={getVideoThumbnailUrl(previewUrl) || ''}
533
+ alt={displayLabel || ''}
534
+ thumbhash={thumbHash}
535
+ class_="w-full h-full object-cover hover:opacity-80 transition-opacity"
536
+ />
537
+ </div>
538
+ {:else}
539
+ <img
540
+ src={getVideoThumbnailUrl(previewUrl)}
541
+ alt={getFileName(value)}
542
+ class="w-full h-full object-cover hover:opacity-80 transition-opacity"
543
+ on:error={() => hasError = true}
544
+ />
545
+ {/if}
546
+ {/if}
547
+
548
+ <!-- Controls overlay -->
549
+ <div
550
+ class="absolute inset-0 flex items-center justify-center {!isPlaying ? 'bg-black bg-opacity-30' : 'bg-transparent hover:bg-black hover:bg-opacity-30'}"
551
+ >
552
+ <img
553
+ src={isPlaying ? icPlayerPause : icPlayerPlay}
554
+ alt={isPlaying ? "Pause" : "Play"}
555
+ class="w-5 h-5 {isPlaying ? 'opacity-0 hover:opacity-100' : 'opacity-100'} transition-opacity"
556
+ />
557
+ </div>
558
+ </div>
559
+ {:else if getFileType(previewUrl) === 'audio'}
560
+ <div
561
+ class="relative w-8 h-7 cursor-pointer"
562
+ on:click|stopPropagation={togglePlayback}
563
+ role="button"
564
+ tabindex={0}
565
+ >
566
+ <!-- Audio icon -->
567
+ <img
568
+ src={icAudio}
569
+ alt={getFileName(value)}
570
+ class="w-full h-full object-contain"
571
+ />
572
+
573
+ <!-- Audio element hidden but needed for playback -->
574
+ <!-- svelte-ignore a11y-media-has-caption -->
575
+ <audio
576
+ bind:this={audioElement}
577
+ src={previewUrl}
578
+ class="hidden"
579
+ on:error={() => hasError = true}
580
+ >
581
+ <track kind="captions" />
582
+ </audio>
583
+
584
+ <!-- Controls overlay -->
585
+ <div
586
+ class="absolute inset-0 flex items-center justify-center"
587
+ >
588
+ <img
589
+ src={isPlaying ? icPlayerPause : icPlayerPlay}
590
+ alt={isPlaying ? "Pause" : "Play"}
591
+ class="w-5 h-5"
592
+ />
593
+ </div>
594
+ </div>
595
+ {:else if getFileType(previewUrl) === 'document'}
596
+ <div
597
+ class="cursor-pointer hover:opacity-80 transition-opacity"
598
+ on:click|stopPropagation={() => window.open(previewUrl, '_blank')}
599
+ role="button"
600
+ tabindex={0}
601
+ >
602
+ <img
603
+ src={icDocument}
604
+ alt={displayLabel}
605
+ class="w-8 h-7 object-contain"
606
+ />
607
+ </div>
608
+ {:else}
609
+ <img
610
+ src={icFolder}
611
+ alt={displayLabel}
612
+ class="w-8 h-7 object-contain"
613
+ />
614
+ {/if}
615
+ {:else if previewUrl}
616
+ <!-- Error state -->
617
+ <img
618
+ src={icError}
619
+ alt="File not found"
620
+ class="w-8 h-7 object-contain"
621
+ />
622
+ {:else}
623
+ <!-- Empty state -->
624
+ <img
625
+ src={icFolder}
626
+ alt="Empty folder"
627
+ class="w-8 h-7 object-contain"
628
+ />
629
+ {/if}
630
+
631
+ <!-- Close button - moved outside the content conditions -->
632
+ {#if value}
633
+ <button
634
+ type="button"
635
+ class="browser-ic-clear-btn absolute top-[-4px] right-[-4px] w-4 h-4 rounded-full hover:bg-grey2 transition-colors flex items-center justify-center"
636
+ on:click={handleContentRemoval}
637
+ aria-label="Clear file"
638
+ >
639
+ <div class="w-4 h-4 flex items-center justify-center">
640
+ <X class="w-4! h-4!" />
641
+ </div>
642
+ </button>
643
+ {/if}
644
+ </div>
645
+ </div>
646
+ </div>
647
+ </div>
648
+ </div>
649
+
650
+ {#if isFileBrowserOpen}
651
+ <Portal target={portalTarget}>
652
+ <div
653
+ class="browser-input-file-browser-overlay pointer-events-auto absolute inset-0 z-[999999] flex flex-col overflow-hidden bg-black/40"
654
+ class:p-3={!fillEditorPanel}
655
+ >
656
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
657
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
658
+ <div class="browser-input-file-browser-backdrop absolute inset-0" on:click={closeFileBrowser}></div>
659
+
660
+ <div
661
+ class="browser-input-file-browser-dialog browser-input-file-browser-dialog-animate relative z-[999999] flex min-h-0 w-full flex-col overflow-hidden bg-white"
662
+ class:absolute={fillEditorPanel}
663
+ class:inset-0={fillEditorPanel}
664
+ class:h-full={fillEditorPanel}
665
+ class:max-w-none={fillEditorPanel}
666
+ class:rounded-none={fillEditorPanel}
667
+ class:shadow-none={fillEditorPanel}
668
+ class:max-w-[520px]={!fillEditorPanel}
669
+ class:flex-1={!fillEditorPanel}
670
+ class:self-center={!fillEditorPanel}
671
+ class:mx-auto={!fillEditorPanel}
672
+ class:rounded-large={!fillEditorPanel}
673
+ class:shadow-2xl={!fillEditorPanel}
674
+ >
675
+ <div class="browser-input-file-browser-header flex h-[57px] shrink-0 items-center justify-between border-b border-grey2 px-4 py-3">
676
+ <span class="body-medium text-grey7">Select file</span>
677
+ <button
678
+ type="button"
679
+ class="browser-input-file-browser-close inline-flex h-8 w-8 items-center justify-center rounded-full hover:bg-grey2"
680
+ on:click={closeFileBrowser}
681
+ aria-label="Close file browser"
682
+ >
683
+ <X class="h-4! w-4!" />
684
+ </button>
685
+ </div>
686
+
687
+ <div class="browser-input-file-browser-body flex min-h-0 flex-1 flex-col overflow-hidden">
688
+ <FileBrowser
689
+ class="h-full min-h-0 flex-1"
690
+ instanceId={`props-editor-browser-input-${fileBrowserFilter}`}
691
+ initialFilter={fileBrowserFilter}
692
+ restrictUpload={fileBrowserRestrictUpload}
693
+ useDemoContent={false}
694
+ allowSelecting={true}
695
+ showAddToEditor={true}
696
+ maxSelections={1}
697
+ activeFileId={getCurrentFileId()}
698
+ addToEditorLabel={fileBrowserAddToEditorLabelSingular}
699
+ on:select={handleFileBrowserSelect}
700
+ />
701
+ </div>
702
+ </div>
703
+ </div>
704
+ </Portal>
705
+ {/if}
706
+
707
+ <style>
708
+ .browser-input-file-browser-dialog-animate {
709
+ transform-origin: center center;
710
+ animation: browser-input-fb-scale-in 0.22s cubic-bezier(0.4, 0, 0.2, 1);
711
+ }
712
+
713
+ @keyframes browser-input-fb-scale-in {
714
+ from {
715
+ transform: scale(0.94);
716
+ opacity: 0;
717
+ }
718
+ to {
719
+ transform: scale(1);
720
+ opacity: 1;
721
+ }
722
+ }
723
+ </style>
724
+