@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.
- package/README.md +245 -0
- package/dist/assets/fonts.json +331 -0
- package/dist/assets/icons/ic-browser/audio.svg +7 -0
- package/dist/assets/icons/ic-browser/document.svg +11 -0
- package/dist/assets/icons/ic-browser/error.svg +5 -0
- package/dist/assets/icons/ic-browser/folder.svg +28 -0
- package/dist/assets/icons/ic-browser/player-pause.svg +1 -0
- package/dist/assets/icons/ic-browser/player-play.svg +1 -0
- package/dist/assets/icons/ic-browser/trash.svg +1 -0
- package/dist/assets/icons/ic-fixed-position/background-deselected.svg +3 -0
- package/dist/assets/icons/ic-fixed-position/background-selected.svg +3 -0
- package/dist/assets/icons/ic-fixed-position/bottom-left-background-deselected.svg +3 -0
- package/dist/assets/icons/ic-fixed-position/bottom-left-background-selected.svg +3 -0
- package/dist/assets/icons/ic-fixed-position/bottom-left-icon.svg +4 -0
- package/dist/assets/icons/ic-fixed-position/bottom-right-background-deselected.svg +3 -0
- package/dist/assets/icons/ic-fixed-position/bottom-right-background-selected.svg +3 -0
- package/dist/assets/icons/ic-fixed-position/bottom-right-icon.svg +4 -0
- package/dist/assets/icons/ic-fixed-position/center-bottom-icon.svg +5 -0
- package/dist/assets/icons/ic-fixed-position/center-center-icon.svg +3 -0
- package/dist/assets/icons/ic-fixed-position/center-left-icon.svg +5 -0
- package/dist/assets/icons/ic-fixed-position/center-right-icon.svg +5 -0
- package/dist/assets/icons/ic-fixed-position/center-top-icon.svg +5 -0
- package/dist/assets/icons/ic-fixed-position/top-left-background-deselected.svg +3 -0
- package/dist/assets/icons/ic-fixed-position/top-left-background-selected.svg +3 -0
- package/dist/assets/icons/ic-fixed-position/top-left-icon.svg +4 -0
- package/dist/assets/icons/ic-fixed-position/top-right-background-deselected.svg +3 -0
- package/dist/assets/icons/ic-fixed-position/top-right-background-selected.svg +3 -0
- package/dist/assets/icons/ic-fixed-position/top-right-icon.svg +4 -0
- package/dist/assets/icons/trash.svg +1 -0
- package/dist/components/MockWidget.svelte +108 -0
- package/dist/components/MockWidget.svelte.d.ts +22 -0
- package/dist/components/WidgetPreview.svelte +852 -0
- package/dist/components/WidgetPreview.svelte.d.ts +100 -0
- package/dist/components/color-select/ColorSelect.svelte +258 -0
- package/dist/components/color-select/ColorSelect.svelte.d.ts +42 -0
- package/dist/components/color-select/color.d.ts +25 -0
- package/dist/components/color-select/color.js +21 -0
- package/dist/components/color-select/constants.d.ts +5 -0
- package/dist/components/color-select/constants.js +5 -0
- package/dist/components/color-select/render.d.ts +5 -0
- package/dist/components/color-select/render.js +77 -0
- package/dist/components/color-select/shaders.d.ts +3 -0
- package/dist/components/color-select/shaders.js +8 -0
- package/dist/components/editors/EmbedEditor.svelte +700 -0
- package/dist/components/editors/EmbedEditor.svelte.d.ts +50 -0
- package/dist/components/editors/PropsEditor.svelte +3952 -0
- package/dist/components/editors/PropsEditor.svelte.d.ts +62 -0
- package/dist/components/editors/props-editor.css +73 -0
- package/dist/components/ic/AngleInputController.svelte +276 -0
- package/dist/components/ic/AngleInputController.svelte.d.ts +26 -0
- package/dist/components/ic/BrowserInputController.svelte +724 -0
- package/dist/components/ic/BrowserInputController.svelte.d.ts +39 -0
- package/dist/components/ic/CheckboxInputController.svelte +203 -0
- package/dist/components/ic/CheckboxInputController.svelte.d.ts +41 -0
- package/dist/components/ic/ColorPickerInputController.svelte +1584 -0
- package/dist/components/ic/ColorPickerInputController.svelte.d.ts +50 -0
- package/dist/components/ic/DateFieldInputController.svelte +453 -0
- package/dist/components/ic/DateFieldInputController.svelte.d.ts +35 -0
- package/dist/components/ic/DatePickerInputController.svelte +364 -0
- package/dist/components/ic/DatePickerInputController.svelte.d.ts +28 -0
- package/dist/components/ic/DropdownInputController.svelte +226 -0
- package/dist/components/ic/DropdownInputController.svelte.d.ts +43 -0
- package/dist/components/ic/FixedPositionInputController.svelte +353 -0
- package/dist/components/ic/FixedPositionInputController.svelte.d.ts +23 -0
- package/dist/components/ic/FontInputController.svelte +2062 -0
- package/dist/components/ic/FontInputController.svelte.d.ts +47 -0
- package/dist/components/ic/InputControllerHeader.svelte +147 -0
- package/dist/components/ic/InputControllerHeader.svelte.d.ts +23 -0
- package/dist/components/ic/NumberControls.svelte +299 -0
- package/dist/components/ic/NumberControls.svelte.d.ts +30 -0
- package/dist/components/ic/NumberInputController.svelte +397 -0
- package/dist/components/ic/NumberInputController.svelte.d.ts +30 -0
- package/dist/components/ic/PositionInputController.svelte +252 -0
- package/dist/components/ic/PositionInputController.svelte.d.ts +37 -0
- package/dist/components/ic/RadioGroupInputController.svelte +162 -0
- package/dist/components/ic/RadioGroupInputController.svelte.d.ts +38 -0
- package/dist/components/ic/RangeCalendarInputController.svelte +262 -0
- package/dist/components/ic/RangeCalendarInputController.svelte.d.ts +32 -0
- package/dist/components/ic/RoundedCornersInputController.svelte +469 -0
- package/dist/components/ic/RoundedCornersInputController.svelte.d.ts +37 -0
- package/dist/components/ic/SliderInputController.svelte +411 -0
- package/dist/components/ic/SliderInputController.svelte.d.ts +46 -0
- package/dist/components/ic/SliderRangeInputController.svelte +155 -0
- package/dist/components/ic/SliderRangeInputController.svelte.d.ts +33 -0
- package/dist/components/ic/SwitchInputController.svelte +107 -0
- package/dist/components/ic/SwitchInputController.svelte.d.ts +24 -0
- package/dist/components/ic/TagsInputController.svelte +125 -0
- package/dist/components/ic/TagsInputController.svelte.d.ts +27 -0
- package/dist/components/ic/TextAreaInputController.svelte +1804 -0
- package/dist/components/ic/TextAreaInputController.svelte.d.ts +13 -0
- package/dist/components/ic/TextAreaPreviewInputController.svelte +476 -0
- package/dist/components/ic/TextAreaPreviewInputController.svelte.d.ts +28 -0
- package/dist/components/ic/TextInputController.svelte +70 -0
- package/dist/components/ic/TextInputController.svelte.d.ts +30 -0
- package/dist/components/ic/TimeInputController.svelte +434 -0
- package/dist/components/ic/TimeInputController.svelte.d.ts +25 -0
- package/dist/components/ic/VectorInputController.svelte +1826 -0
- package/dist/components/ic/VectorInputController.svelte.d.ts +47 -0
- package/dist/components/ic/index.d.ts +39 -0
- package/dist/components/ic/index.js +24 -0
- package/dist/components/ic/shared/CategoryTabs.svelte +40 -0
- package/dist/components/ic/shared/CategoryTabs.svelte.d.ts +25 -0
- package/dist/components/ic/shared/ItemGrid.svelte +181 -0
- package/dist/components/ic/shared/ItemGrid.svelte.d.ts +35 -0
- package/dist/components/ic/shared/RecentItemsSection.svelte +260 -0
- package/dist/components/ic/shared/RecentItemsSection.svelte.d.ts +35 -0
- package/dist/components/ic/shared/index.d.ts +8 -0
- package/dist/components/ic/shared/index.js +9 -0
- package/dist/components/icons/addnew.svelte +21 -0
- package/dist/components/icons/addnew.svelte.d.ts +20 -0
- package/dist/components/icons/drag.svelte +29 -0
- package/dist/components/icons/drag.svelte.d.ts +20 -0
- package/dist/components/icons/drag.svg +1 -0
- package/dist/components/icons/locked.svelte +4 -0
- package/dist/components/icons/locked.svelte.d.ts +26 -0
- package/dist/components/icons/locked.svg +4 -0
- package/dist/components/icons/ok.svelte +20 -0
- package/dist/components/icons/ok.svelte.d.ts +20 -0
- package/dist/components/icons/ok.svg +11 -0
- package/dist/components/icons/unlocked.svelte +4 -0
- package/dist/components/icons/unlocked.svelte.d.ts +26 -0
- package/dist/components/icons/unlocked.svg +4 -0
- package/dist/components/icons/x.svelte +14 -0
- package/dist/components/icons/x.svelte.d.ts +20 -0
- package/dist/components/icons/x.svg +5 -0
- package/dist/components/ui/arrows/OpacitySliderArrows.svelte +43 -0
- package/dist/components/ui/arrows/OpacitySliderArrows.svelte.d.ts +23 -0
- package/dist/components/ui/checkerboard-background/CheckerboardBackground.svelte +15 -0
- package/dist/components/ui/checkerboard-background/CheckerboardBackground.svelte.d.ts +20 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +19 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +8 -0
- package/dist/stores/userSession.d.ts +7 -0
- package/dist/stores/userSession.js +28 -0
- package/dist/utils/FontManager.d.ts +276 -0
- package/dist/utils/FontManager.js +1283 -0
- package/dist/utils/MediaManager.d.ts +35 -0
- package/dist/utils/MediaManager.js +59 -0
- package/dist/utils/VectorManager.d.ts +190 -0
- package/dist/utils/VectorManager.js +754 -0
- package/dist/utils/colorAutocomplete.d.ts +10 -0
- package/dist/utils/colorAutocomplete.js +28 -0
- package/dist/utils/colorNames.d.ts +3 -0
- package/dist/utils/colorNames.js +152 -0
- package/dist/utils/colorTransparency.d.ts +52 -0
- package/dist/utils/colorTransparency.js +114 -0
- package/dist/utils/fontUtils.d.ts +34 -0
- package/dist/utils/fontUtils.js +132 -0
- package/dist/utils/passiveEvents.js +20 -0
- package/dist/utils/recentColors.d.ts +10 -0
- package/dist/utils/recentColors.js +63 -0
- package/dist/utils/skipFonts.d.ts +3 -0
- package/dist/utils/skipFonts.js +49 -0
- package/dist/utils/vectorUtils.d.ts +34 -0
- package/dist/utils/vectorUtils.js +71 -0
- package/dist/utils.d.ts +11 -0
- package/dist/utils.js +38 -0
- package/package.json +134 -74
- package/.babelrc +0 -10
- package/.bowerrc +0 -4
- package/.nvmrc +0 -1
- package/Gruntfile.coffee +0 -69
- package/bower.json +0 -28
- package/css/browser/entries/activateable.styl +0 -29
- package/css/browser/entries/audio.styl +0 -39
- package/css/browser/entries/folder.styl +0 -79
- package/css/browser/entries/image.styl +0 -26
- package/css/browser/entries/index.styl +0 -66
- package/css/browser/entries/rss.styl +0 -11
- package/css/browser/entries/video.styl +0 -11
- package/css/browser/index.styl +0 -86
- package/css/browser/intent/index.styl +0 -61
- package/css/browser/nav/index.styl +0 -73
- package/css/browser/social-browser.styl +0 -23
- package/css/controls/clock.styl +0 -110
- package/css/controls/config.styl +0 -6
- package/css/controls/control-audio-details.styl +0 -63
- package/css/controls/control-audio.styl +0 -28
- package/css/controls/control-browser.styl +0 -48
- package/css/controls/control-color.styl +0 -423
- package/css/controls/control-date_time.styl +0 -191
- package/css/controls/control-dropdown.styl +0 -79
- package/css/controls/control-font.styl +0 -147
- package/css/controls/control-image-details.styl +0 -35
- package/css/controls/control-image.styl +0 -43
- package/css/controls/control-order-picker.styl +0 -29
- package/css/controls/control-position.styl +0 -390
- package/css/controls/control-range.styl +0 -68
- package/css/controls/control-scale.styl +0 -30
- package/css/controls/control-slider.styl +0 -38
- package/css/controls/control-spinner.styl +0 -39
- package/css/controls/control-textarea.styl +0 -52
- package/css/controls/control-toggle.styl +0 -34
- package/css/controls/control-url.styl +0 -32
- package/css/controls/control-video-details.styl +0 -85
- package/css/controls/control-video.styl +0 -43
- package/css/controls/general.styl +0 -98
- package/css/controls/index.styl +0 -25
- package/css/editor/colors.styl +0 -7
- package/css/editor/content/directinput.styl +0 -47
- package/css/editor/content/index.styl +0 -111
- package/css/editor/content/message.styl +0 -53
- package/css/editor/content/tabs.styl +0 -75
- package/css/editor/copied-from-old-style.styl +0 -197
- package/css/editor/details/bulk-editor.styl +0 -104
- package/css/editor/details/index.styl +0 -21
- package/css/editor/details/item.styl +0 -153
- package/css/editor/embed.styl +0 -106
- package/css/editor/footer.styl +0 -180
- package/css/editor/full-editor.styl +0 -16
- package/css/editor/index.styl +0 -124
- package/css/editor/login-popup.styl +0 -13
- package/css/editor/preview.styl +0 -257
- package/css/editor/skin/editor/index.styl +0 -54
- package/css/editor/skin/editor/tabs.styl +0 -111
- package/css/editor/skin/index.styl +0 -138
- package/css/editor/skin/popup.styl +0 -152
- package/css/editor/skin/presets/dropdown.styl +0 -61
- package/css/editor/skin/presets/index.styl +0 -86
- package/css/editor/skin/presets/list.styl +0 -244
- package/css/editor/tooltips.styl +0 -85
- package/css/fonts.styl +0 -47
- package/css/icons/BlogvioEditor.dev.svg +0 -112
- package/css/icons.styl +0 -16
- package/css/img/arrow-right-rounded-v-small.png +0 -0
- package/css/img/browser-folder-separator.png +0 -0
- package/css/img/calendar-input-icons.png +0 -0
- package/css/img/check.png +0 -0
- package/css/img/close.png +0 -0
- package/css/img/composition/edit-icon.png +0 -0
- package/css/img/content/audio-icon.png +0 -0
- package/css/img/content/folder-icon.png +0 -0
- package/css/img/content/messages/error-background.png +0 -0
- package/css/img/content/messages/error-icon.png +0 -0
- package/css/img/content/messages/notification-background.png +0 -0
- package/css/img/content/messages/notification-icon.png +0 -0
- package/css/img/content/no-files-audio.png +0 -0
- package/css/img/content/no-files-image.png +0 -0
- package/css/img/content/no-files-video.png +0 -0
- package/css/img/content/no-files.png +0 -0
- package/css/img/content/rss-icon.png +0 -0
- package/css/img/content/selected.png +0 -0
- package/css/img/content/video-icon.png +0 -0
- package/css/img/content/with-control-text.png +0 -0
- package/css/img/control-dropdown-arrow.png +0 -0
- package/css/img/control-image-valid.png +0 -0
- package/css/img/control-position-icon.png +0 -0
- package/css/img/control-scale-lock-icon.png +0 -0
- package/css/img/control-slider-arrows-hover.png +0 -0
- package/css/img/control-slider-arrows.png +0 -0
- package/css/img/control-spinner-buttons-hover.png +0 -0
- package/css/img/control-spinner-buttons.png +0 -0
- package/css/img/control-textarea-bold-active.png +0 -0
- package/css/img/control-textarea-bold.png +0 -0
- package/css/img/control-textarea-italic-active.png +0 -0
- package/css/img/control-textarea-italic.png +0 -0
- package/css/img/control-textarea-underline-active.png +0 -0
- package/css/img/control-textarea-underline.png +0 -0
- package/css/img/custom-checkbox-sprite.png +0 -0
- package/css/img/details/item-collapse-icon.png +0 -0
- package/css/img/details/item-expand-icon.png +0 -0
- package/css/img/details/item-sort-icon.png +0 -0
- package/css/img/done-arrow.png +0 -0
- package/css/img/fb-logo-icon-w.png +0 -0
- package/css/img/grid-icons.png +0 -0
- package/css/img/icon-reference.png +0 -0
- package/css/img/indicator.png +0 -0
- package/css/img/loader.gif +0 -0
- package/css/img/loaders/audio-white.png +0 -0
- package/css/img/loaders/audio.png +0 -0
- package/css/img/loaders/photo-white.png +0 -0
- package/css/img/loaders/photo.png +0 -0
- package/css/img/loaders/util-white.png +0 -0
- package/css/img/loaders/util.png +0 -0
- package/css/img/loaders/video-white.png +0 -0
- package/css/img/loaders/video.png +0 -0
- package/css/img/maximize.png +0 -0
- package/css/img/minimize.png +0 -0
- package/css/img/next-btn.png +0 -0
- package/css/img/search-icon-sprite.png +0 -0
- package/css/img/services/blogvio.png +0 -0
- package/css/img/services/drive.png +0 -0
- package/css/img/services/dropbox-login.png +0 -0
- package/css/img/services/dropbox.png +0 -0
- package/css/img/services/facebook-login.png +0 -0
- package/css/img/services/facebook.png +0 -0
- package/css/img/services/flickr-login.png +0 -0
- package/css/img/services/flickr.png +0 -0
- package/css/img/services/instagram-login.png +0 -0
- package/css/img/services/instagram.png +0 -0
- package/css/img/services/text.png +0 -0
- package/css/img/services/uploads.png +0 -0
- package/css/img/services/uploads.svg +0 -689
- package/css/img/services/webaddress-bw.png +0 -0
- package/css/img/services/webaddress.png +0 -0
- package/css/img/services/webadress.png +0 -0
- package/css/img/services/websearch.png +0 -0
- package/css/img/services/wix.png +0 -0
- package/css/img/skin/item-active-indicator.png +0 -0
- package/css/img/skin/item-hover-icon.png +0 -0
- package/css/img/skin/overwrite.png +0 -0
- package/css/img/skin/popup-name-icon.png +0 -0
- package/css/img/skin/popup-save.png +0 -0
- package/css/img/skin/preset.png +0 -0
- package/css/img/skin/presets-arrow-purple.png +0 -0
- package/css/img/tw-icon-w.png +0 -0
- package/css/img/warning.png +0 -0
- package/css/img/white-rounded-check.png +0 -0
- package/css/index.styl +0 -9
- package/css/mixins.styl +0 -62
- package/css/scrollable.styl +0 -101
- package/karma.conf.js +0 -73
- package/lib/control.js +0 -1
- package/lib/controls.js +0 -1
- package/lib/core.editor.js +0 -4
- package/lib/core.js +0 -1
- package/lib/core.vendor.js +0 -3
- package/lib/dev/control.js +0 -845
- package/lib/dev/controls.js +0 -7774
- package/lib/dev/core.editor.js +0 -6439
- package/lib/dev/core.js +0 -1486
- package/lib/dev/core.vendor.js +0 -10708
- package/lib/dev/editor.css +0 -166
- package/lib/dev/editor.js +0 -29710
- package/lib/dev/editor.vendor.js +0 -15119
- package/lib/dev/jquery.nanoscroller.js.map +0 -10
- package/lib/editor.css +0 -167
- package/lib/editor.js +0 -49
- package/lib/editor.vendor.js +0 -11
- package/src/api/index.coffee +0 -23
- package/src/api/mixin.coffee +0 -89
- package/src/browser/controller/entry/audio.coffee +0 -38
- package/src/browser/controller/entry/button.coffee +0 -16
- package/src/browser/controller/entry/file.coffee +0 -35
- package/src/browser/controller/entry/folder.coffee +0 -14
- package/src/browser/controller/entry/image.coffee +0 -24
- package/src/browser/controller/entry/index.coffee +0 -18
- package/src/browser/controller/entry/rss.coffee +0 -5
- package/src/browser/controller/entry/video.coffee +0 -4
- package/src/browser/controller/index.coffee +0 -289
- package/src/browser/controller/instagram.coffee +0 -129
- package/src/browser/controller/navbar.coffee +0 -48
- package/src/browser/controller/social.coffee +0 -213
- package/src/browser/model/entry.coffee +0 -18
- package/src/browser/model/index.coffee +0 -34
- package/src/core/controller/font-loader.coffee +0 -65
- package/src/core/controller/lazyload.coffee +0 -14
- package/src/core/controller/overlay.coffee +0 -146
- package/src/core/controller/popup.coffee +0 -36
- package/src/core/controller/scrollable.coffee +0 -68
- package/src/core/controls/audio.coffee +0 -56
- package/src/core/controls/browser.coffee +0 -271
- package/src/core/controls/color.coffee +0 -121
- package/src/core/controls/date-time/calendar/index.coffee +0 -99
- package/src/core/controls/date-time/calendar/months.coffee +0 -52
- package/src/core/controls/date-time/calendar/years.coffee +0 -58
- package/src/core/controls/date-time/clock.coffee +0 -62
- package/src/core/controls/date-time/helper.coffee +0 -31
- package/src/core/controls/date-time/index.coffee +0 -62
- package/src/core/controls/date-time/popup.coffee +0 -56
- package/src/core/controls/details/audio.coffee +0 -33
- package/src/core/controls/details/image.coffee +0 -19
- package/src/core/controls/details/video.coffee +0 -14
- package/src/core/controls/dropdown.coffee +0 -100
- package/src/core/controls/font/font-item.coffee +0 -22
- package/src/core/controls/font/font-list.coffee +0 -108
- package/src/core/controls/font/fonts-popup.coffee +0 -91
- package/src/core/controls/font/index.coffee +0 -66
- package/src/core/controls/image.coffee +0 -37
- package/src/core/controls/index.coffee +0 -88
- package/src/core/controls/orderPicker.coffee +0 -93
- package/src/core/controls/position/grid-panel.coffee +0 -75
- package/src/core/controls/position/index.coffee +0 -98
- package/src/core/controls/position/panel.coffee +0 -68
- package/src/core/controls/position/pixel-panel.coffee +0 -54
- package/src/core/controls/position/popup.coffee +0 -63
- package/src/core/controls/position/reference-panel.coffee +0 -26
- package/src/core/controls/range.coffee +0 -191
- package/src/core/controls/rss.coffee +0 -16
- package/src/core/controls/scale.coffee +0 -78
- package/src/core/controls/slider.coffee +0 -122
- package/src/core/controls/stepper.coffee +0 -97
- package/src/core/controls/text.coffee +0 -54
- package/src/core/controls/textarea.coffee +0 -78
- package/src/core/controls/toggle.coffee +0 -29
- package/src/core/controls/url.coffee +0 -88
- package/src/core/controls/video.coffee +0 -9
- package/src/core/embed/api.js +0 -178
- package/src/core/embed/controller.js +0 -331
- package/src/core/models/composition.coffee +0 -178
- package/src/core/models/content.coffee +0 -79
- package/src/core/models/skin.coffee +0 -91
- package/src/core/models/user.coffee +0 -6
- package/src/core/models/widget.coffee +0 -88
- package/src/core/router/index.coffee +0 -44
- package/src/core/services/container/index.js +0 -18
- package/src/core/services/container/instance.js +0 -3
- package/src/core/services/content.js +0 -80
- package/src/core/services/instagram.coffee +0 -47
- package/src/core/services/mixin/events.js +0 -17
- package/src/core/services/service.js +0 -1
- package/src/core/services/sounds.js +0 -81
- package/src/core/services/uploads.js +0 -299
- package/src/core/utils/popup.coffee +0 -67
- package/src/core/utils/should-show.coffee +0 -12
- package/src/core/views/audio-details.pug +0 -9
- package/src/core/views/audio.pug +0 -7
- package/src/core/views/browser.pug +0 -4
- package/src/core/views/color.pug +0 -8
- package/src/core/views/date-time/calendar.pug +0 -3
- package/src/core/views/date-time/clock.pug +0 -12
- package/src/core/views/date-time/grid.pug +0 -6
- package/src/core/views/date-time/input.pug +0 -4
- package/src/core/views/date-time/table.pug +0 -6
- package/src/core/views/dropdown.pug +0 -9
- package/src/core/views/font/font-item.pug +0 -3
- package/src/core/views/font/fonts-list.pug +0 -7
- package/src/core/views/font/fonts-popup.pug +0 -5
- package/src/core/views/font/index.pug +0 -7
- package/src/core/views/image-details.pug +0 -6
- package/src/core/views/image.pug +0 -5
- package/src/core/views/input-layout.pug +0 -15
- package/src/core/views/order-items.pug +0 -7
- package/src/core/views/order-picker.pug +0 -7
- package/src/core/views/pixelpanel.pug +0 -69
- package/src/core/views/position.pug +0 -10
- package/src/core/views/range.pug +0 -9
- package/src/core/views/scale.pug +0 -7
- package/src/core/views/slider.pug +0 -6
- package/src/core/views/stepper.pug +0 -6
- package/src/core/views/text.pug +0 -4
- package/src/core/views/textarea.pug +0 -8
- package/src/core/views/toggle.pug +0 -5
- package/src/core/views/video-details.pug +0 -7
- package/src/core/views/video.pug +0 -4
- package/src/core/widget/index.coffee +0 -66
- package/src/editor/content/browser/dropzone.html +0 -268
- package/src/editor/content/browser/file.html +0 -124
- package/src/editor/content/browser/scroll-pane.html +0 -32
- package/src/editor/content/browser/service.html +0 -53
- package/src/editor/content/browser/upload.coffee +0 -44
- package/src/editor/content/browser/upload.html +0 -439
- package/src/editor/content/index.coffee +0 -294
- package/src/editor/content/input/field.coffee +0 -45
- package/src/editor/content/input/index.coffee +0 -115
- package/src/editor/content/service/base/photoitem.coffee +0 -49
- package/src/editor/content/service/cache.coffee +0 -20
- package/src/editor/content/service/default.coffee +0 -59
- package/src/editor/content/service/dropbox.coffee +0 -71
- package/src/editor/content/service/facebook.coffee +0 -143
- package/src/editor/content/service/flickr.coffee +0 -85
- package/src/editor/content/service/google-drive-sdk.coffee +0 -18
- package/src/editor/content/service/google-drive.coffee +0 -144
- package/src/editor/content/service/instagram-social.coffee +0 -84
- package/src/editor/content/service/instagram.coffee +0 -168
- package/src/editor/content/service/share-popup.coffee +0 -15
- package/src/editor/content/service/soundcloud.coffee +0 -163
- package/src/editor/content/tab.coffee +0 -27
- package/src/editor/details/bulk-editor/attributes-panel.coffee +0 -11
- package/src/editor/details/bulk-editor/index.coffee +0 -86
- package/src/editor/details/index.coffee +0 -156
- package/src/editor/details/item/attributes.coffee +0 -45
- package/src/editor/details/item/index.coffee +0 -82
- package/src/editor/editor.coffee +0 -274
- package/src/editor/footer/breadcrumb.coffee +0 -17
- package/src/editor/footer/index.coffee +0 -36
- package/src/editor/index.coffee +0 -79
- package/src/editor/listeners/embed-listener.coffee +0 -143
- package/src/editor/login-popup.coffee +0 -29
- package/src/editor/notification-controller.coffee +0 -35
- package/src/editor/popup.coffee +0 -68
- package/src/editor/remote-preview.coffee +0 -68
- package/src/editor/save/index.coffee +0 -62
- package/src/editor/skin/delete.coffee +0 -33
- package/src/editor/skin/editor/index.coffee +0 -188
- package/src/editor/skin/editor/panel.coffee +0 -37
- package/src/editor/skin/index.coffee +0 -126
- package/src/editor/skin/save.coffee +0 -58
- package/src/editor/skin/selector/index.coffee +0 -59
- package/src/editor/skin/selector/item.coffee +0 -123
- package/src/editor/skin/selector/list.coffee +0 -97
- package/src/editor/views/embed.pug +0 -10
- package/src/editor/views/loginbutton.pug +0 -8
- package/src/editor/views/popup.pug +0 -17
- package/src/editor/views/presets.pug +0 -8
- package/src/editor/views/presetslist-header.pug +0 -8
- package/src/editor/views/skinitem.pug +0 -13
- package/src/modules/control.js +0 -3
- package/src/modules/controls.js +0 -29
- package/src/modules/core.js +0 -19
- package/src/modules/editor.js +0 -80
- package/test/config.js +0 -3
- package/test/core/models/skin-spec.js +0 -209
- package/webpack.config.js +0 -46
- package/webpack.config.prod.js +0 -9
- /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
|
+
|