@widgetic/editor 3.11.3 → 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,852 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount, onDestroy, createEventDispatcher, tick } from 'svelte';
|
|
3
|
+
import { GenerateLoader } from '@widgetic/design-system/components';
|
|
4
|
+
|
|
5
|
+
const dispatch = createEventDispatcher<{
|
|
6
|
+
load: { src: string | null };
|
|
7
|
+
error: { src: string | null };
|
|
8
|
+
refresh: void;
|
|
9
|
+
openInTab: void;
|
|
10
|
+
resize: { width: number; height: number };
|
|
11
|
+
mobileViewport: { width: number; height: number };
|
|
12
|
+
desktopViewport: void;
|
|
13
|
+
iframeLoad: Event;
|
|
14
|
+
iframeError: Event;
|
|
15
|
+
retry: void;
|
|
16
|
+
fixErrors: void;
|
|
17
|
+
viewErrors: void;
|
|
18
|
+
retryPreview: void;
|
|
19
|
+
}>();
|
|
20
|
+
|
|
21
|
+
/** standalone = resolve URL + postMessage internally; controlled = parent supplies src/state */
|
|
22
|
+
export let mode: 'standalone' | 'controlled' = 'standalone';
|
|
23
|
+
|
|
24
|
+
let className = '';
|
|
25
|
+
export { className as class };
|
|
26
|
+
export let style: string = '';
|
|
27
|
+
|
|
28
|
+
// ── Standalone props (props-editor) ─────────────────────────────────────
|
|
29
|
+
export let widget: any = null;
|
|
30
|
+
export let apiBaseUrl: string = '';
|
|
31
|
+
export let widgetBuilderUrl: string = '';
|
|
32
|
+
export let designValues: any = {};
|
|
33
|
+
export let contentValues: any = {};
|
|
34
|
+
|
|
35
|
+
// ── Controlled props (widget-creator) ───────────────────────────────────
|
|
36
|
+
export let src: string | null = null;
|
|
37
|
+
export let displayUrl: string | null = null;
|
|
38
|
+
export let previewLoading: boolean = false;
|
|
39
|
+
export let previewHydrating: boolean = false;
|
|
40
|
+
export let previewError: string | null = null;
|
|
41
|
+
export let previewRetryCount: number = 0;
|
|
42
|
+
export let previewHasRuntimeError: boolean = false;
|
|
43
|
+
export let previewRuntimeErrorStatus: number | null = null;
|
|
44
|
+
export let isContentReady: boolean = false;
|
|
45
|
+
export let isLoadingUrl: boolean = false;
|
|
46
|
+
export let isGeneratingCode: boolean = false;
|
|
47
|
+
export let forceMockReady: boolean = false;
|
|
48
|
+
export let debugMode: boolean = false;
|
|
49
|
+
export let iframeReloadKey = 0;
|
|
50
|
+
|
|
51
|
+
// ── Layout / chrome ─────────────────────────────────────────────────────
|
|
52
|
+
export let width: string = '100%';
|
|
53
|
+
export let height: string = '100%';
|
|
54
|
+
export let contentHeight: string = '100%';
|
|
55
|
+
export let showUrlBar: boolean = false;
|
|
56
|
+
export let showUrlBarButtons: boolean = true;
|
|
57
|
+
/** Mobile + desktop viewport buttons in URL bar (before New tab) */
|
|
58
|
+
export let showViewportButtons: boolean = true;
|
|
59
|
+
export let mobileViewportWidth: number = 390;
|
|
60
|
+
export let mobileViewportHeight: number = 667;
|
|
61
|
+
export let enableResize: boolean = false;
|
|
62
|
+
/** Observe stage size and fill it (desktop modal) */
|
|
63
|
+
export let autoFitStage: boolean = false;
|
|
64
|
+
/** No padding/border on preview-content-container — matches widget-creator Edit panel */
|
|
65
|
+
export let compactChrome: boolean = false;
|
|
66
|
+
/** Fixed preview stage size; inner iframe resizes within these bounds */
|
|
67
|
+
export let boundsWidth: number | null = null;
|
|
68
|
+
export let boundsHeight: number | null = null;
|
|
69
|
+
export let resizeWidth: number | null = null;
|
|
70
|
+
export let resizeHeight: number | null = null;
|
|
71
|
+
|
|
72
|
+
export let iframeEl: HTMLIFrameElement | null = null;
|
|
73
|
+
|
|
74
|
+
// ── Standalone internal state ───────────────────────────────────────────
|
|
75
|
+
let internalIframeSrc: string | null = null;
|
|
76
|
+
let iframeLoaded = false;
|
|
77
|
+
let iframeError = false;
|
|
78
|
+
let errorMessage = '';
|
|
79
|
+
let isWidgetPublished = false;
|
|
80
|
+
let triedFallback = false;
|
|
81
|
+
let pendingWidget: any = null;
|
|
82
|
+
let activeWidgetKey: string | null = null;
|
|
83
|
+
let pendingMessages: Record<string, unknown>[] = [];
|
|
84
|
+
let widgetReady = false;
|
|
85
|
+
let isResolvingUrl = false;
|
|
86
|
+
|
|
87
|
+
const MIN_WIDTH = 120;
|
|
88
|
+
const MIN_HEIGHT = 80;
|
|
89
|
+
const HANDLE_MARGIN = 6;
|
|
90
|
+
/** Inset padding so resize handles (-4px) and dimension badge stay inside bounds */
|
|
91
|
+
const RESIZE_PAD_X = 8;
|
|
92
|
+
const RESIZE_PAD_TOP = 8;
|
|
93
|
+
const RESIZE_PAD_BOTTOM = 22;
|
|
94
|
+
let isResizing = false;
|
|
95
|
+
let contentContainerEl: HTMLElement | null = null;
|
|
96
|
+
let resizeStageEl: HTMLElement | null = null;
|
|
97
|
+
let stageResizeObserver: ResizeObserver | null = null;
|
|
98
|
+
|
|
99
|
+
export function getResizeLimits(): { maxWidth: number; maxHeight: number } {
|
|
100
|
+
const stageEl = resizeStageEl ?? contentContainerEl;
|
|
101
|
+
if (stageEl) {
|
|
102
|
+
return {
|
|
103
|
+
maxWidth: Math.max(MIN_WIDTH, stageEl.clientWidth),
|
|
104
|
+
maxHeight: Math.max(MIN_HEIGHT, stageEl.clientHeight),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (hasFixedBounds && boundsWidth != null && boundsHeight != null) {
|
|
108
|
+
return {
|
|
109
|
+
maxWidth: Math.max(MIN_WIDTH, boundsWidth - RESIZE_PAD_X * 2),
|
|
110
|
+
maxHeight: Math.max(MIN_HEIGHT, boundsHeight - RESIZE_PAD_TOP - RESIZE_PAD_BOTTOM),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return { maxWidth: 720, maxHeight: 420 };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Firefox/Chrome skip painting a cross-origin iframe that started at opacity 0 or inside a CSS filter until a reflow (opening DevTools). */
|
|
117
|
+
let iframePaintNudgeGeneration = 0;
|
|
118
|
+
export function nudgeIframePaint(): void {
|
|
119
|
+
const el = iframeEl;
|
|
120
|
+
if (!el) return;
|
|
121
|
+
const generation = ++iframePaintNudgeGeneration;
|
|
122
|
+
// Force a 1px layout twitch, then ALWAYS clear inline size so w-full/h-full can track the wrapper.
|
|
123
|
+
// Restoring a previous pixel width (from overlapping nudges) permanently capped the iframe
|
|
124
|
+
// smaller than the resize stage — widgets looked letterboxed / "not responsive".
|
|
125
|
+
const twitchWidth = Math.max(1, el.offsetWidth + 1);
|
|
126
|
+
el.style.width = `${twitchWidth}px`;
|
|
127
|
+
void el.offsetHeight;
|
|
128
|
+
requestAnimationFrame(() => {
|
|
129
|
+
if (generation !== iframePaintNudgeGeneration) return;
|
|
130
|
+
el.style.width = '';
|
|
131
|
+
el.style.height = '';
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Drop any stuck inline iframe size whenever the stage pixel size changes. */
|
|
136
|
+
$: if (iframeEl && (resizeWidth != null || resizeHeight != null)) {
|
|
137
|
+
iframeEl.style.width = '';
|
|
138
|
+
iframeEl.style.height = '';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Fill the available preview stage (e.g. desktop modal) */
|
|
142
|
+
export function fitToContainer(): void {
|
|
143
|
+
const attemptFit = (attemptsLeft: number) => {
|
|
144
|
+
const stageEl = resizeStageEl ?? contentContainerEl;
|
|
145
|
+
const limits = getResizeLimits();
|
|
146
|
+
const stageReady =
|
|
147
|
+
!!stageEl && stageEl.clientWidth > MIN_WIDTH && stageEl.clientHeight > MIN_HEIGHT;
|
|
148
|
+
if (!stageReady && attemptsLeft > 0) {
|
|
149
|
+
requestAnimationFrame(() => attemptFit(attemptsLeft - 1));
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
resizeWidth = limits.maxWidth;
|
|
153
|
+
resizeHeight = limits.maxHeight;
|
|
154
|
+
dispatch('resize', { width: limits.maxWidth, height: limits.maxHeight });
|
|
155
|
+
requestAnimationFrame(() => nudgeIframePaint());
|
|
156
|
+
};
|
|
157
|
+
attemptFit(24);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
$: effectiveSrc = mode === 'controlled' ? src : internalIframeSrc;
|
|
161
|
+
$: effectiveDisplayUrl =
|
|
162
|
+
mode === 'controlled' ? displayUrl || src : internalIframeSrc;
|
|
163
|
+
$: mountedPreviewSrc =
|
|
164
|
+
effectiveSrc && effectiveSrc !== 'about:blank' ? effectiveSrc : null;
|
|
165
|
+
$: showStandaloneLoading =
|
|
166
|
+
mode === 'standalone' &&
|
|
167
|
+
(isResolvingUrl || !!effectiveSrc) &&
|
|
168
|
+
!iframeLoaded &&
|
|
169
|
+
!iframeError;
|
|
170
|
+
$: showControlledLoading =
|
|
171
|
+
mode === 'controlled' &&
|
|
172
|
+
(previewLoading || previewHydrating) &&
|
|
173
|
+
!previewHasRuntimeError;
|
|
174
|
+
$: showResizeHandles = enableResize && (mode === 'controlled' ? isContentReady : iframeLoaded);
|
|
175
|
+
$: hasFixedBounds = boundsWidth != null && boundsHeight != null;
|
|
176
|
+
$: containerPaddingStyle = enableResize
|
|
177
|
+
? `padding: ${RESIZE_PAD_TOP}px ${RESIZE_PAD_X}px ${RESIZE_PAD_BOTTOM}px ${RESIZE_PAD_X}px;`
|
|
178
|
+
: !hasFixedBounds && !compactChrome && (showUrlBar || mode === 'controlled')
|
|
179
|
+
? `padding: ${HANDLE_MARGIN}px;`
|
|
180
|
+
: '';
|
|
181
|
+
// Always clip — a too-wide iframe must not paint outside the stage when the Creator
|
|
182
|
+
// column shrinks (that looked like the widget being "cut off" on resize).
|
|
183
|
+
$: containerOverflowClass = 'overflow-hidden';
|
|
184
|
+
// Keep pixel preview size inside the stage whenever the parent layout changes.
|
|
185
|
+
$: if (enableResize && (resizeWidth != null || resizeHeight != null)) {
|
|
186
|
+
const { maxWidth, maxHeight } = getResizeLimits();
|
|
187
|
+
if (resizeWidth != null && resizeWidth > maxWidth) resizeWidth = maxWidth;
|
|
188
|
+
if (resizeHeight != null && resizeHeight > maxHeight) resizeHeight = maxHeight;
|
|
189
|
+
}
|
|
190
|
+
$: boundedContainerStyle = hasFixedBounds
|
|
191
|
+
? `width: ${boundsWidth}px; height: ${boundsHeight}px; flex: 0 0 auto;`
|
|
192
|
+
: '';
|
|
193
|
+
$: iframeTitle =
|
|
194
|
+
mode === 'controlled'
|
|
195
|
+
? 'Widget preview'
|
|
196
|
+
: `Widget preview – ${widget?.name || 'Widget'}`;
|
|
197
|
+
|
|
198
|
+
function buildWidgetUrl(w: any): string | null {
|
|
199
|
+
if (!w) return null;
|
|
200
|
+
|
|
201
|
+
const jsPath = w.jsPath || w.js_path;
|
|
202
|
+
|
|
203
|
+
if (jsPath) {
|
|
204
|
+
if (apiBaseUrl) {
|
|
205
|
+
const artifactPath = jsPath.match(/\/widgets\/[^/]+\/v\d+\/.+$/i);
|
|
206
|
+
if (artifactPath) {
|
|
207
|
+
const proxyUrl = `${apiBaseUrl}${artifactPath[0]}`;
|
|
208
|
+
console.log('[WidgetPreview] Using API proxy URL (R2):', proxyUrl);
|
|
209
|
+
return proxyUrl;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (jsPath.startsWith('http')) return jsPath;
|
|
213
|
+
return `https://cdn.widgetic.com${jsPath.startsWith('/') ? '' : '/'}${jsPath}`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (widgetBuilderUrl && w.id) {
|
|
217
|
+
const previewUrl = `${widgetBuilderUrl.replace(/\/+$/, '')}/preview/${w.id}`;
|
|
218
|
+
console.log('[WidgetPreview] Using Worker preview URL (unpublished):', previewUrl);
|
|
219
|
+
return previewUrl;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
console.log('[WidgetPreview] Widget not published and no Worker URL:', w.name, w.id);
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function tryFallbackUrl(w: any): string | null {
|
|
227
|
+
if (!w?.id || !widgetBuilderUrl) return null;
|
|
228
|
+
return `${widgetBuilderUrl.replace(/\/+$/, '')}/preview/${w.id}`;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function resolveWidgetPreviewUrl(w: any, primaryUrl: string): Promise<string> {
|
|
232
|
+
try {
|
|
233
|
+
const res = await fetch(primaryUrl, { method: 'GET', mode: 'cors' });
|
|
234
|
+
const contentType = res.headers.get('content-type') || '';
|
|
235
|
+
const looksLikeErrorPayload =
|
|
236
|
+
!res.ok || (contentType.includes('application/json') && !contentType.includes('html'));
|
|
237
|
+
if (looksLikeErrorPayload) {
|
|
238
|
+
const fallbackUrl = tryFallbackUrl(w);
|
|
239
|
+
if (fallbackUrl && !triedFallback) {
|
|
240
|
+
triedFallback = true;
|
|
241
|
+
console.log('[WidgetPreview] Primary URL failed, trying Worker fallback:', fallbackUrl);
|
|
242
|
+
return fallbackUrl;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
} catch (err) {
|
|
246
|
+
const fallbackUrl = tryFallbackUrl(w);
|
|
247
|
+
if (fallbackUrl && !triedFallback) {
|
|
248
|
+
triedFallback = true;
|
|
249
|
+
console.log('[WidgetPreview] Primary URL unreachable, trying Worker fallback:', fallbackUrl);
|
|
250
|
+
return fallbackUrl;
|
|
251
|
+
}
|
|
252
|
+
console.warn('[WidgetPreview] URL probe failed:', primaryUrl, err);
|
|
253
|
+
}
|
|
254
|
+
return primaryUrl;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function beginWidgetLoad(w: any, url: string | null) {
|
|
258
|
+
pendingWidget = w;
|
|
259
|
+
triedFallback = false;
|
|
260
|
+
iframeLoaded = false;
|
|
261
|
+
iframeError = false;
|
|
262
|
+
widgetReady = false;
|
|
263
|
+
errorMessage = '';
|
|
264
|
+
pendingMessages = [];
|
|
265
|
+
|
|
266
|
+
if (!url) {
|
|
267
|
+
internalIframeSrc = null;
|
|
268
|
+
isResolvingUrl = false;
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
isResolvingUrl = true;
|
|
273
|
+
console.log('[WidgetPreview] Resolving widget URL:', url);
|
|
274
|
+
void resolveWidgetPreviewUrl(w, url).then(async (resolvedUrl) => {
|
|
275
|
+
if (pendingWidget !== w) return;
|
|
276
|
+
isResolvingUrl = false;
|
|
277
|
+
internalIframeSrc = resolvedUrl;
|
|
278
|
+
await tick();
|
|
279
|
+
requestAnimationFrame(() => {
|
|
280
|
+
ensureIframeLoadDetected();
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function ensureIframeLoadDetected() {
|
|
286
|
+
if (!iframeEl || (mode === 'standalone' && (iframeLoaded || iframeError))) return;
|
|
287
|
+
|
|
288
|
+
try {
|
|
289
|
+
const doc = iframeEl.contentDocument;
|
|
290
|
+
if (doc?.readyState === 'complete') {
|
|
291
|
+
void handleIframeLoad();
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
} catch {
|
|
295
|
+
// Cross-origin
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
iframeEl.contentWindow?.postMessage({ type: 'widgetic:ping' }, '*');
|
|
299
|
+
|
|
300
|
+
window.setTimeout(() => {
|
|
301
|
+
if (mode === 'standalone' && !iframeLoaded && !iframeError && iframeEl && effectiveSrc) {
|
|
302
|
+
console.log('[WidgetPreview] Fallback: marking iframe loaded after ping timeout');
|
|
303
|
+
void handleIframeLoad();
|
|
304
|
+
}
|
|
305
|
+
}, 400);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
$: if (mode === 'standalone' && widget) {
|
|
309
|
+
isWidgetPublished = !!(widget.jsPath || widget.js_path);
|
|
310
|
+
const newUrl = buildWidgetUrl(widget);
|
|
311
|
+
const widgetKey = `${widget.id}:${newUrl ?? 'none'}`;
|
|
312
|
+
if (widgetKey !== activeWidgetKey) {
|
|
313
|
+
activeWidgetKey = widgetKey;
|
|
314
|
+
beginWidgetLoad(widget, newUrl);
|
|
315
|
+
}
|
|
316
|
+
} else if (mode === 'standalone' && !widget) {
|
|
317
|
+
activeWidgetKey = null;
|
|
318
|
+
pendingWidget = null;
|
|
319
|
+
internalIframeSrc = null;
|
|
320
|
+
isWidgetPublished = false;
|
|
321
|
+
iframeLoaded = false;
|
|
322
|
+
iframeError = false;
|
|
323
|
+
errorMessage = '';
|
|
324
|
+
widgetReady = false;
|
|
325
|
+
isResolvingUrl = false;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
$: if (mode === 'controlled' && src) {
|
|
329
|
+
requestAnimationFrame(() => ensureIframeLoadDetected());
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
$: if (mode === 'standalone' && iframeLoaded && iframeEl?.contentWindow) {
|
|
333
|
+
sendPropertiesToWidget(designValues, contentValues);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function sendPropertiesToWidget(design: any, content: any) {
|
|
337
|
+
if (!iframeEl?.contentWindow) return;
|
|
338
|
+
try {
|
|
339
|
+
const { items, ...genericContent } = content || {};
|
|
340
|
+
|
|
341
|
+
let contentItems: any[] | undefined;
|
|
342
|
+
if (items && typeof items === 'object') {
|
|
343
|
+
contentItems = Object.entries(items).map(([itemId, props]: [string, any]) => ({
|
|
344
|
+
id: itemId,
|
|
345
|
+
...props
|
|
346
|
+
}));
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const message = {
|
|
350
|
+
type: 'widgetic:update',
|
|
351
|
+
design,
|
|
352
|
+
content: genericContent,
|
|
353
|
+
contentItems
|
|
354
|
+
};
|
|
355
|
+
iframeEl.contentWindow.postMessage(message, '*');
|
|
356
|
+
console.log('[WidgetPreview] Sent property update to widget iframe', {
|
|
357
|
+
designKeys: design ? Object.keys(design) : [],
|
|
358
|
+
genericContentKeys: Object.keys(genericContent),
|
|
359
|
+
contentItemsCount: contentItems?.length,
|
|
360
|
+
iframeSrc: effectiveSrc?.substring(0, 80)
|
|
361
|
+
});
|
|
362
|
+
} catch (err) {
|
|
363
|
+
console.warn('[WidgetPreview] Failed to send postMessage:', err);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function flushPendingMessages() {
|
|
368
|
+
if (!iframeEl?.contentWindow || pendingMessages.length === 0) return;
|
|
369
|
+
for (const message of pendingMessages) {
|
|
370
|
+
iframeEl.contentWindow.postMessage(message, '*');
|
|
371
|
+
}
|
|
372
|
+
pendingMessages = [];
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function sendMessageToPreview(message: Record<string, unknown>): void {
|
|
376
|
+
if (mode === 'controlled') {
|
|
377
|
+
if (iframeEl?.contentWindow) {
|
|
378
|
+
iframeEl.contentWindow.postMessage(message, '*');
|
|
379
|
+
}
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (widgetReady && iframeEl?.contentWindow) {
|
|
383
|
+
iframeEl.contentWindow.postMessage(message, '*');
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
pendingMessages.push(message);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export function goToItem(index: number) {
|
|
390
|
+
sendMessageToPreview({ type: 'widgetic:goToItem', index });
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export function refreshValues() {
|
|
394
|
+
sendPropertiesToWidget(designValues, contentValues);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
async function handleIframeLoad() {
|
|
398
|
+
if (mode === 'controlled') {
|
|
399
|
+
if (src === 'about:blank' || iframeEl?.src?.includes('about:blank')) return;
|
|
400
|
+
dispatch('iframeLoad', new Event('load'));
|
|
401
|
+
requestAnimationFrame(() => nudgeIframePaint());
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (iframeLoaded) return;
|
|
406
|
+
iframeLoaded = true;
|
|
407
|
+
iframeError = false;
|
|
408
|
+
widgetReady = true;
|
|
409
|
+
console.log('[WidgetPreview] iframe onload:', effectiveSrc);
|
|
410
|
+
|
|
411
|
+
if (iframeEl?.contentWindow) {
|
|
412
|
+
iframeEl.contentWindow.postMessage({ type: 'widgetic:ping' }, '*');
|
|
413
|
+
sendPropertiesToWidget(designValues, contentValues);
|
|
414
|
+
flushPendingMessages();
|
|
415
|
+
dispatch('load', { src: effectiveSrc });
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
await tick();
|
|
419
|
+
requestAnimationFrame(() => {
|
|
420
|
+
nudgeIframePaint();
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function handleIframeError(event?: Event) {
|
|
425
|
+
if (mode === 'controlled') {
|
|
426
|
+
dispatch('iframeError', event || new Event('error'));
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
iframeError = true;
|
|
430
|
+
iframeLoaded = false;
|
|
431
|
+
widgetReady = false;
|
|
432
|
+
errorMessage = 'Failed to load widget preview.';
|
|
433
|
+
console.error('[WidgetPreview] Widget iframe onerror:', effectiveSrc);
|
|
434
|
+
dispatch('error', { src: effectiveSrc });
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
function handleMessage(event: MessageEvent) {
|
|
438
|
+
const type = event.data?.type;
|
|
439
|
+
if (type === 'widgetic:ready' || type === 'widgetic:pong') {
|
|
440
|
+
if (mode === 'standalone') {
|
|
441
|
+
iframeLoaded = true;
|
|
442
|
+
iframeError = false;
|
|
443
|
+
widgetReady = true;
|
|
444
|
+
console.log('[WidgetPreview] Widget confirmed ready via postMessage');
|
|
445
|
+
sendPropertiesToWidget(designValues, contentValues);
|
|
446
|
+
flushPendingMessages();
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function handleRefreshClick() {
|
|
452
|
+
if (mode === 'standalone' && widget) {
|
|
453
|
+
beginWidgetLoad(widget, buildWidgetUrl(widget));
|
|
454
|
+
}
|
|
455
|
+
dispatch('refresh');
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
function handleOpenInTabClick() {
|
|
459
|
+
const url = effectiveDisplayUrl || effectiveSrc;
|
|
460
|
+
if (url) window.open(url, '_blank');
|
|
461
|
+
dispatch('openInTab');
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function applyMobileViewport() {
|
|
465
|
+
const { maxWidth, maxHeight } = getResizeLimits();
|
|
466
|
+
const w = Math.min(mobileViewportWidth, maxWidth);
|
|
467
|
+
const h = Math.min(mobileViewportHeight, maxHeight);
|
|
468
|
+
resizeWidth = w;
|
|
469
|
+
resizeHeight = h;
|
|
470
|
+
dispatch('resize', { width: w, height: h });
|
|
471
|
+
dispatch('mobileViewport', { width: w, height: h });
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
function handleDesktopViewport() {
|
|
475
|
+
dispatch('desktopViewport');
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function handleFitToAreaClick() {
|
|
479
|
+
fitToContainer();
|
|
480
|
+
dispatch('fitToArea');
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function clampResizeToLimits() {
|
|
484
|
+
if (!enableResize || resizeWidth == null || resizeHeight == null) return;
|
|
485
|
+
const { maxWidth, maxHeight } = getResizeLimits();
|
|
486
|
+
const nextW = Math.min(resizeWidth, maxWidth);
|
|
487
|
+
const nextH = Math.min(resizeHeight, maxHeight);
|
|
488
|
+
if (nextW !== resizeWidth || nextH !== resizeHeight) {
|
|
489
|
+
resizeWidth = nextW;
|
|
490
|
+
resizeHeight = nextH;
|
|
491
|
+
dispatch('resize', { width: nextW, height: nextH });
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
function startResize(event: PointerEvent, signX: number, signY: number) {
|
|
496
|
+
event.preventDefault();
|
|
497
|
+
event.stopPropagation();
|
|
498
|
+
isResizing = true;
|
|
499
|
+
const startX = event.clientX;
|
|
500
|
+
const startY = event.clientY;
|
|
501
|
+
|
|
502
|
+
const { maxWidth, maxHeight } = getResizeLimits();
|
|
503
|
+
const startWidth = resizeWidth ?? maxWidth;
|
|
504
|
+
const startHeight = resizeHeight ?? maxHeight;
|
|
505
|
+
|
|
506
|
+
function onPointerMove(e: PointerEvent) {
|
|
507
|
+
const deltaX = (e.clientX - startX) * signX * 2;
|
|
508
|
+
const deltaY = (e.clientY - startY) * signY * 2;
|
|
509
|
+
resizeWidth = Math.max(MIN_WIDTH, Math.min(maxWidth, startWidth + deltaX));
|
|
510
|
+
resizeHeight = Math.max(MIN_HEIGHT, Math.min(maxHeight, startHeight + deltaY));
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
function endResize() {
|
|
514
|
+
isResizing = false;
|
|
515
|
+
document.removeEventListener('pointermove', onPointerMove);
|
|
516
|
+
document.removeEventListener('pointerup', endResize);
|
|
517
|
+
document.removeEventListener('pointercancel', endResize);
|
|
518
|
+
document.body.style.removeProperty('user-select');
|
|
519
|
+
document.body.style.removeProperty('cursor');
|
|
520
|
+
if (resizeWidth != null && resizeHeight != null) {
|
|
521
|
+
dispatch('resize', { width: resizeWidth, height: resizeHeight });
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
document.body.style.userSelect = 'none';
|
|
526
|
+
document.body.style.cursor = 'nwse-resize';
|
|
527
|
+
document.addEventListener('pointermove', onPointerMove);
|
|
528
|
+
document.addEventListener('pointerup', endResize);
|
|
529
|
+
document.addEventListener('pointercancel', endResize);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
$: if (enableResize && contentContainerEl && (resizeWidth != null || resizeHeight != null)) {
|
|
533
|
+
clampResizeToLimits();
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
$: if (autoFitStage && resizeStageEl) {
|
|
537
|
+
stageResizeObserver?.disconnect();
|
|
538
|
+
stageResizeObserver = new ResizeObserver(() => {
|
|
539
|
+
fitToContainer();
|
|
540
|
+
});
|
|
541
|
+
stageResizeObserver.observe(resizeStageEl);
|
|
542
|
+
fitToContainer();
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
onMount(() => {
|
|
546
|
+
window.addEventListener('message', handleMessage);
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
onDestroy(() => {
|
|
550
|
+
window.removeEventListener('message', handleMessage);
|
|
551
|
+
stageResizeObserver?.disconnect();
|
|
552
|
+
document.body.style.removeProperty('user-select');
|
|
553
|
+
document.body.style.removeProperty('cursor');
|
|
554
|
+
});
|
|
555
|
+
</script>
|
|
556
|
+
|
|
557
|
+
<div
|
|
558
|
+
class="{className ? className + ' ' : ''}widget-preview-content-root flex flex-col min-h-0 user-select-none {hasFixedBounds ? 'w-auto shrink-0' : mode === 'standalone' && !showUrlBar ? 'relative overflow-hidden rounded-[4px] bg-transparent' : 'h-full w-full'}"
|
|
559
|
+
style="{style ? style + ';' : ''}{hasFixedBounds ? `width: ${boundsWidth}px;` : mode === 'standalone' && !showUrlBar ? `width: ${width}; height: ${height};` : ''}"
|
|
560
|
+
>
|
|
561
|
+
{#if showUrlBar}
|
|
562
|
+
<div class="preview-content-url-bar flex items-center gap-1.5 pb-1.5 min-w-0">
|
|
563
|
+
<span
|
|
564
|
+
class="preview-url-text flex-1 rounded border border-gray-300 px-2 py-1 text-xs text-gray-500 min-w-0 font-mono overflow-x-auto whitespace-nowrap"
|
|
565
|
+
>
|
|
566
|
+
{effectiveDisplayUrl || effectiveSrc || 'no URL'}
|
|
567
|
+
</span>
|
|
568
|
+
<button
|
|
569
|
+
type="button"
|
|
570
|
+
onclick={() => {
|
|
571
|
+
const url = effectiveDisplayUrl || effectiveSrc;
|
|
572
|
+
if (url) navigator.clipboard.writeText(url);
|
|
573
|
+
}}
|
|
574
|
+
title="Copy URL"
|
|
575
|
+
class="shrink-0 w-7 h-7 flex items-center justify-center rounded border border-gray-300 bg-white hover:bg-gray-100 text-sm cursor-pointer"
|
|
576
|
+
>
|
|
577
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
|
|
578
|
+
</button>
|
|
579
|
+
{#if showUrlBarButtons}
|
|
580
|
+
<button
|
|
581
|
+
type="button"
|
|
582
|
+
onclick={handleRefreshClick}
|
|
583
|
+
title="Refresh preview"
|
|
584
|
+
class="shrink-0 w-7 h-7 flex items-center justify-center rounded border border-gray-300 bg-white hover:bg-gray-100 text-sm cursor-pointer"
|
|
585
|
+
>🔄</button>
|
|
586
|
+
{#if showViewportButtons && enableResize}
|
|
587
|
+
<button
|
|
588
|
+
type="button"
|
|
589
|
+
onclick={handleFitToAreaClick}
|
|
590
|
+
title="Fit preview to panel"
|
|
591
|
+
class="preview-fit-to-area-btn shrink-0 w-7 h-7 flex items-center justify-center rounded border border-gray-300 bg-white hover:bg-gray-100 cursor-pointer"
|
|
592
|
+
>
|
|
593
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6"/><path d="M9 21H3v-6"/><path d="M21 3l-7 7"/><path d="M3 21l7-7"/></svg>
|
|
594
|
+
</button>
|
|
595
|
+
<button
|
|
596
|
+
type="button"
|
|
597
|
+
onclick={applyMobileViewport}
|
|
598
|
+
title="Mobile viewport"
|
|
599
|
+
class="preview-mobile-viewport-btn shrink-0 w-7 h-7 flex items-center justify-center rounded border border-gray-300 bg-white hover:bg-gray-100 cursor-pointer"
|
|
600
|
+
>
|
|
601
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="2" width="14" height="20" rx="2" ry="2"/><line x1="12" y1="18" x2="12.01" y2="18"/></svg>
|
|
602
|
+
</button>
|
|
603
|
+
<button
|
|
604
|
+
type="button"
|
|
605
|
+
onclick={handleDesktopViewport}
|
|
606
|
+
title="Desktop viewport (full window)"
|
|
607
|
+
class="preview-desktop-viewport-btn shrink-0 w-7 h-7 flex items-center justify-center rounded border border-gray-300 bg-white hover:bg-gray-100 cursor-pointer"
|
|
608
|
+
>
|
|
609
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
|
|
610
|
+
</button>
|
|
611
|
+
{/if}
|
|
612
|
+
<button
|
|
613
|
+
type="button"
|
|
614
|
+
onclick={handleOpenInTabClick}
|
|
615
|
+
title="Open in new tab"
|
|
616
|
+
class="shrink-0 px-2 h-7 flex items-center justify-center rounded border border-gray-300 bg-white hover:bg-gray-100 text-xs cursor-pointer whitespace-nowrap"
|
|
617
|
+
>↗ New tab</button>
|
|
618
|
+
{/if}
|
|
619
|
+
</div>
|
|
620
|
+
{/if}
|
|
621
|
+
|
|
622
|
+
<div
|
|
623
|
+
bind:this={contentContainerEl}
|
|
624
|
+
class="preview-content-container relative flex items-center justify-center {containerOverflowClass} {hasFixedBounds ? 'rounded-lg bg-gray-50 border border-gray-300 shrink-0' : compactChrome ? 'flex-1 min-h-0 h-full' : showUrlBar || mode === 'controlled' ? 'flex-1 min-h-0 rounded-lg bg-gray-50 border border-gray-300' : 'flex-1 min-h-0 h-full'}"
|
|
625
|
+
style="{boundedContainerStyle}{containerPaddingStyle}{contentHeight && (showUrlBar || mode === 'controlled') && !compactChrome && !hasFixedBounds ? ` min-height: 0;` : ''}"
|
|
626
|
+
>
|
|
627
|
+
{#if forceMockReady}
|
|
628
|
+
<div class="flex flex-col items-center justify-center w-full h-full bg-gray-100 text-gray-500">
|
|
629
|
+
<div class="text-4xl mb-2">🚀</div>
|
|
630
|
+
<div class="font-semibold">Mock Preview Mode</div>
|
|
631
|
+
<div class="text-sm">Preview simulated as Ready. URL: about:blank</div>
|
|
632
|
+
</div>
|
|
633
|
+
|
|
634
|
+
{:else if mode === 'standalone' && !widget}
|
|
635
|
+
<div class="widget-preview-select-ct flex items-center justify-center h-full text-sm text-gray-400">
|
|
636
|
+
Select a widget to preview
|
|
637
|
+
</div>
|
|
638
|
+
|
|
639
|
+
{:else if mode === 'standalone' && widget && !effectiveSrc && !isResolvingUrl && !iframeError}
|
|
640
|
+
<div class="widget-preview-unpublished-ct flex items-center justify-center h-full w-full">
|
|
641
|
+
<div class="widget-preview-unpublished-content-ct flex flex-col items-center gap-3 text-center px-6">
|
|
642
|
+
<div class="w-10 h-10 rounded-full bg-amber-50 flex items-center justify-center">
|
|
643
|
+
<svg class="w-5 h-5 text-amber-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
|
644
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4.5c-.77-.833-2.694-.833-3.464 0L3.34 16.5c-.77.833.192 2.5 1.732 2.5z" />
|
|
645
|
+
</svg>
|
|
646
|
+
</div>
|
|
647
|
+
<div>
|
|
648
|
+
<p class="text-sm font-medium text-gray-600">{widget.name || 'Widget'}</p>
|
|
649
|
+
<p class="text-xs text-gray-400 mt-1">Not published yet</p>
|
|
650
|
+
</div>
|
|
651
|
+
<p class="text-[11px] text-gray-300 max-w-[220px]">
|
|
652
|
+
Publish the widget in Widget Creator to preview it here.
|
|
653
|
+
</p>
|
|
654
|
+
</div>
|
|
655
|
+
</div>
|
|
656
|
+
|
|
657
|
+
{:else if effectiveSrc || (mode === 'standalone' && isResolvingUrl)}
|
|
658
|
+
<div
|
|
659
|
+
bind:this={resizeStageEl}
|
|
660
|
+
class="{enableResize ? 'preview-resize-stage-ct absolute inset-0 overflow-hidden flex items-center justify-center' : 'preview-resize-stage-ct relative flex items-center justify-center w-full h-full'}"
|
|
661
|
+
>
|
|
662
|
+
<div
|
|
663
|
+
class="preview-iframe-wrapper relative"
|
|
664
|
+
style="width: {resizeWidth ? resizeWidth + 'px' : '100%'}; height: {resizeHeight ? resizeHeight + 'px' : '100%'}; transition: {isResizing ? 'none' : 'width 0.2s, height 0.2s'};"
|
|
665
|
+
>
|
|
666
|
+
{#if showResizeHandles}
|
|
667
|
+
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
668
|
+
<div class="preview-resize-handle preview-resize-handle-tl" onpointerdown={(e) => startResize(e, -1, -1)}></div>
|
|
669
|
+
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
670
|
+
<div class="preview-resize-handle preview-resize-handle-tr" onpointerdown={(e) => startResize(e, 1, -1)}></div>
|
|
671
|
+
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
672
|
+
<div class="preview-resize-handle preview-resize-handle-bl" onpointerdown={(e) => startResize(e, -1, 1)}></div>
|
|
673
|
+
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
674
|
+
<div class="preview-resize-handle preview-resize-handle-br" onpointerdown={(e) => startResize(e, 1, 1)}></div>
|
|
675
|
+
{/if}
|
|
676
|
+
|
|
677
|
+
{#if resizeWidth || resizeHeight}
|
|
678
|
+
<div
|
|
679
|
+
class="widget-preview-dimension-badge absolute left-1/2 -translate-x-1/2 text-[10px] bg-black/70 px-1.5 py-px rounded text-gray-300 select-none pointer-events-none z-20 whitespace-nowrap"
|
|
680
|
+
style="top: calc(100% + 4px);"
|
|
681
|
+
>
|
|
682
|
+
{resizeWidth != null ? Math.round(resizeWidth) + 'px' : '100%'} × {resizeHeight != null ? Math.round(resizeHeight) + 'px' : '100%'}
|
|
683
|
+
</div>
|
|
684
|
+
{/if}
|
|
685
|
+
|
|
686
|
+
<div class="preview-iframe-container relative w-full h-full overflow-hidden {compactChrome ? '' : showUrlBar || mode === 'controlled' || enableResize ? 'border border-gray-300' : ''}">
|
|
687
|
+
{#if mode === 'standalone' && iframeError}
|
|
688
|
+
<div class="widget-preview-error-ct absolute inset-0 flex items-center justify-center bg-white z-10 rounded">
|
|
689
|
+
<div class="widget-preview-error-content-ct flex flex-col items-center gap-2 text-center px-4">
|
|
690
|
+
<svg class="w-8 h-8 text-gray-300" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
|
|
691
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z" />
|
|
692
|
+
</svg>
|
|
693
|
+
<span class="text-sm text-gray-500">{@html errorMessage || 'Failed to load widget.'}</span>
|
|
694
|
+
</div>
|
|
695
|
+
</div>
|
|
696
|
+
{:else if mode === 'controlled' && previewError && !isGeneratingCode}
|
|
697
|
+
<div class="preview-error-overlay absolute inset-0 z-10 flex h-full flex-col items-center justify-center bg-red-50/95 text-gray-700 p-6">
|
|
698
|
+
<div class="text-4xl mb-3">⚠️</div>
|
|
699
|
+
<div class="font-semibold text-lg text-red-600 mb-2">Preview Unavailable</div>
|
|
700
|
+
<div class="text-sm text-center max-w-md whitespace-pre-line text-gray-600 mb-4">{previewError}</div>
|
|
701
|
+
<div class="flex gap-3">
|
|
702
|
+
<button type="button" onclick={() => dispatch('retry')} class="px-3 py-1.5 text-xs rounded border border-blue-500 text-blue-600 bg-white hover:bg-blue-50 cursor-pointer">
|
|
703
|
+
🔄 Retry {previewRetryCount > 0 ? `(${previewRetryCount})` : ''}
|
|
704
|
+
</button>
|
|
705
|
+
<button type="button" onclick={() => dispatch('openInTab')} class="px-3 py-1.5 text-xs rounded border border-gray-300 text-gray-600 bg-white hover:bg-gray-100 cursor-pointer">
|
|
706
|
+
Open in new tab
|
|
707
|
+
</button>
|
|
708
|
+
</div>
|
|
709
|
+
</div>
|
|
710
|
+
{/if}
|
|
711
|
+
|
|
712
|
+
{#if showStandaloneLoading}
|
|
713
|
+
<div class="widget-preview-loading-ct absolute inset-0 z-10 flex items-center justify-center bg-gray-50/80">
|
|
714
|
+
<GenerateLoader title="Loading widget…" subtitle="" size="md" />
|
|
715
|
+
</div>
|
|
716
|
+
{:else if showControlledLoading && !isGeneratingCode}
|
|
717
|
+
<div class="loading-overlay absolute inset-0 z-20 flex items-center justify-center bg-gray-50">
|
|
718
|
+
<GenerateLoader
|
|
719
|
+
title={!src && isLoadingUrl
|
|
720
|
+
? 'Loading Preview…'
|
|
721
|
+
: previewHydrating
|
|
722
|
+
? 'Loading Preview…'
|
|
723
|
+
: 'Loading Preview…'}
|
|
724
|
+
subtitle={!src && isLoadingUrl
|
|
725
|
+
? 'Checking widget on Worker…'
|
|
726
|
+
: previewHydrating
|
|
727
|
+
? 'Applying composition settings…'
|
|
728
|
+
: 'Connecting to the widget preview…'}
|
|
729
|
+
size="lg"
|
|
730
|
+
/>
|
|
731
|
+
</div>
|
|
732
|
+
{/if}
|
|
733
|
+
|
|
734
|
+
{#if mode === 'controlled' && previewHasRuntimeError && !isGeneratingCode}
|
|
735
|
+
<div class="compilation-error-overlay absolute inset-0 z-20 flex flex-col items-center justify-center bg-red-50 text-red-700 p-6">
|
|
736
|
+
<div class="text-5xl mb-4">⚠️</div>
|
|
737
|
+
<div class="font-semibold text-xl mb-2">Code Has Compilation Errors</div>
|
|
738
|
+
<div class="text-sm text-center text-red-600 mb-4 max-w-md">
|
|
739
|
+
The generated code has syntax or compilation errors (HTTP {previewRuntimeErrorStatus}).
|
|
740
|
+
</div>
|
|
741
|
+
<div class="flex gap-3 flex-wrap justify-center">
|
|
742
|
+
<button type="button" onclick={() => dispatch('fixErrors')} class="px-4 py-2 text-xs rounded bg-red-600 hover:bg-red-700 text-white cursor-pointer border-0">🔧 Fix Errors</button>
|
|
743
|
+
<button type="button" onclick={() => dispatch('viewErrors')} class="px-3 py-1.5 text-xs rounded border border-orange-400 text-orange-600 bg-white hover:bg-orange-50 cursor-pointer">📋 View Errors</button>
|
|
744
|
+
<button type="button" onclick={() => dispatch('retryPreview')} class="px-3 py-1.5 text-xs rounded border border-red-300 text-red-600 bg-white hover:bg-red-50 cursor-pointer">🔄 Retry Preview</button>
|
|
745
|
+
</div>
|
|
746
|
+
</div>
|
|
747
|
+
{/if}
|
|
748
|
+
|
|
749
|
+
{#if mountedPreviewSrc}
|
|
750
|
+
{#key mode === 'controlled' ? `${iframeReloadKey}:${mountedPreviewSrc}` : mountedPreviewSrc}
|
|
751
|
+
<!-- svelte-ignore a11y-missing-attribute -->
|
|
752
|
+
<iframe
|
|
753
|
+
bind:this={iframeEl}
|
|
754
|
+
title={iframeTitle}
|
|
755
|
+
src={mountedPreviewSrc}
|
|
756
|
+
class="widget-preview-iframe h-full w-full border-0"
|
|
757
|
+
tabindex="-1"
|
|
758
|
+
sandbox={mode === 'controlled' ? undefined : 'allow-scripts allow-popups allow-forms'}
|
|
759
|
+
loading="eager"
|
|
760
|
+
allow="clipboard-read; clipboard-write"
|
|
761
|
+
onload={handleIframeLoad}
|
|
762
|
+
onerror={handleIframeError}
|
|
763
|
+
></iframe>
|
|
764
|
+
{/key}
|
|
765
|
+
{/if}
|
|
766
|
+
|
|
767
|
+
{#if isResizing}
|
|
768
|
+
<div class="resize-iframe-blocker absolute inset-0 z-5 cursor-nwse-resize" style="background: transparent;"></div>
|
|
769
|
+
{/if}
|
|
770
|
+
|
|
771
|
+
{#if mode === 'controlled' && isGeneratingCode}
|
|
772
|
+
<GenerateLoader overlay title="Generating code…" size="lg" />
|
|
773
|
+
{/if}
|
|
774
|
+
</div>
|
|
775
|
+
</div>
|
|
776
|
+
</div>
|
|
777
|
+
|
|
778
|
+
{:else if mode === 'controlled'}
|
|
779
|
+
{#if isLoadingUrl}
|
|
780
|
+
<div class="flex h-full flex-col items-center justify-center p-6">
|
|
781
|
+
<GenerateLoader title="Loading Preview…" subtitle="" size="lg" />
|
|
782
|
+
</div>
|
|
783
|
+
{:else}
|
|
784
|
+
<div class="flex h-full flex-col items-center justify-center p-6 text-center text-sm text-gray-600">
|
|
785
|
+
{#if isGeneratingCode}
|
|
786
|
+
<GenerateLoader title="Generating code…" size="lg" />
|
|
787
|
+
{:else if previewError === 'NO_CODE_YET'}
|
|
788
|
+
<div class="font-semibold text-lg text-gray-700 mb-2">No Code Generated Yet</div>
|
|
789
|
+
{:else if previewError}
|
|
790
|
+
<div class="font-semibold text-lg text-red-600 mb-2">Preview Unavailable</div>
|
|
791
|
+
<div class="text-sm text-gray-600 mb-4">{previewError}</div>
|
|
792
|
+
<button type="button" onclick={() => dispatch('retry')} class="px-3 py-1.5 text-xs rounded border border-blue-500 text-blue-600 bg-white hover:bg-blue-50 cursor-pointer">🔄 Retry Build</button>
|
|
793
|
+
{:else if previewLoading}
|
|
794
|
+
<div class="text-lg font-medium text-gray-700">Building Preview...</div>
|
|
795
|
+
{:else}
|
|
796
|
+
<div class="text-lg text-gray-600 mb-2">🖼️ No Preview Available</div>
|
|
797
|
+
{/if}
|
|
798
|
+
</div>
|
|
799
|
+
{/if}
|
|
800
|
+
{/if}
|
|
801
|
+
</div>
|
|
802
|
+
|
|
803
|
+
{#if isResizing}
|
|
804
|
+
<div
|
|
805
|
+
class="widget-preview-resize-guard-ct fixed inset-0 z-999999 cursor-nwse-resize"
|
|
806
|
+
style="background: transparent;"
|
|
807
|
+
aria-hidden="true"
|
|
808
|
+
></div>
|
|
809
|
+
{/if}
|
|
810
|
+
</div>
|
|
811
|
+
|
|
812
|
+
<style>
|
|
813
|
+
.preview-url-text::-webkit-scrollbar { display: none; }
|
|
814
|
+
.preview-url-text { scrollbar-width: none; }
|
|
815
|
+
|
|
816
|
+
.preview-resize-handle {
|
|
817
|
+
position: absolute;
|
|
818
|
+
width: 16px;
|
|
819
|
+
height: 16px;
|
|
820
|
+
z-index: 30;
|
|
821
|
+
border-radius: 2px;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
.preview-resize-handle::before,
|
|
825
|
+
.preview-resize-handle::after {
|
|
826
|
+
content: '';
|
|
827
|
+
position: absolute;
|
|
828
|
+
background: #94a3b8;
|
|
829
|
+
border-radius: 1px;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
.preview-resize-handle-tl { top: -4px; left: -4px; cursor: nwse-resize; }
|
|
833
|
+
.preview-resize-handle-tl::before { top: 0; left: 0; width: 10px; height: 2px; }
|
|
834
|
+
.preview-resize-handle-tl::after { top: 0; left: 0; width: 2px; height: 10px; }
|
|
835
|
+
|
|
836
|
+
.preview-resize-handle-tr { top: -4px; right: -4px; cursor: nesw-resize; }
|
|
837
|
+
.preview-resize-handle-tr::before { top: 0; right: 0; width: 10px; height: 2px; }
|
|
838
|
+
.preview-resize-handle-tr::after { top: 0; right: 0; width: 2px; height: 10px; }
|
|
839
|
+
|
|
840
|
+
.preview-resize-handle-bl { bottom: -4px; left: -4px; cursor: nesw-resize; }
|
|
841
|
+
.preview-resize-handle-bl::before { bottom: 0; left: 0; width: 10px; height: 2px; }
|
|
842
|
+
.preview-resize-handle-bl::after { bottom: 0; left: 0; width: 2px; height: 10px; }
|
|
843
|
+
|
|
844
|
+
.preview-resize-handle-br { bottom: -4px; right: -4px; cursor: nwse-resize; }
|
|
845
|
+
.preview-resize-handle-br::before { bottom: 0; right: 0; width: 10px; height: 2px; }
|
|
846
|
+
.preview-resize-handle-br::after { bottom: 0; right: 0; width: 2px; height: 10px; }
|
|
847
|
+
|
|
848
|
+
.preview-resize-handle:hover::before,
|
|
849
|
+
.preview-resize-handle:hover::after {
|
|
850
|
+
background: #64748b;
|
|
851
|
+
}
|
|
852
|
+
</style>
|