@lumiastream/ui 0.5.3 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LSButton.js +1 -1
- package/dist/LSCheckbox.js +1 -1
- package/dist/LSColorPicker.js +1 -1
- package/dist/LSDatePicker.js +1 -1
- package/dist/LSFontPicker.js +1 -1
- package/dist/LSInput.js +1 -1
- package/dist/LSMultiSelect.js +1 -1
- package/dist/LSRadio.js +1 -1
- package/dist/LSSelect.js +1 -1
- package/dist/LSSliderInput.js +1 -1
- package/dist/LSTextField.js +1 -1
- package/dist/LSVariableInputField.js +1 -1
- package/dist/components.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +837 -456
- package/dist/se-import.d.ts +9 -3
- package/dist/se-import.js +836 -455
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ function styleInject(css, { insertAt } = {}) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
// src/lumia-ui.css
|
|
24
|
-
styleInject(".ls-color-picker,\n.ls-color-picker *,\n.mui-multi-select,\n.mui-multi-select *,\n.ls-multi-select-value,\n.ls-multi-select-value *,\n.ls-variable-picker,\n.ls-variable-picker *,\n.ls-variable-token,\n.ls-variable-token *,\n.ls-font-picker,\n.ls-font-picker *,\n.mui-ls-input,\n.mui-ls-input * {\n box-sizing: border-box;\n}\n.ls-color-picker button,\n.mui-multi-select button {\n font: inherit;\n letter-spacing: inherit;\n color: inherit;\n margin: 0;\n}\n.ls-color-picker__preview {\n appearance: none;\n -webkit-appearance: none;\n background-color: transparent;\n background-image: none;\n cursor: pointer;\n text-transform: uppercase;\n user-select: none;\n}\n.mui-ls-button.Mui-disabled {\n color: var(--neutralLight2, var(--white2, #cac9d5));\n opacity: 0.45;\n background-color: var(--separator, #0a0821);\n cursor: not-allowed;\n}\n.mui-ls-button {\n border-radius: var(--radius, 1rem);\n padding: 0.375rem 1.5rem;\n text-transform: uppercase;\n}\n.mui-ls-button.MuiButton-sizeSmall {\n padding: 0.25rem 1rem;\n}\n.mui-ls-button.MuiButton-sizeLarge {\n padding: 0.625rem 2rem;\n}\n.mui-ls-button--extended {\n padding-inline: 3rem;\n}\n.mui-ls-button.MuiButton-containedPrimary,\n.mui-ls-button.Mui-disabled.MuiButton-containedPrimary {\n background: var(--primary, #ff4076);\n color: var(--alwayswhite, #fff) !important;\n}\n.mui-ls-button.MuiButton-containedSecondary {\n background-color: var(--secondary, #535395);\n color: var(--alwayswhite, #fff) !important;\n}\n.mui-ls-button.Mui-disabled.MuiButton-containedSecondary {\n background-color: var(--secondary, #535395);\n color: var(--neutralLight2, var(--white2, #cac9d5));\n opacity: 0.4;\n}\n.mui-ls-button.MuiButton-outlinedPrimary {\n color: var(--primary, #ff4076);\n border-color: var(--primary, #ff4076);\n}\n.mui-ls-button.MuiButton-outlinedPrimary:hover {\n border-color: var(--primary, #ff4076);\n background-color: color-mix(in srgb, var(--primary, #ff4076) 12%, transparent);\n}\n.mui-ls-button.MuiButton-outlinedSecondary {\n color: var(--neutralLight1, var(--white, #fff));\n border-color: var(--secondary, #535395);\n}\n.mui-ls-button.MuiButton-outlinedSecondary.Mui-disabled {\n color: var(--neutralLight2, var(--white2, #cac9d5));\n border-color: var(--neutralDark4, var(--cardborder, #393853));\n background-color: var(--transwhite, rgba(255, 255, 255, 0.05));\n opacity: 0.5;\n}\n.mui-ls-button.MuiButton-outlinedSecondary:hover {\n border-color: var(--secondary, #535395);\n background-color: var(--transwhite, rgba(255, 255, 255, 0.05));\n}\n.mui-ls-button.MuiButton-containedError {\n color: var(--alwayswhite, #fff) !important;\n}\n.mui-ls-button.MuiButton-outlinedError {\n color: var(--error, #fd5454);\n border-color: var(--error, #fd5454);\n}\n.mui-ls-button.MuiButton-outlinedError:hover {\n border-color: var(--error, #fd5454);\n background-color: color-mix(in srgb, var(--error, #fd5454) 12%, transparent);\n}\n.mui-ls-button--neutral.mui-ls-button--contained {\n background-color: var(--neutralDark4, var(--cardborder, #393853));\n color: var(--neutralLight1, var(--white, #fff)) !important;\n}\n.mui-ls-button--neutral.mui-ls-button--contained:hover {\n background-color: color-mix(in srgb, var(--neutralDark4, var(--cardborder, #393853)) 82%, var(--neutralLight1, #fff));\n}\n.mui-ls-button--neutral.mui-ls-button--outlined {\n color: var(--neutralLight1, var(--white, #fff));\n border-color: var(--neutralDark4, var(--cardborder, #393853));\n background-color: transparent;\n}\n.mui-ls-button--neutral.mui-ls-button--outlined:hover {\n border-color: var(--neutralLight3, var(--grey, #9392a1));\n background-color: var(--transwhite, rgba(255, 255, 255, 0.05));\n}\n.mui-ls-button--neutral.mui-ls-button--text {\n color: var(--neutralLight1, var(--white, #fff));\n}\n.mui-ls-button--neutral.mui-ls-button--text:hover {\n background-color: var(--transwhite, rgba(255, 255, 255, 0.05));\n}\n.mui-ls-button svg {\n max-height: 24px;\n max-width: 24px;\n}\n.mui-ls-input,\n.ls-font-picker,\n.ls-color-picker__input {\n width: 100%;\n}\n.mui-ls-input,\n.mui-ls-select-form-control,\n.mui-multi-select,\n.ls-font-picker,\n.mui-ls-slider-input-root {\n --ls-control-height: 55px;\n}\n.mui-ls-input .MuiOutlinedInput-root,\n.mui-ls-input .MuiInputBase-root,\n.mui-ls-input .MuiOutlinedInput-notchedOutline,\n.mui-ls-select.MuiOutlinedInput-root,\n.mui-ls-select .MuiOutlinedInput-notchedOutline,\n.mui-multi-select .mui-ls-select.MuiOutlinedInput-root,\n.mui-multi-select .mui-ls-select .MuiOutlinedInput-notchedOutline,\n.ls-font-picker .MuiOutlinedInput-root,\n.ls-font-picker .MuiInputBase-root,\n.ls-font-picker .MuiOutlinedInput-notchedOutline,\n.ls-color-picker__input .MuiOutlinedInput-root,\n.ls-color-picker__input .MuiInputBase-root,\n.ls-color-picker__input .MuiOutlinedInput-notchedOutline {\n border-radius: var(--radius) !important;\n}\n.mui-ls-input .MuiInputBase-root,\n.mui-ls-select.MuiInputBase-root,\n.mui-multi-select .mui-ls-select.MuiInputBase-root,\n.ls-font-picker .MuiInputBase-root {\n min-height: var(--ls-control-height);\n}\n.mui-ls-input.small .MuiInputBase-root {\n min-height: 25px;\n}\n.mui-ls-input.medium .MuiInputBase-root {\n min-height: 35px;\n}\n.mui-ls-input.noMinHeight .MuiInputBase-root {\n min-height: unset;\n}\n.mui-ls-date-picker input[type=datetime-local]::-webkit-calendar-picker-indicator {\n cursor: pointer;\n opacity: 0.9;\n filter: invert(1);\n}\n.mui-ls-select .MuiSelect-select,\n.mui-multi-select .MuiSelect-select {\n display: flex;\n min-height: calc(var(--ls-control-height) - 2px);\n align-items: center;\n box-sizing: border-box;\n border-radius: var(--radius);\n}\n.mui-multi-select .MuiSelect-select {\n min-width: 0;\n}\n.MuiSvgIcon-root svg {\n color: var(--neutralLight1, var(--white, #fff)) !important;\n}\n.mui-ls-input .MuiSvgIcon-root svg path {\n fill: currentcolor;\n stroke: currentcolor;\n}\n.mui-ls-input input::placeholder,\n.mui-ls-input textarea::placeholder {\n color: var(--neutralLight3, var(--grey, #9392a1));\n opacity: 1;\n}\n.mui-ls-input .Mui-focused .MuiOutlinedInput-notchedOutline,\n.mui-ls-input .MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline {\n border-color: var(--primary, #ff4076) !important;\n}\n.ls-variable-autocomplete-popper .MuiAutocomplete-paper,\n.ls-variable-autocomplete-paper {\n border: 1px solid var(--neutralDark4, var(--cardborder, #393853)) !important;\n border-radius: var(--radius, 1rem) !important;\n background: var(--neutralDark2, var(--cardbackground, #211f45)) !important;\n color: var(--neutralLight1, var(--white, #fff)) !important;\n box-shadow: 0 16px 32px rgba(0, 0, 0, 0.32) !important;\n overflow: hidden !important;\n}\n.ls-variable-autocomplete-popper .MuiAutocomplete-listbox,\n.ls-variable-autocomplete-listbox {\n padding: 0.25rem 0 !important;\n background: var(--neutralDark2, var(--cardbackground, #211f45)) !important;\n color: var(--neutralLight1, var(--white, #fff)) !important;\n}\n.ls-variable-autocomplete-popper .MuiAutocomplete-option,\n.ls-variable-autocomplete-listbox .MuiAutocomplete-option {\n display: flex !important;\n min-height: 44px !important;\n align-items: center !important;\n padding: 0.625rem 1rem !important;\n color: var(--neutralLight1, var(--white, #fff)) !important;\n font-size: 1rem !important;\n line-height: 1.35 !important;\n cursor: pointer !important;\n transition: background-color 120ms ease, color 120ms ease !important;\n}\n.ls-variable-autocomplete-popper .MuiAutocomplete-option > *,\n.ls-variable-autocomplete-listbox .MuiAutocomplete-option > * {\n min-width: 0;\n}\n.ls-variable-autocomplete-popper .MuiAutocomplete-option:hover,\n.ls-variable-autocomplete-popper .MuiAutocomplete-option.Mui-focused,\n.ls-variable-autocomplete-popper .MuiAutocomplete-option[data-focus=true],\n.ls-variable-autocomplete-popper .MuiAutocomplete-option[aria-selected=true],\n.ls-variable-autocomplete-listbox .MuiAutocomplete-option:hover,\n.ls-variable-autocomplete-listbox .MuiAutocomplete-option.Mui-focused,\n.ls-variable-autocomplete-listbox .MuiAutocomplete-option[data-focus=true],\n.ls-variable-autocomplete-listbox .MuiAutocomplete-option[aria-selected=true] {\n background: var( --cardHover, var(--transwhite, rgba(255, 255, 255, 0.05)) ) !important;\n color: var(--neutralLight1, var(--white, #fff)) !important;\n}\n.ls-variable-option {\n gap: 0.75rem;\n}\n.ls-variable-option__thumb {\n width: 40px;\n height: 40px;\n flex: 0 0 40px;\n border-radius: var(--radius, 1rem);\n object-fit: cover;\n}\n.ls-variable-option__thumb--placeholder {\n background: var(--neutralDark4, var(--cardborder, #393853));\n}\n.ls-variable-option__body {\n min-width: 0;\n}\n.ls-variable-option__label {\n color: var(--neutralLight1, var(--white, #fff));\n font-weight: 500;\n line-height: 1.25;\n}\n.ls-variable-option__helper {\n margin-top: 0.125rem;\n color: var(--neutralLight3, var(--grey, #9392a1));\n font-size: 0.875rem;\n line-height: 1.25;\n}\n.ls-variable-autocomplete-popup-indicator,\n.ls-variable-autocomplete-popup-indicator.MuiIconButton-root,\n.ls-variable-autocomplete-popup-indicator svg {\n color: var(--neutralLight1, var(--white, #fff)) !important;\n}\n.ls-variable-autocomplete-popup-indicator svg path {\n fill: currentcolor !important;\n stroke: currentcolor !important;\n}\n.ls-variable-input-adornment,\n.ls-variable-input-adornment.MuiInputAdornment-root {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 24px;\n width: 24px;\n min-width: 24px;\n margin-left: 0.35rem;\n border-radius: var(--radius, 1rem);\n background: var(--primary, #ff4076) !important;\n color: var(--alwayswhite, var(--white, #fff)) !important;\n font-weight: 800;\n line-height: 1;\n letter-spacing: 0;\n cursor: pointer;\n user-select: none;\n}\n.ls-variable-input-adornment svg,\n.ls-variable-input-adornment path {\n color: currentcolor !important;\n fill: currentcolor !important;\n stroke: currentcolor !important;\n}\n.ls-variable-input-adornment:hover,\n.ls-variable-input-adornment.MuiInputAdornment-root:hover {\n filter: brightness(1.08);\n}\n.ls-variable-input-adornment:active,\n.ls-variable-input-adornment.MuiInputAdornment-root:active {\n filter: brightness(0.96);\n}\n.mui-ls-slider-input-root {\n width: 100%;\n}\n.mui-ls-slider-input-fieldset {\n position: relative;\n min-width: 0;\n width: 100%;\n min-height: var(--ls-control-height);\n margin: 0;\n border: 2px solid var(--neutralDark4, var(--cardborder, #393853));\n border-radius: var(--radius, 1rem);\n padding: 0 0.875rem 0.5rem 0.875rem;\n background: transparent;\n color: var(--neutralLight1, var(--white, #fff));\n}\n.mui-ls-slider-input-fieldset:hover {\n border-color: var(--primary, #ff4076);\n}\n.mui-ls-slider-input-legend {\n display: block;\n width: auto;\n max-width: calc(100% - 1rem);\n margin: 0;\n padding: 0 0.25rem;\n color: var(--neutralLight1, var(--white, #fff));\n font-size: 0.875rem;\n line-height: 1.1;\n white-space: nowrap;\n}\n.mui-ls-slider-input-row {\n display: flex;\n min-width: 0;\n min-height: calc(var(--ls-control-height) - 14px);\n align-items: center;\n gap: 1rem;\n}\n.mui-ls-slider-input-row--slider {\n flex-wrap: nowrap;\n}\n.mui-ls-slider-input-row--input {\n justify-content: stretch;\n}\n.mui-ls-slider-input-value.mui-ls-input {\n margin: 0;\n}\n.mui-ls-slider-input-value.mui-ls-input .MuiFormControl-root,\n.mui-ls-slider-input-value.mui-ls-input .MuiTextField-root {\n margin: 0;\n}\n.mui-ls-slider-input-value.mui-ls-input .MuiInputBase-root {\n min-height: 36px;\n}\n.mui-ls-slider-input-value.mui-ls-input .MuiOutlinedInput-notchedOutline {\n border-color: var(--neutralDark4, var(--cardborder, #393853));\n}\n.mui-ls-slider-input-helper {\n display: block;\n margin-top: 0.25rem;\n color: var(--neutralLight3, var(--grey, #9392a1));\n font-size: 0.75rem;\n line-height: 1.25;\n}\n.ls-multi-select-value {\n display: flex;\n width: 100%;\n min-width: 0;\n flex-wrap: nowrap;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n overflow: hidden;\n white-space: nowrap;\n}\n.ls-multi-select-value__label {\n min-width: 0;\n flex: 1 1 0%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.ls-multi-select-value__count {\n flex-shrink: 0;\n white-space: nowrap;\n}\n.ls-color-picker__preview {\n position: relative;\n display: inline-block;\n width: 1.5rem;\n height: 1.5rem;\n flex-shrink: 0;\n padding: 0;\n border: 1px solid color-mix(in srgb, #fff 25%, transparent);\n border-radius: var(--radius, 1rem);\n background-size: cover;\n background-position: center;\n background-repeat: no-repeat;\n box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);\n color: transparent;\n line-height: 0;\n}\n.ls-color-picker__preview:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n.ls-color-picker__preview:focus {\n outline: none;\n}\n.ls-color-picker__preview:focus-visible {\n box-shadow:\n 0 0 0 2px var(--primary, #ff4076),\n 0 0 0 4px var(--neutralDark1, #1b1a28),\n 0 0 0 1px rgba(0, 0, 0, 0.25);\n}\n.ls-color-picker__gradient circle,\n.ls-color-picker__gradient polyline {\n stroke: #fff;\n}\n.ls-variable-picker {\n --variable-custom-color: var(--customVariables, #69ffd2);\n --variable-function-color: var( --functionVariables, var(--semanticPurple, #b489ff) );\n --variable-normal-color: var(--normalVariables, var(--semanticBlue, #65b8ff));\n display: flex;\n width: 92vw;\n max-width: 1100px;\n min-height: 50vh;\n max-height: 55vh;\n flex-direction: column;\n overflow: hidden;\n padding: 1rem;\n}\n.ls-variable-picker__field {\n margin: 0 0 0.75rem;\n border: 1px solid color-mix(in srgb, var(--primary, #ff4076) 42%, var(--neutralDark4, #393853));\n border-radius: var(--radius, 1rem);\n padding: 0.5rem;\n}\n.ls-variable-picker__legend {\n padding-inline: 0.375rem;\n color: var(--primary, #ff4076);\n font-size: 0.75rem;\n font-weight: 700;\n}\n.ls-variable-picker__intro {\n margin-bottom: 1rem;\n color: var(--neutralLight2, #cac9d5);\n}\n.ls-variable-picker__header,\n.ls-variable-picker__row {\n display: grid;\n grid-template-columns: minmax(300px, 1.5fr) 1fr 1fr;\n gap: 2rem;\n}\n.ls-variable-picker__header {\n margin-bottom: 0.25rem;\n padding-inline: 0.25rem;\n padding-right: 1.7rem;\n color: var(--neutralLight3, #9392a1);\n}\n.ls-variable-picker__list {\n height: 100%;\n overflow: auto;\n padding-right: 1rem;\n}\n.ls-variable-picker__row {\n cursor: pointer;\n align-items: start;\n border-bottom: 1px solid color-mix(in srgb, var(--neutralDark4, #393853) 70%, transparent);\n padding: 1rem 0.25rem;\n}\n.ls-variable-picker__row--no-border {\n border-bottom: 0;\n}\n.ls-variable-picker__token-cell {\n display: flex;\n min-width: 0;\n align-items: center;\n gap: 0.375rem;\n}\n.ls-variable-picker__expand-toggle,\n.ls-variable-picker__expand-spacer {\n width: 24px;\n height: 24px;\n flex: 0 0 24px;\n}\n.ls-variable-picker__expand-toggle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: 1px solid color-mix(in srgb, var(--neutralDark4, #393853) 75%, transparent);\n border-radius: var(--radius, 1rem);\n padding: 0;\n background: var(--neutralDark3, var(--containerbackground, #1f1f3a));\n color: var(--neutralLight2, #cac9d5);\n transition:\n background-color 140ms ease,\n border-color 140ms ease,\n color 140ms ease,\n transform 140ms ease;\n}\n.ls-variable-picker__expand-toggle:hover {\n border-color: var(--primary, #ff4076);\n background: color-mix(in srgb, var(--primary, #ff4076) 16%, var(--neutralDark3, #1f1f3a));\n color: var(--neutralLight1, #fff);\n}\n.ls-variable-picker__expand-toggle svg {\n transform: rotate(-90deg);\n transition: transform 140ms ease;\n}\n.ls-variable-picker__expand-toggle--expanded svg {\n transform: rotate(0deg);\n}\n.ls-variable-picker__row:active {\n opacity: 0.8;\n}\n.ls-variable-picker__description {\n max-width: 600px;\n overflow-wrap: break-word;\n line-height: 1.25;\n word-break: break-all;\n}\n.ls-variable-picker__value {\n min-width: 0;\n}\n.ls-variable-picker__value-input {\n width: 100%;\n min-width: 0;\n cursor: text;\n overflow: hidden;\n border: 0;\n background: transparent;\n color: var(--neutralLight1, var(--white, #fff));\n caret-color: transparent;\n font: inherit;\n font-size: 1rem;\n line-height: 1.25;\n outline: 0;\n padding: 0;\n text-overflow: ellipsis;\n}\n.ls-variable-picker__value-input:focus {\n outline: 0;\n}\n.ls-variable-picker__value-input::selection {\n background: color-mix(in srgb, var(--primary, #ff4076) 45%, transparent);\n color: var(--alwayswhite, var(--white, #fff));\n}\n.ls-variable-token {\n display: flex;\n min-width: 0;\n align-items: center;\n}\n.ls-variable-token--suggested {\n color: var(--suggestedVariables, #ffb469);\n}\n.ls-variable-token--custom {\n color: var(--customVariables, #69ffd2);\n}\n.ls-variable-token--function {\n color: var(--functionVariables, var(--semanticPurple, #b489ff));\n}\n.ls-variable-token--system {\n color: var(--normalVariables, var(--semanticBlue, #65b8ff));\n}\n.ls-variable-token__name {\n min-width: 0;\n word-break: break-all;\n}\n.ls-variable-token__badge {\n display: inline-flex;\n margin-left: 0.5rem;\n flex-shrink: 0;\n align-items: center;\n border: 1px solid currentcolor;\n border-radius: var(--radius, 1rem);\n padding-inline: 0.25rem;\n padding-block: 0;\n font-size: 10px;\n font-weight: 600;\n line-height: 1;\n text-transform: uppercase;\n}\n");
|
|
24
|
+
styleInject(".ls-color-picker,\n.ls-color-picker *,\n.mui-multi-select,\n.mui-multi-select *,\n.ls-multi-select-value,\n.ls-multi-select-value *,\n.ls-variable-picker,\n.ls-variable-picker *,\n.ls-variable-token,\n.ls-variable-token *,\n.ls-font-picker,\n.ls-font-picker *,\n.mui-ls-input,\n.mui-ls-input * {\n box-sizing: border-box;\n}\n.ls-color-picker button,\n.mui-multi-select button {\n font: inherit;\n letter-spacing: inherit;\n color: inherit;\n margin: 0;\n}\n.ls-color-picker__preview {\n appearance: none;\n -webkit-appearance: none;\n background-color: transparent;\n background-image: none;\n cursor: pointer;\n text-transform: uppercase;\n user-select: none;\n}\n.mui-ls-button.Mui-disabled {\n color: var(--neutralLight2, var(--white2, #cac9d5));\n opacity: 0.45;\n background-color: var(--separator, #0a0821);\n cursor: not-allowed;\n}\n.mui-ls-button {\n border-radius: var(--radius, 1rem);\n padding: 0.375rem 1.5rem;\n text-transform: uppercase;\n}\n.mui-ls-button.MuiButton-sizeSmall {\n padding: 0.25rem 1rem;\n}\n.mui-ls-button.MuiButton-sizeLarge {\n padding: 0.625rem 2rem;\n}\n.mui-ls-button--extended {\n padding-inline: 3rem;\n}\n.mui-ls-button.MuiButton-containedPrimary,\n.mui-ls-button.Mui-disabled.MuiButton-containedPrimary {\n background: var(--primary, #ff4076);\n color: var(--alwayswhite, #fff) !important;\n}\n.mui-ls-button.MuiButton-containedSecondary {\n background-color: var(--secondary, #535395);\n color: var(--alwayswhite, #fff) !important;\n}\n.mui-ls-button.Mui-disabled.MuiButton-containedSecondary {\n background-color: var(--secondary, #535395);\n color: var(--neutralLight2, var(--white2, #cac9d5));\n opacity: 0.4;\n}\n.mui-ls-button.MuiButton-outlinedPrimary {\n color: var(--primary, #ff4076);\n border-color: var(--primary, #ff4076);\n}\n.mui-ls-button.MuiButton-outlinedPrimary:hover {\n border-color: var(--primary, #ff4076);\n background-color: color-mix(in srgb, var(--primary, #ff4076) 12%, transparent);\n}\n.mui-ls-button.MuiButton-outlinedSecondary {\n color: var(--neutralLight1, var(--white, #fff));\n border-color: var(--secondary, #535395);\n}\n.mui-ls-button.MuiButton-outlinedSecondary.Mui-disabled {\n color: var(--neutralLight2, var(--white2, #cac9d5));\n border-color: var(--neutralDark4, var(--cardborder, #393853));\n background-color: var(--transwhite, rgba(255, 255, 255, 0.05));\n opacity: 0.5;\n}\n.mui-ls-button.MuiButton-outlinedSecondary:hover {\n border-color: var(--secondary, #535395);\n background-color: var(--transwhite, rgba(255, 255, 255, 0.05));\n}\n.mui-ls-button.MuiButton-containedError {\n color: var(--alwayswhite, #fff) !important;\n}\n.mui-ls-button.MuiButton-outlinedError {\n color: var(--error, #fd5454);\n border-color: var(--error, #fd5454);\n}\n.mui-ls-button.MuiButton-outlinedError:hover {\n border-color: var(--error, #fd5454);\n background-color: color-mix(in srgb, var(--error, #fd5454) 12%, transparent);\n}\n.mui-ls-button--neutral.mui-ls-button--contained {\n background-color: var(--neutralDark4, var(--cardborder, #393853));\n color: var(--neutralLight1, var(--white, #fff)) !important;\n}\n.mui-ls-button--neutral.mui-ls-button--contained:hover {\n background-color: color-mix(in srgb, var(--neutralDark4, var(--cardborder, #393853)) 82%, var(--neutralLight1, #fff));\n}\n.mui-ls-button--neutral.mui-ls-button--outlined {\n color: var(--neutralLight1, var(--white, #fff));\n border-color: var(--neutralDark4, var(--cardborder, #393853));\n background-color: transparent;\n}\n.mui-ls-button--neutral.mui-ls-button--outlined:hover {\n border-color: var(--neutralLight3, var(--grey, #9392a1));\n background-color: var(--transwhite, rgba(255, 255, 255, 0.05));\n}\n.mui-ls-button--neutral.mui-ls-button--text {\n color: var(--neutralLight1, var(--white, #fff));\n}\n.mui-ls-button--neutral.mui-ls-button--text:hover {\n background-color: var(--transwhite, rgba(255, 255, 255, 0.05));\n}\n.mui-ls-button svg {\n max-height: 24px;\n max-width: 24px;\n}\n.mui-ls-input,\n.ls-font-picker,\n.ls-color-picker__input {\n width: 100%;\n}\n.mui-ls-input,\n.mui-ls-select-form-control,\n.mui-multi-select,\n.ls-font-picker,\n.mui-ls-slider-input-root {\n --ls-control-height: 55px;\n}\n.mui-ls-input .MuiOutlinedInput-root,\n.mui-ls-input .MuiInputBase-root,\n.mui-ls-input .MuiOutlinedInput-notchedOutline,\n.mui-ls-select.MuiOutlinedInput-root,\n.mui-ls-select .MuiOutlinedInput-notchedOutline,\n.mui-multi-select .mui-ls-select.MuiOutlinedInput-root,\n.mui-multi-select .mui-ls-select .MuiOutlinedInput-notchedOutline,\n.ls-font-picker .MuiOutlinedInput-root,\n.ls-font-picker .MuiInputBase-root,\n.ls-font-picker .MuiOutlinedInput-notchedOutline,\n.ls-color-picker__input .MuiOutlinedInput-root,\n.ls-color-picker__input .MuiInputBase-root,\n.ls-color-picker__input .MuiOutlinedInput-notchedOutline {\n border-radius: var(--radius) !important;\n}\n.mui-ls-input .MuiInputBase-root,\n.mui-ls-select.MuiInputBase-root,\n.mui-multi-select .mui-ls-select.MuiInputBase-root,\n.ls-font-picker .MuiInputBase-root {\n min-height: var(--ls-control-height);\n}\n.mui-ls-input.small .MuiInputBase-root {\n min-height: 25px;\n}\n.mui-ls-input.medium .MuiInputBase-root {\n min-height: 35px;\n}\n.mui-ls-input.noMinHeight .MuiInputBase-root {\n min-height: unset;\n}\n.mui-ls-date-picker input[type=datetime-local]::-webkit-calendar-picker-indicator {\n cursor: pointer;\n opacity: 0.9;\n filter: invert(1);\n}\n.mui-ls-select .MuiSelect-select,\n.mui-multi-select .MuiSelect-select {\n display: flex;\n min-height: calc(var(--ls-control-height) - 2px);\n align-items: center;\n box-sizing: border-box;\n border-radius: var(--radius);\n}\n.mui-multi-select .MuiSelect-select {\n min-width: 0;\n}\n.MuiSvgIcon-root svg {\n color: var(--neutralLight1, var(--white, #fff)) !important;\n}\n.mui-ls-input .MuiSvgIcon-root svg path {\n fill: currentcolor;\n stroke: currentcolor;\n}\n.mui-ls-input input::placeholder,\n.mui-ls-input textarea::placeholder {\n color: var(--neutralLight3, var(--grey, #9392a1));\n opacity: 0.55;\n font-style: italic;\n}\n.mui-ls-input .MuiInputBase-input,\n.mui-ls-input .MuiInputAdornment-root,\n.mui-ls-input .MuiSvgIcon-root,\n.mui-ls-input .MuiFormHelperText-root {\n color: var(--neutralLight1, var(--white, #fff));\n opacity: 1;\n}\n.mui-ls-input .Mui-focused .MuiOutlinedInput-notchedOutline,\n.mui-ls-input .MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline {\n border-color: var(--primary, #ff4076) !important;\n}\n.ls-variable-autocomplete-popper .MuiAutocomplete-paper,\n.ls-variable-autocomplete-paper {\n border: 1px solid var(--neutralDark4, var(--cardborder, #393853)) !important;\n border-radius: var(--radius, 1rem) !important;\n background: var(--neutralDark2, var(--cardbackground, #211f45)) !important;\n color: var(--neutralLight1, var(--white, #fff)) !important;\n box-shadow: 0 16px 32px rgba(0, 0, 0, 0.32) !important;\n overflow: hidden !important;\n}\n.ls-variable-autocomplete-popper .MuiAutocomplete-listbox,\n.ls-variable-autocomplete-listbox {\n padding: 0.25rem 0 !important;\n background: var(--neutralDark2, var(--cardbackground, #211f45)) !important;\n color: var(--neutralLight1, var(--white, #fff)) !important;\n}\n.ls-variable-autocomplete-popper .MuiAutocomplete-option,\n.ls-variable-autocomplete-listbox .MuiAutocomplete-option {\n display: flex !important;\n min-height: 44px !important;\n align-items: center !important;\n padding: 0.625rem 1rem !important;\n color: var(--neutralLight1, var(--white, #fff)) !important;\n font-size: 1rem !important;\n line-height: 1.35 !important;\n cursor: pointer !important;\n transition: background-color 120ms ease, color 120ms ease !important;\n}\n.ls-variable-autocomplete-popper .MuiAutocomplete-option > *,\n.ls-variable-autocomplete-listbox .MuiAutocomplete-option > * {\n min-width: 0;\n}\n.ls-variable-autocomplete-popper .MuiAutocomplete-option:hover,\n.ls-variable-autocomplete-popper .MuiAutocomplete-option.Mui-focused,\n.ls-variable-autocomplete-popper .MuiAutocomplete-option[data-focus=true],\n.ls-variable-autocomplete-popper .MuiAutocomplete-option[aria-selected=true],\n.ls-variable-autocomplete-listbox .MuiAutocomplete-option:hover,\n.ls-variable-autocomplete-listbox .MuiAutocomplete-option.Mui-focused,\n.ls-variable-autocomplete-listbox .MuiAutocomplete-option[data-focus=true],\n.ls-variable-autocomplete-listbox .MuiAutocomplete-option[aria-selected=true] {\n background: var( --cardHover, var(--transwhite, rgba(255, 255, 255, 0.05)) ) !important;\n color: var(--neutralLight1, var(--white, #fff)) !important;\n}\n.ls-variable-option {\n gap: 0.75rem;\n}\n.ls-variable-option__thumb {\n width: 40px;\n height: 40px;\n flex: 0 0 40px;\n border-radius: var(--radius, 1rem);\n object-fit: cover;\n}\n.ls-variable-option__thumb--placeholder {\n background: var(--neutralDark4, var(--cardborder, #393853));\n}\n.ls-variable-option__body {\n min-width: 0;\n}\n.ls-variable-option__label {\n color: var(--neutralLight1, var(--white, #fff));\n font-weight: 500;\n line-height: 1.25;\n}\n.ls-variable-option__helper {\n margin-top: 0.125rem;\n color: var(--neutralLight3, var(--grey, #9392a1));\n font-size: 0.875rem;\n line-height: 1.25;\n}\n.ls-variable-autocomplete-popup-indicator,\n.ls-variable-autocomplete-popup-indicator.MuiIconButton-root,\n.ls-variable-autocomplete-popup-indicator svg {\n color: var(--neutralLight1, var(--white, #fff)) !important;\n}\n.ls-variable-autocomplete-popup-indicator svg path {\n fill: currentcolor !important;\n stroke: currentcolor !important;\n}\n.ls-variable-input-adornment,\n.ls-variable-input-adornment.MuiInputAdornment-root {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 24px;\n width: 24px;\n min-width: 24px;\n margin-left: 0.35rem;\n border-radius: var(--radius, 1rem);\n background: var(--primary, #ff4076) !important;\n color: var(--alwayswhite, var(--white, #fff)) !important;\n font-weight: 800;\n line-height: 1;\n letter-spacing: 0;\n cursor: pointer;\n user-select: none;\n}\n.ls-variable-input-adornment svg,\n.ls-variable-input-adornment path {\n color: currentcolor !important;\n fill: currentcolor !important;\n stroke: currentcolor !important;\n}\n.ls-variable-input-adornment:hover,\n.ls-variable-input-adornment.MuiInputAdornment-root:hover {\n filter: brightness(1.08);\n}\n.ls-variable-input-adornment:active,\n.ls-variable-input-adornment.MuiInputAdornment-root:active {\n filter: brightness(0.96);\n}\n.mui-ls-slider-input-root {\n width: 100%;\n}\n.mui-ls-slider-input-fieldset {\n position: relative;\n min-width: 0;\n width: 100%;\n min-height: var(--ls-control-height);\n margin: 0;\n border: 2px solid var(--neutralDark4, var(--cardborder, #393853));\n border-radius: var(--radius, 1rem);\n padding: 0 0.875rem 0.5rem 0.875rem;\n background: transparent;\n color: var(--neutralLight1, var(--white, #fff));\n}\n.mui-ls-slider-input-fieldset:hover {\n border-color: var(--primary, #ff4076);\n}\n.mui-ls-slider-input-legend {\n display: block;\n width: auto;\n max-width: calc(100% - 1rem);\n margin: 0;\n padding: 0 0.25rem;\n color: var(--neutralLight1, var(--white, #fff));\n font-size: 0.875rem;\n line-height: 1.1;\n white-space: nowrap;\n}\n.mui-ls-slider-input-row {\n display: flex;\n min-width: 0;\n min-height: calc(var(--ls-control-height) - 14px);\n align-items: center;\n gap: 1rem;\n}\n.mui-ls-slider-input-row--slider {\n flex-wrap: nowrap;\n}\n.mui-ls-slider-input-row--input {\n justify-content: stretch;\n}\n.mui-ls-slider-input-value.mui-ls-input {\n margin: 0;\n}\n.mui-ls-slider-input-value.mui-ls-input .MuiFormControl-root,\n.mui-ls-slider-input-value.mui-ls-input .MuiTextField-root {\n margin: 0;\n}\n.mui-ls-slider-input-value.mui-ls-input .MuiInputBase-root {\n min-height: 36px;\n}\n.mui-ls-slider-input-value.mui-ls-input .MuiOutlinedInput-notchedOutline {\n border-color: var(--neutralDark4, var(--cardborder, #393853));\n}\n.mui-ls-slider-input-helper {\n display: block;\n margin-top: 0.25rem;\n color: var(--neutralLight3, var(--grey, #9392a1));\n font-size: 0.75rem;\n line-height: 1.25;\n}\n.ls-multi-select-value {\n display: flex;\n width: 100%;\n min-width: 0;\n flex-wrap: nowrap;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n overflow: hidden;\n white-space: nowrap;\n}\n.ls-multi-select-value__label {\n min-width: 0;\n flex: 1 1 0%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.ls-multi-select-value__count {\n flex-shrink: 0;\n white-space: nowrap;\n}\n.ls-color-picker__preview {\n position: relative;\n display: inline-block;\n width: 1.5rem;\n height: 1.5rem;\n flex-shrink: 0;\n padding: 0;\n border: 1px solid color-mix(in srgb, #fff 25%, transparent);\n border-radius: var(--radius, 1rem);\n background-size: cover;\n background-position: center;\n background-repeat: no-repeat;\n box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);\n color: transparent;\n line-height: 0;\n}\n.ls-color-picker__preview:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n.ls-color-picker__preview:focus {\n outline: none;\n}\n.ls-color-picker__preview:focus-visible {\n box-shadow:\n 0 0 0 2px var(--primary, #ff4076),\n 0 0 0 4px var(--neutralDark1, #1b1a28),\n 0 0 0 1px rgba(0, 0, 0, 0.25);\n}\n.ls-color-picker__gradient circle,\n.ls-color-picker__gradient polyline {\n stroke: #fff;\n}\n.ls-variable-picker {\n --variable-custom-color: var(--customVariables, #69ffd2);\n --variable-function-color: var( --functionVariables, var(--semanticPurple, #b489ff) );\n --variable-normal-color: var(--normalVariables, var(--semanticBlue, #65b8ff));\n display: flex;\n width: 92vw;\n max-width: 1100px;\n min-height: 50vh;\n max-height: 55vh;\n flex-direction: column;\n overflow: hidden;\n padding: 1rem;\n}\n.ls-variable-picker__field {\n margin: 0 0 0.75rem;\n border: 1px solid color-mix(in srgb, var(--primary, #ff4076) 42%, var(--neutralDark4, #393853));\n border-radius: var(--radius, 1rem);\n padding: 0.5rem;\n}\n.ls-variable-picker__legend {\n padding-inline: 0.375rem;\n color: var(--primary, #ff4076);\n font-size: 0.75rem;\n font-weight: 700;\n}\n.ls-variable-picker__intro {\n margin-bottom: 1rem;\n color: var(--neutralLight2, #cac9d5);\n}\n.ls-variable-picker__header,\n.ls-variable-picker__row {\n display: grid;\n grid-template-columns: minmax(300px, 1.5fr) 1fr 1fr;\n gap: 2rem;\n}\n.ls-variable-picker__header {\n margin-bottom: 0.25rem;\n padding-inline: 0.25rem;\n padding-right: 1.7rem;\n color: var(--neutralLight3, #9392a1);\n}\n.ls-variable-picker__list {\n height: 100%;\n overflow: auto;\n padding-right: 1rem;\n}\n.ls-variable-picker__row {\n cursor: pointer;\n align-items: start;\n border-bottom: 1px solid color-mix(in srgb, var(--neutralDark4, #393853) 70%, transparent);\n padding: 1rem 0.25rem;\n}\n.ls-variable-picker__row--no-border {\n border-bottom: 0;\n}\n.ls-variable-picker__token-cell {\n display: flex;\n min-width: 0;\n align-items: center;\n gap: 0.375rem;\n}\n.ls-variable-picker__expand-toggle,\n.ls-variable-picker__expand-spacer {\n width: 24px;\n height: 24px;\n flex: 0 0 24px;\n}\n.ls-variable-picker__expand-toggle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: 1px solid color-mix(in srgb, var(--neutralDark4, #393853) 75%, transparent);\n border-radius: var(--radius, 1rem);\n padding: 0;\n background: var(--neutralDark3, var(--containerbackground, #1f1f3a));\n color: var(--neutralLight2, #cac9d5);\n transition:\n background-color 140ms ease,\n border-color 140ms ease,\n color 140ms ease,\n transform 140ms ease;\n}\n.ls-variable-picker__expand-toggle:hover {\n border-color: var(--primary, #ff4076);\n background: color-mix(in srgb, var(--primary, #ff4076) 16%, var(--neutralDark3, #1f1f3a));\n color: var(--neutralLight1, #fff);\n}\n.ls-variable-picker__expand-toggle svg {\n transform: rotate(-90deg);\n transition: transform 140ms ease;\n}\n.ls-variable-picker__expand-toggle--expanded svg {\n transform: rotate(0deg);\n}\n.ls-variable-picker__row:active {\n opacity: 0.8;\n}\n.ls-variable-picker__description {\n max-width: 600px;\n overflow-wrap: break-word;\n line-height: 1.25;\n word-break: break-all;\n}\n.ls-variable-picker__value {\n min-width: 0;\n}\n.ls-variable-picker__value-input {\n width: 100%;\n min-width: 0;\n cursor: text;\n overflow: hidden;\n border: 0;\n background: transparent;\n color: var(--neutralLight1, var(--white, #fff));\n caret-color: transparent;\n font: inherit;\n font-size: 1rem;\n line-height: 1.25;\n outline: 0;\n padding: 0;\n text-overflow: ellipsis;\n}\n.ls-variable-picker__value-input:focus {\n outline: 0;\n}\n.ls-variable-picker__value-input::selection {\n background: color-mix(in srgb, var(--primary, #ff4076) 45%, transparent);\n color: var(--alwayswhite, var(--white, #fff));\n}\n.ls-variable-token {\n display: flex;\n min-width: 0;\n align-items: center;\n}\n.ls-variable-token--suggested {\n color: var(--suggestedVariables, #ffb469);\n}\n.ls-variable-token--custom {\n color: var(--customVariables, #69ffd2);\n}\n.ls-variable-token--function {\n color: var(--functionVariables, var(--semanticPurple, #b489ff));\n}\n.ls-variable-token--system {\n color: var(--normalVariables, var(--semanticBlue, #65b8ff));\n}\n.ls-variable-token__name {\n min-width: 0;\n word-break: break-all;\n}\n.ls-variable-token__badge {\n display: inline-flex;\n margin-left: 0.5rem;\n flex-shrink: 0;\n align-items: center;\n border: 1px solid currentcolor;\n border-radius: var(--radius, 1rem);\n padding-inline: 0.25rem;\n padding-block: 0;\n font-size: 10px;\n font-weight: 600;\n line-height: 1;\n text-transform: uppercase;\n}\n");
|
|
25
25
|
|
|
26
26
|
// src/components/LSButton/LSButton.tsx
|
|
27
27
|
import Button from "@mui/material/Button";
|
|
@@ -3133,7 +3133,7 @@ var resolveChatterProfileUrlWithResolvers = async ({
|
|
|
3133
3133
|
};
|
|
3134
3134
|
|
|
3135
3135
|
// src/se-import/index.ts
|
|
3136
|
-
import { nanoid as
|
|
3136
|
+
import { nanoid as nanoid8 } from "nanoid";
|
|
3137
3137
|
|
|
3138
3138
|
// src/se-import/translate.ts
|
|
3139
3139
|
var SE_TO_LUMIA_PLACEHOLDER = {
|
|
@@ -4198,12 +4198,26 @@ function mapImage(widget, ctx) {
|
|
|
4198
4198
|
);
|
|
4199
4199
|
const innerWidth = widget.image?.css?.width;
|
|
4200
4200
|
const innerHeight = widget.image?.css?.height;
|
|
4201
|
+
const outerWidthExplicit = isExplicitPxSize(widget.css?.width);
|
|
4202
|
+
const outerHeightExplicit = isExplicitPxSize(widget.css?.height);
|
|
4201
4203
|
const bounds = unit.layer.bounds;
|
|
4202
|
-
if (innerWidth === "auto") bounds.autoWidth = true;
|
|
4203
|
-
if (innerHeight === "auto") bounds.autoHeight = true;
|
|
4204
|
+
if (innerWidth === "auto" && !outerWidthExplicit) bounds.autoWidth = true;
|
|
4205
|
+
if (innerHeight === "auto" && !outerHeightExplicit) bounds.autoHeight = true;
|
|
4204
4206
|
return unit;
|
|
4205
4207
|
}
|
|
4208
|
+
function isExplicitPxSize(value) {
|
|
4209
|
+
if (value == null) return false;
|
|
4210
|
+
if (typeof value === "number") return Number.isFinite(value) && value > 0;
|
|
4211
|
+
if (typeof value !== "string") return false;
|
|
4212
|
+
const s = value.trim().toLowerCase();
|
|
4213
|
+
if (s === "" || s === "auto") return false;
|
|
4214
|
+
if (s.endsWith("%")) return false;
|
|
4215
|
+
const parsed = parseFloat(s);
|
|
4216
|
+
return Number.isFinite(parsed) && parsed > 0;
|
|
4217
|
+
}
|
|
4206
4218
|
function mapVideo(widget, ctx) {
|
|
4219
|
+
const innerWidth = widget.video?.css?.width;
|
|
4220
|
+
const isInnerAutoWidth = innerWidth === "auto";
|
|
4207
4221
|
const unit = buildUnit(
|
|
4208
4222
|
widget,
|
|
4209
4223
|
"video",
|
|
@@ -4212,12 +4226,19 @@ function mapVideo(widget, ctx) {
|
|
|
4212
4226
|
src: widget.video?.src ?? "",
|
|
4213
4227
|
volume: widget.video?.volume ?? 0.5,
|
|
4214
4228
|
loop: true,
|
|
4215
|
-
muted: false
|
|
4229
|
+
muted: false,
|
|
4230
|
+
...isInnerAutoWidth ? { objectFit: "contain" } : {}
|
|
4216
4231
|
}
|
|
4217
4232
|
},
|
|
4218
4233
|
ctx
|
|
4219
4234
|
);
|
|
4220
|
-
unit.layer.bounds
|
|
4235
|
+
const bounds = unit.layer.bounds;
|
|
4236
|
+
if (isInnerAutoWidth) {
|
|
4237
|
+
bounds.autoWidth = true;
|
|
4238
|
+
bounds.autoHeight = true;
|
|
4239
|
+
} else {
|
|
4240
|
+
bounds.autoHeight = true;
|
|
4241
|
+
}
|
|
4221
4242
|
return unit;
|
|
4222
4243
|
}
|
|
4223
4244
|
var LUMIA_SNOW_WEBM = "https://storage.lumiastream.com/overlays/global/seasonal/snow.webm";
|
|
@@ -4276,118 +4297,157 @@ function mapReadout(widget, fallbackVar, ctx) {
|
|
|
4276
4297
|
|
|
4277
4298
|
// src/se-import/mappers/alert.ts
|
|
4278
4299
|
import { LumiaAlertConfigs } from "@lumiastream/lumia-types";
|
|
4300
|
+
import { nanoid as nanoid2 } from "nanoid";
|
|
4301
|
+
|
|
4302
|
+
// src/se-import/import-utils.ts
|
|
4303
|
+
function pxToNumber(raw, fallback) {
|
|
4304
|
+
if (typeof raw === "number" && Number.isFinite(raw)) return raw;
|
|
4305
|
+
if (typeof raw !== "string") return fallback;
|
|
4306
|
+
const trimmed = raw.trim();
|
|
4307
|
+
if (!trimmed) return fallback;
|
|
4308
|
+
if (trimmed.endsWith("px")) {
|
|
4309
|
+
const n2 = parseFloat(trimmed.slice(0, -2));
|
|
4310
|
+
return Number.isFinite(n2) ? n2 : fallback;
|
|
4311
|
+
}
|
|
4312
|
+
const n = parseFloat(trimmed);
|
|
4313
|
+
return Number.isFinite(n) ? n : fallback;
|
|
4314
|
+
}
|
|
4315
|
+
function parseDurationMs(raw, fallbackMs) {
|
|
4316
|
+
if (typeof raw === "number" && Number.isFinite(raw)) return raw;
|
|
4317
|
+
if (typeof raw !== "string") return fallbackMs;
|
|
4318
|
+
const trimmed = raw.trim();
|
|
4319
|
+
if (!trimmed) return fallbackMs;
|
|
4320
|
+
if (trimmed.endsWith("ms")) {
|
|
4321
|
+
const n2 = parseFloat(trimmed.slice(0, -2));
|
|
4322
|
+
return Number.isFinite(n2) ? n2 : fallbackMs;
|
|
4323
|
+
}
|
|
4324
|
+
if (trimmed.endsWith("s")) {
|
|
4325
|
+
const n2 = parseFloat(trimmed.slice(0, -1));
|
|
4326
|
+
return Number.isFinite(n2) ? n2 * 1e3 : fallbackMs;
|
|
4327
|
+
}
|
|
4328
|
+
const n = parseFloat(trimmed);
|
|
4329
|
+
return Number.isFinite(n) ? n : fallbackMs;
|
|
4330
|
+
}
|
|
4331
|
+
function buildImportDescription(head, sourceUrl) {
|
|
4332
|
+
if (typeof sourceUrl === "string" && sourceUrl.trim().length > 0) {
|
|
4333
|
+
return `${head}
|
|
4334
|
+
Source: ${sourceUrl.trim()}`;
|
|
4335
|
+
}
|
|
4336
|
+
return head;
|
|
4337
|
+
}
|
|
4279
4338
|
|
|
4280
4339
|
// src/se-import/mappers/provider-alerts.ts
|
|
4340
|
+
import { LumiaAlertValues } from "@lumiastream/lumia-types";
|
|
4281
4341
|
var ALERT_BOX_KEYS = {
|
|
4282
4342
|
twitch: {
|
|
4283
|
-
follower: [
|
|
4284
|
-
subscriber: [
|
|
4285
|
-
tip: [
|
|
4286
|
-
cheer: [
|
|
4287
|
-
raid: [
|
|
4288
|
-
merch: [
|
|
4289
|
-
purchase: [
|
|
4290
|
-
charityCampaignDonation: [
|
|
4343
|
+
follower: [LumiaAlertValues.TWITCH_FOLLOWER],
|
|
4344
|
+
subscriber: [LumiaAlertValues.TWITCH_SUBSCRIBER],
|
|
4345
|
+
tip: [LumiaAlertValues.LUMIASTREAM_DONATION, LumiaAlertValues.STREAMELEMENTS_DONATION],
|
|
4346
|
+
cheer: [LumiaAlertValues.TWITCH_BITS],
|
|
4347
|
+
raid: [LumiaAlertValues.TWITCH_RAID],
|
|
4348
|
+
merch: [LumiaAlertValues.FOURTHWALL_SHOPORDER],
|
|
4349
|
+
purchase: [LumiaAlertValues.FOURTHWALL_SHOPORDER],
|
|
4350
|
+
charityCampaignDonation: [LumiaAlertValues.TWITCH_CHARITY_DONATION]
|
|
4291
4351
|
},
|
|
4292
4352
|
kick: {
|
|
4293
|
-
follower: [
|
|
4294
|
-
subscriber: [
|
|
4295
|
-
tip: [
|
|
4296
|
-
cheer: [
|
|
4297
|
-
raid: [
|
|
4298
|
-
host: [
|
|
4299
|
-
merch: [
|
|
4300
|
-
purchase: [
|
|
4353
|
+
follower: [LumiaAlertValues.KICK_FOLLOWER],
|
|
4354
|
+
subscriber: [LumiaAlertValues.KICK_SUBSCRIBER],
|
|
4355
|
+
tip: [LumiaAlertValues.LUMIASTREAM_DONATION, LumiaAlertValues.STREAMELEMENTS_DONATION],
|
|
4356
|
+
cheer: [LumiaAlertValues.KICK_KICKS],
|
|
4357
|
+
raid: [LumiaAlertValues.KICK_HOST],
|
|
4358
|
+
host: [LumiaAlertValues.KICK_HOST],
|
|
4359
|
+
merch: [LumiaAlertValues.FOURTHWALL_SHOPORDER],
|
|
4360
|
+
purchase: [LumiaAlertValues.FOURTHWALL_SHOPORDER]
|
|
4301
4361
|
},
|
|
4302
4362
|
youtube: {
|
|
4303
|
-
follower: [
|
|
4304
|
-
subscriber: [
|
|
4305
|
-
tip: [
|
|
4306
|
-
cheer: [
|
|
4307
|
-
merch: [
|
|
4308
|
-
purchase: [
|
|
4363
|
+
follower: [LumiaAlertValues.YOUTUBE_SUBSCRIBER],
|
|
4364
|
+
subscriber: [LumiaAlertValues.YOUTUBE_MEMBER],
|
|
4365
|
+
tip: [LumiaAlertValues.LUMIASTREAM_DONATION, LumiaAlertValues.STREAMELEMENTS_DONATION],
|
|
4366
|
+
cheer: [LumiaAlertValues.YOUTUBE_SUPERCHAT],
|
|
4367
|
+
merch: [LumiaAlertValues.FOURTHWALL_SHOPORDER],
|
|
4368
|
+
purchase: [LumiaAlertValues.FOURTHWALL_SHOPORDER]
|
|
4309
4369
|
}
|
|
4310
4370
|
};
|
|
4311
4371
|
var KAPPAGEN_KEYS = {
|
|
4312
4372
|
twitch: {
|
|
4313
|
-
follower:
|
|
4314
|
-
subscriber:
|
|
4315
|
-
cheer:
|
|
4316
|
-
raid:
|
|
4317
|
-
tip:
|
|
4373
|
+
follower: LumiaAlertValues.TWITCH_FOLLOWER,
|
|
4374
|
+
subscriber: LumiaAlertValues.TWITCH_SUBSCRIBER,
|
|
4375
|
+
cheer: LumiaAlertValues.TWITCH_BITS,
|
|
4376
|
+
raid: LumiaAlertValues.TWITCH_RAID,
|
|
4377
|
+
tip: LumiaAlertValues.LUMIASTREAM_DONATION
|
|
4318
4378
|
},
|
|
4319
4379
|
kick: {
|
|
4320
|
-
follower:
|
|
4321
|
-
subscriber:
|
|
4322
|
-
cheer:
|
|
4323
|
-
raid:
|
|
4324
|
-
tip:
|
|
4380
|
+
follower: LumiaAlertValues.KICK_FOLLOWER,
|
|
4381
|
+
subscriber: LumiaAlertValues.KICK_SUBSCRIBER,
|
|
4382
|
+
cheer: LumiaAlertValues.KICK_KICKS,
|
|
4383
|
+
raid: LumiaAlertValues.KICK_HOST,
|
|
4384
|
+
tip: LumiaAlertValues.LUMIASTREAM_DONATION
|
|
4325
4385
|
},
|
|
4326
4386
|
youtube: {
|
|
4327
|
-
follower:
|
|
4328
|
-
subscriber:
|
|
4329
|
-
cheer:
|
|
4330
|
-
tip:
|
|
4387
|
+
follower: LumiaAlertValues.YOUTUBE_SUBSCRIBER,
|
|
4388
|
+
subscriber: LumiaAlertValues.YOUTUBE_MEMBER,
|
|
4389
|
+
cheer: LumiaAlertValues.YOUTUBE_SUPERCHAT,
|
|
4390
|
+
tip: LumiaAlertValues.LUMIASTREAM_DONATION
|
|
4331
4391
|
}
|
|
4332
4392
|
};
|
|
4333
4393
|
var STREAMBOSS_LISTENER_KEYS = {
|
|
4334
4394
|
twitch: {
|
|
4335
|
-
"follower-latest": [
|
|
4336
|
-
"subscriber-latest": [
|
|
4337
|
-
"tip-latest": [
|
|
4338
|
-
"cheer-latest": [
|
|
4339
|
-
"raid-latest": [
|
|
4395
|
+
"follower-latest": [LumiaAlertValues.TWITCH_FOLLOWER],
|
|
4396
|
+
"subscriber-latest": [LumiaAlertValues.TWITCH_SUBSCRIBER],
|
|
4397
|
+
"tip-latest": [LumiaAlertValues.LUMIASTREAM_DONATION, LumiaAlertValues.STREAMELEMENTS_DONATION],
|
|
4398
|
+
"cheer-latest": [LumiaAlertValues.TWITCH_BITS],
|
|
4399
|
+
"raid-latest": [LumiaAlertValues.TWITCH_RAID]
|
|
4340
4400
|
},
|
|
4341
4401
|
kick: {
|
|
4342
|
-
"follower-latest": [
|
|
4343
|
-
"subscriber-latest": [
|
|
4344
|
-
"tip-latest": [
|
|
4345
|
-
"cheer-latest": [
|
|
4346
|
-
"raid-latest": [
|
|
4402
|
+
"follower-latest": [LumiaAlertValues.KICK_FOLLOWER],
|
|
4403
|
+
"subscriber-latest": [LumiaAlertValues.KICK_SUBSCRIBER],
|
|
4404
|
+
"tip-latest": [LumiaAlertValues.LUMIASTREAM_DONATION, LumiaAlertValues.STREAMELEMENTS_DONATION],
|
|
4405
|
+
"cheer-latest": [LumiaAlertValues.KICK_KICKS],
|
|
4406
|
+
"raid-latest": [LumiaAlertValues.KICK_HOST]
|
|
4347
4407
|
},
|
|
4348
4408
|
youtube: {
|
|
4349
|
-
"follower-latest": [
|
|
4350
|
-
"subscriber-latest": [
|
|
4351
|
-
"tip-latest": [
|
|
4352
|
-
"cheer-latest": [
|
|
4409
|
+
"follower-latest": [LumiaAlertValues.YOUTUBE_SUBSCRIBER],
|
|
4410
|
+
"subscriber-latest": [LumiaAlertValues.YOUTUBE_MEMBER],
|
|
4411
|
+
"tip-latest": [LumiaAlertValues.LUMIASTREAM_DONATION, LumiaAlertValues.STREAMELEMENTS_DONATION],
|
|
4412
|
+
"cheer-latest": [LumiaAlertValues.YOUTUBE_SUPERCHAT]
|
|
4353
4413
|
}
|
|
4354
4414
|
};
|
|
4355
4415
|
var CURATED_ALERTS = {
|
|
4356
4416
|
twitch: [
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4417
|
+
LumiaAlertValues.TWITCH_FOLLOWER,
|
|
4418
|
+
LumiaAlertValues.TWITCH_SUBSCRIBER,
|
|
4419
|
+
LumiaAlertValues.TWITCH_GIFT_SUBSCRIPTION,
|
|
4420
|
+
LumiaAlertValues.TWITCH_BITS,
|
|
4421
|
+
LumiaAlertValues.TWITCH_BITS_COMBO,
|
|
4422
|
+
LumiaAlertValues.TWITCH_RAID,
|
|
4423
|
+
LumiaAlertValues.TWITCH_POINTS,
|
|
4424
|
+
LumiaAlertValues.TWITCH_REDEMPTION,
|
|
4425
|
+
LumiaAlertValues.TWITCH_CHARITY_DONATION,
|
|
4426
|
+
LumiaAlertValues.TWITCH_HYPETRAIN_STARTED,
|
|
4427
|
+
LumiaAlertValues.TWITCH_CLIP,
|
|
4428
|
+
LumiaAlertValues.TWITCH_SHOUTOUT_RECEIVE,
|
|
4429
|
+
LumiaAlertValues.TWITCH_WATCH_STREAK,
|
|
4430
|
+
LumiaAlertValues.TWITCH_FIRST_CHATTER,
|
|
4431
|
+
LumiaAlertValues.TWITCH_EXTENSION
|
|
4372
4432
|
],
|
|
4373
4433
|
kick: [
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4434
|
+
LumiaAlertValues.KICK_FOLLOWER,
|
|
4435
|
+
LumiaAlertValues.KICK_SUBSCRIBER,
|
|
4436
|
+
LumiaAlertValues.KICK_GIFT_SUBSCRIPTION,
|
|
4437
|
+
LumiaAlertValues.KICK_KICKS,
|
|
4438
|
+
LumiaAlertValues.KICK_HOST,
|
|
4439
|
+
LumiaAlertValues.KICK_POINTS,
|
|
4440
|
+
LumiaAlertValues.KICK_FIRST_CHATTER
|
|
4381
4441
|
],
|
|
4382
4442
|
youtube: [
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4443
|
+
LumiaAlertValues.YOUTUBE_SUBSCRIBER,
|
|
4444
|
+
LumiaAlertValues.YOUTUBE_MEMBER,
|
|
4445
|
+
LumiaAlertValues.YOUTUBE_GIFT_MEMBERS,
|
|
4446
|
+
LumiaAlertValues.YOUTUBE_SUPERCHAT,
|
|
4447
|
+
LumiaAlertValues.YOUTUBE_SUPERSTICKER,
|
|
4448
|
+
LumiaAlertValues.YOUTUBE_GIFTS,
|
|
4449
|
+
LumiaAlertValues.YOUTUBE_LIKE,
|
|
4450
|
+
LumiaAlertValues.YOUTUBE_FIRST_CHATTER
|
|
4391
4451
|
]
|
|
4392
4452
|
};
|
|
4393
4453
|
function curatedAlertsFor(provider = "twitch") {
|
|
@@ -4455,8 +4515,12 @@ function buildAlertEvent(seEvent, seEventType) {
|
|
|
4455
4515
|
const shadowEnabled = text.enableShadow !== false;
|
|
4456
4516
|
const importedTextShadow = css["text-shadow"] ?? "rgba(0, 0, 0, 0.8) 1px 1px 1px";
|
|
4457
4517
|
const textShadow = shadowEnabled ? importedTextShadow : "none";
|
|
4458
|
-
const
|
|
4459
|
-
const pushTextUp =
|
|
4518
|
+
const allowPush = seLayoutUsesPushText(seEvent.layout);
|
|
4519
|
+
const pushTextUp = allowPush ? pxToNumber(css["margin-top"], 0) : 0;
|
|
4520
|
+
const pushTextLeft = allowPush ? pxToNumber(css["margin-left"], 0) : 0;
|
|
4521
|
+
const usesColumnLayout = !seEvent.layout || seEvent.layout === "column";
|
|
4522
|
+
const usesRowLayout = seEvent.layout === "row";
|
|
4523
|
+
const tightLayout = allowPush && (usesColumnLayout || usesRowLayout);
|
|
4460
4524
|
const variations = (seEvent.variations ?? []).map((variation) => buildAlertVariation(variation, seEventType, seEvent)).filter((v) => v != null);
|
|
4461
4525
|
const defaultDuration = (seEventType && SE_DEFAULT_DURATION_BY_EVENT[seEventType]) ?? 8;
|
|
4462
4526
|
return {
|
|
@@ -4483,7 +4547,7 @@ function buildAlertEvent(seEvent, seEventType) {
|
|
|
4483
4547
|
showBrandIcon: true
|
|
4484
4548
|
},
|
|
4485
4549
|
settings: { duration: (seEvent.duration ?? defaultDuration) * 1e3 },
|
|
4486
|
-
layout: { value: translateLayout(seEvent.layout), css: {}, customCss: "", pushTextUp, pushTextLeft:
|
|
4550
|
+
layout: { value: translateLayout(seEvent.layout), css: {}, customCss: "", pushTextUp, pushTextLeft, tight: tightLayout },
|
|
4487
4551
|
text: {
|
|
4488
4552
|
css: {
|
|
4489
4553
|
fontFamily: css["font-family"] ?? "Roboto",
|
|
@@ -4492,6 +4556,10 @@ function buildAlertEvent(seEvent, seEventType) {
|
|
|
4492
4556
|
fontWeight: css["font-weight"] ?? "bold",
|
|
4493
4557
|
textShadow,
|
|
4494
4558
|
textAlign: css["text-align"] ?? "center"
|
|
4559
|
+
// SE's per-event `margin-top` / `margin-left` are routed to
|
|
4560
|
+
// `layout.pushTextUp` / `layout.pushTextLeft` above (not
|
|
4561
|
+
// stamped on `text.css`) so they land in the alert editor's
|
|
4562
|
+
// dedicated sliders. See the long comment near `pushTextUp`.
|
|
4495
4563
|
},
|
|
4496
4564
|
messageCss,
|
|
4497
4565
|
content: { value: translateSeText(text.message ?? "") }
|
|
@@ -4561,6 +4629,15 @@ function buildAlertVariation(v, seEventType, parentSettings) {
|
|
|
4561
4629
|
const mergedSettings = deepMergeSeSettings(parentSettings ? parentInheritable : void 0, v.settings);
|
|
4562
4630
|
const base = buildAlertEvent(mergedSettings, seEventType);
|
|
4563
4631
|
return {
|
|
4632
|
+
// Stable per-variation ID. Lumia's alert editor (Settings.tsx) auto-
|
|
4633
|
+
// stamps a nanoid on first open for any variation missing an id, but
|
|
4634
|
+
// that leaves a window where the imported overlay's variations have
|
|
4635
|
+
// no stable key — list components rendering them key on
|
|
4636
|
+
// `variation.id || variation.name || idx` and adjacent variations
|
|
4637
|
+
// with the same name collide. Stamping at import time gives every
|
|
4638
|
+
// variation a stable identity from save #1 without waiting for the
|
|
4639
|
+
// editor's first mount.
|
|
4640
|
+
id: nanoid2(),
|
|
4564
4641
|
name: v.name ?? "Variation",
|
|
4565
4642
|
on: v.enabled !== false,
|
|
4566
4643
|
randomChance: v.chance ?? 100,
|
|
@@ -4644,7 +4721,7 @@ function mapSingleAlert(widget, lumiaAlertKey, ctx) {
|
|
|
4644
4721
|
css: { ...topCss, ...innerCss }
|
|
4645
4722
|
};
|
|
4646
4723
|
}
|
|
4647
|
-
const built = buildAlertEvent(merged);
|
|
4724
|
+
const built = buildAlertEvent(merged, void 0);
|
|
4648
4725
|
const events = {
|
|
4649
4726
|
[lumiaAlertKey]: built
|
|
4650
4727
|
};
|
|
@@ -4790,7 +4867,7 @@ function mapGoal(widget, ctx) {
|
|
|
4790
4867
|
}
|
|
4791
4868
|
|
|
4792
4869
|
// src/se-import/mappers/custom.ts
|
|
4793
|
-
import { nanoid as
|
|
4870
|
+
import { nanoid as nanoid3 } from "nanoid";
|
|
4794
4871
|
var SOURCE_TO_LUMIA_FIELD_TYPE = {
|
|
4795
4872
|
text: "input",
|
|
4796
4873
|
number: "number",
|
|
@@ -4880,7 +4957,7 @@ function mapCustom(widget, ctx) {
|
|
|
4880
4957
|
// imports — codeId is the scoping key for variables, storage, and
|
|
4881
4958
|
// event listeners. Mint a fresh nanoid so every imported widget
|
|
4882
4959
|
// has its own scope.
|
|
4883
|
-
codeId:
|
|
4960
|
+
codeId: nanoid3(),
|
|
4884
4961
|
html: v.html ?? "",
|
|
4885
4962
|
css: v.css ?? "",
|
|
4886
4963
|
js: v.js ?? "",
|
|
@@ -5017,6 +5094,63 @@ var TIPJAR_DEFAULT_MODULE = {
|
|
|
5017
5094
|
version: 1,
|
|
5018
5095
|
content: TIPJAR_DEFAULT_CONTENT_FIELDS
|
|
5019
5096
|
};
|
|
5097
|
+
var EVENTLIST_DEFAULT_CONTENT_FIELDS = {
|
|
5098
|
+
version: 2,
|
|
5099
|
+
eventListType: {},
|
|
5100
|
+
theme: "basic",
|
|
5101
|
+
themeConfig: {},
|
|
5102
|
+
borderRadius: "10px",
|
|
5103
|
+
condensedText: true,
|
|
5104
|
+
src: "",
|
|
5105
|
+
// Category blacklist — events whose Lumia type appears here are
|
|
5106
|
+
// hidden. SL `show_<type>: false` maps to inserting the equivalent
|
|
5107
|
+
// Lumia category here.
|
|
5108
|
+
filters: [],
|
|
5109
|
+
sites: [],
|
|
5110
|
+
maxItemsToShow: 20,
|
|
5111
|
+
removeAfter: 0,
|
|
5112
|
+
reverse: false,
|
|
5113
|
+
horizontal: false,
|
|
5114
|
+
animations: {
|
|
5115
|
+
enterAnimation: "fadeIn",
|
|
5116
|
+
exitAnimation: "fadeOut",
|
|
5117
|
+
enterAnimationDuration: 1e3,
|
|
5118
|
+
exitAnimationDuration: 1e3,
|
|
5119
|
+
enterAnimationDelay: 0,
|
|
5120
|
+
exitAnimationDelay: 0
|
|
5121
|
+
},
|
|
5122
|
+
showDetailedText: true,
|
|
5123
|
+
hideAlertMessage: false,
|
|
5124
|
+
showAlertIcon: true,
|
|
5125
|
+
showSiteIcon: false,
|
|
5126
|
+
showUserAvatar: false,
|
|
5127
|
+
fadeOutAfterDelay: false,
|
|
5128
|
+
fadeOutDelayTime: 5,
|
|
5129
|
+
image: "",
|
|
5130
|
+
itemGap: 16,
|
|
5131
|
+
audio: {
|
|
5132
|
+
enter: "",
|
|
5133
|
+
volume: 1
|
|
5134
|
+
}
|
|
5135
|
+
};
|
|
5136
|
+
var EVENTLIST_DEFAULT_MODULE = {
|
|
5137
|
+
version: 2,
|
|
5138
|
+
content: EVENTLIST_DEFAULT_CONTENT_FIELDS,
|
|
5139
|
+
css: {
|
|
5140
|
+
borderRadius: "0px",
|
|
5141
|
+
borderStyle: "solid",
|
|
5142
|
+
borderWidth: "0px",
|
|
5143
|
+
borderColor: "transparent",
|
|
5144
|
+
fontSize: 16,
|
|
5145
|
+
lineHeight: 1.2,
|
|
5146
|
+
textAlign: "left",
|
|
5147
|
+
fontFamily: "Roboto",
|
|
5148
|
+
fontWeight: "normal",
|
|
5149
|
+
color: "#ffffff",
|
|
5150
|
+
textShadow: "",
|
|
5151
|
+
background: "transparent"
|
|
5152
|
+
}
|
|
5153
|
+
};
|
|
5020
5154
|
|
|
5021
5155
|
// src/se-import/mappers/misc.ts
|
|
5022
5156
|
function mapChatboxTheme(seTheme) {
|
|
@@ -6966,11 +7100,6 @@ function rewriteAssetURLs(overlay, mapping) {
|
|
|
6966
7100
|
};
|
|
6967
7101
|
}
|
|
6968
7102
|
var MAX_MIRROR_ASSET_BYTES = 100 * 1024 * 1024;
|
|
6969
|
-
function looksLikeCorsError2(err) {
|
|
6970
|
-
if (!(err instanceof TypeError)) return false;
|
|
6971
|
-
const msg = (err.message ?? "").toLowerCase();
|
|
6972
|
-
return msg.includes("failed to fetch") || msg.includes("networkerror") || msg.includes("network error") || msg.includes("cors") || msg.includes("access-control") || err.message.length > 0;
|
|
6973
|
-
}
|
|
6974
7103
|
async function mirrorOneAsset(url, upload, signal, proxyAssetFetch) {
|
|
6975
7104
|
const blob = await fetchAssetBlob(url, signal, proxyAssetFetch);
|
|
6976
7105
|
if (signal?.aborted) throw new DOMException("Aborted", "AbortError");
|
|
@@ -7002,7 +7131,7 @@ async function fetchAssetBlob(url, signal, proxyAssetFetch) {
|
|
|
7002
7131
|
return res.blob();
|
|
7003
7132
|
}
|
|
7004
7133
|
if (signal?.aborted) throw new DOMException("Aborted", "AbortError");
|
|
7005
|
-
if (proxyAssetFetch &&
|
|
7134
|
+
if (proxyAssetFetch && looksLikeCorsError(directErr)) {
|
|
7006
7135
|
try {
|
|
7007
7136
|
return await proxyAssetFetch(url);
|
|
7008
7137
|
} catch (proxyErr) {
|
|
@@ -7053,7 +7182,7 @@ function guessMime(name) {
|
|
|
7053
7182
|
}
|
|
7054
7183
|
|
|
7055
7184
|
// src/se-import/transplant.ts
|
|
7056
|
-
import { nanoid as
|
|
7185
|
+
import { nanoid as nanoid4 } from "nanoid";
|
|
7057
7186
|
function cloneModuleForTransplant(srcModule, newId) {
|
|
7058
7187
|
const clonedContent = srcModule.content ? structuredClone(srcModule.content) : srcModule.content;
|
|
7059
7188
|
if (srcModule.settings?.type === "custom" && clonedContent) {
|
|
@@ -7071,7 +7200,7 @@ function transplantLayer(source, sourceLayerId) {
|
|
|
7071
7200
|
const srcLayer = layers.find((l) => l.id === sourceLayerId);
|
|
7072
7201
|
const srcModule = modules[sourceLayerId];
|
|
7073
7202
|
if (!srcLayer || !srcModule) return null;
|
|
7074
|
-
const rootNewId =
|
|
7203
|
+
const rootNewId = nanoid4();
|
|
7075
7204
|
if (srcLayer.type !== "group") {
|
|
7076
7205
|
const layer = { ...srcLayer, id: rootNewId };
|
|
7077
7206
|
const module = cloneModuleForTransplant(srcModule, rootNewId);
|
|
@@ -7089,7 +7218,7 @@ function transplantLayer(source, sourceLayerId) {
|
|
|
7089
7218
|
if (seen.has(child.id)) continue;
|
|
7090
7219
|
seen.add(child.id);
|
|
7091
7220
|
descendants.push(child);
|
|
7092
|
-
idRemap.set(child.id,
|
|
7221
|
+
idRemap.set(child.id, nanoid4());
|
|
7093
7222
|
if (child.type === "group") queue.push(child.id);
|
|
7094
7223
|
}
|
|
7095
7224
|
}
|
|
@@ -7593,7 +7722,74 @@ function readSLProvider(response) {
|
|
|
7593
7722
|
}
|
|
7594
7723
|
|
|
7595
7724
|
// src/sl-import/mappers/alert-box.ts
|
|
7596
|
-
import { nanoid as
|
|
7725
|
+
import { nanoid as nanoid6 } from "nanoid";
|
|
7726
|
+
import { LumiaAlertValues as LumiaAlertValues2 } from "@lumiastream/lumia-types";
|
|
7727
|
+
|
|
7728
|
+
// src/se-import/import-envelope.ts
|
|
7729
|
+
import { nanoid as nanoid5 } from "nanoid";
|
|
7730
|
+
function buildModuleEnvelope(opts) {
|
|
7731
|
+
const id = opts.id ?? nanoid5();
|
|
7732
|
+
const locked = opts.locked ?? false;
|
|
7733
|
+
const visible = opts.visible ?? true;
|
|
7734
|
+
const layer = {
|
|
7735
|
+
id,
|
|
7736
|
+
...opts.parentGroupId !== void 0 ? { group: opts.parentGroupId } : {},
|
|
7737
|
+
...opts.type_layer ? { type: opts.type_layer } : {},
|
|
7738
|
+
state: {
|
|
7739
|
+
visible,
|
|
7740
|
+
locked,
|
|
7741
|
+
...opts.expanded !== void 0 ? { expanded: opts.expanded } : {}
|
|
7742
|
+
},
|
|
7743
|
+
bounds: {
|
|
7744
|
+
x: opts.bounds.x,
|
|
7745
|
+
y: opts.bounds.y,
|
|
7746
|
+
width: opts.bounds.width,
|
|
7747
|
+
height: opts.bounds.height,
|
|
7748
|
+
scale: [1, 1],
|
|
7749
|
+
...opts.zIndex !== void 0 ? { zIndex: opts.zIndex } : {}
|
|
7750
|
+
}
|
|
7751
|
+
};
|
|
7752
|
+
const module = {
|
|
7753
|
+
id,
|
|
7754
|
+
version: opts.version ?? 1,
|
|
7755
|
+
loaded: true,
|
|
7756
|
+
settings: { type: opts.type, title: opts.title, locked },
|
|
7757
|
+
lights: opts.lights ?? [],
|
|
7758
|
+
css: opts.css ?? {},
|
|
7759
|
+
content: opts.content ?? {},
|
|
7760
|
+
variables: opts.variables ?? {},
|
|
7761
|
+
events: opts.events ?? {},
|
|
7762
|
+
...opts.alert !== void 0 ? { alert: opts.alert } : {}
|
|
7763
|
+
};
|
|
7764
|
+
return { id, layer, module };
|
|
7765
|
+
}
|
|
7766
|
+
var IMPORT_META_KEY = "importMeta";
|
|
7767
|
+
function stampImportMetaMerge(module, meta) {
|
|
7768
|
+
const existing = module.content?.[IMPORT_META_KEY] ?? {};
|
|
7769
|
+
module.content = {
|
|
7770
|
+
...module.content ?? {},
|
|
7771
|
+
[IMPORT_META_KEY]: {
|
|
7772
|
+
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7773
|
+
...existing,
|
|
7774
|
+
...meta
|
|
7775
|
+
}
|
|
7776
|
+
};
|
|
7777
|
+
}
|
|
7778
|
+
function customHtmlReviewItem(moduleId, importSourceType, settings, reason) {
|
|
7779
|
+
return {
|
|
7780
|
+
moduleId,
|
|
7781
|
+
// ReviewItem's `seWidget` is typed against SEWidget but the review
|
|
7782
|
+
// UI just reads `.type` and `.settings`. Cast through unknown is
|
|
7783
|
+
// the only place we touch the shape mismatch; widening the
|
|
7784
|
+
// ReviewItem type is a future cleanup.
|
|
7785
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7786
|
+
seWidget: { type: importSourceType, settings },
|
|
7787
|
+
status: "template",
|
|
7788
|
+
reason
|
|
7789
|
+
};
|
|
7790
|
+
}
|
|
7791
|
+
|
|
7792
|
+
// src/sl-import/mappers/alert-box.ts
|
|
7597
7793
|
var SL_EVENT_ROUTING = {
|
|
7598
7794
|
// Platform-native — provider routes (Twitch / Kick / YouTube).
|
|
7599
7795
|
follow: { pickProviderKeys: "follower" },
|
|
@@ -7605,47 +7801,35 @@ var SL_EVENT_ROUTING = {
|
|
|
7605
7801
|
// `subscriber` here is YouTube subscribe (free); `sponsor` is YouTube
|
|
7606
7802
|
// channel membership; `fanfunding` is YouTube superchat. SL ships these
|
|
7607
7803
|
// even on Twitch-primary accounts so we always map them.
|
|
7608
|
-
subscriber: { keys: [
|
|
7609
|
-
sponsor: { keys: [
|
|
7610
|
-
fanfunding: { keys: [
|
|
7611
|
-
super_sticker: { keys: [
|
|
7804
|
+
subscriber: { keys: [LumiaAlertValues2.YOUTUBE_SUBSCRIBER] },
|
|
7805
|
+
sponsor: { keys: [LumiaAlertValues2.YOUTUBE_MEMBER] },
|
|
7806
|
+
fanfunding: { keys: [LumiaAlertValues2.YOUTUBE_SUPERCHAT] },
|
|
7807
|
+
super_sticker: { keys: [LumiaAlertValues2.YOUTUBE_SUPERSTICKER] },
|
|
7612
7808
|
// Donation / tip channels — Lumia ships dedicated alert keys for each
|
|
7613
7809
|
// integration. `donation` itself fans out to `streamlabs-donation` AND
|
|
7614
7810
|
// `lumiastream-donation` so the imported alert fires regardless of which
|
|
7615
7811
|
// channel the donation actually came in on.
|
|
7616
|
-
donation: { keys: [
|
|
7617
|
-
eldonation: { keys: [
|
|
7618
|
-
tiltifydonation: { keys: [
|
|
7619
|
-
donordrivedonation: { keys: [
|
|
7620
|
-
justgivingdonation: { keys: [
|
|
7621
|
-
pledge: { keys: [
|
|
7812
|
+
donation: { keys: [LumiaAlertValues2.STREAMLABS_DONATION, LumiaAlertValues2.LUMIASTREAM_DONATION] },
|
|
7813
|
+
eldonation: { keys: [LumiaAlertValues2.EXTRALIFE_DONATION] },
|
|
7814
|
+
tiltifydonation: { keys: [LumiaAlertValues2.TILTIFY_DONATION] },
|
|
7815
|
+
donordrivedonation: { keys: [LumiaAlertValues2.DONORDRIVE_DONATION] },
|
|
7816
|
+
justgivingdonation: { keys: [LumiaAlertValues2.STREAMLABS_DONATION] },
|
|
7817
|
+
pledge: { keys: [LumiaAlertValues2.PATREON_PLEDGE] },
|
|
7622
7818
|
// Charity / merch / loyalty / prime gifting — SL-flavored channels with
|
|
7623
7819
|
// matching Lumia keys.
|
|
7624
|
-
streamlabscharitydonation: { keys: [
|
|
7625
|
-
twitchcharitydonation: { keys: [
|
|
7626
|
-
merch: { keys: [
|
|
7627
|
-
loyalty_store_redemption: { keys: [
|
|
7628
|
-
prime_sub_gift: { keys: [
|
|
7629
|
-
treat: { keys: [
|
|
7820
|
+
streamlabscharitydonation: { keys: [LumiaAlertValues2.STREAMLABS_CHARITY] },
|
|
7821
|
+
twitchcharitydonation: { keys: [LumiaAlertValues2.TWITCH_CHARITY_DONATION] },
|
|
7822
|
+
merch: { keys: [LumiaAlertValues2.STREAMLABS_MERCH] },
|
|
7823
|
+
loyalty_store_redemption: { keys: [LumiaAlertValues2.STREAMLABS_REDEMPTION] },
|
|
7824
|
+
prime_sub_gift: { keys: [LumiaAlertValues2.STREAMLABS_PRIMEGIFT] },
|
|
7825
|
+
treat: { keys: [LumiaAlertValues2.TREATSTREAM_TREAT] },
|
|
7630
7826
|
// TikTok-flavored (jewel gift is TikTok-ish in concept).
|
|
7631
|
-
jewel_gift: { keys: [
|
|
7827
|
+
jewel_gift: { keys: [LumiaAlertValues2.TIKTOK_GIFT] }
|
|
7632
7828
|
};
|
|
7633
7829
|
function getField(settings, prefix, field) {
|
|
7634
7830
|
const key = `${prefix}_${field}`;
|
|
7635
7831
|
return settings[key];
|
|
7636
7832
|
}
|
|
7637
|
-
function pxToNumber(raw, fallback) {
|
|
7638
|
-
if (typeof raw === "number" && Number.isFinite(raw)) return raw;
|
|
7639
|
-
if (typeof raw !== "string") return fallback;
|
|
7640
|
-
const trimmed = raw.trim();
|
|
7641
|
-
if (!trimmed) return fallback;
|
|
7642
|
-
if (trimmed.endsWith("px")) {
|
|
7643
|
-
const n2 = parseFloat(trimmed.slice(0, -2));
|
|
7644
|
-
return Number.isFinite(n2) ? n2 : fallback;
|
|
7645
|
-
}
|
|
7646
|
-
const n = parseFloat(trimmed);
|
|
7647
|
-
return Number.isFinite(n) ? n : fallback;
|
|
7648
|
-
}
|
|
7649
7833
|
function translateLayout2(slLayout) {
|
|
7650
7834
|
switch (slLayout) {
|
|
7651
7835
|
case "above":
|
|
@@ -7755,9 +7939,7 @@ function buildBaseAlertEvent(settings, prefix, defaultMessage) {
|
|
|
7755
7939
|
tts: {
|
|
7756
7940
|
enabled: getField(settings, prefix, "tts_enabled") ?? false,
|
|
7757
7941
|
voice: getField(settings, prefix, "tts_language") ?? "Brian",
|
|
7758
|
-
volume: clampVolume(
|
|
7759
|
-
getField(settings, prefix, "tts_volume") ?? 75
|
|
7760
|
-
),
|
|
7942
|
+
volume: clampVolume(getField(settings, prefix, "tts_volume") ?? 75),
|
|
7761
7943
|
minAmount: getField(settings, prefix, "tts_min_amount") ?? 0
|
|
7762
7944
|
},
|
|
7763
7945
|
variations: []
|
|
@@ -7772,10 +7954,7 @@ function readSecondaryMessageConfig(settings, prefix, primaryFontFamily) {
|
|
|
7772
7954
|
const enabled = settings[showKey];
|
|
7773
7955
|
if (enabled !== true) return null;
|
|
7774
7956
|
const fontFamily = getField(settings, secondaryPrefix, "message_font") ?? primaryFontFamily;
|
|
7775
|
-
const fontSize = pxToNumber(
|
|
7776
|
-
getField(settings, secondaryPrefix, "message_font_size"),
|
|
7777
|
-
20
|
|
7778
|
-
);
|
|
7957
|
+
const fontSize = pxToNumber(getField(settings, secondaryPrefix, "message_font_size"), 20);
|
|
7779
7958
|
const fontWeight = getField(settings, secondaryPrefix, "message_font_weight") ?? 400;
|
|
7780
7959
|
const fontColor = getField(settings, secondaryPrefix, "message_font_color") ?? "#FFFFFF";
|
|
7781
7960
|
return {
|
|
@@ -7802,11 +7981,20 @@ function translateSLVariationCondition(v) {
|
|
|
7802
7981
|
const numericData = typeof data === "number" ? data : Number(data);
|
|
7803
7982
|
switch (v.condition) {
|
|
7804
7983
|
case "RANDOM":
|
|
7805
|
-
return {
|
|
7984
|
+
return {
|
|
7985
|
+
conditionType: "RANDOM",
|
|
7986
|
+
condition: Number.isFinite(numericData) ? numericData : 100
|
|
7987
|
+
};
|
|
7806
7988
|
case "MIN_BITS_USED":
|
|
7807
|
-
return {
|
|
7989
|
+
return {
|
|
7990
|
+
conditionType: "GREATER_NUMBER",
|
|
7991
|
+
condition: Number.isFinite(numericData) ? numericData : 0
|
|
7992
|
+
};
|
|
7808
7993
|
case "EXACT_BITS_USED":
|
|
7809
|
-
return {
|
|
7994
|
+
return {
|
|
7995
|
+
conditionType: "EQUAL_NUMBER",
|
|
7996
|
+
condition: Number.isFinite(numericData) ? numericData : 0
|
|
7997
|
+
};
|
|
7810
7998
|
case "MIN_MONTHS_SUBSCRIBED":
|
|
7811
7999
|
return {
|
|
7812
8000
|
conditionType: "SUBSCRIBED_MONTHS_GREATER",
|
|
@@ -7871,6 +8059,14 @@ function buildVariationEvent(v, parentBase) {
|
|
|
7871
8059
|
if (s.hideAnimation) inherited.animations.alertExitAnimation = s.hideAnimation;
|
|
7872
8060
|
if (s.layout) inherited.layout.value = translateLayout2(s.layout);
|
|
7873
8061
|
return {
|
|
8062
|
+
// Reuse SL's own `uuid` when present so re-importing the same SL
|
|
8063
|
+
// alert-box keeps the variation identity stable across import
|
|
8064
|
+
// runs. SL always emits a uuid in their config (every fixture we've
|
|
8065
|
+
// seen has one); fall back to nanoid for the edge case of a
|
|
8066
|
+
// hand-crafted / older payload that omits it. Matches the SE
|
|
8067
|
+
// alert mapper's variation-id pattern — see Settings.tsx auto-fill
|
|
8068
|
+
// note there for why a stable id matters from save #1.
|
|
8069
|
+
id: typeof v.uuid === "string" && v.uuid.length > 0 ? v.uuid : nanoid6(),
|
|
7874
8070
|
name: v.name ?? "Variation",
|
|
7875
8071
|
on: v.paused !== true,
|
|
7876
8072
|
randomChance: 100,
|
|
@@ -7936,11 +8132,7 @@ function buildSLAlertBox(settings, options = {}) {
|
|
|
7936
8132
|
for (const [prefix, routing] of Object.entries(SL_EVENT_ROUTING)) {
|
|
7937
8133
|
const lumiaKeys = routing.pickProviderKeys ? alertBoxKeysFor(routing.pickProviderKeys, provider) : routing.keys ?? [];
|
|
7938
8134
|
if (lumiaKeys.length === 0) continue;
|
|
7939
|
-
const built = buildBaseAlertEvent(
|
|
7940
|
-
settings,
|
|
7941
|
-
prefix,
|
|
7942
|
-
DEFAULT_MESSAGES[prefix] ?? "{name}"
|
|
7943
|
-
);
|
|
8135
|
+
const built = buildBaseAlertEvent(settings, prefix, DEFAULT_MESSAGES[prefix] ?? "{name}");
|
|
7944
8136
|
if (!built) continue;
|
|
7945
8137
|
const variationKey = VARIATION_KEY_FOR_PREFIX[prefix];
|
|
7946
8138
|
const variations = variationKey ? settings[variationKey] : void 0;
|
|
@@ -7957,53 +8149,32 @@ function buildSLAlertBox(settings, options = {}) {
|
|
|
7957
8149
|
channelsImported.push(prefix);
|
|
7958
8150
|
if (firstEvent == null) firstEvent = built;
|
|
7959
8151
|
}
|
|
7960
|
-
const id = nanoid4();
|
|
7961
|
-
const layer = {
|
|
7962
|
-
id,
|
|
7963
|
-
state: { visible: true, locked: false },
|
|
7964
|
-
bounds: { x: 100, y: 100, width: 700, height: 600, scale: [1, 1] }
|
|
7965
|
-
};
|
|
7966
8152
|
const baseAlert = firstEvent ? stripEventOnlyFields(firstEvent) : {};
|
|
7967
|
-
const module = {
|
|
7968
|
-
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
settings: { type: "alert", title: "Streamlabs Alerts", locked: false },
|
|
7972
|
-
lights: [],
|
|
7973
|
-
css: {},
|
|
7974
|
-
content: {},
|
|
7975
|
-
variables: {},
|
|
7976
|
-
events: {},
|
|
8153
|
+
const { layer, module } = buildModuleEnvelope({
|
|
8154
|
+
type: "alert",
|
|
8155
|
+
title: "Streamlabs Alerts",
|
|
8156
|
+
bounds: { x: 100, y: 100, width: 700, height: 600 },
|
|
7977
8157
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7978
8158
|
alert: { ...baseAlert, events }
|
|
7979
|
-
};
|
|
8159
|
+
});
|
|
7980
8160
|
return { layer, module, channelsImported };
|
|
7981
8161
|
}
|
|
7982
8162
|
function stripEventOnlyFields(event) {
|
|
7983
|
-
const {
|
|
8163
|
+
const {
|
|
8164
|
+
on: _on,
|
|
8165
|
+
variations: _variations,
|
|
8166
|
+
matchEmptyCondition: _mec,
|
|
8167
|
+
...base
|
|
8168
|
+
} = event;
|
|
7984
8169
|
return base;
|
|
7985
8170
|
}
|
|
7986
8171
|
|
|
7987
8172
|
// src/sl-import/mappers/tip-jar.ts
|
|
7988
|
-
import { nanoid as nanoid5 } from "nanoid";
|
|
7989
|
-
function pxToNumber2(raw, fallback) {
|
|
7990
|
-
if (typeof raw === "number" && Number.isFinite(raw)) return raw;
|
|
7991
|
-
if (typeof raw !== "string") return fallback;
|
|
7992
|
-
const trimmed = raw.trim();
|
|
7993
|
-
if (!trimmed) return fallback;
|
|
7994
|
-
if (trimmed.endsWith("px")) {
|
|
7995
|
-
const n2 = parseFloat(trimmed.slice(0, -2));
|
|
7996
|
-
return Number.isFinite(n2) ? n2 : fallback;
|
|
7997
|
-
}
|
|
7998
|
-
const n = parseFloat(trimmed);
|
|
7999
|
-
return Number.isFinite(n) ? n : fallback;
|
|
8000
|
-
}
|
|
8001
8173
|
function buildSLTipJar(settings) {
|
|
8002
|
-
const id = nanoid5();
|
|
8003
8174
|
const backgroundColor = settings.background?.color ?? "transparent";
|
|
8004
8175
|
const textColor = settings.text?.color ?? "#FFFFFF";
|
|
8005
8176
|
const fontFamily = settings.text?.font ?? "Open Sans";
|
|
8006
|
-
const fontSize =
|
|
8177
|
+
const fontSize = pxToNumber(settings.text?.size, 32);
|
|
8007
8178
|
const types = settings.types ?? {};
|
|
8008
8179
|
const tipsConfig = types.tips ?? {};
|
|
8009
8180
|
const slEvents = {
|
|
@@ -8019,17 +8190,11 @@ function buildSLTipJar(settings) {
|
|
|
8019
8190
|
...TIPJAR_DEFAULT_MODULE.content.display,
|
|
8020
8191
|
showEventMessages: settings.text?.show !== false
|
|
8021
8192
|
};
|
|
8022
|
-
const layer = {
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
bounds: { x: 100, y: 100, width: 600, height: 700
|
|
8026
|
-
};
|
|
8027
|
-
const module = {
|
|
8028
|
-
id,
|
|
8193
|
+
const { layer, module } = buildModuleEnvelope({
|
|
8194
|
+
type: "tipjar",
|
|
8195
|
+
title: "Streamlabs Tip Jar",
|
|
8196
|
+
bounds: { x: 100, y: 100, width: 600, height: 700 },
|
|
8029
8197
|
version: TIPJAR_DEFAULT_MODULE.version,
|
|
8030
|
-
loaded: true,
|
|
8031
|
-
settings: { type: "tipjar", title: "Streamlabs Tip Jar", locked: false },
|
|
8032
|
-
lights: [],
|
|
8033
8198
|
css: {
|
|
8034
8199
|
fontFamily,
|
|
8035
8200
|
fontSize,
|
|
@@ -8050,12 +8215,7 @@ function buildSLTipJar(settings) {
|
|
|
8050
8215
|
source: "streamlabs",
|
|
8051
8216
|
widgetType: "tip_jar",
|
|
8052
8217
|
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8053
|
-
// SL jar type doesn't have a 1:1 mapping to Lumia's preset
|
|
8054
|
-
// vocabulary (cup-01, cup-02, …). Stashed for review.
|
|
8055
8218
|
slJarType: settings.jar?.type ?? null,
|
|
8056
|
-
// SL tier coin tiers — Lumia's sprite tiers are per-event and
|
|
8057
|
-
// configured in the sprite editor; the user re-creates these
|
|
8058
|
-
// manually. Stored here so they're not lost.
|
|
8059
8219
|
slTipTiers: Array.isArray(tipsConfig.tiers) ? tipsConfig.tiers.map((t) => ({
|
|
8060
8220
|
minimumAmount: t.minimum_amount,
|
|
8061
8221
|
imageSrc: t.image_src ?? null
|
|
@@ -8063,15 +8223,12 @@ function buildSLTipJar(settings) {
|
|
|
8063
8223
|
slMinimumTipAmount: tipsConfig.minimum_amount ?? null,
|
|
8064
8224
|
slHadCustomHtml: settings.custom_html_enabled === true
|
|
8065
8225
|
}
|
|
8066
|
-
}
|
|
8067
|
-
|
|
8068
|
-
events: {}
|
|
8069
|
-
};
|
|
8226
|
+
}
|
|
8227
|
+
});
|
|
8070
8228
|
return { layer, module };
|
|
8071
8229
|
}
|
|
8072
8230
|
|
|
8073
8231
|
// src/sl-import/mappers/goal.ts
|
|
8074
|
-
import { nanoid as nanoid6 } from "nanoid";
|
|
8075
8232
|
var GOAL_SOURCE_MAP = {
|
|
8076
8233
|
follower_goal: "follower",
|
|
8077
8234
|
sub_goal: "subscriber",
|
|
@@ -8084,69 +8241,262 @@ var GOAL_TITLE_MAP = {
|
|
|
8084
8241
|
donation_goal: "Donation Goal",
|
|
8085
8242
|
bit_goal: "Bits Goal"
|
|
8086
8243
|
};
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
const n2 = parseFloat(trimmed.slice(0, -2));
|
|
8094
|
-
return Number.isFinite(n2) ? n2 : fallback;
|
|
8095
|
-
}
|
|
8096
|
-
const n = parseFloat(trimmed);
|
|
8097
|
-
return Number.isFinite(n) ? n : fallback;
|
|
8098
|
-
}
|
|
8244
|
+
var GOAL_CURRENT_TEMPLATE = {
|
|
8245
|
+
follower_goal: "{{twitch_total_follower_count}}",
|
|
8246
|
+
sub_goal: "{{twitch_total_subscriber_count}}",
|
|
8247
|
+
donation_goal: "{{total_donation_amount}}",
|
|
8248
|
+
bit_goal: "{{twitch_total_bits_count}}"
|
|
8249
|
+
};
|
|
8099
8250
|
function buildSLGoal(settings, widgetType) {
|
|
8100
|
-
const id = nanoid6();
|
|
8101
8251
|
const goalSource = GOAL_SOURCE_MAP[widgetType] ?? "follower";
|
|
8102
8252
|
const defaultTitle = GOAL_TITLE_MAP[widgetType] ?? "Goal";
|
|
8253
|
+
const currentTemplate = GOAL_CURRENT_TEMPLATE[widgetType] ?? "";
|
|
8254
|
+
const requiresReview = settings.custom_enabled === true;
|
|
8103
8255
|
const title = typeof settings.title === "string" ? settings.title : defaultTitle;
|
|
8104
8256
|
const goalAmount = typeof settings.goal === "number" ? settings.goal : 100;
|
|
8105
8257
|
const currentAmount = typeof settings.current === "number" ? settings.current : 0;
|
|
8106
8258
|
const startingAmount = typeof settings.starting_amount === "number" ? settings.starting_amount : 0;
|
|
8107
|
-
const endsAt = typeof settings.ends_at === "string" ? settings.ends_at :
|
|
8259
|
+
const endsAt = typeof settings.ends_at === "string" ? settings.ends_at : "";
|
|
8108
8260
|
const barColor = settings.bar_color ?? "#32C3A6";
|
|
8109
|
-
const
|
|
8261
|
+
const barBgColor = settings.bar_bg_color ?? "#181818";
|
|
8262
|
+
const widgetBgColor = settings.background_color ?? "transparent";
|
|
8110
8263
|
const textColor = settings.text_color ?? "#FFFFFF";
|
|
8111
8264
|
const barTextColor = settings.bar_text_color ?? textColor;
|
|
8112
8265
|
const fontFamily = settings.font ?? "Open Sans";
|
|
8113
|
-
const
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
version: 1,
|
|
8121
|
-
loaded: true,
|
|
8122
|
-
settings: { type: "goal", title, locked: false },
|
|
8123
|
-
lights: [],
|
|
8266
|
+
const fontSize = pxToNumber(settings.font_size, 24);
|
|
8267
|
+
const barThickness = pxToNumber(settings.bar_thickness, 48);
|
|
8268
|
+
const layerHeight = Math.max(60, barThickness + 32);
|
|
8269
|
+
const { layer, module } = buildModuleEnvelope({
|
|
8270
|
+
type: "goal",
|
|
8271
|
+
title,
|
|
8272
|
+
bounds: { x: 100, y: 100, width: 740, height: layerHeight },
|
|
8124
8273
|
css: {
|
|
8125
8274
|
fontFamily,
|
|
8126
8275
|
color: textColor,
|
|
8127
|
-
background:
|
|
8276
|
+
background: widgetBgColor,
|
|
8277
|
+
fontSize
|
|
8128
8278
|
},
|
|
8279
|
+
// Use Lumia's canonical goal field names — `targetGoal` (string),
|
|
8280
|
+
// `current` (template string), `display`, `filledColor` /
|
|
8281
|
+
// `unfilledColor`. The prior schema used invented field names
|
|
8282
|
+
// (`goalAmount`, `barColor`) that the renderer ignored.
|
|
8129
8283
|
content: {
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8284
|
+
version: 1,
|
|
8285
|
+
type: "bar",
|
|
8286
|
+
label: title,
|
|
8287
|
+
subLabel: "",
|
|
8288
|
+
display: "{{current}} / {{goal}}",
|
|
8289
|
+
current: currentAmount > 0 ? String(currentAmount) : currentTemplate,
|
|
8290
|
+
targetGoal: String(goalAmount),
|
|
8291
|
+
image: "",
|
|
8292
|
+
audio: {
|
|
8293
|
+
decrement: "",
|
|
8294
|
+
increment: "",
|
|
8295
|
+
goal: "",
|
|
8296
|
+
goalFailed: "",
|
|
8297
|
+
volume: 1
|
|
8298
|
+
},
|
|
8299
|
+
endDate: endsAt,
|
|
8300
|
+
goalAnimation: "",
|
|
8301
|
+
goalAnimationLoop: true,
|
|
8302
|
+
unfilledColor: barBgColor,
|
|
8303
|
+
filledColor: barColor,
|
|
8304
|
+
alignItemsToEdges: false,
|
|
8305
|
+
border: "solid 1px transparent",
|
|
8306
|
+
borderRadius: "40px",
|
|
8307
|
+
highlightColor: "inherit",
|
|
8308
|
+
importMeta: {
|
|
8309
|
+
source: "streamlabs",
|
|
8310
|
+
widgetType,
|
|
8311
|
+
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8312
|
+
goalSource,
|
|
8313
|
+
slLayout: settings.layout ?? null,
|
|
8314
|
+
slBarTextColor: barTextColor,
|
|
8315
|
+
slBarThickness: barThickness,
|
|
8316
|
+
slStartingAmount: startingAmount,
|
|
8317
|
+
slHadCustomHtml: settings.custom_enabled === true
|
|
8318
|
+
}
|
|
8319
|
+
}
|
|
8320
|
+
});
|
|
8321
|
+
return { layer, module, requiresReview };
|
|
8322
|
+
}
|
|
8323
|
+
|
|
8324
|
+
// src/sl-import/mappers/chat-box.ts
|
|
8325
|
+
function buildSitesArray(settings) {
|
|
8326
|
+
const defaultSites = [...CHATBOX_DEFAULT_MODULE.content.sites];
|
|
8327
|
+
const drop = /* @__PURE__ */ new Set();
|
|
8328
|
+
if (settings.show_bttv_emotes === false) drop.add("bttv");
|
|
8329
|
+
if (settings.show_franker_emotes === false) drop.add("ffz");
|
|
8330
|
+
if (settings.show_7tv_emotes === false) drop.add("seventv");
|
|
8331
|
+
if (settings.twitch_enabled === false) drop.add("twitch");
|
|
8332
|
+
if (settings.youtube_enabled === false) drop.add("youtube");
|
|
8333
|
+
if (settings.facebook_enabled === false) drop.add("facebook");
|
|
8334
|
+
if (settings.tiktok_enabled === false) drop.add("tiktok");
|
|
8335
|
+
if (settings.kick_enabled === false) drop.add("kick");
|
|
8336
|
+
if (drop.size === 0) return defaultSites;
|
|
8337
|
+
return defaultSites.filter((s) => !drop.has(s));
|
|
8338
|
+
}
|
|
8339
|
+
function buildSLChatBox(settings) {
|
|
8340
|
+
const requiresReview = settings.custom_enabled === true;
|
|
8341
|
+
const backgroundColor = settings.background_color ?? "transparent";
|
|
8342
|
+
const textColor = settings.text_color ?? "#FFFFFF";
|
|
8343
|
+
const textSize = pxToNumber(settings.text_size, 16);
|
|
8344
|
+
const fadeOutAfterDelay = settings.always_show_messages !== true;
|
|
8345
|
+
const fadeOutDelayTime = fadeOutAfterDelay ? Math.max(1, Math.round((settings.message_hide_delay ?? 15e3) / 1e3)) : 0;
|
|
8346
|
+
const sites = buildSitesArray(settings);
|
|
8347
|
+
const { layer, module } = buildModuleEnvelope({
|
|
8348
|
+
type: "chatbox",
|
|
8349
|
+
title: "Streamlabs Chat Box",
|
|
8350
|
+
bounds: { x: 100, y: 100, width: 375, height: 470 },
|
|
8351
|
+
version: CHATBOX_DEFAULT_MODULE.version,
|
|
8352
|
+
css: {
|
|
8353
|
+
background: backgroundColor,
|
|
8354
|
+
color: textColor,
|
|
8355
|
+
fontSize: textSize
|
|
8141
8356
|
},
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
|
|
8357
|
+
content: {
|
|
8358
|
+
// Spread canonical defaults FIRST so the renderer's dereferences
|
|
8359
|
+
// (chatboxStreamingSite.<platform>.themeConfig, animations,
|
|
8360
|
+
// chatboxStreamingSite.<platform>.message, etc.) all exist.
|
|
8361
|
+
...CHATBOX_DEFAULT_MODULE.content,
|
|
8362
|
+
// Then override the bits SL controls.
|
|
8363
|
+
sites,
|
|
8364
|
+
fadeOutAfterDelay,
|
|
8365
|
+
fadeOutDelayTime,
|
|
8366
|
+
// SL keeps history forever by default — `always_show_messages`
|
|
8367
|
+
// implies the streamer wants a permanent scrollback. Lumia
|
|
8368
|
+
// exposes that as `permanent: true`.
|
|
8369
|
+
permanent: settings.always_show_messages === true,
|
|
8370
|
+
// Preserve the SL-specific provenance for the review step.
|
|
8371
|
+
importMeta: {
|
|
8372
|
+
source: "streamlabs",
|
|
8373
|
+
widgetType: "chat_box",
|
|
8374
|
+
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8375
|
+
slTheme: settings.theme ?? null,
|
|
8376
|
+
slHadCustomHtml: settings.custom_enabled === true,
|
|
8377
|
+
slHidesCommonBots: settings.hide_common_chat_bots === true,
|
|
8378
|
+
slHidesCommands: settings.hide_commands === true,
|
|
8379
|
+
slMutedChatters: settings.muted_chatters ?? "",
|
|
8380
|
+
slMessageShowDelayMs: settings.message_show_delay ?? 0
|
|
8381
|
+
}
|
|
8382
|
+
}
|
|
8383
|
+
});
|
|
8384
|
+
return { layer, module, requiresReview };
|
|
8385
|
+
}
|
|
8386
|
+
|
|
8387
|
+
// src/sl-import/mappers/event-list.ts
|
|
8388
|
+
var SL_SHOW_FLAG_TO_LUMIA_FILTER = {
|
|
8389
|
+
show_follows: "follower",
|
|
8390
|
+
show_subscriptions: "subscribers",
|
|
8391
|
+
show_resubs: "subscribers",
|
|
8392
|
+
show_sub_gifts: "gifts",
|
|
8393
|
+
show_subscribers: "subscribers",
|
|
8394
|
+
show_sponsors: "subscribers",
|
|
8395
|
+
// YouTube channel members
|
|
8396
|
+
show_sponsor_gifts: "gifts",
|
|
8397
|
+
show_bits: "bits",
|
|
8398
|
+
show_donations: "donation",
|
|
8399
|
+
show_pledges: "donation",
|
|
8400
|
+
// Patreon
|
|
8401
|
+
show_eldonations: "donation",
|
|
8402
|
+
show_tiltifydonations: "donation",
|
|
8403
|
+
show_donordrivedonations: "donation",
|
|
8404
|
+
show_justgivingdonations: "donation",
|
|
8405
|
+
show_streamlabscharitydonations: "donation",
|
|
8406
|
+
show_twitchcharitydonations: "donation",
|
|
8407
|
+
show_twitch_charity: "donation",
|
|
8408
|
+
show_treats: "donation",
|
|
8409
|
+
// TreatStream
|
|
8410
|
+
show_merch: "purchases",
|
|
8411
|
+
show_raids: "raids",
|
|
8412
|
+
show_hosts: "raids",
|
|
8413
|
+
show_redemptions: "redemption",
|
|
8414
|
+
show_fanfundings: "superchats",
|
|
8415
|
+
// YouTube Super Chat
|
|
8416
|
+
show_super_stickers: "superstickers",
|
|
8417
|
+
show_jewel_gifts: "stars"
|
|
8418
|
+
// TikTok-flavored, closest analogue
|
|
8419
|
+
};
|
|
8420
|
+
function buildFilters(settings) {
|
|
8421
|
+
const drop = /* @__PURE__ */ new Set();
|
|
8422
|
+
for (const [slFlag, lumiaCategory] of Object.entries(SL_SHOW_FLAG_TO_LUMIA_FILTER)) {
|
|
8423
|
+
if (settings[slFlag] === false) {
|
|
8424
|
+
drop.add(lumiaCategory);
|
|
8425
|
+
}
|
|
8426
|
+
}
|
|
8427
|
+
return Array.from(drop);
|
|
8428
|
+
}
|
|
8429
|
+
function buildSLEventList(settings) {
|
|
8430
|
+
const requiresReview = settings.custom_enabled === true;
|
|
8431
|
+
const backgroundColor = settings.background_color ?? "transparent";
|
|
8432
|
+
const textColor = settings.text_color ?? "#FFFFFF";
|
|
8433
|
+
const textSize = pxToNumber(settings.text_size, 16);
|
|
8434
|
+
const fontFamily = settings.font_family ?? "Roboto";
|
|
8435
|
+
const maxEvents = typeof settings.max_events === "number" && settings.max_events > 0 ? settings.max_events : EVENTLIST_DEFAULT_MODULE.content.maxItemsToShow;
|
|
8436
|
+
const enterAnimation = settings.show_animation ?? "fadeIn";
|
|
8437
|
+
const exitAnimation = settings.hide_animation ?? "fadeOut";
|
|
8438
|
+
const animationDuration = typeof settings.animation_speed === "number" ? settings.animation_speed : 1e3;
|
|
8439
|
+
const filters = buildFilters(settings);
|
|
8440
|
+
const { layer, module } = buildModuleEnvelope({
|
|
8441
|
+
type: "eventlist",
|
|
8442
|
+
title: "Streamlabs Event List",
|
|
8443
|
+
bounds: { x: 100, y: 100, width: 375, height: 470 },
|
|
8444
|
+
version: EVENTLIST_DEFAULT_MODULE.version,
|
|
8445
|
+
css: {
|
|
8446
|
+
...EVENTLIST_DEFAULT_MODULE.css,
|
|
8447
|
+
background: backgroundColor,
|
|
8448
|
+
color: textColor,
|
|
8449
|
+
fontSize: textSize,
|
|
8450
|
+
fontFamily
|
|
8451
|
+
},
|
|
8452
|
+
content: {
|
|
8453
|
+
// Spread canonical defaults FIRST so the renderer's dereferences
|
|
8454
|
+
// don't crash on missing nested objects.
|
|
8455
|
+
...EVENTLIST_DEFAULT_MODULE.content,
|
|
8456
|
+
maxItemsToShow: maxEvents,
|
|
8457
|
+
// SL's `flip_y` corresponds to Lumia's `reverse` (newest item
|
|
8458
|
+
// at the bottom vs the top). SL's `flip_x` flips the alignment
|
|
8459
|
+
// to right; Lumia covers that via css.textAlign but doesn't
|
|
8460
|
+
// have a per-module horizontal flip — stash as importMeta for
|
|
8461
|
+
// the review step.
|
|
8462
|
+
reverse: settings.flip_y === true,
|
|
8463
|
+
// SL's `keep_history: false` means events disappear after the
|
|
8464
|
+
// fade time; map to `fadeOutAfterDelay: true` with the fade
|
|
8465
|
+
// time SL configured.
|
|
8466
|
+
fadeOutAfterDelay: settings.keep_history === false,
|
|
8467
|
+
fadeOutDelayTime: typeof settings.fade_time === "number" && settings.fade_time > 0 ? Math.max(1, Math.round(settings.fade_time / 1e3)) : EVENTLIST_DEFAULT_MODULE.content.fadeOutDelayTime,
|
|
8468
|
+
animations: {
|
|
8469
|
+
...EVENTLIST_DEFAULT_MODULE.content.animations,
|
|
8470
|
+
enterAnimation,
|
|
8471
|
+
exitAnimation,
|
|
8472
|
+
enterAnimationDuration: animationDuration,
|
|
8473
|
+
exitAnimationDuration: animationDuration
|
|
8474
|
+
},
|
|
8475
|
+
filters,
|
|
8476
|
+
importMeta: {
|
|
8477
|
+
source: "streamlabs",
|
|
8478
|
+
widgetType: "event_list",
|
|
8479
|
+
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8480
|
+
slTheme: settings.theme ?? null,
|
|
8481
|
+
slThemeColor: settings.theme_color ?? null,
|
|
8482
|
+
slFlipX: settings.flip_x === true,
|
|
8483
|
+
slHadCustomHtml: settings.custom_enabled === true,
|
|
8484
|
+
// Per-event-type minimums SL filters by — Lumia's eventlist
|
|
8485
|
+
// has no equivalent thresholding; preserve so the streamer
|
|
8486
|
+
// can recreate via the alert module's variation conditions.
|
|
8487
|
+
slHostViewerMinimum: settings.host_viewer_minimum ?? 0,
|
|
8488
|
+
slBitsMinimum: settings.bits_minimum ?? 0,
|
|
8489
|
+
slRaidRaiderMinimum: settings.raid_raider_minimum ?? 0
|
|
8490
|
+
}
|
|
8491
|
+
}
|
|
8492
|
+
});
|
|
8493
|
+
return { layer, module, requiresReview };
|
|
8146
8494
|
}
|
|
8147
8495
|
|
|
8148
8496
|
// src/sl-import/sl-dispatch.ts
|
|
8149
|
-
|
|
8497
|
+
function buildSLDescription(widgetType, sourceUrl) {
|
|
8498
|
+
return buildImportDescription(`Imported from Streamlabs ${widgetType}`, sourceUrl);
|
|
8499
|
+
}
|
|
8150
8500
|
var GOAL_WIDGET_TYPES = /* @__PURE__ */ new Set([
|
|
8151
8501
|
"follower_goal",
|
|
8152
8502
|
"sub_goal",
|
|
@@ -8154,8 +8504,6 @@ var GOAL_WIDGET_TYPES = /* @__PURE__ */ new Set([
|
|
|
8154
8504
|
"bit_goal"
|
|
8155
8505
|
]);
|
|
8156
8506
|
var PLACEHOLDER_WIDGET_TYPES = /* @__PURE__ */ new Set([
|
|
8157
|
-
"chat_box",
|
|
8158
|
-
"event_list",
|
|
8159
8507
|
"donation_ticker",
|
|
8160
8508
|
"stream_boss",
|
|
8161
8509
|
"credits",
|
|
@@ -8165,8 +8513,6 @@ var PLACEHOLDER_WIDGET_TYPES = /* @__PURE__ */ new Set([
|
|
|
8165
8513
|
"streamlabels"
|
|
8166
8514
|
]);
|
|
8167
8515
|
var PLACEHOLDER_REASONS = {
|
|
8168
|
-
chat_box: "Lumia has a native chatbox module \u2014 set it up directly rather than importing the SL config.",
|
|
8169
|
-
event_list: "Lumia has a native eventlist module \u2014 set it up directly rather than importing the SL config.",
|
|
8170
8516
|
donation_ticker: "No native Lumia equivalent yet \u2014 imported as a placeholder text layer.",
|
|
8171
8517
|
stream_boss: "Lumia has a native streamboss module \u2014 set it up directly rather than importing the SL config.",
|
|
8172
8518
|
credits: "Lumia has a native credits module \u2014 set it up directly rather than importing the SL config.",
|
|
@@ -8175,19 +8521,14 @@ var PLACEHOLDER_REASONS = {
|
|
|
8175
8521
|
sub_train: "No native Lumia equivalent yet \u2014 imported as a placeholder text layer.",
|
|
8176
8522
|
streamlabels: "Use Lumia template variables (e.g. {{twitch_last_follower}}) inside a Text module instead of importing the SL streamlabels config."
|
|
8177
8523
|
};
|
|
8524
|
+
var CUSTOM_HTML_REVIEW_REASON = "The Streamlabs widget used custom HTML/CSS/JS that Lumia cannot host. The native Lumia module is the right starting point \u2014 recreate the styling there. The original SL settings are stashed under module.content.importMeta for reference.";
|
|
8178
8525
|
function stampImportMeta(module, widgetType, role, extra = {}) {
|
|
8179
|
-
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
|
|
8184
|
-
|
|
8185
|
-
role,
|
|
8186
|
-
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8187
|
-
...existing,
|
|
8188
|
-
...extra
|
|
8189
|
-
}
|
|
8190
|
-
};
|
|
8526
|
+
stampImportMetaMerge(module, {
|
|
8527
|
+
source: "streamlabs",
|
|
8528
|
+
widgetType,
|
|
8529
|
+
role,
|
|
8530
|
+
...extra
|
|
8531
|
+
});
|
|
8191
8532
|
}
|
|
8192
8533
|
function buildPlaceholder(widgetType) {
|
|
8193
8534
|
const id = nanoid7();
|
|
@@ -8219,7 +8560,7 @@ function buildPlaceholder(widgetType) {
|
|
|
8219
8560
|
};
|
|
8220
8561
|
return { layer, module };
|
|
8221
8562
|
}
|
|
8222
|
-
function importStreamlabsWidget(response, widgetType) {
|
|
8563
|
+
function importStreamlabsWidget(response, widgetType, options = {}) {
|
|
8223
8564
|
if (!isSLWidgetConfigResponse(response)) {
|
|
8224
8565
|
throw new Error(
|
|
8225
8566
|
"Streamlabs response is missing the expected `settings` envelope. The widget may be private or the response format may have changed."
|
|
@@ -8269,9 +8610,61 @@ function importStreamlabsWidget(response, widgetType) {
|
|
|
8269
8610
|
coverage.mappings.push({
|
|
8270
8611
|
seType: `streamlabs:${widgetType}`,
|
|
8271
8612
|
lumiaType: "goal",
|
|
8272
|
-
status: "direct",
|
|
8613
|
+
status: built.requiresReview ? "partial" : "direct",
|
|
8273
8614
|
count: 1
|
|
8274
8615
|
});
|
|
8616
|
+
if (built.requiresReview) {
|
|
8617
|
+
reviewItems.push(
|
|
8618
|
+
customHtmlReviewItem(
|
|
8619
|
+
built.module.id,
|
|
8620
|
+
`streamlabs-${widgetType}`,
|
|
8621
|
+
response.settings,
|
|
8622
|
+
CUSTOM_HTML_REVIEW_REASON
|
|
8623
|
+
)
|
|
8624
|
+
);
|
|
8625
|
+
}
|
|
8626
|
+
} else if (widgetType === "chat_box") {
|
|
8627
|
+
const built = buildSLChatBox(response.settings);
|
|
8628
|
+
stampImportMeta(built.module, widgetType, "chatbox");
|
|
8629
|
+
layers.push(built.layer);
|
|
8630
|
+
modules[built.layer.id] = built.module;
|
|
8631
|
+
coverage.mappings.push({
|
|
8632
|
+
seType: "streamlabs:chat_box",
|
|
8633
|
+
lumiaType: "chatbox",
|
|
8634
|
+
status: built.requiresReview ? "partial" : "direct",
|
|
8635
|
+
count: 1
|
|
8636
|
+
});
|
|
8637
|
+
if (built.requiresReview) {
|
|
8638
|
+
reviewItems.push(
|
|
8639
|
+
customHtmlReviewItem(
|
|
8640
|
+
built.module.id,
|
|
8641
|
+
"streamlabs-chat_box",
|
|
8642
|
+
response.settings,
|
|
8643
|
+
CUSTOM_HTML_REVIEW_REASON
|
|
8644
|
+
)
|
|
8645
|
+
);
|
|
8646
|
+
}
|
|
8647
|
+
} else if (widgetType === "event_list") {
|
|
8648
|
+
const built = buildSLEventList(response.settings);
|
|
8649
|
+
stampImportMeta(built.module, widgetType, "eventlist");
|
|
8650
|
+
layers.push(built.layer);
|
|
8651
|
+
modules[built.layer.id] = built.module;
|
|
8652
|
+
coverage.mappings.push({
|
|
8653
|
+
seType: "streamlabs:event_list",
|
|
8654
|
+
lumiaType: "eventlist",
|
|
8655
|
+
status: built.requiresReview ? "partial" : "direct",
|
|
8656
|
+
count: 1
|
|
8657
|
+
});
|
|
8658
|
+
if (built.requiresReview) {
|
|
8659
|
+
reviewItems.push(
|
|
8660
|
+
customHtmlReviewItem(
|
|
8661
|
+
built.module.id,
|
|
8662
|
+
"streamlabs-event_list",
|
|
8663
|
+
response.settings,
|
|
8664
|
+
CUSTOM_HTML_REVIEW_REASON
|
|
8665
|
+
)
|
|
8666
|
+
);
|
|
8667
|
+
}
|
|
8275
8668
|
} else if (PLACEHOLDER_WIDGET_TYPES.has(widgetType)) {
|
|
8276
8669
|
const placeholder = buildPlaceholder(widgetType);
|
|
8277
8670
|
const reason = PLACEHOLDER_REASONS[widgetType] ?? "No native Lumia mapping yet.";
|
|
@@ -8320,7 +8713,7 @@ function importStreamlabsWidget(response, widgetType) {
|
|
|
8320
8713
|
uuid: "",
|
|
8321
8714
|
listen_id: "",
|
|
8322
8715
|
name: overlayName,
|
|
8323
|
-
description:
|
|
8716
|
+
description: buildSLDescription(widgetType, options.sourceUrl),
|
|
8324
8717
|
settings: {
|
|
8325
8718
|
metadata: { width: 1920, height: 1080 },
|
|
8326
8719
|
layers,
|
|
@@ -9882,7 +10275,12 @@ function SEImportWizard({
|
|
|
9882
10275
|
);
|
|
9883
10276
|
}
|
|
9884
10277
|
importedOverlays.push({
|
|
9885
|
-
result: importSEBootstrap(bootstrap
|
|
10278
|
+
result: importSEBootstrap(bootstrap, {
|
|
10279
|
+
// JWT-flow imports don't come from a pasted URL; synthesize
|
|
10280
|
+
// the SE dashboard URL so the description still carries a
|
|
10281
|
+
// useful traceback. Same shape SE editor links use.
|
|
10282
|
+
sourceUrl: `https://streamelements.com/dashboard/overlays/${overlayId}/editor`
|
|
10283
|
+
}),
|
|
9886
10284
|
summary
|
|
9887
10285
|
});
|
|
9888
10286
|
}
|
|
@@ -9927,7 +10325,9 @@ function SEImportWizard({
|
|
|
9927
10325
|
"StreamElements returned a payload that doesn't look like an overlay bootstrap."
|
|
9928
10326
|
);
|
|
9929
10327
|
}
|
|
9930
|
-
const imported = importSEBootstrap(bootstrap
|
|
10328
|
+
const imported = importSEBootstrap(bootstrap, {
|
|
10329
|
+
sourceUrl: `https://streamelements.com/dashboard/overlays/${overlayId}/editor`
|
|
10330
|
+
});
|
|
9931
10331
|
setBatchImports([{ result: imported, summary }]);
|
|
9932
10332
|
setResult(imported);
|
|
9933
10333
|
setAssetUrls(findSEAssetURLs(imported.overlay));
|
|
@@ -10015,7 +10415,9 @@ function SEImportWizard({
|
|
|
10015
10415
|
"Streamlabs returned a response that does not look like a widget config payload."
|
|
10016
10416
|
);
|
|
10017
10417
|
}
|
|
10018
|
-
const imported = importStreamlabsWidget(raw, slParts.widgetType
|
|
10418
|
+
const imported = importStreamlabsWidget(raw, slParts.widgetType, {
|
|
10419
|
+
sourceUrl: url
|
|
10420
|
+
});
|
|
10019
10421
|
setBatchImports([]);
|
|
10020
10422
|
setResult(imported);
|
|
10021
10423
|
setAssetUrls(findSEAssetURLs(imported.overlay));
|
|
@@ -10056,7 +10458,7 @@ function SEImportWizard({
|
|
|
10056
10458
|
"StreamElements returned a response that does not look like an Element widget payload."
|
|
10057
10459
|
);
|
|
10058
10460
|
}
|
|
10059
|
-
const imported = importElementOverlay(raw);
|
|
10461
|
+
const imported = importElementOverlay(raw, { sourceUrl: url });
|
|
10060
10462
|
setBatchImports([]);
|
|
10061
10463
|
setResult(imported);
|
|
10062
10464
|
setAssetUrls(findSEAssetURLs(imported.overlay));
|
|
@@ -10104,7 +10506,7 @@ function SEImportWizard({
|
|
|
10104
10506
|
...parts,
|
|
10105
10507
|
proxyFetch: bindings.proxyFetch
|
|
10106
10508
|
});
|
|
10107
|
-
const imported = importSEBootstrap(bootstrap);
|
|
10509
|
+
const imported = importSEBootstrap(bootstrap, { sourceUrl: url });
|
|
10108
10510
|
setBatchImports([]);
|
|
10109
10511
|
setResult(imported);
|
|
10110
10512
|
setAssetUrls(findSEAssetURLs(imported.overlay));
|
|
@@ -10763,7 +11165,7 @@ function extractErrorMessage(err) {
|
|
|
10763
11165
|
}
|
|
10764
11166
|
|
|
10765
11167
|
// src/se-import/element-dispatch.ts
|
|
10766
|
-
import {
|
|
11168
|
+
import { LumiaAlertValues as LumiaAlertValues3 } from "@lumiastream/lumia-types";
|
|
10767
11169
|
|
|
10768
11170
|
// src/se-import/element-types.ts
|
|
10769
11171
|
function isSEElementResponse(value) {
|
|
@@ -11007,34 +11409,8 @@ function translateAnimationName(name, fallback) {
|
|
|
11007
11409
|
if (PINNED_ANIMATION_MAP[name]) return PINNED_ANIMATION_MAP[name];
|
|
11008
11410
|
return name.replace(/-([a-z])/g, (_m, c) => c.toUpperCase());
|
|
11009
11411
|
}
|
|
11010
|
-
|
|
11011
|
-
|
|
11012
|
-
if (typeof raw !== "string") return fallbackMs;
|
|
11013
|
-
const trimmed = raw.trim();
|
|
11014
|
-
if (!trimmed) return fallbackMs;
|
|
11015
|
-
if (trimmed.endsWith("ms")) {
|
|
11016
|
-
const n2 = parseFloat(trimmed.slice(0, -2));
|
|
11017
|
-
return Number.isFinite(n2) ? n2 : fallbackMs;
|
|
11018
|
-
}
|
|
11019
|
-
if (trimmed.endsWith("s")) {
|
|
11020
|
-
const n2 = parseFloat(trimmed.slice(0, -1));
|
|
11021
|
-
return Number.isFinite(n2) ? n2 * 1e3 : fallbackMs;
|
|
11022
|
-
}
|
|
11023
|
-
const n = parseFloat(trimmed);
|
|
11024
|
-
return Number.isFinite(n) ? n : fallbackMs;
|
|
11025
|
-
}
|
|
11026
|
-
function parsePx2(raw) {
|
|
11027
|
-
if (typeof raw === "number" && Number.isFinite(raw)) return raw;
|
|
11028
|
-
if (typeof raw !== "string") return NaN;
|
|
11029
|
-
const trimmed = raw.trim();
|
|
11030
|
-
if (!trimmed) return NaN;
|
|
11031
|
-
if (trimmed.endsWith("px")) {
|
|
11032
|
-
const n2 = parseFloat(trimmed.slice(0, -2));
|
|
11033
|
-
return Number.isFinite(n2) ? n2 : NaN;
|
|
11034
|
-
}
|
|
11035
|
-
const n = parseFloat(trimmed);
|
|
11036
|
-
return Number.isFinite(n) ? n : NaN;
|
|
11037
|
-
}
|
|
11412
|
+
var parseAnimationDurationMs = parseDurationMs;
|
|
11413
|
+
var parsePx2 = (raw) => pxToNumber(raw, NaN);
|
|
11038
11414
|
function findFieldByType(fields, type) {
|
|
11039
11415
|
if (!fields) return void 0;
|
|
11040
11416
|
for (const f of Object.values(fields)) {
|
|
@@ -11110,6 +11486,47 @@ function buildAnimations(title) {
|
|
|
11110
11486
|
const visibleDurationMs = enterDelay + enterDuration + staticDuration + exitDuration;
|
|
11111
11487
|
return { animations, visibleDurationMs: visibleDurationMs || DEFAULT_DURATION_MS };
|
|
11112
11488
|
}
|
|
11489
|
+
function resolveFieldBoundsInCanvas(style, canvas, textContent) {
|
|
11490
|
+
if (!style) return null;
|
|
11491
|
+
const x = parsePx2(style.left);
|
|
11492
|
+
const y = parsePx2(style.top);
|
|
11493
|
+
const hasXY = Number.isFinite(x) || Number.isFinite(y);
|
|
11494
|
+
if (!hasXY && style.width == null && style.height == null) return null;
|
|
11495
|
+
const sx = Number.isFinite(x) ? x : 0;
|
|
11496
|
+
const sy = Number.isFinite(y) ? y : 0;
|
|
11497
|
+
let width = parsePx2(style.width);
|
|
11498
|
+
let height = parsePx2(style.height);
|
|
11499
|
+
if (!Number.isFinite(width)) width = Math.max(1, canvas.width - sx);
|
|
11500
|
+
if (!Number.isFinite(height)) {
|
|
11501
|
+
if (typeof textContent === "string") {
|
|
11502
|
+
const lineCount = (textContent.match(/\n/g)?.length ?? 0) + 1;
|
|
11503
|
+
const lhPx = parsePx2(style.lineHeight) || parsePx2(style["line-height"]);
|
|
11504
|
+
const fsPx = parsePx2(style.fontSize);
|
|
11505
|
+
let effectiveLh = lhPx;
|
|
11506
|
+
if (!Number.isFinite(effectiveLh) || effectiveLh < 8) {
|
|
11507
|
+
effectiveLh = Number.isFinite(fsPx) ? fsPx * 1.3 : 24 * 1.3;
|
|
11508
|
+
}
|
|
11509
|
+
height = Math.max(1, lineCount * effectiveLh);
|
|
11510
|
+
} else {
|
|
11511
|
+
height = Math.max(1, canvas.height - sy);
|
|
11512
|
+
}
|
|
11513
|
+
}
|
|
11514
|
+
return { x: sx, y: sy, width, height };
|
|
11515
|
+
}
|
|
11516
|
+
function unionBounds(boxes) {
|
|
11517
|
+
if (boxes.length === 0) return null;
|
|
11518
|
+
let minX = Infinity;
|
|
11519
|
+
let minY = Infinity;
|
|
11520
|
+
let maxX = -Infinity;
|
|
11521
|
+
let maxY = -Infinity;
|
|
11522
|
+
for (const b of boxes) {
|
|
11523
|
+
minX = Math.min(minX, b.x);
|
|
11524
|
+
minY = Math.min(minY, b.y);
|
|
11525
|
+
maxX = Math.max(maxX, b.x + b.width);
|
|
11526
|
+
maxY = Math.max(maxY, b.y + b.height);
|
|
11527
|
+
}
|
|
11528
|
+
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
11529
|
+
}
|
|
11113
11530
|
function buildElementAlertEvent(state, options = {}) {
|
|
11114
11531
|
const compositeFields = state.settings?.compositeFields;
|
|
11115
11532
|
const titleField = findFieldByType(compositeFields, "text");
|
|
@@ -11127,6 +11544,31 @@ function buildElementAlertEvent(state, options = {}) {
|
|
|
11127
11544
|
const titleStyle = titleField?.style;
|
|
11128
11545
|
const highlightColor = titleField?.highlightedStyle?.color ?? null;
|
|
11129
11546
|
const { animations, visibleDurationMs } = buildAnimations(titleField);
|
|
11547
|
+
const canvas = options.canvas ?? { width: 1920, height: 1080 };
|
|
11548
|
+
const mediaBounds = resolveFieldBoundsInCanvas(mainAsset?.style, canvas);
|
|
11549
|
+
const textBounds = resolveFieldBoundsInCanvas(titleStyle, canvas, rawMessage);
|
|
11550
|
+
const collected = [];
|
|
11551
|
+
if (mediaBounds) collected.push(mediaBounds);
|
|
11552
|
+
if (textBounds) collected.push(textBounds);
|
|
11553
|
+
let layerBounds = unionBounds(collected);
|
|
11554
|
+
if (!layerBounds) {
|
|
11555
|
+
layerBounds = {
|
|
11556
|
+
x: Math.round(canvas.width * 0.6),
|
|
11557
|
+
y: Math.round(canvas.height * 0.15),
|
|
11558
|
+
width: 400,
|
|
11559
|
+
height: 300
|
|
11560
|
+
};
|
|
11561
|
+
}
|
|
11562
|
+
let pushTextUp = 0;
|
|
11563
|
+
let pushTextLeft = 0;
|
|
11564
|
+
if (textBounds) {
|
|
11565
|
+
const desiredTextTopInLayer = textBounds.y - layerBounds.y;
|
|
11566
|
+
const naturalTextTopInLayer = Math.max(0, (layerBounds.height - textBounds.height) / 2);
|
|
11567
|
+
pushTextUp = Math.round(desiredTextTopInLayer - naturalTextTopInLayer);
|
|
11568
|
+
const desiredTextLeftInLayer = textBounds.x - layerBounds.x;
|
|
11569
|
+
const naturalTextLeftInLayer = Math.max(0, (layerBounds.width - textBounds.width) / 2);
|
|
11570
|
+
pushTextLeft = Math.round(desiredTextLeftInLayer - naturalTextLeftInLayer);
|
|
11571
|
+
}
|
|
11130
11572
|
const event = {
|
|
11131
11573
|
on: true,
|
|
11132
11574
|
// `'custom'` lowercase is load-bearing in Lumia's AlertBoxHandler —
|
|
@@ -11145,7 +11587,11 @@ function buildElementAlertEvent(state, options = {}) {
|
|
|
11145
11587
|
showBrandIcon: true
|
|
11146
11588
|
},
|
|
11147
11589
|
settings: { duration: visibleDurationMs },
|
|
11148
|
-
|
|
11590
|
+
// `textOver` matches SE Element's text-on-video render pattern.
|
|
11591
|
+
// `imageOver` / `column` / `row` would all stack the text outside
|
|
11592
|
+
// the media, which is the bug this layout fixes (text rendered
|
|
11593
|
+
// below the alert graphic instead of overlaid on it).
|
|
11594
|
+
layout: { value: "textOver", css: {}, customCss: "", pushTextUp, pushTextLeft },
|
|
11149
11595
|
text: {
|
|
11150
11596
|
css: titleCss(titleStyle),
|
|
11151
11597
|
messageCss: {},
|
|
@@ -11167,44 +11613,13 @@ function buildElementAlertEvent(state, options = {}) {
|
|
|
11167
11613
|
},
|
|
11168
11614
|
variations: []
|
|
11169
11615
|
};
|
|
11170
|
-
|
|
11171
|
-
let bounds;
|
|
11172
|
-
if (style) {
|
|
11173
|
-
const x = parsePx2(style.left);
|
|
11174
|
-
const y = parsePx2(style.top);
|
|
11175
|
-
const width = parsePx2(style.width);
|
|
11176
|
-
const height = parsePx2(style.height);
|
|
11177
|
-
if (Number.isFinite(x) && Number.isFinite(y) && Number.isFinite(width)) {
|
|
11178
|
-
bounds = {
|
|
11179
|
-
x,
|
|
11180
|
-
y,
|
|
11181
|
-
width,
|
|
11182
|
-
// Height isn't always present on video Main Assets (the video
|
|
11183
|
-
// aspect-ratios itself from the source). Fall back to a
|
|
11184
|
-
// reasonable default that matches SE's preview row.
|
|
11185
|
-
height: Number.isFinite(height) ? height : Math.round(width * 0.75)
|
|
11186
|
-
};
|
|
11187
|
-
}
|
|
11188
|
-
}
|
|
11189
|
-
return { event, bounds };
|
|
11616
|
+
return { event, bounds: layerBounds };
|
|
11190
11617
|
}
|
|
11191
11618
|
|
|
11192
11619
|
// src/se-import/mappers/element-scene.ts
|
|
11193
|
-
import { nanoid as nanoid8 } from "nanoid";
|
|
11194
11620
|
var TEXT_FALLBACK = { width: 400, height: 50 };
|
|
11195
11621
|
var IMAGE_FALLBACK = { width: 300, height: 100 };
|
|
11196
|
-
|
|
11197
|
-
if (typeof raw === "number" && Number.isFinite(raw)) return raw;
|
|
11198
|
-
if (typeof raw !== "string") return NaN;
|
|
11199
|
-
const trimmed = raw.trim();
|
|
11200
|
-
if (!trimmed) return NaN;
|
|
11201
|
-
if (trimmed.endsWith("px")) {
|
|
11202
|
-
const n2 = parseFloat(trimmed.slice(0, -2));
|
|
11203
|
-
return Number.isFinite(n2) ? n2 : NaN;
|
|
11204
|
-
}
|
|
11205
|
-
const n = parseFloat(trimmed);
|
|
11206
|
-
return Number.isFinite(n) ? n : NaN;
|
|
11207
|
-
}
|
|
11622
|
+
var parsePx3 = (raw) => pxToNumber(raw, NaN);
|
|
11208
11623
|
function styleToBounds(style, type, canvas) {
|
|
11209
11624
|
const x = Number.isFinite(parsePx3(style?.left)) ? parsePx3(style?.left) : 0;
|
|
11210
11625
|
const y = Number.isFinite(parsePx3(style?.top)) ? parsePx3(style?.top) : 0;
|
|
@@ -11240,33 +11655,17 @@ function styleToBounds(style, type, canvas) {
|
|
|
11240
11655
|
}
|
|
11241
11656
|
return { x, y, width, height };
|
|
11242
11657
|
}
|
|
11243
|
-
function
|
|
11244
|
-
|
|
11245
|
-
|
|
11246
|
-
|
|
11247
|
-
|
|
11248
|
-
bounds: {
|
|
11249
|
-
x: bounds.x,
|
|
11250
|
-
y: bounds.y,
|
|
11251
|
-
width: bounds.width,
|
|
11252
|
-
height: bounds.height,
|
|
11253
|
-
scale: [1, 1],
|
|
11254
|
-
zIndex
|
|
11255
|
-
}
|
|
11256
|
-
};
|
|
11257
|
-
}
|
|
11258
|
-
function buildModule(id, type, title, content, css = {}) {
|
|
11259
|
-
return {
|
|
11260
|
-
id,
|
|
11261
|
-
version: 1,
|
|
11262
|
-
loaded: true,
|
|
11263
|
-
settings: { type, title, locked: false },
|
|
11264
|
-
lights: [],
|
|
11265
|
-
css,
|
|
11658
|
+
function buildChild(groupId, zIndex, bounds, type, title, content, css = {}) {
|
|
11659
|
+
const { layer, module } = buildModuleEnvelope({
|
|
11660
|
+
type,
|
|
11661
|
+
title,
|
|
11662
|
+
bounds,
|
|
11266
11663
|
content,
|
|
11267
|
-
|
|
11268
|
-
|
|
11269
|
-
|
|
11664
|
+
css,
|
|
11665
|
+
parentGroupId: groupId,
|
|
11666
|
+
zIndex
|
|
11667
|
+
});
|
|
11668
|
+
return { layer, module };
|
|
11270
11669
|
}
|
|
11271
11670
|
function textStyleToCss(style) {
|
|
11272
11671
|
const s = style ?? {};
|
|
@@ -11281,80 +11680,69 @@ function textStyleToCss(style) {
|
|
|
11281
11680
|
return out;
|
|
11282
11681
|
}
|
|
11283
11682
|
function mapCompositeField(name, field, groupId, zIndex, provider, canvas) {
|
|
11284
|
-
const id = nanoid8();
|
|
11285
11683
|
switch (field.type) {
|
|
11286
11684
|
case "video": {
|
|
11287
|
-
const bounds = styleToBounds(field.style, "video", canvas);
|
|
11288
|
-
const layer = buildLayer(id, groupId, bounds, zIndex);
|
|
11289
11685
|
const src = pickFieldMediaHref(field.media, "video/");
|
|
11290
11686
|
const volume = typeof field.volume === "number" ? field.volume : 1;
|
|
11291
|
-
|
|
11292
|
-
|
|
11293
|
-
|
|
11294
|
-
|
|
11295
|
-
|
|
11296
|
-
|
|
11297
|
-
|
|
11298
|
-
|
|
11687
|
+
return buildChild(
|
|
11688
|
+
groupId,
|
|
11689
|
+
zIndex,
|
|
11690
|
+
styleToBounds(field.style, "video", canvas),
|
|
11691
|
+
"video",
|
|
11692
|
+
name,
|
|
11693
|
+
{ src, volume, loop: true, autoplay: true, muted: volume === 0 }
|
|
11694
|
+
);
|
|
11299
11695
|
}
|
|
11300
11696
|
case "image": {
|
|
11301
|
-
const bounds = styleToBounds(field.style, "image", canvas);
|
|
11302
|
-
const layer = buildLayer(id, groupId, bounds, zIndex);
|
|
11303
11697
|
const src = pickFieldMediaHref(field.media, "image/");
|
|
11304
|
-
|
|
11305
|
-
|
|
11698
|
+
return buildChild(
|
|
11699
|
+
groupId,
|
|
11700
|
+
zIndex,
|
|
11701
|
+
styleToBounds(field.style, "image", canvas),
|
|
11702
|
+
"image",
|
|
11703
|
+
name,
|
|
11704
|
+
{ src }
|
|
11705
|
+
);
|
|
11306
11706
|
}
|
|
11307
11707
|
case "text": {
|
|
11308
|
-
const bounds = styleToBounds(field.style, "text", canvas);
|
|
11309
|
-
const layer = buildLayer(id, groupId, bounds, zIndex);
|
|
11310
11708
|
const raw = field.text?.[0]?.content ?? "";
|
|
11311
11709
|
const value = substituteElementTokens(raw, { provider });
|
|
11312
|
-
|
|
11313
|
-
|
|
11710
|
+
return buildChild(
|
|
11711
|
+
groupId,
|
|
11712
|
+
zIndex,
|
|
11713
|
+
styleToBounds(field.style, "text", canvas),
|
|
11314
11714
|
"text",
|
|
11315
11715
|
name,
|
|
11316
11716
|
{ value, highlightColor: "inherit" },
|
|
11317
11717
|
textStyleToCss(field.style)
|
|
11318
11718
|
);
|
|
11319
|
-
return { layer, module };
|
|
11320
11719
|
}
|
|
11321
11720
|
case "audio": {
|
|
11322
|
-
const layer = buildLayer(id, groupId, { x: 0, y: 0, width: 1, height: 1 }, zIndex);
|
|
11323
11721
|
const src = pickFieldMediaHref(field.media, "audio/");
|
|
11324
11722
|
const volume = typeof field.volume === "number" ? field.volume : 0.5;
|
|
11325
|
-
|
|
11326
|
-
|
|
11723
|
+
return buildChild(
|
|
11724
|
+
groupId,
|
|
11725
|
+
zIndex,
|
|
11726
|
+
{ x: 0, y: 0, width: 1, height: 1 },
|
|
11727
|
+
"audio",
|
|
11728
|
+
name,
|
|
11729
|
+
{ src, volume, loop: false }
|
|
11730
|
+
);
|
|
11327
11731
|
}
|
|
11328
11732
|
default:
|
|
11329
11733
|
return null;
|
|
11330
11734
|
}
|
|
11331
11735
|
}
|
|
11332
11736
|
function buildElementScene(state, options) {
|
|
11333
|
-
const groupId = nanoid8();
|
|
11334
11737
|
const groupTitle = typeof state.displayName === "string" && state.displayName || state.referenceId || "Scene";
|
|
11335
|
-
const groupLayer = {
|
|
11336
|
-
id: groupId,
|
|
11738
|
+
const { id: groupId, layer: groupLayer, module: groupModule } = buildModuleEnvelope({
|
|
11337
11739
|
type: "group",
|
|
11338
|
-
|
|
11339
|
-
bounds: {
|
|
11340
|
-
|
|
11341
|
-
|
|
11342
|
-
|
|
11343
|
-
|
|
11344
|
-
scale: [1, 1]
|
|
11345
|
-
},
|
|
11346
|
-
state: { visible: true, locked: false, expanded: false }
|
|
11347
|
-
};
|
|
11348
|
-
const groupModule = {
|
|
11349
|
-
id: groupId,
|
|
11350
|
-
loaded: true,
|
|
11351
|
-
settings: { type: "group", title: groupTitle },
|
|
11352
|
-
lights: [],
|
|
11353
|
-
css: {},
|
|
11354
|
-
content: {},
|
|
11355
|
-
variables: {},
|
|
11356
|
-
events: {}
|
|
11357
|
-
};
|
|
11740
|
+
title: groupTitle,
|
|
11741
|
+
bounds: { x: 0, y: 0, width: options.canvas.width, height: options.canvas.height },
|
|
11742
|
+
type_layer: "group",
|
|
11743
|
+
parentGroupId: null,
|
|
11744
|
+
expanded: false
|
|
11745
|
+
});
|
|
11358
11746
|
const children = [];
|
|
11359
11747
|
const fields = state.settings?.compositeFields ?? {};
|
|
11360
11748
|
let zIndex = 1;
|
|
@@ -11373,7 +11761,12 @@ function buildElementScene(state, options) {
|
|
|
11373
11761
|
}
|
|
11374
11762
|
|
|
11375
11763
|
// src/se-import/element-dispatch.ts
|
|
11376
|
-
|
|
11764
|
+
function buildElementDescription(widgetInstanceId, sourceUrl) {
|
|
11765
|
+
return buildImportDescription(
|
|
11766
|
+
`Imported from StreamElements Element widget ${widgetInstanceId}`,
|
|
11767
|
+
sourceUrl
|
|
11768
|
+
);
|
|
11769
|
+
}
|
|
11377
11770
|
function elementAlertKindToLumiaKeys(kind, provider) {
|
|
11378
11771
|
switch (kind) {
|
|
11379
11772
|
case "follower":
|
|
@@ -11392,9 +11785,9 @@ function elementAlertKindToLumiaKeys(kind, provider) {
|
|
|
11392
11785
|
return alertBoxKeysFor("charityCampaignDonation", provider);
|
|
11393
11786
|
case "subscriberGift":
|
|
11394
11787
|
case "communityGiftPurchase": {
|
|
11395
|
-
if (provider === "twitch") return [
|
|
11396
|
-
if (provider === "kick") return [
|
|
11397
|
-
if (provider === "youtube") return [
|
|
11788
|
+
if (provider === "twitch") return [LumiaAlertValues3.TWITCH_GIFT_SUBSCRIPTION];
|
|
11789
|
+
if (provider === "kick") return [LumiaAlertValues3.KICK_GIFT_SUBSCRIPTION];
|
|
11790
|
+
if (provider === "youtube") return [LumiaAlertValues3.YOUTUBE_GIFT_MEMBERS];
|
|
11398
11791
|
return alertBoxKeysFor("subscriber", provider);
|
|
11399
11792
|
}
|
|
11400
11793
|
default:
|
|
@@ -11409,7 +11802,7 @@ function buildCombinedAlertModule(alertStates, provider, canvas) {
|
|
|
11409
11802
|
for (const state of alertStates) {
|
|
11410
11803
|
const cls = classifyConfigState(state);
|
|
11411
11804
|
if (cls.kind !== "alert") continue;
|
|
11412
|
-
const { event, bounds: bounds2 } = buildElementAlertEvent(state, { provider });
|
|
11805
|
+
const { event, bounds: bounds2 } = buildElementAlertEvent(state, { provider, canvas });
|
|
11413
11806
|
const keys = elementAlertKindToLumiaKeys(cls.alertKind, provider);
|
|
11414
11807
|
if (keys.length === 0) continue;
|
|
11415
11808
|
for (const key of keys) {
|
|
@@ -11421,61 +11814,42 @@ function buildCombinedAlertModule(alertStates, provider, canvas) {
|
|
|
11421
11814
|
}
|
|
11422
11815
|
}
|
|
11423
11816
|
if (Object.keys(events).length === 0) return null;
|
|
11424
|
-
const id = nanoid9();
|
|
11425
11817
|
const bounds = firstBounds ?? {
|
|
11426
11818
|
x: Math.round(canvas.width * 0.6),
|
|
11427
11819
|
y: Math.round(canvas.height * 0.15),
|
|
11428
11820
|
width: 400,
|
|
11429
11821
|
height: 300
|
|
11430
11822
|
};
|
|
11431
|
-
const layer = {
|
|
11432
|
-
id,
|
|
11433
|
-
state: { visible: true, locked: false },
|
|
11434
|
-
bounds: {
|
|
11435
|
-
x: bounds.x,
|
|
11436
|
-
y: bounds.y,
|
|
11437
|
-
width: bounds.width,
|
|
11438
|
-
height: bounds.height,
|
|
11439
|
-
scale: [1, 1]
|
|
11440
|
-
}
|
|
11441
|
-
};
|
|
11442
11823
|
const baseAlert = firstEvent ? stripEventOnlyFields2(firstEvent) : {};
|
|
11443
|
-
const module = {
|
|
11444
|
-
|
|
11445
|
-
|
|
11446
|
-
|
|
11447
|
-
settings: { type: "alert", title: "Alerts (Element import)", locked: false },
|
|
11448
|
-
lights: [],
|
|
11449
|
-
css: {},
|
|
11450
|
-
content: {},
|
|
11451
|
-
variables: {},
|
|
11452
|
-
events: {},
|
|
11824
|
+
const { layer, module } = buildModuleEnvelope({
|
|
11825
|
+
type: "alert",
|
|
11826
|
+
title: "Alerts (Element import)",
|
|
11827
|
+
bounds,
|
|
11453
11828
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11454
11829
|
alert: { ...baseAlert, events }
|
|
11455
|
-
};
|
|
11830
|
+
});
|
|
11456
11831
|
return { layer, module };
|
|
11457
11832
|
}
|
|
11458
11833
|
function stripEventOnlyFields2(event) {
|
|
11459
|
-
const {
|
|
11834
|
+
const {
|
|
11835
|
+
on: _on,
|
|
11836
|
+
variations: _variations,
|
|
11837
|
+
matchEmptyCondition: _mec,
|
|
11838
|
+
...base
|
|
11839
|
+
} = event;
|
|
11460
11840
|
return base;
|
|
11461
11841
|
}
|
|
11462
11842
|
function stampImportMeta2(module, state, role) {
|
|
11463
|
-
module
|
|
11464
|
-
|
|
11465
|
-
|
|
11466
|
-
|
|
11467
|
-
|
|
11468
|
-
|
|
11469
|
-
|
|
11470
|
-
displayName: state?.displayName,
|
|
11471
|
-
importedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
11472
|
-
}
|
|
11473
|
-
};
|
|
11843
|
+
stampImportMetaMerge(module, {
|
|
11844
|
+
source: "streamelements-element",
|
|
11845
|
+
role,
|
|
11846
|
+
referenceId: state?.referenceId,
|
|
11847
|
+
categoryId: state?.categoryId,
|
|
11848
|
+
displayName: state?.displayName
|
|
11849
|
+
});
|
|
11474
11850
|
}
|
|
11475
|
-
function importElementOverlay(response) {
|
|
11476
|
-
const configData = parseElementConfigData(
|
|
11477
|
-
response.widgetInstanceConfigVersion.configData
|
|
11478
|
-
);
|
|
11851
|
+
function importElementOverlay(response, options = {}) {
|
|
11852
|
+
const configData = parseElementConfigData(response.widgetInstanceConfigVersion.configData);
|
|
11479
11853
|
if (!configData) {
|
|
11480
11854
|
throw new Error(
|
|
11481
11855
|
"StreamElements Element response carries an invalid configData payload. The widget may be corrupted or the response format may have changed."
|
|
@@ -11545,7 +11919,10 @@ function importElementOverlay(response) {
|
|
|
11545
11919
|
uuid: "",
|
|
11546
11920
|
listen_id: "",
|
|
11547
11921
|
name: response.widgetInstance.displayName ? `[SE Element] ${response.widgetInstance.displayName}` : `Imported from StreamElements Element (${response.widgetInstance.widgetInstanceId})`,
|
|
11548
|
-
description:
|
|
11922
|
+
description: buildElementDescription(
|
|
11923
|
+
response.widgetInstance.widgetInstanceId,
|
|
11924
|
+
options.sourceUrl
|
|
11925
|
+
),
|
|
11549
11926
|
settings: {
|
|
11550
11927
|
metadata: { width: canvas.width, height: canvas.height },
|
|
11551
11928
|
layers,
|
|
@@ -11559,7 +11936,7 @@ function importElementOverlay(response) {
|
|
|
11559
11936
|
}
|
|
11560
11937
|
|
|
11561
11938
|
// src/se-import/index.ts
|
|
11562
|
-
var
|
|
11939
|
+
var IMPORT_META_KEY2 = "importMeta";
|
|
11563
11940
|
var REVIEW_REASONS = {
|
|
11564
11941
|
"se-widget-bit-boss": "No native Lumia equivalent \u2014 bit boss fight bar with HP/damage states.",
|
|
11565
11942
|
// `se-widget-hype-cup` intentionally omitted — it now routes to the native
|
|
@@ -11589,6 +11966,10 @@ function reasonFor(seType, status, flaggedOff) {
|
|
|
11589
11966
|
if (flaggedOff && FLAG_OFF_REASONS[seType]) return FLAG_OFF_REASONS[seType];
|
|
11590
11967
|
return REVIEW_REASONS[seType] ?? (status === "template" ? "Imported as a generic template stub." : "No native mapping yet \u2014 imported as a labelled text placeholder.");
|
|
11591
11968
|
}
|
|
11969
|
+
function buildSEBootstrapDescription(overlayId, sourceUrl) {
|
|
11970
|
+
const head = overlayId ? `Imported from StreamElements overlay ${overlayId}` : "Imported from StreamElements";
|
|
11971
|
+
return buildImportDescription(head, sourceUrl);
|
|
11972
|
+
}
|
|
11592
11973
|
function extractSEOverlayId(input) {
|
|
11593
11974
|
const trimmed = input.trim();
|
|
11594
11975
|
const m = trimmed.match(/[0-9a-f]{24}/i);
|
|
@@ -11643,7 +12024,7 @@ function isSEBootstrap(value) {
|
|
|
11643
12024
|
const o = v.overlay;
|
|
11644
12025
|
return Array.isArray(o.widgets);
|
|
11645
12026
|
}
|
|
11646
|
-
function importSEBootstrap(bootstrap) {
|
|
12027
|
+
function importSEBootstrap(bootstrap, options = {}) {
|
|
11647
12028
|
const seOverlay = bootstrap.overlay;
|
|
11648
12029
|
const widgets = seOverlay?.widgets ?? [];
|
|
11649
12030
|
const coverage = {
|
|
@@ -11666,7 +12047,7 @@ function importSEBootstrap(bootstrap) {
|
|
|
11666
12047
|
if (w.type !== "se-widget-group") continue;
|
|
11667
12048
|
const uid = w.variables?.uid;
|
|
11668
12049
|
if (typeof uid !== "string") continue;
|
|
11669
|
-
const lumiaGroupId =
|
|
12050
|
+
const lumiaGroupId = nanoid8();
|
|
11670
12051
|
seUidToLumiaGroupId[uid] = lumiaGroupId;
|
|
11671
12052
|
groupWidgetByUid[uid] = w;
|
|
11672
12053
|
}
|
|
@@ -11705,7 +12086,7 @@ function importSEBootstrap(bootstrap) {
|
|
|
11705
12086
|
lights: [],
|
|
11706
12087
|
css: {},
|
|
11707
12088
|
content: {
|
|
11708
|
-
[
|
|
12089
|
+
[IMPORT_META_KEY2]: {
|
|
11709
12090
|
source: "streamelements",
|
|
11710
12091
|
widgetType: w.type,
|
|
11711
12092
|
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -11743,7 +12124,7 @@ function importSEBootstrap(bootstrap) {
|
|
|
11743
12124
|
if (result.status === "placeholder" || result.status === "template") {
|
|
11744
12125
|
module.content = {
|
|
11745
12126
|
...module.content ?? {},
|
|
11746
|
-
[
|
|
12127
|
+
[IMPORT_META_KEY2]: {
|
|
11747
12128
|
source: "streamelements",
|
|
11748
12129
|
widgetType: w.type,
|
|
11749
12130
|
importedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -11783,7 +12164,7 @@ function importSEBootstrap(bootstrap) {
|
|
|
11783
12164
|
uuid: "",
|
|
11784
12165
|
listen_id: "",
|
|
11785
12166
|
name: seOverlay?.name ? `[SE] ${seOverlay.name}` : `Imported from StreamElements (${seOverlay?._id ?? ""})`,
|
|
11786
|
-
description: seOverlay?._id
|
|
12167
|
+
description: buildSEBootstrapDescription(seOverlay?._id, options.sourceUrl),
|
|
11787
12168
|
settings: {
|
|
11788
12169
|
metadata: {
|
|
11789
12170
|
width: seOverlay?.settings?.width ?? 1920,
|
|
@@ -11831,7 +12212,7 @@ function applyReviewAction(result, moduleId, action, payload) {
|
|
|
11831
12212
|
bounds: existingLayer.bounds,
|
|
11832
12213
|
state: existingLayer.state
|
|
11833
12214
|
};
|
|
11834
|
-
const importMeta2 = existing2.content?.[
|
|
12215
|
+
const importMeta2 = existing2.content?.[IMPORT_META_KEY2];
|
|
11835
12216
|
const mergedLights = (existing2.lights?.length ?? 0) > 0 ? existing2.lights : transplant.module.lights;
|
|
11836
12217
|
const mergedEvents = existing2.events && Object.keys(existing2.events).length > 0 ? { ...transplant.module.events, ...existing2.events } : transplant.module.events;
|
|
11837
12218
|
const mergedVariables = existing2.variables && Object.keys(existing2.variables).length > 0 ? { ...transplant.module.variables, ...existing2.variables } : transplant.module.variables;
|
|
@@ -11843,7 +12224,7 @@ function applyReviewAction(result, moduleId, action, payload) {
|
|
|
11843
12224
|
variables: mergedVariables,
|
|
11844
12225
|
content: {
|
|
11845
12226
|
...transplant.module.content ?? {},
|
|
11846
|
-
[
|
|
12227
|
+
[IMPORT_META_KEY2]: importMeta2
|
|
11847
12228
|
}
|
|
11848
12229
|
};
|
|
11849
12230
|
const rootOldNewId = transplant.layer.id;
|
|
@@ -11871,7 +12252,7 @@ function applyReviewAction(result, moduleId, action, payload) {
|
|
|
11871
12252
|
const existing = modules[moduleId];
|
|
11872
12253
|
const generated = payload;
|
|
11873
12254
|
if (!existing || !generated) return result;
|
|
11874
|
-
const importMeta = existing.content?.[
|
|
12255
|
+
const importMeta = existing.content?.[IMPORT_META_KEY2];
|
|
11875
12256
|
const replaced = {
|
|
11876
12257
|
...existing,
|
|
11877
12258
|
settings: { ...existing.settings ?? {}, type: "custom" },
|
|
@@ -11885,7 +12266,7 @@ function applyReviewAction(result, moduleId, action, payload) {
|
|
|
11885
12266
|
data: parseLooseJson(generated.data) ?? {},
|
|
11886
12267
|
configs: parseLooseJson(generated.configs) ?? [],
|
|
11887
12268
|
flavor: "ai-generated",
|
|
11888
|
-
[
|
|
12269
|
+
[IMPORT_META_KEY2]: importMeta
|
|
11889
12270
|
}
|
|
11890
12271
|
};
|
|
11891
12272
|
modules[moduleId] = replaced;
|